Hi Remy, This patch looks straight forward to me as it would be useful for generic USB file system write support in future (FYI i was able to write kernel image to raw partition & boot from it). I would really appreciate any feedback or suggestions on this.
Thanks Mahavir On Mon, 2009-11-02 at 22:52 -0800, Mahavir Jain wrote: > 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 <mj...@marvell.com> > --- > common/cmd_usb.c | 24 ++++++++++++ > common/usb_storage.c | 99 > ++++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 123 insertions(+), 0 deletions(-) > > diff --git a/common/cmd_usb.c b/common/cmd_usb.c > index 7b8ee6b..1acb6fc 100644 > --- a/common/cmd_usb.c > +++ b/common/cmd_usb.c > @@ -642,6 +642,28 @@ int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char > *argv[]) > 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 (argc == 3) { > int dev = (int)simple_strtoul(argv[2], NULL, 10); > @@ -687,6 +709,8 @@ U_BOOT_CMD( > " devices\n" > "usb read addr blk# cnt - read `cnt' blocks starting at block `blk#'\n" > " to memory address `addr'" > + "usb write addr blk# cnt - write `cnt' blocks starting at block > `blk#'\n" > + " from memory address `addr'" > ); > > > diff --git a/common/usb_storage.c b/common/usb_storage.c > index 19613f2..ed5b3f3 100644 > --- a/common/usb_storage.c > +++ b/common/usb_storage.c > @@ -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, _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot