Hi, l...@gnu.org (Ludovic Courtès) writes:
> The request sense KCQ can be interpreted as ‘Not Ready - Medium Not > Present’, according to > <https://secure.wikimedia.org/wikipedia/en/wiki/KCQ>, despite the fact > that the SD card is actually in (and Linux can successfully read from > it.) > > The card reader has USB IDs 05e3:0726 (Genesys Logic). The problem was that this card reader exposes two SCSI logical units (LUNs), whereas the code in ‘usb_storage.c’ assumed single-LUN devices (which is typically the case with USB keys and disks.) The patch below adds support for multiple-LUN devices like this one. Tested on the GuruPlug. The net effect for the GuruPlug is that it makes it possible to boot a kernel stored on a microSD card, something long overdue [0, 1]. Can you please review and apply? Thanks, Ludo’. [0] http://plugcomputer.org/plugforum/index.php?topic=1642 [1] It really feels like I’m doing GlobalScale’s or Marvell’s job here. It looks like GlobalScale is steadily strengthening its reputation of being incompetent. Keep up the bad work!
From 2a82fa460b3e4ae19e52b742c151ce00484b2941 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <l...@gnu.org> Date: Mon, 4 Oct 2010 23:57:01 +0200 Subject: [PATCH] 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. --- common/usb_storage.c | 39 +++++++++++++++++++++++++++++++++++---- 1 files changed, 35 insertions(+), 4 deletions(-) diff --git a/common/usb_storage.c b/common/usb_storage.c index 76949b8..613c4f0 100644 --- a/common/usb_storage.c +++ b/common/usb_storage.c @@ -204,6 +204,22 @@ int usb_stor_info(void) 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 * to the user if mode = 1 @@ -241,13 +257,22 @@ int usb_stor_scan(int mode) break; /* no more devices avaiable */ if (usb_storage_probe(dev, 0, &usb_stor[usb_max_devs])) { - /* ok, it is a storage devices - * get info and fill it in + /* OK, it's a storage device. Iterate over its LUNs + * and populate `usb_dev_desc'. */ - if (usb_stor_get_info(dev, &usb_stor[usb_max_devs], - &usb_dev_desc[usb_max_devs]) == 1) + int lun, max_lun, start = usb_max_devs; + + 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++; } + } + } /* if storage device */ if (usb_max_devs == USB_MAX_STOR_DEV) { printf("max USB Storage Device reached: %d stopping\n", @@ -882,6 +907,7 @@ static int usb_inquiry(ccb *srb, struct us_data *ss) do { memset(&srb->cmd[0], 0, 12); srb->cmd[0] = SCSI_INQUIRY; + srb->cmd[1] = srb->lun << 5; srb->cmd[4] = 36; srb->datalen = 36; srb->cmdlen = 12; @@ -905,6 +931,7 @@ static int usb_request_sense(ccb *srb, struct us_data *ss) ptr = (char *)srb->pdata; memset(&srb->cmd[0], 0, 12); srb->cmd[0] = SCSI_REQ_SENSE; + srb->cmd[1] = srb->lun << 5; srb->cmd[4] = 18; srb->datalen = 18; srb->pdata = &srb->sense_buf[0]; @@ -924,6 +951,7 @@ static int usb_test_unit_ready(ccb *srb, struct us_data *ss) do { memset(&srb->cmd[0], 0, 12); srb->cmd[0] = SCSI_TST_U_RDY; + srb->cmd[1] = srb->lun << 5; srb->datalen = 0; srb->cmdlen = 12; 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 { memset(&srb->cmd[0], 0, 12); srb->cmd[0] = SCSI_RD_CAPAC; + srb->cmd[1] = srb->lun << 5; srb->datalen = 8; srb->cmdlen = 12; 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); srb->cmd[0] = SCSI_READ10; + srb->cmd[1] = srb->lun << 5; srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff; srb->cmd[3] = ((unsigned char) (start >> 16)) & 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); srb->cmd[0] = SCSI_WRITE10; + srb->cmd[1] = srb->lun << 5; srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff; srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff; srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff; -- 1.7.0
pgpEKUgwoY6tU.pgp
Description: PGP signature
_______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot