aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2011-11-16 13:02:47 +0100
committerKevin O'Connor <kevin@koconnor.net>2011-11-17 21:20:30 -0500
commitddb8cebd80573e72e2f43fbd6a948fcfcef02f0c (patch)
treef2a8ad62bec31b43cab7cfbc88732610799e9e25
parent092fc3502871e393845a740a041bc76102811a46 (diff)
downloadseabios-ddb8cebd80573e72e2f43fbd6a948fcfcef02f0c.tar.gz
usb-msc: support WRITE commands
Writes only require building the CDB and some care with the direction in the USB packet. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--src/blockcmd.c12
-rw-r--r--src/blockcmd.h1
-rw-r--r--src/usb-msc.c12
3 files changed, 19 insertions, 6 deletions
diff --git a/src/blockcmd.c b/src/blockcmd.c
index c1277290..f5e2ce3f 100644
--- a/src/blockcmd.c
+++ b/src/blockcmd.c
@@ -91,3 +91,15 @@ cdb_read(struct disk_op_s *op)
cmd.count = htons(op->count);
return cdb_cmd_data(op, &cmd, GET_GLOBAL(op->drive_g->blksize));
}
+
+// Write sectors.
+int
+cdb_write(struct disk_op_s *op)
+{
+ struct cdb_rwdata_10 cmd;
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.command = CDB_CMD_WRITE_10;
+ cmd.lba = htonl(op->lba);
+ cmd.count = htons(op->count);
+ return cdb_cmd_data(op, &cmd, GET_GLOBAL(op->drive_g->blksize));
+}
diff --git a/src/blockcmd.h b/src/blockcmd.h
index 49921b05..84ab6598 100644
--- a/src/blockcmd.h
+++ b/src/blockcmd.h
@@ -75,5 +75,6 @@ int cdb_test_unit_ready(struct disk_op_s *op);
int cdb_read_capacity(struct disk_op_s *op, struct cdbres_read_capacity *data);
int cdb_inquiry(struct disk_op_s *op, struct cdbres_inquiry *data);
int cdb_read(struct disk_op_s *op);
+int cdb_write(struct disk_op_s *op);
#endif // blockcmd.h
diff --git a/src/usb-msc.c b/src/usb-msc.c
index 37644814..068e18ce 100644
--- a/src/usb-msc.c
+++ b/src/usb-msc.c
@@ -73,13 +73,13 @@ usb_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize)
u32 bytes = blocksize * op->count;
struct cbw_s cbw;
memset(&cbw, 0, sizeof(cbw));
+ memcpy(cbw.CBWCB, cdbcmd, USB_CDB_SIZE);
cbw.dCBWSignature = CBW_SIGNATURE;
cbw.dCBWTag = 999; // XXX
cbw.dCBWDataTransferLength = bytes;
- cbw.bmCBWFlags = USB_DIR_IN; // XXX
+ cbw.bmCBWFlags = (cbw.CBWCB[0] == CDB_CMD_WRITE_10) ? USB_DIR_OUT : USB_DIR_IN;
cbw.bCBWLUN = 0; // XXX
cbw.bCBWCBLength = USB_CDB_SIZE;
- memcpy(cbw.CBWCB, cdbcmd, USB_CDB_SIZE);
// Transfer cbw to device.
int ret = usb_msc_send(udrive_g, USB_DIR_OUT
@@ -87,9 +87,9 @@ usb_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize)
if (ret)
goto fail;
- // Transfer data from device.
+ // Transfer data to/from device.
if (bytes) {
- ret = usb_msc_send(udrive_g, USB_DIR_IN, op->buf_fl, bytes);
+ ret = usb_msc_send(udrive_g, cbw.bmCBWFlags, op->buf_fl, bytes);
if (ret)
goto fail;
}
@@ -131,9 +131,9 @@ process_usb_op(struct disk_op_s *op)
switch (op->command) {
case CMD_READ:
return cdb_read(op);
- case CMD_FORMAT:
case CMD_WRITE:
- return DISK_RET_EWRITEPROTECT;
+ return cdb_write(op);
+ case CMD_FORMAT:
case CMD_RESET:
case CMD_ISREADY:
case CMD_VERIFY: