X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=common%2Fusb_storage.c;h=7c08f957752a34e7d8a973f3a2836093439a4be1;hb=5e3dca577b7c1bf58bd2b48449b18b7e7dcd8e04;hp=fd116be86acf646c04f9c3948a483dafffeff64b;hpb=f8d813e34f03823ddfeb3b9f44a9807d3ffb847e;p=oweals%2Fu-boot.git diff --git a/common/usb_storage.c b/common/usb_storage.c index fd116be86a..7c08f95775 100644 --- a/common/usb_storage.c +++ b/common/usb_storage.c @@ -1,12 +1,19 @@ /* - * (C) Copyright 2001 - * Denis Peter, MPL AG Switzerland + * Most of this source has been derived from the Linux USB + * project: + * (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net) + * (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org) + * (c) 1999 Michael Gee (michael@linuxspecific.com) + * (c) 2000 Yggdrasil Computing, Inc. + * + * + * Adapted for U-Boot: + * (C) Copyright 2001 Denis Peter, MPL AG Switzerland * * For BBB support (C) Copyright 2003 * Gary Jennejohn, DENX Software Engineering * - * Most of this source has been derived from the Linux USB - * project. BBB support based on /sys/dev/usb/umass.c from + * BBB support based on /sys/dev/usb/umass.c from * FreeBSD. * * See file CREDITS for list of people who contributed to this @@ -48,7 +55,8 @@ #include -#if (CONFIG_COMMANDS & CFG_CMD_USB) +#if defined(CONFIG_CMD_USB) +#include #include #ifdef CONFIG_USB_STORAGE @@ -121,7 +129,7 @@ typedef struct { #define UMASS_BBB_CSW_SIZE 13 #define USB_MAX_STOR_DEV 5 -static int usb_max_devs; /* number of highest available usb device */ +static int usb_max_devs = 0; /* number of highest available usb device */ static block_dev_desc_t usb_dev_desc[USB_MAX_STOR_DEV]; @@ -161,13 +169,13 @@ static struct us_data usb_stor[USB_MAX_STOR_DEV]; int usb_stor_get_info(struct usb_device *dev, struct us_data *us, block_dev_desc_t *dev_desc); int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,struct us_data *ss); -unsigned long usb_stor_read(int device, unsigned long blknr, unsigned long blkcnt, unsigned long *buffer); +unsigned long usb_stor_read(int device, unsigned long blknr, unsigned long blkcnt, void *buffer); struct usb_device * usb_get_dev_index(int index); void uhci_show_temp_int_td(void); block_dev_desc_t *usb_stor_get_dev(int index) { - return &usb_dev_desc[index]; + return (index < USB_MAX_STOR_DEV) ? &usb_dev_desc[index] : NULL; } @@ -177,7 +185,27 @@ void usb_show_progress(void) } /********************************************************************************* - * (re)-scan the usb and reports device info + * show info on storage devices; 'usb start/init' must be invoked earlier + * as we only retrieve structures populated during devices initialization + */ +int usb_stor_info(void) +{ + int i; + + if (usb_max_devs > 0) { + for (i = 0; i < usb_max_devs; i++) { + printf (" Device %d: ", i); + dev_print(&usb_dev_desc[i]); + } + return 0; + } + + printf("No storage devices, perhaps not 'usb start'ed..?\n"); + return 1; +} + +/********************************************************************************* + * scan the usb and reports device info * to the user if mode = 1 * returns current device or -1 if no */ @@ -190,7 +218,7 @@ int usb_stor_scan(int mode) memset(usb_stor_buf, 0, sizeof(usb_stor_buf)); if(mode==1) { - printf(" scanning bus for storage devices...\n"); + printf(" scanning bus for storage devices... "); } usb_disable_asynch(1); /* asynch transfer not allowed */ @@ -202,6 +230,7 @@ int usb_stor_scan(int mode) usb_dev_desc[i].part_type=PART_TYPE_UNKNOWN; usb_dev_desc[i].block_read=usb_stor_read; } + usb_max_devs=0; for(i=0;i0) return 0; else @@ -367,11 +392,13 @@ static int usb_stor_BBB_reset(struct us_data *us) result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0), US_BBB_RESET, USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, us->ifnum, 0, 0, USB_CNTL_TIMEOUT*5); + if((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) { USB_STOR_PRINTF("RESET:stall\n"); return -1; } + /* long wait for reset */ wait_ms(150); USB_STOR_PRINTF("BBB_reset result %d: status %X reset\n",result,us->pusb_dev->status); @@ -467,7 +494,7 @@ int usb_stor_BBB_comdat(ccb *srb, struct us_data *us) */ int usb_stor_CB_comdat(ccb *srb, struct us_data *us) { - int result; + int result = 0; int dir_in,retry; unsigned int pipe; unsigned long status; @@ -505,7 +532,7 @@ int usb_stor_CB_comdat(ccb *srb, struct us_data *us) USB_STOR_PRINTF("CB_transport: control msg returned %d, direction is %s to go 0x%lx\n",result,dir_in ? "IN" : "OUT",srb->datalen); if (srb->datalen) { - result = us_one_transfer(us, pipe, srb->pdata,srb->datalen); + result = us_one_transfer(us, pipe, (char *)srb->pdata,srb->datalen); USB_STOR_PRINTF("CBI attempted to transfer data, result is %d status %lX, len %d\n", result,us->pusb_dev->status,us->pusb_dev->act_len); if(!(us->pusb_dev->status & USB_ST_NAK_REC)) break; @@ -640,7 +667,9 @@ int usb_stor_BBB_transport(ccb *srb, struct us_data *us) retry = 0; again: USB_STOR_PRINTF("STATUS phase\n"); - result = usb_bulk_msg(us->pusb_dev, pipein, &csw, UMASS_BBB_CSW_SIZE, &actlen, USB_CNTL_TIMEOUT*5); + result = usb_bulk_msg(us->pusb_dev, pipein, &csw, UMASS_BBB_CSW_SIZE, + &actlen, USB_CNTL_TIMEOUT*5); + /* special handling of STALL in STATUS phase */ if((result < 0) && (retry < 1) && (us->pusb_dev->status & USB_ST_STALLED)) { USB_STOR_PRINTF("STATUS:stall\n"); @@ -797,7 +826,7 @@ do_retry: static int usb_inquiry(ccb *srb,struct us_data *ss) { int retry,i; - retry=3; + retry=5; do { memset(&srb->cmd[0],0,12); srb->cmd[0]=SCSI_INQUIRY; @@ -822,7 +851,7 @@ static int usb_request_sense(ccb *srb,struct us_data *ss) { char *ptr; - ptr=srb->pdata; + ptr=(char *)srb->pdata; memset(&srb->cmd[0],0,12); srb->cmd[0]=SCSI_REQ_SENSE; srb->cmd[1]=srb->lun<<5; @@ -832,13 +861,13 @@ static int usb_request_sense(ccb *srb,struct us_data *ss) srb->cmdlen=12; ss->transport(srb,ss); USB_STOR_PRINTF("Request Sense returned %02X %02X %02X\n",srb->sense_buf[2],srb->sense_buf[12],srb->sense_buf[13]); - srb->pdata=ptr; + srb->pdata=(uchar *)ptr; return 0; } static int usb_test_unit_ready(ccb *srb,struct us_data *ss) { - int retries=10; + int retries = 10; do { memset(&srb->cmd[0],0,12); @@ -859,7 +888,7 @@ static int usb_test_unit_ready(ccb *srb,struct us_data *ss) static int usb_read_capacity(ccb *srb,struct us_data *ss) { int retry; - retry=2; /* retries */ + retry = 3; /* retries */ do { memset(&srb->cmd[0],0,12); srb->cmd[0]=SCSI_RD_CAPAC; @@ -891,9 +920,31 @@ static int usb_read_10(ccb *srb,struct us_data *ss, unsigned long start, unsigne } +#ifdef CONFIG_USB_BIN_FIXUP +/* + * Some USB storage devices queried for SCSI identification data respond with + * binary strings, which if output to the console freeze the terminal. The + * workaround is to modify the vendor and product strings read from such + * device with proper values (as reported by 'usb info'). + * + * Vendor and product length limits are taken from the definition of + * block_dev_desc_t in include/part.h. + */ +static void usb_bin_fixup(struct usb_device_descriptor descriptor, + unsigned char vendor[], + unsigned char product[]) { + const unsigned char max_vendor_len = 40; + const unsigned char max_product_len = 20; + if (descriptor.idVendor == 0x0424 && descriptor.idProduct == 0x223a) { + strncpy ((char *)vendor, "SMSC", max_vendor_len); + strncpy ((char *)product, "Flash Media Cntrller", max_product_len); + } +} +#endif /* CONFIG_USB_BIN_FIXUP */ + #define USB_MAX_READ_BLK 20 -unsigned long usb_stor_read(int device, unsigned long blknr, unsigned long blkcnt, unsigned long *buffer) +unsigned long usb_stor_read(int device, unsigned long blknr, unsigned long blkcnt, void *buffer) { unsigned long start,blks, buf_addr; unsigned short smallblks; @@ -972,9 +1023,6 @@ int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,struct us_data int protocol = 0; int subclass = 0; - - memset(ss, 0, sizeof(struct us_data)); - /* let's examine the device now */ iface = &dev->config.if_desc[ifnum]; @@ -996,6 +1044,8 @@ int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,struct us_data return 0; } + memset(ss, 0, sizeof(struct us_data)); + /* At this point, we know we've got a live one */ USB_STOR_PRINTF("\n\nUSB Mass Storage device detected\n"); @@ -1103,47 +1153,69 @@ int usb_stor_get_info(struct usb_device *dev,struct us_data *ss,block_dev_desc_t unsigned char perq,modi; unsigned long cap[2]; unsigned long *capacity,*blksz; - ccb *pccb=&usb_ccb; + ccb *pccb = &usb_ccb; + + /* for some reasons a couple of devices would not survive this reset */ + if ( + /* Sony USM256E */ + (dev->descriptor.idVendor == 0x054c && + dev->descriptor.idProduct == 0x019e) + + || + /* USB007 Mini-USB2 Flash Drive */ + (dev->descriptor.idVendor == 0x066f && + dev->descriptor.idProduct == 0x2010) + || + /* SanDisk Corporation Cruzer Micro 20044318410546613953 */ + (dev->descriptor.idVendor == 0x0781 && + dev->descriptor.idProduct == 0x5151) + ) + USB_STOR_PRINTF("usb_stor_get_info: skipping RESET..\n"); + else + ss->transport_reset(ss); - ss->transport_reset(ss); - pccb->pdata=usb_stor_buf; + pccb->pdata = usb_stor_buf; - dev_desc->target=dev->devnum; - pccb->lun=dev_desc->lun; + dev_desc->target = dev->devnum; + pccb->lun = dev_desc->lun; USB_STOR_PRINTF(" address %d\n",dev_desc->target); if(usb_inquiry(pccb,ss)) return -1; - perq=usb_stor_buf[0]; - modi=usb_stor_buf[1]; - if((perq & 0x1f)==0x1f) { + + perq = usb_stor_buf[0]; + modi = usb_stor_buf[1]; + if((perq & 0x1f) == 0x1f) { return 0; /* skip unknown devices */ } - if((modi&0x80)==0x80) {/* drive is removable */ - dev_desc->removable=1; + if((modi&0x80) == 0x80) {/* drive is removable */ + dev_desc->removable = 1; } memcpy(&dev_desc->vendor[0], &usb_stor_buf[8], 8); memcpy(&dev_desc->product[0], &usb_stor_buf[16], 16); memcpy(&dev_desc->revision[0], &usb_stor_buf[32], 4); - dev_desc->vendor[8]=0; - dev_desc->product[16]=0; - dev_desc->revision[4]=0; + dev_desc->vendor[8] = 0; + dev_desc->product[16] = 0; + dev_desc->revision[4] = 0; +#ifdef CONFIG_USB_BIN_FIXUP + usb_bin_fixup(dev->descriptor, (uchar *)dev_desc->vendor, (uchar *)dev_desc->product); +#endif /* CONFIG_USB_BIN_FIXUP */ USB_STOR_PRINTF("ISO Vers %X, Response Data %X\n",usb_stor_buf[2],usb_stor_buf[3]); if(usb_test_unit_ready(pccb,ss)) { printf("Device NOT ready\n Request Sense returned %02X %02X %02X\n",pccb->sense_buf[2],pccb->sense_buf[12],pccb->sense_buf[13]); - if(dev_desc->removable==1) { - dev_desc->type=perq; + if(dev_desc->removable == 1) { + dev_desc->type = perq; return 1; } else return 0; } - pccb->pdata=(unsigned char *)&cap[0]; + pccb->pdata = (unsigned char *)&cap[0]; memset(pccb->pdata,0,8); - if(usb_read_capacity(pccb,ss)!=0) { + if(usb_read_capacity(pccb,ss) != 0) { printf("READ_CAP ERROR\n"); - cap[0]=2880; - cap[1]=0x200; + cap[0] = 2880; + cap[1] = 0x200; } USB_STOR_PRINTF("Read Capacity returns: 0x%lx, 0x%lx\n",cap[0],cap[1]); #if 0 @@ -1163,13 +1235,13 @@ int usb_stor_get_info(struct usb_device *dev,struct us_data *ss,block_dev_desc_t (((unsigned long)(cap[1]) & (unsigned long)0xff000000UL) >> 24) )); #endif /* this assumes bigendian! */ - cap[0]+=1; - capacity=&cap[0]; - blksz=&cap[1]; + cap[0] += 1; + capacity = &cap[0]; + blksz = &cap[1]; USB_STOR_PRINTF("Capacity = 0x%lx, blocksz = 0x%lx\n",*capacity,*blksz); - dev_desc->lba=*capacity; - dev_desc->blksz=*blksz; - dev_desc->type=perq; + dev_desc->lba = *capacity; + dev_desc->blksz = *blksz; + dev_desc->type = perq; USB_STOR_PRINTF(" address %d\n",dev_desc->target); USB_STOR_PRINTF("partype: %d\n",dev_desc->part_type); @@ -1180,4 +1252,4 @@ int usb_stor_get_info(struct usb_device *dev,struct us_data *ss,block_dev_desc_t } #endif /* CONFIG_USB_STORAGE */ -#endif /* CFG_CMD_USB */ +#endif