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:
parent
73c8640e93
commit
127e10842b
|
@ -642,6 +642,28 @@ int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (strcmp(argv[1], "write") == 0) {
|
||||||
|
if (usb_stor_curr_dev < 0) {
|
||||||
|
printf("no current device selected\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (argc == 5) {
|
||||||
|
unsigned long addr = simple_strtoul(argv[2], NULL, 16);
|
||||||
|
unsigned long blk = simple_strtoul(argv[3], NULL, 16);
|
||||||
|
unsigned long cnt = simple_strtoul(argv[4], NULL, 16);
|
||||||
|
unsigned long n;
|
||||||
|
printf("\nUSB write: device %d block # %ld, count %ld"
|
||||||
|
" ... ", usb_stor_curr_dev, blk, cnt);
|
||||||
|
stor_dev = usb_stor_get_dev(usb_stor_curr_dev);
|
||||||
|
n = stor_dev->block_write(usb_stor_curr_dev, blk, cnt,
|
||||||
|
(ulong *)addr);
|
||||||
|
printf("%ld blocks write: %s\n", n,
|
||||||
|
(n == cnt) ? "OK" : "ERROR");
|
||||||
|
if (n == cnt)
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (strncmp(argv[1], "dev", 3) == 0) {
|
if (strncmp(argv[1], "dev", 3) == 0) {
|
||||||
if (argc == 3) {
|
if (argc == 3) {
|
||||||
int dev = (int)simple_strtoul(argv[2], NULL, 10);
|
int dev = (int)simple_strtoul(argv[2], NULL, 10);
|
||||||
|
@ -687,6 +709,8 @@ U_BOOT_CMD(
|
||||||
" devices\n"
|
" devices\n"
|
||||||
"usb read addr blk# cnt - read `cnt' blocks starting at block `blk#'\n"
|
"usb read addr blk# cnt - read `cnt' blocks starting at block `blk#'\n"
|
||||||
" to memory address `addr'"
|
" to memory address `addr'"
|
||||||
|
"usb write addr blk# cnt - write `cnt' blocks starting at block `blk#'\n"
|
||||||
|
" from memory address `addr'"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -168,6 +168,8 @@ int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
|
||||||
struct us_data *ss);
|
struct us_data *ss);
|
||||||
unsigned long usb_stor_read(int device, unsigned long blknr,
|
unsigned long usb_stor_read(int device, unsigned long blknr,
|
||||||
unsigned long blkcnt, void *buffer);
|
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);
|
struct usb_device * usb_get_dev_index(int index);
|
||||||
void uhci_show_temp_int_td(void);
|
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].dev = i;
|
||||||
usb_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
|
usb_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
|
||||||
usb_dev_desc[i].block_read = usb_stor_read;
|
usb_dev_desc[i].block_read = usb_stor_read;
|
||||||
|
usb_dev_desc[i].block_write = usb_stor_write;
|
||||||
}
|
}
|
||||||
|
|
||||||
usb_max_devs = 0;
|
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);
|
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
|
#ifdef CONFIG_USB_BIN_FIXUP
|
||||||
/*
|
/*
|
||||||
|
@ -1065,6 +1084,86 @@ retry_it:
|
||||||
return blkcnt;
|
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 */
|
/* Probe to see if a new device is actually a Storage device */
|
||||||
int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
|
int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
|
||||||
|
|
Loading…
Reference in New Issue