[OpenBIOS] [commit] r1047 - trunk/openbios-devel/drivers
repository service
svn at openbios.org
Sat Aug 20 14:10:08 CEST 2011
Author: blueswirl
Date: Sat Aug 20 14:10:07 2011
New Revision: 1047
URL: http://tracker.coreboot.org/trac/openbios/changeset/1047
Log:
ESP: clear Unit Attention condition after reset
In recent QEMU, SCSI devices are in Unit Attention condition after
reset and this made Read Capacity command fail.
Fix by sending a Test Unit Ready command to the devices first.
Also avoid division by zero if block size is 0 when
Read Capacity fails.
Thanks to Paolo Bonzini for analysis.
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
Modified:
trunk/openbios-devel/drivers/esp.c
Modified: trunk/openbios-devel/drivers/esp.c
==============================================================================
--- trunk/openbios-devel/drivers/esp.c Mon Aug 8 14:33:10 2011 (r1046)
+++ trunk/openbios-devel/drivers/esp.c Sat Aug 20 14:10:07 2011 (r1047)
@@ -108,11 +108,17 @@
DPRINTF("do_command: id %d, cmd[0] 0x%x, status 0x%x\n", sd->id, esp->buffer[0], status);
- // Target didn't want all command data or went to status phase
- // instead of data phase?
- if ((status & ESP_STAT_TCNT) != ESP_STAT_TCNT
- || (status & ESP_STAT_PMASK) == ESP_STATP)
+ /* Target didn't want all command data? */
+ if ((status & ESP_STAT_TCNT) != ESP_STAT_TCNT) {
return status;
+ }
+ if (replylen == 0) {
+ return 0;
+ }
+ /* Target went to status phase instead of data phase? */
+ if ((status & ESP_STAT_PMASK) == ESP_STATP) {
+ return status;
+ }
// Get reply
// Set DMA address
@@ -176,12 +182,31 @@
if (do_command(esp, sd, 11, 8)) {
sd->sectors = 0;
sd->bs = 0;
-
+ DPRINTF("read_capacity id %d failed\n", sd->id);
return 0;
}
sd->bs = (esp->buffer[4] << 24) | (esp->buffer[5] << 16) | (esp->buffer[6] << 8) | esp->buffer[7];
sd->sectors = ((esp->buffer[0] << 24) | (esp->buffer[1] << 16) | (esp->buffer[2] << 8) | esp->buffer[3]) * (sd->bs / 512);
+ DPRINTF("read_capacity id %d bs %d sectors %d\n", sd->id, sd->bs,
+ sd->sectors);
+ return 1;
+}
+
+static unsigned int
+test_unit_ready(esp_private_t *esp, sd_private_t *sd)
+{
+ /* Setup command = Test Unit Ready */
+ memset(esp->buffer, 0, 6);
+ esp->buffer[0] = 0x80;
+ esp->buffer[1] = TEST_UNIT_READY;
+
+ if (do_command(esp, sd, 6, 0)) {
+ DPRINTF("test_unit_ready id %d failed\n", sd->id);
+ return 0;
+ }
+
+ DPRINTF("test_unit_ready id %d success\n", sd->id);
return 1;
}
@@ -234,6 +259,10 @@
DPRINTF("ob_sd_read_blocks id %d %lx block=%d n=%d\n", (*sd)->id, (unsigned long)dest, blk, n );
+ if ((*sd)->bs == 0) {
+ PUSH(0);
+ return;
+ }
spb = (*sd)->bs / 512;
while (n) {
sect_offset = blk / spb;
@@ -438,6 +467,7 @@
int id, diskcount = 0, cdcount = 0, *counter_ptr;
char nodebuff[256], aliasbuff[256];
esp_private_t *esp;
+ unsigned int i;
DPRINTF("Initializing SCSI...");
@@ -476,8 +506,21 @@
for (id = 0; id < 8; id++) {
esp->sd[id].id = id;
- if (!inquiry(esp, &esp->sd[id]))
+ if (!inquiry(esp, &esp->sd[id])) {
+ DPRINTF("Unit %d not present\n", id);
continue;
+ }
+ /* Clear Unit Attention condition from reset */
+ for (i = 0; i < 5; i++) {
+ if (test_unit_ready(esp, &esp->sd[id])) {
+ break;
+ }
+ }
+ if (i == 5) {
+ DPRINTF("Unit %d present but won't become ready\n", id);
+ continue;
+ }
+ DPRINTF("Unit %d present\n", id);
read_capacity(esp, &esp->sd[id]);
#ifdef CONFIG_DEBUG_ESP
More information about the OpenBIOS
mailing list