static int ata_choose_xfer_mode(const struct ata_port *ap,
u8 *xfer_mode_out,
unsigned int *xfer_shift_out);
+static void ata_pio_error(struct ata_port *ap);
static unsigned int ata_unique_id = 1;
static struct workqueue_struct *ata_wq;
} else if (lba48 && (qc->ap->flags & ATA_FLAG_PIO_LBA48)) {
/* Unable to use DMA due to host limitation */
tf->protocol = ATA_PROT_PIO;
- index = dev->multi_count ? 0 : 4;
+ index = dev->multi_count ? 0 : 8;
} else {
tf->protocol = ATA_PROT_DMA;
index = 16;
timing API will get this right anyway */
}
-static inline void
-ata_queue_packet_task(struct ata_port *ap)
-{
- if (!(ap->flags & ATA_FLAG_FLUSH_PIO_TASK))
- queue_work(ata_wq, &ap->packet_task);
-}
-
static inline void
ata_queue_pio_task(struct ata_port *ap)
{
}
/**
- * ata_flush_pio_tasks - Flush pio_task and packet_task
+ * ata_flush_pio_tasks - Flush pio_task
* @ap: the target ata_port
*
- * After this function completes, pio_task and packet_task are
+ * After this function completes, pio_task is
* guranteed not to be running or scheduled.
*
* LOCKING:
* Cancel and flush.
*/
tmp |= cancel_delayed_work(&ap->pio_task);
- tmp |= cancel_delayed_work(&ap->packet_task);
if (!tmp) {
DPRINTK("flush #2\n");
flush_workqueue(ata_wq);
DPRINTK("ENTER, host %u, dev %u\n", ap->id, device);
- assert (dev->class == ATA_DEV_ATA || dev->class == ATA_DEV_ATAPI ||
- dev->class == ATA_DEV_NONE);
+ WARN_ON(dev->class != ATA_DEV_ATA && dev->class != ATA_DEV_ATAPI &&
+ dev->class != ATA_DEV_NONE);
ata_dev_select(ap, device, 1, 1); /* select device 0/1 */
}
+ if (dev->id[59] & 0x100) {
+ dev->multi_count = dev->id[59] & 0xff;
+ DPRINTK("ata%u: dev %u multi count %u\n",
+ ap->id, device, dev->multi_count);
+ }
+
ap->host->max_cmd_len = 16;
}
ap->cdb_len = (unsigned int) rc;
ap->host->max_cmd_len = (unsigned char) ap->cdb_len;
+ if (ata_id_cdb_intr(dev->id))
+ dev->flags |= ATA_DFLAG_CDB_INTR;
+
/* print device info to dmesg */
printk(KERN_INFO "ata%u: dev %u ATAPI, max %s\n",
ap->id, device,
*
* @ap is about to be probed. Initialize it. This function is
* to be used as standard callback for ata_drive_probe_reset().
+ *
+ * NOTE!!! Do not use this function as probeinit if a low level
+ * driver implements only hardreset. Just pass NULL as probeinit
+ * in that case. Using this function is probably okay but doing
+ * so makes reset sequence different from the original
+ * ->phy_reset implementation and Jeff nervous. :-P
*/
extern void ata_std_probeinit(struct ata_port *ap)
{
- if (ap->flags & ATA_FLAG_SATA && ap->ops->scr_read)
+ if (ap->flags & ATA_FLAG_SATA && ap->ops->scr_read) {
sata_phy_resume(ap);
+ if (sata_dev_present(ap))
+ ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+ }
}
/**
DPRINTK("ENTER\n");
+ if (ap->ops->scr_read && !sata_dev_present(ap)) {
+ classes[0] = ATA_DEV_NONE;
+ goto out;
+ }
+
/* determine if device 0/1 are present */
if (ata_devchk(ap, 0))
devmask |= (1 << 0);
if (slave_possible && ata_devchk(ap, 1))
devmask |= (1 << 1);
- /* devchk reports device presence without actual device on
- * most SATA controllers. Check SStatus and turn devmask off
- * if link is offline. Note that we should continue resetting
- * even when it seems like there's no device.
- */
- if (ap->ops->scr_read && !sata_dev_present(ap))
- devmask = 0;
-
/* select device 0 again */
ap->ops->dev_select(ap, 0);
if (slave_possible && err != 0x81)
classes[1] = ata_dev_try_classify(ap, 1, &err);
+ out:
DPRINTK("EXIT, classes[0]=%u [1]=%u\n", classes[0], classes[1]);
return 0;
}
*/
int sata_std_hardreset(struct ata_port *ap, int verbose, unsigned int *class)
{
- u32 serror;
-
DPRINTK("ENTER\n");
/* Issue phy wake/reset */
/* Bring phy back */
sata_phy_resume(ap);
- /* Clear SError */
- serror = scr_read(ap, SCR_ERROR);
- scr_write(ap, SCR_ERROR, serror);
-
/* TODO: phy layer with polling, timeouts, etc. */
if (!sata_dev_present(ap)) {
*class = ATA_DEV_NONE;
return -EIO;
}
+ ap->ops->dev_select(ap, 0); /* probably unnecessary */
+
*class = ata_dev_try_classify(ap, 0, NULL);
DPRINTK("EXIT, class=%u\n", *class);
if (ap->cbl == ATA_CBL_SATA)
sata_print_link_status(ap);
- /* bail out if no device is present */
- if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) {
- DPRINTK("EXIT, no device\n");
- return;
- }
+ /* re-enable interrupts */
+ if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */
+ ata_irq_on(ap);
/* is double-select really necessary? */
if (classes[0] != ATA_DEV_NONE)
if (classes[1] != ATA_DEV_NONE)
ap->ops->dev_select(ap, 0);
- /* re-enable interrupts & set up device control */
- if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */
- ata_irq_on(ap);
+ /* bail out if no device is present */
+ if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) {
+ DPRINTK("EXIT, no device\n");
+ return;
+ }
+
+ /* set up device control */
+ if (ap->ioaddr.ctl_addr) {
+ if (ap->flags & ATA_FLAG_MMIO)
+ writeb(ap->ctl, (void __iomem *) ap->ioaddr.ctl_addr);
+ else
+ outb(ap->ctl, ap->ioaddr.ctl_addr);
+ }
DPRINTK("EXIT\n");
}
master = &ap->device[0];
slave = &ap->device[1];
- assert (ata_dev_present(master) || ata_dev_present(slave));
+ WARN_ON(!ata_dev_present(master) && !ata_dev_present(slave));
if (shift == ATA_SHIFT_UDMA) {
mask = ap->udma_mask;
int dir = qc->dma_dir;
void *pad_buf = NULL;
- assert(qc->flags & ATA_QCFLAG_DMAMAP);
- assert(sg != NULL);
+ WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP));
+ WARN_ON(sg == NULL);
if (qc->flags & ATA_QCFLAG_SINGLE)
- assert(qc->n_elem == 1);
+ WARN_ON(qc->n_elem != 1);
VPRINTK("unmapping %u sg elements\n", qc->n_elem);
struct scatterlist *sg;
unsigned int idx;
- assert(qc->__sg != NULL);
- assert(qc->n_elem > 0);
+ WARN_ON(qc->__sg == NULL);
+ WARN_ON(qc->n_elem == 0);
idx = 0;
ata_for_each_sg(sg, qc) {
void *pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ);
struct scatterlist *psg = &qc->pad_sgent;
- assert(qc->dev->class == ATA_DEV_ATAPI);
+ WARN_ON(qc->dev->class != ATA_DEV_ATAPI);
memset(pad_buf, 0, ATA_DMA_PAD_SZ);
int n_elem, pre_n_elem, dir, trim_sg = 0;
VPRINTK("ENTER, ata%u\n", ap->id);
- assert(qc->flags & ATA_QCFLAG_SG);
+ WARN_ON(!(qc->flags & ATA_QCFLAG_SG));
/* we must lengthen transfers to end on a 32-bit boundary */
qc->pad_len = lsg->length & 3;
struct scatterlist *psg = &qc->pad_sgent;
unsigned int offset;
- assert(qc->dev->class == ATA_DEV_ATAPI);
+ WARN_ON(qc->dev->class != ATA_DEV_ATAPI);
memset(pad_buf, 0, ATA_DMA_PAD_SZ);
unsigned long flags;
spin_lock_irqsave(&ap->host_set->lock, flags);
- ap->flags &= ~ATA_FLAG_NOINTR;
ata_irq_on(ap);
ata_qc_complete(qc);
spin_unlock_irqrestore(&ap->host_set->lock, flags);
unsigned int reg_state = HSM_ST_UNKNOWN;
qc = ata_qc_from_tag(ap, ap->active_tag);
- assert(qc != NULL);
+ WARN_ON(qc == NULL);
switch (ap->hsm_task_state) {
case HSM_ST:
* None. (executing in kernel thread context)
*
* RETURNS:
- * Non-zero if qc completed, zero otherwise.
+ * Zero if qc completed.
+ * Non-zero if has next.
*/
static int ata_pio_complete (struct ata_port *ap)
* we enter, BSY will be cleared in a chk-status or two. If not,
* the drive is probably seeking or something. Snooze for a couple
* msecs, then chk-status again. If still busy, fall back to
- * HSM_ST_POLL state.
+ * HSM_ST_LAST_POLL state.
*/
drv_stat = ata_busy_wait(ap, ATA_BUSY, 10);
if (drv_stat & ATA_BUSY) {
if (drv_stat & ATA_BUSY) {
ap->hsm_task_state = HSM_ST_LAST_POLL;
ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO;
- return 0;
+ return 1;
}
}
qc = ata_qc_from_tag(ap, ap->active_tag);
- assert(qc != NULL);
+ WARN_ON(qc == NULL);
drv_stat = ata_wait_idle(ap);
if (!ata_ok(drv_stat)) {
qc->err_mask |= __ac_err_mask(drv_stat);
ap->hsm_task_state = HSM_ST_ERR;
- return 0;
+ return 1;
}
ap->hsm_task_state = HSM_ST_IDLE;
- assert(qc->err_mask == 0);
+ WARN_ON(qc->err_mask);
ata_poll_qc_complete(qc);
/* another command may start at this point */
- return 1;
+ return 0;
}
page = nth_page(page, (offset >> PAGE_SHIFT));
offset %= PAGE_SIZE;
- buf = kmap(page) + offset;
+ DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
+
+ if (PageHighMem(page)) {
+ unsigned long flags;
+
+ local_irq_save(flags);
+ buf = kmap_atomic(page, KM_IRQ0);
+
+ /* do the actual data transfer */
+ ata_data_xfer(ap, buf + offset, ATA_SECT_SIZE, do_write);
+
+ kunmap_atomic(buf, KM_IRQ0);
+ local_irq_restore(flags);
+ } else {
+ buf = page_address(page);
+ ata_data_xfer(ap, buf + offset, ATA_SECT_SIZE, do_write);
+ }
qc->cursect++;
qc->cursg_ofs++;
qc->cursg++;
qc->cursg_ofs = 0;
}
+}
- DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
+/**
+ * ata_pio_sectors - Transfer one or many 512-byte sectors.
+ * @qc: Command on going
+ *
+ * Transfer one or many ATA_SECT_SIZE of data from/to the
+ * ATA device for the DRQ request.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+
+static void ata_pio_sectors(struct ata_queued_cmd *qc)
+{
+ if (is_multi_taskfile(&qc->tf)) {
+ /* READ/WRITE MULTIPLE */
+ unsigned int nsect;
+
+ assert(qc->dev->multi_count);
+
+ nsect = min(qc->nsect - qc->cursect, qc->dev->multi_count);
+ while (nsect--)
+ ata_pio_sector(qc);
+ } else
+ ata_pio_sector(qc);
+}
+
+/**
+ * atapi_send_cdb - Write CDB bytes to hardware
+ * @ap: Port to which ATAPI device is attached.
+ * @qc: Taskfile currently active
+ *
+ * When device has indicated its readiness to accept
+ * a CDB, this function is called. Send the CDB.
+ *
+ * LOCKING:
+ * caller.
+ */
+
+static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc)
+{
+ /* send SCSI cdb */
+ DPRINTK("send cdb\n");
+ assert(ap->cdb_len >= 12);
+
+ ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1);
+ ata_altstatus(ap); /* flush */
+
+ switch (qc->tf.protocol) {
+ case ATA_PROT_ATAPI:
+ ap->hsm_task_state = HSM_ST;
+ break;
+ case ATA_PROT_ATAPI_NODATA:
+ ap->hsm_task_state = HSM_ST_LAST;
+ break;
+ case ATA_PROT_ATAPI_DMA:
+ ap->hsm_task_state = HSM_ST_LAST;
+ /* initiate bmdma */
+ ap->ops->bmdma_start(qc);
+ break;
+ }
+}
+
+/**
+ * ata_pio_first_block - Write first data block to hardware
+ * @ap: Port to which ATA/ATAPI device is attached.
+ *
+ * When device has indicated its readiness to accept
+ * the data, this function sends out the CDB or
+ * the first data block by PIO.
+ * After this,
+ * - If polling, ata_pio_task() handles the rest.
+ * - Otherwise, interrupt handler takes over.
+ *
+ * LOCKING:
+ * Kernel thread context (may sleep)
+ *
+ * RETURNS:
+ * Zero if irq handler takes over
+ * Non-zero if has next (polling).
+ */
+
+static int ata_pio_first_block(struct ata_port *ap)
+{
+ struct ata_queued_cmd *qc;
+ u8 status;
+ unsigned long flags;
+ int has_next;
+
+ qc = ata_qc_from_tag(ap, ap->active_tag);
+ assert(qc != NULL);
+ assert(qc->flags & ATA_QCFLAG_ACTIVE);
+
+ /* if polling, we will stay in the work queue after sending the data.
+ * otherwise, interrupt handler takes over after sending the data.
+ */
+ has_next = (qc->tf.flags & ATA_TFLAG_POLLING);
+
+ /* sleep-wait for BSY to clear */
+ DPRINTK("busy wait\n");
+ if (ata_busy_sleep(ap, ATA_TMOUT_DATAOUT_QUICK, ATA_TMOUT_DATAOUT)) {
+ qc->err_mask |= AC_ERR_TIMEOUT;
+ ap->hsm_task_state = HSM_ST_TMOUT;
+ goto err_out;
+ }
+
+ /* make sure DRQ is set */
+ status = ata_chk_status(ap);
+ if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ) {
+ /* device status error */
+ qc->err_mask |= AC_ERR_HSM;
+ ap->hsm_task_state = HSM_ST_ERR;
+ goto err_out;
+ }
+
+ /* Send the CDB (atapi) or the first data block (ata pio out).
+ * During the state transition, interrupt handler shouldn't
+ * be invoked before the data transfer is complete and
+ * hsm_task_state is changed. Hence, the following locking.
+ */
+ spin_lock_irqsave(&ap->host_set->lock, flags);
+
+ if (qc->tf.protocol == ATA_PROT_PIO) {
+ /* PIO data out protocol.
+ * send first data block.
+ */
+
+ /* ata_pio_sectors() might change the state to HSM_ST_LAST.
+ * so, the state is changed here before ata_pio_sectors().
+ */
+ ap->hsm_task_state = HSM_ST;
+ ata_pio_sectors(qc);
+ ata_altstatus(ap); /* flush */
+ } else
+ /* send CDB */
+ atapi_send_cdb(ap, qc);
- /* do the actual data transfer */
- do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
- ata_data_xfer(ap, buf, ATA_SECT_SIZE, do_write);
+ spin_unlock_irqrestore(&ap->host_set->lock, flags);
- kunmap(page);
+ /* if polling, ata_pio_task() handles the rest.
+ * otherwise, interrupt handler takes over from here.
+ */
+ return has_next;
+
+err_out:
+ return 1; /* has next */
}
/**
/* don't cross page boundaries */
count = min(count, (unsigned int)PAGE_SIZE - offset);
- buf = kmap(page) + offset;
+ DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
+
+ if (PageHighMem(page)) {
+ unsigned long flags;
+
+ local_irq_save(flags);
+ buf = kmap_atomic(page, KM_IRQ0);
+
+ /* do the actual data transfer */
+ ata_data_xfer(ap, buf + offset, count, do_write);
+
+ kunmap_atomic(buf, KM_IRQ0);
+ local_irq_restore(flags);
+ } else {
+ buf = page_address(page);
+ ata_data_xfer(ap, buf + offset, count, do_write);
+ }
bytes -= count;
qc->curbytes += count;
qc->cursg_ofs = 0;
}
- DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
-
- /* do the actual data transfer */
- ata_data_xfer(ap, buf, count, do_write);
-
- kunmap(page);
-
if (bytes)
goto next_sg;
}
if (do_write != i_write)
goto err_out;
+ VPRINTK("ata%u: xfering %d bytes\n", ap->id, bytes);
+
__atapi_pio_bytes(qc, bytes);
return;
}
qc = ata_qc_from_tag(ap, ap->active_tag);
- assert(qc != NULL);
+ WARN_ON(qc == NULL);
/* check error */
if (status & (ATA_ERR | ATA_DF)) {
return;
}
- ata_pio_sector(qc);
+ ata_pio_sectors(qc);
}
+
+ ata_altstatus(ap); /* flush */
}
static void ata_pio_error(struct ata_port *ap)
{
struct ata_queued_cmd *qc;
- printk(KERN_WARNING "ata%u: PIO error\n", ap->id);
-
qc = ata_qc_from_tag(ap, ap->active_tag);
- assert(qc != NULL);
+ WARN_ON(qc == NULL);
+
+ if (qc->tf.command != ATA_CMD_PACKET)
+ printk(KERN_WARNING "ata%u: PIO error\n", ap->id);
/* make sure qc->err_mask is available to
* know what's wrong and recover
*/
- assert(qc->err_mask);
+ WARN_ON(qc->err_mask == 0);
ap->hsm_task_state = HSM_ST_IDLE;
{
struct ata_port *ap = _data;
unsigned long timeout;
- int qc_completed;
+ int has_next;
fsm_start:
timeout = 0;
- qc_completed = 0;
+ has_next = 1;
switch (ap->hsm_task_state) {
- case HSM_ST_IDLE:
- return;
+ case HSM_ST_FIRST:
+ has_next = ata_pio_first_block(ap);
+ break;
case HSM_ST:
ata_pio_block(ap);
break;
case HSM_ST_LAST:
- qc_completed = ata_pio_complete(ap);
+ has_next = ata_pio_complete(ap);
break;
case HSM_ST_POLL:
case HSM_ST_ERR:
ata_pio_error(ap);
return;
+
+ default:
+ BUG();
+ return;
}
if (timeout)
ata_queue_delayed_pio_task(ap, timeout);
- else if (!qc_completed)
+ else if (has_next)
goto fsm_start;
}
printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x host_stat 0x%x\n",
ap->id, qc->tf.command, drv_stat, host_stat);
+ ap->hsm_task_state = HSM_ST_IDLE;
+
/* complete taskfile transaction */
- qc->err_mask |= ac_err_mask(drv_stat);
+ qc->err_mask |= AC_ERR_TIMEOUT;
break;
}
void ata_eng_timeout(struct ata_port *ap)
{
- struct ata_queued_cmd *qc;
-
DPRINTK("ENTER\n");
- qc = ata_qc_from_tag(ap, ap->active_tag);
- if (qc)
- ata_qc_timeout(qc);
- else {
- printk(KERN_ERR "ata%u: BUG: timeout without command\n",
- ap->id);
- goto out;
- }
+ ata_qc_timeout(ata_qc_from_tag(ap, ap->active_tag));
-out:
DPRINTK("EXIT\n");
}
struct ata_port *ap = qc->ap;
unsigned int tag;
- assert(qc != NULL); /* ata_qc_from_tag _might_ return NULL */
+ WARN_ON(qc == NULL); /* ata_qc_from_tag _might_ return NULL */
qc->flags = 0;
tag = qc->tag;
}
}
-inline void __ata_qc_complete(struct ata_queued_cmd *qc)
+void __ata_qc_complete(struct ata_queued_cmd *qc)
{
- assert(qc != NULL); /* ata_qc_from_tag _might_ return NULL */
- assert(qc->flags & ATA_QCFLAG_ACTIVE);
+ WARN_ON(qc == NULL); /* ata_qc_from_tag _might_ return NULL */
+ WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE));
if (likely(qc->flags & ATA_QCFLAG_DMAMAP))
ata_sg_clean(qc);
qc->complete_fn(qc);
}
-/**
- * ata_qc_complete - Complete an active ATA command
- * @qc: Command to complete
- * @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.
- *
- * LOCKING:
- * spin_lock_irqsave(host_set lock)
- */
-void ata_qc_complete(struct ata_queued_cmd *qc)
-{
- if (unlikely(qc->flags & ATA_QCFLAG_EH_SCHEDULED))
- return;
-
- __ata_qc_complete(qc);
-}
-
static inline int ata_should_dma_map(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
{
struct ata_port *ap = qc->ap;
+ /* Use polling pio if the LLD doesn't handle
+ * interrupt driven pio and atapi CDB interrupt.
+ */
+ if (ap->flags & ATA_FLAG_PIO_POLLING) {
+ switch (qc->tf.protocol) {
+ case ATA_PROT_PIO:
+ case ATA_PROT_ATAPI:
+ case ATA_PROT_ATAPI_NODATA:
+ qc->tf.flags |= ATA_TFLAG_POLLING;
+ break;
+ case ATA_PROT_ATAPI_DMA:
+ if (qc->dev->flags & ATA_DFLAG_CDB_INTR)
+ BUG();
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* select the device */
ata_dev_select(ap, qc->dev->devno, 1, 0);
+ /* start the command */
switch (qc->tf.protocol) {
case ATA_PROT_NODATA:
+ if (qc->tf.flags & ATA_TFLAG_POLLING)
+ ata_qc_set_polling(qc);
+
ata_tf_to_host(ap, &qc->tf);
+ ap->hsm_task_state = HSM_ST_LAST;
+
+ if (qc->tf.flags & ATA_TFLAG_POLLING)
+ ata_queue_pio_task(ap);
+
break;
case ATA_PROT_DMA:
+ assert(!(qc->tf.flags & ATA_TFLAG_POLLING));
+
ap->ops->tf_load(ap, &qc->tf); /* load tf registers */
ap->ops->bmdma_setup(qc); /* set up bmdma */
ap->ops->bmdma_start(qc); /* initiate bmdma */
+ ap->hsm_task_state = HSM_ST_LAST;
break;
- case ATA_PROT_PIO: /* load tf registers, initiate polling pio */
- ata_qc_set_polling(qc);
- ata_tf_to_host(ap, &qc->tf);
- ap->hsm_task_state = HSM_ST;
- ata_queue_pio_task(ap);
- break;
+ case ATA_PROT_PIO:
+ if (qc->tf.flags & ATA_TFLAG_POLLING)
+ ata_qc_set_polling(qc);
- case ATA_PROT_ATAPI:
- ata_qc_set_polling(qc);
ata_tf_to_host(ap, &qc->tf);
- ata_queue_packet_task(ap);
+
+ if (qc->tf.flags & ATA_TFLAG_WRITE) {
+ /* PIO data out protocol */
+ ap->hsm_task_state = HSM_ST_FIRST;
+ ata_queue_pio_task(ap);
+
+ /* always send first data block using
+ * the ata_pio_task() codepath.
+ */
+ } else {
+ /* PIO data in protocol */
+ ap->hsm_task_state = HSM_ST;
+
+ if (qc->tf.flags & ATA_TFLAG_POLLING)
+ ata_queue_pio_task(ap);
+
+ /* if polling, ata_pio_task() handles the rest.
+ * otherwise, interrupt handler takes over from here.
+ */
+ }
+
break;
+ case ATA_PROT_ATAPI:
case ATA_PROT_ATAPI_NODATA:
- ap->flags |= ATA_FLAG_NOINTR;
+ if (qc->tf.flags & ATA_TFLAG_POLLING)
+ ata_qc_set_polling(qc);
+
ata_tf_to_host(ap, &qc->tf);
- ata_queue_packet_task(ap);
+
+ ap->hsm_task_state = HSM_ST_FIRST;
+
+ /* send cdb by polling if no cdb interrupt */
+ if ((!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) ||
+ (qc->tf.flags & ATA_TFLAG_POLLING))
+ ata_queue_pio_task(ap);
break;
case ATA_PROT_ATAPI_DMA:
- ap->flags |= ATA_FLAG_NOINTR;
+ assert(!(qc->tf.flags & ATA_TFLAG_POLLING));
+
ap->ops->tf_load(ap, &qc->tf); /* load tf registers */
ap->ops->bmdma_setup(qc); /* set up bmdma */
- ata_queue_packet_task(ap);
+ ap->hsm_task_state = HSM_ST_FIRST;
+
+ /* send cdb by polling if no cdb interrupt */
+ if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
+ ata_queue_pio_task(ap);
break;
default:
inline unsigned int ata_host_intr (struct ata_port *ap,
struct ata_queued_cmd *qc)
{
- u8 status, host_stat;
+ u8 status, host_stat = 0;
- switch (qc->tf.protocol) {
+ VPRINTK("ata%u: protocol %d task_state %d\n",
+ ap->id, qc->tf.protocol, ap->hsm_task_state);
- case ATA_PROT_DMA:
- case ATA_PROT_ATAPI_DMA:
- case ATA_PROT_ATAPI:
- /* check status of DMA engine */
- host_stat = ap->ops->bmdma_status(ap);
- VPRINTK("ata%u: host_stat 0x%X\n", ap->id, host_stat);
-
- /* if it's not our irq... */
- if (!(host_stat & ATA_DMA_INTR))
+ /* Check whether we are expecting interrupt in this state */
+ switch (ap->hsm_task_state) {
+ case HSM_ST_FIRST:
+ /* Check the ATA_DFLAG_CDB_INTR flag is enough here.
+ * The flag was turned on only for atapi devices.
+ * No need to check is_atapi_taskfile(&qc->tf) again.
+ */
+ if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
goto idle_irq;
+ break;
+ case HSM_ST_LAST:
+ if (qc->tf.protocol == ATA_PROT_DMA ||
+ qc->tf.protocol == ATA_PROT_ATAPI_DMA) {
+ /* check status of DMA engine */
+ host_stat = ap->ops->bmdma_status(ap);
+ VPRINTK("ata%u: host_stat 0x%X\n", ap->id, host_stat);
+
+ /* if it's not our irq... */
+ if (!(host_stat & ATA_DMA_INTR))
+ goto idle_irq;
+
+ /* before we do anything else, clear DMA-Start bit */
+ ap->ops->bmdma_stop(qc);
+
+ if (unlikely(host_stat & ATA_DMA_ERR)) {
+ /* error when transfering data to/from memory */
+ qc->err_mask |= AC_ERR_HOST_BUS;
+ ap->hsm_task_state = HSM_ST_ERR;
+ }
+ }
+ break;
+ case HSM_ST:
+ break;
+ default:
+ goto idle_irq;
+ }
- /* before we do anything else, clear DMA-Start bit */
- ap->ops->bmdma_stop(qc);
+ /* check altstatus */
+ status = ata_altstatus(ap);
+ if (status & ATA_BUSY)
+ goto idle_irq;
- /* fall through */
+ /* check main status, clearing INTRQ */
+ status = ata_chk_status(ap);
+ if (unlikely(status & ATA_BUSY))
+ goto idle_irq;
- case ATA_PROT_ATAPI_NODATA:
- case ATA_PROT_NODATA:
- /* check altstatus */
- status = ata_altstatus(ap);
- if (status & ATA_BUSY)
- goto idle_irq;
+ DPRINTK("ata%u: protocol %d task_state %d (dev_stat 0x%X)\n",
+ ap->id, qc->tf.protocol, ap->hsm_task_state, status);
- /* check main status, clearing INTRQ */
- status = ata_chk_status(ap);
- if (unlikely(status & ATA_BUSY))
- goto idle_irq;
- DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n",
- ap->id, qc->tf.protocol, status);
+ /* ack bmdma irq events */
+ ap->ops->irq_clear(ap);
- /* ack bmdma irq events */
- ap->ops->irq_clear(ap);
+ /* check error */
+ if (unlikely(status & (ATA_ERR | ATA_DF))) {
+ qc->err_mask |= AC_ERR_DEV;
+ ap->hsm_task_state = HSM_ST_ERR;
+ }
+
+fsm_start:
+ switch (ap->hsm_task_state) {
+ case HSM_ST_FIRST:
+ /* Some pre-ATAPI-4 devices assert INTRQ
+ * at this state when ready to receive CDB.
+ */
+
+ /* check device status */
+ if (unlikely((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ)) {
+ /* Wrong status. Let EH handle this */
+ qc->err_mask |= AC_ERR_HSM;
+ ap->hsm_task_state = HSM_ST_ERR;
+ goto fsm_start;
+ }
+
+ atapi_send_cdb(ap, qc);
+
+ break;
+
+ case HSM_ST:
+ /* complete command or read/write the data register */
+ if (qc->tf.protocol == ATA_PROT_ATAPI) {
+ /* ATAPI PIO protocol */
+ if ((status & ATA_DRQ) == 0) {
+ /* no more data to transfer */
+ ap->hsm_task_state = HSM_ST_LAST;
+ goto fsm_start;
+ }
+
+ atapi_pio_bytes(qc);
+
+ if (unlikely(ap->hsm_task_state == HSM_ST_ERR))
+ /* bad ireason reported by device */
+ goto fsm_start;
+
+ } else {
+ /* ATA PIO protocol */
+ if (unlikely((status & ATA_DRQ) == 0)) {
+ /* handle BSY=0, DRQ=0 as error */
+ qc->err_mask |= AC_ERR_HSM;
+ ap->hsm_task_state = HSM_ST_ERR;
+ goto fsm_start;
+ }
+
+ ata_pio_sectors(qc);
+
+ if (ap->hsm_task_state == HSM_ST_LAST &&
+ (!(qc->tf.flags & ATA_TFLAG_WRITE))) {
+ /* all data read */
+ ata_altstatus(ap);
+ status = ata_chk_status(ap);
+ goto fsm_start;
+ }
+ }
+
+ ata_altstatus(ap); /* flush */
+ break;
+
+ case HSM_ST_LAST:
+ if (unlikely(status & ATA_DRQ)) {
+ /* handle DRQ=1 as error */
+ qc->err_mask |= AC_ERR_HSM;
+ ap->hsm_task_state = HSM_ST_ERR;
+ goto fsm_start;
+ }
+
+ /* no more data to transfer */
+ DPRINTK("ata%u: command complete, drv_stat 0x%x\n",
+ ap->id, status);
+
+ ap->hsm_task_state = HSM_ST_IDLE;
/* complete taskfile transaction */
qc->err_mask |= ac_err_mask(status);
ata_qc_complete(qc);
break;
+ case HSM_ST_ERR:
+ if (qc->tf.command != ATA_CMD_PACKET)
+ printk(KERN_ERR "ata%u: command error, drv_stat 0x%x host_stat 0x%x\n",
+ ap->id, status, host_stat);
+
+ /* make sure qc->err_mask is available to
+ * know what's wrong and recover
+ */
+ assert(qc->err_mask);
+
+ ap->hsm_task_state = HSM_ST_IDLE;
+ ata_qc_complete(qc);
+ break;
default:
goto idle_irq;
}
ap = host_set->ports[i];
if (ap &&
- !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) {
+ !(ap->flags & ATA_FLAG_PORT_DISABLED)) {
struct ata_queued_cmd *qc;
qc = ata_qc_from_tag(ap, ap->active_tag);
- if (qc && (!(qc->tf.ctl & ATA_NIEN)) &&
+ if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)) &&
(qc->flags & ATA_QCFLAG_ACTIVE))
handled |= ata_host_intr(ap, qc);
}
return IRQ_RETVAL(handled);
}
-/**
- * atapi_packet_task - Write CDB bytes to hardware
- * @_data: Port to which ATAPI device is attached.
- *
- * When device has indicated its readiness to accept
- * a CDB, this function is called. Send the CDB.
- * If DMA is to be performed, exit immediately.
- * Otherwise, we are in polling mode, so poll
- * status under operation succeeds or fails.
- *
- * LOCKING:
- * Kernel thread context (may sleep)
- */
-
-static void atapi_packet_task(void *_data)
-{
- struct ata_port *ap = _data;
- struct ata_queued_cmd *qc;
- u8 status;
-
- qc = ata_qc_from_tag(ap, ap->active_tag);
- assert(qc != NULL);
- assert(qc->flags & ATA_QCFLAG_ACTIVE);
-
- /* sleep-wait for BSY to clear */
- DPRINTK("busy wait\n");
- if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB)) {
- qc->err_mask |= AC_ERR_TIMEOUT;
- goto err_out;
- }
-
- /* make sure DRQ is set */
- status = ata_chk_status(ap);
- if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ) {
- qc->err_mask |= AC_ERR_HSM;
- goto err_out;
- }
-
- /* send SCSI cdb */
- DPRINTK("send cdb\n");
- assert(ap->cdb_len >= 12);
-
- if (qc->tf.protocol == ATA_PROT_ATAPI_DMA ||
- qc->tf.protocol == ATA_PROT_ATAPI_NODATA) {
- unsigned long flags;
-
- /* Once we're done issuing command and kicking bmdma,
- * irq handler takes over. To not lose irq, we need
- * to clear NOINTR flag before sending cdb, but
- * interrupt handler shouldn't be invoked before we're
- * finished. Hence, the following locking.
- */
- spin_lock_irqsave(&ap->host_set->lock, flags);
- ap->flags &= ~ATA_FLAG_NOINTR;
- ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1);
- if (qc->tf.protocol == ATA_PROT_ATAPI_DMA)
- ap->ops->bmdma_start(qc); /* initiate bmdma */
- spin_unlock_irqrestore(&ap->host_set->lock, flags);
- } else {
- ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1);
-
- /* PIO commands are handled by polling */
- ap->hsm_task_state = HSM_ST;
- ata_queue_pio_task(ap);
- }
-
- return;
-
-err_out:
- ata_poll_qc_complete(qc);
-}
-
-
/*
* Execute a 'simple' command, that only consists of the opcode 'cmd' itself,
* without filling any other registers
ap->active_tag = ATA_TAG_POISON;
ap->last_ctl = 0xFF;
- INIT_WORK(&ap->packet_task, atapi_packet_task, ap);
INIT_WORK(&ap->pio_task, ata_pio_task, ap);
INIT_LIST_HEAD(&ap->eh_done_q);
EXPORT_SYMBOL_GPL(ata_host_set_remove);
EXPORT_SYMBOL_GPL(ata_sg_init);
EXPORT_SYMBOL_GPL(ata_sg_init_one);
-EXPORT_SYMBOL_GPL(ata_qc_complete);
+EXPORT_SYMBOL_GPL(__ata_qc_complete);
EXPORT_SYMBOL_GPL(ata_qc_issue_prot);
EXPORT_SYMBOL_GPL(ata_eng_timeout);
EXPORT_SYMBOL_GPL(ata_tf_load);