diff options
Diffstat (limited to 'drivers/ide/ide-probe.c')
-rw-r--r-- | drivers/ide/ide-probe.c | 175 |
1 files changed, 80 insertions, 95 deletions
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 0379d1f697cf..edf650b20c67 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c | |||
@@ -235,9 +235,6 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) | |||
235 | drive->media = ide_disk; | 235 | drive->media = ide_disk; |
236 | printk("%s DISK drive\n", (id->config == 0x848a) ? "CFA" : "ATA" ); | 236 | printk("%s DISK drive\n", (id->config == 0x848a) ? "CFA" : "ATA" ); |
237 | 237 | ||
238 | if (hwif->quirkproc) | ||
239 | drive->quirk_list = hwif->quirkproc(drive); | ||
240 | |||
241 | return; | 238 | return; |
242 | 239 | ||
243 | err_misc: | 240 | err_misc: |
@@ -353,22 +350,19 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd) | |||
353 | * the irq handler isn't expecting. | 350 | * the irq handler isn't expecting. |
354 | */ | 351 | */ |
355 | if (IDE_CONTROL_REG) { | 352 | if (IDE_CONTROL_REG) { |
356 | u8 ctl = drive->ctl | 2; | ||
357 | if (!hwif->irq) { | 353 | if (!hwif->irq) { |
358 | autoprobe = 1; | 354 | autoprobe = 1; |
359 | cookie = probe_irq_on(); | 355 | cookie = probe_irq_on(); |
360 | /* enable device irq */ | ||
361 | ctl &= ~2; | ||
362 | } | 356 | } |
363 | hwif->OUTB(ctl, IDE_CONTROL_REG); | 357 | ide_set_irq(drive, autoprobe); |
364 | } | 358 | } |
365 | 359 | ||
366 | retval = actual_try_to_identify(drive, cmd); | 360 | retval = actual_try_to_identify(drive, cmd); |
367 | 361 | ||
368 | if (autoprobe) { | 362 | if (autoprobe) { |
369 | int irq; | 363 | int irq; |
370 | /* mask device irq */ | 364 | |
371 | hwif->OUTB(drive->ctl|2, IDE_CONTROL_REG); | 365 | ide_set_irq(drive, 0); |
372 | /* clear drive IRQ */ | 366 | /* clear drive IRQ */ |
373 | (void) hwif->INB(IDE_STATUS_REG); | 367 | (void) hwif->INB(IDE_STATUS_REG); |
374 | udelay(5); | 368 | udelay(5); |
@@ -388,6 +382,20 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd) | |||
388 | return retval; | 382 | return retval; |
389 | } | 383 | } |
390 | 384 | ||
385 | static int ide_busy_sleep(ide_hwif_t *hwif) | ||
386 | { | ||
387 | unsigned long timeout = jiffies + WAIT_WORSTCASE; | ||
388 | u8 stat; | ||
389 | |||
390 | do { | ||
391 | msleep(50); | ||
392 | stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]); | ||
393 | if ((stat & BUSY_STAT) == 0) | ||
394 | return 0; | ||
395 | } while (time_before(jiffies, timeout)); | ||
396 | |||
397 | return 1; | ||
398 | } | ||
391 | 399 | ||
392 | /** | 400 | /** |
393 | * do_probe - probe an IDE device | 401 | * do_probe - probe an IDE device |
@@ -456,7 +464,6 @@ static int do_probe (ide_drive_t *drive, u8 cmd) | |||
456 | if ((rc == 1 && cmd == WIN_PIDENTIFY) && | 464 | if ((rc == 1 && cmd == WIN_PIDENTIFY) && |
457 | ((drive->autotune == IDE_TUNE_DEFAULT) || | 465 | ((drive->autotune == IDE_TUNE_DEFAULT) || |
458 | (drive->autotune == IDE_TUNE_AUTO))) { | 466 | (drive->autotune == IDE_TUNE_AUTO))) { |
459 | unsigned long timeout; | ||
460 | printk("%s: no response (status = 0x%02x), " | 467 | printk("%s: no response (status = 0x%02x), " |
461 | "resetting drive\n", drive->name, | 468 | "resetting drive\n", drive->name, |
462 | hwif->INB(IDE_STATUS_REG)); | 469 | hwif->INB(IDE_STATUS_REG)); |
@@ -464,10 +471,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd) | |||
464 | hwif->OUTB(drive->select.all, IDE_SELECT_REG); | 471 | hwif->OUTB(drive->select.all, IDE_SELECT_REG); |
465 | msleep(50); | 472 | msleep(50); |
466 | hwif->OUTB(WIN_SRST, IDE_COMMAND_REG); | 473 | hwif->OUTB(WIN_SRST, IDE_COMMAND_REG); |
467 | timeout = jiffies; | 474 | (void)ide_busy_sleep(hwif); |
468 | while (((hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && | ||
469 | time_before(jiffies, timeout + WAIT_WORSTCASE)) | ||
470 | msleep(50); | ||
471 | rc = try_to_identify(drive, cmd); | 475 | rc = try_to_identify(drive, cmd); |
472 | } | 476 | } |
473 | if (rc == 1) | 477 | if (rc == 1) |
@@ -495,20 +499,16 @@ static int do_probe (ide_drive_t *drive, u8 cmd) | |||
495 | static void enable_nest (ide_drive_t *drive) | 499 | static void enable_nest (ide_drive_t *drive) |
496 | { | 500 | { |
497 | ide_hwif_t *hwif = HWIF(drive); | 501 | ide_hwif_t *hwif = HWIF(drive); |
498 | unsigned long timeout; | ||
499 | 502 | ||
500 | printk("%s: enabling %s -- ", hwif->name, drive->id->model); | 503 | printk("%s: enabling %s -- ", hwif->name, drive->id->model); |
501 | SELECT_DRIVE(drive); | 504 | SELECT_DRIVE(drive); |
502 | msleep(50); | 505 | msleep(50); |
503 | hwif->OUTB(EXABYTE_ENABLE_NEST, IDE_COMMAND_REG); | 506 | hwif->OUTB(EXABYTE_ENABLE_NEST, IDE_COMMAND_REG); |
504 | timeout = jiffies + WAIT_WORSTCASE; | 507 | |
505 | do { | 508 | if (ide_busy_sleep(hwif)) { |
506 | if (time_after(jiffies, timeout)) { | 509 | printk(KERN_CONT "failed (timeout)\n"); |
507 | printk("failed (timeout)\n"); | 510 | return; |
508 | return; | 511 | } |
509 | } | ||
510 | msleep(50); | ||
511 | } while ((hwif->INB(IDE_STATUS_REG)) & BUSY_STAT); | ||
512 | 512 | ||
513 | msleep(50); | 513 | msleep(50); |
514 | 514 | ||
@@ -656,8 +656,7 @@ static int wait_hwif_ready(ide_hwif_t *hwif) | |||
656 | /* Ignore disks that we will not probe for later. */ | 656 | /* Ignore disks that we will not probe for later. */ |
657 | if (!drive->noprobe || drive->present) { | 657 | if (!drive->noprobe || drive->present) { |
658 | SELECT_DRIVE(drive); | 658 | SELECT_DRIVE(drive); |
659 | if (IDE_CONTROL_REG) | 659 | ide_set_irq(drive, 1); |
660 | hwif->OUTB(drive->ctl, IDE_CONTROL_REG); | ||
661 | mdelay(2); | 660 | mdelay(2); |
662 | rc = ide_wait_not_busy(hwif, 35000); | 661 | rc = ide_wait_not_busy(hwif, 35000); |
663 | if (rc) | 662 | if (rc) |
@@ -676,19 +675,18 @@ out: | |||
676 | 675 | ||
677 | /** | 676 | /** |
678 | * ide_undecoded_slave - look for bad CF adapters | 677 | * ide_undecoded_slave - look for bad CF adapters |
679 | * @hwif: interface | 678 | * @drive1: drive |
680 | * | 679 | * |
681 | * Analyse the drives on the interface and attempt to decide if we | 680 | * Analyse the drives on the interface and attempt to decide if we |
682 | * have the same drive viewed twice. This occurs with crap CF adapters | 681 | * have the same drive viewed twice. This occurs with crap CF adapters |
683 | * and PCMCIA sometimes. | 682 | * and PCMCIA sometimes. |
684 | */ | 683 | */ |
685 | 684 | ||
686 | void ide_undecoded_slave(ide_hwif_t *hwif) | 685 | void ide_undecoded_slave(ide_drive_t *drive1) |
687 | { | 686 | { |
688 | ide_drive_t *drive0 = &hwif->drives[0]; | 687 | ide_drive_t *drive0 = &drive1->hwif->drives[0]; |
689 | ide_drive_t *drive1 = &hwif->drives[1]; | ||
690 | 688 | ||
691 | if (drive0->present == 0 || drive1->present == 0) | 689 | if ((drive1->dn & 1) == 0 || drive0->present == 0) |
692 | return; | 690 | return; |
693 | 691 | ||
694 | /* If the models don't match they are not the same product */ | 692 | /* If the models don't match they are not the same product */ |
@@ -791,18 +789,11 @@ static void probe_hwif(ide_hwif_t *hwif) | |||
791 | } | 789 | } |
792 | } | 790 | } |
793 | if (hwif->io_ports[IDE_CONTROL_OFFSET] && hwif->reset) { | 791 | if (hwif->io_ports[IDE_CONTROL_OFFSET] && hwif->reset) { |
794 | unsigned long timeout = jiffies + WAIT_WORSTCASE; | ||
795 | u8 stat; | ||
796 | |||
797 | printk(KERN_WARNING "%s: reset\n", hwif->name); | 792 | printk(KERN_WARNING "%s: reset\n", hwif->name); |
798 | hwif->OUTB(12, hwif->io_ports[IDE_CONTROL_OFFSET]); | 793 | hwif->OUTB(12, hwif->io_ports[IDE_CONTROL_OFFSET]); |
799 | udelay(10); | 794 | udelay(10); |
800 | hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]); | 795 | hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]); |
801 | do { | 796 | (void)ide_busy_sleep(hwif); |
802 | msleep(50); | ||
803 | stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]); | ||
804 | } while ((stat & BUSY_STAT) && time_after(timeout, jiffies)); | ||
805 | |||
806 | } | 797 | } |
807 | local_irq_restore(flags); | 798 | local_irq_restore(flags); |
808 | /* | 799 | /* |
@@ -817,8 +808,12 @@ static void probe_hwif(ide_hwif_t *hwif) | |||
817 | return; | 808 | return; |
818 | } | 809 | } |
819 | 810 | ||
820 | if (hwif->fixup) | 811 | for (unit = 0; unit < MAX_DRIVES; unit++) { |
821 | hwif->fixup(hwif); | 812 | ide_drive_t *drive = &hwif->drives[unit]; |
813 | |||
814 | if (drive->present && hwif->quirkproc) | ||
815 | hwif->quirkproc(drive); | ||
816 | } | ||
822 | 817 | ||
823 | for (unit = 0; unit < MAX_DRIVES; ++unit) { | 818 | for (unit = 0; unit < MAX_DRIVES; ++unit) { |
824 | ide_drive_t *drive = &hwif->drives[unit]; | 819 | ide_drive_t *drive = &hwif->drives[unit]; |
@@ -833,7 +828,7 @@ static void probe_hwif(ide_hwif_t *hwif) | |||
833 | 828 | ||
834 | drive->nice1 = 1; | 829 | drive->nice1 = 1; |
835 | 830 | ||
836 | if (hwif->ide_dma_on) | 831 | if (hwif->dma_host_set) |
837 | ide_set_dma(drive); | 832 | ide_set_dma(drive); |
838 | } | 833 | } |
839 | } | 834 | } |
@@ -848,25 +843,6 @@ static void probe_hwif(ide_hwif_t *hwif) | |||
848 | } | 843 | } |
849 | } | 844 | } |
850 | 845 | ||
851 | static int hwif_init(ide_hwif_t *hwif); | ||
852 | static void hwif_register_devices(ide_hwif_t *hwif); | ||
853 | |||
854 | static int probe_hwif_init(ide_hwif_t *hwif) | ||
855 | { | ||
856 | probe_hwif(hwif); | ||
857 | |||
858 | if (!hwif_init(hwif)) { | ||
859 | printk(KERN_INFO "%s: failed to initialize IDE interface\n", | ||
860 | hwif->name); | ||
861 | return -1; | ||
862 | } | ||
863 | |||
864 | if (hwif->present) | ||
865 | hwif_register_devices(hwif); | ||
866 | |||
867 | return 0; | ||
868 | } | ||
869 | |||
870 | #if MAX_HWIFS > 1 | 846 | #if MAX_HWIFS > 1 |
871 | /* | 847 | /* |
872 | * save_match() is used to simplify logic in init_irq() below. | 848 | * save_match() is used to simplify logic in init_irq() below. |
@@ -1359,54 +1335,63 @@ static void hwif_register_devices(ide_hwif_t *hwif) | |||
1359 | } | 1335 | } |
1360 | } | 1336 | } |
1361 | 1337 | ||
1362 | int ideprobe_init (void) | 1338 | int ide_device_add_all(u8 *idx) |
1363 | { | 1339 | { |
1364 | unsigned int index; | 1340 | ide_hwif_t *hwif; |
1365 | int probe[MAX_HWIFS]; | 1341 | int i, rc = 0; |
1366 | 1342 | ||
1367 | memset(probe, 0, MAX_HWIFS * sizeof(int)); | 1343 | for (i = 0; i < MAX_HWIFS; i++) { |
1368 | for (index = 0; index < MAX_HWIFS; ++index) | 1344 | if (idx[i] == 0xff) |
1369 | probe[index] = !ide_hwifs[index].present; | 1345 | continue; |
1370 | 1346 | ||
1371 | for (index = 0; index < MAX_HWIFS; ++index) | 1347 | probe_hwif(&ide_hwifs[idx[i]]); |
1372 | if (probe[index]) | 1348 | } |
1373 | probe_hwif(&ide_hwifs[index]); | 1349 | |
1374 | for (index = 0; index < MAX_HWIFS; ++index) | 1350 | for (i = 0; i < MAX_HWIFS; i++) { |
1375 | if (probe[index]) | 1351 | if (idx[i] == 0xff) |
1376 | hwif_init(&ide_hwifs[index]); | 1352 | continue; |
1377 | for (index = 0; index < MAX_HWIFS; ++index) { | 1353 | |
1378 | if (probe[index]) { | 1354 | hwif = &ide_hwifs[idx[i]]; |
1379 | ide_hwif_t *hwif = &ide_hwifs[index]; | 1355 | |
1380 | if (!hwif->present) | 1356 | if (hwif_init(hwif) == 0) { |
1381 | continue; | 1357 | printk(KERN_INFO "%s: failed to initialize IDE " |
1382 | if (hwif->chipset == ide_unknown || hwif->chipset == ide_forced) | 1358 | "interface\n", hwif->name); |
1383 | hwif->chipset = ide_generic; | 1359 | rc = -1; |
1384 | hwif_register_devices(hwif); | 1360 | continue; |
1385 | } | 1361 | } |
1386 | } | 1362 | } |
1387 | for (index = 0; index < MAX_HWIFS; ++index) | ||
1388 | if (probe[index]) | ||
1389 | ide_proc_register_port(&ide_hwifs[index]); | ||
1390 | return 0; | ||
1391 | } | ||
1392 | 1363 | ||
1393 | EXPORT_SYMBOL_GPL(ideprobe_init); | 1364 | for (i = 0; i < MAX_HWIFS; i++) { |
1365 | if (idx[i] == 0xff) | ||
1366 | continue; | ||
1394 | 1367 | ||
1395 | int ide_device_add(u8 idx[4]) | 1368 | hwif = &ide_hwifs[idx[i]]; |
1396 | { | ||
1397 | int i, rc = 0; | ||
1398 | 1369 | ||
1399 | for (i = 0; i < 4; i++) { | 1370 | if (hwif->present) { |
1400 | if (idx[i] != 0xff) | 1371 | if (hwif->chipset == ide_unknown || |
1401 | rc |= probe_hwif_init(&ide_hwifs[idx[i]]); | 1372 | hwif->chipset == ide_forced) |
1373 | hwif->chipset = ide_generic; | ||
1374 | hwif_register_devices(hwif); | ||
1375 | } | ||
1402 | } | 1376 | } |
1403 | 1377 | ||
1404 | for (i = 0; i < 4; i++) { | 1378 | for (i = 0; i < MAX_HWIFS; i++) { |
1405 | if (idx[i] != 0xff) | 1379 | if (idx[i] != 0xff) |
1406 | ide_proc_register_port(&ide_hwifs[idx[i]]); | 1380 | ide_proc_register_port(&ide_hwifs[idx[i]]); |
1407 | } | 1381 | } |
1408 | 1382 | ||
1409 | return rc; | 1383 | return rc; |
1410 | } | 1384 | } |
1385 | EXPORT_SYMBOL_GPL(ide_device_add_all); | ||
1386 | |||
1387 | int ide_device_add(u8 idx[4]) | ||
1388 | { | ||
1389 | u8 idx_all[MAX_HWIFS]; | ||
1390 | int i; | ||
1411 | 1391 | ||
1392 | for (i = 0; i < MAX_HWIFS; i++) | ||
1393 | idx_all[i] = (i < 4) ? idx[i] : 0xff; | ||
1394 | |||
1395 | return ide_device_add_all(idx_all); | ||
1396 | } | ||
1412 | EXPORT_SYMBOL_GPL(ide_device_add); | 1397 | EXPORT_SYMBOL_GPL(ide_device_add); |