lkml.org 
[lkml]   [2005]   [Aug]   [13]   [last100]   RSS Feed
Views: [more markup]  [less markup]  [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
DateSat, 13 Aug 2005 18:36:58 +0100
FromJon Escombe <>
Subject[patch] libata passthrough - return register data from HDIO_* commands
Here is a first attempt at a patch to return register data from the 
libata passthrough HDIO ioctl handlers, I needed this as the ATA 'unload 
immediate' command returns the success in the lbal register. This patch 
applies on top of 2.6.12 and Jeffs 2.6.12-git4-passthru1.patch. 
(Apologies, but Thunderbird appears to have replaced the tabs with spaces).

One oddity is that the sr_result field is correctly being set in 
ata_gen_ata_desc_sense(), however the high word is different when we're 
back in the ioctl hander. I've coded round this for now by only checking 
the low word, but this needs more investigation.

Jeff, could this functionality be incorporated into the pasthrough patch 
when complete?

Regards,
Jon.

--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -89,6 +89,7 @@
     u8 args[4], *argbuf = NULL;
     int argsize = 0;
     struct scsi_request *sreq;
+    unsigned char *sb, *desc;
 
     if (NULL == (void *)arg)
         return -EINVAL;
@@ -100,6 +101,9 @@
     if (!sreq)
         return -EINTR;
 
+    sb = sreq->sr_sense_buffer;
+    desc = sb + 8;
+
     memset(scsi_cmd, 0, sizeof(scsi_cmd));
 
     if (args[3]) {
@@ -109,12 +113,12 @@
             return -ENOMEM;
 
         scsi_cmd[1]  = (4 << 1); /* PIO Data-in */
-        scsi_cmd[2]  = 0x0e;     /* no off.line or cc, read from dev,
+        scsi_cmd[2]  = 0x2e;     /* no off.line, read from dev, request cc
                                     block count in sector count field */
         sreq->sr_data_direction = DMA_FROM_DEVICE;
     } else {
         scsi_cmd[1]  = (3 << 1); /* Non-data */
-        /* scsi_cmd[2] is already 0 -- no off.line, cc, or data xfer */
+        scsi_cmd[2]  = 0x20;     /* no off.line or data xfer, request 
check condtion */
         sreq->sr_data_direction = DMA_NONE;
     }
 
@@ -135,16 +139,24 @@
        from scsi_ioctl_send_command() for default case... */
     scsi_wait_req(sreq, scsi_cmd, argbuf, argsize, (10*HZ), 5);
 
-    if (sreq->sr_result) {
+    if ((sreq->sr_result & 0xFFFF) != SAM_STAT_CHECK_CONDITION) {
         rc = -EIO;
         goto error;
     }
 
-    /* Need code to retrieve data from check condition? */
+    /* Retrieve data from check condition */
+    args[1] = desc[3];
+    args[2] = desc[5];
+    args[3] = desc[7];
+    args[4] = desc[9];
+    args[5] = desc[11];
+    args[0] = desc[13];
 
     if ((argbuf)
      && copy_to_user((void *)(arg + sizeof(args)), argbuf, argsize))
         rc = -EFAULT;
+    if (copy_to_user(arg, args, sizeof(args)))
+        rc = -EFAULT;
 error:
     scsi_release_request(sreq);
 
@@ -171,6 +183,7 @@
     u8 scsi_cmd[MAX_COMMAND_SIZE];
     u8 args[7];
     struct scsi_request *sreq;
+    unsigned char *sb, *desc;
 
     if (NULL == (void *)arg)
         return -EINVAL;
@@ -181,7 +194,7 @@
     memset(scsi_cmd, 0, sizeof(scsi_cmd));
     scsi_cmd[0]  = ATA_16;
     scsi_cmd[1]  = (3 << 1); /* Non-data */
-    /* scsi_cmd[2] is already 0 -- no off.line, cc, or data xfer */
+    scsi_cmd[2]  = 0x20;     /* no off.line, or data xfer, request cc */
     scsi_cmd[4]  = args[1];
     scsi_cmd[6]  = args[2];
     scsi_cmd[8]  = args[3];
@@ -195,18 +208,29 @@
         goto error;
     }
 
+    sb = sreq->sr_sense_buffer;
+    desc = sb + 8;
+
     sreq->sr_data_direction = DMA_NONE;
     /* Good values for timeout and retries?  Values below
        from scsi_ioctl_send_command() for default case... */
     scsi_wait_req(sreq, scsi_cmd, NULL, 0, (10*HZ), 5);
 
-    if (sreq->sr_result) {
+    if ((sreq->sr_result & 0xFFFF) != SAM_STAT_CHECK_CONDITION) {
         rc = -EIO;
         goto error;
     }
 
-    /* Need code to retrieve data from check condition? */
+    /* Retrieve data from check condition */
+    args[1] = desc[3];
+    args[2] = desc[5];
+    args[3] = desc[7];
+    args[4] = desc[9];
+    args[5] = desc[11];
+    args[0] = desc[13];
 
+    if (copy_to_user(arg, args, sizeof(args)))
+        rc = -EFAULT;
 error:
     scsi_release_request(sreq);
     return rc;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-08-13 19:41    [W:0.318 / U:0.050 seconds]
©2003-2008 Jasper Spaans