aboutsummaryrefslogtreecommitdiff
path: root/drivers/ide/ide-probe.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ide/ide-probe.c')
-rw-r--r--drivers/ide/ide-probe.c459
1 files changed, 226 insertions, 233 deletions
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 994e41099b4..f27baa5f140 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -50,59 +50,54 @@
static void generic_id(ide_drive_t *drive)
{
- drive->id->cyls = drive->cyl;
- drive->id->heads = drive->head;
- drive->id->sectors = drive->sect;
- drive->id->cur_cyls = drive->cyl;
- drive->id->cur_heads = drive->head;
- drive->id->cur_sectors = drive->sect;
+ u16 *id = drive->id;
+
+ id[ATA_ID_CUR_CYLS] = id[ATA_ID_CYLS] = drive->cyl;
+ id[ATA_ID_CUR_HEADS] = id[ATA_ID_HEADS] = drive->head;
+ id[ATA_ID_CUR_SECTORS] = id[ATA_ID_SECTORS] = drive->sect;
}
static void ide_disk_init_chs(ide_drive_t *drive)
{
- struct hd_driveid *id = drive->id;
+ u16 *id = drive->id;
/* Extract geometry if we did not already have one for the drive */
if (!drive->cyl || !drive->head || !drive->sect) {
- drive->cyl = drive->bios_cyl = id->cyls;
- drive->head = drive->bios_head = id->heads;
- drive->sect = drive->bios_sect = id->sectors;
+ drive->cyl = drive->bios_cyl = id[ATA_ID_CYLS];
+ drive->head = drive->bios_head = id[ATA_ID_HEADS];
+ drive->sect = drive->bios_sect = id[ATA_ID_SECTORS];
}
/* Handle logical geometry translation by the drive */
- if ((id->field_valid & 1) && id->cur_cyls &&
- id->cur_heads && (id->cur_heads <= 16) && id->cur_sectors) {
- drive->cyl = id->cur_cyls;
- drive->head = id->cur_heads;
- drive->sect = id->cur_sectors;
+ if (ata_id_current_chs_valid(id)) {
+ drive->cyl = id[ATA_ID_CUR_CYLS];
+ drive->head = id[ATA_ID_CUR_HEADS];
+ drive->sect = id[ATA_ID_CUR_SECTORS];
}
/* Use physical geometry if what we have still makes no sense */
- if (drive->head > 16 && id->heads && id->heads <= 16) {
- drive->cyl = id->cyls;
- drive->head = id->heads;
- drive->sect = id->sectors;
+ if (drive->head > 16 && id[ATA_ID_HEADS] && id[ATA_ID_HEADS] <= 16) {
+ drive->cyl = id[ATA_ID_CYLS];
+ drive->head = id[ATA_ID_HEADS];
+ drive->sect = id[ATA_ID_SECTORS];
}
}
static void ide_disk_init_mult_count(ide_drive_t *drive)
{
- struct hd_driveid *id = drive->id;
-
- drive->mult_count = 0;
- if (id->max_multsect) {
-#ifdef CONFIG_IDEDISK_MULTI_MODE
- id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0;
- id->multsect_valid = id->multsect ? 1 : 0;
- drive->mult_req = id->multsect_valid ? id->max_multsect : 0;
- drive->special.b.set_multmode = drive->mult_req ? 1 : 0;
-#else /* original, pre IDE-NFG, per request of AC */
- drive->mult_req = 0;
- if (drive->mult_req > id->max_multsect)
- drive->mult_req = id->max_multsect;
- if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect))
+ u16 *id = drive->id;
+ u8 max_multsect = id[ATA_ID_MAX_MULTSECT] & 0xff;
+
+ if (max_multsect) {
+ if ((max_multsect / 2) > 1)
+ id[ATA_ID_MULTSECT] = max_multsect | 0x100;
+ else
+ id[ATA_ID_MULTSECT] &= ~0x1ff;
+
+ drive->mult_req = id[ATA_ID_MULTSECT] & 0xff;
+
+ if (drive->mult_req)
drive->special.b.set_multmode = 1;
-#endif
}
}
@@ -119,14 +114,15 @@ static void ide_disk_init_mult_count(ide_drive_t *drive)
static inline void do_identify (ide_drive_t *drive, u8 cmd)
{
ide_hwif_t *hwif = HWIF(drive);
- int bswap = 1;
- struct hd_driveid *id;
+ u16 *id = drive->id;
+ char *m = (char *)&id[ATA_ID_PROD];
+ int bswap = 1, is_cfa;
- id = drive->id;
/* 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);
@@ -135,59 +131,59 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
ide_fix_driveid(id);
/*
- * WIN_IDENTIFY returns little-endian info,
- * WIN_PIDENTIFY *usually* returns little-endian info.
+ * ATA_CMD_ID_ATA returns little-endian info,
+ * ATA_CMD_ID_ATAPI *usually* returns little-endian info.
*/
- if (cmd == WIN_PIDENTIFY) {
- if ((id->model[0] == 'N' && id->model[1] == 'E') /* NEC */
- || (id->model[0] == 'F' && id->model[1] == 'X') /* Mitsumi */
- || (id->model[0] == 'P' && id->model[1] == 'i'))/* Pioneer */
+ if (cmd == ATA_CMD_ID_ATAPI) {
+ if ((m[0] == 'N' && m[1] == 'E') || /* NEC */
+ (m[0] == 'F' && m[1] == 'X') || /* Mitsumi */
+ (m[0] == 'P' && m[1] == 'i')) /* Pioneer */
/* Vertos drives may still be weird */
- bswap ^= 1;
+ bswap ^= 1;
}
- ide_fixstring(id->model, sizeof(id->model), bswap);
- ide_fixstring(id->fw_rev, sizeof(id->fw_rev), bswap);
- ide_fixstring(id->serial_no, sizeof(id->serial_no), bswap);
+
+ ide_fixstring(m, ATA_ID_PROD_LEN, bswap);
+ ide_fixstring((char *)&id[ATA_ID_FW_REV], ATA_ID_FW_REV_LEN, bswap);
+ ide_fixstring((char *)&id[ATA_ID_SERNO], ATA_ID_SERNO_LEN, bswap);
/* we depend on this a lot! */
- id->model[sizeof(id->model)-1] = '\0';
+ m[ATA_ID_PROD_LEN - 1] = '\0';
- if (strstr(id->model, "E X A B Y T E N E S T"))
+ if (strstr(m, "E X A B Y T E N E S T"))
goto err_misc;
- printk(KERN_INFO "%s: %s, ", drive->name, id->model);
+ 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
*/
- if (cmd == WIN_PIDENTIFY) {
- u8 type = (id->config >> 8) & 0x1f;
+ if (cmd == ATA_CMD_ID_ATAPI) {
+ u8 type = (id[ATA_ID_CONFIG] >> 8) & 0x1f;
printk(KERN_CONT "ATAPI ");
switch (type) {
case ide_floppy:
- if (!strstr(id->model, "CD-ROM")) {
- if (!strstr(id->model, "oppy") &&
- !strstr(id->model, "poyp") &&
- !strstr(id->model, "ZIP"))
+ if (!strstr(m, "CD-ROM")) {
+ if (!strstr(m, "oppy") &&
+ !strstr(m, "poyp") &&
+ !strstr(m, "ZIP"))
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(id->model, "CD-ROM") &&
- strstr(id->model, "ZIP")) {
+ if (!strstr(m, "CD-ROM") && strstr(m, "ZIP")) {
printk(KERN_CONT "FLOPPY");
type = ide_floppy;
break;
@@ -200,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);
@@ -210,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;
}
@@ -217,24 +217,24 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
* Not an ATAPI device: looks like a "regular" hard disk
*/
- /*
- * 0x848a = CompactFlash device
- * These are *not* removable in Linux definition of the term
- */
+ is_cfa = ata_id_is_cfa(id);
- if ((id->config != 0x848a) && (id->config & (1<<7)))
- drive->removable = 1;
+ /* CF devices are *not* removable in Linux definition of the term */
+ if (is_cfa == 0 && (id[ATA_ID_CONFIG] & (1 << 7)))
+ drive->dev_flags |= IDE_DFLAG_REMOVABLE;
drive->media = ide_disk;
- printk(KERN_CONT "%s DISK drive\n",
- (id->config == 0x848a) ? "CFA" : "ATA");
+ 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;
}
@@ -268,7 +268,7 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
if (io_ports->ctl_addr) {
a = tp_ops->read_altstatus(hwif);
s = tp_ops->read_status(hwif);
- if ((a ^ s) & ~INDEX_STAT)
+ if ((a ^ s) & ~ATA_IDX)
/* ancient Seagate drives, broken interfaces */
printk(KERN_INFO "%s: probing with STATUS(0x%02x) "
"instead of ALTSTATUS(0x%02x)\n",
@@ -281,7 +281,7 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
/* set features register for atapi
* identify command to be sure of reply
*/
- if (cmd == WIN_PIDENTIFY) {
+ if (cmd == ATA_CMD_ID_ATAPI) {
ide_task_t task;
memset(&task, 0, sizeof(task));
@@ -294,24 +294,16 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
/* ask drive for ID */
tp_ops->exec_command(hwif, cmd);
- timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2;
- timeout += jiffies;
- do {
- if (time_after(jiffies, timeout)) {
- /* drive timed-out */
- return 1;
- }
- /* give drive a breather */
- msleep(50);
- s = use_altstatus ? tp_ops->read_altstatus(hwif)
- : tp_ops->read_status(hwif);
- } while (s & BUSY_STAT);
+ timeout = ((cmd == ATA_CMD_ID_ATA) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2;
- /* wait for IRQ and DRQ_STAT */
+ if (ide_busy_sleep(hwif, timeout, use_altstatus))
+ return 1;
+
+ /* wait for IRQ and ATA_DRQ */
msleep(50);
s = tp_ops->read_status(hwif);
- if (OK_STAT(s, DRQ_STAT, BAD_R_STAT)) {
+ if (OK_STAT(s, ATA_DRQ, BAD_R_STAT)) {
unsigned long flags;
/* local CPU only; some systems need this */
@@ -387,19 +379,21 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd)
return retval;
}
-static int ide_busy_sleep(ide_hwif_t *hwif)
+int ide_busy_sleep(ide_hwif_t *hwif, unsigned long timeout, int altstatus)
{
- unsigned long timeout = jiffies + WAIT_WORSTCASE;
u8 stat;
+ timeout += jiffies;
+
do {
- msleep(50);
- stat = hwif->tp_ops->read_status(hwif);
- if ((stat & BUSY_STAT) == 0)
+ msleep(50); /* give drive a breather */
+ stat = altstatus ? hwif->tp_ops->read_altstatus(hwif)
+ : hwif->tp_ops->read_status(hwif);
+ if ((stat & ATA_BUSY) == 0)
return 0;
} while (time_before(jiffies, timeout));
- return 1;
+ return 1; /* drive timed-out */
}
static u8 ide_read_device(ide_drive_t *drive)
@@ -440,17 +434,16 @@ 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 == WIN_IDENTIFY))
- return 4;
- }
#ifdef DEBUG
printk(KERN_INFO "probing for %s: present=%d, media=%d, probetype=%s\n",
- drive->name, drive->present, drive->media,
- (cmd == WIN_IDENTIFY) ? "ATA" : "ATAPI");
+ drive->name, present, drive->media,
+ (cmd == ATA_CMD_ID_ATA) ? "ATA" : "ATAPI");
#endif
/* needed for some systems
@@ -460,11 +453,11 @@ 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 BUSY_STAT to assert & clear */
+ /* allow ATA_BUSY to assert & clear */
msleep(50);
}
/* no i/f present: mmm.. this should be a 4 -ml */
@@ -473,8 +466,8 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
stat = tp_ops->read_status(hwif);
- if (OK_STAT(stat, READY_STAT, BUSY_STAT) ||
- drive->present || cmd == WIN_PIDENTIFY) {
+ if (OK_STAT(stat, ATA_DRDY, ATA_BUSY) ||
+ present || cmd == ATA_CMD_ID_ATAPI) {
/* send cmd and wait */
if ((rc = try_to_identify(drive, cmd))) {
/* failed: try again */
@@ -483,17 +476,17 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
stat = tp_ops->read_status(hwif);
- if (stat == (BUSY_STAT | READY_STAT))
+ if (stat == (ATA_BUSY | ATA_DRDY))
return 4;
- if (rc == 1 && cmd == WIN_PIDENTIFY) {
+ if (rc == 1 && cmd == ATA_CMD_ID_ATAPI) {
printk(KERN_ERR "%s: no response (status = 0x%02x), "
"resetting drive\n", drive->name, stat);
msleep(50);
SELECT_DRIVE(drive);
msleep(50);
- tp_ops->exec_command(hwif, WIN_SRST);
- (void)ide_busy_sleep(hwif);
+ tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET);
+ (void)ide_busy_sleep(hwif, WAIT_WORSTCASE, 0);
rc = try_to_identify(drive, cmd);
}
@@ -507,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);
@@ -526,13 +519,14 @@ static void enable_nest (ide_drive_t *drive)
const struct ide_tp_ops *tp_ops = hwif->tp_ops;
u8 stat;
- printk(KERN_INFO "%s: enabling %s -- ", hwif->name, drive->id->model);
+ printk(KERN_INFO "%s: enabling %s -- ",
+ hwif->name, (char *)&drive->id[ATA_ID_PROD]);
SELECT_DRIVE(drive);
msleep(50);
- tp_ops->exec_command(hwif, EXABYTE_ENABLE_NEST);
+ tp_ops->exec_command(hwif, ATA_EXABYTE_ENABLE_NEST);
- if (ide_busy_sleep(hwif)) {
+ if (ide_busy_sleep(hwif, WAIT_WORSTCASE, 0)) {
printk(KERN_CONT "failed (timeout)\n");
return;
}
@@ -545,12 +539,6 @@ static void enable_nest (ide_drive_t *drive)
printk(KERN_CONT "failed (status = 0x%02x)\n", stat);
else
printk(KERN_CONT "success\n");
-
- /* if !(success||timed-out) */
- if (do_probe(drive, WIN_IDENTIFY) >= 2) {
- /* look for ATAPI device */
- (void) do_probe(drive, WIN_PIDENTIFY);
- }
}
/**
@@ -561,12 +549,14 @@ 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)
{
+ char *m;
+
/*
* In order to keep things simple we have an id
* block for all drives at all times. If the device
@@ -576,31 +566,36 @@ static inline u8 probe_for_drive (ide_drive_t *drive)
* Also note that 0 everywhere means "can't do X"
*/
- drive->id = kzalloc(SECTOR_WORDS *4, GFP_KERNEL);
- drive->id_read = 0;
- if(drive->id == NULL)
- {
+ drive->dev_flags &= ~IDE_DFLAG_ID_READ;
+
+ drive->id = kzalloc(SECTOR_SIZE, GFP_KERNEL);
+ if (drive->id == NULL) {
printk(KERN_ERR "ide: out of memory for id data.\n");
return 0;
}
- strcpy(drive->id->model, "UNKNOWN");
-
+
+ m = (char *)&drive->id[ATA_ID_PROD];
+ 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, WIN_IDENTIFY) >= 2) {
+ if (do_probe(drive, ATA_CMD_ID_ATA) >= 2)
/* look for ATAPI device */
- (void) do_probe(drive, WIN_PIDENTIFY);
- }
- if (!drive->present)
+ (void)do_probe(drive, ATA_CMD_ID_ATAPI);
+
+ if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
/* drive not found */
return 0;
- if (strstr(drive->id->model, "E X A B Y T E N E S T"))
+
+ if (strstr(m, "E X A B Y T E N E S T")) {
enable_nest(drive);
-
+ goto 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,
@@ -610,15 +605,17 @@ static inline u8 probe_for_drive (ide_drive_t *drive)
} 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;
}
@@ -628,7 +625,7 @@ static inline u8 probe_for_drive (ide_drive_t *drive)
ide_disk_init_mult_count(drive);
}
- return drive->present;
+ return !!(drive->dev_flags & IDE_DFLAG_PRESENT);
}
static void hwif_release_dev(struct device *dev)
@@ -719,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);
@@ -740,36 +738,38 @@ out:
/**
* ide_undecoded_slave - look for bad CF adapters
- * @drive1: drive
+ * @dev1: slave device
*
* Analyse the drives on the interface and attempt to decide if we
* have the same drive viewed twice. This occurs with crap CF adapters
* and PCMCIA sometimes.
*/
-void ide_undecoded_slave(ide_drive_t *drive1)
+void ide_undecoded_slave(ide_drive_t *dev1)
{
- ide_drive_t *drive0 = &drive1->hwif->drives[0];
+ ide_drive_t *dev0 = &dev1->hwif->drives[0];
- if ((drive1->dn & 1) == 0 || drive0->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 */
- if (strcmp(drive0->id->model, drive1->id->model))
+ if (strcmp((char *)&dev0->id[ATA_ID_PROD],
+ (char *)&dev1->id[ATA_ID_PROD]))
return;
/* Serial numbers do not match */
- if (strncmp(drive0->id->serial_no, drive1->id->serial_no, 20))
+ if (strncmp((char *)&dev0->id[ATA_ID_SERNO],
+ (char *)&dev1->id[ATA_ID_SERNO], ATA_ID_SERNO_LEN))
return;
/* No serial number, thankfully very rare for CF */
- if (drive0->id->serial_no[0] == 0)
+ if (*(char *)&dev0->id[ATA_ID_SERNO] == 0)
return;
/* Appears to be an IDE flash adapter with decode bugs */
printk(KERN_WARNING "ide-probe: ignoring undecoded slave\n");
- drive1->present = 0;
+ dev1->dev_flags &= ~IDE_DFLAG_PRESENT;
}
EXPORT_SYMBOL_GPL(ide_undecoded_slave);
@@ -782,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;
/*
@@ -804,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;
}
@@ -830,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);
@@ -850,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->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.
*
@@ -882,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
@@ -961,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];
@@ -1037,14 +1046,9 @@ static int init_irq (ide_hwif_t *hwif)
ide_hwgroup_t *hwgroup;
ide_hwif_t *match = NULL;
-
- BUG_ON(in_interrupt());
- BUG_ON(irqs_disabled());
- BUG_ON(hwif == NULL);
-
mutex_lock(&ide_cfg_mtx);
hwif->hwgroup = NULL;
-#if MAX_HWIFS > 1
+
/*
* Group up with any other hwifs that share our irq(s).
*/
@@ -1069,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
*/
@@ -1116,7 +1120,8 @@ static int init_irq (ide_hwif_t *hwif)
sa = IRQF_SHARED;
#endif /* __mc68000__ */
- if (IDE_CHIPSET_IS_PCI(hwif->chipset))
+ if (hwif->chipset == ide_pci || hwif->chipset == ide_cmd646 ||
+ hwif->chipset == ide_ali14xx)
sa = IRQF_SHARED;
if (io_ports->ctl_addr)
@@ -1167,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");
@@ -1188,7 +1194,7 @@ static struct kobject *exact_match(dev_t dev, int *part, void *data)
{
struct gendisk *p = data;
*part &= (1 << PARTN_BITS) - 1;
- return &p->dev.kobj;
+ return &disk_to_dev(p)->kobj;
}
static int exact_lock(dev_t dev, void *data)
@@ -1219,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;
@@ -1262,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);
@@ -1341,11 +1347,9 @@ 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;
- ide_add_generic_settings(drive);
-
snprintf(dev->bus_id, BUS_ID_SIZE, "%u.%u", hwif->index, i);
dev->parent = &hwif->gendev;
dev->bus = &ide_bus_type;
@@ -1367,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);
@@ -1492,7 +1498,7 @@ static struct device_attribute *ide_port_attrs[] = {
static int ide_sysfs_register_port(ide_hwif_t *hwif)
{
- int i, rc;
+ int i, uninitialized_var(rc);
for (i = 0; ide_port_attrs[i]; i++) {
rc = device_create_file(hwif->portdev, ide_port_attrs[i]);
@@ -1529,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);
@@ -1557,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;
@@ -1567,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;
@@ -1602,23 +1602,13 @@ struct ide_host *ide_host_alloc_all(const struct ide_port_info *d,
if (hws[0])
host->dev[0] = hws[0]->dev;
- if (d)
+ if (d) {
+ host->init_chipset = d->init_chipset;
host->host_flags = d->host_flags;
+ }
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,
@@ -1627,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) {
@@ -1640,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)
@@ -1672,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)
@@ -1685,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);
@@ -1696,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)
@@ -1709,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)
@@ -1754,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)
@@ -1772,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]);
}