mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-19 03:15:00 +00:00
USB storage cleanup patch
Cleanup usb storage Signed-off-by: Michael Trimarchi <trimarchimichael@yahoo.it> Signed-off-by: Remy Bohmer <linux@bohmer.net>
This commit is contained in:
parent
2b6fd5c77d
commit
a0cb3fc31e
1 changed files with 394 additions and 316 deletions
|
@ -110,7 +110,7 @@ typedef struct {
|
|||
__u8 CBWCDB[CBWCDBLENGTH];
|
||||
} umass_bbb_cbw_t;
|
||||
#define UMASS_BBB_CBW_SIZE 31
|
||||
static __u32 CBWTag = 0;
|
||||
static __u32 CBWTag;
|
||||
|
||||
/* Command Status Wrapper */
|
||||
typedef struct {
|
||||
|
@ -126,16 +126,17 @@ typedef struct {
|
|||
#define UMASS_BBB_CSW_SIZE 13
|
||||
|
||||
#define USB_MAX_STOR_DEV 5
|
||||
static int usb_max_devs = 0; /* number of highest available usb device */
|
||||
static int usb_max_devs; /* number of highest available usb device */
|
||||
|
||||
static block_dev_desc_t usb_dev_desc[USB_MAX_STOR_DEV];
|
||||
|
||||
struct us_data;
|
||||
typedef int (*trans_cmnd)(ccb*, struct us_data*);
|
||||
typedef int (*trans_reset)(struct us_data*);
|
||||
typedef int (*trans_cmnd)(ccb *cb, struct us_data *data);
|
||||
typedef int (*trans_reset)(struct us_data *data);
|
||||
|
||||
struct us_data {
|
||||
struct usb_device *pusb_dev; /* this usb_device */
|
||||
|
||||
unsigned int flags; /* from filter initially */
|
||||
unsigned char ifnum; /* interface number */
|
||||
unsigned char ep_in; /* in endpoint */
|
||||
|
@ -163,10 +164,12 @@ static struct us_data usb_stor[USB_MAX_STOR_DEV];
|
|||
#define USB_STOR_TRANSPORT_FAILED -1
|
||||
#define USB_STOR_TRANSPORT_ERROR -2
|
||||
|
||||
|
||||
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, void *buffer);
|
||||
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, void *buffer);
|
||||
struct usb_device * usb_get_dev_index(int index);
|
||||
void uhci_show_temp_int_td(void);
|
||||
|
||||
|
@ -181,7 +184,7 @@ void usb_show_progress(void)
|
|||
printf(".");
|
||||
}
|
||||
|
||||
/*********************************************************************************
|
||||
/*******************************************************************************
|
||||
* show info on storage devices; 'usb start/init' must be invoked earlier
|
||||
* as we only retrieve structures populated during devices initialization
|
||||
*/
|
||||
|
@ -201,7 +204,7 @@ int usb_stor_info(void)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/*********************************************************************************
|
||||
/*******************************************************************************
|
||||
* scan the usb and reports device info
|
||||
* to the user if mode = 1
|
||||
* returns current device or -1 if no
|
||||
|
@ -214,9 +217,9 @@ int usb_stor_scan(int mode)
|
|||
/* GJ */
|
||||
memset(usb_stor_buf, 0, sizeof(usb_stor_buf));
|
||||
|
||||
if(mode==1) {
|
||||
if (mode == 1)
|
||||
printf(" scanning bus for storage devices... ");
|
||||
}
|
||||
|
||||
usb_disable_asynch(1); /* asynch transfer not allowed */
|
||||
|
||||
for (i = 0; i < USB_MAX_STOR_DEV; i++) {
|
||||
|
@ -232,16 +235,21 @@ int usb_stor_scan(int mode)
|
|||
for (i = 0; i < USB_MAX_DEVICE; i++) {
|
||||
dev = usb_get_dev_index(i); /* get device */
|
||||
USB_STOR_PRINTF("i=%d\n", i);
|
||||
if(dev==NULL) {
|
||||
if (dev == NULL)
|
||||
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 */
|
||||
if(usb_stor_get_info(dev, &usb_stor[usb_max_devs], &usb_dev_desc[usb_max_devs]))
|
||||
|
||||
if (usb_storage_probe(dev, 0, &usb_stor[usb_max_devs])) {
|
||||
/* ok, it is a storage devices
|
||||
* get info and fill it in
|
||||
*/
|
||||
if (usb_stor_get_info(dev, &usb_stor[usb_max_devs],
|
||||
&usb_dev_desc[usb_max_devs]))
|
||||
usb_max_devs++;
|
||||
} /* if storage device */
|
||||
}
|
||||
/* if storage device */
|
||||
if (usb_max_devs == USB_MAX_STOR_DEV) {
|
||||
printf("max USB Storage Device reached: %d stopping\n",usb_max_devs);
|
||||
printf("max USB Storage Device reached: %d stopping\n",
|
||||
usb_max_devs);
|
||||
break;
|
||||
}
|
||||
} /* for */
|
||||
|
@ -250,7 +258,6 @@ int usb_stor_scan(int mode)
|
|||
printf("%d Storage Device(s) found\n", usb_max_devs);
|
||||
if (usb_max_devs > 0)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -259,9 +266,8 @@ static int usb_stor_irq(struct usb_device *dev)
|
|||
struct us_data *us;
|
||||
us = (struct us_data *)dev->privptr;
|
||||
|
||||
if(us->ip_wanted) {
|
||||
if (us->ip_wanted)
|
||||
us->ip_wanted = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -272,9 +278,8 @@ static void usb_show_srb(ccb * pccb)
|
|||
{
|
||||
int i;
|
||||
printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
|
||||
for(i=0;i<12;i++) {
|
||||
for (i = 0; i < 12; i++)
|
||||
printf("%02X ", pccb->cmd[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
@ -322,11 +327,14 @@ static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
|
|||
USB_STOR_PRINTF("Bulk xfer 0x%x(%d) try #%d\n",
|
||||
(unsigned int)buf, this_xfer, 11 - maxtry);
|
||||
result = usb_bulk_msg(us->pusb_dev, pipe, buf,
|
||||
this_xfer, &partial, USB_CNTL_TIMEOUT*5);
|
||||
this_xfer, &partial,
|
||||
USB_CNTL_TIMEOUT * 5);
|
||||
USB_STOR_PRINTF("bulk_msg returned %d xferred %d/%d\n",
|
||||
result, partial, this_xfer);
|
||||
if (us->pusb_dev->status != 0) {
|
||||
/* if we stall, we need to clear it before we go on */
|
||||
/* if we stall, we need to clear it before
|
||||
* we go on
|
||||
*/
|
||||
#ifdef USB_STOR_DEBUG
|
||||
display_int_status(us->pusb_dev->status);
|
||||
#endif
|
||||
|
@ -346,12 +354,15 @@ static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
|
|||
USB_STOR_PRINTF("Device NAKed bulk_msg\n");
|
||||
return result;
|
||||
}
|
||||
USB_STOR_PRINTF("bulk transferred with error");
|
||||
if (this_xfer == partial) {
|
||||
USB_STOR_PRINTF("bulk transferred with error %d, but data ok\n",us->pusb_dev->status);
|
||||
USB_STOR_PRINTF(" %d, but data ok\n",
|
||||
us->pusb_dev->status);
|
||||
return 0;
|
||||
}
|
||||
/* if our try counter reaches 0, bail out */
|
||||
USB_STOR_PRINTF("bulk transferred with error %d, data %d\n",us->pusb_dev->status,partial);
|
||||
USB_STOR_PRINTF(" %d, data %d\n",
|
||||
us->pusb_dev->status, partial);
|
||||
if (!maxtry--)
|
||||
return result;
|
||||
}
|
||||
|
@ -387,28 +398,32 @@ static int usb_stor_BBB_reset(struct us_data *us)
|
|||
*/
|
||||
USB_STOR_PRINTF("BBB_reset\n");
|
||||
result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
|
||||
US_BBB_RESET, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
|
||||
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))
|
||||
{
|
||||
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);
|
||||
USB_STOR_PRINTF("BBB_reset result %d: status %X reset\n", result,
|
||||
us->pusb_dev->status);
|
||||
pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
|
||||
result = usb_clear_halt(us->pusb_dev, pipe);
|
||||
/* long wait for reset */
|
||||
wait_ms(150);
|
||||
USB_STOR_PRINTF("BBB_reset result %d: status %X clearing IN endpoint\n",result,us->pusb_dev->status);
|
||||
USB_STOR_PRINTF("BBB_reset result %d: status %X clearing IN endpoint\n",
|
||||
result, us->pusb_dev->status);
|
||||
/* long wait for reset */
|
||||
pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
|
||||
result = usb_clear_halt(us->pusb_dev, pipe);
|
||||
wait_ms(150);
|
||||
USB_STOR_PRINTF("BBB_reset result %d: status %X clearing OUT endpoint\n",result,us->pusb_dev->status);
|
||||
USB_STOR_PRINTF("BBB_reset result %d: status %X"
|
||||
" clearing OUT endpoint\n", result,
|
||||
us->pusb_dev->status);
|
||||
USB_STOR_PRINTF("BBB_reset done\n");
|
||||
return 0;
|
||||
}
|
||||
|
@ -423,16 +438,20 @@ static int usb_stor_CB_reset(struct us_data *us)
|
|||
int result;
|
||||
|
||||
USB_STOR_PRINTF("CB_reset\n");
|
||||
memset(cmd, 0xFF, sizeof(cmd));
|
||||
memset(cmd, 0xff, sizeof(cmd));
|
||||
cmd[0] = SCSI_SEND_DIAG;
|
||||
cmd[1] = 4;
|
||||
result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev, 0),
|
||||
US_CBI_ADSC, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
|
||||
0, us->ifnum, cmd, sizeof(cmd), USB_CNTL_TIMEOUT*5);
|
||||
US_CBI_ADSC,
|
||||
USB_TYPE_CLASS | USB_RECIP_INTERFACE,
|
||||
0, us->ifnum, cmd, sizeof(cmd),
|
||||
USB_CNTL_TIMEOUT * 5);
|
||||
|
||||
/* long wait for reset */
|
||||
wait_ms(1500);
|
||||
USB_STOR_PRINTF("CB_reset result %d: status %X clearing endpoint halt\n",result,us->pusb_dev->status);
|
||||
USB_STOR_PRINTF("CB_reset result %d: status %X"
|
||||
" clearing endpoint halt\n", result,
|
||||
us->pusb_dev->status);
|
||||
usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
|
||||
usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
|
||||
|
||||
|
@ -455,7 +474,9 @@ int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
|
|||
dir_in = US_DIRECTION(srb->cmd[0]);
|
||||
|
||||
#ifdef BBB_COMDAT_TRACE
|
||||
printf("dir %d lun %d cmdlen %d cmd %p datalen %d pdata %p\n", dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen, srb->pdata);
|
||||
printf("dir %d lun %d cmdlen %d cmd %p datalen %d pdata %p\n",
|
||||
dir_in, srb->lun, srb->cmdlen, srb->cmd, srb->datalen,
|
||||
srb->pdata);
|
||||
if (srb->cmdlen) {
|
||||
for (result = 0; result < srb->cmdlen; result++)
|
||||
printf("cmd[%d] %#x ", result, srb->cmd[result]);
|
||||
|
@ -480,7 +501,8 @@ int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
|
|||
/* copy the command data into the CBW command data buffer */
|
||||
/* DST SRC LEN!!! */
|
||||
memcpy(cbw.CBWCDB, srb->cmd, srb->cmdlen);
|
||||
result = usb_bulk_msg(us->pusb_dev, pipe, &cbw, UMASS_BBB_CBW_SIZE, &actlen, USB_CNTL_TIMEOUT*5);
|
||||
result = usb_bulk_msg(us->pusb_dev, pipe, &cbw, UMASS_BBB_CBW_SIZE,
|
||||
&actlen, USB_CNTL_TIMEOUT * 5);
|
||||
if (result < 0)
|
||||
USB_STOR_PRINTF("usb_stor_BBB_comdat:usb_bulk_msg error\n");
|
||||
return result;
|
||||
|
@ -503,34 +525,49 @@ int usb_stor_CB_comdat(ccb *srb, struct us_data *us)
|
|||
pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
|
||||
else
|
||||
pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
|
||||
|
||||
while (retry--) {
|
||||
USB_STOR_PRINTF("CBI gets a command: Try %d\n", 5 - retry);
|
||||
#ifdef USB_STOR_DEBUG
|
||||
usb_show_srb(srb);
|
||||
#endif
|
||||
/* let's send the command via the control pipe */
|
||||
result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
|
||||
US_CBI_ADSC, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
|
||||
result = usb_control_msg(us->pusb_dev,
|
||||
usb_sndctrlpipe(us->pusb_dev , 0),
|
||||
US_CBI_ADSC,
|
||||
USB_TYPE_CLASS | USB_RECIP_INTERFACE,
|
||||
0, us->ifnum,
|
||||
srb->cmd, srb->cmdlen, USB_CNTL_TIMEOUT*5);
|
||||
USB_STOR_PRINTF("CB_transport: control msg returned %d, status %X\n",result,us->pusb_dev->status);
|
||||
srb->cmd, srb->cmdlen,
|
||||
USB_CNTL_TIMEOUT * 5);
|
||||
USB_STOR_PRINTF("CB_transport: control msg returned %d,"
|
||||
" status %X\n", result, us->pusb_dev->status);
|
||||
/* check the return code for the command */
|
||||
if (result < 0) {
|
||||
if (us->pusb_dev->status & USB_ST_STALLED) {
|
||||
status = us->pusb_dev->status;
|
||||
USB_STOR_PRINTF(" stall during command found, clear pipe\n");
|
||||
usb_clear_halt(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0));
|
||||
USB_STOR_PRINTF(" stall during command found,"
|
||||
" clear pipe\n");
|
||||
usb_clear_halt(us->pusb_dev,
|
||||
usb_sndctrlpipe(us->pusb_dev, 0));
|
||||
us->pusb_dev->status = status;
|
||||
}
|
||||
USB_STOR_PRINTF(" error during command %02X Stat = %X\n",srb->cmd[0],us->pusb_dev->status);
|
||||
USB_STOR_PRINTF(" error during command %02X"
|
||||
" Stat = %X\n", srb->cmd[0],
|
||||
us->pusb_dev->status);
|
||||
return result;
|
||||
}
|
||||
/* transfer the data payload for this command, if one exists*/
|
||||
|
||||
USB_STOR_PRINTF("CB_transport: control msg returned %d, direction is %s to go 0x%lx\n",result,dir_in ? "IN" : "OUT",srb->datalen);
|
||||
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, (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);
|
||||
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;
|
||||
} /* if (srb->datalen) */
|
||||
|
@ -638,12 +675,14 @@ int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
|
|||
pipe = pipein;
|
||||
else
|
||||
pipe = pipeout;
|
||||
result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen, &data_actlen, USB_CNTL_TIMEOUT*5);
|
||||
result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, srb->datalen,
|
||||
&data_actlen, USB_CNTL_TIMEOUT * 5);
|
||||
/* special handling of STALL in DATA phase */
|
||||
if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) {
|
||||
USB_STOR_PRINTF("DATA:stall\n");
|
||||
/* clear the STALL on the endpoint */
|
||||
result = usb_stor_BBB_clear_endpt_stall(us, dir_in? us->ep_in : us->ep_out);
|
||||
result = usb_stor_BBB_clear_endpt_stall(us,
|
||||
dir_in ? us->ep_in : us->ep_out);
|
||||
if (result >= 0)
|
||||
/* continue on to STATUS phase */
|
||||
goto st;
|
||||
|
@ -668,7 +707,8 @@ int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
|
|||
&actlen, USB_CNTL_TIMEOUT*5);
|
||||
|
||||
/* special handling of STALL in STATUS phase */
|
||||
if((result < 0) && (retry < 1) && (us->pusb_dev->status & USB_ST_STALLED)) {
|
||||
if ((result < 0) && (retry < 1) &&
|
||||
(us->pusb_dev->status & USB_ST_STALLED)) {
|
||||
USB_STOR_PRINTF("STATUS:stall\n");
|
||||
/* clear the STALL on the endpoint */
|
||||
result = usb_stor_BBB_clear_endpt_stall(us, us->ep_in);
|
||||
|
@ -734,7 +774,8 @@ int usb_stor_CB_transport(ccb *srb, struct us_data *us)
|
|||
/* issue the command */
|
||||
do_retry:
|
||||
result = usb_stor_CB_comdat(srb, us);
|
||||
USB_STOR_PRINTF("command / Data returned %d, status %X\n",result,us->pusb_dev->status);
|
||||
USB_STOR_PRINTF("command / Data returned %d, status %X\n",
|
||||
result, us->pusb_dev->status);
|
||||
/* if this is an CBI Protocol, get IRQ */
|
||||
if (us->protocol == US_PR_CBI) {
|
||||
status = usb_stor_CBI_get_status(srb, us);
|
||||
|
@ -762,7 +803,8 @@ do_retry:
|
|||
}
|
||||
if ((us->protocol == US_PR_CBI) &&
|
||||
((srb->cmd[0] == SCSI_REQ_SENSE) ||
|
||||
(srb->cmd[0]==SCSI_INQUIRY))) { /* do not issue an autorequest after request sense */
|
||||
(srb->cmd[0] == SCSI_INQUIRY))) {
|
||||
/* do not issue an autorequest after request sense */
|
||||
USB_STOR_PRINTF("No auto request and good\n");
|
||||
return USB_STOR_TRANSPORT_GOOD;
|
||||
}
|
||||
|
@ -778,28 +820,38 @@ do_retry:
|
|||
result = usb_stor_CB_comdat(psrb, us);
|
||||
USB_STOR_PRINTF("auto request returned %d\n", result);
|
||||
/* if this is an CBI Protocol, get IRQ */
|
||||
if(us->protocol==US_PR_CBI) {
|
||||
if (us->protocol == US_PR_CBI)
|
||||
status = usb_stor_CBI_get_status(psrb, us);
|
||||
}
|
||||
|
||||
if ((result < 0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
|
||||
USB_STOR_PRINTF(" AUTO REQUEST ERROR %d\n",us->pusb_dev->status);
|
||||
USB_STOR_PRINTF(" AUTO REQUEST ERROR %d\n",
|
||||
us->pusb_dev->status);
|
||||
return USB_STOR_TRANSPORT_ERROR;
|
||||
}
|
||||
USB_STOR_PRINTF("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",srb->sense_buf[0],srb->sense_buf[2],srb->sense_buf[12],srb->sense_buf[13]);
|
||||
USB_STOR_PRINTF("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
|
||||
srb->sense_buf[0], srb->sense_buf[2],
|
||||
srb->sense_buf[12], srb->sense_buf[13]);
|
||||
/* Check the auto request result */
|
||||
if ((srb->sense_buf[2] == 0) &&
|
||||
(srb->sense_buf[12] == 0) &&
|
||||
(srb->sense_buf[13]==0)) /* ok, no sense */
|
||||
(srb->sense_buf[13] == 0)) {
|
||||
/* ok, no sense */
|
||||
return USB_STOR_TRANSPORT_GOOD;
|
||||
}
|
||||
|
||||
/* Check the auto request result */
|
||||
switch (srb->sense_buf[2]) {
|
||||
case 0x01: /* Recovered Error */
|
||||
case 0x01:
|
||||
/* Recovered Error */
|
||||
return USB_STOR_TRANSPORT_GOOD;
|
||||
break;
|
||||
case 0x02: /* Not Ready */
|
||||
case 0x02:
|
||||
/* Not Ready */
|
||||
if (notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
|
||||
printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X 0x%02X (NOT READY)\n",
|
||||
srb->cmd[0],srb->sense_buf[0],srb->sense_buf[2],srb->sense_buf[12],srb->sense_buf[13]);
|
||||
printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
|
||||
" 0x%02X (NOT READY)\n", srb->cmd[0],
|
||||
srb->sense_buf[0], srb->sense_buf[2],
|
||||
srb->sense_buf[12], srb->sense_buf[13]);
|
||||
return USB_STOR_TRANSPORT_FAILED;
|
||||
} else {
|
||||
wait_ms(100);
|
||||
|
@ -808,12 +860,13 @@ do_retry:
|
|||
break;
|
||||
default:
|
||||
if (retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
|
||||
printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
|
||||
srb->cmd[0],srb->sense_buf[0],srb->sense_buf[2],srb->sense_buf[12],srb->sense_buf[13]);
|
||||
printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X"
|
||||
" 0x%02X\n", srb->cmd[0], srb->sense_buf[0],
|
||||
srb->sense_buf[2], srb->sense_buf[12],
|
||||
srb->sense_buf[13]);
|
||||
return USB_STOR_TRANSPORT_FAILED;
|
||||
} else {
|
||||
} else
|
||||
goto do_retry;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return USB_STOR_TRANSPORT_FAILED;
|
||||
|
@ -857,7 +910,9 @@ static int usb_request_sense(ccb *srb,struct us_data *ss)
|
|||
srb->pdata = &srb->sense_buf[0];
|
||||
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]);
|
||||
USB_STOR_PRINTF("Request Sense returned %02X %02X %02X\n",
|
||||
srb->sense_buf[2], srb->sense_buf[12],
|
||||
srb->sense_buf[13]);
|
||||
srb->pdata = (uchar *)ptr;
|
||||
return 0;
|
||||
}
|
||||
|
@ -872,9 +927,8 @@ static int usb_test_unit_ready(ccb *srb,struct us_data *ss)
|
|||
srb->cmd[1] = srb->lun << 5;
|
||||
srb->datalen = 0;
|
||||
srb->cmdlen = 12;
|
||||
if(ss->transport(srb,ss)==USB_STOR_TRANSPORT_GOOD) {
|
||||
if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
|
||||
return 0;
|
||||
}
|
||||
usb_request_sense(srb, ss);
|
||||
wait_ms(100);
|
||||
} while (retries--);
|
||||
|
@ -885,22 +939,23 @@ 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 = 3; /* retries */
|
||||
/* XXX retries */
|
||||
retry = 3;
|
||||
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) {
|
||||
if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
|
||||
return 0;
|
||||
}
|
||||
} while (retry--);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int usb_read_10(ccb *srb,struct us_data *ss, unsigned long start, unsigned short blocks)
|
||||
static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
|
||||
unsigned short blocks)
|
||||
{
|
||||
memset(&srb->cmd[0], 0, 12);
|
||||
srb->cmd[0] = SCSI_READ10;
|
||||
|
@ -934,14 +989,16 @@ static void usb_bin_fixup(struct usb_device_descriptor descriptor,
|
|||
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);
|
||||
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, void *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;
|
||||
|
@ -953,15 +1010,13 @@ unsigned long usb_stor_read(int device, unsigned long blknr, unsigned long blkcn
|
|||
return 0;
|
||||
|
||||
device &= 0xff;
|
||||
/* Setup device
|
||||
*/
|
||||
/* Setup device */
|
||||
USB_STOR_PRINTF("\nusb_read: dev %d \n", device);
|
||||
dev = NULL;
|
||||
for (i = 0; i < USB_MAX_DEVICE; i++) {
|
||||
dev = usb_get_dev_index(i);
|
||||
if(dev==NULL) {
|
||||
if (dev == NULL)
|
||||
return 0;
|
||||
}
|
||||
if (dev->devnum == usb_dev_desc[device].target)
|
||||
break;
|
||||
}
|
||||
|
@ -972,25 +1027,30 @@ unsigned long usb_stor_read(int device, unsigned long blknr, unsigned long blkcn
|
|||
start = blknr;
|
||||
blks = blkcnt;
|
||||
if (usb_test_unit_ready(srb, (struct us_data *)dev->privptr)) {
|
||||
printf("Device NOT ready\n Request Sense returned %02X %02X %02X\n",
|
||||
srb->sense_buf[2],srb->sense_buf[12],srb->sense_buf[13]);
|
||||
printf("Device NOT ready\n Request Sense returned %02X %02X"
|
||||
" %02X\n", srb->sense_buf[2], srb->sense_buf[12],
|
||||
srb->sense_buf[13]);
|
||||
return 0;
|
||||
}
|
||||
USB_STOR_PRINTF("\nusb_read: dev %d startblk %lx, blccnt %lx buffer %lx\n",device,start,blks, buf_addr);
|
||||
|
||||
USB_STOR_PRINTF("\nusb_read: dev %d startblk %lx, blccnt %lx"
|
||||
" buffer %lx\n", device, start, blks, buf_addr);
|
||||
|
||||
do {
|
||||
/* XXX need some comment here */
|
||||
retry = 2;
|
||||
srb->pdata = (unsigned char *)buf_addr;
|
||||
if(blks>USB_MAX_READ_BLK) {
|
||||
if (blks > USB_MAX_READ_BLK)
|
||||
smallblks = USB_MAX_READ_BLK;
|
||||
} else {
|
||||
else
|
||||
smallblks = (unsigned short) blks;
|
||||
}
|
||||
retry_it:
|
||||
if (smallblks == USB_MAX_READ_BLK)
|
||||
usb_show_progress();
|
||||
srb->datalen = usb_dev_desc[device].blksz * smallblks;
|
||||
srb->pdata = (unsigned char *)buf_addr;
|
||||
if(usb_read_10(srb,(struct us_data *)dev->privptr, start, smallblks)) {
|
||||
if (usb_read_10(srb, (struct us_data *)dev->privptr, start,
|
||||
smallblks)) {
|
||||
USB_STOR_PRINTF("Read ERROR\n");
|
||||
usb_request_sense(srb, (struct us_data *)dev->privptr);
|
||||
if (retry--)
|
||||
|
@ -1002,16 +1062,20 @@ retry_it:
|
|||
blks -= smallblks;
|
||||
buf_addr += srb->datalen;
|
||||
} while (blks != 0);
|
||||
USB_STOR_PRINTF("usb_read: end startblk %lx, blccnt %x buffer %lx\n",start,smallblks,buf_addr);
|
||||
|
||||
USB_STOR_PRINTF("usb_read: end startblk %lx, blccnt %x buffer %lx\n",
|
||||
start, smallblks, buf_addr);
|
||||
|
||||
usb_disable_asynch(0); /* asynch transfer allowed */
|
||||
if (blkcnt >= USB_MAX_READ_BLK)
|
||||
printf("\n");
|
||||
return(blkcnt);
|
||||
return blkcnt;
|
||||
}
|
||||
|
||||
|
||||
/* Probe to see if a new device is actually a Storage device */
|
||||
int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,struct us_data *ss)
|
||||
int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
|
||||
struct us_data *ss)
|
||||
{
|
||||
struct usb_interface_descriptor *iface;
|
||||
int i;
|
||||
|
@ -1025,8 +1089,11 @@ int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,struct us_data
|
|||
|
||||
#if 0
|
||||
/* this is the place to patch some storage devices */
|
||||
USB_STOR_PRINTF("iVendor %X iProduct %X\n",dev->descriptor.idVendor,dev->descriptor.idProduct);
|
||||
if ((dev->descriptor.idVendor) == 0x066b && (dev->descriptor.idProduct) == 0x0103) {
|
||||
USB_STOR_PRINTF("iVendor %X iProduct %X\n", dev->descriptor.idVendor,
|
||||
dev->descriptor.idProduct);
|
||||
|
||||
if ((dev->descriptor.idVendor) == 0x066b &&
|
||||
(dev->descriptor.idProduct) == 0x0103) {
|
||||
USB_STOR_PRINTF("patched for E-USB\n");
|
||||
protocol = US_PR_CB;
|
||||
subclass = US_SC_UFI; /* an assumption */
|
||||
|
@ -1095,19 +1162,20 @@ int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,struct us_data
|
|||
*/
|
||||
for (i = 0; i < iface->bNumEndpoints; i++) {
|
||||
/* is it an BULK endpoint? */
|
||||
if ((iface->ep_desc[i].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
|
||||
== USB_ENDPOINT_XFER_BULK) {
|
||||
if ((iface->ep_desc[i].bmAttributes &
|
||||
USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
|
||||
if (iface->ep_desc[i].bEndpointAddress & USB_DIR_IN)
|
||||
ss->ep_in = iface->ep_desc[i].bEndpointAddress &
|
||||
USB_ENDPOINT_NUMBER_MASK;
|
||||
else
|
||||
ss->ep_out = iface->ep_desc[i].bEndpointAddress &
|
||||
ss->ep_out =
|
||||
iface->ep_desc[i].bEndpointAddress &
|
||||
USB_ENDPOINT_NUMBER_MASK;
|
||||
}
|
||||
|
||||
/* is it an interrupt endpoint? */
|
||||
if ((iface->ep_desc[i].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
|
||||
== USB_ENDPOINT_XFER_INT) {
|
||||
if ((iface->ep_desc[i].bmAttributes &
|
||||
USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
|
||||
ss->ep_int = iface->ep_desc[i].bEndpointAddress &
|
||||
USB_ENDPOINT_NUMBER_MASK;
|
||||
ss->irqinterval = iface->ep_desc[i].bInterval;
|
||||
|
@ -1133,9 +1201,10 @@ int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,struct us_data
|
|||
printf("Sorry, protocol %d not yet supported.\n", ss->subclass);
|
||||
return 0;
|
||||
}
|
||||
if(ss->ep_int) { /* we had found an interrupt endpoint, prepare irq pipe */
|
||||
/* set up the IRQ pipe and handler */
|
||||
|
||||
if (ss->ep_int) {
|
||||
/* we had found an interrupt endpoint, prepare irq pipe
|
||||
* set up the IRQ pipe and handler
|
||||
*/
|
||||
ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255;
|
||||
ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
|
||||
ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
|
||||
|
@ -1145,7 +1214,8 @@ int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,struct us_data
|
|||
return 1;
|
||||
}
|
||||
|
||||
int usb_stor_get_info(struct usb_device *dev,struct us_data *ss,block_dev_desc_t *dev_desc)
|
||||
int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
|
||||
block_dev_desc_t *dev_desc)
|
||||
{
|
||||
unsigned char perq, modi;
|
||||
unsigned long cap[2];
|
||||
|
@ -1157,7 +1227,6 @@ int usb_stor_get_info(struct usb_device *dev,struct us_data *ss,block_dev_desc_t
|
|||
/* Sony USM256E */
|
||||
(dev->descriptor.idVendor == 0x054c &&
|
||||
dev->descriptor.idProduct == 0x019e)
|
||||
|
||||
||
|
||||
/* USB007 Mini-USB2 Flash Drive */
|
||||
(dev->descriptor.idVendor == 0x066f &&
|
||||
|
@ -1182,10 +1251,13 @@ int usb_stor_get_info(struct usb_device *dev,struct us_data *ss,block_dev_desc_t
|
|||
|
||||
perq = usb_stor_buf[0];
|
||||
modi = usb_stor_buf[1];
|
||||
|
||||
if ((perq & 0x1f) == 0x1f) {
|
||||
return 0; /* skip unknown devices */
|
||||
/* skip unknown devices */
|
||||
return 0;
|
||||
}
|
||||
if((modi&0x80) == 0x80) {/* drive is removable */
|
||||
if ((modi&0x80) == 0x80) {
|
||||
/* drive is removable */
|
||||
dev_desc->removable = 1;
|
||||
}
|
||||
memcpy(&dev_desc->vendor[0], &usb_stor_buf[8], 8);
|
||||
|
@ -1195,16 +1267,20 @@ int usb_stor_get_info(struct usb_device *dev,struct us_data *ss,block_dev_desc_t
|
|||
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);
|
||||
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]);
|
||||
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]);
|
||||
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;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
pccb->pdata = (unsigned char *)&cap[0];
|
||||
|
@ -1214,7 +1290,8 @@ int usb_stor_get_info(struct usb_device *dev,struct us_data *ss,block_dev_desc_t
|
|||
cap[0] = 2880;
|
||||
cap[1] = 0x200;
|
||||
}
|
||||
USB_STOR_PRINTF("Read Capacity returns: 0x%lx, 0x%lx\n",cap[0],cap[1]);
|
||||
USB_STOR_PRINTF("Read Capacity returns: 0x%lx, 0x%lx\n", cap[0],
|
||||
cap[1]);
|
||||
#if 0
|
||||
if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
|
||||
cap[0] >>= 16;
|
||||
|
@ -1226,7 +1303,8 @@ int usb_stor_get_info(struct usb_device *dev,struct us_data *ss,block_dev_desc_t
|
|||
cap[0] += 1;
|
||||
capacity = &cap[0];
|
||||
blksz = &cap[1];
|
||||
USB_STOR_PRINTF("Capacity = 0x%lx, blocksz = 0x%lx\n",*capacity,*blksz);
|
||||
USB_STOR_PRINTF("Capacity = 0x%lx, blocksz = 0x%lx\n",
|
||||
*capacity, *blksz);
|
||||
dev_desc->lba = *capacity;
|
||||
dev_desc->blksz = *blksz;
|
||||
dev_desc->type = perq;
|
||||
|
|
Loading…
Add table
Reference in a new issue