📄 usb_storage.c
字号:
if(ss->transport(srb,ss) == USB_STOR_TRANSPORT_GOOD)
{ return 0;
}
usb_request_sense (srb, ss);
os_dly_wait (10);
}while(retries--);
return -1;
}
static int usb_read_capacity(ccb *srb,struct us_data *ss)
{
int retry;
retry = 3; /* retries */
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)
{ return 0;
}
} while(retry--);
return -1;
}
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;
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;
srb->cmd[5] = ((unsigned char) (start))&0xff;
srb->cmd[7] = ((unsigned char) (blocks>>8))&0xff;
srb->cmd[8] = (unsigned char) blocks & 0xff;
srb->cmdlen = 12;
return ss->transport(srb,ss);
}
#define USB_MAX_READ_BLK 20
unsigned long usb_stor_read(int device, unsigned long blknr, unsigned long blkcnt, void *buffer)
{
unsigned long start,blks, buf_addr;
unsigned short smallblks;
struct usb_device *dev;
int retry;
ccb *srb = &usb_ccb;
if (blkcnt == 0) { return 0; }
device &= 0xff;
/* Setup device */
dev = usb_device_find(usb_dev_desc[device].target);
if(dev == NULL) return 0;
usb_disable_asynch(1); /* asynch transfer not allowed */
srb->lun = usb_dev_desc[device].lun;
buf_addr = (unsigned long)buffer;
start = blknr;
blks = blkcnt;
if(usb_test_unit_ready(srb,(struct us_data *)dev->privptr))
{ return 0;
}
do {
retry = 2;
srb->pdata = (unsigned char *)buf_addr;
if(blks > USB_MAX_READ_BLK)
{ smallblks = USB_MAX_READ_BLK;
}
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))
{
usb_request_sense(srb,(struct us_data *)dev->privptr);
if(retry--) goto retry_it;
blkcnt -= blks;
break;
}
start += smallblks;
blks -= smallblks;
buf_addr += srb->datalen;
} while(blks != 0);
usb_disable_asynch(0); /* asynch transfer allowed */
return(blkcnt);
}
static int usb_write_10(ccb *srb, struct us_data *ss, unsigned long start, unsigned short blocks)
{
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;
srb->cmd[5] = ((unsigned char) (start))&0xff;
srb->cmd[7] = ((unsigned char) (blocks>>8))&0xff;
srb->cmd[8] = (unsigned char) blocks & 0xff;
srb->cmdlen = 12;
return ss->transport(srb,ss);
}
#define USB_MAX_READ_BLK 20
unsigned long usb_stor_write(int device, unsigned long blknr, unsigned long blkcnt, void *buffer)
{
unsigned long start,blks, buf_addr;
unsigned short smallblks;
struct usb_device *dev;
int retry;
ccb *srb = &usb_ccb;
if (blkcnt == 0) { return 0; }
device &= 0xff;
/* Setup device */
dev = usb_device_find(usb_dev_desc[device].target);
if(dev == NULL) return 0;
usb_disable_asynch(1); /* asynch transfer not allowed */
srb->lun = usb_dev_desc[device].lun;
buf_addr = (unsigned long)buffer;
start = blknr;
blks = blkcnt;
if(usb_test_unit_ready(srb,(struct us_data *)dev->privptr))
{ return 0;
}
do {
retry = 2;
srb->pdata = (unsigned char *)buf_addr;
if(blks > USB_MAX_READ_BLK)
{ smallblks = USB_MAX_READ_BLK;
}
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_write_10(srb, (struct us_data *)dev->privptr, start, smallblks))
{
usb_request_sense(srb,(struct us_data *)dev->privptr);
if(retry--) goto retry_it;
blkcnt -= blks;
break;
}
start += smallblks;
blks -= smallblks;
buf_addr += srb->datalen;
} while(blks != 0);
usb_disable_asynch(0); /* asynch transfer allowed */
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)
{
struct usb_interface_descriptor *iface;
int i;
unsigned int flags = 0;
int protocol = 0;
int subclass = 0;
/* let's examine the device now */
iface = &dev->config.if_desc[ifnum];
/* if it's not a mass storage, we go no further */
if((dev->descriptor.bDeviceClass != 0) ||
(iface->bInterfaceClass != USB_CLASS_MASS_STORAGE) ||
(iface->bInterfaceSubClass < US_SC_MIN) ||
(iface->bInterfaceSubClass > US_SC_MAX))
{ return 0;
}
memset(ss, 0, sizeof(struct us_data));
/* At this point, we know we've got a live one */
/* Initialize the us_data structure with some useful info */
ss->flags = flags;
ss->ifnum = ifnum;
ss->pusb_dev = dev;
ss->attention_done = 0;
/* If the device has subclass and protocol, then use that. Otherwise,
* take data from the specific interface.
*/
if (subclass)
{
ss->subclass = subclass;
ss->protocol = protocol;
}
else
{
ss->subclass = iface->bInterfaceSubClass;
ss->protocol = iface->bInterfaceProtocol;
}
/* set the handler pointers based on the protocol */
switch (ss->protocol) {
case US_PR_CB:
ss->transport = usb_stor_CB_transport;
ss->transport_reset = usb_stor_CB_reset;
break;
case US_PR_CBI:
ss->transport = usb_stor_CB_transport;
ss->transport_reset = usb_stor_CB_reset;
break;
case US_PR_BULK:
ss->transport = usb_stor_BBB_transport;
ss->transport_reset = usb_stor_BBB_reset;
break;
default:
return 0;
}
/*
* We are expecting a minimum of 2 endpoints - in and out (bulk).
* An optional interrupt is OK (necessary for CBI protocol).
* We will ignore any others.
*/
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].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 & USB_ENDPOINT_NUMBER_MASK; }
}
/* is it an interrupt endpoint? */
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;
}
}
/* Do some basic sanity checks, and bail if we find a problem */
usb_set_interface(dev, iface->bInterfaceNumber, 0); /* 有些设备不支持接口设置 */
if((!ss->ep_in) || (!ss->ep_out) ||
(ss->protocol == US_PR_CBI && ss->ep_int == 0))
{
return 0;
}
/* set class specific stuff */
/* We only handle certain protocols. Currently, these are
* the only ones.
* The SFF8070 accepts the requests used in u-boot
*/
if((ss->subclass != US_SC_UFI) && (ss->subclass != US_SC_SCSI) && (ss->subclass != US_SC_8070))
{
return 0;
}
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);
dev->irq_handle=usb_stor_irq;
}
dev->privptr = (void *)ss;
return 1;
}
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;
unsigned long *capacity,*blksz;
ccb *pccb = &usb_ccb;
unsigned char *usb_stor_buf;
usb_stor_buf = malloc(512);
if(usb_stor_buf == NULL) return -1;
memset(usb_stor_buf, 0, sizeof(usb_stor_buf));
/* 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))
)
{ }
else
{ ss->transport_reset(ss);
}
pccb->pdata = usb_stor_buf;
dev_desc->target = dev->devnum;
pccb->lun = dev_desc->lun;
if(usb_inquiry(pccb, ss))
{ free( usb_stor_buf );
return -1;
}
perq = usb_stor_buf[0];
modi = usb_stor_buf[1];
if((perq & 0x1f) == 0x1f)
{ free( usb_stor_buf );
return 0; /* skip unknown devices */
}
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);
free( usb_stor_buf );
dev_desc->vendor[8] = 0;
dev_desc->product[16] = 0;
dev_desc->revision[4] = 0;
if(usb_test_unit_ready(pccb,ss))
{
if(dev_desc->removable == 1)
{ dev_desc->type = perq;
return 1;
}
else
{ return 0; }
}
cap = (unsigned long *)malloc(8);
if(cap == NULL) return -1;
pccb->pdata = (unsigned char *)&cap[0];
memset(pccb->pdata,0,8);
if(usb_read_capacity(pccb,ss) != 0)
{
cap[0] = 2880;
cap[1] = 0x200;
}
cap[0] = ((unsigned long)(
(((unsigned long)(cap[0]) & (unsigned long)0x000000ffUL) << 24) |
(((unsigned long)(cap[0]) & (unsigned long)0x0000ff00UL) << 8) |
(((unsigned long)(cap[0]) & (unsigned long)0x00ff0000UL) >> 8) |
(((unsigned long)(cap[0]) & (unsigned long)0xff000000UL) >> 24) ));
cap[1] = ((unsigned long)(
(((unsigned long)(cap[1]) & (unsigned long)0x000000ffUL) << 24) |
(((unsigned long)(cap[1]) & (unsigned long)0x0000ff00UL) << 8) |
(((unsigned long)(cap[1]) & (unsigned long)0x00ff0000UL) >> 8) |
(((unsigned long)(cap[1]) & (unsigned long)0xff000000UL) >> 24) ));
/* this assumes bigendian! */
cap[0] += 1;
capacity = &cap[0];
blksz = &cap[1];
free(cap);
dev_desc->lba = *capacity;
dev_desc->blksz = *blksz;
dev_desc->type = perq;
//init_part(dev_desc);
dev_desc->part_type = PART_TYPE_DOS; /* 直接标记, 不检查, 由 FAT_initfiles 检查 */
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -