mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-10 23:24:38 +00:00
usb: Add support for multiple-LUN mass storage devices
This patch changes `usb_stor_scan' to scan all the LUNs of each mass storage device. It also fixes the various commands to correctly set the LUN field. Notably, it allows each LUN of GuruPlug's microSD card reader to be accessed. Signed-off-by: Ludovic Courtès <ludo@gnu.org> Acked-by: Prafulla Wadaskar <prafulla@marvell.com>
This commit is contained in:
parent
98fae9707f
commit
99e9ed1f49
1 changed files with 35 additions and 4 deletions
|
@ -204,6 +204,22 @@ int usb_stor_info(void)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned int usb_get_max_lun(struct us_data *us)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
unsigned char result;
|
||||||
|
len = usb_control_msg(us->pusb_dev,
|
||||||
|
usb_rcvctrlpipe(us->pusb_dev, 0),
|
||||||
|
US_BBB_GET_MAX_LUN,
|
||||||
|
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
|
||||||
|
0, us->ifnum,
|
||||||
|
&result, sizeof(result),
|
||||||
|
USB_CNTL_TIMEOUT * 5);
|
||||||
|
USB_STOR_PRINTF("Get Max LUN -> len = %i, result = %i\n",
|
||||||
|
len, (int) result);
|
||||||
|
return (len > 0) ? result : 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* scan the usb and reports device info
|
* scan the usb and reports device info
|
||||||
* to the user if mode = 1
|
* to the user if mode = 1
|
||||||
|
@ -241,12 +257,21 @@ int usb_stor_scan(int mode)
|
||||||
break; /* no more devices avaiable */
|
break; /* no more devices avaiable */
|
||||||
|
|
||||||
if (usb_storage_probe(dev, 0, &usb_stor[usb_max_devs])) {
|
if (usb_storage_probe(dev, 0, &usb_stor[usb_max_devs])) {
|
||||||
/* ok, it is a storage devices
|
/* OK, it's a storage device. Iterate over its LUNs
|
||||||
* get info and fill it in
|
* and populate `usb_dev_desc'.
|
||||||
*/
|
*/
|
||||||
if (usb_stor_get_info(dev, &usb_stor[usb_max_devs],
|
int lun, max_lun, start = usb_max_devs;
|
||||||
&usb_dev_desc[usb_max_devs]) == 1)
|
|
||||||
|
max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
|
||||||
|
for (lun = 0;
|
||||||
|
lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
|
||||||
|
lun++) {
|
||||||
|
usb_dev_desc[usb_max_devs].lun = lun;
|
||||||
|
if (usb_stor_get_info(dev, &usb_stor[start],
|
||||||
|
&usb_dev_desc[usb_max_devs]) == 1) {
|
||||||
usb_max_devs++;
|
usb_max_devs++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* if storage device */
|
/* if storage device */
|
||||||
if (usb_max_devs == USB_MAX_STOR_DEV) {
|
if (usb_max_devs == USB_MAX_STOR_DEV) {
|
||||||
|
@ -882,6 +907,7 @@ static int usb_inquiry(ccb *srb, struct us_data *ss)
|
||||||
do {
|
do {
|
||||||
memset(&srb->cmd[0], 0, 12);
|
memset(&srb->cmd[0], 0, 12);
|
||||||
srb->cmd[0] = SCSI_INQUIRY;
|
srb->cmd[0] = SCSI_INQUIRY;
|
||||||
|
srb->cmd[1] = srb->lun << 5;
|
||||||
srb->cmd[4] = 36;
|
srb->cmd[4] = 36;
|
||||||
srb->datalen = 36;
|
srb->datalen = 36;
|
||||||
srb->cmdlen = 12;
|
srb->cmdlen = 12;
|
||||||
|
@ -905,6 +931,7 @@ static int usb_request_sense(ccb *srb, struct us_data *ss)
|
||||||
ptr = (char *)srb->pdata;
|
ptr = (char *)srb->pdata;
|
||||||
memset(&srb->cmd[0], 0, 12);
|
memset(&srb->cmd[0], 0, 12);
|
||||||
srb->cmd[0] = SCSI_REQ_SENSE;
|
srb->cmd[0] = SCSI_REQ_SENSE;
|
||||||
|
srb->cmd[1] = srb->lun << 5;
|
||||||
srb->cmd[4] = 18;
|
srb->cmd[4] = 18;
|
||||||
srb->datalen = 18;
|
srb->datalen = 18;
|
||||||
srb->pdata = &srb->sense_buf[0];
|
srb->pdata = &srb->sense_buf[0];
|
||||||
|
@ -924,6 +951,7 @@ static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
|
||||||
do {
|
do {
|
||||||
memset(&srb->cmd[0], 0, 12);
|
memset(&srb->cmd[0], 0, 12);
|
||||||
srb->cmd[0] = SCSI_TST_U_RDY;
|
srb->cmd[0] = SCSI_TST_U_RDY;
|
||||||
|
srb->cmd[1] = srb->lun << 5;
|
||||||
srb->datalen = 0;
|
srb->datalen = 0;
|
||||||
srb->cmdlen = 12;
|
srb->cmdlen = 12;
|
||||||
if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
|
if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
|
||||||
|
@ -943,6 +971,7 @@ static int usb_read_capacity(ccb *srb, struct us_data *ss)
|
||||||
do {
|
do {
|
||||||
memset(&srb->cmd[0], 0, 12);
|
memset(&srb->cmd[0], 0, 12);
|
||||||
srb->cmd[0] = SCSI_RD_CAPAC;
|
srb->cmd[0] = SCSI_RD_CAPAC;
|
||||||
|
srb->cmd[1] = srb->lun << 5;
|
||||||
srb->datalen = 8;
|
srb->datalen = 8;
|
||||||
srb->cmdlen = 12;
|
srb->cmdlen = 12;
|
||||||
if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
|
if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
|
||||||
|
@ -957,6 +986,7 @@ static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
|
||||||
{
|
{
|
||||||
memset(&srb->cmd[0], 0, 12);
|
memset(&srb->cmd[0], 0, 12);
|
||||||
srb->cmd[0] = SCSI_READ10;
|
srb->cmd[0] = SCSI_READ10;
|
||||||
|
srb->cmd[1] = srb->lun << 5;
|
||||||
srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
|
srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
|
||||||
srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
|
srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
|
||||||
srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
|
srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
|
||||||
|
@ -973,6 +1003,7 @@ static int usb_write_10(ccb *srb, struct us_data *ss, unsigned long start,
|
||||||
{
|
{
|
||||||
memset(&srb->cmd[0], 0, 12);
|
memset(&srb->cmd[0], 0, 12);
|
||||||
srb->cmd[0] = SCSI_WRITE10;
|
srb->cmd[0] = SCSI_WRITE10;
|
||||||
|
srb->cmd[1] = srb->lun << 5;
|
||||||
srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
|
srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
|
||||||
srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
|
srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
|
||||||
srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
|
srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
|
||||||
|
|
Loading…
Reference in a new issue