NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: kern/42122: larger than 2TB drives can't be properly found at boot
The following reply was made to PR kern/42122; it has been noted by GNATS.
From: David Holland <dholland-bugs%netbsd.org@localhost>
To: gnats-bugs%netbsd.org@localhost
Cc:
Subject: Re: kern/42122: larger than 2TB drives can't be properly found at
boot
Date: Thu, 28 Jan 2010 05:18:08 +0000
(wasn't sent to gnats-bugs)
------
From: Michael van Elst <mlelstv%serpens.de@localhost>
To: gnats%netbsd.org@localhost
Subject: Re: kern/42122: larger than 2TB drives can't be properly found at
boot
Date: Mon, 25 Jan 2010 13:54:06 +0100
The Array should return -1 with read_capacity_10 to signal
that read_capacity_16 is required. Apparently this is not
implemented right. A workaround is to try the read_capacity_16
first and retry with read_capacity_10 if the command wasn't
accepted (Invalid Command).
Does this patch help?
Index: sd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/sd.c,v
retrieving revision 1.290
diff -u -r1.290 sd.c
--- sd.c 21 Oct 2009 21:12:05 -0000 1.290
+++ sd.c 25 Jan 2010 11:26:14 -0000
@@ -1679,9 +1679,7 @@
struct scsipi_read_capacity_16_data data16;
} *datap;
uint64_t rv;
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.cmd.opcode = READ_CAPACITY_10;
+ int error;
/*
* Don't allocate data buffer on stack;
@@ -1693,43 +1691,44 @@
if (datap == NULL)
return 0;
- /*
- * If the command works, interpret the result as a 4 byte
- * number of blocks
- */
rv = 0;
- memset(datap, 0, sizeof(datap->data));
- if (scsipi_command(periph, (void *)&cmd.cmd, sizeof(cmd.cmd),
- (void *)datap, sizeof(datap->data), SCSIPIRETRIES, 20000, NULL,
- flags | XS_CTL_DATA_IN | XS_CTL_SILENT) != 0)
- goto out;
-
- if (_4btol(datap->data.addr) != 0xffffffff) {
- *blksize = _4btol(datap->data.length);
- rv = _4btol(datap->data.addr) + 1;
- goto out;
- }
/*
- * Device is larger than can be reflected by READ CAPACITY (10).
- * Try READ CAPACITY (16).
+ * Try READ CAPACITY (16) first, some disks don't return
+ * a correct overflow with READ CAPACITY (10).
*/
-
memset(&cmd, 0, sizeof(cmd));
cmd.cmd16.opcode = READ_CAPACITY_16;
cmd.cmd16.byte2 = SRC16_SERVICE_ACTION;
_lto4b(sizeof(datap->data16), cmd.cmd16.len);
memset(datap, 0, sizeof(datap->data16));
- if (scsipi_command(periph, (void *)&cmd.cmd16, sizeof(cmd.cmd16),
+ error = scsipi_command(periph, (void *)&cmd.cmd16, sizeof(cmd.cmd16),
(void *)datap, sizeof(datap->data16), SCSIPIRETRIES, 20000, NULL,
- flags | XS_CTL_DATA_IN | XS_CTL_SILENT) != 0)
- goto out;
+ flags | XS_CTL_DATA_IN | XS_CTL_SILENT);
- *blksize = _4btol(datap->data16.length);
- rv = _8btol(datap->data16.addr) + 1;
+ if (error == 0) {
+ *blksize = _4btol(datap->data16.length);
+ rv = _8btol(datap->data16.addr) + 1;
+ } else if (error == EINVAL) {
+ /*
+ * Fall back to READ CAPACITY (10)
+ */
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.cmd.opcode = READ_CAPACITY_10;
+
+ memset(datap, 0, sizeof(datap->data));
+ error = scsipi_command(periph, (void *)&cmd.cmd,
sizeof(cmd.cmd),
+ (void *)datap, sizeof(datap->data), SCSIPIRETRIES, 20000,
NULL,
+ flags | XS_CTL_DATA_IN | XS_CTL_SILENT);
+ if (error == 0) {
+ if (_4btol(datap->data.addr) != 0xffffffff) {
+ *blksize = _4btol(datap->data.length);
+ rv = _4btol(datap->data.addr) + 1;
+ }
+ }
+ }
- out:
free(datap, M_TEMP);
return rv;
}
--
Michael van Elst
Internet: mlelstv%serpens.de@localhost
"A potential Snark may lurk in every tree."
Home |
Main Index |
Thread Index |
Old Index