#include <linux/jiffies.h>
#include <linux/scatterlist.h>
#include <scsi/scsi.h>
-#include "scsi.h"
#include "scsi_priv.h"
+#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_host.h>
#include <linux/libata.h>
#include <asm/io.h>
* @fis: Buffer from which data will be input
* @tf: Taskfile to output
*
- * Converts a standard ATA taskfile to a Serial ATA
- * FIS structure (Register - Host to Device).
+ * Converts a serial ATA FIS structure to a standard ATA taskfile.
*
* LOCKING:
* Inherited from caller.
* ATA software reset (SRST, the default) does not appear
* to have this problem.
*/
- if ((using_edd) && (qc->tf.command == ATA_CMD_ID_ATA)) {
+ if ((using_edd) && (dev->class == ATA_DEV_ATA)) {
u8 err = qc->tf.feature;
if (err & ATA_ABORTED) {
dev->class = ATA_DEV_ATAPI;
}
/* ATAPI-specific feature tests */
- else {
+ else if (dev->class == ATA_DEV_ATAPI) {
if (ata_id_is_ata(dev->id)) /* sanity check */
goto err_out_nosup;
/*
* Find the mode.
- */
+ */
if (!(s = ata_timing_find_mode(speed)))
return -EINVAL;
+ memcpy(t, s, sizeof(*s));
+
/*
* If the drive is an EIDE drive, it can tell us it needs extended
* PIO/MW_DMA cycle timing.
* Convert the timing to bus clock counts.
*/
- ata_timing_quantize(s, t, T, UT);
+ ata_timing_quantize(t, t, T, UT);
/*
* Even in DMA/UDMA modes we still use PIO access for IDENTIFY, S.M.A.R.T
if (qc->flags & ATA_QCFLAG_SINGLE)
assert(qc->n_elem == 1);
- DPRINTK("unmapping %u sg elements\n", qc->n_elem);
+ VPRINTK("unmapping %u sg elements\n", qc->n_elem);
/* if we padded the buffer out to 32-bit bound, and data
* xfer direction is from-device, we must copy from the
pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ);
if (qc->flags & ATA_QCFLAG_SG) {
- dma_unmap_sg(ap->host_set->dev, sg, qc->n_elem, dir);
+ if (qc->n_elem)
+ dma_unmap_sg(ap->host_set->dev, sg, qc->n_elem, dir);
/* restore last sg */
sg[qc->orig_n_elem - 1].length += qc->pad_len;
if (pad_buf) {
kunmap_atomic(psg->page, KM_IRQ0);
}
} else {
- dma_unmap_single(ap->host_set->dev, sg_dma_address(&sg[0]),
- sg_dma_len(&sg[0]), dir);
+ if (sg_dma_len(&sg[0]) > 0)
+ dma_unmap_single(ap->host_set->dev,
+ sg_dma_address(&sg[0]), sg_dma_len(&sg[0]),
+ dir);
/* restore sg */
sg->length += qc->pad_len;
if (pad_buf)
sg->length, qc->pad_len);
}
+ if (!sg->length) {
+ sg_dma_address(sg) = 0;
+ goto skip_map;
+ }
+
dma_address = dma_map_single(ap->host_set->dev, qc->buf_virt,
sg->length, dir);
- if (dma_mapping_error(dma_address))
+ if (dma_mapping_error(dma_address)) {
+ /* restore sg */
+ sg->length += qc->pad_len;
return -1;
+ }
sg_dma_address(sg) = dma_address;
+skip_map:
sg_dma_len(sg) = sg->length;
DPRINTK("mapped buffer of %d bytes for %s\n", sg_dma_len(sg),
struct ata_port *ap = qc->ap;
struct scatterlist *sg = qc->__sg;
struct scatterlist *lsg = &sg[qc->n_elem - 1];
- int n_elem, dir;
+ int n_elem, pre_n_elem, dir, trim_sg = 0;
VPRINTK("ENTER, ata%u\n", ap->id);
assert(qc->flags & ATA_QCFLAG_SG);
sg_dma_len(psg) = ATA_DMA_PAD_SZ;
/* trim last sg */
lsg->length -= qc->pad_len;
+ if (lsg->length == 0)
+ trim_sg = 1;
DPRINTK("padding done, sg[%d].length=%u pad_len=%u\n",
qc->n_elem - 1, lsg->length, qc->pad_len);
}
+ pre_n_elem = qc->n_elem;
+ if (trim_sg && pre_n_elem)
+ pre_n_elem--;
+
+ if (!pre_n_elem) {
+ n_elem = 0;
+ goto skip_map;
+ }
+
dir = qc->dma_dir;
- n_elem = dma_map_sg(ap->host_set->dev, sg, qc->n_elem, dir);
- if (n_elem < 1)
+ n_elem = dma_map_sg(ap->host_set->dev, sg, pre_n_elem, dir);
+ if (n_elem < 1) {
+ /* restore last sg */
+ lsg->length += qc->pad_len;
return -1;
+ }
DPRINTK("%d sg elements mapped\n", n_elem);
+skip_map:
qc->n_elem = n_elem;
return 0;
/**
* ata_poll_qc_complete - turn irq back on and finish qc
* @qc: Command to complete
- * @drv_stat: ATA status register content
+ * @err_mask: ATA status register content
*
* LOCKING:
* None. (grabs host lock)
u8 status;
unsigned int poll_state = HSM_ST_UNKNOWN;
unsigned int reg_state = HSM_ST_UNKNOWN;
- const unsigned int tmout_state = HSM_ST_TMOUT;
switch (ap->hsm_task_state) {
case HSM_ST:
status = ata_chk_status(ap);
if (status & ATA_BUSY) {
if (time_after(jiffies, ap->pio_task_timeout)) {
- ap->hsm_task_state = tmout_state;
+ ap->hsm_task_state = HSM_ST_TMOUT;
return 0;
}
ap->hsm_task_state = poll_state;
{
struct ata_port *ap = qc->ap;
struct ata_host_set *host_set = ap->host_set;
- struct ata_device *dev = qc->dev;
u8 host_stat = 0, drv_stat;
unsigned long flags;
DPRINTK("ENTER\n");
- /* FIXME: doesn't this conflict with timeout handling? */
- if (qc->dev->class == ATA_DEV_ATAPI && qc->scsicmd) {
- struct scsi_cmnd *cmd = qc->scsicmd;
-
- if (!(cmd->eh_eflags & SCSI_EH_CANCEL_CMD)) {
-
- /* finish completing original command */
- spin_lock_irqsave(&host_set->lock, flags);
- __ata_qc_complete(qc);
- spin_unlock_irqrestore(&host_set->lock, flags);
-
- atapi_request_sense(ap, dev, cmd);
-
- cmd->result = (CHECK_CONDITION << 1) | (DID_OK << 16);
- scsi_finish_command(cmd);
-
- goto out;
- }
- }
-
spin_lock_irqsave(&host_set->lock, flags);
/* hack alert! We cannot use the supplied completion
spin_unlock_irqrestore(&host_set->lock, flags);
-out:
DPRINTK("EXIT\n");
}
qc = ata_qc_new(ap);
if (qc) {
- qc->__sg = NULL;
- qc->flags = 0;
qc->scsicmd = NULL;
qc->ap = ap;
qc->dev = dev;
- qc->cursect = qc->cursg = qc->cursg_ofs = 0;
- qc->nsect = 0;
- qc->nbytes = qc->curbytes = 0;
- ata_tf_init(ap, &qc->tf, dev->devno);
+ ata_qc_reinit(qc);
}
return qc;
/**
* ata_qc_complete - Complete an active ATA command
* @qc: Command to complete
- * @drv_stat: ATA Status register contents
+ * @err_mask: ATA Status register contents
*
* Indicate to the mid and upper layers that an ATA
* command has completed, with either an ok or not-ok status.
int ata_port_start (struct ata_port *ap)
{
struct device *dev = ap->host_set->dev;
+ int rc;
ap->prd = dma_alloc_coherent(dev, ATA_PRD_TBL_SZ, &ap->prd_dma, GFP_KERNEL);
if (!ap->prd)
return -ENOMEM;
- ap->pad = dma_alloc_coherent(dev, ATA_DMA_PAD_BUF_SZ, &ap->pad_dma, GFP_KERNEL);
- if (!ap->pad) {
+ rc = ata_pad_alloc(ap, dev);
+ if (rc) {
dma_free_coherent(dev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma);
- return -ENOMEM;
+ return rc;
}
DPRINTK("prd alloc, virt %p, dma %llx\n", ap->prd, (unsigned long long) ap->prd_dma);
struct device *dev = ap->host_set->dev;
dma_free_coherent(dev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma);
- dma_free_coherent(dev, ATA_DMA_PAD_BUF_SZ, ap->pad, ap->pad_dma);
+ ata_pad_free(ap, dev);
}
void ata_host_stop (struct ata_host_set *host_set)
probe_ent->irq = pdev->irq;
probe_ent->irq_flags = SA_SHIRQ;
+ probe_ent->private_data = port[0]->private_data;
if (ports & ATA_PORT_PRIMARY) {
probe_ent->port[p].cmd_addr = pci_resource_start(pdev, 0);
probe_ent->legacy_mode = 1;
probe_ent->n_ports = 1;
probe_ent->hard_port_no = port_num;
+ probe_ent->private_data = port->private_data;
switch(port_num)
{