diff options
| author | Gabe Black <gabeblack@chromium.org> | 2012-10-29 05:23:57 +0000 | 
|---|---|---|
| committer | Tom Rini <trini@ti.com> | 2012-11-02 15:20:42 -0700 | 
| commit | b4c5bbce49a081f5d05837ba13ee76afeff72d91 (patch) | |
| tree | 548f8649623034a8de08f3eaba5eef2d98534f5a /common/cmd_scsi.c | |
| parent | 5a2b77f47daa5c87ef45a1c71c72cbc16ede77f8 (diff) | |
| download | olio-uboot-2014.01-b4c5bbce49a081f5d05837ba13ee76afeff72d91.tar.xz olio-uboot-2014.01-b4c5bbce49a081f5d05837ba13ee76afeff72d91.zip | |
ahci: Support 64-bit LBA option when reading capacity
Capacity needs to allow for a 64-bit value.
Signed-off-by: Gabe Black <gabeblack@google.com>
Signed-off-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'common/cmd_scsi.c')
| -rw-r--r-- | common/cmd_scsi.c | 92 | 
1 files changed, 66 insertions, 26 deletions
| diff --git a/common/cmd_scsi.c b/common/cmd_scsi.c index 9bd8ec9ec..266bfa690 100644 --- a/common/cmd_scsi.c +++ b/common/cmd_scsi.c @@ -72,7 +72,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);  static void scsi_setup_write_ext(ccb *pccb, unsigned long start, @@ -81,6 +80,8 @@ 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);  static ulong scsi_read(int device, ulong blknr, lbaint_t blkcnt, void *buffer);  static ulong scsi_write(int device, ulong blknr,  			lbaint_t blkcnt, const void *buffer); @@ -93,7 +94,8 @@ static ulong scsi_write(int device, ulong blknr,  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) { @@ -158,16 +160,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; @@ -514,6 +510,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 @@ -530,23 +587,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; |