From 049a1ca4b4d2d5a6e6c6eb0715b09a929470f600 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Sun, 4 Jul 2004 09:35:29 -0400 Subject: [libata] transfer mode cleanup Add MWDMA support, and rework pio/mwdma/udma mode setup. In the lone test case for PATA support, ata_piix, MWDMA mode setting does not appear to work here. UDMA and PIO continue to work, so nobody will really notice. But beware. Probably a driver problem, not a bug in the core. Also, doesn't bother writing to dummy timing registers on ICH5/6 SATA anymore. --- include/linux/ata.h | 7 +++++++ include/linux/libata.h | 21 +++++++++++++++------ 2 files changed, 22 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/linux/ata.h b/include/linux/ata.h index 7a99d7ee2f89..c8c5a0385414 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -42,6 +42,7 @@ enum { ATA_ID_SERNO_OFS = 10, ATA_ID_MAJOR_VER = 80, ATA_ID_PIO_MODES = 64, + ATA_ID_MWDMA_MODES = 63, ATA_ID_UDMA_MODES = 88, ATA_ID_PIO4 = (1 << 1), @@ -133,8 +134,14 @@ enum { XFER_UDMA_2 = 0x42, XFER_UDMA_1 = 0x41, XFER_UDMA_0 = 0x40, + XFER_MW_DMA_2 = 0x22, + XFER_MW_DMA_1 = 0x21, + XFER_MW_DMA_0 = 0x20, XFER_PIO_4 = 0x0C, XFER_PIO_3 = 0x0B, + XFER_PIO_2 = 0x0A, + XFER_PIO_1 = 0x09, + XFER_PIO_0 = 0x08, /* ATAPI stuff */ ATAPI_PKT_DMA = (1 << 0), diff --git a/include/linux/libata.h b/include/linux/libata.h index b646a48345a0..ac2b1fb85764 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -32,7 +32,6 @@ /* * compile-time options */ -#undef ATA_FORCE_PIO /* do not configure or use DMA */ #undef ATA_DEBUG /* debugging output */ #undef ATA_VERBOSE_DEBUG /* yet more debugging output */ #undef ATA_IRQ_TRAP /* define to ack screaming irqs */ @@ -140,6 +139,13 @@ enum { PORT_UNKNOWN = 0, PORT_ENABLED = 1, PORT_DISABLED = 2, + + /* encoding various smaller bitmaps into a single + * unsigned long bitmap + */ + ATA_SHIFT_UDMA = 0, + ATA_SHIFT_MWDMA = 8, + ATA_SHIFT_PIO = 11, }; enum pio_task_states { @@ -188,6 +194,7 @@ struct ata_probe_ent { struct ata_ioports port[ATA_MAX_PORTS]; unsigned int n_ports; unsigned int pio_mask; + unsigned int mwdma_mask; unsigned int udma_mask; unsigned int legacy_mode; unsigned long irq; @@ -252,7 +259,9 @@ struct ata_device { unsigned int devno; /* 0 or 1 */ u16 id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */ unsigned int pio_mode; - unsigned int udma_mode; + unsigned int dma_mode; + unsigned int xfer_mode; + unsigned int xfer_shift; /* ATA_SHIFT_xxx */ /* cache info about current transfer mode */ u8 xfer_protocol; /* taskfile xfer protocol */ @@ -277,6 +286,7 @@ struct ata_port { unsigned int bus_state; unsigned int port_state; unsigned int pio_mask; + unsigned int mwdma_mask; unsigned int udma_mask; unsigned int cbl; /* cable type; ATA_CBL_xxx */ @@ -303,10 +313,8 @@ struct ata_port_operations { void (*dev_config) (struct ata_port *, struct ata_device *); - void (*set_piomode) (struct ata_port *, struct ata_device *, - unsigned int); - void (*set_udmamode) (struct ata_port *, struct ata_device *, - unsigned int); + void (*set_piomode) (struct ata_port *, struct ata_device *); + void (*set_dmamode) (struct ata_port *, struct ata_device *); void (*tf_load) (struct ata_port *ap, struct ata_taskfile *tf); void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf); @@ -342,6 +350,7 @@ struct ata_port_info { Scsi_Host_Template *sht; unsigned long host_flags; unsigned long pio_mask; + unsigned long mwdma_mask; unsigned long udma_mask; struct ata_port_operations *port_ops; }; -- cgit v1.2.3 From 1d6fb7da31f8d134a10e9b55e8d7683bd6bfb1d4 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Sun, 4 Jul 2004 13:02:36 -0400 Subject: [libata] transfer mode bug fixes and type cleanup Fix two bugs that causes the recently-added transfer mode code to break on 64-bit platforms. Make associated code more type-correct in the process. --- drivers/scsi/libata-core.c | 54 ++++++++++++++++++++++++++++------------------ include/linux/libata.h | 6 +++--- 2 files changed, 36 insertions(+), 24 deletions(-) (limited to 'include') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 4b8c2a225341..621e421d4ec0 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -53,9 +53,9 @@ static void __ata_dev_select (struct ata_port *ap, unsigned int device); static void ata_set_mode(struct ata_port *ap); static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev); static unsigned int ata_get_mode_mask(struct ata_port *ap, int shift); -static int fgb(unsigned long bitmap); +static int fgb(u32 bitmap); static int ata_choose_xfer_mode(struct ata_port *ap, - unsigned int *xfer_mode_out, + u8 *xfer_mode_out, unsigned int *xfer_shift_out); static unsigned int ata_unique_id = 1; @@ -948,7 +948,8 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) { struct ata_device *dev = &ap->device[device]; unsigned int i; - u16 tmp, xfer_modes; + u16 tmp; + unsigned long xfer_modes; u8 status; struct ata_taskfile tf; unsigned int using_edd; @@ -1063,7 +1064,7 @@ retry: goto err_out_nosup; } - /* we require UDMA support */ + /* quick-n-dirty find max transfer mode; for printk only */ xfer_modes = dev->id[ATA_ID_UDMA_MODES]; if (!xfer_modes) xfer_modes = (dev->id[ATA_ID_MWDMA_MODES]) << ATA_SHIFT_MWDMA; @@ -1253,14 +1254,14 @@ void ata_port_disable(struct ata_port *ap) static struct { unsigned int shift; - unsigned int base; + u8 base; } xfer_mode_classes[] = { { ATA_SHIFT_UDMA, XFER_UDMA_0 }, { ATA_SHIFT_MWDMA, XFER_MW_DMA_0 }, { ATA_SHIFT_PIO, XFER_PIO_0 }, }; -static inline unsigned int base_from_shift(unsigned int shift) +static inline u8 base_from_shift(unsigned int shift) { int i; @@ -1268,12 +1269,13 @@ static inline unsigned int base_from_shift(unsigned int shift) if (xfer_mode_classes[i].shift == shift) return xfer_mode_classes[i].base; - return 0xffffffff; + return 0xff; } static void ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) { - unsigned int base, offset; + int ofs, idx; + u8 base; if (!ata_dev_present(dev) || (ap->flags & ATA_FLAG_PORT_DISABLED)) return; @@ -1281,17 +1283,22 @@ static void ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) ata_dev_set_xfermode(ap, dev); base = base_from_shift(dev->xfer_shift); - offset = dev->xfer_mode - base; + ofs = dev->xfer_mode - base; + idx = ofs + dev->xfer_shift; + WARN_ON(idx >= ARRAY_SIZE(xfer_mode_str)); + + DPRINTK("idx=%d xfer_shift=%u, xfer_mode=0x%x, base=0x%x, offset=%d\n", + idx, dev->xfer_shift, (int)dev->xfer_mode, (int)base, ofs); printk(KERN_INFO "ata%u: dev %u configured for %s\n", - ap->id, dev->devno, - xfer_mode_str[offset + dev->xfer_shift]); + ap->id, dev->devno, xfer_mode_str[idx]); } static int ata_host_set_pio(struct ata_port *ap) { - unsigned int mask, base, xfer_mode; + unsigned int mask; int x, i; + u8 base, xfer_mode; mask = ata_get_mode_mask(ap, ATA_SHIFT_PIO); x = fgb(mask); @@ -1303,6 +1310,9 @@ static int ata_host_set_pio(struct ata_port *ap) base = base_from_shift(ATA_SHIFT_PIO); xfer_mode = base + x; + DPRINTK("base 0x%x xfer_mode 0x%x mask 0x%x x %d\n", + (int)base, (int)xfer_mode, mask, x); + for (i = 0; i < ATA_MAX_DEVICES; i++) { struct ata_device *dev = &ap->device[i]; if (ata_dev_present(dev)) { @@ -1317,7 +1327,7 @@ static int ata_host_set_pio(struct ata_port *ap) return 0; } -static void ata_host_set_dma(struct ata_port *ap, unsigned int xfer_mode, +static void ata_host_set_dma(struct ata_port *ap, u8 xfer_mode, unsigned int xfer_shift) { int i; @@ -1343,7 +1353,8 @@ static void ata_host_set_dma(struct ata_port *ap, unsigned int xfer_mode, */ static void ata_set_mode(struct ata_port *ap) { - unsigned int i, xfer_mode, xfer_shift; + unsigned int i, xfer_shift; + u8 xfer_mode; int rc; /* step 1: always set host PIO timings */ @@ -1695,19 +1706,20 @@ static unsigned int ata_get_mode_mask(struct ata_port *ap, int shift) } /* find greatest bit */ -static int fgb(unsigned long bitmap) +static int fgb(u32 bitmap) { - int i, x = -1; + unsigned int i; + int x = -1; - for (i = 0; i < (sizeof(unsigned long) * 8); i++) + for (i = 0; i < 32; i++) if (bitmap & (1 << i)) x = i; - + return x; } /** - * ata_choose_xfer_mode - + * ata_choose_xfer_mode - * @ap: * * LOCKING: @@ -1717,7 +1729,7 @@ static int fgb(unsigned long bitmap) */ static int ata_choose_xfer_mode(struct ata_port *ap, - unsigned int *xfer_mode_out, + u8 *xfer_mode_out, unsigned int *xfer_shift_out) { unsigned int mask, shift; @@ -2941,7 +2953,7 @@ int ata_device_add(struct ata_probe_ent *ent) /* register each port bound to this device */ for (i = 0; i < ent->n_ports; i++) { struct ata_port *ap; - unsigned int xfer_mode_mask; + unsigned long xfer_mode_mask; ap = ata_host_add(ent, host_set, i); if (!ap) diff --git a/include/linux/libata.h b/include/linux/libata.h index ac2b1fb85764..f77a2863c187 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -258,9 +258,9 @@ struct ata_device { unsigned int class; /* ATA_DEV_xxx */ unsigned int devno; /* 0 or 1 */ u16 id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */ - unsigned int pio_mode; - unsigned int dma_mode; - unsigned int xfer_mode; + u8 pio_mode; + u8 dma_mode; + u8 xfer_mode; unsigned int xfer_shift; /* ATA_SHIFT_xxx */ /* cache info about current transfer mode */ -- cgit v1.2.3 From 50035625c1ce8f83b3af3f01a3650f265511a825 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Wed, 7 Jul 2004 07:51:57 -0400 Subject: [libata] pio/dma flag bug fix, and cleanup In the transfer-mode cleanup recently, the code that set flag ATA_DFLAG_PIO disappeared. Resurrect it. Remove ATA_QCFLAG_DMA, it isn't needed. Always set polling in the ->qc_issue function, rather than force the user to do it when setting up an ata_queued_cmd. This gives maximum flexibility to the driver, letting the driver choose whether or not to poll. --- drivers/scsi/libata-core.c | 6 ++++-- drivers/scsi/libata-scsi.c | 9 +++++---- include/linux/libata.h | 2 -- 3 files changed, 9 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 621e421d4ec0..364edc881179 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1280,6 +1280,9 @@ static void ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) if (!ata_dev_present(dev) || (ap->flags & ATA_FLAG_PORT_DISABLED)) return; + if (dev->xfer_shift == ATA_SHIFT_PIO) + dev->flags |= ATA_DFLAG_PIO; + ata_dev_set_xfermode(ap, dev); base = base_from_shift(dev->xfer_shift); @@ -2333,8 +2336,6 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, ata_tf_init(ap, &qc->tf, dev->devno); - if (likely((dev->flags & ATA_DFLAG_PIO) == 0)) - qc->flags |= ATA_QCFLAG_DMA; if (dev->flags & ATA_DFLAG_LBA48) qc->tf.flags |= ATA_TFLAG_LBA48; } @@ -2473,6 +2474,7 @@ int ata_qc_issue_prot(struct ata_queued_cmd *qc) break; case ATA_PROT_ATAPI: + ata_qc_set_polling(qc); ata_tf_to_host_nolock(ap, &qc->tf); queue_work(ata_wq, &ap->packet_task); break; diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index b3340607b99c..1605a15bdce1 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -979,6 +979,8 @@ void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8 static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) { struct scsi_cmnd *cmd = qc->scsicmd; + struct ata_device *dev = qc->dev; + int using_pio = (dev->flags & ATA_DFLAG_PIO); qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; if (cmd->sc_data_direction == SCSI_DATA_WRITE) { @@ -992,14 +994,13 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) if (cmd->sc_data_direction == SCSI_DATA_NONE) qc->tf.protocol = ATA_PROT_ATAPI; - /* PIO data xfer - polling */ - else if ((qc->flags & ATA_QCFLAG_DMA) == 0) { - ata_qc_set_polling(qc); + /* PIO data xfer */ + else if (using_pio) { qc->tf.protocol = ATA_PROT_ATAPI; qc->tf.lbam = (8 * 1024) & 0xff; qc->tf.lbah = (8 * 1024) >> 8; - /* DMA data xfer - interrupt-driven */ + /* DMA data xfer */ } else { qc->tf.protocol = ATA_PROT_ATAPI_DMA; qc->tf.feature |= ATAPI_PKT_DMA; diff --git a/include/linux/libata.h b/include/linux/libata.h index f77a2863c187..009b70759bb8 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -110,7 +110,6 @@ enum { ATA_FLAG_SATA_RESET = (1 << 7), /* use COMRESET */ ATA_QCFLAG_ACTIVE = (1 << 1), /* cmd not yet ack'd to scsi lyer */ - ATA_QCFLAG_DMA = (1 << 2), /* data delivered via DMA */ ATA_QCFLAG_SG = (1 << 3), /* have s/g table? */ ATA_QCFLAG_SINGLE = (1 << 4), /* no s/g, just a single buffer */ ATA_QCFLAG_DMAMAP = ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE, @@ -481,7 +480,6 @@ static inline u8 ata_wait_idle(struct ata_port *ap) static inline void ata_qc_set_polling(struct ata_queued_cmd *qc) { - qc->flags &= ~ATA_QCFLAG_DMA; qc->tf.ctl |= ATA_NIEN; } -- cgit v1.2.3 From 3fcfe3871c0dc3901f740afe7331ba6e67679493 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Sat, 10 Jul 2004 03:09:17 -0400 Subject: [libata] flags cleanup Remove unused/redundant flags ATA_DFLAG_{MASTER,WCACHE} --- drivers/scsi/ata_piix.c | 2 +- drivers/scsi/libata-core.c | 1 - include/linux/libata.h | 5 +---- 3 files changed, 2 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index f4b827d56a6f..bf48ed41ecdf 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -390,7 +390,7 @@ static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev) { unsigned int pio = adev->pio_mode; struct pci_dev *dev = ap->host_set->pdev; - unsigned int is_slave = (adev->flags & ATA_DFLAG_MASTER) ? 0 : 1; + unsigned int is_slave = (adev->devno != 0); unsigned int master_port= ap->port_no ? 0x42 : 0x40; unsigned int slave_port = 0x44; u16 master_data; diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index f5e86c00c7a9..80b475accb8e 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2901,7 +2901,6 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, ap->flags |= ent->host_flags; ap->ops = ent->port_ops; ap->cbl = ATA_CBL_NONE; - ap->device[0].flags = ATA_DFLAG_MASTER; ap->active_tag = ATA_TAG_POISON; ap->last_ctl = 0xFF; diff --git a/include/linux/libata.h b/include/linux/libata.h index 009b70759bb8..42a9bde8e42d 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -87,10 +87,7 @@ enum { /* struct ata_device stuff */ ATA_DFLAG_LBA48 = (1 << 0), /* device supports LBA48 */ ATA_DFLAG_PIO = (1 << 1), /* device currently in PIO mode */ - ATA_DFLAG_MASTER = (1 << 2), /* is device 0? */ - ATA_DFLAG_WCACHE = (1 << 3), /* has write cache we can - * (hopefully) flush? */ - ATA_DFLAG_LOCK_SECTORS = (1 << 4), /* don't adjust max_sectors */ + ATA_DFLAG_LOCK_SECTORS = (1 << 2), /* don't adjust max_sectors */ ATA_DEV_UNKNOWN = 0, /* unknown device */ ATA_DEV_ATA = 1, /* ATA device */ -- cgit v1.2.3 From 04272d0f35b2e25f5ae1a23432260f771e652554 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Sat, 10 Jul 2004 04:47:34 -0400 Subject: [libata] ATAPI work - cdb len, new taskfile protocol, cleanups * new helper atapi_cdb_len() in linux/ata.h, use it after IDENTIFY PACKET DEVICE command completes * add new taskfile protocol ATA_PROT_ATAPI_NODATA * store scsi cdb in ata_queued_cmd. This removes another dependence on the scsi layer, and enables us to issue an internal REQUEST SENSE. * store cdb len in ata_port * new constant ATAPI_CDB_LEN for max cdb length * move ATA taskfile and SCSI cdb near the top of ata_queued_cmd, for better cacheline friendliness. --- drivers/scsi/libata-core.c | 25 +++++++++++++++++-------- drivers/scsi/libata-scsi.c | 19 +++++++++++-------- include/linux/ata.h | 15 ++++++++++++++- include/linux/libata.h | 5 ++++- 4 files changed, 46 insertions(+), 18 deletions(-) (limited to 'include') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 80b475accb8e..d9e63e74809e 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1099,10 +1099,13 @@ retry: if (ata_id_is_ata(dev)) /* sanity check */ goto err_out_nosup; - /* see if 16-byte commands supported */ - tmp = dev->id[0] & 0x3; - if (tmp == 1) - ap->host->max_cmd_len = 16; + rc = atapi_cdb_len(dev->id); + if ((rc < 12) || (rc > ATAPI_CDB_LEN)) { + printk(KERN_WARNING "ata%u: unsupported CDB len\n", ap->id); + goto err_out_nosup; + } + ap->cdb_len = (unsigned int) rc; + ap->host->max_cmd_len = (unsigned char) ap->cdb_len; /* print device info to dmesg */ printk(KERN_INFO "ata%u: dev %u ATAPI, max %s\n", @@ -2265,7 +2268,6 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc) /* fall through */ - case ATA_PROT_NODATA: default: ata_altstatus(ap); drv_stat = ata_chk_status(ap); @@ -2520,6 +2522,11 @@ int ata_qc_issue_prot(struct ata_queued_cmd *qc) queue_work(ata_wq, &ap->packet_task); break; + case ATA_PROT_ATAPI_NODATA: + ata_tf_to_host_nolock(ap, &qc->tf); + queue_work(ata_wq, &ap->packet_task); + break; + case ATA_PROT_ATAPI_DMA: ap->ops->tf_load(ap, &qc->tf); /* load tf registers */ ap->ops->bmdma_setup(qc); /* set up bmdma */ @@ -2685,6 +2692,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap, /* fall through */ + case ATA_PROT_ATAPI_NODATA: case ATA_PROT_NODATA: /* check altstatus */ status = ata_altstatus(ap); @@ -2795,19 +2803,20 @@ static void atapi_packet_task(void *_data) /* make sure DRQ is set */ status = ata_chk_status(ap); - if ((status & ATA_DRQ) == 0) + if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ) goto err_out; /* send SCSI cdb */ DPRINTK("send cdb\n"); - ata_data_xfer(ap, qc->scsicmd->cmnd, ap->host->max_cmd_len, 1); + assert(ap->cdb_len >= 12); + ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1); /* if we are DMA'ing, irq handler takes over from here */ if (qc->tf.protocol == ATA_PROT_ATAPI_DMA) ap->ops->bmdma_start(qc); /* initiate bmdma */ /* non-data commands are also handled via irq */ - else if (qc->scsicmd->sc_data_direction == SCSI_DATA_NONE) { + else if (qc->tf.protocol == ATA_PROT_ATAPI_NODATA) { /* do nothing */ } diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 484a64666247..0bfccede1e78 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -1002,6 +1002,9 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) struct scsi_cmnd *cmd = qc->scsicmd; struct ata_device *dev = qc->dev; int using_pio = (dev->flags & ATA_DFLAG_PIO); + int nodata = (cmd->sc_data_direction == SCSI_DATA_NONE); + + memcpy(&qc->cdb, scsicmd, qc->ap->cdb_len); qc->complete_fn = atapi_qc_complete; @@ -1013,18 +1016,18 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) qc->tf.command = ATA_CMD_PACKET; - /* no data - interrupt-driven */ - if (cmd->sc_data_direction == SCSI_DATA_NONE) - qc->tf.protocol = ATA_PROT_ATAPI; - - /* PIO data xfer */ - else if (using_pio) { - qc->tf.protocol = ATA_PROT_ATAPI; + /* no data, or PIO data xfer */ + if (using_pio || nodata) { + if (nodata) + qc->tf.protocol = ATA_PROT_ATAPI_NODATA; + else + qc->tf.protocol = ATA_PROT_ATAPI; qc->tf.lbam = (8 * 1024) & 0xff; qc->tf.lbah = (8 * 1024) >> 8; + } /* DMA data xfer */ - } else { + else { qc->tf.protocol = ATA_PROT_ATAPI_DMA; qc->tf.feature |= ATAPI_PKT_DMA; diff --git a/include/linux/ata.h b/include/linux/ata.h index c8c5a0385414..58c84a4b31f4 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -147,6 +147,7 @@ enum { ATAPI_PKT_DMA = (1 << 0), ATAPI_DMADIR = (1 << 2), /* ATAPI data dir: 0=to device, 1=to host */ + ATAPI_CDB_LEN = 16, /* cable types */ ATA_CBL_NONE = 0, @@ -176,7 +177,8 @@ enum ata_tf_protocols { ATA_PROT_PIO, /* PIO single sector */ ATA_PROT_PIO_MULT, /* PIO multiple sector */ ATA_PROT_DMA, /* DMA */ - ATA_PROT_ATAPI, /* packet command */ + ATA_PROT_ATAPI, /* packet command, PIO data xfer*/ + ATA_PROT_ATAPI_NODATA, /* packet command, no data */ ATA_PROT_ATAPI_DMA, /* packet command with special DMA sauce */ }; @@ -227,9 +229,20 @@ struct ata_taskfile { ((u64) dev->id[(n) + 1] << 16) | \ ((u64) dev->id[(n) + 0]) ) +static inline int atapi_cdb_len(u16 *dev_id) +{ + u16 tmp = dev_id[0] & 0x3; + switch (tmp) { + case 0: return 12; + case 1: return 16; + default: return -1; + } +} + static inline int is_atapi_taskfile(struct ata_taskfile *tf) { return (tf->protocol == ATA_PROT_ATAPI) || + (tf->protocol == ATA_PROT_ATAPI_NODATA) || (tf->protocol == ATA_PROT_ATAPI_DMA); } diff --git a/include/linux/libata.h b/include/linux/libata.h index 42a9bde8e42d..8443cce6971f 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -218,6 +218,9 @@ struct ata_queued_cmd { struct scsi_cmnd *scsicmd; void (*scsidone)(struct scsi_cmnd *); + struct ata_taskfile tf; + u8 cdb[ATAPI_CDB_LEN]; + unsigned long flags; /* ATA_QCFLAG_xxx */ unsigned int tag; unsigned int n_elem; @@ -229,7 +232,6 @@ struct ata_queued_cmd { unsigned int cursg; unsigned int cursg_ofs; - struct ata_taskfile tf; struct scatterlist sgent; void *buf_virt; @@ -285,6 +287,7 @@ struct ata_port { unsigned int mwdma_mask; unsigned int udma_mask; unsigned int cbl; /* cable type; ATA_CBL_xxx */ + unsigned int cdb_len; struct ata_device device[ATA_MAX_DEVICES]; -- cgit v1.2.3