Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 94830
b: refs/heads/master
c: 65c0d4e
h: refs/heads/master
v: v3
  • Loading branch information
Sonic Zhang authored and Jeff Garzik committed Apr 29, 2008
1 parent 82d38fb commit f532da6
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 5 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 7368f91926a2870a8c3f9546d86535ce71ae0757
refs/heads/master: 65c0d4e54ae4b81d8c8bb685169e48306656bb5c
124 changes: 120 additions & 4 deletions trunk/drivers/ata/pata_bf54x.c
Original file line number Diff line number Diff line change
Expand Up @@ -1272,8 +1272,8 @@ static void bfin_freeze(struct ata_port *ap)

void bfin_thaw(struct ata_port *ap)
{
dev_dbg(ap->dev, "in atapi dma thaw\n");
bfin_check_status(ap);
bfin_irq_clear(ap);
bfin_irq_on(ap);
}

Expand Down Expand Up @@ -1339,13 +1339,130 @@ static int bfin_port_start(struct ata_port *ap)
return 0;
}

static unsigned int bfin_ata_host_intr(struct ata_port *ap,
struct ata_queued_cmd *qc)
{
struct ata_eh_info *ehi = &ap->link.eh_info;
u8 status, host_stat = 0;

VPRINTK("ata%u: protocol %d task_state %d\n",
ap->print_id, qc->tf.protocol, ap->hsm_task_state);

/* Check whether we are expecting interrupt in this state */
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 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 == ATAPI_PROT_DMA) {
/* check status of DMA engine */
host_stat = ap->ops->bmdma_status(ap);
VPRINTK("ata%u: host_stat 0x%X\n",
ap->print_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;
}

/* check altstatus */
status = ap->ops->sff_check_altstatus(ap);
if (status & ATA_BUSY)
goto busy_ata;

/* check main status, clearing INTRQ */
status = ap->ops->sff_check_status(ap);
if (unlikely(status & ATA_BUSY))
goto busy_ata;

/* ack bmdma irq events */
ap->ops->sff_irq_clear(ap);

ata_sff_hsm_move(ap, qc, status, 0);

if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA ||
qc->tf.protocol == ATAPI_PROT_DMA))
ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat);

busy_ata:
return 1; /* irq handled */

idle_irq:
ap->stats.idle_irq++;

#ifdef ATA_IRQ_TRAP
if ((ap->stats.idle_irq % 1000) == 0) {
ap->ops->irq_ack(ap, 0); /* debug trap */
ata_port_printk(ap, KERN_WARNING, "irq trap\n");
return 1;
}
#endif
return 0; /* irq not handled */
}

static irqreturn_t bfin_ata_interrupt(int irq, void *dev_instance)
{
struct ata_host *host = dev_instance;
unsigned int i;
unsigned int handled = 0;
unsigned long flags;

/* TODO: make _irqsave conditional on x86 PCI IDE legacy mode */
spin_lock_irqsave(&host->lock, flags);

for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap;

ap = host->ports[i];
if (ap &&
!(ap->flags & ATA_FLAG_DISABLED)) {
struct ata_queued_cmd *qc;

qc = ata_qc_from_tag(ap, ap->link.active_tag);
if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)) &&
(qc->flags & ATA_QCFLAG_ACTIVE))
handled |= bfin_ata_host_intr(ap, qc);
}
}

spin_unlock_irqrestore(&host->lock, flags);

return IRQ_RETVAL(handled);
}


static struct scsi_host_template bfin_sht = {
ATA_BASE_SHT(DRV_NAME),
.sg_tablesize = SG_NONE,
.dma_boundary = ATA_DMA_BOUNDARY,
};

static const struct ata_port_operations bfin_pata_ops = {
static struct ata_port_operations bfin_pata_ops = {
.inherits = &ata_sff_port_ops,

.set_piomode = bfin_set_piomode,
Expand All @@ -1370,7 +1487,6 @@ static const struct ata_port_operations bfin_pata_ops = {
.thaw = bfin_thaw,
.softreset = bfin_softreset,
.postreset = bfin_postreset,
.post_internal_cmd = bfin_bmdma_stop,

.sff_irq_clear = bfin_irq_clear,
.sff_irq_on = bfin_irq_on,
Expand Down Expand Up @@ -1507,7 +1623,7 @@ static int __devinit bfin_atapi_probe(struct platform_device *pdev)
}

if (ata_host_activate(host, platform_get_irq(pdev, 0),
ata_sff_interrupt, IRQF_SHARED, &bfin_sht) != 0) {
bfin_ata_interrupt, IRQF_SHARED, &bfin_sht) != 0) {
peripheral_free_list(atapi_io_port);
dev_err(&pdev->dev, "Fail to attach ATAPI device\n");
return -ENODEV;
Expand Down

0 comments on commit f532da6

Please sign in to comment.