|
|
|
@ -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; |
|
|
|
|