diff options
Diffstat (limited to 'drivers/ide/ide-probe.c')
-rw-r--r-- | drivers/ide/ide-probe.c | 215 |
1 files changed, 111 insertions, 104 deletions
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 06575a12b635..f27baa5f140e 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -121,7 +121,8 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) /* read 512 bytes of id info */ hwif->tp_ops->input_data(drive, NULL, id, SECTOR_SIZE); - drive->id_read = 1; + drive->dev_flags |= IDE_DFLAG_ID_READ; + local_irq_enable(); #ifdef DEBUG printk(KERN_INFO "%s: dumping identify data\n", drive->name); @@ -153,8 +154,8 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) printk(KERN_INFO "%s: %s, ", drive->name, m); - drive->present = 1; - drive->dead = 0; + drive->dev_flags |= IDE_DFLAG_PRESENT; + drive->dev_flags &= ~IDE_DFLAG_DEAD; /* * Check for an ATAPI device @@ -172,14 +173,14 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) printk(KERN_CONT "cdrom or floppy?, assuming "); if (drive->media != ide_cdrom) { printk(KERN_CONT "FLOPPY"); - drive->removable = 1; + drive->dev_flags |= IDE_DFLAG_REMOVABLE; break; } } /* Early cdrom models used zero */ type = ide_cdrom; case ide_cdrom: - drive->removable = 1; + drive->dev_flags |= IDE_DFLAG_REMOVABLE; #ifdef CONFIG_PPC /* kludge for Apple PowerBook internal zip */ if (!strstr(m, "CD-ROM") && strstr(m, "ZIP")) { @@ -195,7 +196,7 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) break; case ide_optical: printk(KERN_CONT "OPTICAL"); - drive->removable = 1; + drive->dev_flags |= IDE_DFLAG_REMOVABLE; break; default: printk(KERN_CONT "UNKNOWN (type %d)", type); @@ -205,6 +206,10 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) drive->media = type; /* an ATAPI device ignores DRDY */ drive->ready_stat = 0; + if (ata_id_cdb_intr(id)) + drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT; + /* we don't do head unloading on ATAPI devices */ + drive->dev_flags |= IDE_DFLAG_NO_UNLOAD; return; } @@ -216,17 +221,20 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) /* CF devices are *not* removable in Linux definition of the term */ if (is_cfa == 0 && (id[ATA_ID_CONFIG] & (1 << 7))) - drive->removable = 1; + drive->dev_flags |= IDE_DFLAG_REMOVABLE; drive->media = ide_disk; + if (!ata_id_has_unload(drive->id)) + drive->dev_flags |= IDE_DFLAG_NO_UNLOAD; + printk(KERN_CONT "%s DISK drive\n", is_cfa ? "CFA" : "ATA"); return; err_misc: kfree(id); - drive->present = 0; + drive->dev_flags &= ~IDE_DFLAG_PRESENT; return; } @@ -426,16 +434,15 @@ static int do_probe (ide_drive_t *drive, u8 cmd) ide_hwif_t *hwif = HWIF(drive); const struct ide_tp_ops *tp_ops = hwif->tp_ops; int rc; - u8 stat; + u8 present = !!(drive->dev_flags & IDE_DFLAG_PRESENT), stat; + + /* avoid waiting for inappropriate probes */ + if (present && drive->media != ide_disk && cmd == ATA_CMD_ID_ATA) + return 4; - if (drive->present) { - /* avoid waiting for inappropriate probes */ - if (drive->media != ide_disk && cmd == ATA_CMD_ID_ATA) - return 4; - } #ifdef DEBUG printk(KERN_INFO "probing for %s: present=%d, media=%d, probetype=%s\n", - drive->name, drive->present, drive->media, + drive->name, present, drive->media, (cmd == ATA_CMD_ID_ATA) ? "ATA" : "ATAPI"); #endif @@ -446,8 +453,8 @@ static int do_probe (ide_drive_t *drive, u8 cmd) SELECT_DRIVE(drive); msleep(50); - if (ide_read_device(drive) != drive->select.all && !drive->present) { - if (drive->select.b.unit != 0) { + if (ide_read_device(drive) != drive->select && present == 0) { + if (drive->dn & 1) { /* exit with drive0 selected */ SELECT_DRIVE(&hwif->drives[0]); /* allow ATA_BUSY to assert & clear */ @@ -460,7 +467,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd) stat = tp_ops->read_status(hwif); if (OK_STAT(stat, ATA_DRDY, ATA_BUSY) || - drive->present || cmd == ATA_CMD_ID_ATAPI) { + present || cmd == ATA_CMD_ID_ATAPI) { /* send cmd and wait */ if ((rc = try_to_identify(drive, cmd))) { /* failed: try again */ @@ -493,7 +500,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd) /* not present or maybe ATAPI */ rc = 3; } - if (drive->select.b.unit != 0) { + if (drive->dn & 1) { /* exit with drive0 selected */ SELECT_DRIVE(&hwif->drives[0]); msleep(50); @@ -542,8 +549,8 @@ static void enable_nest (ide_drive_t *drive) * and presents things to the user as needed. * * Returns: 0 no device was found - * 1 device was found (note: drive->present might - * still be 0) + * 1 device was found + * (note: IDE_DFLAG_PRESENT might still be not set) */ static inline u8 probe_for_drive (ide_drive_t *drive) @@ -559,10 +566,10 @@ static inline u8 probe_for_drive (ide_drive_t *drive) * Also note that 0 everywhere means "can't do X" */ + drive->dev_flags &= ~IDE_DFLAG_ID_READ; + drive->id = kzalloc(SECTOR_SIZE, GFP_KERNEL); - drive->id_read = 0; - if(drive->id == NULL) - { + if (drive->id == NULL) { printk(KERN_ERR "ide: out of memory for id data.\n"); return 0; } @@ -571,14 +578,14 @@ static inline u8 probe_for_drive (ide_drive_t *drive) strcpy(m, "UNKNOWN"); /* skip probing? */ - if (!drive->noprobe) { + if ((drive->dev_flags & IDE_DFLAG_NOPROBE) == 0) { retry: /* if !(success||timed-out) */ if (do_probe(drive, ATA_CMD_ID_ATA) >= 2) /* look for ATAPI device */ (void)do_probe(drive, ATA_CMD_ID_ATAPI); - if (!drive->present) + if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) /* drive not found */ return 0; @@ -588,7 +595,7 @@ retry: } /* identification failed? */ - if (!drive->id_read) { + if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) { if (drive->media == ide_disk) { printk(KERN_INFO "%s: non-IDE drive, CHS=%d/%d/%d\n", drive->name, drive->cyl, @@ -598,15 +605,17 @@ retry: } else { /* nuke it */ printk(KERN_WARNING "%s: Unknown device on bus refused identification. Ignoring.\n", drive->name); - drive->present = 0; + drive->dev_flags &= ~IDE_DFLAG_PRESENT; } } /* drive was found */ } - if(!drive->present) + + if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) return 0; + /* The drive wasn't being helpful. Add generic info only */ - if (drive->id_read == 0) { + if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) { generic_id(drive); return 1; } @@ -616,7 +625,7 @@ retry: ide_disk_init_mult_count(drive); } - return drive->present; + return !!(drive->dev_flags & IDE_DFLAG_PRESENT); } static void hwif_release_dev(struct device *dev) @@ -707,7 +716,8 @@ static int ide_port_wait_ready(ide_hwif_t *hwif) ide_drive_t *drive = &hwif->drives[unit]; /* Ignore disks that we will not probe for later. */ - if (!drive->noprobe || drive->present) { + if ((drive->dev_flags & IDE_DFLAG_NOPROBE) == 0 || + (drive->dev_flags & IDE_DFLAG_PRESENT)) { SELECT_DRIVE(drive); hwif->tp_ops->set_irq(hwif, 1); mdelay(2); @@ -739,7 +749,7 @@ void ide_undecoded_slave(ide_drive_t *dev1) { ide_drive_t *dev0 = &dev1->hwif->drives[0]; - if ((dev1->dn & 1) == 0 || dev0->present == 0) + if ((dev1->dn & 1) == 0 || (dev0->dev_flags & IDE_DFLAG_PRESENT) == 0) return; /* If the models don't match they are not the same product */ @@ -759,7 +769,7 @@ void ide_undecoded_slave(ide_drive_t *dev1) /* Appears to be an IDE flash adapter with decode bugs */ printk(KERN_WARNING "ide-probe: ignoring undecoded slave\n"); - dev1->present = 0; + dev1->dev_flags &= ~IDE_DFLAG_PRESENT; } EXPORT_SYMBOL_GPL(ide_undecoded_slave); @@ -772,7 +782,8 @@ static int ide_probe_port(ide_hwif_t *hwif) BUG_ON(hwif->present); - if (hwif->drives[0].noprobe && hwif->drives[1].noprobe) + if ((hwif->drives[0].dev_flags & IDE_DFLAG_NOPROBE) && + (hwif->drives[1].dev_flags & IDE_DFLAG_NOPROBE)) return -EACCES; /* @@ -794,9 +805,9 @@ static int ide_probe_port(ide_hwif_t *hwif) */ for (unit = 0; unit < MAX_DRIVES; ++unit) { ide_drive_t *drive = &hwif->drives[unit]; - drive->dn = (hwif->channel ? 2 : 0) + unit; + (void) probe_for_drive(drive); - if (drive->present) + if (drive->dev_flags & IDE_DFLAG_PRESENT) rc = 0; } @@ -820,17 +831,19 @@ static void ide_port_tune_devices(ide_hwif_t *hwif) for (unit = 0; unit < MAX_DRIVES; unit++) { ide_drive_t *drive = &hwif->drives[unit]; - if (drive->present && port_ops && port_ops->quirkproc) - port_ops->quirkproc(drive); + if (drive->dev_flags & IDE_DFLAG_PRESENT) { + if (port_ops && port_ops->quirkproc) + port_ops->quirkproc(drive); + } } for (unit = 0; unit < MAX_DRIVES; ++unit) { ide_drive_t *drive = &hwif->drives[unit]; - if (drive->present) { + if (drive->dev_flags & IDE_DFLAG_PRESENT) { ide_set_max_pio(drive); - drive->nice1 = 1; + drive->dev_flags |= IDE_DFLAG_NICE1; if (hwif->dma_ops) ide_set_dma(drive); @@ -840,14 +853,14 @@ static void ide_port_tune_devices(ide_hwif_t *hwif) for (unit = 0; unit < MAX_DRIVES; ++unit) { ide_drive_t *drive = &hwif->drives[unit]; - if (hwif->host_flags & IDE_HFLAG_NO_IO_32BIT) - drive->no_io_32bit = 1; + if ((hwif->host_flags & IDE_HFLAG_NO_IO_32BIT) || + drive->id[ATA_ID_DWORD_IO]) + drive->dev_flags |= IDE_DFLAG_NO_IO_32BIT; else - drive->no_io_32bit = drive->id[ATA_ID_DWORD_IO] ? 1 : 0; + drive->dev_flags &= ~IDE_DFLAG_NO_IO_32BIT; } } -#if MAX_HWIFS > 1 /* * save_match() is used to simplify logic in init_irq() below. * @@ -872,7 +885,6 @@ static void save_match(ide_hwif_t *hwif, ide_hwif_t *new, ide_hwif_t **match) if (!m || m->irq != hwif->irq) /* don't undo a prior perfect match */ *match = new; } -#endif /* MAX_HWIFS > 1 */ /* * init request queue @@ -951,26 +963,33 @@ static void ide_add_drive_to_hwgroup(ide_drive_t *drive) * - allocate the block device queue * - link drive into the hwgroup */ -static void ide_port_setup_devices(ide_hwif_t *hwif) +static int ide_port_setup_devices(ide_hwif_t *hwif) { - int i; + int i, j = 0; mutex_lock(&ide_cfg_mtx); for (i = 0; i < MAX_DRIVES; i++) { ide_drive_t *drive = &hwif->drives[i]; - if (!drive->present) + if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) continue; if (ide_init_queue(drive)) { printk(KERN_ERR "ide: failed to init %s\n", drive->name); + kfree(drive->id); + drive->id = NULL; + drive->dev_flags &= ~IDE_DFLAG_PRESENT; continue; } + j++; + ide_add_drive_to_hwgroup(drive); } mutex_unlock(&ide_cfg_mtx); + + return j; } static ide_hwif_t *ide_ports[MAX_HWIFS]; @@ -1029,7 +1048,7 @@ static int init_irq (ide_hwif_t *hwif) mutex_lock(&ide_cfg_mtx); hwif->hwgroup = NULL; -#if MAX_HWIFS > 1 + /* * Group up with any other hwifs that share our irq(s). */ @@ -1054,7 +1073,7 @@ static int init_irq (ide_hwif_t *hwif) } } } -#endif /* MAX_HWIFS > 1 */ + /* * If we are still without a hwgroup, then form a new one */ @@ -1153,12 +1172,13 @@ static struct kobject *ata_probe(dev_t dev, int *part, void *data) ide_hwif_t *hwif = data; int unit = *part >> PARTN_BITS; ide_drive_t *drive = &hwif->drives[unit]; - if (!drive->present) + + if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) return NULL; if (drive->media == ide_disk) request_module("ide-disk"); - if (drive->scsi) + if (drive->dev_flags & IDE_DFLAG_SCSI) request_module("ide-scsi"); if (drive->media == ide_cdrom || drive->media == ide_optical) request_module("ide-cd"); @@ -1205,7 +1225,7 @@ EXPORT_SYMBOL_GPL(ide_unregister_region); void ide_init_disk(struct gendisk *disk, ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; - unsigned int unit = (drive->select.all >> 4) & 1; + unsigned int unit = drive->dn & 1; disk->major = hwif->major; disk->first_minor = unit << PARTN_BITS; @@ -1248,7 +1268,7 @@ static void drive_release_dev (struct device *dev) ide_remove_drive_from_hwgroup(drive); kfree(drive->id); drive->id = NULL; - drive->present = 0; + drive->dev_flags &= ~IDE_DFLAG_PRESENT; /* Messed up locking ... */ spin_unlock_irq(&ide_lock); blk_cleanup_queue(drive->queue); @@ -1327,7 +1347,7 @@ static void hwif_register_devices(ide_hwif_t *hwif) struct device *dev = &drive->gendev; int ret; - if (!drive->present) + if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) continue; snprintf(dev->bus_id, BUS_ID_SIZE, "%u.%u", hwif->index, i); @@ -1351,12 +1371,14 @@ static void ide_port_init_devices(ide_hwif_t *hwif) for (i = 0; i < MAX_DRIVES; i++) { ide_drive_t *drive = &hwif->drives[i]; + drive->dn = i + hwif->channel * 2; + if (hwif->host_flags & IDE_HFLAG_IO_32BIT) drive->io_32bit = 1; if (hwif->host_flags & IDE_HFLAG_UNMASK_IRQS) - drive->unmask = 1; + drive->dev_flags |= IDE_DFLAG_UNMASK; if (hwif->host_flags & IDE_HFLAG_NO_UNMASK_IRQS) - drive->no_unmask = 1; + drive->dev_flags |= IDE_DFLAG_NO_UNMASK; if (port_ops && port_ops->init_dev) port_ops->init_dev(drive); @@ -1513,19 +1535,14 @@ static int ide_find_port_slot(const struct ide_port_info *d) * ports 0x1f0/0x170 (the ide0/ide1 defaults). */ mutex_lock(&ide_cfg_mtx); - if (MAX_HWIFS == 1) { - if (ide_indexes == 0 && i == 0) - idx = 1; + if (bootable) { + if ((ide_indexes | i) != (1 << MAX_HWIFS) - 1) + idx = ffz(ide_indexes | i); } else { - if (bootable) { - if ((ide_indexes | i) != (1 << MAX_HWIFS) - 1) - idx = ffz(ide_indexes | i); - } else { - if ((ide_indexes | 3) != (1 << MAX_HWIFS) - 1) - idx = ffz(ide_indexes | 3); - else if ((ide_indexes & 3) != 3) - idx = ffz(ide_indexes); - } + if ((ide_indexes | 3) != (1 << MAX_HWIFS) - 1) + idx = ffz(ide_indexes | 3); + else if ((ide_indexes & 3) != 3) + idx = ffz(ide_indexes); } if (idx >= 0) ide_indexes |= (1 << idx); @@ -1541,8 +1558,7 @@ static void ide_free_port_slot(int idx) mutex_unlock(&ide_cfg_mtx); } -struct ide_host *ide_host_alloc_all(const struct ide_port_info *d, - hw_regs_t **hws) +struct ide_host *ide_host_alloc(const struct ide_port_info *d, hw_regs_t **hws) { struct ide_host *host; int i; @@ -1551,7 +1567,7 @@ struct ide_host *ide_host_alloc_all(const struct ide_port_info *d, if (host == NULL) return NULL; - for (i = 0; i < MAX_HWIFS; i++) { + for (i = 0; i < MAX_HOST_PORTS; i++) { ide_hwif_t *hwif; int idx; @@ -1593,18 +1609,6 @@ struct ide_host *ide_host_alloc_all(const struct ide_port_info *d, return host; } -EXPORT_SYMBOL_GPL(ide_host_alloc_all); - -struct ide_host *ide_host_alloc(const struct ide_port_info *d, hw_regs_t **hws) -{ - hw_regs_t *hws_all[MAX_HWIFS]; - int i; - - for (i = 0; i < MAX_HWIFS; i++) - hws_all[i] = (i < 4) ? hws[i] : NULL; - - return ide_host_alloc_all(d, hws_all); -} EXPORT_SYMBOL_GPL(ide_host_alloc); int ide_host_register(struct ide_host *host, const struct ide_port_info *d, @@ -1613,7 +1617,7 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d, ide_hwif_t *hwif, *mate = NULL; int i, j = 0; - for (i = 0; i < MAX_HWIFS; i++) { + for (i = 0; i < MAX_HOST_PORTS; i++) { hwif = host->ports[i]; if (hwif == NULL) { @@ -1626,22 +1630,22 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d, if (d == NULL) { mate = NULL; - continue; - } + } else { + if ((i & 1) && mate) { + hwif->mate = mate; + mate->mate = hwif; + } - if ((i & 1) && mate) { - hwif->mate = mate; - mate->mate = hwif; - } + mate = (i & 1) ? NULL : hwif; - mate = (i & 1) ? NULL : hwif; + ide_init_port(hwif, i & 1, d); + ide_port_cable_detect(hwif); + } - ide_init_port(hwif, i & 1, d); - ide_port_cable_detect(hwif); ide_port_init_devices(hwif); } - for (i = 0; i < MAX_HWIFS; i++) { + for (i = 0; i < MAX_HOST_PORTS; i++) { hwif = host->ports[i]; if (hwif == NULL) @@ -1658,7 +1662,7 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d, ide_port_tune_devices(hwif); } - for (i = 0; i < MAX_HWIFS; i++) { + for (i = 0; i < MAX_HOST_PORTS; i++) { hwif = host->ports[i]; if (hwif == NULL) @@ -1671,10 +1675,13 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d, continue; } - j++; - if (hwif->present) - ide_port_setup_devices(hwif); + if (ide_port_setup_devices(hwif) == 0) { + hwif->present = 0; + continue; + } + + j++; ide_acpi_init(hwif); @@ -1682,7 +1689,7 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d, ide_acpi_port_init_devices(hwif); } - for (i = 0; i < MAX_HWIFS; i++) { + for (i = 0; i < MAX_HOST_PORTS; i++) { hwif = host->ports[i]; if (hwif == NULL) @@ -1695,7 +1702,7 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d, hwif_register_devices(hwif); } - for (i = 0; i < MAX_HWIFS; i++) { + for (i = 0; i < MAX_HOST_PORTS; i++) { hwif = host->ports[i]; if (hwif == NULL) @@ -1740,7 +1747,7 @@ void ide_host_free(struct ide_host *host) ide_hwif_t *hwif; int i; - for (i = 0; i < MAX_HWIFS; i++) { + for (i = 0; i < MAX_HOST_PORTS; i++) { hwif = host->ports[i]; if (hwif == NULL) @@ -1758,7 +1765,7 @@ void ide_host_remove(struct ide_host *host) { int i; - for (i = 0; i < MAX_HWIFS; i++) { + for (i = 0; i < MAX_HOST_PORTS; i++) { if (host->ports[i]) ide_unregister(host->ports[i]); } |