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
This commit is contained in:
Søren Schmidt 2003-03-29 13:37:09 +00:00
parent 50e960d918
commit 566cf07a7c
11 changed files with 614 additions and 537 deletions

View File

@ -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);

View File

@ -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)

View File

@ -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),

View File

@ -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);
}

View File

@ -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:

View File

@ -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);

View File

@ -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;
}
int
ata_dmastart(struct ata_device *atadev, caddr_t data, int32_t count, int dir)
static int
ata_dmastatus(struct ata_channel *ch)
{
return ch->dma->flags & ATA_DMA_ACTIVE;
}
int
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;
}

View File

@ -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;

View File

@ -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 busmastering supported and configured ? */
if ((cmd & PCIM_CMD_BUSMASTEREN) == PCIM_CMD_BUSMASTEREN) {
int rid = ATA_BMADDR_RID;
/* 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");
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[] = {

View File

@ -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);

View File

@ -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");