pcmcia: setup resource information for pseudo multifunction devices.
[safe/jmp/linux-2.6] / drivers / pcmcia / i82365.c
index 4ddd762..71653ab 100644 (file)
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/timer.h>
-#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
@@ -65,7 +63,7 @@
 #include "vg468.h"
 #include "ricoh.h"
 
-#ifdef DEBUG
+#ifdef CONFIG_PCMCIA_DEBUG
 static const char version[] =
 "i82365.c 1.265 1999/11/10 18:36:21 (David Hinds)";
 
@@ -81,7 +79,7 @@ module_param(pc_debug, int, 0644);
 #define debug(lvl, fmt, arg...) do { } while (0)
 #endif
 
-static irqreturn_t i365_count_irq(int, void *, struct pt_regs *);
+static irqreturn_t i365_count_irq(int, void *);
 static inline int _check_irq(int irq, int flags)
 {
     if (request_irq(irq, i365_count_irq, flags, "x", i365_count_irq) != 0)
@@ -103,7 +101,7 @@ static int ignore = -1;
 /* Bit map or list of interrupts to choose from */
 static u_int irq_mask = 0xffff;
 static int irq_list[16];
-static int irq_list_count;
+static unsigned int irq_list_count;
 /* The card status change interrupt -- 0 means autoselect */
 static int cs_irq = 0;
 
@@ -166,7 +164,7 @@ struct i82365_socket {
     u_short            type, flags;
     struct pcmcia_socket       socket;
     unsigned int       number;
-    kio_addr_t         ioaddr;
+    unsigned int       ioaddr;
     u_short            psock;
     u_char             cs_irq, intr;
     union {
@@ -240,7 +238,7 @@ static u_char i365_get(u_short sock, u_short reg)
     unsigned long flags;
     spin_lock_irqsave(&bus_lock,flags);
     {
-       kio_addr_t port = socket[sock].ioaddr;
+       unsigned int port = socket[sock].ioaddr;
        u_char val;
        reg = I365_REG(socket[sock].psock, reg);
        outb(reg, port); val = inb(port+1);
@@ -254,7 +252,7 @@ static void i365_set(u_short sock, u_short reg, u_char data)
     unsigned long flags;
     spin_lock_irqsave(&bus_lock,flags);
     {
-       kio_addr_t port = socket[sock].ioaddr;
+       unsigned int port = socket[sock].ioaddr;
        u_char val = I365_REG(socket[sock].psock, reg);
        outb(val, port); outb(data, port+1);
        spin_unlock_irqrestore(&bus_lock,flags);
@@ -499,7 +497,7 @@ static u_int __init set_bridge_opts(u_short s, u_short ns)
 static volatile u_int irq_hits;
 static u_short irq_sock;
 
-static irqreturn_t i365_count_irq(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t i365_count_irq(int irq, void *dev)
 {
     i365_get(irq_sock, I365_CSC);
     irq_hits++;
@@ -510,7 +508,8 @@ static irqreturn_t i365_count_irq(int irq, void *dev, struct pt_regs *regs)
 static u_int __init test_irq(u_short sock, int irq)
 {
     debug(2, "  testing ISA irq %d\n", irq);
-    if (request_irq(irq, i365_count_irq, 0, "scan", i365_count_irq) != 0)
+    if (request_irq(irq, i365_count_irq, IRQF_PROBE_SHARED, "scan",
+                       i365_count_irq) != 0)
        return 1;
     irq_hits = 0; irq_sock = sock;
     msleep(10);
@@ -562,7 +561,7 @@ static u_int __init isa_scan(u_short sock, u_int mask0)
     } else {
        /* Fallback: just find interrupts that aren't in use */
        for (i = 0; i < 16; i++)
-           if ((mask0 & (1 << i)) && (_check_irq(i, 0) == 0))
+           if ((mask0 & (1 << i)) && (_check_irq(i, IRQF_PROBE_SHARED) == 0))
                mask1 |= (1 << i);
        printk("default");
        /* If scan failed, default to polled status */
@@ -589,7 +588,7 @@ static int to_cycles(int ns)
 
 /*====================================================================*/
 
-static int __init identify(kio_addr_t port, u_short sock)
+static int __init identify(unsigned int port, u_short sock)
 {
     u_char val;
     int type = -1;
@@ -660,7 +659,7 @@ static int __init identify(kio_addr_t port, u_short sock)
 static int __init is_alive(u_short sock)
 {
     u_char stat;
-    kio_addr_t start, stop;
+    unsigned int start, stop;
     
     stat = i365_get(sock, I365_STATUS);
     start = i365_get_pair(sock, I365_IO(0)+I365_W_START);
@@ -679,7 +678,7 @@ static int __init is_alive(u_short sock)
 
 /*====================================================================*/
 
-static void __init add_socket(kio_addr_t port, int psock, int type)
+static void __init add_socket(unsigned int port, int psock, int type)
 {
     socket[sockets].ioaddr = port;
     socket[sockets].psock = psock;
@@ -699,7 +698,7 @@ static void __init add_pcic(int ns, int type)
     base = sockets-ns;
     if (base == 0) printk("\n");
     printk(KERN_INFO "  %s", pcic[type].name);
-    printk(" ISA-to-PCMCIA at port %#lx ofs 0x%02x",
+    printk(" ISA-to-PCMCIA at port %#x ofs 0x%02x",
               t->ioaddr, t->psock*0x40);
     printk(", %d socket%s\n", ns, ((ns > 1) ? "s" : ""));
 
@@ -726,7 +725,7 @@ static void __init add_pcic(int ns, int type)
        u_int cs_mask = mask & ((cs_irq) ? (1<<cs_irq) : ~(1<<12));
        for (cs_irq = 15; cs_irq > 0; cs_irq--)
            if ((cs_mask & (1 << cs_irq)) &&
-               (_check_irq(cs_irq, 0) == 0))
+               (_check_irq(cs_irq, IRQF_PROBE_SHARED) == 0))
                break;
        if (cs_irq) {
            grab_irq = 1;
@@ -773,7 +772,7 @@ static struct pnp_dev *i82365_pnpdev;
 static void __init isa_probe(void)
 {
     int i, j, sock, k, ns, id;
-    kio_addr_t port;
+    unsigned int port;
 #ifdef CONFIG_PNP
     struct isapnp_device_id *devid;
     struct pnp_dev *dev;
@@ -848,8 +847,7 @@ static void __init isa_probe(void)
 
 /*====================================================================*/
 
-static irqreturn_t pcic_interrupt(int irq, void *dev,
-                                   struct pt_regs *regs)
+static irqreturn_t pcic_interrupt(int irq, void *dev)
 {
     int i, j, csc;
     u_int events, active;
@@ -898,7 +896,7 @@ static irqreturn_t pcic_interrupt(int irq, void *dev,
 
 static void pcic_interrupt_wrapper(u_long data)
 {
-    pcic_interrupt(0, NULL, NULL);
+    pcic_interrupt(0, NULL);
     poll_timer.expires = jiffies + poll_interval;
     add_timer(&poll_timer);
 }
@@ -940,78 +938,6 @@ static int i365_get_status(u_short sock, u_int *value)
 
 /*====================================================================*/
 
-static int i365_get_socket(u_short sock, socket_state_t *state)
-{
-    struct i82365_socket *t = &socket[sock];
-    u_char reg, vcc, vpp;
-    
-    reg = i365_get(sock, I365_POWER);
-    state->flags = (reg & I365_PWR_AUTO) ? SS_PWR_AUTO : 0;
-    state->flags |= (reg & I365_PWR_OUT) ? SS_OUTPUT_ENA : 0;
-    vcc = reg & I365_VCC_MASK; vpp = reg & I365_VPP1_MASK;
-    state->Vcc = state->Vpp = 0;
-    if (t->flags & IS_CIRRUS) {
-       if (i365_get(sock, PD67_MISC_CTL_1) & PD67_MC1_VCC_3V) {
-           if (reg & I365_VCC_5V) state->Vcc = 33;
-           if (vpp == I365_VPP1_5V) state->Vpp = 33;
-       } else {
-           if (reg & I365_VCC_5V) state->Vcc = 50;
-           if (vpp == I365_VPP1_5V) state->Vpp = 50;
-       }
-       if (vpp == I365_VPP1_12V) state->Vpp = 120;
-    } else if (t->flags & IS_VG_PWR) {
-       if (i365_get(sock, VG469_VSELECT) & VG469_VSEL_VCC) {
-           if (reg & I365_VCC_5V) state->Vcc = 33;
-           if (vpp == I365_VPP1_5V) state->Vpp = 33;
-       } else {
-           if (reg & I365_VCC_5V) state->Vcc = 50;
-           if (vpp == I365_VPP1_5V) state->Vpp = 50;
-       }
-       if (vpp == I365_VPP1_12V) state->Vpp = 120;
-    } else if (t->flags & IS_DF_PWR) {
-       if (vcc == I365_VCC_3V) state->Vcc = 33;
-       if (vcc == I365_VCC_5V) state->Vcc = 50;
-       if (vpp == I365_VPP1_5V) state->Vpp = 50;
-       if (vpp == I365_VPP1_12V) state->Vpp = 120;
-    } else {
-       if (reg & I365_VCC_5V) {
-           state->Vcc = 50;
-           if (vpp == I365_VPP1_5V) state->Vpp = 50;
-           if (vpp == I365_VPP1_12V) state->Vpp = 120;
-       }
-    }
-
-    /* IO card, RESET flags, IO interrupt */
-    reg = i365_get(sock, I365_INTCTL);
-    state->flags |= (reg & I365_PC_RESET) ? 0 : SS_RESET;
-    if (reg & I365_PC_IOCARD) state->flags |= SS_IOCARD;
-    state->io_irq = reg & I365_IRQ_MASK;
-    
-    /* speaker control */
-    if (t->flags & IS_CIRRUS) {
-       if (i365_get(sock, PD67_MISC_CTL_1) & PD67_MC1_SPKR_ENA)
-           state->flags |= SS_SPKR_ENA;
-    }
-    
-    /* Card status change mask */
-    reg = i365_get(sock, I365_CSCINT);
-    state->csc_mask = (reg & I365_CSC_DETECT) ? SS_DETECT : 0;
-    if (state->flags & SS_IOCARD)
-       state->csc_mask |= (reg & I365_CSC_STSCHG) ? SS_STSCHG : 0;
-    else {
-       state->csc_mask |= (reg & I365_CSC_BVD1) ? SS_BATDEAD : 0;
-       state->csc_mask |= (reg & I365_CSC_BVD2) ? SS_BATWARN : 0;
-       state->csc_mask |= (reg & I365_CSC_READY) ? SS_READY : 0;
-    }
-    
-    debug(1, "GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
-         "io_irq %d, csc_mask %#2.2x\n", sock, state->flags,
-         state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
-    return 0;
-} /* i365_get_socket */
-
-/*====================================================================*/
-
 static int i365_set_socket(u_short sock, socket_state_t *state)
 {
     struct i82365_socket *t = &socket[sock];
@@ -1127,7 +1053,7 @@ static int i365_set_io_map(u_short sock, struct pccard_io_map *io)
     u_char map, ioctl;
     
     debug(1, "SetIOMap(%d, %d, %#2.2x, %d ns, "
-         "%#lx-%#lx)\n", sock, io->map, io->flags,
+         "%#x-%#x)\n", sock, io->map, io->flags,
          io->speed, io->start, io->stop);
     map = io->map;
     if ((map > 1) || (io->start > 0xffff) || (io->stop > 0xffff) ||
@@ -1156,9 +1082,10 @@ static int i365_set_mem_map(u_short sock, struct pccard_mem_map *mem)
     u_short base, i;
     u_char map;
     
-    debug(1, "SetMemMap(%d, %d, %#2.2x, %d ns, %#lx-%#lx, "
+    debug(1, "SetMemMap(%d, %d, %#2.2x, %d ns, %#llx-%#llx, "
          "%#x)\n", sock, mem->map, mem->flags, mem->speed,
-         mem->res->start, mem->res->end, mem->card_start);
+         (unsigned long long)mem->res->start,
+         (unsigned long long)mem->res->end, mem->card_start);
 
     map = mem->map;
     if ((map > 4) || (mem->card_start > 0x3ffffff) ||
@@ -1265,16 +1192,6 @@ static int pcic_get_status(struct pcmcia_socket *s, u_int *value)
        LOCKED(i365_get_status(sock, value));
 }
 
-static int pcic_get_socket(struct pcmcia_socket *s, socket_state_t *state)
-{
-       unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
-
-       if (socket[sock].flags & IS_ALIVE)
-               return -EINVAL;
-
-       LOCKED(i365_get_socket(sock, state));
-}
-
 static int pcic_set_socket(struct pcmcia_socket *s, socket_state_t *state)
 {
        unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
@@ -1324,7 +1241,6 @@ static int pcic_init(struct pcmcia_socket *s)
 static struct pccard_operations pcic_operations = {
        .init                   = pcic_init,
        .get_status             = pcic_get_status,
-       .get_socket             = pcic_get_socket,
        .set_socket             = pcic_set_socket,
        .set_io_map             = pcic_set_io_map,
        .set_mem_map            = pcic_set_mem_map,
@@ -1339,10 +1255,7 @@ static struct device_driver i82365_driver = {
        .resume = pcmcia_socket_dev_resume,
 };
 
-static struct platform_device i82365_device = {
-       .name = "i82365",
-       .id = 0,
-};
+static struct platform_device *i82365_device;
 
 static int __init init_i82365(void)
 {
@@ -1350,13 +1263,18 @@ static int __init init_i82365(void)
 
     ret = driver_register(&i82365_driver);
     if (ret)
-       return ret;
+       goto err_out;
 
-    ret = platform_device_register(&i82365_device);
-    if (ret) {
-       driver_unregister(&i82365_driver);
-       return ret;
-    }
+    i82365_device = platform_device_alloc("i82365", 0);
+    if (i82365_device) {
+           ret = platform_device_add(i82365_device);
+           if (ret)
+                   platform_device_put(i82365_device);
+    } else
+           ret = -ENOMEM;
+
+    if (ret)
+       goto err_driver_unregister;
 
     printk(KERN_INFO "Intel ISA PCIC probe: ");
     sockets = 0;
@@ -1365,19 +1283,20 @@ static int __init init_i82365(void)
 
     if (sockets == 0) {
        printk("not found.\n");
-       platform_device_unregister(&i82365_device);
-       release_region(i365_base, 2);
-       driver_unregister(&i82365_driver);
-       return -ENODEV;
+       ret = -ENODEV;
+       goto err_dev_unregister;
     }
 
     /* Set up interrupt handler(s) */
     if (grab_irq != 0)
-       request_irq(cs_irq, pcic_interrupt, 0, "i82365", pcic_interrupt);
-    
+       ret = request_irq(cs_irq, pcic_interrupt, 0, "i82365", pcic_interrupt);
+
+    if (ret)
+       goto err_socket_release;
+
     /* register sockets with the pcmcia core */
     for (i = 0; i < sockets; i++) {
-           socket[i].socket.dev.dev = &i82365_device.dev;
+           socket[i].socket.dev.parent = &i82365_device->dev;
            socket[i].socket.ops = &pcic_operations;
            socket[i].socket.resource_ops = &pccard_nonstatic_ops;
            socket[i].socket.owner = THIS_MODULE;
@@ -1404,7 +1323,23 @@ static int __init init_i82365(void)
     }
     
     return 0;
-    
+err_socket_release:
+    for (i = 0; i < sockets; i++) {
+       /* Turn off all interrupt sources! */
+       i365_set(i, I365_CSCINT, 0);
+       release_region(socket[i].ioaddr, 2);
+    }
+err_dev_unregister:
+    platform_device_unregister(i82365_device);
+    release_region(i365_base, 2);
+#ifdef CONFIG_PNP
+    if (i82365_pnpdev)
+       pnp_disable_dev(i82365_pnpdev);
+#endif
+err_driver_unregister:
+    driver_unregister(&i82365_driver);
+err_out:
+    return ret;
 } /* init_i82365 */
 
 static void __exit exit_i82365(void)
@@ -1415,7 +1350,7 @@ static void __exit exit_i82365(void)
            if (socket[i].flags & IS_REGISTERED)
                    pcmcia_unregister_socket(&socket[i].socket);
     }
-    platform_device_unregister(&i82365_device);
+    platform_device_unregister(i82365_device);
     if (poll_interval != 0)
        del_timer_sync(&poll_timer);
     if (grab_irq != 0)