1
0
mirror of https://xff.cz/git/u-boot/ synced 2025-09-01 08:42:12 +02:00

usb: write command for RAW partition.

This patch implements write support to usb device with raw partition.
It will be useful for filesystem write support to usb device from
u-boot in future.

Tested with writing kernel image to raw usb disk & booting with usb
read command into ram.

[Note:  run usb part to get info about start sector & number of
sectors on a partition for usb write operation.]

Signed-off-by: Mahavir Jain <mjain@marvell.com>
This commit is contained in:
Mahavir Jain
2009-11-03 12:22:10 +05:30
committed by Remy Bohmer
parent 73c8640e93
commit 127e10842b
2 changed files with 123 additions and 0 deletions

View File

@@ -168,6 +168,8 @@ 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);
unsigned long usb_stor_write(int device, unsigned long blknr,
unsigned long blkcnt, const void *buffer);
struct usb_device * usb_get_dev_index(int index);
void uhci_show_temp_int_td(void);
@@ -227,6 +229,7 @@ int usb_stor_scan(int mode)
usb_dev_desc[i].dev = i;
usb_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
usb_dev_desc[i].block_read = usb_stor_read;
usb_dev_desc[i].block_write = usb_stor_write;
}
usb_max_devs = 0;
@@ -964,6 +967,22 @@ static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
return ss->transport(srb, ss);
}
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[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;
USB_STOR_PRINTF("write10: start %lx blocks %x\n", start, blocks);
return ss->transport(srb, ss);
}
#ifdef CONFIG_USB_BIN_FIXUP
/*
@@ -1065,6 +1084,86 @@ retry_it:
return blkcnt;
}
#define USB_MAX_WRITE_BLK 20
unsigned long usb_stor_write(int device, unsigned long blknr,
unsigned long blkcnt, const void *buffer)
{
unsigned long start, blks, buf_addr;
unsigned short smallblks;
struct usb_device *dev;
int retry, i;
ccb *srb = &usb_ccb;
if (blkcnt == 0)
return 0;
device &= 0xff;
/* Setup device */
USB_STOR_PRINTF("\nusb_write: dev %d \n", device);
dev = NULL;
for (i = 0; i < USB_MAX_DEVICE; i++) {
dev = usb_get_dev_index(i);
if (dev == NULL)
return 0;
if (dev->devnum == usb_dev_desc[device].target)
break;
}
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)) {
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_write: dev %d startblk %lx, blccnt %lx"
" buffer %lx\n", device, start, blks, buf_addr);
do {
/* If write fails retry for max retry count else
* return with number of blocks written successfully.
*/
retry = 2;
srb->pdata = (unsigned char *)buf_addr;
if (blks > USB_MAX_WRITE_BLK)
smallblks = USB_MAX_WRITE_BLK;
else
smallblks = (unsigned short) blks;
retry_it:
if (smallblks == USB_MAX_WRITE_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_STOR_PRINTF("Write ERROR\n");
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_STOR_PRINTF("usb_write: end startblk %lx, blccnt %x buffer %lx\n",
start, smallblks, buf_addr);
usb_disable_asynch(0); /* asynch transfer allowed */
if (blkcnt >= USB_MAX_WRITE_BLK)
printf("\n");
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,