Patrick Georgi (patrick@georgi-clan.de) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/1087
-gerrit
commit 4193fd9b4921a78831f9346b02cbb004b69b16e3 Author: Nico Huber nico.huber@secunet.com Date: Fri May 25 11:34:08 2012 +0200
Make booting from ATAPI drives more resilient.
This fixes a semantic error, where the ATAPI driver requested sense from the drive instead of retrying a failed command (i.e. the actual command had been overwritten). The count of retries and delays are also adapted to behave more like the Linux kernel driver.
Change-Id: Iabf20120c841bbc277af4efa48c6594804f60205 Signed-off-by: Patrick Georgi patrick.georgi@secunet.com --- drivers/ide_new.c | 90 +++++++++++++++++++++++------------------------------ drivers/ide_new.h | 6 ++-- 2 files changed, 42 insertions(+), 54 deletions(-)
diff --git a/drivers/ide_new.c b/drivers/ide_new.c index 658f177..cc1fb83 100644 --- a/drivers/ide_new.c +++ b/drivers/ide_new.c @@ -192,8 +192,10 @@ ob_ide_error(struct ide_drive *drive, unsigned char stat, char *msg) for (i = 0; i < sizeof(cmd->cdb); i++) debug("%02x ", cmd->cdb[i]); } - if (cmd->sense_valid) - debug(", sense: %02x/%02x/%02x", cmd->sense.sense_key, cmd->sense.asc, cmd->sense.ascq); + if (cmd->sense) + debug(", sense: %02x/%02x/%02x", + cmd->sense->sense_key, + cmd->sense->asc, cmd->sense->ascq); else debug(", no sense"); debug("\n"); @@ -535,7 +537,7 @@ ob_ide_pio_packet(struct ide_drive *drive, struct atapi_command *cmd) static int ob_ide_atapi_packet(struct ide_drive *drive, struct atapi_command *cmd) { - int retries = 5, ret; + int retries = 10, ret;
if (drive->type != ide_type_atapi) return 1; @@ -550,33 +552,35 @@ ob_ide_atapi_packet(struct ide_drive *drive, struct atapi_command *cmd) if (!ret) break;
- /* - * request sense failed, bummer - */ - if (cmd->cdb[0] == ATAPI_REQ_SENSE) - break; - if (ob_ide_atapi_request_sense(drive)) break;
/* - * we know sense is valid. retry if the drive isn't ready, - * otherwise don't bother. - */ - if (cmd->sense.sense_key != ATAPI_SENSE_NOT_READY) - break; - /* - * ... except 'medium not present' + * We know sense is valid. Retry if the unit attention + * condition has been set (media change / reset) or the + * drive isn't ready, otherwise don't bother. */ - if (cmd->sense.asc == 0x3a) { - /* 'medium not present' is not an error */ - ret = 0; - /* force reevaluation */ - drive->channel->present = 0; + if (cmd->sense->sense_key == ATAPI_SENSE_UNIT_ATTENTION) { + /* Just retry. */ + } else if (cmd->sense->sense_key == ATAPI_SENSE_NOT_READY) { + if (cmd->sense->asc == 0x04) { + /* The drive is becoming ready, give it some + * more time. */ + mdelay(3000); + } else if (cmd->sense->asc == 0x3a) { + /* + * 'medium not present' is not an error, + * but we have to report nevertheless + */ + ret = RETURN_NO_MEDIUM; + /* force reevaluation */ + drive->channel->present = 0; + /* Don't retry in this case. */ + break; + } + } else { break; } - - mdelay(1000); } while (retries--);
if (ret) @@ -588,26 +592,25 @@ ob_ide_atapi_packet(struct ide_drive *drive, struct atapi_command *cmd) static int ob_ide_atapi_request_sense(struct ide_drive *drive) { - struct atapi_command *cmd = &drive->channel->atapi_cmd; - unsigned char old_cdb; + struct atapi_command *orig_cmd = &drive->channel->atapi_cmd; + struct atapi_command cmd;
+ memset(&cmd, 0, sizeof(cmd)); + + cmd.cdb[0] = ATAPI_REQ_SENSE; + cmd.cdb[4] = 18; + cmd.buffer = (unsigned char *)&drive->channel->atapi_sense; + cmd.buflen = 18; + cmd.data_direction = atapi_ddir_read; /* * save old cdb for debug error */ - old_cdb = cmd->cdb[0]; - - memset(cmd, 0, sizeof(*cmd)); - cmd->cdb[0] = ATAPI_REQ_SENSE; - cmd->cdb[4] = 18; - cmd->buffer = (unsigned char *) &cmd->sense; - cmd->buflen = 18; - cmd->data_direction = atapi_ddir_read; - cmd->old_cdb = old_cdb; + cmd.old_cdb = orig_cmd->cdb[0];
- if (ob_ide_atapi_packet(drive, cmd)) + if (ob_ide_pio_packet(drive, &cmd)) return 1;
- cmd->sense_valid = 1; + orig_cmd->sense = &drive->channel->atapi_sense; return 0; }
@@ -621,21 +624,6 @@ ob_ide_atapi_drive_ready(struct ide_drive *drive) struct atapi_capacity cap; int i;
- /* - * Test Unit Ready is like a ping - * But wait a bit, as the drive might take a while - */ - i = 30; - while (i-- != 0) { - memset(cmd, 0, sizeof(*cmd)); - cmd->cdb[0] = ATAPI_TUR; - - if (!ob_ide_atapi_packet(drive,cmd)) break; - - /* Give the drive some time to breathe */ - mdelay(500); - } - memset(cmd, 0, sizeof(*cmd)); cmd->cdb[0] = ATAPI_TUR;
diff --git a/drivers/ide_new.h b/drivers/ide_new.h index f667e41..742cc42 100644 --- a/drivers/ide_new.h +++ b/drivers/ide_new.h @@ -77,6 +77,7 @@ * atapi sense keys */ #define ATAPI_SENSE_NOT_READY 0x02 +#define ATAPI_SENSE_UNIT_ATTENTION 0x06
/* * supported device types @@ -142,8 +143,7 @@ struct atapi_command { unsigned char data_direction;
unsigned char stat; - unsigned char sense_valid; - struct request_sense sense; + struct request_sense *sense; unsigned char old_cdb; };
@@ -199,7 +199,7 @@ struct ide_channel { */ struct ata_command ata_cmd; struct atapi_command atapi_cmd; - + struct request_sense atapi_sense; };
enum {