diff options
| author | Søren Schmidt <sos@FreeBSD.org> | 2005-06-05 21:18:26 +0000 |
|---|---|---|
| committer | Søren Schmidt <sos@FreeBSD.org> | 2005-06-05 21:18:26 +0000 |
| commit | b9203a8aca13d075223865855245d4f5ef8f74a9 (patch) | |
| tree | c1dd0fe8fda5a2293fda98d6fba7d44c53757fcb /sys/dev | |
| parent | b1bb8b168443ee311d91e5e6bee583ae88236385 (diff) | |
Notes
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/ata/ata-chipset.c | 53 |
1 files changed, 27 insertions, 26 deletions
diff --git a/sys/dev/ata/ata-chipset.c b/sys/dev/ata/ata-chipset.c index c640fe2269939..261e1fc7c6faa 100644 --- a/sys/dev/ata/ata-chipset.c +++ b/sys/dev/ata/ata-chipset.c @@ -1848,14 +1848,28 @@ ata_nvidia_chipinit(device_t dev) ctlr->r_rid2 = PCIR_BAR(5); if ((ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2, &ctlr->r_rid2, RF_ACTIVE))) { + int offset = ctlr->chip->cfg2 & NV4OFF ? 0x0440 : 0x0010; + if (bus_teardown_intr(dev, ctlr->r_irq, ctlr->handle) || bus_setup_intr(dev, ctlr->r_irq, ATA_INTR_FLAGS, ata_nvidia_intr, ctlr, &ctlr->handle)) { device_printf(dev, "unable to setup interrupt\n"); return ENXIO; } + + /* enable control access */ + pci_write_config(dev, 0x50, pci_read_config(dev, 0x50, 1) | 0x04,1); + + /* clear interrupt status */ + ATA_OUTB(ctlr->r_res2, offset, 0xff); + + /* enable device and PHY state change interrupts */ + ATA_OUTB(ctlr->r_res2, offset + 1, 0xdd); + + /* enable PCI interrupt */ pci_write_config(dev, PCIR_COMMAND, pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400,2); + ctlr->allocate = ata_nvidia_allocate; ctlr->reset = ata_nvidia_reset; } @@ -1874,7 +1888,6 @@ ata_nvidia_allocate(device_t dev) { struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); struct ata_channel *ch = device_get_softc(dev); - int offset = ctlr->chip->cfg2 & NV4OFF ? 0x0441 : 0x0011; /* setup the usual register normal pci style */ ata_pci_allocate(dev); @@ -1887,9 +1900,6 @@ ata_nvidia_allocate(device_t dev) ch->r_io[ATA_SCONTROL].offset = 0x08 + (ch->unit << 6); ch->flags |= ATA_NO_SLAVE; - /* enable PHY state change interrupts */ - ATA_OUTB(ctlr->r_res2, offset, - ATA_INB(ctlr->r_res2, offset) | (0x0c << (ch->unit << 2))); return 0; } @@ -1902,20 +1912,22 @@ ata_nvidia_intr(void *data) u_int8_t status; int unit; - for (unit = 0; unit < ctlr->channels; unit++) { - if (!(ch = ctlr->interrupt[unit].argument)) - continue; + /* get interrupt status */ + status = ATA_INB(ctlr->r_res2, offset); - if ((status = ATA_INB(ctlr->r_res2, offset))) { - u_int32_t error = ATA_IDX_INL(ch, ATA_SERROR); + /* clear interrupt status */ + ATA_OUTB(ctlr->r_res2, offset, 0xff); + + for (unit = 0; unit < ctlr->channels; unit++) { + if ((ch = ctlr->interrupt[unit].argument)) { struct ata_connect_task *tp; + int maskshift = ch->unit << 2; - /* clear error bits/interrupt */ - ATA_IDX_OUTL(ch, ATA_SERROR, error); - ATA_OUTB(ctlr->r_res2, offset, status); + /* clear error status */ + ATA_IDX_OUTL(ch, ATA_SERROR, ATA_IDX_INL(ch, ATA_SERROR)); /* check for and handle connect events */ - if ((status & (0x04 << (ch->unit << 2))) && + if (((status & (0x0c << maskshift)) == (0x04 << maskshift)) && (tp = (struct ata_connect_task *) malloc(sizeof(struct ata_connect_task), M_ATA, M_NOWAIT | M_ZERO))) { @@ -1925,11 +1937,10 @@ ata_nvidia_intr(void *data) tp->dev = ch->dev; TASK_INIT(&tp->task, 0, ata_sata_phy_event, tp); taskqueue_enqueue(taskqueue_thread, &tp->task); - } /* check for and handle disconnect events */ - if ((status & (0x08 << (ch->unit << 2))) && + if ((status & (0x08 << maskshift)) && (tp = (struct ata_connect_task *) malloc(sizeof(struct ata_connect_task), M_ATA, M_NOWAIT | M_ZERO))) { @@ -1942,7 +1953,7 @@ ata_nvidia_intr(void *data) } /* any drive action to take care of ? */ - if (status & (0x01 << (ch->unit << 2))) { + if (status & (0x01 << maskshift)) { if (ch->dma && (ch->dma->flags & ATA_DMA_ACTIVE)) { int bmstat = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK; @@ -1961,19 +1972,9 @@ ata_nvidia_intr(void *data) static void ata_nvidia_reset(device_t dev) { - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); struct ata_channel *ch = device_get_softc(dev); - int offset = ctlr->chip->cfg2 & NV4OFF ? 0x0441 : 0x0011; - - /* disable PHY state change interrupt */ - ATA_OUTB(ctlr->r_res2, offset, - ATA_INB(ctlr->r_res2, offset) & (~0x0c << (ch->unit << 2))); ata_sata_phy_enable(ch); - - /* enable PHY state change interrupt */ - ATA_OUTB(ctlr->r_res2, offset, - ATA_INB(ctlr->r_res2, offset) | (0x0c << (ch->unit << 2))); } |
