diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/char/sx.c | 183 |
1 files changed, 105 insertions, 78 deletions
diff --git a/drivers/char/sx.c b/drivers/char/sx.c index cf08be76b8a7..5e01337e6107 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c | |||
@@ -246,14 +246,6 @@ | |||
246 | #define PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 0x2000 | 246 | #define PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 0x2000 |
247 | #endif | 247 | #endif |
248 | 248 | ||
249 | #ifdef CONFIG_PCI | ||
250 | static struct pci_device_id sx_pci_tbl[] = { | ||
251 | { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, PCI_ANY_ID, PCI_ANY_ID }, | ||
252 | { 0 } | ||
253 | }; | ||
254 | MODULE_DEVICE_TABLE(pci, sx_pci_tbl); | ||
255 | #endif /* CONFIG_PCI */ | ||
256 | |||
257 | /* Configurable options: | 249 | /* Configurable options: |
258 | (Don't be too sure that it'll work if you toggle them) */ | 250 | (Don't be too sure that it'll work if you toggle them) */ |
259 | 251 | ||
@@ -2373,7 +2365,6 @@ static void __exit sx_release_drivers(void) | |||
2373 | func_exit(); | 2365 | func_exit(); |
2374 | } | 2366 | } |
2375 | 2367 | ||
2376 | #ifdef CONFIG_PCI | ||
2377 | /******************************************************** | 2368 | /******************************************************** |
2378 | * Setting bit 17 in the CNTRL register of the PLX 9050 * | 2369 | * Setting bit 17 in the CNTRL register of the PLX 9050 * |
2379 | * chip forces a retry on writes while a read is pending.* | 2370 | * chip forces a retry on writes while a read is pending.* |
@@ -2404,22 +2395,112 @@ static void fix_sx_pci (struct pci_dev *pdev, struct sx_board *board) | |||
2404 | } | 2395 | } |
2405 | iounmap(rebase); | 2396 | iounmap(rebase); |
2406 | } | 2397 | } |
2407 | #endif | ||
2408 | 2398 | ||
2399 | static int __devinit sx_pci_probe(struct pci_dev *pdev, | ||
2400 | const struct pci_device_id *ent) | ||
2401 | { | ||
2402 | struct sx_board *board; | ||
2403 | unsigned int i; | ||
2404 | int retval = -EIO; | ||
2405 | |||
2406 | for (i = 0; i < SX_NBOARDS; i++) | ||
2407 | if (!(boards[i].flags & SX_BOARD_PRESENT)) | ||
2408 | break; | ||
2409 | |||
2410 | if (i == SX_NBOARDS) | ||
2411 | goto err; | ||
2412 | |||
2413 | retval = pci_enable_device(pdev); | ||
2414 | if (retval) | ||
2415 | goto err; | ||
2416 | |||
2417 | board = &boards[i]; | ||
2418 | |||
2419 | board->flags &= ~SX_BOARD_TYPE; | ||
2420 | board->flags |= (pdev->subsystem_vendor == 0x200) ? SX_PCI_BOARD : | ||
2421 | SX_CFPCI_BOARD; | ||
2422 | |||
2423 | /* CF boards use base address 3.... */ | ||
2424 | if (IS_CF_BOARD (board)) | ||
2425 | board->hw_base = pci_resource_start(pdev, 3); | ||
2426 | else | ||
2427 | board->hw_base = pci_resource_start(pdev, 2); | ||
2428 | board->base2 = | ||
2429 | board->base = ioremap(board->hw_base, WINDOW_LEN (board)); | ||
2430 | if (!board->base) { | ||
2431 | dev_err(&pdev->dev, "ioremap failed\n"); | ||
2432 | goto err; | ||
2433 | } | ||
2434 | |||
2435 | /* Most of the stuff on the CF board is offset by 0x18000 .... */ | ||
2436 | if (IS_CF_BOARD (board)) | ||
2437 | board->base += 0x18000; | ||
2438 | |||
2439 | board->irq = pdev->irq; | ||
2440 | |||
2441 | dev_info(&pdev->dev, "Got a specialix card: %p(%d) %x.\n", board->base, | ||
2442 | board->irq, board->flags); | ||
2443 | |||
2444 | if (!probe_sx(board)) { | ||
2445 | retval = -EIO; | ||
2446 | goto err_unmap; | ||
2447 | } | ||
2448 | |||
2449 | fix_sx_pci(pdev, board); | ||
2450 | |||
2451 | pci_set_drvdata(pdev, board); | ||
2452 | |||
2453 | return 0; | ||
2454 | err_unmap: | ||
2455 | iounmap(board->base2); | ||
2456 | err: | ||
2457 | return retval; | ||
2458 | } | ||
2459 | |||
2460 | static void __devexit sx_pci_remove(struct pci_dev *pdev) | ||
2461 | { | ||
2462 | struct sx_board *board = pci_get_drvdata(pdev); | ||
2463 | |||
2464 | if (board->flags & SX_BOARD_INITIALIZED) { | ||
2465 | /* The board should stop messing with us. (actually I mean the | ||
2466 | interrupt) */ | ||
2467 | sx_reset(board); | ||
2468 | if ((board->irq) && (board->flags & SX_IRQ_ALLOCATED)) | ||
2469 | free_irq(board->irq, board); | ||
2470 | |||
2471 | /* It is safe/allowed to del_timer a non-active timer */ | ||
2472 | del_timer(&board->timer); | ||
2473 | iounmap(board->base); | ||
2474 | |||
2475 | board->flags &= ~(SX_BOARD_INITIALIZED|SX_BOARD_PRESENT); | ||
2476 | } | ||
2477 | } | ||
2478 | |||
2479 | /* Specialix has a whole bunch of cards with 0x2000 as the device ID. They say | ||
2480 | its because the standard requires it. So check for SUBVENDOR_ID. */ | ||
2481 | static struct pci_device_id sx_pci_tbl[] = { | ||
2482 | { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, | ||
2483 | .subvendor = 0x0200, .subdevice = PCI_ANY_ID }, | ||
2484 | { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, | ||
2485 | .subvendor = 0x0300, .subdevice = PCI_ANY_ID }, | ||
2486 | { 0 } | ||
2487 | }; | ||
2488 | MODULE_DEVICE_TABLE(pci, sx_pci_tbl); | ||
2489 | |||
2490 | static struct pci_driver sx_pcidriver = { | ||
2491 | .name = "sx", | ||
2492 | .id_table = sx_pci_tbl, | ||
2493 | .probe = sx_pci_probe, | ||
2494 | .remove = __devexit_p(sx_pci_remove) | ||
2495 | }; | ||
2409 | 2496 | ||
2410 | static int __init sx_init(void) | 2497 | static int __init sx_init(void) |
2411 | { | 2498 | { |
2412 | int i; | 2499 | int retval, i; |
2413 | int found = 0; | 2500 | int found = 0; |
2414 | int eisa_slot; | 2501 | int eisa_slot; |
2415 | struct sx_board *board; | 2502 | struct sx_board *board; |
2416 | 2503 | ||
2417 | #ifdef CONFIG_PCI | ||
2418 | struct pci_dev *pdev = NULL; | ||
2419 | unsigned int tint; | ||
2420 | unsigned short tshort; | ||
2421 | #endif | ||
2422 | |||
2423 | func_enter(); | 2504 | func_enter(); |
2424 | sx_dprintk (SX_DEBUG_INIT, "Initing sx module... (sx_debug=%d)\n", sx_debug); | 2505 | sx_dprintk (SX_DEBUG_INIT, "Initing sx module... (sx_debug=%d)\n", sx_debug); |
2425 | if (abs ((long) (&sx_debug) - sx_debug) < 0x10000) { | 2506 | if (abs ((long) (&sx_debug) - sx_debug) < 0x10000) { |
@@ -2434,65 +2515,6 @@ static int __init sx_init(void) | |||
2434 | return -EIO; | 2515 | return -EIO; |
2435 | } | 2516 | } |
2436 | 2517 | ||
2437 | #ifdef CONFIG_PCI | ||
2438 | while ((pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, | ||
2439 | PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, | ||
2440 | pdev))) { | ||
2441 | if (pci_enable_device(pdev)) | ||
2442 | continue; | ||
2443 | |||
2444 | /* Specialix has a whole bunch of cards with | ||
2445 | 0x2000 as the device ID. They say its because | ||
2446 | the standard requires it. Stupid standard. */ | ||
2447 | /* It seems that reading a word doesn't work reliably on 2.0. | ||
2448 | Also, reading a non-aligned dword doesn't work. So we read the | ||
2449 | whole dword at 0x2c and extract the word at 0x2e (SUBSYSTEM_ID) | ||
2450 | ourselves */ | ||
2451 | /* I don't know why the define doesn't work, constant 0x2c does --REW */ | ||
2452 | pci_read_config_dword (pdev, 0x2c, &tint); | ||
2453 | tshort = (tint >> 16) & 0xffff; | ||
2454 | sx_dprintk (SX_DEBUG_PROBE, "Got a specialix card: %x.\n", tint); | ||
2455 | /* sx_dprintk (SX_DEBUG_PROBE, "pdev = %d/%d (%x)\n", pdev, tint); */ | ||
2456 | if ((tshort != 0x0200) && (tshort != 0x0300)) { | ||
2457 | sx_dprintk (SX_DEBUG_PROBE, "But it's not an SX card (%d)...\n", | ||
2458 | tshort); | ||
2459 | continue; | ||
2460 | } | ||
2461 | board = &boards[found]; | ||
2462 | |||
2463 | board->flags &= ~SX_BOARD_TYPE; | ||
2464 | board->flags |= (tshort == 0x200)?SX_PCI_BOARD: | ||
2465 | SX_CFPCI_BOARD; | ||
2466 | |||
2467 | /* CF boards use base address 3.... */ | ||
2468 | if (IS_CF_BOARD (board)) | ||
2469 | board->hw_base = pci_resource_start (pdev, 3); | ||
2470 | else | ||
2471 | board->hw_base = pci_resource_start (pdev, 2); | ||
2472 | board->base2 = | ||
2473 | board->base = ioremap(board->hw_base, WINDOW_LEN (board)); | ||
2474 | if (!board->base) { | ||
2475 | printk(KERN_ERR "ioremap failed\n"); | ||
2476 | /* XXX handle error */ | ||
2477 | } | ||
2478 | |||
2479 | /* Most of the stuff on the CF board is offset by | ||
2480 | 0x18000 .... */ | ||
2481 | if (IS_CF_BOARD (board)) board->base += 0x18000; | ||
2482 | |||
2483 | board->irq = pdev->irq; | ||
2484 | |||
2485 | sx_dprintk (SX_DEBUG_PROBE, "Got a specialix card: %x/%p(%d) %x.\n", | ||
2486 | tint, boards[found].base, board->irq, board->flags); | ||
2487 | |||
2488 | if (probe_sx (board)) { | ||
2489 | found++; | ||
2490 | fix_sx_pci (pdev, board); | ||
2491 | } else | ||
2492 | iounmap(board->base2); | ||
2493 | } | ||
2494 | #endif | ||
2495 | |||
2496 | for (i=0;i<NR_SX_ADDRS;i++) { | 2518 | for (i=0;i<NR_SX_ADDRS;i++) { |
2497 | board = &boards[found]; | 2519 | board = &boards[found]; |
2498 | board->hw_base = sx_probe_addrs[i]; | 2520 | board->hw_base = sx_probe_addrs[i]; |
@@ -2568,14 +2590,18 @@ static int __init sx_init(void) | |||
2568 | found++; | 2590 | found++; |
2569 | } | 2591 | } |
2570 | } | 2592 | } |
2593 | |||
2594 | retval = pci_register_driver(&sx_pcidriver); | ||
2595 | |||
2571 | if (found) { | 2596 | if (found) { |
2572 | printk (KERN_INFO "sx: total of %d boards detected.\n", found); | 2597 | printk (KERN_INFO "sx: total of %d boards detected.\n", found); |
2573 | } else { | 2598 | retval = 0; |
2599 | } else if (retval) { | ||
2574 | misc_deregister(&sx_fw_device); | 2600 | misc_deregister(&sx_fw_device); |
2575 | } | 2601 | } |
2576 | 2602 | ||
2577 | func_exit(); | 2603 | func_exit(); |
2578 | return found?0:-EIO; | 2604 | return retval; |
2579 | } | 2605 | } |
2580 | 2606 | ||
2581 | 2607 | ||
@@ -2585,6 +2611,7 @@ static void __exit sx_exit (void) | |||
2585 | struct sx_board *board; | 2611 | struct sx_board *board; |
2586 | 2612 | ||
2587 | func_enter(); | 2613 | func_enter(); |
2614 | pci_unregister_driver(&sx_pcidriver); | ||
2588 | for (i = 0; i < SX_NBOARDS; i++) { | 2615 | for (i = 0; i < SX_NBOARDS; i++) { |
2589 | board = &boards[i]; | 2616 | board = &boards[i]; |
2590 | if (board->flags & SX_BOARD_INITIALIZED) { | 2617 | if (board->flags & SX_BOARD_INITIALIZED) { |