* RETURNS:
* Packed xfer_mask.
*/
-unsigned int ata_pack_xfermask(unsigned int pio_mask,
- unsigned int mwdma_mask, unsigned int udma_mask)
+unsigned long ata_pack_xfermask(unsigned long pio_mask,
+ unsigned long mwdma_mask,
+ unsigned long udma_mask)
{
return ((pio_mask << ATA_SHIFT_PIO) & ATA_MASK_PIO) |
((mwdma_mask << ATA_SHIFT_MWDMA) & ATA_MASK_MWDMA) |
* Unpack @xfer_mask into @pio_mask, @mwdma_mask and @udma_mask.
* Any NULL distination masks will be ignored.
*/
-void ata_unpack_xfermask(unsigned int xfer_mask, unsigned int *pio_mask,
- unsigned int *mwdma_mask, unsigned int *udma_mask)
+void ata_unpack_xfermask(unsigned long xfer_mask, unsigned long *pio_mask,
+ unsigned long *mwdma_mask, unsigned long *udma_mask)
{
if (pio_mask)
*pio_mask = (xfer_mask & ATA_MASK_PIO) >> ATA_SHIFT_PIO;
* RETURNS:
* Matching XFER_* value, 0xff if no match found.
*/
-u8 ata_xfer_mask2mode(unsigned int xfer_mask)
+u8 ata_xfer_mask2mode(unsigned long xfer_mask)
{
int highbit = fls(xfer_mask) - 1;
const struct ata_xfer_ent *ent;
* RETURNS:
* Matching xfer_mask, 0 if no match found.
*/
-unsigned int ata_xfer_mode2mask(u8 xfer_mode)
+unsigned long ata_xfer_mode2mask(u8 xfer_mode)
{
const struct ata_xfer_ent *ent;
* RETURNS:
* Matching xfer_shift, -1 if no match found.
*/
-int ata_xfer_mode2shift(unsigned int xfer_mode)
+int ata_xfer_mode2shift(unsigned long xfer_mode)
{
const struct ata_xfer_ent *ent;
* Constant C string representing highest speed listed in
* @mode_mask, or the constant C string "<n/a>".
*/
-const char *ata_mode_string(unsigned int xfer_mask)
+const char *ata_mode_string(unsigned long xfer_mask)
{
static const char * const xfer_mode_str[] = {
"PIO0",
return 0;
}
-/**
- * ata_id_to_dma_mode - Identify DMA mode from id block
- * @dev: device to identify
- * @unknown: mode to assume if we cannot tell
- *
- * Set up the timing values for the device based upon the identify
- * reported values for the DMA mode. This function is used by drivers
- * which rely upon firmware configured modes, but wish to report the
- * mode correctly when possible.
- *
- * In addition we emit similarly formatted messages to the default
- * ata_dev_set_mode handler, in order to provide consistency of
- * presentation.
- */
-
-void ata_id_to_dma_mode(struct ata_device *dev, u8 unknown)
-{
- unsigned int mask;
- u8 mode;
-
- /* Pack the DMA modes */
- mask = ((dev->id[63] >> 8) << ATA_SHIFT_MWDMA) & ATA_MASK_MWDMA;
- if (dev->id[53] & 0x04)
- mask |= ((dev->id[88] >> 8) << ATA_SHIFT_UDMA) & ATA_MASK_UDMA;
-
- /* Select the mode in use */
- mode = ata_xfer_mask2mode(mask);
-
- if (mode != 0xff) {
- ata_dev_printk(dev, KERN_INFO, "configured for %s\n",
- ata_mode_string(mask));
- } else {
- /* SWDMA perhaps ? */
- mode = unknown;
- ata_dev_printk(dev, KERN_INFO, "configured for DMA\n");
- }
-
- /* Configure the device reporting */
- dev->xfer_mode = mode;
- dev->xfer_shift = ata_xfer_mode2shift(mode);
-}
-
/**
* ata_noop_dev_select - Select device 0/1 on ATA bus
* @ap: ATA channel to manipulate
* RETURNS:
* Computed xfermask
*/
-unsigned int ata_id_xfermask(const u16 *id)
+unsigned long ata_id_xfermask(const u16 *id)
{
- unsigned int pio_mask, mwdma_mask, udma_mask;
+ unsigned long pio_mask, mwdma_mask, udma_mask;
/* Usual case. Word 53 indicates word 64 is valid */
if (id[ATA_ID_FIELD_VALID] & (1 << 1)) {
struct ata_eh_context *ehc = &dev->link->eh_context;
int print_info = ehc->i.flags & ATA_EHI_PRINTINFO;
const u16 *id = dev->id;
- unsigned int xfer_mask;
+ unsigned long xfer_mask;
char revbuf[7]; /* XYZ-99\0 */
char fwrevbuf[ATA_ID_FW_REV_LEN+1];
char modelbuf[ATA_ID_PROD_LEN+1];
return ATA_CBL_PATA_UNK;
}
+/**
+ * ata_cable_ignore - return ignored PATA cable.
+ * @ap: port
+ *
+ * Helper method for drivers which don't use cable type to limit
+ * transfer mode.
+ */
+int ata_cable_ignore(struct ata_port *ap)
+{
+ return ATA_CBL_PATA_IGN;
+}
+
/**
* ata_cable_sata - return SATA cable type
* @ap: port
return 0;
}
+/**
+ * ata_timing_cycle2mode - find xfer mode for the specified cycle duration
+ * @xfer_shift: ATA_SHIFT_* value for transfer type to examine.
+ * @cycle: cycle duration in ns
+ *
+ * Return matching xfer mode for @cycle. The returned mode is of
+ * the transfer type specified by @xfer_shift. If @cycle is too
+ * slow for @xfer_shift, 0xff is returned. If @cycle is faster
+ * than the fastest known mode, the fasted mode is returned.
+ *
+ * LOCKING:
+ * None.
+ *
+ * RETURNS:
+ * Matching xfer_mode, 0xff if no match found.
+ */
+u8 ata_timing_cycle2mode(unsigned int xfer_shift, int cycle)
+{
+ u8 base_mode = 0xff, last_mode = 0xff;
+ const struct ata_xfer_ent *ent;
+ const struct ata_timing *t;
+
+ for (ent = ata_xfer_tbl; ent->shift >= 0; ent++)
+ if (ent->shift == xfer_shift)
+ base_mode = ent->base;
+
+ for (t = ata_timing_find_mode(base_mode);
+ t && ata_xfer_mode2shift(t->mode) == xfer_shift; t++) {
+ unsigned short this_cycle;
+
+ switch (xfer_shift) {
+ case ATA_SHIFT_PIO:
+ case ATA_SHIFT_MWDMA:
+ this_cycle = t->cycle;
+ break;
+ case ATA_SHIFT_UDMA:
+ this_cycle = t->udma;
+ break;
+ default:
+ return 0xff;
+ }
+
+ if (cycle > this_cycle)
+ break;
+
+ last_mode = t->mode;
+ }
+
+ return last_mode;
+}
+
/**
* ata_down_xfermask_limit - adjust dev xfer masks downward
* @dev: Device to adjust xfer masks
int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel)
{
char buf[32];
- unsigned int orig_mask, xfer_mask;
- unsigned int pio_mask, mwdma_mask, udma_mask;
+ unsigned long orig_mask, xfer_mask;
+ unsigned long pio_mask, mwdma_mask, udma_mask;
int quiet, highbit;
quiet = !!(sel & ATA_DNXFER_QUIET);
/* step 1: calculate xfer_mask */
ata_link_for_each_dev(dev, link) {
- unsigned int pio_mask, dma_mask;
+ unsigned long pio_mask, dma_mask;
unsigned int mode_mask;
if (!ata_dev_enabled(dev))
WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP));
WARN_ON(sg == NULL);
- if (qc->flags & ATA_QCFLAG_SINGLE)
- WARN_ON(qc->n_elem > 1);
-
VPRINTK("unmapping %u sg elements\n", qc->n_elem);
/* if we padded the buffer out to 32-bit bound, and data
if (qc->pad_len && !(qc->tf.flags & ATA_TFLAG_WRITE))
pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ);
- if (qc->flags & ATA_QCFLAG_SG) {
- if (qc->n_elem)
- dma_unmap_sg(ap->dev, sg, qc->n_elem, dir);
- /* restore last sg */
- sg_last(sg, qc->orig_n_elem)->length += qc->pad_len;
- if (pad_buf) {
- struct scatterlist *psg = &qc->pad_sgent;
- void *addr = kmap_atomic(sg_page(psg), KM_IRQ0);
- memcpy(addr + psg->offset, pad_buf, qc->pad_len);
- kunmap_atomic(addr, KM_IRQ0);
- }
- } else {
- if (qc->n_elem)
- dma_unmap_single(ap->dev,
- sg_dma_address(&sg[0]), sg_dma_len(&sg[0]),
- dir);
- /* restore sg */
- sg->length += qc->pad_len;
- if (pad_buf)
- memcpy(qc->buf_virt + sg->length - qc->pad_len,
- pad_buf, qc->pad_len);
+ if (qc->n_elem)
+ dma_unmap_sg(ap->dev, sg, qc->n_elem, dir);
+ /* restore last sg */
+ sg_last(sg, qc->orig_n_elem)->length += qc->pad_len;
+ if (pad_buf) {
+ struct scatterlist *psg = &qc->pad_sgent;
+ void *addr = kmap_atomic(sg_page(psg), KM_IRQ0);
+ memcpy(addr + psg->offset, pad_buf, qc->pad_len);
+ kunmap_atomic(addr, KM_IRQ0);
}
qc->flags &= ~ATA_QCFLAG_DMAMAP;
*/
static int atapi_qc_may_overflow(struct ata_queued_cmd *qc)
{
- if (qc->tf.protocol != ATA_PROT_ATAPI &&
- qc->tf.protocol != ATA_PROT_ATAPI_DMA)
+ if (qc->tf.protocol != ATAPI_PROT_PIO &&
+ qc->tf.protocol != ATAPI_PROT_DMA)
return 0;
if (qc->tf.flags & ATA_TFLAG_WRITE)
void ata_noop_qc_prep(struct ata_queued_cmd *qc) { }
-/**
- * ata_sg_init_one - Associate command with memory buffer
- * @qc: Command to be associated
- * @buf: Memory buffer
- * @buflen: Length of memory buffer, in bytes.
- *
- * Initialize the data-related elements of queued_cmd @qc
- * to point to a single memory buffer, @buf of byte length @buflen.
- *
- * LOCKING:
- * spin_lock_irqsave(host lock)
- */
-
-void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen)
-{
- qc->flags |= ATA_QCFLAG_SINGLE;
-
- qc->__sg = &qc->sgent;
- qc->n_elem = 1;
- qc->orig_n_elem = 1;
- qc->buf_virt = buf;
- qc->nbytes = buflen;
- qc->cursg = qc->__sg;
-
- sg_init_one(&qc->sgent, buf, buflen);
-}
-
/**
* ata_sg_init - Associate command with scatter-gather table.
* @qc: Command to be associated
void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
unsigned int n_elem)
{
- qc->flags |= ATA_QCFLAG_SG;
+ qc->flags |= ATA_QCFLAG_DMAMAP;
qc->__sg = sg;
qc->n_elem = n_elem;
qc->orig_n_elem = n_elem;
qc->cursg = qc->__sg;
}
-/**
- * ata_sg_setup_one - DMA-map the memory buffer associated with a command.
- * @qc: Command with memory buffer to be mapped.
- *
- * DMA-map the memory buffer associated with queued_cmd @qc.
- *
- * LOCKING:
- * spin_lock_irqsave(host lock)
- *
- * RETURNS:
- * Zero on success, negative on error.
- */
-
-static int ata_sg_setup_one(struct ata_queued_cmd *qc)
-{
- struct ata_port *ap = qc->ap;
- int dir = qc->dma_dir;
- struct scatterlist *sg = qc->__sg;
- dma_addr_t dma_address;
- int trim_sg = 0;
-
- /* we must lengthen transfers to end on a 32-bit boundary */
- qc->pad_len = sg->length & 3;
- if (qc->pad_len) {
- void *pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ);
- struct scatterlist *psg = &qc->pad_sgent;
-
- WARN_ON(qc->dev->class != ATA_DEV_ATAPI);
-
- memset(pad_buf, 0, ATA_DMA_PAD_SZ);
-
- if (qc->tf.flags & ATA_TFLAG_WRITE)
- memcpy(pad_buf, qc->buf_virt + sg->length - qc->pad_len,
- qc->pad_len);
-
- sg_dma_address(psg) = ap->pad_dma + (qc->tag * ATA_DMA_PAD_SZ);
- sg_dma_len(psg) = ATA_DMA_PAD_SZ;
- /* trim sg */
- sg->length -= qc->pad_len;
- if (sg->length == 0)
- trim_sg = 1;
-
- DPRINTK("padding done, sg->length=%u pad_len=%u\n",
- sg->length, qc->pad_len);
- }
-
- if (trim_sg) {
- qc->n_elem--;
- goto skip_map;
- }
-
- dma_address = dma_map_single(ap->dev, qc->buf_virt,
- sg->length, dir);
- if (dma_mapping_error(dma_address)) {
- /* restore sg */
- sg->length += qc->pad_len;
- return -1;
- }
-
- sg_dma_address(sg) = dma_address;
- sg_dma_len(sg) = sg->length;
-
-skip_map:
- DPRINTK("mapped buffer of %d bytes for %s\n", sg_dma_len(sg),
- qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
-
- return 0;
-}
-
/**
* ata_sg_setup - DMA-map the scatter-gather table associated with a command.
* @qc: Command with scatter-gather table to be mapped.
int n_elem, pre_n_elem, dir, trim_sg = 0;
VPRINTK("ENTER, ata%u\n", ap->print_id);
- WARN_ON(!(qc->flags & ATA_QCFLAG_SG));
+ WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP));
/* we must lengthen transfers to end on a 32-bit boundary */
qc->pad_len = lsg->length & 3;
/**
* ata_data_xfer - Transfer data by PIO
- * @adev: device to target
+ * @dev: device to target
* @buf: data buffer
* @buflen: buffer length
* @write_data: read/write
*
* LOCKING:
* Inherited from caller.
+ *
+ * RETURNS:
+ * Bytes consumed.
*/
-void ata_data_xfer(struct ata_device *adev, unsigned char *buf,
- unsigned int buflen, int write_data)
+unsigned int ata_data_xfer(struct ata_device *dev, unsigned char *buf,
+ unsigned int buflen, int rw)
{
- struct ata_port *ap = adev->link->ap;
+ struct ata_port *ap = dev->link->ap;
+ void __iomem *data_addr = ap->ioaddr.data_addr;
unsigned int words = buflen >> 1;
/* Transfer multiple of 2 bytes */
- if (write_data)
- iowrite16_rep(ap->ioaddr.data_addr, buf, words);
+ if (rw == READ)
+ ioread16_rep(data_addr, buf, words);
else
- ioread16_rep(ap->ioaddr.data_addr, buf, words);
+ iowrite16_rep(data_addr, buf, words);
/* Transfer trailing 1 byte, if any. */
if (unlikely(buflen & 0x01)) {
u16 align_buf[1] = { 0 };
unsigned char *trailing_buf = buf + buflen - 1;
- if (write_data) {
- memcpy(align_buf, trailing_buf, 1);
- iowrite16(le16_to_cpu(align_buf[0]), ap->ioaddr.data_addr);
- } else {
- align_buf[0] = cpu_to_le16(ioread16(ap->ioaddr.data_addr));
+ if (rw == READ) {
+ align_buf[0] = cpu_to_le16(ioread16(data_addr));
memcpy(trailing_buf, align_buf, 1);
+ } else {
+ memcpy(align_buf, trailing_buf, 1);
+ iowrite16(le16_to_cpu(align_buf[0]), data_addr);
}
+ words++;
}
+
+ return words << 1;
}
/**
* ata_data_xfer_noirq - Transfer data by PIO
- * @adev: device to target
+ * @dev: device to target
* @buf: data buffer
* @buflen: buffer length
* @write_data: read/write
*
* LOCKING:
* Inherited from caller.
+ *
+ * RETURNS:
+ * Bytes consumed.
*/
-void ata_data_xfer_noirq(struct ata_device *adev, unsigned char *buf,
- unsigned int buflen, int write_data)
+unsigned int ata_data_xfer_noirq(struct ata_device *dev, unsigned char *buf,
+ unsigned int buflen, int rw)
{
unsigned long flags;
+ unsigned int consumed;
+
local_irq_save(flags);
- ata_data_xfer(adev, buf, buflen, write_data);
+ consumed = ata_data_xfer(dev, buf, buflen, rw);
local_irq_restore(flags);
+
+ return consumed;
}
ata_altstatus(ap); /* flush */
switch (qc->tf.protocol) {
- case ATA_PROT_ATAPI:
+ case ATAPI_PROT_PIO:
ap->hsm_task_state = HSM_ST;
break;
- case ATA_PROT_ATAPI_NODATA:
+ case ATAPI_PROT_NODATA:
ap->hsm_task_state = HSM_ST_LAST;
break;
- case ATA_PROT_ATAPI_DMA:
+ case ATAPI_PROT_DMA:
ap->hsm_task_state = HSM_ST_LAST;
/* initiate bmdma */
ap->ops->bmdma_start(qc);
bytes = (bc_hi << 8) | bc_lo;
/* shall be cleared to zero, indicating xfer of data */
- if (ireason & (1 << 0))
+ if (unlikely(ireason & (1 << 0)))
goto err_out;
/* make sure transfer direction matches expected */
i_write = ((ireason & (1 << 1)) == 0) ? 1 : 0;
- if (do_write != i_write)
+ if (unlikely(do_write != i_write))
+ goto err_out;
+
+ if (unlikely(!bytes))
goto err_out;
VPRINTK("ata%u: xfering %d bytes\n", ap->print_id, bytes);
case HSM_ST:
/* complete command or read/write the data register */
- if (qc->tf.protocol == ATA_PROT_ATAPI) {
+ if (qc->tf.protocol == ATAPI_PROT_PIO) {
/* ATAPI PIO protocol */
if ((status & ATA_DRQ) == 0) {
/* No more data to transfer or device error.
*/
WARN_ON(ap->ops->error_handler && ata_tag_valid(link->active_tag));
- if (prot == ATA_PROT_NCQ) {
+ if (ata_is_ncq(prot)) {
WARN_ON(link->sactive & (1 << qc->tag));
if (!link->sactive)
if (ata_is_dma(prot) || (ata_is_pio(prot) &&
(ap->flags & ATA_FLAG_PIO_DMA))) {
- if (qc->flags & ATA_QCFLAG_SG) {
- if (ata_sg_setup(qc))
- goto sg_err;
- } else if (qc->flags & ATA_QCFLAG_SINGLE) {
- if (ata_sg_setup_one(qc))
- goto sg_err;
- }
- } else {
- qc->flags &= ~ATA_QCFLAG_DMAMAP;
- }
+ if (ata_sg_setup(qc))
+ goto sg_err;
+ } else
+ qc->flags &= ATA_QCFLAG_DMAMAP;
/* if device is sleeping, schedule softreset and abort the link */
if (unlikely(qc->dev->flags & ATA_DFLAG_SLEEPING)) {
switch (qc->tf.protocol) {
case ATA_PROT_PIO:
case ATA_PROT_NODATA:
- case ATA_PROT_ATAPI:
- case ATA_PROT_ATAPI_NODATA:
+ case ATAPI_PROT_PIO:
+ case ATAPI_PROT_NODATA:
qc->tf.flags |= ATA_TFLAG_POLLING;
break;
- case ATA_PROT_ATAPI_DMA:
+ case ATAPI_PROT_DMA:
if (qc->dev->flags & ATA_DFLAG_CDB_INTR)
/* see ata_dma_blacklisted() */
BUG();
break;
- case ATA_PROT_ATAPI:
- case ATA_PROT_ATAPI_NODATA:
+ case ATAPI_PROT_PIO:
+ case ATAPI_PROT_NODATA:
if (qc->tf.flags & ATA_TFLAG_POLLING)
ata_qc_set_polling(qc);
ata_port_queue_task(ap, ata_pio_task, qc, 0);
break;
- case ATA_PROT_ATAPI_DMA:
+ case ATAPI_PROT_DMA:
WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING);
ap->ops->tf_load(ap, &qc->tf); /* load tf registers */
break;
case HSM_ST_LAST:
if (qc->tf.protocol == ATA_PROT_DMA ||
- qc->tf.protocol == ATA_PROT_ATAPI_DMA) {
+ qc->tf.protocol == ATAPI_PROT_DMA) {
/* check status of DMA engine */
host_stat = ap->ops->bmdma_status(ap);
VPRINTK("ata%u: host_stat 0x%X\n",
ata_hsm_move(ap, qc, status, 0);
if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA ||
- qc->tf.protocol == ATA_PROT_ATAPI_DMA))
+ qc->tf.protocol == ATAPI_PROT_DMA))
ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat);
return 1; /* irq handled */
EXPORT_SYMBOL_GPL(ata_host_activate);
EXPORT_SYMBOL_GPL(ata_host_detach);
EXPORT_SYMBOL_GPL(ata_sg_init);
-EXPORT_SYMBOL_GPL(ata_sg_init_one);
EXPORT_SYMBOL_GPL(ata_hsm_move);
EXPORT_SYMBOL_GPL(ata_qc_complete);
EXPORT_SYMBOL_GPL(ata_qc_complete_multiple);
#endif /* CONFIG_PM */
EXPORT_SYMBOL_GPL(ata_id_string);
EXPORT_SYMBOL_GPL(ata_id_c_string);
-EXPORT_SYMBOL_GPL(ata_id_to_dma_mode);
EXPORT_SYMBOL_GPL(ata_scsi_simulate);
EXPORT_SYMBOL_GPL(ata_pio_need_iordy);
EXPORT_SYMBOL_GPL(ata_timing_find_mode);
EXPORT_SYMBOL_GPL(ata_timing_compute);
EXPORT_SYMBOL_GPL(ata_timing_merge);
+EXPORT_SYMBOL_GPL(ata_timing_cycle2mode);
#ifdef CONFIG_PCI
EXPORT_SYMBOL_GPL(pci_test_config_bits);
EXPORT_SYMBOL_GPL(ata_cable_40wire);
EXPORT_SYMBOL_GPL(ata_cable_80wire);
EXPORT_SYMBOL_GPL(ata_cable_unknown);
+EXPORT_SYMBOL_GPL(ata_cable_ignore);
EXPORT_SYMBOL_GPL(ata_cable_sata);