* T10/04-262 ATA pass thru - another patch.
@ 2004-10-05 23:20 Andy Warner
2004-10-06 3:10 ` Jeff Garzik
2004-10-07 3:38 ` Jeff Garzik
0 siblings, 2 replies; 4+ messages in thread
From: Andy Warner @ 2004-10-05 23:20 UTC (permalink / raw)
To: linux-ide, Jeff Garzik, John Linville, linville, Pat LaVarre,
Mark Lord
[-- Attachment #1: Type: text/plain, Size: 364 bytes --]
Attached are two patchfiles, which implement the following
features of libata ATA pass-thru:
o check condition processing
o 12-byte CDB handling
patch.041005 can be applied to vanilla libata-2.6 trees
patch-dev.041005 can be applied to libata-dev-2.6 trees
Questions/problems -> me.
--
andyw@pobox.com
Andy Warner Voice: (612) 801-8549 Fax: (208) 575-5634
[-- Attachment #2: patch.041005 --]
[-- Type: text/plain, Size: 9559 bytes --]
===== drivers/scsi/libata-core.c 1.100 vs edited =====
--- 1.100/drivers/scsi/libata-core.c 2004-09-16 01:45:15 -05:00
+++ edited/drivers/scsi/libata-core.c 2004-10-05 16:40:35 -05:00
@@ -321,10 +321,10 @@
tf->lbam = inb(ioaddr->lbam_addr);
tf->lbah = inb(ioaddr->lbah_addr);
tf->device = inb(ioaddr->device_addr);
+ tf->feature = inb(ioaddr->error_addr);
if (tf->flags & ATA_TFLAG_LBA48) {
outb(tf->ctl | ATA_HOB, ioaddr->ctl_addr);
- tf->hob_feature = inb(ioaddr->error_addr);
tf->hob_nsect = inb(ioaddr->nsect_addr);
tf->hob_lbal = inb(ioaddr->lbal_addr);
tf->hob_lbam = inb(ioaddr->lbam_addr);
@@ -353,10 +353,10 @@
tf->lbam = readb((void __iomem *)ioaddr->lbam_addr);
tf->lbah = readb((void __iomem *)ioaddr->lbah_addr);
tf->device = readb((void __iomem *)ioaddr->device_addr);
+ tf->feature = readb((void __iomem *)ioaddr->error_addr);
if (tf->flags & ATA_TFLAG_LBA48) {
writeb(tf->ctl | ATA_HOB, (void __iomem *) ap->ioaddr.ctl_addr);
- tf->hob_feature = readb((void __iomem *)ioaddr->error_addr);
tf->hob_nsect = readb((void __iomem *)ioaddr->nsect_addr);
tf->hob_lbal = readb((void __iomem *)ioaddr->lbal_addr);
tf->hob_lbam = readb((void __iomem *)ioaddr->lbam_addr);
@@ -1946,7 +1946,7 @@
sg->offset = (unsigned long) buf & ~PAGE_MASK;
sg_dma_len(sg) = buflen;
- WARN_ON(buflen > PAGE_SIZE);
+// WARN_ON(buflen > PAGE_SIZE);
}
void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
===== drivers/scsi/libata-scsi.c 1.52 vs edited =====
--- 1.52/drivers/scsi/libata-scsi.c 2004-08-27 15:05:05 -05:00
+++ edited/drivers/scsi/libata-scsi.c 2004-10-05 16:41:26 -05:00
@@ -315,6 +315,85 @@
}
}
+/*
+ * ata_pass_thru_cc - Generate check condition sense block.
+ * @qc: Command that completed.
+ *
+ * Regardless of whether the command errored or not, return
+ * a sense block. Copy all controller registers into
+ * the sense block. Clear sense key, ASC & ASCQ if
+ * there is no error.
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host_set lock)
+ */
+void ata_pass_thru_cc(struct ata_queued_cmd *qc, u8 drv_stat)
+{
+ struct scsi_cmnd *cmd = qc->scsicmd;
+ struct ata_taskfile *tf = &qc->tf;
+ unsigned char *sb = cmd->sense_buffer;
+ unsigned char *desc = sb + 8 ;
+
+ cmd->result = SAM_STAT_CHECK_CONDITION;
+
+ /*
+ * Use ata_to_sense_error() to map status register bits
+ * onto sense key, asc & ascq. We will overwrite some
+ * (many) of the fields later.
+ *
+ * TODO: reorganise better, by splitting ata_to_sense_error()
+ */
+ if (unlikely(drv_stat & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ))) {
+ ata_to_sense_error(qc, drv_stat) ;
+ } else {
+ sb[3] = sb[2] = sb[1] = 0x00 ;
+ }
+
+ /*
+ * Sense data is current and format is
+ * descriptor.
+ */
+ sb[0] = 0x72 ;
+
+ desc[0] = 0x8e ; /* TODO: replace with official value. */
+
+ /*
+ * Set length of additional sense data.
+ * Since we only populate descriptor 0, the total
+ * length is the same (fixed) length as descriptor 0.
+ */
+ desc[1] = sb[7] = 14 ;
+
+ /*
+ * Read the controller registers.
+ */
+ qc->ap->ops->tf_read(qc->ap, tf);
+
+ /*
+ * Copy registers into sense buffer.
+ */
+ desc[2] = 0x00 ;
+ desc[3] = tf->feature ; /* Note: becomes error register when read. */
+ desc[5] = tf->nsect ;
+ desc[7] = tf->lbal ;
+ desc[9] = tf->lbam ;
+ desc[11] = tf->lbah ;
+ desc[12] = tf->device ;
+ desc[13] = drv_stat ;
+
+ /*
+ * Fill in Extend bit, and the high order bytes
+ * if applicable.
+ */
+ if (tf->flags & ATA_TFLAG_LBA48) {
+ desc[2] |= 0x01 ;
+ desc[4] = tf->hob_nsect ;
+ desc[6] = tf->hob_lbal ;
+ desc[8] = tf->hob_lbam ;
+ desc[10] = tf->hob_lbah ;
+ }
+}
+
/**
* ata_scsi_slave_config - Set SCSI device attributes
* @sdev: SCSI device to examine
@@ -623,10 +702,22 @@
{
struct scsi_cmnd *cmd = qc->scsicmd;
- if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ)))
- ata_to_sense_error(qc, drv_stat);
- else
- cmd->result = SAM_STAT_GOOD;
+ /*
+ * If this was a pass-thru command, and the user requested
+ * a check condition return including register values.
+ * Note that check condition is generated, and the ATA
+ * register values are returned, whether the command completed
+ * successfully or not. If there was no error, SK, ASC and
+ * ASCQ will all be zero.
+ */
+ if ((cmd->cmnd[0] == ATA_16) && (cmd->cmnd[2] & 0x20)) {
+ ata_pass_thru_cc(qc, drv_stat) ;
+ } else {
+ if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ)))
+ ata_to_sense_error(qc, drv_stat);
+ else
+ cmd->result = SAM_STAT_GOOD;
+ }
qc->scsidone(cmd);
@@ -1368,6 +1459,135 @@
return dev;
}
+/*
+ * ata_scsi_map_proto - Map pass-thru protocol value to taskfile value.
+ * @byte1: Byte 1 from pass-thru CDB.
+ *
+ * RETURNS:
+ * ATA_PROT_UNKNOWN if mapping failed/unimplemented, protocol otherwise.
+ */
+static u8
+ata_scsi_map_proto(u8 byte1)
+{
+ switch((byte1 & 0x1e) >> 1) {
+ case 3: /* Non-data */
+ return ATA_PROT_NODATA;
+
+ case 6: /* DMA */
+ return ATA_PROT_DMA;
+
+ case 4: /* PIO Data-in */
+ case 5: /* PIO Data-out */
+ if (byte1 & 0xe0) {
+ return ATA_PROT_PIO_MULT;
+ }
+ return ATA_PROT_PIO;
+
+ case 10: /* Device Reset */
+ case 0: /* Hard Reset */
+ case 1: /* SRST */
+ case 2: /* Bus Idle */
+ case 7: /* Packet */
+ case 8: /* DMA Queued */
+ case 9: /* Device Diagnostic */
+ case 11: /* UDMA Data-in */
+ case 12: /* UDMA Data-Out */
+ case 13: /* FPDMA */
+ default: /* Reserved */
+ break;
+ }
+
+ return ATA_PROT_UNKNOWN;
+}
+
+/**
+ * ata_scsi_pass_thru - convert ATA pass-thru CDB to taskfile
+ * @qc: command structure to be initialized
+ * @cmd: SCSI command to convert
+ *
+ * Handles either 12 or 16-byte versions of the CDB.
+ *
+ * RETURNS:
+ * Zero on success, non-zero on failure.
+ */
+static unsigned int
+ata_scsi_pass_thru(struct ata_queued_cmd *qc, u8 *scsicmd)
+{
+ struct ata_taskfile *tf = &(qc->tf);
+ struct scsi_cmnd *cmd = qc->scsicmd;
+
+ if ((tf->protocol = ata_scsi_map_proto(scsicmd[1])) == ATA_PROT_UNKNOWN) {
+ return 1;
+ }
+
+ /*
+ * 12 and 16 byte CDBs use different offsets to
+ * provide the various register values.
+ */
+ if (scsicmd[0] == ATA_16) {
+ /*
+ * 16-byte CDB - may contain extended commands.
+ *
+ * If that is the case, copy the upper byte register values.
+ */
+ if (scsicmd[1] & 0x01) {
+ tf->hob_feature = scsicmd[3];
+ tf->hob_nsect = scsicmd[5];
+ tf->hob_lbal = scsicmd[7];
+ tf->hob_lbam = scsicmd[9];
+ tf->hob_lbah = scsicmd[11];
+ tf->flags |= ATA_TFLAG_LBA48 ;
+ } else {
+ tf->flags &= ~ATA_TFLAG_LBA48 ;
+ }
+
+ /*
+ * Always copy low byte, device and command registers.
+ */
+ tf->feature = scsicmd[4];
+ tf->nsect = scsicmd[6];
+ tf->lbal = scsicmd[8];
+ tf->lbam = scsicmd[10];
+ tf->lbah = scsicmd[12];
+ tf->device = scsicmd[13];
+ tf->command = scsicmd[14];
+ } else {
+ /*
+ * 12-byte CDB - incapable of extended commands.
+ */
+ tf->flags &= ~ATA_TFLAG_LBA48 ;
+
+ tf->feature = scsicmd[3];
+ tf->nsect = scsicmd[4];
+ tf->lbal = scsicmd[5];
+ tf->lbam = scsicmd[6];
+ tf->lbah = scsicmd[7];
+ tf->device = scsicmd[8];
+ tf->command = scsicmd[9];
+ }
+
+ /*
+ * Set flags so that all registers will be written,
+ * and pass on write indication (used for PIO/DMA
+ * setup.)
+ */
+ tf->flags |= (ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE) ;
+
+ if (cmd->sc_data_direction == SCSI_DATA_WRITE) {
+ tf->flags |= ATA_TFLAG_WRITE;
+ }
+
+ /*
+ * Set transfer length.
+ *
+ * TODO: find out if we need to do more here to
+ * cover scatter/gather case.
+ */
+ qc->nsect = cmd->bufflen / ATA_SECT_SIZE ;
+
+ return 0;
+}
+
/**
* ata_get_xlat_func - check if SCSI to ATA translation is possible
* @dev: ATA device
@@ -1400,6 +1620,10 @@
case VERIFY:
case VERIFY_16:
return ata_scsi_verify_xlat;
+
+ case ATA_12:
+ case ATA_16:
+ return ata_scsi_pass_thru ;
}
return NULL;
===== drivers/scsi/sata_svw.c 1.26 vs edited =====
--- 1.26/drivers/scsi/sata_svw.c 2004-09-16 01:45:15 -05:00
+++ edited/drivers/scsi/sata_svw.c 2004-09-29 18:13:06 -05:00
@@ -138,9 +138,9 @@
lbam = tf->lbam = readw(ioaddr->lbam_addr);
lbah = tf->lbah = readw(ioaddr->lbah_addr);
tf->device = readw(ioaddr->device_addr);
+ tf->feature = readw(ioaddr->error_addr);
if (tf->flags & ATA_TFLAG_LBA48) {
- tf->hob_feature = readw(ioaddr->error_addr) >> 8;
tf->hob_nsect = nsect >> 8;
tf->hob_lbal = lbal >> 8;
tf->hob_lbam = lbam >> 8;
===== drivers/scsi/sata_vsc.c 1.19 vs edited =====
--- 1.19/drivers/scsi/sata_vsc.c 2004-09-16 01:45:15 -05:00
+++ edited/drivers/scsi/sata_vsc.c 2004-09-29 18:13:07 -05:00
@@ -139,9 +139,9 @@
lbam = tf->lbam = readw(ioaddr->lbam_addr);
lbah = tf->lbah = readw(ioaddr->lbah_addr);
tf->device = readw(ioaddr->device_addr);
+ tf->feature = readb(ioaddr->error_addr);
if (tf->flags & ATA_TFLAG_LBA48) {
- tf->hob_feature = readb(ioaddr->error_addr);
tf->hob_nsect = nsect >> 8;
tf->hob_lbal = lbal >> 8;
tf->hob_lbam = lbam >> 8;
===== include/scsi/scsi.h 1.24 vs edited =====
--- 1.24/include/scsi/scsi.h 2004-08-24 18:09:04 -05:00
+++ edited/include/scsi/scsi.h 2004-09-27 22:11:07 -05:00
@@ -113,6 +113,9 @@
/* values for service action in */
#define SAI_READ_CAPACITY_16 0x10
+/* Temporary values for T10/04-262 until official values are allocated */
+#define ATA_16 0x85 /* 16-byte pass-thru [0x85 == unused]*/
+#define ATA_12 0xb3 /* 12-byte pass-thru [0xb3 == obsolete set limits command] */
/*
* SCSI Architecture Model (SAM) Status codes. Taken from SAM-3 draft
[-- Attachment #3: patch-dev.041005 --]
[-- Type: text/plain, Size: 8938 bytes --]
diff -ur -X /tmp/dontdiff libata-dev-2.6/drivers/scsi/libata-core.c hotplug/drivers/scsi/libata-core.c
--- libata-dev-2.6/drivers/scsi/libata-core.c 2004-10-05 16:23:15.000000000 -0500
+++ hotplug/drivers/scsi/libata-core.c 2004-10-05 16:40:35.193080994 -0500
@@ -321,10 +321,10 @@
tf->lbam = inb(ioaddr->lbam_addr);
tf->lbah = inb(ioaddr->lbah_addr);
tf->device = inb(ioaddr->device_addr);
+ tf->feature = inb(ioaddr->error_addr);
if (tf->flags & ATA_TFLAG_LBA48) {
outb(tf->ctl | ATA_HOB, ioaddr->ctl_addr);
- tf->hob_feature = inb(ioaddr->error_addr);
tf->hob_nsect = inb(ioaddr->nsect_addr);
tf->hob_lbal = inb(ioaddr->lbal_addr);
tf->hob_lbam = inb(ioaddr->lbam_addr);
@@ -353,10 +353,10 @@
tf->lbam = readb((void __iomem *)ioaddr->lbam_addr);
tf->lbah = readb((void __iomem *)ioaddr->lbah_addr);
tf->device = readb((void __iomem *)ioaddr->device_addr);
+ tf->feature = readb((void __iomem *)ioaddr->error_addr);
if (tf->flags & ATA_TFLAG_LBA48) {
writeb(tf->ctl | ATA_HOB, (void __iomem *) ap->ioaddr.ctl_addr);
- tf->hob_feature = readb((void __iomem *)ioaddr->error_addr);
tf->hob_nsect = readb((void __iomem *)ioaddr->nsect_addr);
tf->hob_lbal = readb((void __iomem *)ioaddr->lbal_addr);
tf->hob_lbam = readb((void __iomem *)ioaddr->lbam_addr);
diff -ur -X /tmp/dontdiff libata-dev-2.6/drivers/scsi/libata-scsi.c hotplug/drivers/scsi/libata-scsi.c
--- libata-dev-2.6/drivers/scsi/libata-scsi.c 2004-10-05 16:23:15.000000000 -0500
+++ hotplug/drivers/scsi/libata-scsi.c 2004-10-05 16:41:26.459332921 -0500
@@ -468,6 +315,85 @@
}
}
+/*
+ * ata_pass_thru_cc - Generate check condition sense block.
+ * @qc: Command that completed.
+ *
+ * Regardless of whether the command errored or not, return
+ * a sense block. Copy all controller registers into
+ * the sense block. Clear sense key, ASC & ASCQ if
+ * there is no error.
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host_set lock)
+ */
+void ata_pass_thru_cc(struct ata_queued_cmd *qc, u8 drv_stat)
+{
+ struct scsi_cmnd *cmd = qc->scsicmd;
+ struct ata_taskfile *tf = &qc->tf;
+ unsigned char *sb = cmd->sense_buffer;
+ unsigned char *desc = sb + 8 ;
+
+ cmd->result = SAM_STAT_CHECK_CONDITION;
+
+ /*
+ * Use ata_to_sense_error() to map status register bits
+ * onto sense key, asc & ascq. We will overwrite some
+ * (many) of the fields later.
+ *
+ * TODO: reorganise better, by splitting ata_to_sense_error()
+ */
+ if (unlikely(drv_stat & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ))) {
+ ata_to_sense_error(qc, drv_stat) ;
+ } else {
+ sb[3] = sb[2] = sb[1] = 0x00 ;
+ }
+
+ /*
+ * Sense data is current and format is
+ * descriptor.
+ */
+ sb[0] = 0x72 ;
+
+ desc[0] = 0x8e ; /* TODO: replace with official value. */
+
+ /*
+ * Set length of additional sense data.
+ * Since we only populate descriptor 0, the total
+ * length is the same (fixed) length as descriptor 0.
+ */
+ desc[1] = sb[7] = 14 ;
+
+ /*
+ * Read the controller registers.
+ */
+ qc->ap->ops->tf_read(qc->ap, tf);
+
+ /*
+ * Copy registers into sense buffer.
+ */
+ desc[2] = 0x00 ;
+ desc[3] = tf->feature ; /* Note: becomes error register when read. */
+ desc[5] = tf->nsect ;
+ desc[7] = tf->lbal ;
+ desc[9] = tf->lbam ;
+ desc[11] = tf->lbah ;
+ desc[12] = tf->device ;
+ desc[13] = drv_stat ;
+
+ /*
+ * Fill in Extend bit, and the high order bytes
+ * if applicable.
+ */
+ if (tf->flags & ATA_TFLAG_LBA48) {
+ desc[2] |= 0x01 ;
+ desc[4] = tf->hob_nsect ;
+ desc[6] = tf->hob_lbal ;
+ desc[8] = tf->hob_lbam ;
+ desc[10] = tf->hob_lbah ;
+ }
+}
+
/**
* ata_scsi_slave_config - Set SCSI device attributes
* @sdev: SCSI device to examine
@@ -785,7 +711,7 @@
* ASCQ will all be zero.
*/
if ((cmd->cmnd[0] == ATA_16) && (cmd->cmnd[2] & 0x20)) {
-/*DWD*/ printk("XX 0x%0lx/0x%0x\n", qc->tf.flags, qc->tf.protocol);
+ ata_pass_thru_cc(qc, drv_stat) ;
} else {
if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ)))
ata_to_sense_error(qc, drv_stat);
@@ -853,6 +779,7 @@
if (xlat_func(qc, scsicmd))
goto err_out;
+
/* select device, send command to hardware */
if (ata_qc_issue(qc))
goto err_out;
@@ -1533,9 +1460,11 @@
}
/*
- * ata_scsi_map_proto() - Map the protocol specified
- * in the pass-thru CDB onto the
- * protocol values used by taskfiles.
+ * ata_scsi_map_proto - Map pass-thru protocol value to taskfile value.
+ * @byte1: Byte 1 from pass-thru CDB.
+ *
+ * RETURNS:
+ * ATA_PROT_UNKNOWN if mapping failed/unimplemented, protocol otherwise.
*/
static u8
ata_scsi_map_proto(u8 byte1)
@@ -1571,8 +1500,18 @@
return ATA_PROT_UNKNOWN;
}
+/**
+ * ata_scsi_pass_thru - convert ATA pass-thru CDB to taskfile
+ * @qc: command structure to be initialized
+ * @cmd: SCSI command to convert
+ *
+ * Handles either 12 or 16-byte versions of the CDB.
+ *
+ * RETURNS:
+ * Zero on success, non-zero on failure.
+ */
static unsigned int
-ata_scsi_pass_thru_16(struct ata_queued_cmd *qc, u8 *scsicmd)
+ata_scsi_pass_thru(struct ata_queued_cmd *qc, u8 *scsicmd)
{
struct ata_taskfile *tf = &(qc->tf);
struct scsi_cmnd *cmd = qc->scsicmd;
@@ -1582,45 +1521,70 @@
}
/*
- * If the CDB claims to contain extended
- * ATA commands copy the upper byte register values.
- *
- * NOTE: at present copy all register fields,
- * regardless of which ones are valid according
- * to the .En bits. TODO: research optimal
- * algorithm for this.
+ * 12 and 16 byte CDBs use different offsets to
+ * provide the various register values.
*/
- if (scsicmd[1] & 0x01) {
- tf->hob_feature = scsicmd[3];
- tf->hob_nsect = scsicmd[5];
- tf->hob_lbal = scsicmd[7];
- tf->hob_lbam = scsicmd[9];
- tf->hob_lbah = scsicmd[11];
- tf->flags |= ATA_TFLAG_LBA48 ;
+ if (scsicmd[0] == ATA_16) {
+ /*
+ * 16-byte CDB - may contain extended commands.
+ *
+ * If that is the case, copy the upper byte register values.
+ */
+ if (scsicmd[1] & 0x01) {
+ tf->hob_feature = scsicmd[3];
+ tf->hob_nsect = scsicmd[5];
+ tf->hob_lbal = scsicmd[7];
+ tf->hob_lbam = scsicmd[9];
+ tf->hob_lbah = scsicmd[11];
+ tf->flags |= ATA_TFLAG_LBA48 ;
+ } else {
+ tf->flags &= ~ATA_TFLAG_LBA48 ;
+ }
+
+ /*
+ * Always copy low byte, device and command registers.
+ */
+ tf->feature = scsicmd[4];
+ tf->nsect = scsicmd[6];
+ tf->lbal = scsicmd[8];
+ tf->lbam = scsicmd[10];
+ tf->lbah = scsicmd[12];
+ tf->device = scsicmd[13];
+ tf->command = scsicmd[14];
} else {
+ /*
+ * 12-byte CDB - incapable of extended commands.
+ */
tf->flags &= ~ATA_TFLAG_LBA48 ;
- }
- tf->feature = scsicmd[4];
- tf->nsect = scsicmd[6];
- tf->lbal = scsicmd[8];
- tf->lbam = scsicmd[10];
- tf->lbah = scsicmd[12];
+ tf->feature = scsicmd[3];
+ tf->nsect = scsicmd[4];
+ tf->lbal = scsicmd[5];
+ tf->lbam = scsicmd[6];
+ tf->lbah = scsicmd[7];
+ tf->device = scsicmd[8];
+ tf->command = scsicmd[9];
+ }
+ /*
+ * Set flags so that all registers will be written,
+ * and pass on write indication (used for PIO/DMA
+ * setup.)
+ */
tf->flags |= (ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE) ;
- tf->device = scsicmd[13];
- tf->command = scsicmd[14];
+
+ if (cmd->sc_data_direction == SCSI_DATA_WRITE) {
+ tf->flags |= ATA_TFLAG_WRITE;
+ }
/*
+ * Set transfer length.
+ *
* TODO: find out if we need to do more here to
* cover scatter/gather case.
*/
qc->nsect = cmd->bufflen / ATA_SECT_SIZE ;
- if (cmd->sc_data_direction == SCSI_DATA_WRITE) {
- tf->flags |= ATA_TFLAG_WRITE;
- }
-
return 0;
}
@@ -1657,8 +1621,9 @@
case VERIFY_16:
return ata_scsi_verify_xlat;
+ case ATA_12:
case ATA_16:
- return ata_scsi_pass_thru_16 ;
+ return ata_scsi_pass_thru ;
}
return NULL;
diff -ur -X /tmp/dontdiff libata-dev-2.6/drivers/scsi/sata_svw.c hotplug/drivers/scsi/sata_svw.c
--- libata-dev-2.6/drivers/scsi/sata_svw.c 2004-10-05 16:23:15.000000000 -0500
+++ hotplug/drivers/scsi/sata_svw.c 2004-09-29 18:13:06.000000000 -0500
@@ -138,9 +138,9 @@
lbam = tf->lbam = readw(ioaddr->lbam_addr);
lbah = tf->lbah = readw(ioaddr->lbah_addr);
tf->device = readw(ioaddr->device_addr);
+ tf->feature = readw(ioaddr->error_addr);
if (tf->flags & ATA_TFLAG_LBA48) {
- tf->hob_feature = readw(ioaddr->error_addr) >> 8;
tf->hob_nsect = nsect >> 8;
tf->hob_lbal = lbal >> 8;
tf->hob_lbam = lbam >> 8;
diff -ur -X /tmp/dontdiff libata-dev-2.6/drivers/scsi/sata_vsc.c hotplug/drivers/scsi/sata_vsc.c
--- libata-dev-2.6/drivers/scsi/sata_vsc.c 2004-10-05 16:23:15.000000000 -0500
+++ hotplug/drivers/scsi/sata_vsc.c 2004-09-29 18:13:07.000000000 -0500
@@ -139,9 +139,9 @@
lbam = tf->lbam = readw(ioaddr->lbam_addr);
lbah = tf->lbah = readw(ioaddr->lbah_addr);
tf->device = readw(ioaddr->device_addr);
+ tf->feature = readb(ioaddr->error_addr);
if (tf->flags & ATA_TFLAG_LBA48) {
- tf->hob_feature = readb(ioaddr->error_addr);
tf->hob_nsect = nsect >> 8;
tf->hob_lbal = lbal >> 8;
tf->hob_lbam = lbam >> 8;
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: T10/04-262 ATA pass thru - another patch.
2004-10-05 23:20 T10/04-262 ATA pass thru - another patch Andy Warner
@ 2004-10-06 3:10 ` Jeff Garzik
2004-10-06 3:23 ` Andy Warner
2004-10-07 3:38 ` Jeff Garzik
1 sibling, 1 reply; 4+ messages in thread
From: Jeff Garzik @ 2004-10-06 3:10 UTC (permalink / raw)
To: Andy Warner; +Cc: linux-ide, John Linville, linville, Pat LaVarre, Mark Lord
Andy Warner wrote:
> Attached are two patchfiles, which implement the following
> features of libata ATA pass-thru:
>
> o check condition processing
> o 12-byte CDB handling
>
> patch.041005 can be applied to vanilla libata-2.6 trees
> patch-dev.041005 can be applied to libata-dev-2.6 trees
Make sure to split up patches into separate emails, and don't combine
e.g. your error register patch with a passthru update patch.
Separate changes go into separate patches.
http://linux.yyz.us/patch-format.html
http://www.zip.com.au/~akpm/linux/patches/stuff/tpp.txt
> diff -ur -X /tmp/dontdiff libata-dev-2.6/drivers/scsi/libata-scsi.c hotplug/drivers/scsi/libata-scsi.c
> --- libata-dev-2.6/drivers/scsi/libata-scsi.c 2004-10-05 16:23:15.000000000 -0500
> +++ hotplug/drivers/scsi/libata-scsi.c 2004-10-05 16:41:26.459332921 -0500
> @@ -468,6 +315,85 @@
> }
> }
>
> +/*
> + * ata_pass_thru_cc - Generate check condition sense block.
> + * @qc: Command that completed.
> + *
> + * Regardless of whether the command errored or not, return
> + * a sense block. Copy all controller registers into
> + * the sense block. Clear sense key, ASC & ASCQ if
> + * there is no error.
> + *
> + * LOCKING:
> + * spin_lock_irqsave(host_set lock)
> + */
> +void ata_pass_thru_cc(struct ata_queued_cmd *qc, u8 drv_stat)
> +{
> + struct scsi_cmnd *cmd = qc->scsicmd;
> + struct ata_taskfile *tf = &qc->tf;
> + unsigned char *sb = cmd->sense_buffer;
> + unsigned char *desc = sb + 8 ;
> +
> + cmd->result = SAM_STAT_CHECK_CONDITION;
> +
> + /*
> + * Use ata_to_sense_error() to map status register bits
> + * onto sense key, asc & ascq. We will overwrite some
> + * (many) of the fields later.
> + *
> + * TODO: reorganise better, by splitting ata_to_sense_error()
> + */
> + if (unlikely(drv_stat & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ))) {
> + ata_to_sense_error(qc, drv_stat) ;
> + } else {
> + sb[3] = sb[2] = sb[1] = 0x00 ;
> + }
> +
> + /*
> + * Sense data is current and format is
> + * descriptor.
> + */
> + sb[0] = 0x72 ;
> +
> + desc[0] = 0x8e ; /* TODO: replace with official value. */
prefer constants to magic numbers
> + /*
> + * Set length of additional sense data.
> + * Since we only populate descriptor 0, the total
> + * length is the same (fixed) length as descriptor 0.
> + */
> + desc[1] = sb[7] = 14 ;
> +
> + /*
> + * Read the controller registers.
> + */
> + qc->ap->ops->tf_read(qc->ap, tf);
> +
> + /*
> + * Copy registers into sense buffer.
> + */
> + desc[2] = 0x00 ;
> + desc[3] = tf->feature ; /* Note: becomes error register when read. */
> + desc[5] = tf->nsect ;
> + desc[7] = tf->lbal ;
> + desc[9] = tf->lbam ;
> + desc[11] = tf->lbah ;
> + desc[12] = tf->device ;
> + desc[13] = drv_stat ;
> +
> + /*
> + * Fill in Extend bit, and the high order bytes
> + * if applicable.
> + */
> + if (tf->flags & ATA_TFLAG_LBA48) {
> + desc[2] |= 0x01 ;
> + desc[4] = tf->hob_nsect ;
> + desc[6] = tf->hob_lbal ;
> + desc[8] = tf->hob_lbam ;
> + desc[10] = tf->hob_lbah ;
> + }
> +}
> +
> /**
> * ata_scsi_slave_config - Set SCSI device attributes
> * @sdev: SCSI device to examine
> @@ -785,7 +711,7 @@
> * ASCQ will all be zero.
> */
> if ((cmd->cmnd[0] == ATA_16) && (cmd->cmnd[2] & 0x20)) {
> -/*DWD*/ printk("XX 0x%0lx/0x%0x\n", qc->tf.flags, qc->tf.protocol);
> + ata_pass_thru_cc(qc, drv_stat) ;
> } else {
> if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ)))
> ata_to_sense_error(qc, drv_stat);
> @@ -853,6 +779,7 @@
>
> if (xlat_func(qc, scsicmd))
> goto err_out;
> +
> /* select device, send command to hardware */
> if (ata_qc_issue(qc))
> goto err_out;
> @@ -1533,9 +1460,11 @@
> }
>
> /*
> - * ata_scsi_map_proto() - Map the protocol specified
> - * in the pass-thru CDB onto the
> - * protocol values used by taskfiles.
> + * ata_scsi_map_proto - Map pass-thru protocol value to taskfile value.
> + * @byte1: Byte 1 from pass-thru CDB.
> + *
> + * RETURNS:
> + * ATA_PROT_UNKNOWN if mapping failed/unimplemented, protocol otherwise.
> */
> static u8
> ata_scsi_map_proto(u8 byte1)
> @@ -1571,8 +1500,18 @@
> return ATA_PROT_UNKNOWN;
> }
>
> +/**
> + * ata_scsi_pass_thru - convert ATA pass-thru CDB to taskfile
> + * @qc: command structure to be initialized
> + * @cmd: SCSI command to convert
> + *
> + * Handles either 12 or 16-byte versions of the CDB.
> + *
> + * RETURNS:
> + * Zero on success, non-zero on failure.
> + */
> static unsigned int
> -ata_scsi_pass_thru_16(struct ata_queued_cmd *qc, u8 *scsicmd)
> +ata_scsi_pass_thru(struct ata_queued_cmd *qc, u8 *scsicmd)
> {
> struct ata_taskfile *tf = &(qc->tf);
> struct scsi_cmnd *cmd = qc->scsicmd;
> @@ -1582,45 +1521,70 @@
> }
>
> /*
> - * If the CDB claims to contain extended
> - * ATA commands copy the upper byte register values.
> - *
> - * NOTE: at present copy all register fields,
> - * regardless of which ones are valid according
> - * to the .En bits. TODO: research optimal
> - * algorithm for this.
> + * 12 and 16 byte CDBs use different offsets to
> + * provide the various register values.
> */
> - if (scsicmd[1] & 0x01) {
> - tf->hob_feature = scsicmd[3];
> - tf->hob_nsect = scsicmd[5];
> - tf->hob_lbal = scsicmd[7];
> - tf->hob_lbam = scsicmd[9];
> - tf->hob_lbah = scsicmd[11];
> - tf->flags |= ATA_TFLAG_LBA48 ;
> + if (scsicmd[0] == ATA_16) {
> + /*
> + * 16-byte CDB - may contain extended commands.
> + *
> + * If that is the case, copy the upper byte register values.
> + */
> + if (scsicmd[1] & 0x01) {
> + tf->hob_feature = scsicmd[3];
> + tf->hob_nsect = scsicmd[5];
> + tf->hob_lbal = scsicmd[7];
> + tf->hob_lbam = scsicmd[9];
> + tf->hob_lbah = scsicmd[11];
> + tf->flags |= ATA_TFLAG_LBA48 ;
> + } else {
> + tf->flags &= ~ATA_TFLAG_LBA48 ;
> + }
ATA_TFLAG_LBA48 is dependent on device capabilities, not just what the
user inputs.
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: T10/04-262 ATA pass thru - another patch.
2004-10-06 3:10 ` Jeff Garzik
@ 2004-10-06 3:23 ` Andy Warner
0 siblings, 0 replies; 4+ messages in thread
From: Andy Warner @ 2004-10-06 3:23 UTC (permalink / raw)
To: Jeff Garzik
Cc: Andy Warner, linux-ide, John Linville, linville, Pat LaVarre,
Mark Lord
Jeff Garzik wrote:
> [...]
> Make sure to split up patches into separate emails, and don't combine
> e.g. your error register patch with a passthru update patch.
>
> Separate changes go into separate patches.
Ack.
Apologies.
I was not really sure who the customer is for these: integrators
or folks trying to test this stuff and not wanting them to have
to play find-the-missing-patch.
Won't happen again.
--
andyw@pobox.com
Andy Warner Voice: (612) 801-8549 Fax: (208) 575-5634
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: T10/04-262 ATA pass thru - another patch.
2004-10-05 23:20 T10/04-262 ATA pass thru - another patch Andy Warner
2004-10-06 3:10 ` Jeff Garzik
@ 2004-10-07 3:38 ` Jeff Garzik
1 sibling, 0 replies; 4+ messages in thread
From: Jeff Garzik @ 2004-10-07 3:38 UTC (permalink / raw)
To: Andy Warner; +Cc: linux-ide, John Linville, linville, Pat LaVarre, Mark Lord
Andy Warner wrote:
> Attached are two patchfiles, which implement the following
> features of libata ATA pass-thru:
>
> o check condition processing
> o 12-byte CDB handling
>
> patch.041005 can be applied to vanilla libata-2.6 trees
> patch-dev.041005 can be applied to libata-dev-2.6 trees
Please resend this as two patches, diff'd against libata-dev-2.6 tree.
I'll apply the error register patch for now, and think about it later
;-) That's what libata-dev is for, after all.
I'll generate a new libata-dev patch, too.
Jeff
P.S. One patch per email, please. Mailbombing is acceptable.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2004-10-07 3:38 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-10-05 23:20 T10/04-262 ATA pass thru - another patch Andy Warner
2004-10-06 3:10 ` Jeff Garzik
2004-10-06 3:23 ` Andy Warner
2004-10-07 3:38 ` Jeff Garzik
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).