summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorsos <sos@FreeBSD.org>2003-03-29 13:37:09 +0000
committersos <sos@FreeBSD.org>2003-03-29 13:37:09 +0000
commit1aa8f29ccf0eb6c6db95c1257318186a901b5ef9 (patch)
treebb9ce90b8fcfe8e400644fa3aceb2bcd039d7993 /sys
parentededebc1a4663fdc2452865586200d45a8fef1fe (diff)
downloadFreeBSD-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')
-rw-r--r--sys/dev/ata/ata-all.c249
-rw-r--r--sys/dev/ata/ata-all.h102
-rw-r--r--sys/dev/ata/ata-card.c49
-rw-r--r--sys/dev/ata/ata-cbus.c67
-rw-r--r--sys/dev/ata/ata-chipset.c147
-rw-r--r--sys/dev/ata/ata-disk.c39
-rw-r--r--sys/dev/ata/ata-dma.c188
-rw-r--r--sys/dev/ata/ata-isa.c25
-rw-r--r--sys/dev/ata/ata-pci.c211
-rw-r--r--sys/dev/ata/ata-pci.h24
-rw-r--r--sys/dev/ata/atapi-all.c50
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");
OpenPOWER on IntegriCloud