]> xenbits.xensource.com Git - seabios.git/commitdiff
Use OUT mode for all zero byte "scsi" transfers.
authorKevin O'Connor <kevin@koconnor.net>
Thu, 15 Mar 2012 01:27:45 +0000 (21:27 -0400)
committerKevin O'Connor <kevin@koconnor.net>
Thu, 15 Mar 2012 01:27:45 +0000 (21:27 -0400)
Some devices can get confused if asked to "read" data during a zero
byte transfer, so consider these transfers as "writes".  (Reported by
Steve Goodrich.)

Also, extract out the code to determine the transfer direction into
cdb_is_read().

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
src/blockcmd.c
src/blockcmd.h
src/usb-msc.c
src/virtio-scsi.c

index 8d881a5d1e9f17b6e7a4b70cbeccbc0d56b80e3c..2dda04db1d45e13da1d89db596174cba6bca2178 100644 (file)
@@ -35,6 +35,13 @@ cdb_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize)
     }
 }
 
+// Determine if the command is a request to pull data from the device
+int
+cdb_is_read(u8 *cdbcmd, u16 blocksize)
+{
+    return blocksize && cdbcmd[0] != CDB_CMD_WRITE_10;
+}
+
 int
 scsi_is_ready(struct disk_op_s *op)
 {
index ccfeeafdd830afb89068cc3018ab1826df765d8f..8459d3e4a048d069c4a64d00c56f2d57680049d1 100644 (file)
@@ -100,6 +100,7 @@ struct cdbres_mode_sense_geom {
 } PACKED;
 
 // blockcmd.c
+int cdb_is_read(u8 *cdbcmd, u16 blocksize);
 int cdb_get_inquiry(struct disk_op_s *op, struct cdbres_inquiry *data);
 int cdb_get_sense(struct disk_op_s *op, struct cdbres_request_sense *data);
 int cdb_test_unit_ready(struct disk_op_s *op);
index dadb9caa0083282d6f23e7d3d0d4425f39b9d4a0..c53a1f508be999754ec961400efd58a9faa56989 100644 (file)
@@ -77,13 +77,13 @@ usb_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize)
     cbw.dCBWSignature = CBW_SIGNATURE;
     cbw.dCBWTag = 999; // XXX
     cbw.dCBWDataTransferLength = bytes;
-    cbw.bmCBWFlags = (cbw.CBWCB[0] == CDB_CMD_WRITE_10) ? USB_DIR_OUT : USB_DIR_IN;
+    cbw.bmCBWFlags = cdb_is_read(cdbcmd, blocksize) ? USB_DIR_IN : USB_DIR_OUT;
     cbw.bCBWLUN = 0; // XXX
     cbw.bCBWCBLength = USB_CDB_SIZE;
 
     // Transfer cbw to device.
     int ret = usb_msc_send(udrive_g, USB_DIR_OUT
-                            , MAKE_FLATPTR(GET_SEG(SS), &cbw), sizeof(cbw));
+                           , MAKE_FLATPTR(GET_SEG(SS), &cbw), sizeof(cbw));
     if (ret)
         goto fail;
 
index 3c594385b23666549ab3c9b83ba5792d33976ea9..50339d70f264f9d2408bfbd9d80601512dc10d80 100644 (file)
@@ -31,7 +31,7 @@ struct virtio_lun_s {
 
 static int
 virtio_scsi_cmd(u16 ioaddr, struct vring_virtqueue *vq, struct disk_op_s *op,
-                void *cdbcmd, u16 target, u16 lun, u32 len)
+                void *cdbcmd, u16 target, u16 lun, u16 blocksize)
 {
     struct virtio_scsi_req_cmd req;
     struct virtio_scsi_resp_cmd resp;
@@ -44,7 +44,8 @@ virtio_scsi_cmd(u16 ioaddr, struct vring_virtqueue *vq, struct disk_op_s *op,
     req.lun[3] = (lun & 0xff);
     memcpy(req.cdb, cdbcmd, 16);
 
-    int datain = (req.cdb[0] != CDB_CMD_WRITE_10);
+    u32 len = op->count * blocksize;
+    int datain = cdb_is_read(cdbcmd, blocksize);
     int data_idx = (datain ? 2 : 1);
     int out_num = (datain ? 1 : 2);
     int in_num = (len ? 3 : 2) - out_num;
@@ -89,7 +90,7 @@ virtio_scsi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize)
     return virtio_scsi_cmd(GET_GLOBAL(vlun->ioaddr),
                            GET_GLOBAL(vlun->vq), op, cdbcmd,
                            GET_GLOBAL(vlun->target), GET_GLOBAL(vlun->lun),
-                           blocksize * op->count);
+                           blocksize);
 }
 
 static int