diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2011-11-16 13:02:47 +0100 |
---|---|---|
committer | Kevin O'Connor <kevin@koconnor.net> | 2011-11-17 21:20:30 -0500 |
commit | ddb8cebd80573e72e2f43fbd6a948fcfcef02f0c (patch) | |
tree | f2a8ad62bec31b43cab7cfbc88732610799e9e25 /src | |
parent | 092fc3502871e393845a740a041bc76102811a46 (diff) | |
download | seabios-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>
Diffstat (limited to 'src')
-rw-r--r-- | src/blockcmd.c | 12 | ||||
-rw-r--r-- | src/blockcmd.h | 1 | ||||
-rw-r--r-- | src/usb-msc.c | 12 |
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: |