[U-Boot] [PATCH] 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 --- 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,

Hi,
Any feedback or comments 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 mjain@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,

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 mjain@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,

Hi,
2009/11/19 Mahavir Jain mjain@marvell.com:
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.
Applied to U-boot-usb next.
Thanks.
Remy
participants (2)
-
Mahavir Jain
-
Remy Bohmer