summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabe Black <gabeblack@chromium.org>2012-03-13 16:03:33 -0700
committerGerrit <chrome-bot@google.com>2012-03-13 19:21:27 -0700
commit1bd4fbf1cd120275c3f05425ac7273e7d0cb4a0a (patch)
treed74bdabf87a1b497adc2f67387ff0f48bb3764ca
parentcf2aaf1a7d548fa575f3c6a8df0e16b918472d28 (diff)
gen: Make the SCSI command aware of READ CAPACITY (16) and how to use it
The generic SCSI code in U-Boot was only aware of the READ CAPACITY (10) SCSI command which can detect the size of disks up to 2TB in size. If that size is exceeded, it should then try the READ CAPACITY (16) command which returns a 64 bit block count value. BUG=chrome-os-partner:8180 TEST=In conjunction with the next change, built and booted into ChromeOS on the Emerald Lake 2 CRB with a 250 GB SSD. Did the same but forced the READ CAPACITY (10) command to saturate and the code to fall back to READ CAPACITY (16). Note that this code has not be tested with a real SCSI disk, just the AHCI code pretending to be a SCSI disk as it historically has. Change-Id: Ia0ee3fa1264649f25065658d5d368101d39ce614 Signed-off-by: Gabe Black <gabeblack@google.com> Reviewed-on: https://gerrit.chromium.org/gerrit/18060 Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r--common/cmd_scsi.c93
-rw-r--r--include/scsi.h2
2 files changed, 69 insertions, 26 deletions
diff --git a/common/cmd_scsi.c b/common/cmd_scsi.c
index 5ecbad040f..3fe48d6d6d 100644
--- a/common/cmd_scsi.c
+++ b/common/cmd_scsi.c
@@ -75,7 +75,6 @@ static block_dev_desc_t scsi_dev_desc[CONFIG_SYS_SCSI_MAX_DEVICE];
* forward declerations of some Setup Routines
*/
void scsi_setup_test_unit_ready(ccb * pccb);
-void scsi_setup_read_capacity(ccb * pccb);
void scsi_setup_read6(ccb * pccb, unsigned long start, unsigned short blocks);
void scsi_setup_read_ext(ccb * pccb, unsigned long start, unsigned short blocks);
void scsi_setup_write_ext(ccb *pccb, unsigned long start,
@@ -84,6 +83,9 @@ void scsi_setup_inquiry(ccb * pccb);
void scsi_ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len);
+static int scsi_read_capacity(ccb *pccb, lbaint_t *capacity,
+ unsigned long *blksz);
+
ulong scsi_read(int device, ulong blknr, lbaint_t blkcnt, void *buffer);
ulong scsi_write(int device, ulong blknr, lbaint_t blkcnt, const void *buffer);
@@ -95,7 +97,8 @@ ulong scsi_write(int device, ulong blknr, lbaint_t blkcnt, const void *buffer);
void scsi_scan(int mode)
{
unsigned char i,perq,modi,lun;
- unsigned long capacity,blksz;
+ lbaint_t capacity;
+ unsigned long blksz;
ccb* pccb=(ccb *)&tempccb;
if(mode==1) {
@@ -160,16 +163,10 @@ void scsi_scan(int mode)
scsi_print_error(pccb);
continue;
}
- pccb->datalen=8;
- scsi_setup_read_capacity(pccb);
- if(scsi_exec(pccb)!=TRUE) {
+ if (scsi_read_capacity(pccb, &capacity, &blksz)) {
scsi_print_error(pccb);
continue;
}
- capacity=((unsigned long)tempbuff[0]<<24)|((unsigned long)tempbuff[1]<<16)|
- ((unsigned long)tempbuff[2]<<8)|((unsigned long)tempbuff[3]);
- blksz=((unsigned long)tempbuff[4]<<24)|((unsigned long)tempbuff[5]<<16)|
- ((unsigned long)tempbuff[6]<<8)|((unsigned long)tempbuff[7]);
scsi_dev_desc[scsi_max_devs].lba=capacity;
scsi_dev_desc[scsi_max_devs].blksz=blksz;
scsi_dev_desc[scsi_max_devs].type=perq;
@@ -635,6 +632,67 @@ void scsi_trim_trail (unsigned char *str, unsigned int len)
}
}
+int scsi_read_capacity(ccb *pccb, lbaint_t *capacity, unsigned long *blksz)
+{
+ *capacity = 0;
+
+ memset(pccb->cmd, 0, sizeof(pccb->cmd));
+ pccb->cmd[0] = SCSI_RD_CAPAC10;
+ pccb->cmd[1] = pccb->lun << 5;
+ pccb->cmdlen = 10;
+ pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
+
+ pccb->datalen = 8;
+ if (scsi_exec(pccb) != TRUE)
+ return 1;
+
+ *capacity = ((lbaint_t)pccb->pdata[0] << 24) |
+ ((lbaint_t)pccb->pdata[1] << 16) |
+ ((lbaint_t)pccb->pdata[2] << 8) |
+ ((lbaint_t)pccb->pdata[3]);
+
+ if (*capacity != 0xffffffff) {
+ /* Read capacity (10) was sufficient for this drive. */
+ *blksz = ((unsigned long)pccb->pdata[4] << 24) |
+ ((unsigned long)pccb->pdata[5] << 16) |
+ ((unsigned long)pccb->pdata[6] << 8) |
+ ((unsigned long)pccb->pdata[7]);
+ return 0;
+ }
+
+ /* Read capacity (10) was insufficient. Use read capacity (16). */
+
+ memset(pccb->cmd, 0, sizeof(pccb->cmd));
+ pccb->cmd[0] = SCSI_RD_CAPAC16;
+ pccb->cmd[1] = 0x10;
+ pccb->cmdlen = 16;
+ pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
+
+ pccb->datalen = 16;
+ if (scsi_exec(pccb) != TRUE)
+ return 1;
+
+ *capacity = ((uint64_t)pccb->pdata[0] << 56) |
+ ((uint64_t)pccb->pdata[1] << 48) |
+ ((uint64_t)pccb->pdata[2] << 40) |
+ ((uint64_t)pccb->pdata[3] << 32) |
+ ((uint64_t)pccb->pdata[4] << 24) |
+ ((uint64_t)pccb->pdata[5] << 16) |
+ ((uint64_t)pccb->pdata[6] << 8) |
+ ((uint64_t)pccb->pdata[7]);
+
+ *blksz = ((uint64_t)pccb->pdata[8] << 56) |
+ ((uint64_t)pccb->pdata[9] << 48) |
+ ((uint64_t)pccb->pdata[10] << 40) |
+ ((uint64_t)pccb->pdata[11] << 32) |
+ ((uint64_t)pccb->pdata[12] << 24) |
+ ((uint64_t)pccb->pdata[13] << 16) |
+ ((uint64_t)pccb->pdata[14] << 8) |
+ ((uint64_t)pccb->pdata[15]);
+
+ return 0;
+}
+
/************************************************************************************
* Some setup (fill-in) routines
@@ -651,23 +709,6 @@ void scsi_setup_test_unit_ready(ccb * pccb)
pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */
}
-void scsi_setup_read_capacity(ccb * pccb)
-{
- pccb->cmd[0]=SCSI_RD_CAPAC;
- pccb->cmd[1]=pccb->lun<<5;
- pccb->cmd[2]=0;
- pccb->cmd[3]=0;
- pccb->cmd[4]=0;
- pccb->cmd[5]=0;
- pccb->cmd[6]=0;
- pccb->cmd[7]=0;
- pccb->cmd[8]=0;
- pccb->cmd[9]=0;
- pccb->cmdlen=10;
- pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */
-
-}
-
void scsi_setup_read_ext(ccb * pccb, unsigned long start, unsigned short blocks)
{
pccb->cmd[0]=SCSI_READ10;
diff --git a/include/scsi.h b/include/scsi.h
index b00b517c4b..cf7c7bc78a 100644
--- a/include/scsi.h
+++ b/include/scsi.h
@@ -148,6 +148,8 @@ typedef struct SCSI_cmd_block{
#define SCSI_READ6 0x08 /* Read 6-byte (MANDATORY) */
#define SCSI_READ10 0x28 /* Read 10-byte (MANDATORY) */
#define SCSI_RD_CAPAC 0x25 /* Read Capacity (MANDATORY) */
+#define SCSI_RD_CAPAC10 SCSI_RD_CAPAC /* Read Capacity (10) */
+#define SCSI_RD_CAPAC16 0x9e /* Read Capacity (16) */
#define SCSI_RD_DEFECT 0x37 /* Read Defect Data (O) */
#define SCSI_READ_LONG 0x3E /* Read Long (O) */
#define SCSI_REASS_BLK 0x07 /* Reassign Blocks (O) */