Messages in this thread Patch in this message | | | Date | Mon, 15 Aug 2005 23:11:02 +0100 | From | Jon Escombe <> | Subject | Re: [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?
I'd failed to realise that scsi_finish_command() sets the high byte of the result field to DRIVER_SENSE when there is sense data. Patch updated to reflect this...
Haven't had any feedback on the patch itself - but this now does what I wanted it do to. (I can't find a way to make Thunderbird retain tabs in the message body, so sending as an attachment).
Regards, Jon.
______________________________________________________________ Email via Mailtraq4Free from Enstar (www.mailtraqdirect.co.uk)--- 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 == ((DRIVER_SENSE << 24) + 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 == ((DRIVER_SENSE << 24) + 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;
| |