diff options
author | sos <sos@FreeBSD.org> | 2003-03-29 13:37:09 +0000 |
---|---|---|
committer | sos <sos@FreeBSD.org> | 2003-03-29 13:37:09 +0000 |
commit | 1aa8f29ccf0eb6c6db95c1257318186a901b5ef9 (patch) | |
tree | bb9ce90b8fcfe8e400644fa3aceb2bcd039d7993 /sys/dev | |
parent | ededebc1a4663fdc2452865586200d45a8fef1fe (diff) | |
download | FreeBSD-src-1aa8f29ccf0eb6c6db95c1257318186a901b5ef9.zip FreeBSD-src-1aa8f29ccf0eb6c6db95c1257318186a901b5ef9.tar.gz |
Second round of updates to the ATA driver.
Clean up the DMA interface too much unneeded stuff crept in with
the busdma code back when.
Modify the ATA_IN* / ATA_OUT* macros so that resource and offset
are gotten from a table. That allows for new chipsets that doesn't
nessesarily have things ordered the good old way. This also removes
the need for the wierd PC98 resource functions.
Tested on: i386, PC98, Alpha, Sparc64
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/ata/ata-all.c | 249 | ||||
-rw-r--r-- | sys/dev/ata/ata-all.h | 102 | ||||
-rw-r--r-- | sys/dev/ata/ata-card.c | 49 | ||||
-rw-r--r-- | sys/dev/ata/ata-cbus.c | 67 | ||||
-rw-r--r-- | sys/dev/ata/ata-chipset.c | 147 | ||||
-rw-r--r-- | sys/dev/ata/ata-disk.c | 39 | ||||
-rw-r--r-- | sys/dev/ata/ata-dma.c | 188 | ||||
-rw-r--r-- | sys/dev/ata/ata-isa.c | 25 | ||||
-rw-r--r-- | sys/dev/ata/ata-pci.c | 211 | ||||
-rw-r--r-- | sys/dev/ata/ata-pci.h | 24 | ||||
-rw-r--r-- | sys/dev/ata/atapi-all.c | 50 |
11 files changed, 614 insertions, 537 deletions
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c index 56a7d29..a2967e7 100644 --- a/sys/dev/ata/ata-all.c +++ b/sys/dev/ata/ata-all.c @@ -92,43 +92,16 @@ int ata_probe(device_t dev) { struct ata_channel *ch; - int rid; if (!dev || !(ch = device_get_softc(dev))) return ENXIO; - if (ch->r_io || ch->r_altio || ch->r_irq) + if (ch->r_irq) return EEXIST; /* initialize the softc basics */ ch->active = ATA_IDLE; ch->dev = dev; - - rid = ATA_IOADDR_RID; - ch->r_io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, - ATA_IOSIZE, RF_ACTIVE); - if (!ch->r_io) - goto failure; - - rid = ATA_ALTADDR_RID; - ch->r_altio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, - ATA_ALTIOSIZE, RF_ACTIVE); - if (!ch->r_altio) - goto failure; - - rid = ATA_BMADDR_RID; - ch->r_bmio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, - ATA_BMIOSIZE, RF_ACTIVE); - if (bootverbose) - ata_printf(ch, -1, "iobase=0x%04x altiobase=0x%04x bmaddr=0x%04x\n", - (int)rman_get_start(ch->r_io), - (int)rman_get_start(ch->r_altio), - (ch->r_bmio) ? (int)rman_get_start(ch->r_bmio) : 0); - - ch->locking(ch, ATA_LF_LOCK); - ata_reset(ch); - ch->locking(ch, ATA_LF_UNLOCK); - ch->device[MASTER].channel = ch; ch->device[MASTER].unit = ATA_MASTER; ch->device[MASTER].mode = ATA_PIO; @@ -137,18 +110,12 @@ ata_probe(device_t dev) ch->device[SLAVE].mode = ATA_PIO; TAILQ_INIT(&ch->ata_queue); TAILQ_INIT(&ch->atapi_queue); + + /* initialise device(s) on this channel */ + ch->locking(ch, ATA_LF_LOCK); + ata_reset(ch); + ch->locking(ch, ATA_LF_UNLOCK); return 0; - -failure: - if (ch->r_io) - bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, ch->r_io); - if (ch->r_altio) - bus_release_resource(dev, SYS_RES_IOPORT, ATA_ALTADDR_RID, ch->r_altio); - if (ch->r_bmio) - bus_release_resource(dev, SYS_RES_IOPORT, ATA_BMADDR_RID, ch->r_bmio); - if (bootverbose) - ata_printf(ch, -1, "probe allocation failed\n"); - return ENXIO; } int @@ -174,7 +141,7 @@ ata_attach(device_t dev) } if (ch->dma) - ch->dma->create(ch); + ch->dma->alloc(ch); /* * do not attach devices if we are in early boot, this is done later @@ -221,8 +188,7 @@ ata_detach(device_t dev) struct ata_channel *ch; int s; - if (!dev || !(ch = device_get_softc(dev)) || - !ch->r_io || !ch->r_altio || !ch->r_irq) + if (!dev || !(ch = device_get_softc(dev)) || !ch->r_irq) return ENXIO; /* make sure channel is not busy */ @@ -261,17 +227,10 @@ ata_detach(device_t dev) ch->device[SLAVE].mode = ATA_PIO; ch->devices = 0; if (ch->dma) - ch->dma->destroy(ch); + ch->dma->free(ch); bus_teardown_intr(dev, ch->r_irq, ch->ih); bus_release_resource(dev, SYS_RES_IRQ, ATA_IRQ_RID, ch->r_irq); - if (ch->r_bmio) - bus_release_resource(dev, SYS_RES_IOPORT, ATA_BMADDR_RID, ch->r_bmio); - bus_release_resource(dev, SYS_RES_IOPORT, ATA_ALTADDR_RID, ch->r_altio); - bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, ch->r_io); - ch->r_io = NULL; - ch->r_altio = NULL; - ch->r_bmio = NULL; ch->r_irq = NULL; ATA_UNLOCK_CH(ch); ch->locking(ch, ATA_LF_UNLOCK); @@ -488,7 +447,7 @@ ata_getparam(struct ata_device *atadev, u_int8_t command) /* apparently some devices needs this repeated */ do { if (ata_command(atadev, command, 0, 0, 0, - dumping ? ATA_WAIT_READY : ATA_WAIT_INTR)) { + dumping ? ATA_WAIT_READY : ATA_WAIT_INTR)) { /* XXX */ ata_prtdev(atadev, "%s identify failed\n", command == ATA_C_ATAPI_IDENTIFY ? "ATAPI" : "ATA"); free(ata_parm, M_ATA); @@ -502,7 +461,7 @@ ata_getparam(struct ata_device *atadev, u_int8_t command) } } while (ata_wait(atadev, ((command == ATA_C_ATAPI_IDENTIFY) ? ATA_S_DRQ : (ATA_S_READY|ATA_S_DSC|ATA_S_DRQ)))); - ATA_INSW(atadev->channel->r_io, ATA_DATA, (int16_t *)ata_parm, + ATA_IDX_INSW(atadev->channel, ATA_DATA, (int16_t *)ata_parm, sizeof(struct ata_params)/sizeof(int16_t)); if (command == ATA_C_ATA_IDENTIFY || @@ -596,17 +555,17 @@ ata_intr(void *data) struct ata_channel *ch = (struct ata_channel *)data; /* if device is busy it didn't interrupt */ - if (ATA_INB(ch->r_altio, ATA_ALTSTAT) & ATA_S_BUSY) { + if (ATA_IDX_INB(ch, ATA_ALTSTAT) & ATA_S_BUSY) { DELAY(100); - if (!(ATA_INB(ch->r_altio, ATA_ALTSTAT) & ATA_S_DRQ)) + if (!(ATA_IDX_INB(ch, ATA_ALTSTAT) & ATA_S_DRQ)) return; } /* clear interrupt and get status */ - ch->status = ATA_INB(ch->r_io, ATA_STATUS); + ch->status = ATA_IDX_INB(ch, ATA_STATUS); if (ch->status & ATA_S_ERROR) - ch->error = ATA_INB(ch->r_io, ATA_ERROR); + ch->error = ATA_IDX_INB(ch, ATA_ERROR); /* find & call the responsible driver to process this interrupt */ switch (ch->active) { @@ -638,7 +597,7 @@ ata_intr(void *data) } if ((ch->flags & ATA_QUEUED) && - ATA_INB(ch->r_altio, ATA_ALTSTAT) & ATA_S_SERVICE) { + ATA_IDX_INB(ch, ATA_ALTSTAT) & ATA_S_SERVICE) { ATA_FORCELOCK_CH(ch, ATA_ACTIVE); if (ata_service(ch) == ATA_OP_CONTINUES) return; @@ -716,16 +675,16 @@ ata_reset(struct ata_channel *ch) int mask = 0, timeout; /* do we have any signs of ATA/ATAPI HW being present ? */ - ATA_OUTB(ch->r_io, ATA_DRIVE, ATA_D_IBM | ATA_MASTER); + ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_MASTER); DELAY(10); - ostat0 = ATA_INB(ch->r_io, ATA_STATUS); + ostat0 = ATA_IDX_INB(ch, ATA_STATUS); if ((ostat0 & 0xf8) != 0xf8 && ostat0 != 0xa5) { stat0 = ATA_S_BUSY; mask |= 0x01; } - ATA_OUTB(ch->r_io, ATA_DRIVE, ATA_D_IBM | ATA_SLAVE); + ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_SLAVE); DELAY(10); - ostat1 = ATA_INB(ch->r_io, ATA_STATUS); + ostat1 = ATA_IDX_INB(ch, ATA_STATUS); if ((ostat1 & 0xf8) != 0xf8 && ostat1 != 0xa5) { stat1 = ATA_S_BUSY; mask |= 0x02; @@ -746,24 +705,24 @@ ata_reset(struct ata_channel *ch) mask, ostat0, ostat1); /* reset channel */ - ATA_OUTB(ch->r_io, ATA_DRIVE, ATA_D_IBM | ATA_MASTER); + ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_MASTER); DELAY(10); - ATA_OUTB(ch->r_altio, ATA_ALTSTAT, ATA_A_IDS | ATA_A_RESET); + ATA_IDX_OUTB(ch, ATA_ALTSTAT, ATA_A_IDS | ATA_A_RESET); DELAY(10000); - ATA_OUTB(ch->r_altio, ATA_ALTSTAT, ATA_A_IDS); + ATA_IDX_OUTB(ch, ATA_ALTSTAT, ATA_A_IDS); DELAY(100000); - ATA_INB(ch->r_io, ATA_ERROR); + ATA_IDX_INB(ch, ATA_ERROR); /* wait for BUSY to go inactive */ for (timeout = 0; timeout < 310000; timeout++) { if (stat0 & ATA_S_BUSY) { - ATA_OUTB(ch->r_io, ATA_DRIVE, ATA_D_IBM | ATA_MASTER); + ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_MASTER); DELAY(10); /* check for ATAPI signature while its still there */ - lsb = ATA_INB(ch->r_io, ATA_CYL_LSB); - msb = ATA_INB(ch->r_io, ATA_CYL_MSB); - stat0 = ATA_INB(ch->r_io, ATA_STATUS); + lsb = ATA_IDX_INB(ch, ATA_CYL_LSB); + msb = ATA_IDX_INB(ch, ATA_CYL_MSB); + stat0 = ATA_IDX_INB(ch, ATA_STATUS); if (!(stat0 & ATA_S_BUSY)) { if (bootverbose) ata_printf(ch, ATA_MASTER, "ATAPI %02x %02x\n", lsb, msb); @@ -772,13 +731,13 @@ ata_reset(struct ata_channel *ch) } } if (stat1 & ATA_S_BUSY) { - ATA_OUTB(ch->r_io, ATA_DRIVE, ATA_D_IBM | ATA_SLAVE); + ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_SLAVE); DELAY(10); /* check for ATAPI signature while its still there */ - lsb = ATA_INB(ch->r_io, ATA_CYL_LSB); - msb = ATA_INB(ch->r_io, ATA_CYL_MSB); - stat1 = ATA_INB(ch->r_io, ATA_STATUS); + lsb = ATA_IDX_INB(ch, ATA_CYL_LSB); + msb = ATA_IDX_INB(ch, ATA_CYL_MSB); + stat1 = ATA_IDX_INB(ch, ATA_STATUS); if (!(stat1 & ATA_S_BUSY)) { if (bootverbose) ata_printf(ch, ATA_SLAVE, "ATAPI %02x %02x\n", lsb, msb); @@ -798,7 +757,7 @@ ata_reset(struct ata_channel *ch) DELAY(100); } DELAY(10); - ATA_OUTB(ch->r_altio, ATA_ALTSTAT, ATA_A_4BIT); + ATA_IDX_OUTB(ch, ATA_ALTSTAT, ATA_A_4BIT); if (stat0 & ATA_S_BUSY) mask &= ~0x01; @@ -811,24 +770,24 @@ ata_reset(struct ata_channel *ch) return; if (mask & 0x01 && ostat0 != 0x00 && !(ch->devices & ATA_ATAPI_MASTER)) { - ATA_OUTB(ch->r_io, ATA_DRIVE, ATA_D_IBM | ATA_MASTER); + ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_MASTER); DELAY(10); - ATA_OUTB(ch->r_io, ATA_ERROR, 0x58); - ATA_OUTB(ch->r_io, ATA_CYL_LSB, 0xa5); - lsb = ATA_INB(ch->r_io, ATA_ERROR); - msb = ATA_INB(ch->r_io, ATA_CYL_LSB); + ATA_IDX_OUTB(ch, ATA_ERROR, 0x58); + ATA_IDX_OUTB(ch, ATA_CYL_LSB, 0xa5); + lsb = ATA_IDX_INB(ch, ATA_ERROR); + msb = ATA_IDX_INB(ch, ATA_CYL_LSB); if (bootverbose) ata_printf(ch, ATA_MASTER, "ATA %02x %02x\n", lsb, msb); if (lsb != 0x58 && msb == 0xa5) ch->devices |= ATA_ATA_MASTER; } if (mask & 0x02 && ostat1 != 0x00 && !(ch->devices & ATA_ATAPI_SLAVE)) { - ATA_OUTB(ch->r_io, ATA_DRIVE, ATA_D_IBM | ATA_SLAVE); + ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_SLAVE); DELAY(10); - ATA_OUTB(ch->r_io, ATA_ERROR, 0x58); - ATA_OUTB(ch->r_io, ATA_CYL_LSB, 0xa5); - lsb = ATA_INB(ch->r_io, ATA_ERROR); - msb = ATA_INB(ch->r_io, ATA_CYL_LSB); + ATA_IDX_OUTB(ch, ATA_ERROR, 0x58); + ATA_IDX_OUTB(ch, ATA_CYL_LSB, 0xa5); + lsb = ATA_IDX_INB(ch, ATA_ERROR); + msb = ATA_IDX_INB(ch, ATA_CYL_LSB); if (bootverbose) ata_printf(ch, ATA_SLAVE, "ATA %02x %02x\n", lsb, msb); if (lsb != 0x58 && msb == 0xa5) @@ -843,13 +802,11 @@ ata_reinit(struct ata_channel *ch) { int devices, misdev, newdev; - ATA_FORCELOCK_CH(ch, ATA_CONTROL); - if (!ch->r_io || !ch->r_altio || !ch->r_irq) { - ATA_UNLOCK_CH(ch); + if (!ch->r_irq) return ENXIO; - } + ATA_FORCELOCK_CH(ch, ATA_CONTROL); ch->running = NULL; devices = ch->devices; ata_printf(ch, -1, "resetting devices ..\n"); @@ -937,11 +894,11 @@ ata_service(struct ata_channel *ch) /* do we have a SERVICE request from the drive ? */ if ((ch->status & (ATA_S_SERVICE|ATA_S_ERROR|ATA_S_DRQ)) == ATA_S_SERVICE) { #if 0 /* XXX */ - ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, + ATA_IDX_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, ch->dma->status(ch) | ATA_BMSTAT_INTERRUPT); #endif #ifdef DEV_ATADISK - if ((ATA_INB(ch->r_io, ATA_DRIVE) & ATA_SLAVE) == ATA_MASTER) { + if ((ATA_IDX_INB(ch, ATA_DRIVE) & ATA_SLAVE) == ATA_MASTER) { if ((ch->devices & ATA_ATA_MASTER) && ch->device[MASTER].driver) return ad_service((struct ad_softc *) ch->device[MASTER].driver, 0); @@ -963,14 +920,14 @@ ata_wait(struct ata_device *atadev, u_int8_t mask) DELAY(1); while (timeout < 5000000) { /* timeout 5 secs */ - atadev->channel->status = ATA_INB(atadev->channel->r_io, ATA_STATUS); + atadev->channel->status = ATA_IDX_INB(atadev->channel, ATA_STATUS); /* if drive fails status, reselect the drive just to be sure */ if (atadev->channel->status == 0xff) { ata_prtdev(atadev, "no status, reselecting device\n"); - ATA_OUTB(atadev->channel->r_io, ATA_DRIVE, ATA_D_IBM|atadev->unit); + ATA_IDX_OUTB(atadev->channel, ATA_DRIVE, ATA_D_IBM|atadev->unit); DELAY(10); - atadev->channel->status = ATA_INB(atadev->channel->r_io,ATA_STATUS); + atadev->channel->status = ATA_IDX_INB(atadev->channel, ATA_STATUS); if (atadev->channel->status == 0xff) return -1; } @@ -989,7 +946,7 @@ ata_wait(struct ata_device *atadev, u_int8_t mask) } } if (atadev->channel->status & ATA_S_ERROR) - atadev->channel->error = ATA_INB(atadev->channel->r_io, ATA_ERROR); + atadev->channel->error = ATA_IDX_INB(atadev->channel, ATA_ERROR); if (timeout >= 5000000) return -1; if (!mask) @@ -998,10 +955,10 @@ ata_wait(struct ata_device *atadev, u_int8_t mask) /* Wait 50 msec for bits wanted. */ timeout = 5000; while (timeout--) { - atadev->channel->status = ATA_INB(atadev->channel->r_io, ATA_STATUS); + atadev->channel->status = ATA_IDX_INB(atadev->channel, ATA_STATUS); if ((atadev->channel->status & mask) == mask) { if (atadev->channel->status & ATA_S_ERROR) - atadev->channel->error=ATA_INB(atadev->channel->r_io,ATA_ERROR); + atadev->channel->error=ATA_IDX_INB(atadev->channel, ATA_ERROR); return (atadev->channel->status & ATA_S_ERROR); } DELAY (10); @@ -1017,16 +974,16 @@ ata_command(struct ata_device *atadev, u_int8_t command, #ifdef ATA_DEBUG ata_prtdev(atadev, "ata_command: addr=%04lx, cmd=%02x, " "lba=%jd, count=%d, feature=%d, flags=%02x\n", - rman_get_start(atadev->channel->r_io), + rman_get_start(atadev->channel), command, (intmax_t)lba, count, feature, flags); #endif /* select device */ - ATA_OUTB(atadev->channel->r_io, ATA_DRIVE, ATA_D_IBM | atadev->unit); + ATA_IDX_OUTB(atadev->channel, ATA_DRIVE, ATA_D_IBM | atadev->unit); /* disable interrupt from device */ if (atadev->channel->flags & ATA_QUEUED) - ATA_OUTB(atadev->channel->r_altio, ATA_ALTSTAT, ATA_A_IDS | ATA_A_4BIT); + ATA_IDX_OUTB(atadev->channel, ATA_ALTSTAT, ATA_A_IDS | ATA_A_4BIT); /* ready to issue command ? */ if (ata_wait(atadev, 0) < 0) { @@ -1038,17 +995,17 @@ ata_command(struct ata_device *atadev, u_int8_t command, /* only use 48bit addressing if needed because of the overhead */ if ((lba > 268435455 || count > 256) && atadev->param && atadev->param->support.address48) { - ATA_OUTB(atadev->channel->r_io, ATA_FEATURE, (feature>>8) & 0xff); - ATA_OUTB(atadev->channel->r_io, ATA_FEATURE, feature); - ATA_OUTB(atadev->channel->r_io, ATA_COUNT, (count>>8) & 0xff); - ATA_OUTB(atadev->channel->r_io, ATA_COUNT, count & 0xff); - ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, (lba>>24) & 0xff); - ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, lba & 0xff); - ATA_OUTB(atadev->channel->r_io, ATA_CYL_LSB, (lba>>32) & 0xff); - ATA_OUTB(atadev->channel->r_io, ATA_CYL_LSB, (lba>>8) & 0xff); - ATA_OUTB(atadev->channel->r_io, ATA_CYL_MSB, (lba>>40) & 0xff); - ATA_OUTB(atadev->channel->r_io, ATA_CYL_MSB, (lba>>16) & 0xff); - ATA_OUTB(atadev->channel->r_io, ATA_DRIVE, ATA_D_LBA | atadev->unit); + ATA_IDX_OUTB(atadev->channel, ATA_FEATURE, (feature>>8) & 0xff); + ATA_IDX_OUTB(atadev->channel, ATA_FEATURE, feature); + ATA_IDX_OUTB(atadev->channel, ATA_COUNT, (count>>8) & 0xff); + ATA_IDX_OUTB(atadev->channel, ATA_COUNT, count & 0xff); + ATA_IDX_OUTB(atadev->channel, ATA_SECTOR, (lba>>24) & 0xff); + ATA_IDX_OUTB(atadev->channel, ATA_SECTOR, lba & 0xff); + ATA_IDX_OUTB(atadev->channel, ATA_CYL_LSB, (lba>>32) & 0xff); + ATA_IDX_OUTB(atadev->channel, ATA_CYL_LSB, (lba>>8) & 0xff); + ATA_IDX_OUTB(atadev->channel, ATA_CYL_MSB, (lba>>40) & 0xff); + ATA_IDX_OUTB(atadev->channel, ATA_CYL_MSB, (lba>>16) & 0xff); + ATA_IDX_OUTB(atadev->channel, ATA_DRIVE, ATA_D_LBA | atadev->unit); /* translate command into 48bit version */ switch (command) { @@ -1077,36 +1034,36 @@ ata_command(struct ata_device *atadev, u_int8_t command, atadev->channel->flags |= ATA_48BIT_ACTIVE; } else { - ATA_OUTB(atadev->channel->r_io, ATA_FEATURE, feature); - ATA_OUTB(atadev->channel->r_io, ATA_COUNT, count); - ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, lba & 0xff); - ATA_OUTB(atadev->channel->r_io, ATA_CYL_LSB, (lba>>8) & 0xff); - ATA_OUTB(atadev->channel->r_io, ATA_CYL_MSB, (lba>>16) & 0xff); + ATA_IDX_OUTB(atadev->channel, ATA_FEATURE, feature); + ATA_IDX_OUTB(atadev->channel, ATA_COUNT, count); + ATA_IDX_OUTB(atadev->channel, ATA_SECTOR, lba & 0xff); + ATA_IDX_OUTB(atadev->channel, ATA_CYL_LSB, (lba>>8) & 0xff); + ATA_IDX_OUTB(atadev->channel, ATA_CYL_MSB, (lba>>16) & 0xff); if (atadev->flags & ATA_D_USE_CHS) - ATA_OUTB(atadev->channel->r_io, ATA_DRIVE, + ATA_IDX_OUTB(atadev->channel, ATA_DRIVE, ATA_D_IBM | atadev->unit | ((lba>>24) & 0xf)); else - ATA_OUTB(atadev->channel->r_io, ATA_DRIVE, + ATA_IDX_OUTB(atadev->channel, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | atadev->unit | ((lba>>24) &0xf)); atadev->channel->flags &= ~ATA_48BIT_ACTIVE; } switch (flags & ATA_WAIT_MASK) { case ATA_IMMEDIATE: - ATA_OUTB(atadev->channel->r_io, ATA_CMD, command); + ATA_IDX_OUTB(atadev->channel, ATA_CMD, command); /* enable interrupt */ if (atadev->channel->flags & ATA_QUEUED) - ATA_OUTB(atadev->channel->r_altio, ATA_ALTSTAT, ATA_A_4BIT); + ATA_IDX_OUTB(atadev->channel, ATA_ALTSTAT, ATA_A_4BIT); break; case ATA_WAIT_INTR: atadev->channel->active |= ATA_WAIT_INTR; - ATA_OUTB(atadev->channel->r_io, ATA_CMD, command); + ATA_IDX_OUTB(atadev->channel, ATA_CMD, command); /* enable interrupt */ if (atadev->channel->flags & ATA_QUEUED) - ATA_OUTB(atadev->channel->r_altio, ATA_ALTSTAT, ATA_A_4BIT); + ATA_IDX_OUTB(atadev->channel, ATA_ALTSTAT, ATA_A_4BIT); if (tsleep(atadev->channel, PRIBIO, "atacmd", 10 * hz)) { ata_prtdev(atadev, "timeout waiting for interrupt\n"); @@ -1117,7 +1074,7 @@ ata_command(struct ata_device *atadev, u_int8_t command, case ATA_WAIT_READY: atadev->channel->active |= ATA_WAIT_READY; - ATA_OUTB(atadev->channel->r_io, ATA_CMD, command); + ATA_IDX_OUTB(atadev->channel, ATA_CMD, command); if (ata_wait(atadev, ATA_S_READY) < 0) { ata_prtdev(atadev, "timeout waiting for cmd=%02x s=%02x e=%02x\n", command, atadev->channel->status,atadev->channel->error); @@ -1132,48 +1089,48 @@ ata_command(struct ata_device *atadev, u_int8_t command, static void ata_enclosure_start(struct ata_device *atadev) { - ATA_INB(atadev->channel->r_io, ATA_DRIVE); + ATA_IDX_INB(atadev->channel, ATA_DRIVE); DELAY(1); - ATA_INB(atadev->channel->r_io, ATA_DRIVE); + ATA_IDX_INB(atadev->channel, ATA_DRIVE); DELAY(1); - ATA_INB(atadev->channel->r_io, ATA_CMD); + ATA_IDX_INB(atadev->channel, ATA_CMD); DELAY(1); - ATA_OUTB(atadev->channel->r_io, ATA_DRIVE, ATA_D_IBM | atadev->unit); + ATA_IDX_OUTB(atadev->channel, ATA_DRIVE, ATA_D_IBM | atadev->unit); DELAY(1); - ATA_OUTB(atadev->channel->r_io, ATA_DRIVE, ATA_D_IBM | atadev->unit); + ATA_IDX_OUTB(atadev->channel, ATA_DRIVE, ATA_D_IBM | atadev->unit); DELAY(1); - ATA_OUTB(atadev->channel->r_io, ATA_DRIVE, ATA_D_IBM | atadev->unit); + ATA_IDX_OUTB(atadev->channel, ATA_DRIVE, ATA_D_IBM | atadev->unit); DELAY(1); - ATA_INB(atadev->channel->r_io, ATA_COUNT); + ATA_IDX_INB(atadev->channel, ATA_COUNT); DELAY(1); - ATA_INB(atadev->channel->r_io, ATA_DRIVE); + ATA_IDX_INB(atadev->channel, ATA_DRIVE); DELAY(1); } static void ata_enclosure_end(struct ata_device *atadev) { - ATA_OUTB(atadev->channel->r_io, ATA_DRIVE, ATA_D_IBM | atadev->unit); + ATA_IDX_OUTB(atadev->channel, ATA_DRIVE, ATA_D_IBM | atadev->unit); DELAY(1); } static void ata_enclosure_chip_start(struct ata_device *atadev) { - ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, 0x0b); - ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, 0x0a); + ATA_IDX_OUTB(atadev->channel, ATA_SECTOR, 0x0b); + ATA_IDX_OUTB(atadev->channel, ATA_SECTOR, 0x0a); DELAY(25); - ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, 0x08); + ATA_IDX_OUTB(atadev->channel, ATA_SECTOR, 0x08); } static void ata_enclosure_chip_end(struct ata_device *atadev) { - ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, 0x08); + ATA_IDX_OUTB(atadev->channel, ATA_SECTOR, 0x08); DELAY(64); - ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, 0x0a); + ATA_IDX_OUTB(atadev->channel, ATA_SECTOR, 0x0a); DELAY(25); - ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, 0x0b); + ATA_IDX_OUTB(atadev->channel, ATA_SECTOR, 0x0b); DELAY(64); } @@ -1182,11 +1139,11 @@ ata_enclosure_chip_rdbit(struct ata_device *atadev) { u_int8_t val; - ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, 0); + ATA_IDX_OUTB(atadev->channel, ATA_SECTOR, 0); DELAY(64); - ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, 0x02); + ATA_IDX_OUTB(atadev->channel, ATA_SECTOR, 0x02); DELAY(25); - val = ATA_INB(atadev->channel->r_io, ATA_SECTOR) & 0x01; + val = ATA_IDX_INB(atadev->channel, ATA_SECTOR) & 0x01; DELAY(38); return val; } @@ -1194,9 +1151,9 @@ ata_enclosure_chip_rdbit(struct ata_device *atadev) static void ata_enclosure_chip_wrbit(struct ata_device *atadev, u_int8_t data) { - ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, 0x08 | (data & 0x01)); + ATA_IDX_OUTB(atadev->channel, ATA_SECTOR, 0x08 | (data & 0x01)); DELAY(64); - ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, 0x08 | 0x02 | (data & 0x01)); + ATA_IDX_OUTB(atadev->channel, ATA_SECTOR, 0x08 | 0x02 | (data & 0x01)); DELAY(64); } @@ -1283,9 +1240,9 @@ ata_enclosure_print(struct ata_device *atadev) atadev->channel->locking(atadev->channel, ATA_LF_LOCK); ATA_SLEEPLOCK_CH(atadev->channel, ATA_CONTROL); ata_enclosure_start(atadev); - id = ATA_INB(atadev->channel->r_io, ATA_DRIVE); + id = ATA_IDX_INB(atadev->channel, ATA_DRIVE); DELAY(1); - st = ATA_INB(atadev->channel->r_io, ATA_COUNT); + st = ATA_IDX_INB(atadev->channel, ATA_COUNT); DELAY(1); ata_enclosure_end(atadev); ATA_UNLOCK_CH(atadev->channel); @@ -1323,9 +1280,9 @@ ata_enclosure_leds(struct ata_device *atadev, u_int8_t color) u_int8_t reg; ata_enclosure_start(atadev); - reg = ATA_INB(atadev->channel->r_io, ATA_COUNT); + reg = ATA_IDX_INB(atadev->channel, ATA_COUNT); DELAY(1); - ATA_OUTB(atadev->channel->r_io, ATA_COUNT, + ATA_IDX_OUTB(atadev->channel, ATA_COUNT, (color & ATA_LED_MASK) | (reg & ~ATA_LED_MASK)); DELAY(1); ata_enclosure_end(atadev); diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h index 52d4348..7bb9189 100644 --- a/sys/dev/ata/ata-all.h +++ b/sys/dev/ata/ata-all.h @@ -109,7 +109,7 @@ #define ATA_S_READY 0x40 /* drive ready */ #define ATA_S_BUSY 0x80 /* busy */ -#define ATA_ALTSTAT 0x00 /* alternate status register */ +#define ATA_ALTSTAT 0x08 /* alternate status register */ #define ATA_ALTOFFSET 0x206 /* alternate registers offset */ #define ATA_PCCARD_ALTOFFSET 0x0e /* do for PCCARD devices */ #define ATA_PC98_ALTOFFSET 0x10c /* do for PC98 devices */ @@ -122,6 +122,7 @@ #define ATA_SECONDARY 0x170 #define ATA_PC98_BANK 0x432 #define ATA_IOSIZE 0x08 +#define ATA_PC98_IOSIZE 0x10 #define ATA_ALTIOSIZE 0x01 #define ATA_BMIOSIZE 0x08 #define ATA_PC98_BANKIOSIZE 0x01 @@ -129,7 +130,7 @@ #define ATA_OP_CONTINUES 0x01 #define ATA_IOADDR_RID 0 #define ATA_ALTADDR_RID 1 -#define ATA_BMADDR_RID 2 +#define ATA_BMADDR_RID 0x20 #define ATA_PC98_ALTADDR_RID 8 #define ATA_PC98_BANKADDR_RID 9 @@ -140,12 +141,12 @@ #define ATA_DMA_ENTRIES 256 #define ATA_DMA_EOT 0x80000000 -#define ATA_BMCMD_PORT 0x00 +#define ATA_BMCMD_PORT 0x09 #define ATA_BMCMD_START_STOP 0x01 #define ATA_BMCMD_WRITE_READ 0x08 -#define ATA_BMDEVSPEC_0 0x01 -#define ATA_BMSTAT_PORT 0x02 +#define ATA_BMDEVSPEC_0 0x0a +#define ATA_BMSTAT_PORT 0x0b #define ATA_BMSTAT_ACTIVE 0x01 #define ATA_BMSTAT_ERROR 0x02 #define ATA_BMSTAT_INTERRUPT 0x04 @@ -154,8 +155,10 @@ #define ATA_BMSTAT_DMA_SLAVE 0x40 #define ATA_BMSTAT_DMA_SIMPLEX 0x80 -#define ATA_BMDEVSPEC_1 0x03 -#define ATA_BMDTP_PORT 0x04 +#define ATA_BMDEVSPEC_1 0x0c +#define ATA_BMDTP_PORT 0x0d + +#define ATA_MAX_RES 0x10 /* structure for holding DMA address data */ struct ata_dmaentry { @@ -163,18 +166,6 @@ struct ata_dmaentry { u_int32_t count; }; -struct ata_dmastate { - bus_dma_tag_t ddmatag; /* data DMA tag */ - bus_dmamap_t ddmamap; /* data DMA map */ - bus_dma_tag_t cdmatag; /* control DMA tag */ - bus_dmamap_t cdmamap; /* control DMA map */ - struct ata_dmaentry *dmatab; /* DMA transfer table */ - bus_addr_t mdmatab; /* bus address of dmatab */ - int flags; /* debugging */ -#define ATA_DS_ACTIVE 0x01 /* debugging */ -#define ATA_DS_READ 0x02 /* transaction is a read */ -}; - /* structure describing an ATA/ATAPI device */ struct ata_device { struct ata_channel *channel; @@ -195,33 +186,44 @@ struct ata_device { void *result; /* misc data */ int mode; /* transfermode */ void (*setmode)(struct ata_device *, int); - struct ata_dmastate dmastate; /* dma state */ }; -/* structure holding DMA function pointers */ -struct ata_dma_funcs { - void (*create)(struct ata_channel *); - void (*destroy)(struct ata_channel *); - int (*alloc)(struct ata_device *); - void (*free)(struct ata_device *); +/* structure holding DMA related information */ +struct ata_dma_data { + bus_dma_tag_t dmatag; /* parent DMA tag */ + bus_dma_tag_t cdmatag; /* control DMA tag */ + bus_dmamap_t cdmamap; /* control DMA map */ + bus_dma_tag_t ddmatag; /* data DMA tag */ + bus_dmamap_t ddmamap; /* data DMA map */ + struct ata_dmaentry *dmatab; /* DMA transfer table */ + bus_addr_t mdmatab; /* bus address of dmatab */ + u_int32_t alignment; /* DMA engine alignment */ + int flags; +#define ATA_DMA_ACTIVE 0x01 /* DMA transfer in progress */ +#define ATA_DMA_READ 0x02 /* transaction is a read */ + + int (*alloc)(struct ata_channel *); + void (*free)(struct ata_channel *); int (*setup)(struct ata_device *, caddr_t, int32_t); - int (*start)(struct ata_device *, caddr_t, int32_t, int); - int (*stop)(struct ata_device *); + int (*start)(struct ata_channel *, caddr_t, int32_t, int); + int (*stop)(struct ata_channel *); int (*status)(struct ata_channel *); - u_int32_t alignment; /* dma engine alignment */ +}; + +/* structure holding resources for an ATA channel */ +struct ata_resource { + struct resource *res; + int offset; }; /* structure describing an ATA channel */ struct ata_channel { struct device *dev; /* device handle */ int unit; /* channel number */ - struct resource *r_io; /* io addr resource handle */ - struct resource *r_altio; /* altio addr resource handle */ - struct resource *r_bmio; /* bmio addr resource handle */ - bus_dma_tag_t dmatag; /* parent dma tag */ + struct ata_resource r_io[ATA_MAX_RES];/* I/O resources */ struct resource *r_irq; /* interrupt of this channel */ void *ih; /* interrupt handle */ - struct ata_dma_funcs *dma; /* DMA functions */ + struct ata_dma_data *dma; /* DMA data / functions */ u_int32_t chiptype; /* controller chip PCI id */ int flags; /* channel flags */ #define ATA_NO_SLAVE 0x01 @@ -229,8 +231,7 @@ struct ata_channel { #define ATA_USE_PC98GEOM 0x04 #define ATA_ATAPI_DMA_RO 0x08 #define ATA_QUEUED 0x10 -#define ATA_DMA_ACTIVE 0x20 -#define ATA_48BIT_ACTIVE 0x40 +#define ATA_48BIT_ACTIVE 0x20 struct ata_device device[2]; /* devices on this channel */ #define MASTER 0x00 @@ -316,6 +317,7 @@ int ata_limit_mode(struct ata_device *, int, int); #define ATA_INB(res, offset) \ bus_space_read_1(rman_get_bustag((res)), \ rman_get_bushandle((res)), (offset)) + #define ATA_INW(res, offset) \ bus_space_read_2(rman_get_bustag((res)), \ rman_get_bushandle((res)), (offset)) @@ -363,3 +365,31 @@ int ata_limit_mode(struct ata_device *, int, int); bus_space_write_multi_stream_4(rman_get_bustag((res)), \ rman_get_bushandle((res)), \ (offset), (addr), (count)) +#define ATA_IDX_INB(ch, idx) \ + ATA_INB(ch->r_io[idx].res, ch->r_io[idx].offset) +#define ATA_IDX_INW(ch, idx) \ + ATA_INW(ch->r_io[idx].res, ch->r_io[idx].offset) +#define ATA_IDX_INL(ch, idx) \ + ATA_INL(ch->r_io[idx].res, ch->r_io[idx].offset) +#define ATA_IDX_INSW(ch, idx, addr, count) \ + ATA_INSW(ch->r_io[idx].res, ch->r_io[idx].offset, addr, count) +#define ATA_IDX_INSW_STRM(ch, idx, addr, count) \ + ATA_INSW_STRM(ch->r_io[idx].res, ch->r_io[idx].offset, addr, count) +#define ATA_IDX_INSL(ch, idx, addr, count) \ + ATA_INSL(ch->r_io[idx].res, ch->r_io[idx].offset, addr, count) +#define ATA_IDX_INSL_STRM(ch, idx, addr, count) \ + ATA_INSL_STRM(ch->r_io[idx].res, ch->r_io[idx].offset, addr, count) +#define ATA_IDX_OUTB(ch, idx, value) \ + ATA_OUTB(ch->r_io[idx].res, ch->r_io[idx].offset, value) +#define ATA_IDX_OUTW(ch, idx, value) \ + ATA_OUTW(ch->r_io[idx].res, ch->r_io[idx].offset, value) +#define ATA_IDX_OUTL(ch, idx, value) \ + ATA_OUTL(ch->r_io[idx].res, ch->r_io[idx].offset, value) +#define ATA_IDX_OUTSW(ch, idx, addr, count) \ + ATA_OUTSW(ch->r_io[idx].res, ch->r_io[idx].offset, addr, count) +#define ATA_IDX_OUTSW_STRM(ch, idx, addr, count) \ + ATA_OUTSW_STRM(ch->r_io[idx].res, ch->r_io[idx].offset, addr, count) +#define ATA_IDX_OUTSL(ch, idx, addr, count) \ + ATA_OUTSL(ch->r_io[idx].res, ch->r_io[idx].offset, addr, count) +#define ATA_IDX_OUTSL_STRM(ch, idx, addr, count) \ + ATA_OUTSL_STRM(ch->r_io[idx].res, ch->r_io[idx].offset, addr, count) diff --git a/sys/dev/ata/ata-card.c b/sys/dev/ata/ata-card.c index 8adf0b2..f616a0f 100644 --- a/sys/dev/ata/ata-card.c +++ b/sys/dev/ata/ata-card.c @@ -77,8 +77,8 @@ static int ata_pccard_probe(device_t dev) { struct ata_channel *ch = device_get_softc(dev); - struct resource *io; - int rid, len, start, end; + struct resource *io, *altio; + int i, rid, len, start, end; u_long tmp; /* allocate the io range to get start and length */ @@ -87,7 +87,7 @@ ata_pccard_probe(device_t dev) io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, ATA_IOSIZE, RF_ACTIVE); if (!io) - return ENOMEM; + return ENXIO; /* reallocate the io address to only cover the io ports */ start = rman_get_start(io); @@ -95,7 +95,6 @@ ata_pccard_probe(device_t dev) bus_release_resource(dev, SYS_RES_IOPORT, rid, io); io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, start, end, ATA_IOSIZE, RF_ACTIVE); - bus_release_resource(dev, SYS_RES_IOPORT, rid, io); /* * if we got more than the default ATA_IOSIZE ports, this is likely @@ -112,9 +111,29 @@ ata_pccard_probe(device_t dev) start + ATA_ALTOFFSET, ATA_ALTIOSIZE); } } - else - return ENOMEM; + else { + bus_release_resource(dev, SYS_RES_IOPORT, rid, io); + return ENXIO; + } + + /* allocate the altport range */ + rid = ATA_ALTADDR_RID; + altio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, + ATA_ALTIOSIZE, RF_ACTIVE); + if (!altio) { + bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, io); + return ENXIO; + } + + /* setup the resource vectors */ + for (i = ATA_DATA; i <= ATA_STATUS; i++) { + ch->r_io[i].res = io; + ch->r_io[i].offset = i; + } + ch->r_io[ATA_ALTSTAT].res = altio; + ch->r_io[ATA_ALTSTAT].offset = 0; + /* initialize softc for this channel */ ch->unit = 0; ch->flags |= (ATA_USE_16BIT | ATA_NO_SLAVE); ch->locking = ata_pccard_locknoop; @@ -123,11 +142,27 @@ ata_pccard_probe(device_t dev) return ata_probe(dev); } +static int +ata_pccard_detach(device_t dev) +{ + struct ata_channel *ch = device_get_softc(dev); + int i; + + ata_detach(dev); + bus_release_resource(dev, SYS_RES_IOPORT, + ATA_ALTADDR_RID, ch->r_io[ATA_ALTSTAT].res); + bus_release_resource(dev, SYS_RES_IOPORT, + ATA_IOADDR_RID, ch->r_io[ATA_DATA].res); + for (i = ATA_DATA; i <= ATA_MAX_RES; i++) + ch->r_io[i].res = NULL; + return 0; +} + static device_method_t ata_pccard_methods[] = { /* device interface */ DEVMETHOD(device_probe, pccard_compat_probe), DEVMETHOD(device_attach, pccard_compat_attach), - DEVMETHOD(device_detach, ata_detach), + DEVMETHOD(device_detach, ata_pccard_detach), /* Card interface */ DEVMETHOD(card_compat_match, ata_pccard_match), diff --git a/sys/dev/ata/ata-cbus.c b/sys/dev/ata/ata-cbus.c index 38a2d20..0bca3ab 100644 --- a/sys/dev/ata/ata-cbus.c +++ b/sys/dev/ata/ata-cbus.c @@ -42,10 +42,6 @@ #include <dev/ata/ata-all.h> /* local vars */ -static bus_addr_t ata_pc98_ports[] = { - 0x0, 0x2, 0x4, 0x6, 0x8, 0xa, 0xc, 0xe -}; - struct ata_cbus_controller { struct resource *io; struct resource *altio; @@ -56,8 +52,8 @@ struct ata_cbus_controller { void (*locking)(struct ata_channel *, int); int current_bank; struct { - void (*function)(void *); - void *argument; + void (*function)(void *); + void *argument; } interrupt[2]; }; @@ -79,11 +75,10 @@ ata_cbus_probe(device_t dev) /* allocate the ioport range */ rid = ATA_IOADDR_RID; - io = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, ata_pc98_ports, - ATA_IOSIZE, RF_ACTIVE); + io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, + ATA_PC98_IOSIZE, RF_ACTIVE); if (!io) - return ENOMEM; - isa_load_resourcev(io, ata_pc98_ports, ATA_IOSIZE); + return ENOMEM; /* calculate & set the altport range */ rid = ATA_PC98_ALTADDR_RID; @@ -111,37 +106,50 @@ ata_cbus_attach(device_t dev) /* allocate resources */ rid = ATA_IOADDR_RID; - ctlr->io = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, ata_pc98_ports, - ATA_IOSIZE, RF_ACTIVE); + ctlr->io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, + ATA_PC98_IOSIZE, RF_ACTIVE); if (!ctlr->io) return ENOMEM; - isa_load_resourcev(ctlr->io, ata_pc98_ports, ATA_IOSIZE); - rid = ATA_PC98_ALTADDR_RID; - ctlr->altio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, - rman_get_start(ctlr->io)+ATA_PC98_ALTOFFSET, - ~0, ATA_ALTIOSIZE, RF_ACTIVE); - if (!ctlr->altio) + ctlr->altio = + bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, + rman_get_start(ctlr->io) + ATA_PC98_ALTOFFSET, ~0, + ATA_ALTIOSIZE, RF_ACTIVE); + if (!ctlr->altio) { + bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, ctlr->io); return ENOMEM; + } rid = ATA_PC98_BANKADDR_RID; ctlr->bankio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, ATA_PC98_BANK, ~0, ATA_PC98_BANKIOSIZE, RF_ACTIVE); - if (!ctlr->bankio) + if (!ctlr->bankio) { + bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, ctlr->io); + bus_release_resource(dev, SYS_RES_IOPORT, ATA_ALTADDR_RID, ctlr->altio); return ENOMEM; + } - rid = 0; + rid = ATA_IRQ_RID; if (!(ctlr->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, - 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE))) { + 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE))) { device_printf(dev, "unable to alloc interrupt\n"); + bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, ctlr->io); + bus_release_resource(dev, SYS_RES_IOPORT, ATA_ALTADDR_RID, ctlr->altio); + bus_release_resource(dev, SYS_RES_IOPORT, + ATA_PC98_BANKADDR_RID, ctlr->bankio); return ENXIO; } if ((bus_setup_intr(dev, ctlr->irq, INTR_TYPE_BIO | INTR_ENTROPY, ata_cbus_intr, ctlr, &ctlr->ih))) { device_printf(dev, "unable to setup interrupt\n"); + bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, ctlr->io); + bus_release_resource(dev, SYS_RES_IOPORT, ATA_ALTADDR_RID, ctlr->altio); + bus_release_resource(dev, SYS_RES_IOPORT, + ATA_PC98_BANKADDR_RID, ctlr->bankio); + bus_release_resource(dev, SYS_RES_IOPORT, ATA_IRQ_RID, ctlr->irq); return ENXIO; } @@ -226,9 +234,8 @@ ata_cbus_banking(struct ata_channel *ch, int flags) if (ctlr->current_bank == ch->unit) break; while (!atomic_cmpset_acq_int(&ctlr->current_bank, -1, ch->unit)) - tsleep((caddr_t)ch->locking, PRIBIO, "atalck", 1); - bus_space_write_1(rman_get_bustag(ctlr->bankio), - rman_get_bushandle(ctlr->bankio), 0, ch->unit); + tsleep((caddr_t)ch->locking, PRIBIO, "atabnk", 1); + ATA_OUTB(ctlr->bankio, 0, ch->unit); break; case ATA_LF_UNLOCK: @@ -283,10 +290,20 @@ ata_cbussub_probe(device_t dev) ch->unit = i; } free(children, M_TEMP); + + /* setup the resource vectors */ + for (i = ATA_DATA; i <= ATA_STATUS; i ++) { + ch->r_io[i].res = ctlr->io; + ch->r_io[i].offset = i << 1; + } + ch->r_io[ATA_ALTSTAT].res = ctlr->altio; + ch->r_io[ATA_ALTSTAT].offset = 0; + + /* initialize softc for this channel */ ch->flags |= ATA_USE_16BIT | ATA_USE_PC98GEOM; + ch->locking = ctlr->locking; ch->device[MASTER].setmode = ctlr->setmode; ch->device[SLAVE].setmode = ctlr->setmode; - ch->locking = ctlr->locking; return ata_probe(dev); } diff --git a/sys/dev/ata/ata-chipset.c b/sys/dev/ata/ata-chipset.c index 5ec0dd8..03dcf20 100644 --- a/sys/dev/ata/ata-chipset.c +++ b/sys/dev/ata/ata-chipset.c @@ -79,12 +79,12 @@ static int ata_via_chipinit(device_t); static void ata_via_family_setmode(struct ata_device *, int); static void ata_via_southbridge_fixup(device_t); static int ata_promise_chipinit(device_t); -static void ata_promise_intr(void *); +static void ata_promise_old_intr(void *); static void ata_promise_tx2_intr(void *); static void ata_promise_setmode(struct ata_device *, int); -static int ata_promise_dmainit(struct ata_channel *); -static int ata_promise_dmastart(struct ata_device *, caddr_t, int32_t, int); -static int ata_promise_dmastop(struct ata_device *); +static int ata_promise_old_dmainit(struct ata_channel *); +static int ata_promise_old_dmastart(struct ata_channel *, caddr_t, int32_t,int); +static int ata_promise_old_dmastop(struct ata_channel *); static int ata_serverworks_chipinit(device_t); static void ata_serverworks_setmode(struct ata_device *, int); static int ata_sii_chipinit(device_t); @@ -134,10 +134,10 @@ ata_generic_intr(void *data) for (unit = 0; unit < 2; unit++) { if (!(ch = ctlr->interrupt[unit].argument)) continue; - if (ch->flags & ATA_DMA_ACTIVE) { + if (ch->dma->flags & ATA_DMA_ACTIVE) { if (!((dmastat = ch->dma->status(ch)) & ATA_BMSTAT_INTERRUPT)) continue; - ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, dmastat|ATA_BMSTAT_INTERRUPT); + ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, dmastat|ATA_BMSTAT_INTERRUPT); DELAY(1); } ctlr->interrupt[unit].function(ch); @@ -219,13 +219,13 @@ ata_acard_intr(void *data) if (ctlr->chip->cfg1 == ATPOLD && ctlr->locked_ch != unit) continue; ch = ctlr->interrupt[unit].argument; - if (ch->flags & ATA_DMA_ACTIVE) { + if (ch->dma->flags & ATA_DMA_ACTIVE) { if (!((dmastat = ch->dma->status(ch)) & ATA_BMSTAT_INTERRUPT)) continue; - ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, dmastat|ATA_BMSTAT_INTERRUPT); + ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, dmastat|ATA_BMSTAT_INTERRUPT); DELAY(1); - ATA_OUTB(ch->r_bmio, ATA_BMCMD_PORT, - ATA_INB(ch->r_bmio, ATA_BMCMD_PORT)&~ATA_BMCMD_START_STOP); + ATA_IDX_OUTB(ch, ATA_BMCMD_PORT, + ATA_IDX_INB(ch, ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP); DELAY(1); } ctlr->interrupt[unit].function(ch); @@ -490,6 +490,7 @@ ata_cyrix_chipinit(device_t dev) static void ata_cyrix_setmode(struct ata_device *atadev, int mode) { + struct ata_channel *ch = atadev->channel; int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit); u_int32_t piotiming[] = { 0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010 }; @@ -507,16 +508,16 @@ ata_cyrix_setmode(struct ata_device *atadev, int mode) (error) ? "failed" : "success", ata_mode2str(mode)); if (!error) { if (mode >= ATA_UDMA0) { - ATA_OUTL(atadev->channel->r_bmio, (devno << 3) + 0x24, - udmatiming[mode % ATA_MODE_MASK]); + ATA_OUTL(ch->r_io[ATA_BMCMD_PORT].res, + 0x24 + (devno << 3), udmatiming[mode % ATA_MODE_MASK]); } else if (mode >= ATA_WDMA0) { - ATA_OUTL(atadev->channel->r_bmio, (devno << 3) + 0x24, - dmatiming[mode % ATA_MODE_MASK]); + ATA_OUTL(ch->r_io[ATA_BMCMD_PORT].res, + 0x24 + (devno << 3), dmatiming[mode % ATA_MODE_MASK]); } else { - ATA_OUTL(atadev->channel->r_bmio, (devno << 3) + 0x20, - piotiming[mode % ATA_MODE_MASK]); + ATA_OUTL(ch->r_io[ATA_BMCMD_PORT].res, + 0x20 + (devno << 3), piotiming[mode % ATA_MODE_MASK]); } atadev->mode = mode; } @@ -666,7 +667,7 @@ ata_highpoint_intr(void *data) if (((dmastat = ch->dma->status(ch)) & (ATA_BMSTAT_ACTIVE | ATA_BMSTAT_INTERRUPT))!=ATA_BMSTAT_INTERRUPT) continue; - ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, dmastat | ATA_BMSTAT_INTERRUPT); + ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, dmastat | ATA_BMSTAT_INTERRUPT); DELAY(1); ctlr->interrupt[unit].function(ch); } @@ -786,7 +787,7 @@ ata_intel_chipinit(device_t dev) if (ata_default_interrupt(dev)) return ENXIO; - if (ctlr->chip->chiptype == ATA_I82371FB) + if (ctlr->chip->chipid == ATA_I82371FB) ctlr->setmode = ata_intel_old_setmode; else ctlr->setmode = ata_intel_new_setmode; @@ -936,10 +937,6 @@ ata_promise_ident(device_t dev) { ATA_PDC20275, 0, PRTX, 0x00, ATA_UDMA6, "Promise PDC20275" }, { ATA_PDC20276, 0, PRTX, PRSX6K, ATA_UDMA6, "Promise PDC20276" }, { ATA_PDC20277, 0, PRTX, 0x00, ATA_UDMA6, "Promise PDC20277" }, -#if 0 - { ATA_PDC20376, 0, PRCH, 0x00, ATA_SDMA6, "Promise PDC20376" }, - { ATA_PDC20621, 0, PRCH, 0x00, ATA_SDMA6, "Promise SX4000" }, -#endif { 0, 0, 0, 0, 0, 0}}; char *desc, buffer[64]; uintptr_t devid = 0; @@ -995,21 +992,35 @@ ata_promise_chipinit(device_t dev) device_printf(dev, "unable to map interrupt\n"); return ENXIO; } - if ((bus_setup_intr(dev, ctlr->r_irq, INTR_TYPE_BIO | INTR_ENTROPY, - ctlr->chip->cfg1 == PRTX ? - ata_promise_tx2_intr : ata_promise_intr, - ctlr, &ctlr->handle))) { - device_printf(dev, "unable to setup interrupt\n"); - return ENXIO; + + switch (ctlr->chip->cfg1) { + case PRNEW: + ctlr->dmainit = ata_promise_old_dmainit; + /* FALLTHROUGH */ + + case PROLD: + if ((bus_setup_intr(dev, ctlr->r_irq, INTR_TYPE_BIO | INTR_ENTROPY, + ata_promise_old_intr, ctlr, &ctlr->handle))) { + device_printf(dev, "unable to setup interrupt\n"); + return ENXIO; + } + break; + + case PRTX: + if ((bus_setup_intr(dev, ctlr->r_irq, INTR_TYPE_BIO | INTR_ENTROPY, + ata_promise_tx2_intr, ctlr, &ctlr->handle))) { + device_printf(dev, "unable to setup interrupt\n"); + return ENXIO; + } + break; } + ctlr->setmode = ata_promise_setmode; - if (ctlr->chip->cfg1 == PRNEW ) - ctlr->dmainit = ata_promise_dmainit; return 0; } static void -ata_promise_intr(void *data) +ata_promise_old_intr(void *data) { struct ata_pci_controller *ctlr = data; struct ata_channel *ch = ctlr->interrupt[0].argument; @@ -1020,13 +1031,11 @@ ata_promise_intr(void *data) for (unit = 0; unit < 2; unit++) { if (!(ch = ctlr->interrupt[unit].argument)) continue; - if (ATA_INL(ch->r_bmio, (ch->unit ? 0x14 : 0x1c)) & - (ch->unit ? 0x00004000 : 0x00000400)) { - if (ch->flags & ATA_DMA_ACTIVE) { + if (ATA_INL(ctlr->r_bmio, 0x1c) & (ch->unit ? 0x00004000 : 0x00000400)){ + if (ch->dma->flags & ATA_DMA_ACTIVE) { if (!((dmastat = ch->dma->status(ch)) & ATA_BMSTAT_INTERRUPT)) continue; - ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, - dmastat | ATA_BMSTAT_INTERRUPT); + ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, dmastat|ATA_BMSTAT_INTERRUPT); DELAY(1); } ctlr->interrupt[unit].function(ch); @@ -1046,13 +1055,12 @@ ata_promise_tx2_intr(void *data) for (unit = 0; unit < 2; unit++) { if (!(ch = ctlr->interrupt[unit].argument)) continue; - ATA_OUTB(ch->r_bmio, ATA_BMDEVSPEC_0, 0x0b); - if (ATA_INB(ch->r_bmio, ATA_BMDEVSPEC_1) & 0x20) { - if (ch->flags & ATA_DMA_ACTIVE) { + ATA_IDX_OUTB(ch, ATA_BMDEVSPEC_0, 0x0b); + if (ATA_IDX_INB(ch, ATA_BMDEVSPEC_1) & 0x20) { + if (ch->dma->flags & ATA_DMA_ACTIVE) { if (!((dmastat = ch->dma->status(ch)) & ATA_BMSTAT_INTERRUPT)) continue; - ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, - dmastat | ATA_BMSTAT_INTERRUPT); + ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, dmastat | ATA_BMSTAT_INTERRUPT); DELAY(1); } ctlr->interrupt[unit].function(ch); @@ -1088,16 +1096,19 @@ ata_promise_setmode(struct ata_device *atadev, int mode) mode = ata_limit_mode(atadev, mode, ctlr->chip->max_dma); /* is this a TX2 or later chip ? */ - if (ctlr->chip->cfg1 >= PRTX) { - ATA_OUTB(atadev->channel->r_bmio, ATA_BMDEVSPEC_0, 0x0b); + switch (ctlr->chip->cfg1) { + case PRTX: + ATA_IDX_OUTB(atadev->channel, ATA_BMDEVSPEC_0, 0x0b); if (mode > ATA_UDMA2 && - ATA_INB(atadev->channel->r_bmio, ATA_BMDEVSPEC_1) & 0x04) { + ATA_IDX_INB(atadev->channel, ATA_BMDEVSPEC_1) & 0x04) { ata_prtdev(atadev, "DMA limited to UDMA33, non-ATA66 cable or device\n"); mode = ATA_UDMA2; } - } - else { + break; + + case PROLD: + case PRNEW: if (mode > ATA_UDMA2 && (pci_read_config(parent, 0x50, 2) & (atadev->channel->unit ? 1 << 11 : 1 << 10))) { ata_prtdev(atadev, @@ -1125,50 +1136,50 @@ ata_promise_setmode(struct ata_device *atadev, int mode) } static int -ata_promise_dmainit(struct ata_channel *ch) +ata_promise_old_dmainit(struct ata_channel *ch) { int error; if ((error = ata_dmainit(ch))) return error; - ch->dma->start = ata_promise_dmastart; - ch->dma->stop = ata_promise_dmastop; + ch->dma->start = ata_promise_old_dmastart; + ch->dma->stop = ata_promise_old_dmastop; return 0; } static int -ata_promise_dmastart(struct ata_device *atadev, +ata_promise_old_dmastart(struct ata_channel *ch, caddr_t data, int32_t count, int dir) { - struct ata_channel *ch = atadev->channel; + struct ata_pci_controller *ctlr = + device_get_softc(device_get_parent(ch->dev)); int error; - if ((error = ata_dmastart(atadev, data, count, dir))) + if ((error = ata_dmastart(ch, data, count, dir))) return error; if (ch->flags & ATA_48BIT_ACTIVE) { - ATA_OUTB(ch->r_bmio, (ch->unit ? 0x09 : 0x11), - ATA_INB(ch->r_bmio, (ch->unit ? 0x09 : 0x11)) | - (ch->unit ? 0x08 : 0x02)); - ATA_OUTL(ch->r_bmio, (ch->unit ? 0x1c : 0x20), + ATA_OUTB(ctlr->r_bmio, 0x11, + ATA_INB(ctlr->r_bmio, 0x11) | (ch->unit ? 0x08 : 0x02)); + ATA_OUTL(ctlr->r_bmio, 0x20, (dir ? 0x05000000 : 0x06000000) | (count >> 1)); } return 0; } static int -ata_promise_dmastop(struct ata_device *atadev) +ata_promise_old_dmastop(struct ata_channel *ch) { - struct ata_channel *ch = atadev->channel; + struct ata_pci_controller *ctlr = + device_get_softc(device_get_parent(ch->dev)); if (ch->flags & ATA_48BIT_ACTIVE) { - ATA_OUTB(ch->r_bmio, (ch->unit ? 0x09 : 0x11), - ATA_INB(ch->r_bmio, (ch->unit ? 0x09 : 0x11)) & - ~(ch->unit ? 0x08 : 0x02)); - ATA_OUTL(ch->r_bmio, (ch->unit ? 0x1c : 0x20), 0); + ATA_OUTB(ctlr->r_bmio, 0x11, + ATA_INB(ctlr->r_bmio, 0x11) & ~(ch->unit ? 0x08 : 0x02)); + ATA_OUTL(ctlr->r_bmio, 0x20, 0); } - return ata_dmastop(atadev); + return ata_dmastop(ch); } /* @@ -1339,10 +1350,10 @@ ata_cmd_intr(void *data) continue; pci_write_config(device_get_parent(ch->dev), 0x71, (ch->unit ? 0x08 : 0x04), 1); - if (ch->flags & ATA_DMA_ACTIVE) { + if (ch->dma->flags & ATA_DMA_ACTIVE) { if (!((dmastat = ch->dma->status(ch)) & ATA_BMSTAT_INTERRUPT)) continue; - ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, dmastat|ATA_BMSTAT_INTERRUPT); + ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, dmastat | ATA_BMSTAT_INTERRUPT); DELAY(1); } ctlr->interrupt[unit].function(ch); @@ -1831,8 +1842,8 @@ ata_find_dev(device_t dev, u_int32_t devid, u_int32_t revid, int slot) static struct ata_chip_id * ata_match_chip(device_t dev, struct ata_chip_id *index, int slot) { - while (index->chiptype != 0) { - if (ata_find_dev(dev, index->chiptype, index->chiprev, slot)) + while (index->chipid != 0) { + if (ata_find_dev(dev, index->chipid, index->chiprev, slot)) return index; index++; } @@ -1871,7 +1882,7 @@ ata_pci_serialize(struct ata_channel *ch, int flags) if (scp->locked_ch == ch->unit) break; while (!atomic_cmpset_acq_int(&scp->locked_ch, -1, ch->unit)) - tsleep(ch->locking, PRIBIO, "atalck", 1); + tsleep(ch->locking, PRIBIO, "atasrl", 1); break; case ATA_LF_UNLOCK: diff --git a/sys/dev/ata/ata-disk.c b/sys/dev/ata/ata-disk.c index 8523c33..c7d80cb 100644 --- a/sys/dev/ata/ata-disk.c +++ b/sys/dev/ata/ata-disk.c @@ -229,19 +229,19 @@ ad_detach(struct ata_device *atadev, int flush) /* get rid of flush XXX SOS */ biofinish(request->bp, NULL, ENXIO); ad_free(request); } - if (atadev->channel->dma) - atadev->channel->dma->free(atadev); while ((bp = bioq_first(&adp->queue))) { bioq_remove(&adp->queue, bp); biofinish(bp, NULL, ENXIO); } disk_destroy(&adp->disk); + + if (adp->flags & AD_F_RAID_SUBDISK) + ata_raiddisk_detach(adp); + if (flush) { if (ata_command(atadev, ATA_C_FLUSHCACHE, 0, 0, 0, ATA_WAIT_READY)) ata_prtdev(atadev, "flushing cache on detach failed\n"); } - if (adp->flags & AD_F_RAID_SUBDISK) - ata_raiddisk_detach(adp); ata_free_name(atadev); ata_free_lun(&adp_lun_map, adp->lun); atadev->driver = NULL; @@ -375,7 +375,7 @@ ad_start(struct ata_device *atadev) if (bp->bio_cmd == BIO_READ) request->flags |= ADR_F_READ; - if (adp->device->mode >= ATA_DMA && atadev->channel->dma->alloc(atadev)) + if (adp->device->mode >= ATA_DMA && !atadev->channel->dma) adp->device->mode = ATA_PIO; /* insert in tag array */ @@ -456,8 +456,7 @@ ad_transfer(struct ad_request *request) /* if ATA bus RELEASE check for SERVICE */ if (adp->flags & AD_F_TAG_ENABLED && - ATA_INB(adp->device->channel->r_io, ATA_IREASON) & - ATA_I_RELEASE) + ATA_IDX_INB(adp->device->channel, ATA_IREASON) & ATA_I_RELEASE) return ad_service(adp, 1); } else { @@ -483,7 +482,7 @@ ad_transfer(struct ad_request *request) } /* start transfer, return and wait for interrupt */ - adp->device->channel->dma->start(adp->device, request->data, request->bytecount, + adp->device->channel->dma->start(adp->device->channel, request->data, request->bytecount, request->flags & ADR_F_READ); return ATA_OP_CONTINUES; } @@ -517,11 +516,11 @@ ad_transfer(struct ad_request *request) /* output the data */ if (adp->device->channel->flags & ATA_USE_16BIT) - ATA_OUTSW_STRM(adp->device->channel->r_io, ATA_DATA, + ATA_IDX_OUTSW_STRM(adp->device->channel, ATA_DATA, (void *)((uintptr_t)request->data + request->donecount), request->currentsize / sizeof(int16_t)); else - ATA_OUTSL_STRM(adp->device->channel->r_io, ATA_DATA, + ATA_IDX_OUTSL_STRM(adp->device->channel, ATA_DATA, (void *)((uintptr_t)request->data + request->donecount), request->currentsize / sizeof(int32_t)); return ATA_OP_CONTINUES; @@ -553,7 +552,7 @@ ad_interrupt(struct ad_request *request) /* finish DMA transfer */ if (request->flags & ADR_F_DMA_USED) - dma_stat = adp->device->channel->dma->stop(adp->device); + dma_stat = adp->device->channel->dma->stop(adp->device->channel); /* do we have a corrected soft error ? */ if (adp->device->channel->status & ATA_S_CORR) @@ -564,7 +563,7 @@ ad_interrupt(struct ad_request *request) if ((adp->device->channel->status & ATA_S_ERROR) || (request->flags & ADR_F_DMA_USED && dma_stat & ATA_BMSTAT_ERROR)) { adp->device->channel->error = - ATA_INB(adp->device->channel->r_io, ATA_ERROR); + ATA_IDX_INB(adp->device->channel, ATA_ERROR); disk_err(request->bp, (adp->device->channel->error & ATA_E_ICRC) ? "UDMA ICRC error" : "hard error", request->blockaddr + (request->donecount / DEV_BSIZE), 1); @@ -621,12 +620,12 @@ ad_interrupt(struct ad_request *request) else { /* data ready, read in */ if (adp->device->channel->flags & ATA_USE_16BIT) - ATA_INSW_STRM(adp->device->channel->r_io, ATA_DATA, + ATA_IDX_INSW_STRM(adp->device->channel, ATA_DATA, (void*)((uintptr_t)request->data + request->donecount), request->currentsize / sizeof(int16_t)); else - ATA_INSL_STRM(adp->device->channel->r_io, ATA_DATA, + ATA_IDX_INSL_STRM(adp->device->channel, ATA_DATA, (void*)((uintptr_t)request->data + request->donecount), request->currentsize / sizeof(int32_t)); @@ -685,13 +684,13 @@ ad_service(struct ad_softc *adp, int change) ((struct ad_softc *) (adp->device->channel-> device[ATA_DEV(device)].driver))->outstanding > 0) { - ATA_OUTB(adp->device->channel->r_io, ATA_DRIVE, ATA_D_IBM | device); + ATA_IDX_OUTB(adp->device->channel, ATA_DRIVE, ATA_D_IBM | device); adp = adp->device->channel->device[ATA_DEV(device)].driver; DELAY(1); } } adp->device->channel->status = - ATA_INB(adp->device->channel->r_altio, ATA_ALTSTAT); + ATA_IDX_INB(adp->device->channel, ATA_ALTSTAT); /* do we have a SERVICE request from the drive ? */ if (adp->flags & AD_F_TAG_ENABLED && @@ -719,13 +718,13 @@ ad_service(struct ad_softc *adp, int change) /* setup the transfer environment when ready */ if (ata_wait(adp->device, ATA_S_READY)) { ata_prtdev(adp->device, "SERVICE timeout tag=%d s=%02x e=%02x\n", - ATA_INB(adp->device->channel->r_io, ATA_COUNT) >> 3, + ATA_IDX_INB(adp->device->channel, ATA_COUNT) >> 3, adp->device->channel->status, adp->device->channel->error); ad_invalidatequeue(adp, NULL); return ATA_OP_FINISHED; } - tag = ATA_INB(adp->device->channel->r_io, ATA_COUNT) >> 3; + tag = ATA_IDX_INB(adp->device->channel, ATA_COUNT) >> 3; if (!(request = adp->tags[tag])) { ata_prtdev(adp->device, "no request for tag=%d\n", tag); ad_invalidatequeue(adp, NULL); @@ -743,7 +742,7 @@ ad_service(struct ad_softc *adp, int change) ad_invalidatequeue(adp, NULL); return ATA_OP_FINISHED; } - adp->device->channel->dma->start(adp->device, request->data, request->bytecount, + adp->device->channel->dma->start(adp->device->channel, request->data, request->bytecount, request->flags & ADR_F_READ); return ATA_OP_CONTINUES; } @@ -831,7 +830,7 @@ ad_timeout(struct ad_request *request) request->tag, request->serv); if (request->flags & ADR_F_DMA_USED) { - adp->device->channel->dma->stop(adp->device); + adp->device->channel->dma->stop(adp->device->channel); ad_invalidatequeue(adp, request); if (request->retries == AD_MAX_RETRIES) { adp->device->setmode(adp->device, ATA_PIO_MAX); diff --git a/sys/dev/ata/ata-dma.c b/sys/dev/ata/ata-dma.c index 7f1353b..4f20398 100644 --- a/sys/dev/ata/ata-dma.c +++ b/sys/dev/ata/ata-dma.c @@ -43,16 +43,10 @@ /* prototypes */ static void ata_dmasetupc_cb(void *, bus_dma_segment_t *, int, int); -static int ata_dmaalloc(struct ata_device *); -static void ata_dmafree(struct ata_device *); -static void ata_dmacreate(struct ata_channel *); -static void ata_dmadestroy(struct ata_channel *); +static int ata_dmaalloc(struct ata_channel *); +static void ata_dmafree(struct ata_channel *); static void ata_dmasetupd_cb(void *, bus_dma_segment_t *, int, int); static int ata_dmasetup(struct ata_device *, caddr_t, int32_t); -/* -static int ata_dmastart(struct ata_device *, caddr_t, int32_t, int); -static int ata_dmastop(struct ata_device *); -*/ static int ata_dmastatus(struct ata_channel *); /* local vars */ @@ -72,10 +66,8 @@ int ata_dmainit(struct ata_channel *ch) { if (!(ch->dma = - malloc(sizeof(struct ata_dma_funcs), M_ATADMA, M_NOWAIT | M_ZERO))) + malloc(sizeof(struct ata_dma_data), M_ATADMA, M_NOWAIT | M_ZERO))) return ENOMEM; - ch->dma->create = ata_dmacreate; - ch->dma->destroy = ata_dmadestroy; ch->dma->alloc = ata_dmaalloc; ch->dma->free = ata_dmafree; ch->dma->setup = ata_dmasetup; @@ -97,99 +89,83 @@ ata_dmasetupc_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) } static int -ata_dmaalloc(struct ata_device *atadev) +ata_dmaalloc(struct ata_channel *ch) { - struct ata_channel *ch; struct ata_dc_cb_args ccba; - struct ata_dmastate *ds; int error; - ch = atadev->channel; - ds = &atadev->dmastate; - if (!ds->cdmatag) { - if ((error = bus_dma_tag_create(ch->dmatag, 1, PAGE_SIZE, + if (!ch->dma->dmatag) { + if (bus_dma_tag_create(NULL, 1, 0, + BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, + NULL, NULL, MAXCTLDMASZ, ATA_DMA_ENTRIES, + BUS_SPACE_MAXSIZE_32BIT, 0, &ch->dma->dmatag)) { + printf("DMA tag allocation failed, disabling DMA\n"); + } + } + if (!ch->dma->cdmatag) { + if ((error = bus_dma_tag_create(ch->dma->dmatag, 1, PAGE_SIZE, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MAXTABSZ, 1, MAXTABSZ, - BUS_DMA_ALLOCNOW, &ds->cdmatag))) + BUS_DMA_ALLOCNOW, &ch->dma->cdmatag))) return error; } - if (!ds->ddmatag) { - if ((error = bus_dma_tag_create(ch->dmatag, ch->dma->alignment, 0, + if (!ch->dma->ddmatag) { + if ((error = bus_dma_tag_create(ch->dma->dmatag, ch->dma->alignment, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MAXPHYS, ATA_DMA_ENTRIES, MAXSEGSZ, - BUS_DMA_ALLOCNOW, &ds->ddmatag))) + BUS_DMA_ALLOCNOW, &ch->dma->ddmatag))) return error; } - if (!ds->mdmatab) { - if ((error = bus_dmamem_alloc(ds->cdmatag, (void **)&ds->dmatab, 0, - &ds->cdmamap))) + if (!ch->dma->mdmatab) { + if ((error = bus_dmamem_alloc(ch->dma->cdmatag, + (void **)&ch->dma->dmatab, 0, + &ch->dma->cdmamap))) return error; - if ((error = bus_dmamap_load(ds->cdmatag, ds->cdmamap, ds->dmatab, - MAXTABSZ, ata_dmasetupc_cb, &ccba, - 0)) != 0 || ccba.error != 0) { - bus_dmamem_free(ds->cdmatag, ds->dmatab, ds->cdmamap); + if ((error = bus_dmamap_load(ch->dma->cdmatag, ch->dma->cdmamap, + ch->dma->dmatab, MAXTABSZ, + ata_dmasetupc_cb, &ccba, 0)) != 0 || + ccba.error != 0) { + bus_dmamem_free(ch->dma->cdmatag, ch->dma->dmatab,ch->dma->cdmamap); return error; } - ds->mdmatab = ccba.maddr; + ch->dma->mdmatab = ccba.maddr; } - if (!ds->ddmamap) { - if ((error = bus_dmamap_create(ds->ddmatag, 0, &ds->ddmamap)) != 0) + if (!ch->dma->ddmamap) { + if ((error = bus_dmamap_create(ch->dma->ddmatag, 0, + &ch->dma->ddmamap)) != 0) return error; } return 0; } static void -ata_dmafree(struct ata_device *atadev) +ata_dmafree(struct ata_channel *ch) { - struct ata_dmastate *ds; - - ds = &atadev->dmastate; - if (ds->mdmatab) { - bus_dmamap_unload(ds->cdmatag, ds->cdmamap); - bus_dmamem_free(ds->cdmatag, ds->dmatab, ds->cdmamap); - ds->mdmatab = 0; - ds->cdmamap = NULL; - ds->dmatab = NULL; + if (ch->dma->mdmatab) { + bus_dmamap_unload(ch->dma->cdmatag, ch->dma->cdmamap); + bus_dmamem_free(ch->dma->cdmatag, ch->dma->dmatab, ch->dma->cdmamap); + ch->dma->mdmatab = 0; + ch->dma->cdmamap = NULL; + ch->dma->dmatab = NULL; } - if (ds->ddmamap) { - bus_dmamap_destroy(ds->ddmatag, ds->ddmamap); - ds->ddmamap = NULL; + if (ch->dma->ddmamap) { + bus_dmamap_destroy(ch->dma->ddmatag, ch->dma->ddmamap); + ch->dma->ddmamap = NULL; } - if (ds->cdmatag) { - bus_dma_tag_destroy(ds->cdmatag); - ds->cdmatag = NULL; + if (ch->dma->cdmatag) { + bus_dma_tag_destroy(ch->dma->cdmatag); + ch->dma->cdmatag = NULL; } - if (ds->ddmatag) { - bus_dma_tag_destroy(ds->ddmatag); - ds->ddmatag = NULL; + if (ch->dma->ddmatag) { + bus_dma_tag_destroy(ch->dma->ddmatag); + ch->dma->ddmatag = NULL; } -} - -static void -ata_dmacreate(struct ata_channel *ch) -{ - - if (!ch->dmatag) { - if (bus_dma_tag_create(NULL, 1, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, - NULL, NULL, MAXCTLDMASZ, ATA_DMA_ENTRIES, - BUS_SPACE_MAXSIZE_32BIT, 0, &ch->dmatag)) { - printf("DMA tag allocation failed, disabling DMA\n"); - } - } -} - -static void -ata_dmadestroy(struct ata_channel *ch) -{ - - if (ch->dmatag) { - bus_dma_tag_destroy(ch->dmatag); - ch->dmatag = NULL; + if (ch->dma->dmatag) { + bus_dma_tag_destroy(ch->dma->dmatag); + ch->dma->dmatag = NULL; } } @@ -243,62 +219,42 @@ ata_dmasetup(struct ata_device *atadev, caddr_t data, int32_t count) return 0; } +static int +ata_dmastatus(struct ata_channel *ch) +{ + return ch->dma->flags & ATA_DMA_ACTIVE; +} + int -ata_dmastart(struct ata_device *atadev, caddr_t data, int32_t count, int dir) +ata_dmastart(struct ata_channel *ch, caddr_t data, int32_t count, int dir) { - struct ata_channel *ch = atadev->channel; - struct ata_dmastate *ds = &atadev->dmastate; struct ata_dmasetup_data_cb_args cba; - if (ds->flags & ATA_DS_ACTIVE) + if (ch->dma->flags & ATA_DMA_ACTIVE) panic("ata_dmasetup: transfer active on this device!"); - cba.dmatab = ds->dmatab; - bus_dmamap_sync(ds->cdmatag, ds->cdmamap, BUS_DMASYNC_PREWRITE); - if (bus_dmamap_load(ds->ddmatag, ds->ddmamap, data, count, + cba.dmatab = ch->dma->dmatab; + bus_dmamap_sync(ch->dma->cdmatag, ch->dma->cdmamap, BUS_DMASYNC_PREWRITE); + + if (bus_dmamap_load(ch->dma->ddmatag, ch->dma->ddmamap, data, count, ata_dmasetupd_cb, &cba, 0) || cba.error) return -1; - bus_dmamap_sync(ds->cdmatag, ds->cdmamap, BUS_DMASYNC_POSTWRITE); - bus_dmamap_sync(ds->ddmatag, ds->ddmamap, dir ? BUS_DMASYNC_PREREAD : - BUS_DMASYNC_PREWRITE); + bus_dmamap_sync(ch->dma->cdmatag, ch->dma->cdmamap, BUS_DMASYNC_POSTWRITE); + bus_dmamap_sync(ch->dma->ddmatag, ch->dma->ddmamap, + dir ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); - ch->flags |= ATA_DMA_ACTIVE; - ds->flags = dir ? (ATA_DS_ACTIVE | ATA_DS_READ) : ATA_DS_ACTIVE; - - ATA_OUTL(ch->r_bmio, ATA_BMDTP_PORT, ds->mdmatab); - ATA_OUTB(ch->r_bmio, ATA_BMCMD_PORT, dir ? ATA_BMCMD_WRITE_READ : 0); - ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, - (ATA_INB(ch->r_bmio, ATA_BMSTAT_PORT) | - (ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR))); - ATA_OUTB(ch->r_bmio, ATA_BMCMD_PORT, - ATA_INB(ch->r_bmio, ATA_BMCMD_PORT) | ATA_BMCMD_START_STOP); + ch->dma->flags = dir ? (ATA_DMA_ACTIVE | ATA_DMA_READ) : ATA_DMA_ACTIVE; return 0; } int -ata_dmastop(struct ata_device *atadev) +ata_dmastop(struct ata_channel *ch) { - struct ata_channel *ch = atadev->channel; - struct ata_dmastate *ds = &atadev->dmastate; - int error; - - error = ATA_INB(ch->r_bmio, ATA_BMSTAT_PORT); - ATA_OUTB(ch->r_bmio, ATA_BMCMD_PORT, - ATA_INB(ch->r_bmio, ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP); - ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT,ATA_BMSTAT_INTERRUPT|ATA_BMSTAT_ERROR); - - bus_dmamap_sync(ds->ddmatag, ds->ddmamap, (ds->flags & ATA_DS_READ) != 0 ? + bus_dmamap_sync(ch->dma->ddmatag, ch->dma->ddmamap, + (ch->dma->flags & ATA_DMA_READ) != 0 ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(ds->ddmatag, ds->ddmamap); - - ch->flags &= ~ATA_DMA_ACTIVE; - ds->flags = 0; - return (error & ATA_BMSTAT_MASK); -} - -static int -ata_dmastatus(struct ata_channel *ch) -{ - return ATA_INB(ch->r_bmio, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK; + bus_dmamap_unload(ch->dma->ddmatag, ch->dma->ddmamap); + ch->dma->flags = 0; + return 0; } diff --git a/sys/dev/ata/ata-isa.c b/sys/dev/ata/ata-isa.c index fba5b73..0f4688a 100644 --- a/sys/dev/ata/ata-isa.c +++ b/sys/dev/ata/ata-isa.c @@ -70,9 +70,9 @@ static int ata_isa_probe(device_t dev) { struct ata_channel *ch = device_get_softc(dev); - struct resource *io; + struct resource *io = NULL, *altio = NULL; u_long tmp; - int rid; + int i, rid; /* check isapnp ids */ if (ISA_PNP_PROBE(device_get_parent(dev), dev, ata_ids) == ENXIO) @@ -83,7 +83,7 @@ ata_isa_probe(device_t dev) io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, ATA_IOSIZE, RF_ACTIVE); if (!io) - return ENOMEM; + return ENXIO; /* set the altport range */ if (bus_get_resource(dev, SYS_RES_IOPORT, ATA_ALTADDR_RID, &tmp, &tmp)) { @@ -91,7 +91,24 @@ ata_isa_probe(device_t dev) rman_get_start(io) + ATA_ALTOFFSET, ATA_ALTIOSIZE); } - bus_release_resource(dev, SYS_RES_IOPORT, rid, io); + /* allocate the altport range */ + rid = ATA_ALTADDR_RID; + altio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, + ATA_ALTIOSIZE, RF_ACTIVE); + if (!altio) { + bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, io); + return ENXIO; + } + + /* setup the resource vectors */ + for (i = ATA_DATA; i <= ATA_STATUS; i++) { + ch->r_io[i].res = io; + ch->r_io[i].offset = i; + } + ch->r_io[ATA_ALTSTAT].res = altio; + ch->r_io[ATA_ALTSTAT].offset = 0; + + /* initialize softc for this channel */ ch->unit = 0; ch->flags |= ATA_USE_16BIT; ch->locking = ata_isa_lock; diff --git a/sys/dev/ata/ata-pci.c b/sys/dev/ata/ata-pci.c index 01f2527..d2864cb 100644 --- a/sys/dev/ata/ata-pci.c +++ b/sys/dev/ata/ata-pci.c @@ -54,7 +54,8 @@ static MALLOC_DEFINE(M_ATAPCI, "ATA PCI", "ATA driver PCI"); #define IOMASK 0xfffffffc /* prototypes */ -static int ata_pci_add_child(device_t, int); +static int ata_pci_allocate(device_t, struct ata_channel *); +static int ata_pci_dmainit(struct ata_channel *); static void ata_pci_locknoop(struct ata_channel *, int); static int @@ -93,6 +94,7 @@ ata_pci_probe(device_t dev) case 0x16ca: if (pci_get_devid(dev) == 0x000116ca) { + ata_generic_ident(dev); device_set_desc(dev, "Cenatek Rocket Drive controller"); return 0; } @@ -100,6 +102,7 @@ ata_pci_probe(device_t dev) case 0x1042: if (pci_get_devid(dev)==0x10001042 || pci_get_devid(dev)==0x10011042) { + ata_generic_ident(dev); device_set_desc(dev, "RZ 100? ATA controller !WARNING! buggy HW data loss possible"); return 0; @@ -118,10 +121,10 @@ ata_pci_probe(device_t dev) static int ata_pci_attach(device_t dev) { - struct ata_pci_controller *controller = device_get_softc(dev); + struct ata_pci_controller *ctlr = device_get_softc(dev); u_int8_t class, subclass; u_int32_t type, cmd; - int rid; + int unit; /* set up vendor-specific stuff */ type = pci_get_devid(dev); @@ -134,61 +137,43 @@ ata_pci_attach(device_t dev) return 0; } + /* do chipset specific setups only needed once */ + if (ATA_MASTERDEV(dev) || pci_read_config(dev, 0x18, 4) & IOMASK) + ctlr->channels = 2; + else + ctlr->channels = 1; + ctlr->allocate = ata_pci_allocate; + ctlr->dmainit = ata_pci_dmainit; + ctlr->locking = ata_pci_locknoop; + ctlr->chipinit(dev); + #ifdef __sparc64__ if (!(cmd & PCIM_CMD_BUSMASTEREN)) { pci_write_config(dev, PCIR_COMMAND, cmd | PCIM_CMD_BUSMASTEREN, 2); cmd = pci_read_config(dev, PCIR_COMMAND, 2); } #endif - /* is busmastering supported ? */ - if ((cmd & (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN)) == - (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN)) { - - /* is there a valid port range to connect to ? */ - rid = 0x20; - controller->r_bmio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, - 0, ~0, 1, RF_ACTIVE); - if (!controller->r_bmio) - device_printf(dev, "Busmastering DMA not configured\n"); + /* is busmastering supported and configured ? */ + if ((cmd & PCIM_CMD_BUSMASTEREN) == PCIM_CMD_BUSMASTEREN) { + int rid = ATA_BMADDR_RID; + + if (!ctlr->r_mem) { + if (!(ctlr->r_bmio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, + 0, ~0, 1, RF_ACTIVE))) + device_printf(dev, "Busmastering DMA not configured\n"); + } } else device_printf(dev, "Busmastering DMA not supported\n"); - /* do chipset specific setups only needed once */ - controller->dmainit = ata_dmainit; - controller->locking = ata_pci_locknoop; - controller->chipinit(dev); - - if (controller->r_bmio) { - controller->bmaddr = rman_get_start(controller->r_bmio); - BUS_RELEASE_RESOURCE(device_get_parent(dev), dev, - SYS_RES_IOPORT, rid, controller->r_bmio); - controller->r_bmio = NULL; - } - - ata_pci_add_child(dev, 0); - - if (ATA_MASTERDEV(dev) || pci_read_config(dev, 0x18, 4) & IOMASK) - ata_pci_add_child(dev, 1); + /* attach all channels on this controller */ + for (unit = 0; unit < ctlr->channels; unit++) + device_add_child(dev, "ata", ATA_MASTERDEV(dev) ? + unit : devclass_find_free_unit(ata_devclass, 2)); return bus_generic_attach(dev); } -static int -ata_pci_add_child(device_t dev, int unit) -{ - /* check if this is located at one of the std addresses */ - if (ATA_MASTERDEV(dev)) { - if (!device_add_child(dev, "ata", unit)) - return ENOMEM; - } - else { - if (!device_add_child(dev, "ata", - devclass_find_free_unit(ata_devclass, 2))) - return ENOMEM; - } - return 0; -} static int ata_pci_print_child(device_t dev, device_t child) @@ -197,7 +182,7 @@ ata_pci_print_child(device_t dev, device_t child) int retval = 0; retval += bus_print_child_header(dev, child); - retval += printf(": at 0x%lx", rman_get_start(ch->r_io)); + retval += printf(": at 0x%lx", rman_get_start(ch->r_io[0].res)); if (ATA_MASTERDEV(dev)) retval += printf(" irq %d", 14 + ch->unit); @@ -263,18 +248,6 @@ ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid, } } break; - - case ATA_BMADDR_RID: - if (controller->bmaddr) { - myrid = 0x20; - start = (unit == 0 ? - controller->bmaddr : controller->bmaddr+ATA_BMIOSIZE); - end = start + ATA_BMIOSIZE - 1; - count = ATA_BMIOSIZE; - res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child, - SYS_RES_IOPORT, &myrid, - start, end, count, flags); - } } return res; } @@ -322,10 +295,6 @@ ata_pci_release_resource(device_t dev, device_t child, int type, int rid, return BUS_RELEASE_RESOURCE(device_get_parent(dev), dev, SYS_RES_IOPORT, 0x14 + 8 * unit, r); break; - - case ATA_BMADDR_RID: - return BUS_RELEASE_RESOURCE(device_get_parent(dev), child, - SYS_RES_IOPORT, 0x20, r); default: return ENOENT; } @@ -393,17 +362,115 @@ ata_pci_teardown_intr(device_t dev, device_t child, struct resource *irq, return 0; } } + +static int +ata_pci_allocate(device_t dev, struct ata_channel *ch) +{ + struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); + struct resource *io = NULL, *altio = NULL; + int i, rid; + + rid = ATA_IOADDR_RID; + io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, + 0, ~0, ATA_IOSIZE, RF_ACTIVE); + if (!io) + return ENXIO; + + rid = ATA_ALTADDR_RID; + altio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, + 0, ~0, ATA_ALTIOSIZE, RF_ACTIVE); + if (!altio) { + bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, io); + return ENXIO; + } + + for (i = ATA_DATA; i <= ATA_STATUS; i ++) { + ch->r_io[i].res = io; + ch->r_io[i].offset = i; + } + ch->r_io[ATA_ALTSTAT].res = altio; + ch->r_io[ATA_ALTSTAT].offset = 0; + + if (ctlr->r_bmio) { + for (i = ATA_BMCMD_PORT; i <= ATA_BMDTP_PORT; i++) { + ch->r_io[i].res = ctlr->r_bmio; + ch->r_io[i].offset = (i - ATA_BMCMD_PORT)+(ch->unit * ATA_BMIOSIZE); + } + + /* if simplex controller, only allow DMA on primary channel */ + ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & + (ATA_BMSTAT_DMA_MASTER | ATA_BMSTAT_DMA_SLAVE)); + if (ch->unit > 0 && + (ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_DMA_SIMPLEX)) + device_printf(dev, "simplex device, DMA on primary only\n"); + else + ctlr->dmainit(ch); + } + return 0; +} + +static int +ata_pci_dmastart(struct ata_channel *ch, caddr_t data, int32_t count, int dir) +{ + int error; + + if ((error = ata_dmastart(ch, data, count, dir))) + return error; + + ATA_IDX_OUTL(ch, ATA_BMDTP_PORT, ch->dma->mdmatab); + ATA_IDX_OUTB(ch, ATA_BMCMD_PORT, dir ? ATA_BMCMD_WRITE_READ : 0); + ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, (ATA_IDX_INB(ch, ATA_BMSTAT_PORT) | + (ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR))); + ATA_IDX_OUTB(ch, ATA_BMCMD_PORT, + ATA_IDX_INB(ch, ATA_BMCMD_PORT) | ATA_BMCMD_START_STOP); + return 0; +} + +static int +ata_pci_dmastop(struct ata_channel *ch) +{ + int error; + + error = ATA_IDX_INB(ch, ATA_BMSTAT_PORT); + ATA_IDX_OUTB(ch, ATA_BMCMD_PORT, + ATA_IDX_INB(ch, ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP); + ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR); + + ata_dmastop(ch); + + return (error & ATA_BMSTAT_MASK); +} + +static int +ata_pci_dmastatus(struct ata_channel *ch) +{ + return ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK; +} + +static int +ata_pci_dmainit(struct ata_channel *ch) +{ + int error; + + if ((error = ata_dmainit(ch))) + return error; + + ch->dma->start = ata_pci_dmastart; + ch->dma->stop = ata_pci_dmastop; + ch->dma->status = ata_pci_dmastatus; + return 0; +} static void ata_pci_locknoop(struct ata_channel *ch, int flags) { } - static device_method_t ata_pci_methods[] = { /* device interface */ DEVMETHOD(device_probe, ata_pci_probe), DEVMETHOD(device_attach, ata_pci_attach), + DEVMETHOD(device_detach, ata_pci_attach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD(device_suspend, bus_generic_suspend), DEVMETHOD(device_resume, bus_generic_resume), @@ -445,24 +512,14 @@ ata_pcisub_probe(device_t dev) } free(children, M_TEMP); + if ((error = ctlr->allocate(dev, ch))) + return error; + ch->device[MASTER].setmode = ctlr->setmode; ch->device[SLAVE].setmode = ctlr->setmode; ch->locking = ctlr->locking; - ch->chiptype = pci_get_devid(device_get_parent(dev)); - - if (!(error = ata_probe(dev)) && ch->r_bmio) { - /* if simplex controller, only allow DMA on primary channel */ - ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, - ATA_INB(ch->r_bmio, ATA_BMSTAT_PORT) & - (ATA_BMSTAT_DMA_MASTER | ATA_BMSTAT_DMA_SLAVE)); - if (ch->unit == 1 && ATA_INB(ch->r_bmio, ATA_BMSTAT_PORT) & - ATA_BMSTAT_DMA_SIMPLEX) { - ata_printf(ch, -1, "simplex device, DMA on primary only\n"); - return error; - } - error = ctlr->dmainit(ch); - } - return error; + ch->chiptype = ctlr->chip->chipid; + return ata_probe(dev); } static device_method_t ata_pcisub_methods[] = { diff --git a/sys/dev/ata/ata-pci.h b/sys/dev/ata/ata-pci.h index 7d6205b..3fcf3f1 100644 --- a/sys/dev/ata/ata-pci.h +++ b/sys/dev/ata/ata-pci.h @@ -30,30 +30,32 @@ /* structure holding chipset config info */ struct ata_chip_id { - u_int32_t chiptype; - u_int8_t chiprev; - int cfg1; - int cfg2; - u_int8_t max_dma; - char *text; + u_int32_t chipid; + u_int8_t chiprev; + int cfg1; + int cfg2; + u_int8_t max_dma; + char *text; }; /* structure describing a PCI ATA controller */ struct ata_pci_controller { struct resource *r_bmio; - int bmaddr; + struct resource *r_mem; struct resource *r_irq; void *handle; struct ata_chip_id *chip; int (*chipinit)(device_t); + int (*allocate)(device_t, struct ata_channel *); int (*dmainit)(struct ata_channel *); void (*setmode)(struct ata_device *, int); void (*locking)(struct ata_channel *, int); int locked_ch; + int channels; struct { void (*function)(void *); void *argument; - } interrupt[2]; + } interrupt[4]; /* XXX SOS max ch# for now */ }; #define ATA_MASTERDEV(dev) ((pci_get_progif(dev) & 0x80) && \ @@ -214,7 +216,7 @@ struct ata_pci_controller { #define PROLD 0 #define PRNEW 1 #define PRTX 2 -#define PRCH 3 +#define PRMEM 3 #define PRTX4 0x01 #define PRSX6K 0x02 @@ -246,8 +248,8 @@ struct ata_pci_controller { /* global prototypes */ int ata_dmainit(struct ata_channel *); -int ata_dmastart(struct ata_device *, caddr_t, int32_t, int); -int ata_dmastop(struct ata_device *); +int ata_dmastart(struct ata_channel *, caddr_t, int32_t, int); +int ata_dmastop(struct ata_channel *); int ata_generic_ident(device_t); int ata_acard_ident(device_t); diff --git a/sys/dev/ata/atapi-all.c b/sys/dev/ata/atapi-all.c index fd5e237..1b27ca4 100644 --- a/sys/dev/ata/atapi-all.c +++ b/sys/dev/ata/atapi-all.c @@ -148,8 +148,6 @@ atapi_detach(struct ata_device *atadev) } free(request, M_ATAPI); } - if (atadev->channel->dma) - atadev->channel->dma->free(atadev); free(atadev->result, M_ATAPI); atadev->driver = NULL; atadev->flags = 0; @@ -180,10 +178,8 @@ atapi_queue_cmd(struct ata_device *atadev, int8_t *ccb, caddr_t data, request->callback = callback; request->driver = driver; } - if (atadev->mode >= ATA_DMA) { - if (atadev->channel->dma->alloc(atadev)) + if (atadev->mode >= ATA_DMA && !atadev->channel->dma) atadev->mode = ATA_PIO; - } #ifdef ATAPI_DEBUG ata_prtdev(atadev, "queueing %s ", atapi_cmd2str(request->ccb[0])); @@ -251,9 +247,9 @@ atapi_transfer(struct atapi_request *request) #endif /* is this just a POLL DSC command ? */ if (request->ccb[0] == ATAPI_POLL_DSC) { - ATA_OUTB(atadev->channel->r_io, ATA_DRIVE, ATA_D_IBM | atadev->unit); + ATA_IDX_OUTB(atadev->channel, ATA_DRIVE, ATA_D_IBM | atadev->unit); DELAY(10); - if (ATA_INB(atadev->channel->r_altio, ATA_ALTSTAT) & ATA_S_DSC) + if (ATA_IDX_INB(atadev->channel, ATA_ALTSTAT) & ATA_S_DSC) request->error = 0; else request->error = EBUSY; @@ -289,7 +285,7 @@ atapi_transfer(struct atapi_request *request) ata_prtdev(atadev, "failure to send ATAPI packet command\n"); if (request->flags & ATPR_F_DMA_USED) - atadev->channel->dma->start(atadev, request->data, request->bytecount, + atadev->channel->dma->start(atadev->channel, request->data, request->bytecount, request->flags & ATPR_F_READ); /* command interrupt device ? just return */ @@ -299,8 +295,8 @@ atapi_transfer(struct atapi_request *request) /* ready to write ATAPI command */ timout = 5000; /* might be less for fast devices */ while (timout--) { - reason = ATA_INB(atadev->channel->r_io, ATA_IREASON); - atadev->channel->status = ATA_INB(atadev->channel->r_io, ATA_STATUS); + reason = ATA_IDX_INB(atadev->channel, ATA_IREASON); + atadev->channel->status = ATA_IDX_INB(atadev->channel, ATA_STATUS); if (((reason & (ATA_I_CMD | ATA_I_IN)) | (atadev->channel->status&(ATA_S_DRQ|ATA_S_BUSY)))==ATAPI_P_CMDOUT) break; @@ -318,7 +314,7 @@ atapi_transfer(struct atapi_request *request) DELAY(10); /* send actual command */ - ATA_OUTSW_STRM(atadev->channel->r_io, ATA_DATA, (int16_t *)request->ccb, + ATA_IDX_OUTSW_STRM(atadev->channel, ATA_DATA, (int16_t *)request->ccb, request->ccbsize / sizeof(int16_t)); return ATA_OP_CONTINUES; } @@ -329,7 +325,7 @@ atapi_interrupt(struct atapi_request *request) struct ata_device *atadev = request->device; int reason, dma_stat = 0; - reason = (ATA_INB(atadev->channel->r_io, ATA_IREASON)&(ATA_I_CMD|ATA_I_IN))| + reason = (ATA_IDX_INB(atadev->channel, ATA_IREASON) & (ATA_I_CMD | ATA_I_IN)) | (atadev->channel->status & ATA_S_DRQ); if (reason == ATAPI_P_CMDOUT) { @@ -341,16 +337,16 @@ atapi_interrupt(struct atapi_request *request) atapi_finish(request); return ATA_OP_FINISHED; } - ATA_OUTSW_STRM(atadev->channel->r_io, ATA_DATA, (int16_t *)request->ccb, + ATA_IDX_OUTSW_STRM(atadev->channel, ATA_DATA, (int16_t *)request->ccb, request->ccbsize / sizeof(int16_t)); return ATA_OP_CONTINUES; } if (request->flags & ATPR_F_DMA_USED) { - dma_stat = atadev->channel->dma->stop(atadev); + dma_stat = atadev->channel->dma->stop(atadev->channel); if ((atadev->channel->status & (ATA_S_ERROR | ATA_S_DWF)) || dma_stat & ATA_BMSTAT_ERROR) { - request->result = ATA_INB(atadev->channel->r_io, ATA_ERROR); + request->result = ATA_IDX_INB(atadev->channel, ATA_ERROR); } else { request->result = 0; @@ -359,13 +355,13 @@ atapi_interrupt(struct atapi_request *request) } } else { - int length = ATA_INB(atadev->channel->r_io, ATA_CYL_LSB) | - ATA_INB(atadev->channel->r_io, ATA_CYL_MSB) << 8; + int length = ATA_IDX_INB(atadev->channel, ATA_CYL_LSB) | + ATA_IDX_INB(atadev->channel, ATA_CYL_MSB) << 8; switch (reason) { case ATAPI_P_WRITE: if (request->flags & ATPR_F_READ) { - request->result = ATA_INB(atadev->channel->r_io, ATA_ERROR); + request->result = ATA_IDX_INB(atadev->channel, ATA_ERROR); ata_prtdev(atadev, "%s trying to write on read buffer\n", atapi_cmd2str(atadev->cmd)); break; @@ -375,7 +371,7 @@ atapi_interrupt(struct atapi_request *request) case ATAPI_P_READ: if (!(request->flags & ATPR_F_READ)) { - request->result = ATA_INB(atadev->channel->r_io, ATA_ERROR); + request->result = ATA_IDX_INB(atadev->channel, ATA_ERROR); ata_prtdev(atadev, "%s trying to read on write buffer\n", atapi_cmd2str(atadev->cmd)); break; @@ -394,7 +390,7 @@ atapi_interrupt(struct atapi_request *request) case ATAPI_P_ABORT: case ATAPI_P_DONE: if (atadev->channel->status & (ATA_S_ERROR | ATA_S_DWF)) - request->result = ATA_INB(atadev->channel->r_io, ATA_ERROR); + request->result = ATA_IDX_INB(atadev->channel, ATA_ERROR); else if (!(request->flags & ATPR_F_INTERNAL)) request->result = 0; @@ -521,17 +517,17 @@ atapi_read(struct atapi_request *request, int length) *buffer = (int8_t *)&request->sense; if (ch->flags & ATA_USE_16BIT || (size % sizeof(int32_t))) - ATA_INSW_STRM(ch->r_io, ATA_DATA, (void *)((uintptr_t)*buffer), + ATA_IDX_INSW_STRM(ch, ATA_DATA, (void *)((uintptr_t)*buffer), size / sizeof(int16_t)); else - ATA_INSL_STRM(ch->r_io, ATA_DATA, (void *)((uintptr_t)*buffer), + ATA_IDX_INSL_STRM(ch, ATA_DATA, (void *)((uintptr_t)*buffer), size / sizeof(int32_t)); if (request->bytecount < length) { ata_prtdev(request->device, "read data overrun %d/%d\n", length, request->bytecount); for (resid=request->bytecount; resid<length; resid+=sizeof(int16_t)) - ATA_INW(ch->r_io, ATA_DATA); + ATA_IDX_INW(ch, ATA_DATA); } *buffer += size; request->bytecount -= size; @@ -550,17 +546,17 @@ atapi_write(struct atapi_request *request, int length) *buffer = (int8_t *)&request->sense; if (ch->flags & ATA_USE_16BIT || (size % sizeof(int32_t))) - ATA_OUTSW_STRM(ch->r_io, ATA_DATA, (void *)((uintptr_t)*buffer), + ATA_IDX_OUTSW_STRM(ch, ATA_DATA, (void *)((uintptr_t)*buffer), size / sizeof(int16_t)); else - ATA_OUTSL_STRM(ch->r_io, ATA_DATA, (void *)((uintptr_t)*buffer), + ATA_IDX_OUTSL_STRM(ch, ATA_DATA, (void *)((uintptr_t)*buffer), size / sizeof(int32_t)); if (request->bytecount < length) { ata_prtdev(request->device, "write data underrun %d/%d\n", length, request->bytecount); for (resid=request->bytecount; resid<length; resid+=sizeof(int16_t)) - ATA_OUTW(ch->r_io, ATA_DATA, 0); + ATA_IDX_OUTW(ch, ATA_DATA, 0); } *buffer += size; request->bytecount -= size; @@ -593,7 +589,7 @@ atapi_timeout(struct atapi_request *request) atapi_cmd2str(request->ccb[0])); if (request->flags & ATPR_F_DMA_USED) { - atadev->channel->dma->stop(atadev); + atadev->channel->dma->stop(atadev->channel); if (request->retries == ATAPI_MAX_RETRIES) { atadev->setmode(atadev, ATA_PIO_MAX); ata_prtdev(atadev, "trying fallback to PIO mode\n"); |