+unsigned long usb_stor_write(int device, lbaint_t blknr,
+ lbaint_t blkcnt, const void *buffer)
+{
+ lbaint_t start, blks;
+ uintptr_t buf_addr;
+ unsigned short smallblks;
+ struct usb_device *dev;
+ struct us_data *ss;
+ int retry, i;
+ ccb *srb = &usb_ccb;
+
+ if (blkcnt == 0)
+ return 0;
+
+ device &= 0xff;
+ /* Setup device */
+ debug("\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;
+ }
+ ss = (struct us_data *)dev->privptr;
+
+ usb_disable_asynch(1); /* asynch transfer not allowed */
+
+ srb->lun = usb_dev_desc[device].lun;
+ buf_addr = (unsigned long)buffer;
+ start = blknr;
+ blks = blkcnt;
+
+ debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF
+ " 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_XFER_BLK)
+ smallblks = USB_MAX_XFER_BLK;
+ else
+ smallblks = (unsigned short) blks;
+retry_it:
+ if (smallblks == USB_MAX_XFER_BLK)
+ usb_show_progress();
+ srb->datalen = usb_dev_desc[device].blksz * smallblks;
+ srb->pdata = (unsigned char *)buf_addr;
+ if (usb_write_10(srb, ss, start, smallblks)) {
+ debug("Write ERROR\n");
+ usb_request_sense(srb, ss);
+ if (retry--)
+ goto retry_it;
+ blkcnt -= blks;
+ break;
+ }
+ start += smallblks;
+ blks -= smallblks;
+ buf_addr += srb->datalen;
+ } while (blks != 0);
+ ss->flags &= ~USB_READY;
+
+ debug("usb_write: end startblk " LBAF ", blccnt %x buffer %lx\n",
+ start, smallblks, buf_addr);
+
+ usb_disable_asynch(0); /* asynch transfer allowed */
+ if (blkcnt >= USB_MAX_XFER_BLK)
+ debug("\n");
+ return blkcnt;
+
+}