aboutsummaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorSøren Schmidt <sos@FreeBSD.org>2005-06-05 21:18:26 +0000
committerSøren Schmidt <sos@FreeBSD.org>2005-06-05 21:18:26 +0000
commitb9203a8aca13d075223865855245d4f5ef8f74a9 (patch)
treec1dd0fe8fda5a2293fda98d6fba7d44c53757fcb /sys/dev
parentb1bb8b168443ee311d91e5e6bee583ae88236385 (diff)
Notes
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ata/ata-chipset.c53
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)));
}