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 a85f5eb85585..ca3145a440b7 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c | |||
@@ -214,6 +214,7 @@ | |||
214 | #include <linux/fcntl.h> | 214 | #include <linux/fcntl.h> |
215 | #include <linux/major.h> | 215 | #include <linux/major.h> |
216 | #include <linux/delay.h> | 216 | #include <linux/delay.h> |
217 | #include <linux/eisa.h> | ||
217 | #include <linux/pci.h> | 218 | #include <linux/pci.h> |
218 | #include <linux/slab.h> | 219 | #include <linux/slab.h> |
219 | #include <linux/init.h> | 220 | #include <linux/init.h> |
@@ -2345,6 +2346,17 @@ static int sx_init_portstructs (int nboards, int nports) | |||
2345 | return 0; | 2346 | return 0; |
2346 | } | 2347 | } |
2347 | 2348 | ||
2349 | static unsigned int sx_find_free_board(void) | ||
2350 | { | ||
2351 | unsigned int i; | ||
2352 | |||
2353 | for (i = 0; i < SX_NBOARDS; i++) | ||
2354 | if (!(boards[i].flags & SX_BOARD_PRESENT)) | ||
2355 | break; | ||
2356 | |||
2357 | return i; | ||
2358 | } | ||
2359 | |||
2348 | static void __exit sx_release_drivers(void) | 2360 | static void __exit sx_release_drivers(void) |
2349 | { | 2361 | { |
2350 | func_enter(); | 2362 | func_enter(); |
@@ -2353,6 +2365,97 @@ static void __exit sx_release_drivers(void) | |||
2353 | func_exit(); | 2365 | func_exit(); |
2354 | } | 2366 | } |
2355 | 2367 | ||
2368 | static void __devexit sx_remove_card(struct sx_board *board) | ||
2369 | { | ||
2370 | if (board->flags & SX_BOARD_INITIALIZED) { | ||
2371 | /* The board should stop messing with us. (actually I mean the | ||
2372 | interrupt) */ | ||
2373 | sx_reset(board); | ||
2374 | if ((board->irq) && (board->flags & SX_IRQ_ALLOCATED)) | ||
2375 | free_irq(board->irq, board); | ||
2376 | |||
2377 | /* It is safe/allowed to del_timer a non-active timer */ | ||
2378 | del_timer(&board->timer); | ||
2379 | iounmap(board->base); | ||
2380 | |||
2381 | board->flags &= ~(SX_BOARD_INITIALIZED|SX_BOARD_PRESENT); | ||
2382 | } | ||
2383 | } | ||
2384 | |||
2385 | #ifdef CONFIG_EISA | ||
2386 | |||
2387 | static int __devinit sx_eisa_probe(struct device *dev) | ||
2388 | { | ||
2389 | struct eisa_device *edev = to_eisa_device(dev); | ||
2390 | struct sx_board *board; | ||
2391 | unsigned long eisa_slot = edev->base_addr; | ||
2392 | unsigned int i; | ||
2393 | int retval = -EIO; | ||
2394 | |||
2395 | i = sx_find_free_board(); | ||
2396 | |||
2397 | if (i == SX_NBOARDS) | ||
2398 | goto err; | ||
2399 | |||
2400 | dev_info(dev, "XIO : Signature found in EISA slot %lu, " | ||
2401 | "Product %d Rev %d (REPORT THIS TO LKLM)\n", | ||
2402 | eisa_slot >> 12, | ||
2403 | inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 2), | ||
2404 | inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 3)); | ||
2405 | |||
2406 | board = &boards[i]; | ||
2407 | board->eisa_base = eisa_slot; | ||
2408 | board->flags &= ~SX_BOARD_TYPE; | ||
2409 | board->flags |= SI_EISA_BOARD; | ||
2410 | |||
2411 | board->hw_base = ((inb(eisa_slot + 0xc01) << 8) + | ||
2412 | inb(eisa_slot + 0xc00)) << 16; | ||
2413 | board->base2 = | ||
2414 | board->base = ioremap(board->hw_base, SI2_EISA_WINDOW_LEN); | ||
2415 | |||
2416 | sx_dprintk(SX_DEBUG_PROBE, "IO hw_base address: %lx\n", board->hw_base); | ||
2417 | sx_dprintk(SX_DEBUG_PROBE, "base: %p\n", board->base); | ||
2418 | board->irq = inb(eisa_slot + 0xc02) >> 4; | ||
2419 | sx_dprintk(SX_DEBUG_PROBE, "IRQ: %d\n", board->irq); | ||
2420 | |||
2421 | if (!probe_si(board)) | ||
2422 | goto err_unmap; | ||
2423 | |||
2424 | dev_set_drvdata(dev, board); | ||
2425 | |||
2426 | return 0; | ||
2427 | err_unmap: | ||
2428 | iounmap(board->base); | ||
2429 | err: | ||
2430 | return retval; | ||
2431 | } | ||
2432 | |||
2433 | static int __devexit sx_eisa_remove(struct device *dev) | ||
2434 | { | ||
2435 | struct sx_board *board = dev_get_drvdata(dev); | ||
2436 | |||
2437 | sx_remove_card(board); | ||
2438 | |||
2439 | return 0; | ||
2440 | } | ||
2441 | |||
2442 | static struct eisa_device_id sx_eisa_tbl[] = { | ||
2443 | { "SLX" }, | ||
2444 | { "" } | ||
2445 | }; | ||
2446 | MODULE_DEVICE_TABLE(eisa, sx_eisa_tbl); | ||
2447 | |||
2448 | static struct eisa_driver sx_eisadriver = { | ||
2449 | .id_table = sx_eisa_tbl, | ||
2450 | .driver = { | ||
2451 | .name = "sx", | ||
2452 | .probe = sx_eisa_probe, | ||
2453 | .remove = __devexit_p(sx_eisa_remove), | ||
2454 | } | ||
2455 | }; | ||
2456 | |||
2457 | #endif | ||
2458 | |||
2356 | /******************************************************** | 2459 | /******************************************************** |
2357 | * Setting bit 17 in the CNTRL register of the PLX 9050 * | 2460 | * Setting bit 17 in the CNTRL register of the PLX 9050 * |
2358 | * chip forces a retry on writes while a read is pending.* | 2461 | * 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, | |||
2391 | unsigned int i; | 2494 | unsigned int i; |
2392 | int retval = -EIO; | 2495 | int retval = -EIO; |
2393 | 2496 | ||
2394 | for (i = 0; i < SX_NBOARDS; i++) | 2497 | i = sx_find_free_board(); |
2395 | if (!(boards[i].flags & SX_BOARD_PRESENT)) | ||
2396 | break; | ||
2397 | 2498 | ||
2398 | if (i == SX_NBOARDS) | 2499 | if (i == SX_NBOARDS) |
2399 | goto err; | 2500 | goto err; |
@@ -2449,19 +2550,7 @@ static void __devexit sx_pci_remove(struct pci_dev *pdev) | |||
2449 | { | 2550 | { |
2450 | struct sx_board *board = pci_get_drvdata(pdev); | 2551 | struct sx_board *board = pci_get_drvdata(pdev); |
2451 | 2552 | ||
2452 | if (board->flags & SX_BOARD_INITIALIZED) { | 2553 | sx_remove_card(board); |
2453 | /* The board should stop messing with us. (actually I mean the | ||
2454 | interrupt) */ | ||
2455 | sx_reset(board); | ||
2456 | if ((board->irq) && (board->flags & SX_IRQ_ALLOCATED)) | ||
2457 | free_irq(board->irq, board); | ||
2458 | |||
2459 | /* It is safe/allowed to del_timer a non-active timer */ | ||
2460 | del_timer(&board->timer); | ||
2461 | iounmap(board->base); | ||
2462 | |||
2463 | board->flags &= ~(SX_BOARD_INITIALIZED|SX_BOARD_PRESENT); | ||
2464 | } | ||
2465 | } | 2554 | } |
2466 | 2555 | ||
2467 | /* Specialix has a whole bunch of cards with 0x2000 as the device ID. They say | 2556 | /* 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 = { | |||
2484 | 2573 | ||
2485 | static int __init sx_init(void) | 2574 | static int __init sx_init(void) |
2486 | { | 2575 | { |
2576 | #ifdef CONFIG_EISA | ||
2577 | int retval1; | ||
2578 | #endif | ||
2487 | int retval, i; | 2579 | int retval, i; |
2488 | int found = 0; | 2580 | int found = 0; |
2489 | int eisa_slot; | ||
2490 | struct sx_board *board; | 2581 | struct sx_board *board; |
2491 | 2582 | ||
2492 | func_enter(); | 2583 | func_enter(); |
@@ -2549,42 +2640,18 @@ static int __init sx_init(void) | |||
2549 | iounmap (board->base); | 2640 | iounmap (board->base); |
2550 | } | 2641 | } |
2551 | } | 2642 | } |
2552 | 2643 | #ifdef CONFIG_EISA | |
2553 | sx_dprintk(SX_DEBUG_PROBE, "Probing for EISA cards\n"); | 2644 | retval1 = eisa_driver_register(&sx_eisadriver); |
2554 | for(eisa_slot=0x1000; eisa_slot<0x10000; eisa_slot+=0x1000) | 2645 | #endif |
2555 | { | ||
2556 | if((inb(eisa_slot+0xc80)==0x4d) && | ||
2557 | (inb(eisa_slot+0xc81)==0x98)) | ||
2558 | { | ||
2559 | sx_dprintk(SX_DEBUG_PROBE, "%s : Signature found in EISA slot %d, Product %d Rev %d\n", | ||
2560 | "XIO", (eisa_slot>>12), inb(eisa_slot+0xc82), inb(eisa_slot+0xc83)); | ||
2561 | |||
2562 | board = &boards[found]; | ||
2563 | board->eisa_base = eisa_slot; | ||
2564 | board->flags &= ~SX_BOARD_TYPE; | ||
2565 | board->flags |= SI_EISA_BOARD; | ||
2566 | |||
2567 | board->hw_base = (((inb(0xc01+eisa_slot) << 8) + inb(0xc00+eisa_slot)) << 16); | ||
2568 | board->base2 = | ||
2569 | board->base = ioremap(board->hw_base, SI2_EISA_WINDOW_LEN); | ||
2570 | |||
2571 | sx_dprintk(SX_DEBUG_PROBE, "IO hw_base address: %lx\n", board->hw_base); | ||
2572 | sx_dprintk(SX_DEBUG_PROBE, "base: %p\n", board->base); | ||
2573 | board->irq = inb(board->eisa_base+0xc02)>>4; | ||
2574 | sx_dprintk(SX_DEBUG_PROBE, "IRQ: %d\n", board->irq); | ||
2575 | |||
2576 | probe_si(board); | ||
2577 | |||
2578 | found++; | ||
2579 | } | ||
2580 | } | ||
2581 | |||
2582 | retval = pci_register_driver(&sx_pcidriver); | 2646 | retval = pci_register_driver(&sx_pcidriver); |
2583 | 2647 | ||
2584 | if (found) { | 2648 | if (found) { |
2585 | printk (KERN_INFO "sx: total of %d boards detected.\n", found); | 2649 | printk (KERN_INFO "sx: total of %d boards detected.\n", found); |
2586 | retval = 0; | 2650 | retval = 0; |
2587 | } else if (retval) { | 2651 | } else if (retval) { |
2652 | #ifdef CONFIG_EISA | ||
2653 | if (retval1) | ||
2654 | #endif | ||
2588 | misc_deregister(&sx_fw_device); | 2655 | misc_deregister(&sx_fw_device); |
2589 | } | 2656 | } |
2590 | 2657 | ||
@@ -2599,6 +2666,9 @@ static void __exit sx_exit (void) | |||
2599 | struct sx_board *board; | 2666 | struct sx_board *board; |
2600 | 2667 | ||
2601 | func_enter(); | 2668 | func_enter(); |
2669 | #ifdef CONFIG_EISA | ||
2670 | eisa_driver_unregister(&sx_eisadriver); | ||
2671 | #endif | ||
2602 | pci_unregister_driver(&sx_pcidriver); | 2672 | pci_unregister_driver(&sx_pcidriver); |
2603 | for (i = 0; i < SX_NBOARDS; i++) { | 2673 | for (i = 0; i < SX_NBOARDS; i++) { |
2604 | board = &boards[i]; | 2674 | board = &boards[i]; |