diff options
Diffstat (limited to 'drivers/char/sx.c')
-rw-r--r-- | drivers/char/sx.c | 164 |
1 files changed, 117 insertions, 47 deletions
diff --git a/drivers/char/sx.c b/drivers/char/sx.c index a85f5eb8558..ca3145a440b 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c @@ -214,6 +214,7 @@ #include <linux/fcntl.h> #include <linux/major.h> #include <linux/delay.h> +#include <linux/eisa.h> #include <linux/pci.h> #include <linux/slab.h> #include <linux/init.h> @@ -2345,6 +2346,17 @@ static int sx_init_portstructs (int nboards, int nports) return 0; } +static unsigned int sx_find_free_board(void) +{ + unsigned int i; + + for (i = 0; i < SX_NBOARDS; i++) + if (!(boards[i].flags & SX_BOARD_PRESENT)) + break; + + return i; +} + static void __exit sx_release_drivers(void) { func_enter(); @@ -2353,6 +2365,97 @@ static void __exit sx_release_drivers(void) func_exit(); } +static void __devexit sx_remove_card(struct sx_board *board) +{ + if (board->flags & SX_BOARD_INITIALIZED) { + /* The board should stop messing with us. (actually I mean the + interrupt) */ + sx_reset(board); + if ((board->irq) && (board->flags & SX_IRQ_ALLOCATED)) + free_irq(board->irq, board); + + /* It is safe/allowed to del_timer a non-active timer */ + del_timer(&board->timer); + iounmap(board->base); + + board->flags &= ~(SX_BOARD_INITIALIZED|SX_BOARD_PRESENT); + } +} + +#ifdef CONFIG_EISA + +static int __devinit sx_eisa_probe(struct device *dev) +{ + struct eisa_device *edev = to_eisa_device(dev); + struct sx_board *board; + unsigned long eisa_slot = edev->base_addr; + unsigned int i; + int retval = -EIO; + + i = sx_find_free_board(); + + if (i == SX_NBOARDS) + goto err; + + dev_info(dev, "XIO : Signature found in EISA slot %lu, " + "Product %d Rev %d (REPORT THIS TO LKLM)\n", + eisa_slot >> 12, + inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 2), + inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 3)); + + board = &boards[i]; + board->eisa_base = eisa_slot; + board->flags &= ~SX_BOARD_TYPE; + board->flags |= SI_EISA_BOARD; + + board->hw_base = ((inb(eisa_slot + 0xc01) << 8) + + inb(eisa_slot + 0xc00)) << 16; + board->base2 = + board->base = ioremap(board->hw_base, SI2_EISA_WINDOW_LEN); + + sx_dprintk(SX_DEBUG_PROBE, "IO hw_base address: %lx\n", board->hw_base); + sx_dprintk(SX_DEBUG_PROBE, "base: %p\n", board->base); + board->irq = inb(eisa_slot + 0xc02) >> 4; + sx_dprintk(SX_DEBUG_PROBE, "IRQ: %d\n", board->irq); + + if (!probe_si(board)) + goto err_unmap; + + dev_set_drvdata(dev, board); + + return 0; +err_unmap: + iounmap(board->base); +err: + return retval; +} + +static int __devexit sx_eisa_remove(struct device *dev) +{ + struct sx_board *board = dev_get_drvdata(dev); + + sx_remove_card(board); + + return 0; +} + +static struct eisa_device_id sx_eisa_tbl[] = { + { "SLX" }, + { "" } +}; +MODULE_DEVICE_TABLE(eisa, sx_eisa_tbl); + +static struct eisa_driver sx_eisadriver = { + .id_table = sx_eisa_tbl, + .driver = { + .name = "sx", + .probe = sx_eisa_probe, + .remove = __devexit_p(sx_eisa_remove), + } +}; + +#endif + /******************************************************** * Setting bit 17 in the CNTRL register of the PLX 9050 * * chip forces a retry on writes while a read is pending.* @@ -2391,9 +2494,7 @@ static int __devinit sx_pci_probe(struct pci_dev *pdev, unsigned int i; int retval = -EIO; - for (i = 0; i < SX_NBOARDS; i++) - if (!(boards[i].flags & SX_BOARD_PRESENT)) - break; + i = sx_find_free_board(); if (i == SX_NBOARDS) goto err; @@ -2449,19 +2550,7 @@ static void __devexit sx_pci_remove(struct pci_dev *pdev) { struct sx_board *board = pci_get_drvdata(pdev); - if (board->flags & SX_BOARD_INITIALIZED) { - /* The board should stop messing with us. (actually I mean the - interrupt) */ - sx_reset(board); - if ((board->irq) && (board->flags & SX_IRQ_ALLOCATED)) - free_irq(board->irq, board); - - /* It is safe/allowed to del_timer a non-active timer */ - del_timer(&board->timer); - iounmap(board->base); - - board->flags &= ~(SX_BOARD_INITIALIZED|SX_BOARD_PRESENT); - } + sx_remove_card(board); } /* Specialix has a whole bunch of cards with 0x2000 as the device ID. They say @@ -2484,9 +2573,11 @@ static struct pci_driver sx_pcidriver = { static int __init sx_init(void) { +#ifdef CONFIG_EISA + int retval1; +#endif int retval, i; int found = 0; - int eisa_slot; struct sx_board *board; func_enter(); @@ -2549,42 +2640,18 @@ static int __init sx_init(void) iounmap (board->base); } } - - sx_dprintk(SX_DEBUG_PROBE, "Probing for EISA cards\n"); - for(eisa_slot=0x1000; eisa_slot<0x10000; eisa_slot+=0x1000) - { - if((inb(eisa_slot+0xc80)==0x4d) && - (inb(eisa_slot+0xc81)==0x98)) - { - sx_dprintk(SX_DEBUG_PROBE, "%s : Signature found in EISA slot %d, Product %d Rev %d\n", - "XIO", (eisa_slot>>12), inb(eisa_slot+0xc82), inb(eisa_slot+0xc83)); - - board = &boards[found]; - board->eisa_base = eisa_slot; - board->flags &= ~SX_BOARD_TYPE; - board->flags |= SI_EISA_BOARD; - - board->hw_base = (((inb(0xc01+eisa_slot) << 8) + inb(0xc00+eisa_slot)) << 16); - board->base2 = - board->base = ioremap(board->hw_base, SI2_EISA_WINDOW_LEN); - - sx_dprintk(SX_DEBUG_PROBE, "IO hw_base address: %lx\n", board->hw_base); - sx_dprintk(SX_DEBUG_PROBE, "base: %p\n", board->base); - board->irq = inb(board->eisa_base+0xc02)>>4; - sx_dprintk(SX_DEBUG_PROBE, "IRQ: %d\n", board->irq); - - probe_si(board); - - found++; - } - } - +#ifdef CONFIG_EISA + retval1 = eisa_driver_register(&sx_eisadriver); +#endif retval = pci_register_driver(&sx_pcidriver); if (found) { printk (KERN_INFO "sx: total of %d boards detected.\n", found); retval = 0; } else if (retval) { +#ifdef CONFIG_EISA + if (retval1) +#endif misc_deregister(&sx_fw_device); } @@ -2599,6 +2666,9 @@ static void __exit sx_exit (void) struct sx_board *board; func_enter(); +#ifdef CONFIG_EISA + eisa_driver_unregister(&sx_eisadriver); +#endif pci_unregister_driver(&sx_pcidriver); for (i = 0; i < SX_NBOARDS; i++) { board = &boards[i]; |