Author: stepan Date: 2007-10-04 08:12:32 +0200 (Thu, 04 Oct 2007) New Revision: 38
Modified: trunk/filo-0.5/drivers/ide.c Log: This code is originally from Nikolay Petukhov nikolaypetukhov@gmail.com with one minor change from me. It enables the option of having only slaves on ide, such as the CF found on the msm800sev.
This code has been tested on the msm800sev with one master, master and slave, and only slave and works. I'd like to see some other tests before we commit. IDE is touchy.
Signed-off-by: Ronald G. Minnich rminnich@gmail.com Acked-by: Stefan Reinauer stepan@coresystems.de
Modified: trunk/filo-0.5/drivers/ide.c =================================================================== --- trunk/filo-0.5/drivers/ide.c 2007-10-02 19:30:23 UTC (rev 37) +++ trunk/filo-0.5/drivers/ide.c 2007-10-04 06:12:32 UTC (rev 38) @@ -280,8 +280,29 @@ inb(IDE_REG_STATUS(ctrl)), inb(IDE_REG_ERROR(ctrl))); }
+int select_drive(struct controller *ctrl, int drive) +{ + int device, status; + + outb(0xa0 | (drive << 4), IDE_REG_DEVICE(ctrl)); + status = inb(IDE_REG_STATUS(ctrl)); + + mdelay(10); + + device = inb(IDE_REG_DEVICE(ctrl)); + status = inb(IDE_REG_STATUS(ctrl)); + + if (device == (0xa0 | (drive<<4))) + return 1; + else + return 0; +} + static int ide_software_reset(struct controller *ctrl) { + int master_exist = select_drive(ctrl, 0); + int slave_exist = select_drive(ctrl, 1); + /* Wait a little bit in case this is immediately after * hardware reset. */ @@ -303,7 +324,10 @@ IDE_REG_DEVICE_CONTROL(ctrl)); /* If BSY bit is not asserted within 400ns, no device there */ if (await_ide(bsy, ctrl, currticks() + IDE_RESET_PULSE) < 0) { - return -1; + if (slave_exist) + printf ("reset failed, but slave maybe exist\n"); + else + return -1; } outb(IDE_CTRL_HD15 | IDE_CTRL_NIEN, IDE_REG_DEVICE_CONTROL(ctrl)); mdelay(2); @@ -863,6 +887,7 @@ * is quite rare. * */ + debug("init_controller: drive %d\n", drive); #if !BSY_SET_DURING_SPINUP if (await_ide(timeout, ctrl, currticks() + IDE_TIMEOUT) < 0) { return -1; @@ -886,21 +911,44 @@ */
/* Now initialize the individual drives */ - info = &harddisk_info[drive]; - init_drive(info, ctrl, 0, drive, buffer, IDE_CMD_IDENTIFY_DEVICE); + int master_drive = drive & ~1; + info = &harddisk_info[master_drive]; + + /* master */ + init_drive(info, ctrl, 0, master_drive, buffer, IDE_CMD_IDENTIFY_DEVICE); + if (!info->drive_exists) - init_drive(info, ctrl, 0, drive, buffer, + init_drive(info, ctrl, 0, master_drive, buffer, IDE_CMD_IDENTIFY_PACKET_DEVICE); + + debug("MASTER CHECK: master %s\n", + info->drive_exists ? "yes" : "no"); + /* slave and master */ if (info->drive_exists && !info->slave_absent) { - drive++; + master_drive++; info++; - init_drive(info, ctrl, 1, drive, buffer, + init_drive(info, ctrl, 1, master_drive, buffer, IDE_CMD_IDENTIFY_DEVICE); if (!info->drive_exists) - init_drive(info, ctrl, 1, drive, buffer, + init_drive(info, ctrl, 1, master_drive, buffer, IDE_CMD_IDENTIFY_PACKET_DEVICE); }
+ + /* slave */ + debug("/*slave */ -- drive is %d\n", drive); + info = &harddisk_info[drive]; + if (!info->drive_exists) { + debug("NO MASTER -- check slave!\n"); + init_drive(info, ctrl, 1, drive, buffer, IDE_CMD_IDENTIFY_DEVICE); + + if (!info->drive_exists) + init_drive(info, ctrl, 1, drive, buffer, + IDE_CMD_IDENTIFY_PACKET_DEVICE); + debug("SLAVE ONLY CHECK: slave %s\n", + info->drive_exists ? "yes" : "no"); + } + return 0; }
@@ -1123,7 +1171,7 @@ printf("IDE channel %d not found\n", ctrl_index); return -1; } - if (init_controller(ctrl, drive & ~1, ide_buffer) != 0) { + if (init_controller(ctrl, drive, ide_buffer) != 0) { printf("No drive detected on IDE channel %d\n", ctrl_index); return -1;