summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/conf/files1
-rw-r--r--sys/dev/ata/ata-all.c198
-rw-r--r--sys/dev/ata/ata-all.h55
-rw-r--r--sys/dev/ata/ata-card.c11
-rw-r--r--sys/dev/ata/ata-cbus.c109
-rw-r--r--sys/dev/ata/ata-chipset.c1887
-rw-r--r--sys/dev/ata/ata-disk.c58
-rw-r--r--sys/dev/ata/ata-disk.h2
-rw-r--r--sys/dev/ata/ata-dma.c1616
-rw-r--r--sys/dev/ata/ata-isa.c13
-rw-r--r--sys/dev/ata/ata-pci.c748
-rw-r--r--sys/dev/ata/ata-pci.h262
-rw-r--r--sys/dev/ata/ata-raid.c30
-rw-r--r--sys/dev/ata/ata-raid.h2
-rw-r--r--sys/dev/ata/atapi-all.c46
-rw-r--r--sys/dev/ata/atapi-all.h2
-rw-r--r--sys/dev/ata/atapi-cd.c8
-rw-r--r--sys/dev/ata/atapi-cd.h4
-rw-r--r--sys/dev/ata/atapi-fd.c4
-rw-r--r--sys/dev/ata/atapi-fd.h2
-rw-r--r--sys/dev/ata/atapi-tape.c2
-rw-r--r--sys/dev/ata/atapi-tape.h2
22 files changed, 2606 insertions, 2456 deletions
diff --git a/sys/conf/files b/sys/conf/files
index a67a535..9f739db 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -300,6 +300,7 @@ dev/ata/ata-cbus.c optional ata pc98
dev/ata/ata-card.c optional ata card
dev/ata/ata-card.c optional ata pccard
dev/ata/ata-pci.c optional ata pci
+dev/ata/ata-chipset.c optional ata pci
dev/ata/ata-dma.c optional ata pci
dev/ata/ata-disk.c optional atadisk
dev/ata/ata-raid.c optional atadisk
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c
index 9fb6aa5..183bdb2 100644
--- a/sys/dev/ata/ata-all.c
+++ b/sys/dev/ata/ata-all.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -135,9 +135,9 @@ ata_probe(device_t dev)
(int)rman_get_start(ch->r_altio),
(ch->r_bmio) ? (int)rman_get_start(ch->r_bmio) : 0);
- ch->lock_func(ch, ATA_LF_LOCK);
+ ch->locking(ch, ATA_LF_LOCK);
ata_reset(ch);
- ch->lock_func(ch, ATA_LF_UNLOCK);
+ ch->locking(ch, ATA_LF_UNLOCK);
ch->device[MASTER].channel = ch;
ch->device[MASTER].unit = ATA_MASTER;
@@ -183,13 +183,16 @@ ata_attach(device_t dev)
return error;
}
+ if (ch->dma)
+ ch->dma->create(ch);
+
/*
* do not attach devices if we are in early boot, this is done later
* when interrupts are enabled by a hook into the boot process.
* otherwise attach what the probe has found in ch->devices.
*/
if (!ata_delayed_attach) {
- ch->lock_func(ch, ATA_LF_LOCK);
+ ch->locking(ch, ATA_LF_LOCK);
if (ch->devices & ATA_ATA_SLAVE)
if (ata_getparam(&ch->device[SLAVE], ATA_C_ATA_IDENTIFY))
ch->devices &= ~ATA_ATA_SLAVE;
@@ -217,7 +220,7 @@ ata_attach(device_t dev)
#ifdef DEV_ATAPICAM
atapi_cam_attach_bus(ch);
#endif
- ch->lock_func(ch, ATA_LF_UNLOCK);
+ ch->locking(ch, ATA_LF_UNLOCK);
}
return 0;
}
@@ -233,7 +236,7 @@ ata_detach(device_t dev)
return ENXIO;
/* make sure channel is not busy */
- ch->lock_func(ch, ATA_LF_LOCK);
+ ch->locking(ch, ATA_LF_LOCK);
ATA_SLEEPLOCK_CH(ch, ATA_CONTROL);
s = splbio();
@@ -267,7 +270,8 @@ ata_detach(device_t dev)
ch->device[MASTER].mode = ATA_PIO;
ch->device[SLAVE].mode = ATA_PIO;
ch->devices = 0;
- ata_dmafreetags(ch);
+ if (ch->dma)
+ ch->dma->destroy(ch);
bus_teardown_intr(dev, ch->r_irq, ch->ih);
bus_release_resource(dev, SYS_RES_IRQ, ATA_IRQ_RID, ch->r_irq);
@@ -280,7 +284,7 @@ ata_detach(device_t dev)
ch->r_bmio = NULL;
ch->r_irq = NULL;
ATA_UNLOCK_CH(ch);
- ch->lock_func(ch, ATA_LF_UNLOCK);
+ ch->locking(ch, ATA_LF_UNLOCK);
return 0;
}
@@ -293,9 +297,9 @@ ata_resume(device_t dev)
if (!dev || !(ch = device_get_softc(dev)))
return ENXIO;
- ch->lock_func(ch, ATA_LF_LOCK);
+ ch->locking(ch, ATA_LF_LOCK);
error = ata_reinit(ch);
- ch->lock_func(ch, ATA_LF_UNLOCK);
+ ch->locking(ch, ATA_LF_UNLOCK);
return error;
}
@@ -329,10 +333,10 @@ ataioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct thread *td)
case ATAREINIT:
if (!device || !(ch = device_get_softc(device)))
return ENXIO;
- ch->lock_func(ch, ATA_LF_LOCK);
+ ch->locking(ch, ATA_LF_LOCK);
ATA_SLEEPLOCK_CH(ch, ATA_ACTIVE);
error = ata_reinit(ch);
- ch->lock_func(ch, ATA_LF_UNLOCK);
+ ch->locking(ch, ATA_LF_UNLOCK);
return error;
case ATAGMODE:
@@ -356,7 +360,7 @@ ataioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct thread *td)
if (!device || !(ch = device_get_softc(device)))
return ENXIO;
- ch->lock_func(ch, ATA_LF_LOCK);
+ ch->locking(ch, ATA_LF_LOCK);
if ((iocmd->device == MASTER || iocmd->device == -1) &&
iocmd->u.mode.mode[MASTER] >= 0 && ch->device[MASTER].param) {
ata_change_mode(&ch->device[MASTER],iocmd->u.mode.mode[MASTER]);
@@ -372,7 +376,7 @@ ataioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct thread *td)
}
else
iocmd->u.mode.mode[SLAVE] = -1;
- ch->lock_func(ch, ATA_LF_UNLOCK);
+ ch->locking(ch, ATA_LF_UNLOCK);
return 0;
case ATAGPARM:
@@ -446,8 +450,10 @@ ataioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct thread *td)
if (iocmd->u.atapi.flags & ATAPI_CMD_WRITE) {
error = copyin(iocmd->u.atapi.data, buf, iocmd->u.atapi.count);
- if (error)
+ if (error) {
+ free(buf, M_ATA);
return error;
+ }
}
error = atapi_queue_cmd(atadev, iocmd->u.atapi.ccb,
buf, iocmd->u.atapi.count,
@@ -535,7 +541,7 @@ ata_boot_attach(void)
for (ctlr=0; ctlr<devclass_get_maxunit(ata_devclass); ctlr++) {
if (!(ch = devclass_get_softc(ata_devclass, ctlr)))
continue;
- ch->lock_func(ch, ATA_LF_LOCK);
+ ch->locking(ch, ATA_LF_LOCK);
if (ch->devices & ATA_ATA_SLAVE)
if (ata_getparam(&ch->device[SLAVE], ATA_C_ATA_IDENTIFY))
ch->devices &= ~ATA_ATA_SLAVE;
@@ -548,26 +554,26 @@ ata_boot_attach(void)
if (ch->devices & ATA_ATAPI_MASTER)
if (ata_getparam(&ch->device[MASTER], ATA_C_ATAPI_IDENTIFY))
ch->devices &= ~ATA_ATAPI_MASTER;
- ch->lock_func(ch, ATA_LF_UNLOCK);
+ ch->locking(ch, ATA_LF_UNLOCK);
}
#ifdef DEV_ATADISK
/* now we know whats there, do the real attach, first the ATA disks */
for (ctlr=0; ctlr<devclass_get_maxunit(ata_devclass); ctlr++) {
if (!(ch = devclass_get_softc(ata_devclass, ctlr)))
continue;
- ch->lock_func(ch, ATA_LF_LOCK);
+ ch->locking(ch, ATA_LF_LOCK);
if (ch->devices & ATA_ATA_MASTER)
ad_attach(&ch->device[MASTER]);
if (ch->devices & ATA_ATA_SLAVE)
ad_attach(&ch->device[SLAVE]);
- ch->lock_func(ch, ATA_LF_UNLOCK);
+ ch->locking(ch, ATA_LF_UNLOCK);
}
#endif
/* then the atapi devices */
for (ctlr=0; ctlr<devclass_get_maxunit(ata_devclass); ctlr++) {
if (!(ch = devclass_get_softc(ata_devclass, ctlr)))
continue;
- ch->lock_func(ch, ATA_LF_LOCK);
+ ch->locking(ch, ATA_LF_LOCK);
#if DEV_ATAPIALL
if (ch->devices & ATA_ATAPI_MASTER)
atapi_attach(&ch->device[MASTER]);
@@ -577,7 +583,7 @@ ata_boot_attach(void)
#ifdef DEV_ATAPICAM
atapi_cam_attach_bus(ch);
#endif
- ch->lock_func(ch, ATA_LF_UNLOCK);
+ ch->locking(ch, ATA_LF_UNLOCK);
}
if (ata_delayed_attach) {
config_intrhook_disestablish(ata_delayed_attach);
@@ -593,15 +599,8 @@ static void
ata_intr(void *data)
{
struct ata_channel *ch = (struct ata_channel *)data;
- /*
- * on PCI systems we might share an interrupt line with another
- * device or our twin ATA channel, so call ch->intr_func to figure
- * out if it is really an interrupt we should process here
- */
- if (!ch->intr_func(ch))
- return;
- /* if drive is busy it didn't interrupt */
+ /* if device is busy it didn't interrupt */
if (ATA_INB(ch->r_altio, ATA_ALTSTAT) & ATA_S_BUSY) {
DELAY(100);
if (!(ATA_INB(ch->r_altio, ATA_ALTSTAT) & ATA_S_DRQ))
@@ -651,7 +650,7 @@ ata_intr(void *data)
}
ch->running = NULL;
ATA_UNLOCK_CH(ch);
- ch->lock_func(ch, ATA_LF_UNLOCK);
+ ch->locking(ch, ATA_LF_UNLOCK);
ata_start(ch);
return;
}
@@ -667,7 +666,7 @@ ata_start(struct ata_channel *ch)
#endif
int s;
- ch->lock_func(ch, ATA_LF_LOCK);
+ ch->locking(ch, ATA_LF_LOCK);
if (!ATA_LOCK_CH(ch, ATA_ACTIVE))
return;
@@ -710,7 +709,7 @@ ata_start(struct ata_channel *ch)
}
#endif
ATA_UNLOCK_CH(ch);
- ch->lock_func(ch, ATA_LF_UNLOCK);
+ ch->locking(ch, ATA_LF_UNLOCK);
splx(s);
}
@@ -725,14 +724,14 @@ ata_reset(struct ata_channel *ch)
ATA_OUTB(ch->r_io, ATA_DRIVE, ATA_D_IBM | ATA_MASTER);
DELAY(10);
ostat0 = ATA_INB(ch->r_io, ATA_STATUS);
- if ((ostat0 & 0xf8) != 0xf8 && ostat0 != 0xa5) {
+ if ((ostat0 & 0xf8) == 0x50 && ostat0 != 0xa5) {
stat0 = ATA_S_BUSY;
mask |= 0x01;
}
ATA_OUTB(ch->r_io, ATA_DRIVE, ATA_D_IBM | ATA_SLAVE);
DELAY(10);
ostat1 = ATA_INB(ch->r_io, ATA_STATUS);
- if ((ostat1 & 0xf8) != 0xf8 && ostat1 != 0xa5) {
+ if ((ostat1 & 0xf8) == 0x50 && ostat1 != 0xa5) {
stat1 = ATA_S_BUSY;
mask |= 0x02;
}
@@ -748,7 +747,7 @@ ata_reset(struct ata_channel *ch)
}
if (bootverbose)
- ata_printf(ch, -1, "mask=%02x ostat0=%02x ostat2=%02x\n",
+ ata_printf(ch, -1, "pre reset mask=%02x ostat0=%02x ostat2=%02x\n",
mask, ostat0, ostat1);
/* reset channel */
@@ -811,7 +810,7 @@ ata_reset(struct ata_channel *ch)
if (stat1 & ATA_S_BUSY)
mask &= ~0x02;
if (bootverbose)
- ata_printf(ch, -1, "mask=%02x stat0=%02x stat1=%02x\n",
+ ata_printf(ch, -1, "after reset mask=%02x stat0=%02x stat1=%02x\n",
mask, stat0, stat1);
if (!mask)
return;
@@ -901,32 +900,32 @@ ata_reinit(struct ata_channel *ch)
}
newdev = ~devices & ch->devices;
#ifdef DEV_ATADISK
- if (newdev & ATA_ATA_MASTER && !ch->device[MASTER].driver)
- ad_attach(&ch->device[MASTER]);
- else if (ch->devices & ATA_ATA_MASTER && ch->device[MASTER].driver) {
- ata_getparam(&ch->device[MASTER], ATA_C_ATA_IDENTIFY);
- ad_reinit(&ch->device[MASTER]);
- }
if (newdev & ATA_ATA_SLAVE && !ch->device[SLAVE].driver)
ad_attach(&ch->device[SLAVE]);
else if (ch->devices & (ATA_ATA_SLAVE) && ch->device[SLAVE].driver) {
ata_getparam(&ch->device[SLAVE], ATA_C_ATA_IDENTIFY);
ad_reinit(&ch->device[SLAVE]);
}
+ if (newdev & ATA_ATA_MASTER && !ch->device[MASTER].driver)
+ ad_attach(&ch->device[MASTER]);
+ else if (ch->devices & ATA_ATA_MASTER && ch->device[MASTER].driver) {
+ ata_getparam(&ch->device[MASTER], ATA_C_ATA_IDENTIFY);
+ ad_reinit(&ch->device[MASTER]);
+ }
#endif
#if DEV_ATAPIALL
- if (newdev & ATA_ATAPI_MASTER && !ch->device[MASTER].driver)
- atapi_attach(&ch->device[MASTER]);
- else if (ch->devices & (ATA_ATAPI_MASTER) && ch->device[MASTER].driver) {
- ata_getparam(&ch->device[MASTER], ATA_C_ATAPI_IDENTIFY);
- atapi_reinit(&ch->device[MASTER]);
- }
if (newdev & ATA_ATAPI_SLAVE && !ch->device[SLAVE].driver)
atapi_attach(&ch->device[SLAVE]);
else if (ch->devices & (ATA_ATAPI_SLAVE) && ch->device[SLAVE].driver) {
ata_getparam(&ch->device[SLAVE], ATA_C_ATAPI_IDENTIFY);
atapi_reinit(&ch->device[SLAVE]);
}
+ if (newdev & ATA_ATAPI_MASTER && !ch->device[MASTER].driver)
+ atapi_attach(&ch->device[MASTER]);
+ else if (ch->devices & (ATA_ATAPI_MASTER) && ch->device[MASTER].driver) {
+ ata_getparam(&ch->device[MASTER], ATA_C_ATAPI_IDENTIFY);
+ atapi_reinit(&ch->device[MASTER]);
+ }
#endif
#ifdef DEV_ATAPICAM
atapi_cam_reinit_bus(ch);
@@ -942,8 +941,10 @@ 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_dmastatus(ch) | ATA_BMSTAT_INTERRUPT);
+ ch->dma->status(ch) | ATA_BMSTAT_INTERRUPT);
+#endif
#ifdef DEV_ATADISK
if ((ATA_INB(ch->r_io, ATA_DRIVE) & ATA_SLAVE) == ATA_MASTER) {
if ((ch->devices & ATA_ATA_MASTER) && ch->device[MASTER].driver)
@@ -1250,7 +1251,7 @@ ata_enclosure_status(struct ata_device *atadev,
u_int8_t id1, id2, cnt, div;
if (atadev->flags & ATA_D_ENC_PRESENT) {
- atadev->channel->lock_func(atadev->channel, ATA_LF_LOCK);
+ atadev->channel->locking(atadev->channel, ATA_LF_LOCK);
ATA_SLEEPLOCK_CH(atadev->channel, ATA_CONTROL);
ata_enclosure_sensor(atadev, 1, 0x4e, 0);
id1 = ata_enclosure_sensor(atadev, 0, 0x4f, 0);
@@ -1271,7 +1272,7 @@ ata_enclosure_status(struct ata_device *atadev,
*v05 = ata_enclosure_sensor(atadev, 0, 0x23, 0) * 27;
*v12 = ata_enclosure_sensor(atadev, 0, 0x24, 0) * 61;
ATA_UNLOCK_CH(atadev->channel);
- atadev->channel->lock_func(atadev->channel, ATA_LF_UNLOCK);
+ atadev->channel->locking(atadev->channel, ATA_LF_UNLOCK);
return 0;
}
return ENXIO;
@@ -1283,7 +1284,7 @@ ata_enclosure_print(struct ata_device *atadev)
u_int8_t id, st;
int fan, temp, v05, v12;
- atadev->channel->lock_func(atadev->channel, ATA_LF_LOCK);
+ 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);
@@ -1292,7 +1293,7 @@ ata_enclosure_print(struct ata_device *atadev)
DELAY(1);
ata_enclosure_end(atadev);
ATA_UNLOCK_CH(atadev->channel);
- atadev->channel->lock_func(atadev->channel, ATA_LF_UNLOCK);
+ atadev->channel->locking(atadev->channel, ATA_LF_UNLOCK);
switch (id & 0x93) {
case 0x00:
@@ -1306,11 +1307,12 @@ ata_enclosure_print(struct ata_device *atadev)
ata_prtdev(atadev, "SuperSwap enclosure");
break;
default:
- atadev->flags &= ~ATA_D_ENC_PRESENT;
+ atadev->flags &= ~ATA_D_ENC_PRESENT;
return;
}
atadev->flags |= ATA_D_ENC_PRESENT;
+ ata_enclosure_leds(atadev, ATA_LED_GREEN);
if (ata_enclosure_status(atadev, &fan, &temp, &v05, &v12))
printf(" detected\n");
else
@@ -1337,31 +1339,8 @@ ata_enclosure_leds(struct ata_device *atadev, u_int8_t color)
static void
ata_change_mode(struct ata_device *atadev, int mode)
{
- int umode, wmode, pmode;
-
- umode = ata_umode(atadev->param);
- wmode = ata_wmode(atadev->param);
- pmode = ata_pmode(atadev->param);
-
- switch (mode & ATA_DMA_MASK) {
- case ATA_UDMA:
- if ((mode & ATA_MODE_MASK) < umode)
- umode = mode & ATA_MODE_MASK;
- break;
- case ATA_WDMA:
- if ((mode & ATA_MODE_MASK) < wmode)
- wmode = mode & ATA_MODE_MASK;
- umode = -1;
- break;
- default:
- if (((mode & ATA_MODE_MASK) - ATA_PIO0) < pmode)
- pmode = (mode & ATA_MODE_MASK) - ATA_PIO0;
- umode = -1;
- wmode = -1;
- }
-
ATA_SLEEPLOCK_CH(atadev->channel, ATA_ACTIVE);
- ata_dmainit(atadev, pmode, wmode, umode);
+ atadev->setmode(atadev, mode);
ATA_UNLOCK_CH(atadev->channel);
ata_start(atadev->channel);
}
@@ -1452,8 +1431,13 @@ ata_mode2str(int mode)
case ATA_PIO3: return "PIO3";
case ATA_PIO4: return "PIO4";
case ATA_DMA: return "BIOSDMA";
+ case ATA_WDMA0: return "WDMA0";
+ case ATA_WDMA1: return "WDMA1";
case ATA_WDMA2: return "WDMA2";
+ case ATA_UDMA0: return "UDMA16";
+ case ATA_UDMA1: return "UDMA25";
case ATA_UDMA2: return "UDMA33";
+ case ATA_UDMA3: return "UDMA40";
case ATA_UDMA4: return "UDMA66";
case ATA_UDMA5: return "UDMA100";
case ATA_UDMA6: return "UDMA133";
@@ -1465,29 +1449,33 @@ int
ata_pmode(struct ata_params *ap)
{
if (ap->atavalid & ATA_FLAG_64_70) {
- if (ap->apiomodes & 2)
- return 4;
- if (ap->apiomodes & 1)
- return 3;
+ if (ap->apiomodes & 0x02)
+ return ATA_PIO4;
+ if (ap->apiomodes & 0x01)
+ return ATA_PIO3;
}
if (ap->retired_piomode == 2)
- return 2;
+ return ATA_PIO2;
if (ap->retired_piomode == 1)
- return 1;
+ return ATA_PIO1;
if (ap->retired_piomode == 0)
- return 0;
- return -1;
+ return ATA_PIO0;
+ if (ap->support_dma)
+ return ATA_PIO4;
+ return ATA_PIO0;
}
int
ata_wmode(struct ata_params *ap)
{
if (ap->mwdmamodes & 0x04)
- return 2;
+ return ATA_WDMA2;
if (ap->mwdmamodes & 0x02)
- return 1;
+ return ATA_WDMA1;
if (ap->mwdmamodes & 0x01)
- return 0;
+ return ATA_WDMA0;
+ if (ap->support_dma)
+ return ATA_WDMA2;
return -1;
}
@@ -1496,23 +1484,41 @@ ata_umode(struct ata_params *ap)
{
if (ap->atavalid & ATA_FLAG_88) {
if (ap->udmamodes & 0x40)
- return 6;
+ return ATA_UDMA6;
if (ap->udmamodes & 0x20)
- return 5;
+ return ATA_UDMA5;
if (ap->udmamodes & 0x10)
- return 4;
+ return ATA_UDMA4;
if (ap->udmamodes & 0x08)
- return 3;
+ return ATA_UDMA3;
if (ap->udmamodes & 0x04)
- return 2;
+ return ATA_UDMA2;
if (ap->udmamodes & 0x02)
- return 1;
+ return ATA_UDMA1;
if (ap->udmamodes & 0x01)
- return 0;
+ return ATA_UDMA0;
}
return -1;
}
+int
+ata_limit_mode(struct ata_device *atadev, int mode, int maxmode)
+{
+ if (maxmode && mode > maxmode)
+ mode = maxmode;
+
+ if (mode >= ATA_UDMA0 && ata_umode(atadev->param) > 0)
+ return min(mode, ata_umode(atadev->param));
+
+ if (mode >= ATA_WDMA0 && ata_wmode(atadev->param) > 0)
+ return min(mode, ata_wmode(atadev->param));
+
+ if (mode > ata_pmode(atadev->param))
+ return min(mode, ata_pmode(atadev->param));
+
+ return mode;
+}
+
static void
bswap(int8_t *buf, int len)
{
diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h
index 323a99d..52d4348 100644
--- a/sys/dev/ata/ata-all.h
+++ b/sys/dev/ata/ata-all.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -120,11 +120,11 @@
/* misc defines */
#define ATA_PRIMARY 0x1f0
#define ATA_SECONDARY 0x170
-#define ATA_PC98_BANK 0x432
+#define ATA_PC98_BANK 0x432
#define ATA_IOSIZE 0x08
#define ATA_ALTIOSIZE 0x01
#define ATA_BMIOSIZE 0x08
-#define ATA_PC98_BANKIOSIZE 0x01
+#define ATA_PC98_BANKIOSIZE 0x01
#define ATA_OP_FINISHED 0x00
#define ATA_OP_CONTINUES 0x01
#define ATA_IOADDR_RID 0
@@ -145,7 +145,6 @@
#define ATA_BMCMD_WRITE_READ 0x08
#define ATA_BMDEVSPEC_0 0x01
-
#define ATA_BMSTAT_PORT 0x02
#define ATA_BMSTAT_ACTIVE 0x01
#define ATA_BMSTAT_ERROR 0x02
@@ -172,8 +171,8 @@ struct ata_dmastate {
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 */
+#define ATA_DS_ACTIVE 0x01 /* debugging */
+#define ATA_DS_READ 0x02 /* transaction is a read */
};
/* structure describing an ATA/ATAPI device */
@@ -192,12 +191,26 @@ struct ata_device {
#define ATA_D_MEDIA_CHANGED 0x0004
#define ATA_D_ENC_PRESENT 0x0008
- int mode; /* transfermode */
int cmd; /* last cmd executed */
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 *);
+ 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 (*status)(struct ata_channel *);
+ u_int32_t alignment; /* dma engine alignment */
+};
+
/* structure describing an ATA channel */
struct ata_channel {
struct device *dev; /* device handle */
@@ -208,10 +221,9 @@ struct ata_channel {
bus_dma_tag_t dmatag; /* parent dma tag */
struct resource *r_irq; /* interrupt of this channel */
void *ih; /* interrupt handle */
- int (*intr_func)(struct ata_channel *); /* interrupt function */
- u_int32_t chiptype; /* pciid of controller chip */
- u_int32_t alignment; /* dma engine min alignment */
- int flags; /* controller flags */
+ struct ata_dma_funcs *dma; /* DMA functions */
+ u_int32_t chiptype; /* controller chip PCI id */
+ int flags; /* channel flags */
#define ATA_NO_SLAVE 0x01
#define ATA_USE_16BIT 0x02
#define ATA_USE_PC98GEOM 0x04
@@ -243,7 +255,7 @@ struct ata_channel {
#define ATA_ACTIVE_ATAPI 0x0040
#define ATA_CONTROL 0x0080
- void (*lock_func)(struct ata_channel *, int);/* controller lock function */
+ void (*locking)(struct ata_channel *, int);
#define ATA_LF_LOCK 0x0001
#define ATA_LF_UNLOCK 0x0002
@@ -286,16 +298,7 @@ char *ata_mode2str(int);
int ata_pmode(struct ata_params *);
int ata_wmode(struct ata_params *);
int ata_umode(struct ata_params *);
-int ata_find_dev(device_t, u_int32_t, u_int32_t);
-
-int ata_dmaalloc(struct ata_device *);
-void ata_dmafree(struct ata_device *);
-void ata_dmafreetags(struct ata_channel *);
-void ata_dmainit(struct ata_device *, int, int, int);
-int ata_dmasetup(struct ata_device *, caddr_t, int32_t);
-int ata_dmastart(struct ata_device *, caddr_t, int32_t, int);
-int ata_dmastatus(struct ata_channel *);
-int ata_dmadone(struct ata_device *);
+int ata_limit_mode(struct ata_device *, int, int);
/* macros for locking a channel */
#define ATA_LOCK_CH(ch, value) \
@@ -325,7 +328,7 @@ int ata_dmadone(struct ata_device *);
(offset), (addr), (count))
#define ATA_INSW_STRM(res, offset, addr, count) \
bus_space_read_multi_stream_2(rman_get_bustag((res)), \
- rman_get_bushandle((res)), \
+ rman_get_bushandle((res)), \
(offset), (addr), (count))
#define ATA_INSL(res, offset, addr, count) \
bus_space_read_multi_4(rman_get_bustag((res)), \
@@ -333,7 +336,7 @@ int ata_dmadone(struct ata_device *);
(offset), (addr), (count))
#define ATA_INSL_STRM(res, offset, addr, count) \
bus_space_read_multi_stream_4(rman_get_bustag((res)), \
- rman_get_bushandle((res)), \
+ rman_get_bushandle((res)), \
(offset), (addr), (count))
#define ATA_OUTB(res, offset, value) \
bus_space_write_1(rman_get_bustag((res)), \
@@ -350,7 +353,7 @@ int ata_dmadone(struct ata_device *);
(offset), (addr), (count))
#define ATA_OUTSW_STRM(res, offset, addr, count) \
bus_space_write_multi_stream_2(rman_get_bustag((res)), \
- rman_get_bushandle((res)), \
+ rman_get_bushandle((res)), \
(offset), (addr), (count))
#define ATA_OUTSL(res, offset, addr, count) \
bus_space_write_multi_4(rman_get_bustag((res)), \
@@ -358,5 +361,5 @@ int ata_dmadone(struct ata_device *);
(offset), (addr), (count))
#define ATA_OUTSL_STRM(res, offset, addr, count) \
bus_space_write_multi_stream_4(rman_get_bustag((res)), \
- rman_get_bushandle((res)), \
+ rman_get_bushandle((res)), \
(offset), (addr), (count))
diff --git a/sys/dev/ata/ata-card.c b/sys/dev/ata/ata-card.c
index ef1c338..31ff4ab 100644
--- a/sys/dev/ata/ata-card.c
+++ b/sys/dev/ata/ata-card.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -61,12 +61,6 @@ ata_pccard_match(device_t dev)
return(ENXIO);
}
-static int
-ata_pccard_intrnoop(struct ata_channel *ch)
-{
- return 1;
-}
-
static void
ata_pccard_locknoop(struct ata_channel *ch, int type)
{
@@ -116,8 +110,7 @@ ata_pccard_probe(device_t dev)
ch->unit = 0;
ch->flags |= (ATA_USE_16BIT | ATA_NO_SLAVE);
- ch->intr_func = ata_pccard_intrnoop;
- ch->lock_func = ata_pccard_locknoop;
+ ch->locking = ata_pccard_locknoop;
return ata_probe(dev);
}
diff --git a/sys/dev/ata/ata-cbus.c b/sys/dev/ata/ata-cbus.c
index 854b55e..38a2d20 100644
--- a/sys/dev/ata/ata-cbus.c
+++ b/sys/dev/ata/ata-cbus.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2002 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 2002, 2003 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,6 +32,7 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/ata.h>
#include <sys/bus.h>
#include <sys/malloc.h>
#include <machine/resource.h>
@@ -50,9 +51,21 @@ struct ata_cbus_controller {
struct resource *altio;
struct resource *bankio;
struct resource *irq;
+ void *ih;
+ void (*setmode)(struct ata_device *, int);
+ void (*locking)(struct ata_channel *, int);
int current_bank;
+ struct {
+ void (*function)(void *);
+ void *argument;
+ } interrupt[2];
};
+/* local prototypes */
+static void ata_cbus_intr(void *);
+static void ata_cbus_banking(struct ata_channel *, int);
+static void ata_cbus_setmode(struct ata_device *, int);
+
static int
ata_cbus_probe(device_t dev)
{
@@ -93,37 +106,49 @@ ata_cbus_probe(device_t dev)
static int
ata_cbus_attach(device_t dev)
{
- struct ata_cbus_controller *scp = device_get_softc(dev);
+ struct ata_cbus_controller *ctlr = device_get_softc(dev);
int rid;
/* allocate resources */
rid = ATA_IOADDR_RID;
- scp->io = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, ata_pc98_ports,
+ ctlr->io = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, ata_pc98_ports,
ATA_IOSIZE, RF_ACTIVE);
- if (!scp->io)
+ if (!ctlr->io)
return ENOMEM;
- isa_load_resourcev(scp->io, ata_pc98_ports, ATA_IOSIZE);
+ isa_load_resourcev(ctlr->io, ata_pc98_ports, ATA_IOSIZE);
rid = ATA_PC98_ALTADDR_RID;
- scp->altio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
- rman_get_start(scp->io)+ATA_PC98_ALTOFFSET,
+ ctlr->altio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
+ rman_get_start(ctlr->io)+ATA_PC98_ALTOFFSET,
~0, ATA_ALTIOSIZE, RF_ACTIVE);
- if (!scp->altio)
+ if (!ctlr->altio)
return ENOMEM;
rid = ATA_PC98_BANKADDR_RID;
- scp->bankio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
+ ctlr->bankio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
ATA_PC98_BANK, ~0,
ATA_PC98_BANKIOSIZE, RF_ACTIVE);
- if (!scp->bankio)
+ if (!ctlr->bankio)
return ENOMEM;
rid = 0;
- scp->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
- 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
+ if (!(ctlr->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
+ 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE))) {
+ device_printf(dev, "unable to alloc interrupt\n");
+ 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");
+ return ENXIO;
+ }
+
+ ctlr->locking = ata_cbus_banking;
+ ctlr->current_bank = -1;
+ ctlr->setmode = ata_cbus_setmode;;
- scp->current_bank = -1;
if (!device_add_child(dev, "ata", 0))
return ENOMEM;
if (!device_add_child(dev, "ata", 1))
@@ -136,18 +161,18 @@ static struct resource *
ata_cbus_alloc_resource(device_t dev, device_t child, int type, int *rid,
u_long start, u_long end, u_long count, u_int flags)
{
- struct ata_cbus_controller *scp = device_get_softc(dev);
+ struct ata_cbus_controller *ctlr = device_get_softc(dev);
if (type == SYS_RES_IOPORT) {
switch (*rid) {
case ATA_IOADDR_RID:
- return scp->io;
+ return ctlr->io;
case ATA_ALTADDR_RID:
- return scp->altio;
+ return ctlr->altio;
}
}
if (type == SYS_RES_IRQ) {
- return scp->irq;
+ return ctlr->irq;
}
return 0;
}
@@ -157,8 +182,14 @@ ata_cbus_setup_intr(device_t dev, device_t child, struct resource *irq,
int flags, driver_intr_t *intr, void *arg,
void **cookiep)
{
- return BUS_SETUP_INTR(device_get_parent(dev), dev, irq,
- flags, intr, arg, cookiep);
+ struct ata_cbus_controller *controller = device_get_softc(dev);
+ int unit = ((struct ata_channel *)device_get_softc(child))->unit;
+
+ controller->interrupt[unit].function = intr;
+ controller->interrupt[unit].argument = arg;
+ *cookiep = controller;
+
+ return 0;
}
static int
@@ -173,40 +204,48 @@ ata_cbus_print_child(device_t dev, device_t child)
return retval;
}
-static int
-ata_cbus_intr(struct ata_channel *ch)
+static void
+ata_cbus_intr(void *data)
{
- struct ata_cbus_controller *scp =
- device_get_softc(device_get_parent(ch->dev));
+ struct ata_cbus_controller *ctlr = data;
- return (ch->unit == scp->current_bank);
+ if (ctlr->current_bank != -1 &&
+ ctlr->interrupt[ctlr->current_bank].argument)
+ ctlr->interrupt[ctlr->current_bank].
+ function(ctlr->interrupt[ctlr->current_bank].argument);
}
static void
ata_cbus_banking(struct ata_channel *ch, int flags)
{
- struct ata_cbus_controller *scp =
+ struct ata_cbus_controller *ctlr =
device_get_softc(device_get_parent(ch->dev));
switch (flags) {
case ATA_LF_LOCK:
- if (scp->current_bank == ch->unit)
+ if (ctlr->current_bank == ch->unit)
break;
- while (!atomic_cmpset_acq_int(&scp->current_bank, -1, ch->unit))
- tsleep((caddr_t)ch->lock_func, PRIBIO, "atalck", 1);
- bus_space_write_1(rman_get_bustag(scp->bankio),
- rman_get_bushandle(scp->bankio), 0, ch->unit);
+ 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);
break;
case ATA_LF_UNLOCK:
- if (scp->current_bank == -1 || scp->current_bank != ch->unit)
+ if (ctlr->current_bank == -1 || ctlr->current_bank != ch->unit)
break;
- atomic_store_rel_int(&scp->current_bank, -1);
+ atomic_store_rel_int(&ctlr->current_bank, -1);
break;
}
return;
}
+static void
+ata_cbus_setmode(struct ata_device *atadev, int mode)
+{
+ atadev->mode = ata_limit_mode(atadev, mode, ATA_PIO_MAX);
+}
+
static device_method_t ata_cbus_methods[] = {
/* device_interface */
DEVMETHOD(device_probe, ata_cbus_probe),
@@ -232,6 +271,7 @@ DRIVER_MODULE(atacbus, isa, ata_cbus_driver, ata_cbus_devclass, 0, 0);
static int
ata_cbussub_probe(device_t dev)
{
+ struct ata_cbus_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
device_t *children;
int count, i;
@@ -244,8 +284,9 @@ ata_cbussub_probe(device_t dev)
}
free(children, M_TEMP);
ch->flags |= ATA_USE_16BIT | ATA_USE_PC98GEOM;
- ch->intr_func = ata_cbus_intr;
- ch->lock_func = ata_cbus_banking;
+ 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
new file mode 100644
index 0000000..8860226
--- /dev/null
+++ b/sys/dev/ata/ata-chipset.c
@@ -0,0 +1,1887 @@
+/*-
+ * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification, immediately at the beginning of the file.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#include "opt_ata.h"
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/ata.h>
+#include <sys/bus.h>
+#include <sys/malloc.h>
+#include <machine/stdarg.h>
+#include <machine/resource.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <pci/pcivar.h>
+#include <pci/pcireg.h>
+#include <dev/ata/ata-all.h>
+#include <dev/ata/ata-pci.h>
+
+/* misc defines */
+#define GRANDPARENT(dev) device_get_parent(device_get_parent(dev))
+#define ATAPI_DEVICE(atadev) \
+ ((atadev->unit == ATA_MASTER && \
+ atadev->channel->devices & ATA_ATAPI_MASTER) ||\
+ (atadev->unit == ATA_SLAVE && \
+ atadev->channel->devices & ATA_ATAPI_SLAVE))
+
+/* local prototypes */
+static int ata_generic_chipinit(device_t);
+static void ata_generic_intr(void *);
+static void ata_generic_setmode(struct ata_device *, int);
+static int ata_acard_chipinit(device_t);
+static void ata_acard_intr(void *);
+static void ata_acard_850_setmode(struct ata_device *, int);
+static void ata_acard_86X_setmode(struct ata_device *, int);
+static int ata_ali_chipinit(device_t);
+static void ata_ali_setmode(struct ata_device *, int);
+static int ata_amd_chipinit(device_t);
+static int ata_cyrix_chipinit(device_t);
+static void ata_cyrix_setmode(struct ata_device *, int);
+static int ata_cypress_chipinit(device_t);
+static void ata_cypress_setmode(struct ata_device *, int);
+static int ata_highpoint_chipinit(device_t);
+static void ata_highpoint_intr(void *);
+static void ata_highpoint_setmode(struct ata_device *, int);
+static int ata_highpoint_check_80pin(struct ata_device *, int);
+static int ata_intel_chipinit(device_t);
+static void ata_intel_old_setmode(struct ata_device *, int);
+static void ata_intel_new_setmode(struct ata_device *, int);
+static int ata_nvidia_chipinit(device_t);
+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_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_serverworks_chipinit(device_t);
+static void ata_serverworks_setmode(struct ata_device *, int);
+static int ata_sii_chipinit(device_t);
+static void ata_cmd_intr(void *);
+static void ata_sii_setmode(struct ata_device *, int);
+static void ata_cmd_setmode(struct ata_device *, int);
+static int ata_sis_chipinit(device_t);
+static void ata_sis_setmode(struct ata_device *, int);
+static int ata_mode2idx(int);
+static int ata_check_80pin(struct ata_device *, int);
+static int ata_find_dev(device_t, u_int32_t, u_int32_t);
+static struct ata_chip_id *ata_match_chip(device_t, struct ata_chip_id *);
+static int ata_default_interrupt(device_t);
+static void ata_pci_serialize(struct ata_channel *, int);
+
+/* generic or unknown ATA chipset init code */
+int
+ata_generic_ident(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+
+ device_set_desc(dev, "GENERIC ATA controller");
+ ctlr->chipinit = ata_generic_chipinit;
+ return 0;
+}
+
+static int
+ata_generic_chipinit(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+
+ if (ata_default_interrupt(dev))
+ return ENXIO;
+ ctlr->setmode = ata_generic_setmode;
+ return 0;
+}
+
+static void
+ata_generic_intr(void *data)
+{
+ struct ata_pci_controller *ctlr = data;
+ struct ata_channel *ch;
+ u_int8_t dmastat;
+ int unit;
+
+ /* implement this as a toggle instead to balance load XXX */
+ for (unit = 0; unit < 2; unit++) {
+ if (!(ch = ctlr->interrupt[unit].argument))
+ continue;
+ if (ch->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);
+ DELAY(1);
+ }
+ ctlr->interrupt[unit].function(ch);
+ }
+}
+
+static void
+ata_generic_setmode(struct ata_device *atadev, int mode)
+{
+ if (mode >= ATA_DMA)
+ atadev->mode = ATA_DMA;
+ else
+ atadev->mode = ATA_PIO;
+ return;
+}
+
+/*
+ * Acard chipset support functions
+ */
+int
+ata_acard_ident(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+ struct ata_chip_id *idx;
+ static struct ata_chip_id ids[] =
+ {{ ATA_ATP850R, 0, ATPOLD, 0x00, ATA_UDMA2, "Acard ATP850" },
+ { ATA_ATP860A, 0, 0, 0x00, ATA_UDMA4, "Acard ATP860A" },
+ { ATA_ATP860R, 0, 0, 0x00, ATA_UDMA4, "Acard ATP860R" },
+ { ATA_ATP865A, 0, 0, 0x00, ATA_UDMA6, "Acard ATP865A" },
+ { ATA_ATP865R, 0, 0, 0x00, ATA_UDMA6, "Acard ATP865R" },
+ { 0, 0, 0, 0, 0, 0}};
+ char buffer[64];
+
+ if (!(idx = ata_match_chip(dev, ids)))
+ return ENXIO;
+
+ sprintf(buffer, "%s %s controller", idx->text, ata_mode2str(idx->max_dma));
+ device_set_desc_copy(dev, buffer);
+ ctlr->chip = idx;
+ ctlr->chipinit = ata_acard_chipinit;
+ return 0;
+}
+
+static int
+ata_acard_chipinit(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+ int rid = ATA_IRQ_RID;
+
+ if (!(ctlr->r_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
+ RF_SHAREABLE | RF_ACTIVE))) {
+ device_printf(dev, "unable to map interrupt\n");
+ return ENXIO;
+ }
+ if ((bus_setup_intr(dev, ctlr->r_irq, INTR_TYPE_BIO | INTR_ENTROPY,
+ ata_acard_intr, ctlr, &ctlr->handle))) {
+ device_printf(dev, "unable to setup interrupt\n");
+ return ENXIO;
+ }
+ if (ctlr->chip->cfg1 == ATPOLD) {
+ ctlr->setmode = ata_acard_850_setmode;
+ ctlr->locking = ata_pci_serialize;
+ }
+ else
+ ctlr->setmode = ata_acard_86X_setmode;
+ return 0;
+}
+
+static void
+ata_acard_intr(void *data)
+{
+ struct ata_pci_controller *ctlr = data;
+ struct ata_channel *ch;
+ u_int8_t dmastat;
+ int unit;
+
+ /* implement this as a toggle instead to balance load XXX */
+ for (unit = 0; unit < 2; unit++) {
+ if (ctlr->chip->cfg1 == ATPOLD && ctlr->locked_ch != unit)
+ continue;
+ ch = ctlr->interrupt[unit].argument;
+ if (ch->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);
+ DELAY(1);
+ ATA_OUTB(ch->r_bmio, ATA_BMCMD_PORT,
+ ATA_INB(ch->r_bmio, ATA_BMCMD_PORT)&~ATA_BMCMD_START_STOP);
+ DELAY(1);
+ }
+ ctlr->interrupt[unit].function(ch);
+ }
+}
+
+static void
+ata_acard_850_setmode(struct ata_device *atadev, int mode)
+{
+ device_t parent = device_get_parent(atadev->channel->dev);
+ struct ata_pci_controller *ctlr = device_get_softc(parent);
+ int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit);
+ int error;
+
+ mode = ata_limit_mode(atadev, mode,
+ ATAPI_DEVICE(atadev)?ATA_PIO_MAX:ctlr->chip->max_dma);
+
+/* XXX missing WDMA0+1 + PIO modes */
+ if (mode >= ATA_WDMA2) {
+ error = ata_command(atadev, ATA_C_SETFEATURES, 0,
+ mode, ATA_C_F_SETXFER, ATA_WAIT_READY);
+ if (bootverbose)
+ ata_prtdev(atadev, "%s setting %s on %s chip\n",
+ (error) ? "failed" : "success",
+ ata_mode2str(mode), ctlr->chip->text);
+ if (!error) {
+ u_int8_t reg54 = pci_read_config(parent, 0x54, 1);
+
+ reg54 &= ~(0x03 << (devno << 1));
+ if (mode >= ATA_UDMA0)
+ reg54 |= (((mode & ATA_MODE_MASK) + 1) << (devno << 1));
+ pci_write_config(parent, 0x54, reg54, 1);
+ pci_write_config(parent, 0x4a, 0xa6, 1);
+ pci_write_config(parent, 0x40 + (devno << 1), 0x0301, 2);
+ atadev->mode = mode;
+ return;
+ }
+ }
+ /* we could set PIO mode timings, but we assume the BIOS did that */
+}
+
+static void
+ata_acard_86X_setmode(struct ata_device *atadev, int mode)
+{
+ device_t parent = device_get_parent(atadev->channel->dev);
+ struct ata_pci_controller *ctlr = device_get_softc(parent);
+ int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit);
+ int error;
+
+
+ mode = ata_limit_mode(atadev, mode,
+ ATAPI_DEVICE(atadev)?ATA_PIO_MAX:ctlr->chip->max_dma);
+
+ mode = ata_check_80pin(atadev, mode);
+
+/* XXX missing WDMA0+1 + PIO modes */
+ if (mode >= ATA_WDMA2) {
+ error = ata_command(atadev, ATA_C_SETFEATURES, 0,
+ mode, ATA_C_F_SETXFER, ATA_WAIT_READY);
+ if (bootverbose)
+ ata_prtdev(atadev, "%s setting %s on %s chip\n",
+ (error) ? "failed" : "success",
+ ata_mode2str(mode), ctlr->chip->text);
+ if (!error) {
+ u_int16_t reg44 = pci_read_config(parent, 0x44, 2);
+
+ reg44 &= ~(0x000f << (devno << 2));
+ if (mode >= ATA_UDMA0)
+ reg44 |= (((mode & ATA_MODE_MASK) + 1) << (devno << 2));
+ pci_write_config(parent, 0x44, reg44, 2);
+ pci_write_config(parent, 0x4a, 0xa6, 1);
+ pci_write_config(parent, 0x40 + devno, 0x31, 1);
+ atadev->mode = mode;
+ return;
+ }
+ }
+ /* we could set PIO mode timings, but we assume the BIOS did that */
+}
+
+/*
+ * Acer Labs Inc (ALI) chipset support functions
+ */
+int
+ata_ali_ident(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+ struct ata_chip_id *idx;
+ static struct ata_chip_id ids[] =
+ {{ ATA_ALI_5229, 0xc4, 0, ALICABLE, ATA_UDMA5, "AcerLabs Aladdin" },
+ { ATA_ALI_5229, 0xc2, 0, ALICABLE, ATA_UDMA4, "AcerLabs Aladdin" },
+ { ATA_ALI_5229, 0x20, 0, ALIOLD, ATA_UDMA2, "AcerLabs Aladdin" },
+ { ATA_ALI_5229, 0x00, 0, ALIOLD, ATA_WDMA2, "AcerLabs Aladdin" },
+ { 0, 0, 0, 0, 0, 0}};
+ char buffer[64];
+
+ if (!(idx = ata_match_chip(dev, ids)))
+ return ENXIO;
+
+ sprintf(buffer, "%s %s controller", idx->text, ata_mode2str(idx->max_dma));
+ device_set_desc_copy(dev, buffer);
+ ctlr->chip = idx;
+ ctlr->chipinit = ata_ali_chipinit;
+ return 0;
+}
+
+static int
+ata_ali_chipinit(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+
+ if (ata_default_interrupt(dev))
+ return ENXIO;
+
+ /* AcerLabs Aladdin need to deactivate the ATAPI FIFO */
+ pci_write_config(dev, 0x53, (pci_read_config(dev, 0x53, 1) & ~0x01)|0x02,1);
+
+ if (ctlr->chip->cfg2 & ALICABLE)
+ pci_write_config(dev, 0x4b, pci_read_config(dev, 0x4b, 1) | 0x08, 1);
+ ctlr->setmode = ata_ali_setmode;
+ return 0;
+}
+
+static void
+ata_ali_setmode(struct ata_device *atadev, int mode)
+{
+ device_t parent = device_get_parent(atadev->channel->dev);
+ struct ata_pci_controller *ctlr = device_get_softc(parent);
+ int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit);
+ int error;
+
+ mode = ata_limit_mode(atadev, mode, ctlr->chip->max_dma);
+
+ if (ctlr->chip->cfg2 & ALICABLE) {
+ if (mode > ATA_UDMA2 &&
+ pci_read_config(parent, 0x4a, 1) & (1 << atadev->channel->unit)) {
+ ata_prtdev(atadev,
+ "DMA limited to UDMA33, non-ATA66 cable or device\n");
+ mode = ATA_UDMA2;
+ }
+ }
+ else
+ mode = ata_check_80pin(atadev, mode);
+
+ if (ctlr->chip->cfg2 & ALIOLD) {
+ /* doesn't support ATAPI DMA on write */
+ atadev->channel->flags |= ATA_ATAPI_DMA_RO;
+ if (atadev->channel->devices & ATA_ATAPI_MASTER &&
+ atadev->channel->devices & ATA_ATAPI_SLAVE) {
+ /* doesn't support ATAPI DMA on two ATAPI devices */
+ ata_prtdev(atadev, "two atapi devices on this channel, no DMA\n");
+ ata_limit_mode(atadev, mode, ATA_PIO_MAX);
+ }
+ }
+
+ error = ata_command(atadev, ATA_C_SETFEATURES, 0, mode,
+ ATA_C_F_SETXFER, ATA_WAIT_READY);
+ if (bootverbose)
+ ata_prtdev(atadev, "%s setting %s on %s chip\n",
+ (error) ? "failed" : "success",
+ ata_mode2str(mode), ctlr->chip->text);
+ if (!error) {
+ if (mode >= ATA_UDMA0) {
+ u_int8_t udma[] = {0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x0f};
+ u_int32_t word54 = pci_read_config(parent, 0x54, 4);
+
+ pci_write_config(parent, 0x58 + (atadev->channel->unit << 2),
+ 0x00310001, 4);
+
+ pci_write_config(parent, 0x4b,
+ pci_read_config(parent, 0x4b, 1) | 0x01, 1);
+ word54 &= ~(0x000f000f << (devno << 2));
+ word54 |= (((udma[mode&ATA_MODE_MASK]<<16)|0x05)<<(devno<<2));
+ pci_write_config(parent, 0x54, word54, 4);
+ pci_write_config(parent, 0x53,
+ pci_read_config(parent, 0x53, 1) | 0x03, 1);
+ }
+ else {
+ u_int32_t piotimings[] =
+ { 0x006d0003, 0x00580002, 0x00440001, 0x00330001,
+ 0x00310001, 0x00440001, 0x00330001, 0x00310001};
+
+ pci_write_config(parent, 0x54, pci_read_config(parent, 0x54, 4) &
+ ~(0x0008000f << (devno << 2)), 4);
+
+ pci_write_config(parent, 0x58 + (atadev->channel->unit << 2),
+ piotimings[ata_mode2idx(mode)], 4);
+
+ pci_write_config(parent, 0x53, mode > ATA_PIO_MAX ?
+ (pci_read_config(parent, 0x53, 1) | 0x03, 1) :
+ (pci_read_config(parent, 0x53, 1) & ~0x01)|0x02,1);
+ }
+ atadev->mode = mode;
+ }
+}
+
+/*
+ * American Micro Devices (AMD) support function
+ */
+int
+ata_amd_ident(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+ struct ata_chip_id *idx;
+ static struct ata_chip_id ids[] =
+ {{ ATA_AMD756, 0x00, AMDNVIDIA, 0x00, ATA_UDMA4, "AMD 756" },
+ { ATA_AMD766, 0x00, AMDNVIDIA, AMDCABLE|AMDBUG, ATA_UDMA5, "AMD 766" },
+ { ATA_AMD768, 0x00, AMDNVIDIA, AMDCABLE, ATA_UDMA5, "AMD 768" },
+ { ATA_AMD8111, 0x00, AMDNVIDIA, 0x00, ATA_UDMA6, "AMD 8111" },
+ { 0, 0, 0, 0, 0, 0}};
+ char buffer[64];
+
+ if (!(idx = ata_match_chip(dev, ids)))
+ return ENXIO;
+
+ sprintf(buffer, "%s %s controller", idx->text, ata_mode2str(idx->max_dma));
+ device_set_desc_copy(dev, buffer);
+ ctlr->chip = idx;
+ ctlr->chipinit = ata_amd_chipinit;
+ return 0;
+}
+
+static int
+ata_amd_chipinit(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+
+ if (ata_default_interrupt(dev))
+ return ENXIO;
+
+ /* set prefetch, postwrite */
+ if (ctlr->chip->cfg2 & AMDBUG)
+ pci_write_config(dev, 0x41, pci_read_config(dev, 0x41, 1) & 0x0f, 1);
+ else
+ pci_write_config(dev, 0x41, pci_read_config(dev, 0x41, 1) | 0xf0, 1);
+
+ ctlr->setmode = ata_via_family_setmode;
+ return 0;
+}
+
+/*
+ * Cyrix chipset support functions
+ */
+int
+ata_cyrix_ident(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+
+ if (pci_get_devid(dev) == ATA_CYRIX_5530) {
+ device_set_desc(dev, "Cyrix 5530 ATA33 controller");
+ ctlr->chipinit = ata_cyrix_chipinit;
+ return 0;
+ }
+ return ENXIO;
+}
+
+static int
+ata_cyrix_chipinit(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+
+ if (ata_default_interrupt(dev))
+ return ENXIO;
+
+ ctlr->setmode = ata_cyrix_setmode;
+ return 0;
+}
+
+static void
+ata_cyrix_setmode(struct ata_device *atadev, int mode)
+{
+ int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit);
+ u_int32_t piotiming[] =
+ { 0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010 };
+ u_int32_t dmatiming[] = { 0x00077771, 0x00012121, 0x00002020 };
+ u_int32_t udmatiming[] = { 0x00921250, 0x00911140, 0x00911030 };
+ int error;
+
+ mode = ata_limit_mode(atadev, mode, ATA_UDMA2);
+ atadev->channel->dma->alignment = 16;
+
+ error = ata_command(atadev, ATA_C_SETFEATURES, 0, mode,
+ ATA_C_F_SETXFER, ATA_WAIT_READY);
+ if (bootverbose)
+ ata_prtdev(atadev, "%s setting %s on Cyrix chip\n",
+ (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]);
+ }
+ else if (mode >= ATA_WDMA0) {
+ ATA_OUTL(atadev->channel->r_bmio, (devno << 3) + 0x24,
+ dmatiming[mode % ATA_MODE_MASK]);
+ }
+ else {
+ ATA_OUTL(atadev->channel->r_bmio, (devno << 3) + 0x20,
+ piotiming[mode % ATA_MODE_MASK]);
+ }
+ atadev->mode = mode;
+ }
+}
+
+/*
+ * Cypress chipset support functions
+ */
+int
+ata_cypress_ident(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+
+ /*
+ * the Cypress chip is a mess, it contains two ATA functions, but
+ * both channels are visible on the first one.
+ * simply ignore the second function for now, as the right
+ * solution (ignoring the second channel on the first function)
+ * doesn't work with the crappy ATA interrupt setup on the alpha.
+ */
+ if (pci_get_devid(dev) == ATA_CYPRESS_82C693 &&
+ pci_get_function(dev) == 0 &&
+ pci_get_subclass(dev) == PCIS_STORAGE_IDE) {
+ device_set_desc(dev, "Cypress 82C693 ATA controller");
+ ctlr->chipinit = ata_cypress_chipinit;
+ return 0;
+ }
+ return ENXIO;
+}
+
+static int
+ata_cypress_chipinit(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+
+ if (ata_default_interrupt(dev))
+ return ENXIO;
+
+ ctlr->setmode = ata_cypress_setmode;
+ return 0;
+}
+
+static void
+ata_cypress_setmode(struct ata_device *atadev, int mode)
+{
+ device_t parent = device_get_parent(atadev->channel->dev);
+ int error;
+
+/* XXX missing WDMA0+1 + PIO modes */
+ if (mode == ATA_WDMA2) {
+ error = ata_command(atadev, ATA_C_SETFEATURES, 0, mode,
+ ATA_C_F_SETXFER, ATA_WAIT_READY);
+ if (bootverbose)
+ ata_prtdev(atadev, "%s setting WDMA2 on Cypress chip\n",
+ error ? "failed" : "success");
+ if (!error) {
+ pci_write_config(parent, atadev->channel->unit?0x4e:0x4c,0x2020,2);
+ atadev->mode = mode;
+ return;
+ }
+ }
+ /* we could set PIO mode timings, but we assume the BIOS did that */
+}
+
+/*
+ * HighPoint chipset support functions
+ */
+int
+ata_highpoint_ident(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+ struct ata_chip_id *idx;
+ static struct ata_chip_id ids[] =
+ {{ ATA_HPT366, 0x05, HPT372, 0x00, ATA_UDMA6, "HighPoint HPT372" },
+ { ATA_HPT366, 0x03, HPT370, 0x00, ATA_UDMA5, "HighPoint HPT370" },
+ { ATA_HPT366, 0x02, HPT366, 0x00, ATA_UDMA4, "HighPoint HPT368" },
+ { ATA_HPT366, 0x00, HPT366, HPTOLD, ATA_UDMA4, "HighPoint HPT366" },
+ { ATA_HPT372, 0x01, HPT372, 0x00, ATA_UDMA6, "HighPoint HPT372" },
+ { ATA_HPT374, 0x07, HPT374, 0x00, ATA_UDMA6, "HighPoint HPT374" },
+ { 0, 0, 0, 0, 0, 0}};
+ char buffer[64];
+
+ if (!(idx = ata_match_chip(dev, ids)))
+ return ENXIO;
+
+ sprintf(buffer, "%s %s controller", idx->text, ata_mode2str(idx->max_dma));
+ device_set_desc_copy(dev, buffer);
+ ctlr->chip = idx;
+ ctlr->chipinit = ata_highpoint_chipinit;
+ return 0;
+}
+
+static int
+ata_highpoint_chipinit(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+ int rid = ATA_IRQ_RID;
+
+ if (!(ctlr->r_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
+ RF_SHAREABLE | RF_ACTIVE))) {
+ device_printf(dev, "unable to map interrupt\n");
+ return ENXIO;
+ }
+ if ((bus_setup_intr(dev, ctlr->r_irq, INTR_TYPE_BIO | INTR_ENTROPY,
+ ata_highpoint_intr, ctlr, &ctlr->handle))) {
+ device_printf(dev, "unable to setup interrupt\n");
+ return ENXIO;
+ }
+
+ if (ctlr->chip->cfg2 == HPTOLD) {
+ /* turn off interrupt prediction */
+ pci_write_config(dev, 0x51, (pci_read_config(dev, 0x51, 1) & ~0x80), 1);
+ }
+ else {
+ /* turn off interrupt prediction */
+ pci_write_config(dev, 0x51, (pci_read_config(dev, 0x51, 1) & ~0x03), 1);
+ pci_write_config(dev, 0x55, (pci_read_config(dev, 0x55, 1) & ~0x03), 1);
+
+ /* turn on interrupts */
+ pci_write_config(dev, 0x5a, (pci_read_config(dev, 0x5a, 1) & ~0x10), 1);
+
+ /* set clocks etc */
+ if (ctlr->chip->cfg1 < HPT372)
+ pci_write_config(dev, 0x5b, 0x22, 1);
+ else
+ pci_write_config(dev, 0x5b,
+ (pci_read_config(dev, 0x5b, 1) & 0x01) | 0x20, 1);
+ }
+ ctlr->setmode = ata_highpoint_setmode;
+ return 0;
+}
+
+static void
+ata_highpoint_intr(void *data)
+{
+ struct ata_pci_controller *ctlr = data;
+ struct ata_channel *ch;
+ u_int8_t dmastat;
+ int unit;
+
+ /* implement this as a toggle instead to balance load XXX */
+ for (unit = 0; unit < 2; unit++) {
+ if (!(ch = ctlr->interrupt[unit].argument))
+ continue;
+ 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);
+ DELAY(1);
+ ctlr->interrupt[unit].function(ch);
+ }
+}
+
+static void
+ata_highpoint_setmode(struct ata_device *atadev, int mode)
+{
+ device_t parent = device_get_parent(atadev->channel->dev);
+ struct ata_pci_controller *ctlr = device_get_softc(parent);
+ int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit);
+ int error;
+ u_int32_t timings33[][4] = {
+ /* HPT366 HPT370 HPT372 HPT374 mode */
+ { 0x40d0a7aa, 0x06914e57, 0x0d029d5e, 0x0ac1f48a }, /* PIO 0 */
+ { 0x40d0a7a3, 0x06914e43, 0x0d029d26, 0x0ac1f465 }, /* PIO 1 */
+ { 0x40d0a753, 0x06514e33, 0x0c829ca6, 0x0a81f454 }, /* PIO 2 */
+ { 0x40c8a742, 0x06514e22, 0x0c829c84, 0x0a81f443 }, /* PIO 3 */
+ { 0x40c8a731, 0x06514e21, 0x0c829c62, 0x0a81f442 }, /* PIO 4 */
+ { 0x20c8a797, 0x26514e97, 0x2c82922e, 0x228082ea }, /* MWDMA 0 */
+ { 0x20c8a732, 0x26514e33, 0x2c829266, 0x22808254 }, /* MWDMA 1 */
+ { 0x20c8a731, 0x26514e21, 0x2c829262, 0x22808242 }, /* MWDMA 2 */
+ { 0x10c8a731, 0x16514e31, 0x1c82dc62, 0x121882ea }, /* UDMA 0 */
+ { 0x10cba731, 0x164d4e31, 0x1c9adc62, 0x12148254 }, /* UDMA 1 */
+ { 0x10caa731, 0x16494e31, 0x1c91dc62, 0x120c8242 }, /* UDMA 2 */
+ { 0x10cfa731, 0x166d4e31, 0x1c8edc62, 0x128c8242 }, /* UDMA 3 */
+ { 0x10c9a731, 0x16454e31, 0x1c8ddc62, 0x12ac8242 }, /* UDMA 4 */
+ { 0, 0x16454e31, 0x1c6ddc62, 0x12848242 }, /* UDMA 5 */
+ { 0, 0, 0x1c81dc62, 0x12808242 } /* UDMA 6 */
+ };
+
+ mode = ata_limit_mode(atadev, mode, ctlr->chip->max_dma);
+
+ if (ctlr->chip->cfg1 == HPT366)
+ mode = ata_limit_mode(atadev, mode,
+ ATAPI_DEVICE(atadev) ? ATA_PIO_MAX : ATA_UDMA4);
+
+ mode = ata_highpoint_check_80pin(atadev, mode);
+
+ error = ata_command(atadev, ATA_C_SETFEATURES, 0, mode,
+ ATA_C_F_SETXFER, ATA_WAIT_READY);
+ if (bootverbose)
+ ata_prtdev(atadev, "%s setting %s on HighPoint chip\n",
+ (error) ? "failed" : "success", ata_mode2str(mode));
+ if (!error)
+ pci_write_config(parent, 0x40 + (devno << 2),
+ timings33[ata_mode2idx(mode)][ctlr->chip->cfg1], 4);
+ atadev->mode = mode;
+}
+
+static int
+ata_highpoint_check_80pin(struct ata_device *atadev, int mode)
+{
+ device_t parent = device_get_parent(atadev->channel->dev);
+ struct ata_pci_controller *ctlr = device_get_softc(parent);
+ u_int8_t reg, val, res;
+
+ if (ctlr->chip->cfg1 == HPT374 && pci_get_function(parent) == 1) {
+ reg = atadev->channel->unit ? 0x57 : 0x53;
+ val = pci_read_config(parent, reg, 1);
+ pci_write_config(parent, reg, val | 0x80, 1);
+ }
+ else {
+ reg = 0x5b;
+ val = pci_read_config(parent, reg, 1);
+ pci_write_config(parent, reg, val & 0xfe, 1);
+ }
+ res = pci_read_config(parent, 0x5a, 1) & (atadev->channel->unit ? 0x1:0x2);
+ pci_write_config(parent, reg, val, 1);
+
+ if (mode > ATA_UDMA2 && res) {
+ ata_prtdev(atadev,"DMA limited to UDMA33, non-ATA66 cable or device\n");
+ mode = ATA_UDMA2;
+ }
+ return mode;
+}
+
+/*
+ * Intel chipset support functions
+ */
+int
+ata_intel_ident(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+ struct ata_chip_id *idx;
+ static struct ata_chip_id ids[] =
+ {{ ATA_I82371FB, 0, 0, 0x00, ATA_WDMA2, "Intel PIIX" },
+ { ATA_I82371SB, 0, 0, 0x00, ATA_WDMA2, "Intel PIIX3" },
+ { ATA_I82371AB, 0, 0, 0x00, ATA_UDMA2, "Intel PIIX4" },
+ { ATA_I82443MX, 0, 0, 0x00, ATA_UDMA2, "Intel PIIX4" },
+ { ATA_I82451NX, 0, 0, 0x00, ATA_UDMA2, "Intel PIIX4" },
+ { ATA_I82801AB, 0, 0, 0x00, ATA_UDMA2, "Intel ICH0" },
+ { ATA_I82801AA, 0, 0, 0x00, ATA_UDMA4, "Intel ICH" },
+ { ATA_I82372FB, 0, 0, 0x00, ATA_UDMA4, "Intel ICH" },
+ { ATA_I82801BA, 0, 0, 0x00, ATA_UDMA5, "Intel ICH2" },
+ { ATA_I82801BA_1, 0, 0, 0x00, ATA_UDMA5, "Intel ICH2" },
+ { ATA_I82801CA, 0, 0, 0x00, ATA_UDMA5, "Intel ICH3" },
+ { ATA_I82801CA_1, 0, 0, 0x00, ATA_UDMA5, "Intel ICH3" },
+ { ATA_I82801DB, 0, 0, 0x00, ATA_UDMA5, "Intel ICH4" },
+ { 0, 0, 0, 0, 0, 0}};
+ char buffer[64];
+
+ if (!(idx = ata_match_chip(dev, ids)))
+ return ENXIO;
+
+ sprintf(buffer, "%s %s controller", idx->text, ata_mode2str(idx->max_dma));
+ device_set_desc_copy(dev, buffer);
+ ctlr->chip = idx;
+ ctlr->chipinit = ata_intel_chipinit;
+ return 0;
+}
+
+static int
+ata_intel_chipinit(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+
+ if (ata_default_interrupt(dev))
+ return ENXIO;
+
+ if (ctlr->chip->chiptype == ATA_I82371FB)
+ ctlr->setmode = ata_intel_old_setmode;
+ else
+ ctlr->setmode = ata_intel_new_setmode;
+ return 0;
+}
+
+static void
+ata_intel_old_setmode(struct ata_device *atadev, int mode)
+{
+ /* NOT YET */
+}
+
+static void
+ata_intel_new_setmode(struct ata_device *atadev, int mode)
+{
+ device_t parent = device_get_parent(atadev->channel->dev);
+ struct ata_pci_controller *ctlr = device_get_softc(parent);
+ int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit);
+ u_int32_t reg40 = pci_read_config(parent, 0x40, 4);
+ u_int8_t reg44 = pci_read_config(parent, 0x44, 1);
+ u_int8_t reg48 = pci_read_config(parent, 0x48, 1);
+ u_int16_t reg4a = pci_read_config(parent, 0x4a, 2);
+ u_int16_t reg54 = pci_read_config(parent, 0x54, 2);
+ u_int32_t mask40 = 0, new40 = 0;
+ u_int8_t mask44 = 0, new44 = 0;
+ int error;
+ u_int8_t timings[] = { 0x00, 0x00, 0x10, 0x21, 0x23, 0x10, 0x21, 0x23,
+ 0x23, 0x23, 0x23, 0x23, 0x23, 0x23 };
+
+ mode = ata_limit_mode(atadev, mode, ctlr->chip->max_dma);
+
+ if (ctlr->chip->max_dma && mode > ATA_UDMA2 && !(reg54 & (0x10 << devno))) {
+ ata_prtdev(atadev,"DMA limited to UDMA33, non-ATA66 cable or device\n");
+ mode = ATA_UDMA2;
+ }
+
+ error = ata_command(atadev, ATA_C_SETFEATURES, 0, mode,
+ ATA_C_F_SETXFER, ATA_WAIT_READY);
+ if (bootverbose)
+ ata_prtdev(atadev, "%s setting %s on %s chip\n",
+ (error) ? "failed" : "success",
+ ata_mode2str(mode), ctlr->chip->text);
+ if (!error) {
+ if (mode >= ATA_UDMA0) {
+ pci_write_config(parent, 0x48, reg48 | (0x0001 << devno), 2);
+ pci_write_config(parent, 0x4a, (reg4a & ~(0x3 << (devno<<2))) |
+ (0x01 + !(mode & 0x01)), 2);
+ }
+ else {
+ pci_write_config(parent, 0x48, reg48 & ~(0x0001 << devno), 2);
+ pci_write_config(parent, 0x4a, (reg4a & ~(0x3 << (devno << 2))), 2);
+ }
+ if (mode >= ATA_UDMA2)
+ pci_write_config(parent, 0x54, reg54 | (0x1 << devno), 2);
+ else
+ pci_write_config(parent, 0x54, reg54 & ~(0x1 << devno), 2);
+
+ if (mode >= ATA_UDMA5)
+ pci_write_config(parent, 0x54, reg54 | (0x10000 << devno), 2);
+ else
+ pci_write_config(parent, 0x54, reg54 & ~(0x10000 << devno), 2);
+
+ reg40 &= ~0x00ff00ff;
+ reg40 |= 0x40774077;
+
+ if (atadev->unit == ATA_MASTER) {
+ mask40 = 0x3300;
+ new40 = timings[ata_mode2idx(mode)] << 8;
+ }
+ else {
+ mask44 = 0x0f;
+ new44 = ((timings[ata_mode2idx(mode)] & 0x30) >> 2) |
+ (timings[ata_mode2idx(mode)] & 0x03);
+ }
+ if (atadev->channel->unit) {
+ mask40 <<= 16;
+ new40 <<= 16;
+ mask44 <<= 4;
+ new44 <<= 4;
+ }
+ pci_write_config(parent, 0x40, (reg40 & ~mask40) | new40, 4);
+ pci_write_config(parent, 0x44, (reg44 & ~mask44) | new44, 1);
+ atadev->mode = mode;
+ }
+}
+
+/*
+ * nVidia chipset support functions
+ */
+int
+ata_nvidia_ident(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+ struct ata_chip_id *idx;
+ static struct ata_chip_id ids[] =
+ {{ ATA_NFORCE1, 0, AMDNVIDIA, NVIDIA|AMDBUG, ATA_UDMA5, "nVidia nForce" },
+ { ATA_NFORCE2, 0, AMDNVIDIA, NVIDIA|AMDBUG, ATA_UDMA6, "nVidia nForce2" },
+ { 0, 0, 0, 0, 0, 0}};
+ char buffer[64];
+
+ if (!(idx = ata_match_chip(dev, ids)))
+ return ENXIO;
+
+ sprintf(buffer, "%s %s controller", idx->text, ata_mode2str(idx->max_dma));
+ device_set_desc_copy(dev, buffer);
+ ctlr->chip = idx;
+ ctlr->chipinit = ata_nvidia_chipinit;
+ return 0;
+}
+
+static int
+ata_nvidia_chipinit(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+
+ if (ata_default_interrupt(dev))
+ return ENXIO;
+
+ /* set prefetch, postwrite */
+ if (ctlr->chip->cfg2 & AMDBUG)
+ pci_write_config(dev, 0x51, pci_read_config(dev, 0x51, 1) & 0x0f, 1);
+ else
+ pci_write_config(dev, 0x51, pci_read_config(dev, 0x51, 1) | 0xf0, 1);
+
+ ctlr->setmode = ata_via_family_setmode;
+ return 0;
+}
+
+/*
+ * Promise chipset support functions
+ */
+int
+ata_promise_ident(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+ struct ata_chip_id *idx;
+ static struct ata_chip_id ids[] =
+ {{ ATA_PDC20246, 0, PROLD, 0x00, ATA_UDMA2, "Promise" },
+ { ATA_PDC20262, 0, PRNEW, 0x00, ATA_UDMA4, "Promise" },
+ { ATA_PDC20263, 0, PRNEW, 0x00, ATA_UDMA4, "Promise" },
+ { ATA_PDC20265, 0, PRNEW, 0x00, ATA_UDMA5, "Promise" },
+ { ATA_PDC20267, 0, PRNEW, 0x00, ATA_UDMA5, "Promise" },
+ { ATA_PDC20268, 0, PRTX2, PRTX4, ATA_UDMA5, "Promise TX2" },
+ { ATA_PDC20268R, 0, PRTX2, PRTX4, ATA_UDMA5, "Promise TX2" },
+ { ATA_PDC20269, 0, PRTX2, 0x00, ATA_UDMA6, "Promise TX2" },
+ { ATA_PDC20271, 0, PRTX2, 0x00, ATA_UDMA6, "Promise TX2" },
+ { ATA_PDC20275, 0, PRTX2, 0x00, ATA_UDMA6, "Promise TX2" },
+ { ATA_PDC20276, 0, PRTX2, PRSX6K, ATA_UDMA6, "Promise TX2" },
+ { ATA_PDC20277, 0, PRTX2, 0x00, ATA_UDMA6, "Promise TX2" },
+ { ATA_PDC20376, 0, PRTX2, 0x00, ATA_UDMA6, "Promise SATA" },
+ { 0, 0, 0, 0, 0, 0}};
+ char *desc, buffer[64];
+ uintptr_t devid = 0;
+
+ if (!(idx = ata_match_chip(dev, ids)))
+ return ENXIO;
+
+ /* if we are on a SuperTrak SX6000 dont attach */
+ if (idx->cfg2 & PRSX6K &&
+ !BUS_READ_IVAR(device_get_parent(GRANDPARENT(dev)),
+ GRANDPARENT(dev), PCI_IVAR_DEVID, &devid) &&
+ devid == ATA_I960RM && pci_get_class(GRANDPARENT(dev)) == PCIC_BRIDGE)
+ return ENXIO;
+
+ if (idx->cfg2 & PRTX4 &&
+ !BUS_READ_IVAR(device_get_parent(GRANDPARENT(dev)),
+ GRANDPARENT(dev), PCI_IVAR_DEVID, &devid) &&
+ devid == ATA_DEC_21150 &&
+ pci_get_class(GRANDPARENT(dev)) == PCIC_BRIDGE) {
+ static long start = 0, end = 0;
+
+ /* we belive we are on a TX4, now do our (simple) magic */
+ if (pci_get_slot(dev) == 1) {
+ bus_get_resource(dev, SYS_RES_IRQ, 0, &start, &end);
+ desc = "Promise TX4 (channel 0+1)";
+ }
+ else if (pci_get_slot(dev) == 2 && start && end) {
+ bus_set_resource(dev, SYS_RES_IRQ, 0, start, end);
+ start = end = 0;
+ desc = "Promise TX4 (channel 2+3)";
+ }
+ else {
+ start = end = 0;
+ desc = "Promise TX2";
+ }
+ }
+ else
+ desc = idx->text;
+ sprintf(buffer, "%s %s controller", desc, ata_mode2str(idx->max_dma));
+ device_set_desc_copy(dev, buffer);
+ ctlr->chip = idx;
+ ctlr->chipinit = ata_promise_chipinit;
+ return 0;
+}
+
+static int
+ata_promise_chipinit(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+ int rid = ATA_IRQ_RID;
+
+ if (!(ctlr->r_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
+ RF_SHAREABLE | RF_ACTIVE))) {
+ 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 == PRTX2 ?
+ ata_promise_tx2_intr : ata_promise_intr,
+ ctlr, &ctlr->handle))) {
+ device_printf(dev, "unable to setup interrupt\n");
+ return ENXIO;
+ }
+ ctlr->setmode = ata_promise_setmode;
+ if (ctlr->chip->cfg1 == PRNEW )
+ ctlr->dmainit = ata_promise_dmainit;
+ return 0;
+}
+
+static void
+ata_promise_intr(void *data)
+{
+ struct ata_pci_controller *ctlr = data;
+ struct ata_channel *ch = ctlr->interrupt[0].argument;
+ u_int8_t dmastat;
+ int unit;
+
+ /* implement this as a toggle instead to balance load XXX */
+ 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 (!((dmastat = ch->dma->status(ch)) & ATA_BMSTAT_INTERRUPT))
+ continue;
+ ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT,
+ dmastat | ATA_BMSTAT_INTERRUPT);
+ DELAY(1);
+ }
+ ctlr->interrupt[unit].function(ch);
+ }
+ }
+}
+
+static void
+ata_promise_tx2_intr(void *data)
+{
+ struct ata_pci_controller *ctlr = data;
+ struct ata_channel *ch;
+ u_int8_t dmastat;
+ int unit;
+
+ /* implement this as a toggle instead to balance load XXX */
+ 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) {
+ if (!((dmastat = ch->dma->status(ch)) & ATA_BMSTAT_INTERRUPT))
+ continue;
+ ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT,
+ dmastat | ATA_BMSTAT_INTERRUPT);
+ DELAY(1);
+ }
+ ctlr->interrupt[unit].function(ch);
+ }
+ }
+}
+
+static void
+ata_promise_setmode(struct ata_device *atadev, int mode)
+{
+ device_t parent = device_get_parent(atadev->channel->dev);
+ struct ata_pci_controller *ctlr = device_get_softc(parent);
+ int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit);
+ int error;
+ u_int32_t timings33[][2] = {
+ /* PROLD PRNEW mode */
+ { 0x004ff329, 0x004fff2f }, /* PIO 0 */
+ { 0x004fec25, 0x004ff82a }, /* PIO 1 */
+ { 0x004fe823, 0x004ff026 }, /* PIO 2 */
+ { 0x004fe622, 0x004fec24 }, /* PIO 3 */
+ { 0x004fe421, 0x004fe822 }, /* PIO 4 */
+ { 0x004567f3, 0x004acef6 }, /* MWDMA 0 */
+ { 0x004467f3, 0x0048cef6 }, /* MWDMA 1 */
+ { 0x004367f3, 0x0046cef6 }, /* MWDMA 2 */
+ { 0x004367f3, 0x0046cef6 }, /* UDMA 0 */
+ { 0x004247f3, 0x00448ef6 }, /* UDMA 1 */
+ { 0x004127f3, 0x00436ef6 }, /* UDMA 2 */
+ { 0, 0x00424ef6 }, /* UDMA 3 */
+ { 0, 0x004127f3 }, /* UDMA 4 */
+ { 0, 0x004127f3 } /* UDMA 5 */
+ };
+
+ mode = ata_limit_mode(atadev, mode, ctlr->chip->max_dma);
+
+ /* is this a TX2 or later chip ? */
+ if (ctlr->chip->cfg1 >= PRTX2) {
+ ATA_OUTB(atadev->channel->r_bmio, ATA_BMDEVSPEC_0, 0x0b);
+ if (mode > ATA_UDMA2 &&
+ ATA_INB(atadev->channel->r_bmio, ATA_BMDEVSPEC_1) & 0x04) {
+ ata_prtdev(atadev,
+ "DMA limited to UDMA33, non-ATA66 cable or device\n");
+ mode = ATA_UDMA2;
+ }
+ }
+ else {
+ if (mode > ATA_UDMA2 && (pci_read_config(parent, 0x50, 2) &
+ (atadev->channel->unit ? 1 << 11 : 1 << 10))) {
+ ata_prtdev(atadev,
+ "DMA limited to UDMA33, non-ATA66 cable or device\n");
+ mode = ATA_UDMA2;
+ }
+ if (!ATAPI_DEVICE(atadev) && mode > ATA_PIO_MAX)
+ mode = ata_limit_mode(atadev, mode, ATA_PIO_MAX);
+ }
+
+ error = ata_command(atadev, ATA_C_SETFEATURES, 0, mode,
+ ATA_C_F_SETXFER, ATA_WAIT_READY);
+ if (bootverbose)
+ ata_prtdev(atadev, "%s setting %s on %s chip\n",
+ (error) ? "failed" : "success",
+ ata_mode2str(mode), ctlr->chip->text);
+ if (!error) {
+ if (ctlr->chip->cfg1 < PRTX2)
+ pci_write_config(device_get_parent(atadev->channel->dev),
+ 0x60 + (devno << 2),
+ timings33[ctlr->chip->cfg1][ata_mode2idx(mode)],4);
+ atadev->mode = mode;
+ }
+ return;
+}
+
+static int
+ata_promise_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;
+ return 0;
+}
+
+static int
+ata_promise_dmastart(struct ata_device *atadev,
+ caddr_t data, int32_t count, int dir)
+{
+ struct ata_channel *ch = atadev->channel;
+ int error;
+
+ if ((error = ata_dmastart(atadev, 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),
+ (dir ? 0x05000000 : 0x06000000) | (count >> 1));
+ }
+ return 0;
+}
+
+static int
+ata_promise_dmastop(struct ata_device *atadev)
+{
+ struct ata_channel *ch = atadev->channel;
+
+ 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);
+ }
+ return ata_dmastop(atadev);
+}
+
+/*
+ * ServerWorks chipset support functions
+ */
+int
+ata_serverworks_ident(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+ struct ata_chip_id *idx;
+ static struct ata_chip_id ids[] =
+ {{ ATA_ROSB4, 0x00, SWKS33, 0x00, ATA_UDMA2, "ServerWorks ROSB4" },
+ { ATA_CSB5, 0x92, SWKS100, 0x00, ATA_UDMA5, "ServerWorks CSB5" },
+ { ATA_CSB5, 0x00, SWKS66, 0x00, ATA_UDMA4, "ServerWorks CSB5" },
+ { ATA_CSB6, 0x00, SWKS100, 0x00, ATA_UDMA5, "ServerWorks CSB6" },
+ { ATA_CSB6_1, 0x00, SWKS66, 0x00, ATA_UDMA4, "ServerWorks CSB6" },
+ { 0, 0, 0, 0, 0, 0}};
+ char buffer[64];
+
+ if (!(idx = ata_match_chip(dev, ids)))
+ return ENXIO;
+
+ sprintf(buffer, "%s %s controller", idx->text, ata_mode2str(idx->max_dma));
+ device_set_desc_copy(dev, buffer);
+ ctlr->chip = idx;
+ ctlr->chipinit = ata_serverworks_chipinit;
+ return 0;
+}
+
+static int
+ata_serverworks_chipinit(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+
+ if (ata_default_interrupt(dev))
+ return ENXIO;
+
+ if (ctlr->chip->cfg1 > SWKS33)
+ pci_write_config(dev, 0x5a,
+ (pci_read_config(dev, 0x5a, 1) & ~0x40) |
+ (ctlr->chip->cfg1 == SWKS100) ? 0x03 : 0x02, 1);
+ else
+ pci_write_config(dev, 0x64,
+ (pci_read_config(dev, 0x64, 4) & ~0x00002000) |
+ 0x00004000, 4);
+ ctlr->setmode = ata_serverworks_setmode;
+ return 0;
+}
+
+static void
+ata_serverworks_setmode(struct ata_device *atadev, int mode)
+{
+ device_t parent = device_get_parent(atadev->channel->dev);
+ struct ata_pci_controller *ctlr = device_get_softc(parent);
+ int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit);
+ int offset = devno ^ 0x01;
+ int error;
+ u_int8_t timings[] = { 0x5d, 0x47, 0x34, 0x22, 0x20, 0x34, 0x22, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };
+
+ mode = ata_limit_mode(atadev, mode, ctlr->chip->max_dma);
+
+ mode = ata_check_80pin(atadev, mode);
+
+ error = ata_command(atadev, ATA_C_SETFEATURES, 0, mode,
+ ATA_C_F_SETXFER, ATA_WAIT_READY);
+ if (bootverbose)
+ ata_prtdev(atadev, "%s setting %s on %s chip\n",
+ (error) ? "failed" : "success",
+ ata_mode2str(mode), ctlr->chip->text);
+ if (!error) {
+ if (mode >= ATA_UDMA0) {
+ pci_write_config(parent, 0x54, pci_read_config(parent, 0x54, 1) |
+ (0x01 << devno), 1);
+ pci_write_config(parent, 0x56,
+ (pci_read_config(parent, 0x56, 2) &
+ ~(0xf << (devno << 2))) |
+ ((mode & ATA_MODE_MASK) << (devno << 2)), 2);
+ }
+ else
+ pci_write_config(parent, 0x54, pci_read_config(parent, 0x54, 1) |
+ ~(0x01 << devno), 1);
+
+ pci_write_config(parent, 0x54, pci_read_config(parent, 0x54, 1) &
+ ~(0x01 << devno), 1);
+ pci_write_config(parent, 0x44,
+ (pci_read_config(parent, 0x44, 4) &
+ ~(0xff << (offset << 8))) |
+ (timings[ata_mode2idx(mode)] << (offset << 8)), 4);
+ atadev->mode = mode;
+ }
+}
+
+/*
+ * Silicon Image (former CMD) chipset support functions
+ */
+int
+ata_sii_ident(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+ struct ata_chip_id *idx;
+ static struct ata_chip_id ids[] =
+ {{ ATA_SII0680, 0x00, SII_SETCLK, 0x00, ATA_UDMA6, "SiI 0680" },
+ { ATA_CMD649, 0x00, 0, SII_INTR, ATA_UDMA5, "CMD 649" },
+ { ATA_CMD648, 0x00, 0, SII_INTR, ATA_UDMA4, "CMD 648" },
+ { ATA_CMD646, 0x07, 0, 0x00, ATA_UDMA2, "CMD 646U2" },
+ { ATA_CMD646, 0x00, 0, 0x00, ATA_WDMA2, "CMD 646" },
+ { 0, 0, 0, 0, 0, 0}};
+ char buffer[64];
+
+ if (!(idx = ata_match_chip(dev, ids)))
+ return ENXIO;
+
+ sprintf(buffer, "%s %s controller", idx->text, ata_mode2str(idx->max_dma));
+ device_set_desc_copy(dev, buffer);
+ ctlr->chip = idx;
+ ctlr->chipinit = ata_sii_chipinit;
+ return 0;
+}
+
+static int
+ata_sii_chipinit(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+ int rid = ATA_IRQ_RID;
+
+ if (!(ctlr->r_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
+ RF_SHAREABLE | RF_ACTIVE))) {
+ 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->cfg2 & SII_INTR ?
+ ata_cmd_intr : ata_generic_intr,
+ ctlr, &ctlr->handle))) {
+ device_printf(dev, "unable to setup interrupt\n");
+ return ENXIO;
+ }
+
+ if (ctlr->chip->cfg1 == SII_SETCLK) {
+ if ((pci_read_config(dev, 0x8a, 1) & 0x30) != 0x10)
+ pci_write_config(dev, 0x8a,
+ (pci_read_config(dev, 0x8a, 1) & 0x0F) | 0x10, 1);
+ if ((pci_read_config(dev, 0x8a, 1) & 0x30) != 0x10)
+ device_printf(dev, "%s could not set ATA133 clock\n",
+ ctlr->chip->text);
+ ctlr->setmode = ata_sii_setmode;
+ }
+ else
+ ctlr->setmode = ata_cmd_setmode;
+ return 0;
+}
+
+static void
+ata_cmd_intr(void *data)
+{
+ struct ata_pci_controller *ctlr = data;
+ struct ata_channel *ch;
+ u_int8_t dmastat;
+ int unit;
+
+ /* implement this as a toggle instead to balance load XXX */
+ for (unit = 0; unit < 2; unit++) {
+ if (!(ch = ctlr->interrupt[unit].argument))
+ continue;
+ if (!(pci_read_config(device_get_parent(ch->dev), 0x71, 1) &
+ (ch->unit ? 0x08 : 0x04)))
+ continue;
+ pci_write_config(device_get_parent(ch->dev), 0x71,
+ (ch->unit ? 0x08 : 0x04), 1);
+ if (ch->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);
+ DELAY(1);
+ }
+ ctlr->interrupt[unit].function(ch);
+ }
+}
+
+static void
+ata_sii_setmode(struct ata_device *atadev, int mode)
+{
+ device_t parent = device_get_parent(atadev->channel->dev);
+ struct ata_pci_controller *ctlr = device_get_softc(parent);
+ int devno = (atadev->channel->unit << 4) + (ATA_DEV(atadev->unit) << 1);
+ int mreg = atadev->channel->unit ? 0x84 : 0x80;
+ int mask = 0x03 << (ATA_DEV(atadev->unit) << 2);
+ int mval = pci_read_config(parent, mreg, 1) & ~mask;
+ int error;
+
+ mode = ata_limit_mode(atadev, mode, ctlr->chip->max_dma);
+
+ mode = ata_check_80pin(atadev, mode);
+
+ error = ata_command(atadev, ATA_C_SETFEATURES, 0, mode,
+ ATA_C_F_SETXFER, ATA_WAIT_READY);
+ if (bootverbose)
+ ata_prtdev(atadev, "%s setting %s on %s chip\n",
+ (error) ? "failed" : "success",
+ ata_mode2str(mode), ctlr->chip->text);
+ if (!error) {
+ if (mode >= ATA_UDMA0) {
+ u_int8_t udmatimings[] = { 0xf, 0xb, 0x7, 0x5, 0x3, 0x2, 0x1 };
+ u_int8_t ureg = 0xac + devno;
+
+ pci_write_config(parent, mreg,
+ mval | (0x03 << (ATA_DEV(atadev->unit) << 2)), 1);
+ pci_write_config(parent, ureg,
+ (pci_read_config(parent, ureg, 1) & 0x3f) |
+ udmatimings[mode & ATA_MODE_MASK], 1);
+
+ }
+ else if (mode >= ATA_WDMA0) {
+ u_int8_t dreg = 0xa8 + devno;
+ u_int16_t dmatimings[] = { 0x2208, 0x10c2, 0x10c1 };
+
+ pci_write_config(parent, mreg,
+ mval | (0x02 << (ATA_DEV(atadev->unit) << 2)), 1);
+ pci_write_config(parent, dreg, dmatimings[mode & ATA_MODE_MASK], 2);
+
+ }
+ else {
+ u_int8_t preg = 0xa4 + devno;
+ u_int16_t piotimings[] = { 0x328a, 0x2283, 0x1104, 0x10c3, 0x10c1 };
+
+ pci_write_config(parent, mreg,
+ mval | (0x01 << (ATA_DEV(atadev->unit) << 2)), 1);
+ pci_write_config(parent, preg, piotimings[mode & ATA_MODE_MASK], 2);
+ }
+ atadev->mode = mode;
+ }
+}
+
+static void
+ata_cmd_setmode(struct ata_device *atadev, int mode)
+{
+ device_t parent = device_get_parent(atadev->channel->dev);
+ struct ata_pci_controller *ctlr = device_get_softc(parent);
+ int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit);
+ int error;
+
+ mode = ata_limit_mode(atadev, mode, ctlr->chip->max_dma);
+
+ mode = ata_check_80pin(atadev, mode);
+
+ error = ata_command(atadev, ATA_C_SETFEATURES, 0, mode,
+ ATA_C_F_SETXFER, ATA_WAIT_READY);
+ if (bootverbose)
+ ata_prtdev(atadev, "%s setting %s on %s chip\n",
+ (error) ? "failed" : "success",
+ ata_mode2str(mode), ctlr->chip->text);
+ if (!error) {
+ int treg = 0x54 + (devno < 3) ? (devno << 1) : 7;
+ int ureg = atadev->channel->unit ? 0x7b : 0x73;
+
+ if (mode >= ATA_UDMA0) {
+ int udmatimings[][2] = { { 0x31, 0xc2 }, { 0x21, 0x82 },
+ { 0x11, 0x42 }, { 0x25, 0x8a },
+ { 0x15, 0x4a }, { 0x05, 0x0a } };
+
+ u_int8_t umode = pci_read_config(parent, ureg, 1);
+
+ umode &= ~(atadev->unit == ATA_MASTER ? 0x35 : 0xca);
+ umode |= udmatimings[ATA_DEV(atadev->unit)][mode & ATA_MODE_MASK];
+ pci_write_config(parent, ureg, umode, 1);
+ }
+ else if (mode >= ATA_WDMA0) {
+ int dmatimings[] = { 0x87, 0x32, 0x3f };
+
+ pci_write_config(parent, treg, dmatimings[mode & ATA_MODE_MASK], 1);
+ pci_write_config(parent, ureg,
+ pci_read_config(parent, ureg, 1) &
+ ~(atadev->unit == ATA_MASTER ? 0x35 : 0xca), 1);
+ }
+ else {
+ int piotimings[] = { 0xa9, 0x57, 0x44, 0x32, 0x3f };
+ pci_write_config(parent, treg,
+ piotimings[(mode & ATA_MODE_MASK) - ATA_PIO0], 1);
+ pci_write_config(parent, ureg,
+ pci_read_config(parent, ureg, 1) &
+ ~(atadev->unit == ATA_MASTER ? 0x35 : 0xca), 1);
+ }
+ atadev->mode = mode;
+ }
+}
+
+/*
+ * SiS chipset support functions
+ */
+int
+ata_sis_ident(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+ struct ata_chip_id *idx;
+ static struct ata_chip_id ids[] =
+ {{ ATA_SIS963, 0x00, SIS133NEW, 0, ATA_UDMA6, "SiS 963" }, /* south */
+ { ATA_SIS962, 0x00, SIS133NEW, 0, ATA_UDMA6, "SiS 962" }, /* south */
+
+ { ATA_SIS755, 0x00, SIS_SOUTH, 0, ATA_UDMA6, "SiS 755" }, /* ext south */
+ { ATA_SIS752, 0x00, SIS_SOUTH, 0, ATA_UDMA6, "SiS 752" }, /* unknown */
+ { ATA_SIS751, 0x00, SIS_SOUTH, 0, ATA_UDMA6, "SiS 751" }, /* unknown */
+ { ATA_SIS750, 0x00, SIS_SOUTH, 0, ATA_UDMA6, "SiS 750" }, /* unknown */
+ { ATA_SIS748, 0x00, SIS_SOUTH, 0, ATA_UDMA6, "SiS 748" }, /* unknown */
+ { ATA_SIS746, 0x00, SIS_SOUTH, 0, ATA_UDMA6, "SiS 746" }, /* ext south */
+ { ATA_SIS745, 0x00, SIS100NEW, 0, ATA_UDMA5, "SiS 745" }, /* 1chip */
+ { ATA_SIS740, 0x00, SIS_SOUTH, 0, ATA_UDMA5, "SiS 740" }, /* ext south */
+ { ATA_SIS735, 0x00, SIS100NEW, 0, ATA_UDMA5, "SiS 735" }, /* 1chip */
+ { ATA_SIS733, 0x00, SIS100NEW, 0, ATA_UDMA5, "SiS 733" }, /* 1chip */
+ { ATA_SIS730, 0x00, SIS100OLD, 0, ATA_UDMA5, "SiS 730" }, /* 1chip */
+
+ { ATA_SIS658, 0x00, SIS_SOUTH, 0, ATA_UDMA6, "SiS 658" }, /* ext south */
+ { ATA_SIS655, 0x00, SIS_SOUTH, 0, ATA_UDMA6, "SiS 655" }, /* ext south */
+ { ATA_SIS652, 0x00, SIS_SOUTH, 0, ATA_UDMA6, "SiS 652" }, /* unknown */
+ { ATA_SIS651, 0x00, SIS_SOUTH, 0, ATA_UDMA6, "SiS 651" }, /* ext south */
+ { ATA_SIS650, 0x00, SIS_SOUTH, 0, ATA_UDMA6, "SiS 650" }, /* ext south */
+ { ATA_SIS648, 0x00, SIS_SOUTH, 0, ATA_UDMA6, "SiS 648" }, /* ext south */
+ { ATA_SIS646, 0x00, SIS_SOUTH, 0, ATA_UDMA6, "SiS 645DX" },/* ext south */
+ { ATA_SIS645, 0x00, SIS_SOUTH, 0, ATA_UDMA6, "SiS 645" }, /* ext south */
+ { ATA_SIS640, 0x00, SIS_SOUTH, 0, ATA_UDMA4, "SiS 640" }, /* ext south */
+ { ATA_SIS635, 0x00, SIS100NEW, 0, ATA_UDMA5, "SiS 635" }, /* unknown */
+ { ATA_SIS633, 0x00, SIS100NEW, 0, ATA_UDMA5, "SiS 633" }, /* unknown */
+ { ATA_SIS630, 0x30, SIS100NEW, 0, ATA_UDMA5, "SiS 630S" }, /* 1chip */
+ { ATA_SIS630, 0x00, SIS66, 0, ATA_UDMA4, "SiS 630" }, /* 1chip */
+ { ATA_SIS620, 0x00, SIS66, 0, ATA_UDMA4, "SiS 620" }, /* 1chip */
+
+ { ATA_SIS550, 0x00, SIS66, 0, ATA_UDMA5, "SiS 550" },
+ { ATA_SIS540, 0x00, SIS66, 0, ATA_UDMA4, "SiS 540" },
+ { ATA_SIS530, 0x00, SIS66, 0, ATA_UDMA4, "SiS 530" },
+ { 0, 0, 0, 0, 0, 0 }};
+ char buffer[64];
+
+ if (!(idx = ata_match_chip(dev, ids)))
+ return ENXIO;
+
+ if (idx->cfg1 == SIS_SOUTH) {
+ pci_write_config(dev, 0x57, pci_read_config(dev, 0x57, 1) & 0x7f, 1);
+ if (pci_read_config(dev, 0x00, 4) == ATA_SIS5518) {
+ idx->cfg1 = SIS133NEW;
+ sprintf(buffer, "SiS 96X %s controller",ata_mode2str(idx->max_dma));
+ }
+ else {
+ if (ata_find_dev(dev, ATA_SISSOUTH, 0x10))
+ idx->cfg1 = SIS133OLD;
+ else {
+ idx->max_dma = ATA_UDMA5;
+ idx->cfg1 = SIS100NEW;
+ }
+ sprintf(buffer, "SiS 961 %s controller",ata_mode2str(idx->max_dma));
+ }
+ pci_write_config(dev, 0x57, pci_read_config(dev, 0x57, 1) | 0x80, 1);
+ }
+ else
+ sprintf(buffer,"%s %s controller",idx->text,ata_mode2str(idx->max_dma));
+ device_set_desc_copy(dev, buffer);
+ ctlr->chip = idx;
+ ctlr->chipinit = ata_sis_chipinit;
+ return 0;
+}
+
+static int
+ata_sis_chipinit(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+
+ if (ata_default_interrupt(dev))
+ return ENXIO;
+
+ switch (ctlr->chip->cfg1) {
+ case SIS66:
+ case SIS100OLD:
+ pci_write_config(dev, 0x52, pci_read_config(dev, 0x52, 1) | 0x04, 1);
+ break;
+ case SIS100NEW:
+ case SIS133OLD:
+ pci_write_config(dev, 0x49, pci_read_config(dev, 0x49, 1) | 0x01, 1);
+ break;
+ case SIS133NEW:
+ pci_write_config(dev, 0x50, pci_read_config(dev, 0x50, 2) & 0xfff7, 2);
+ pci_write_config(dev, 0x52, pci_read_config(dev, 0x52, 2) & 0xfff7, 2);
+ break;
+ default:
+ return ENXIO;
+ }
+ ctlr->setmode = ata_sis_setmode;
+ return 0;
+}
+
+static void
+ata_sis_setmode(struct ata_device *atadev, int mode)
+{
+ device_t parent = device_get_parent(atadev->channel->dev);
+ struct ata_pci_controller *ctlr = device_get_softc(parent);
+ int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit);
+ int error;
+
+ mode = ata_limit_mode(atadev, mode, ctlr->chip->max_dma);
+
+ if (ctlr->chip->cfg1 == SIS133NEW) {
+ if (mode > ATA_UDMA2 &&
+ pci_read_config(parent, atadev->channel->unit?0x52:0x50,2)&0x8000){
+ ata_prtdev(atadev,
+ "DMA limited to UDMA33, non-ATA66 cable or device\n");
+ mode = ATA_UDMA2;
+ }
+ }
+ else {
+ if (mode > ATA_UDMA2 &&
+ pci_read_config(parent, 0x48, 1) & atadev->channel->unit?0x20:0x10){
+ ata_prtdev(atadev,
+ "DMA limited to UDMA33, non-ATA66 cable or device\n");
+ mode = ATA_UDMA2;
+ }
+ }
+
+ error = ata_command(atadev, ATA_C_SETFEATURES, 0, mode,
+ ATA_C_F_SETXFER, ATA_WAIT_READY);
+ if (bootverbose)
+ ata_prtdev(atadev, "%s setting %s on %s chip\n",
+ (error) ? "failed" : "success",
+ ata_mode2str(mode), ctlr->chip->text);
+ if (!error) {
+ switch (ctlr->chip->cfg1) {
+ case SIS133NEW: {
+ u_int32_t timings[] =
+ { 0x28269008, 0x0c266008, 0x04263008, 0x0c0a3008, 0x05093008,
+ 0x22190608, 0x0c0a3008, 0x05093008, 0x050939fc, 0x050936ac,
+ 0x0509347c, 0x0509325c, 0x0509323c, 0x0509322c, 0x0509321c};
+ u_int32_t reg;
+
+ reg = (pci_read_config(parent, 0x57, 1)&0x40?0x70:0x40)+(devno<<2);
+ pci_write_config(parent, reg, timings[ata_mode2idx(mode)], 4);
+ break;
+ }
+ case SIS133OLD: {
+ u_int16_t timings[] =
+ { 0x00cb, 0x0067, 0x0044, 0x0033, 0x0031, 0x0044, 0x0033, 0x0031,
+ 0x8f31, 0x8a31, 0x8731, 0x8531, 0x8331, 0x8231, 0x8131 };
+
+ u_int16_t reg = 0x40 + (devno << 1);
+
+ pci_write_config(parent, reg, timings[ata_mode2idx(mode)], 2);
+ break;
+ }
+ case SIS100NEW: {
+ u_int16_t timings[] =
+ { 0x00cb, 0x0067, 0x0044, 0x0033, 0x0031, 0x0044, 0x0033,
+ 0x0031, 0x8b31, 0x8731, 0x8531, 0x8431, 0x8231, 0x8131 };
+ u_int16_t reg = 0x40 + (devno << 1);
+
+ pci_write_config(parent, reg, timings[ata_mode2idx(mode)], 2);
+ break;
+ }
+ case SIS100OLD:
+ case SIS66: {
+ u_int16_t timings[] =
+ { 0x0c0b, 0x0607, 0x0404, 0x0303, 0x0301, 0x0404, 0x0303,
+ 0x0301, 0xf301, 0xd301, 0xb301, 0xa301, 0x9301, 0x8301 };
+ u_int16_t reg = 0x40 + (devno << 1);
+
+ pci_write_config(parent, reg, timings[ata_mode2idx(mode)], 2);
+ break;
+ }
+ }
+ atadev->mode = mode;
+ }
+}
+
+/* VIA chipsets */
+int
+ata_via_ident(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+ struct ata_chip_id *idx;
+ static struct ata_chip_id ids[] =
+ {{ ATA_VIA82C586, 0x02, VIA33, 0x00, ATA_UDMA2, "VIA 82C586b" },
+ { ATA_VIA82C586, 0x00, VIA33, 0x00, ATA_WDMA2, "VIA 82C586" },
+ { ATA_VIA82C596, 0x12, VIA66, VIACLK, ATA_UDMA4, "VIA 82C596b" },
+ { ATA_VIA82C596, 0x00, VIA33, 0x00, ATA_UDMA2, "VIA 82C596" },
+ { ATA_VIA82C686, 0x40, VIA100, VIABUG, ATA_UDMA5, "VIA 82C686b"},
+ { ATA_VIA82C686, 0x10, VIA66, VIACLK, ATA_UDMA4, "VIA 82C686a" },
+ { ATA_VIA82C686, 0x00, VIA33, 0x00, ATA_UDMA2, "VIA 82C686" },
+ { ATA_VIA8231, 0x00, VIA100, VIABUG, ATA_UDMA5, "VIA 8231" },
+ { ATA_VIA8233, 0x00, VIA100, 0x00, ATA_UDMA5, "VIA 8233" },
+ { ATA_VIA8233C, 0x00, VIA100, 0x00, ATA_UDMA5, "VIA 8233c" },
+ { ATA_VIA8233A, 0x00, VIA133, 0x00, ATA_UDMA6, "VIA 8233a" },
+ { ATA_VIA8235, 0x00, VIA133, 0x00, ATA_UDMA6, "VIA 8235" },
+ { 0, 0, 0, 0, 0, 0 }};
+ char buffer[64];
+
+ if (!(idx = ata_match_chip(dev, ids)))
+ return ENXIO;
+
+ sprintf(buffer, "%s %s controller", idx->text, ata_mode2str(idx->max_dma));
+ device_set_desc_copy(dev, buffer);
+ ctlr->chip = idx;
+ ctlr->chipinit = ata_via_chipinit;
+ return 0;
+}
+
+static int
+ata_via_chipinit(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+
+ if (ata_default_interrupt(dev))
+ return ENXIO;
+
+ /* prepare for ATA-66 on the 82C686a and 82C596b */
+ if (ctlr->chip->cfg2 & VIACLK)
+ pci_write_config(dev, 0x50, 0x030b030b, 4);
+
+ /* the southbridge might need the data corruption fix */
+ if (ctlr->chip->cfg2 & VIABUG)
+ ata_via_southbridge_fixup(dev);
+
+ /* set prefetch, postwrite */
+ pci_write_config(dev, 0x41, pci_read_config(dev, 0x41, 1) | 0xf0, 1);
+
+ /* set fifo configuration half'n'half */
+ pci_write_config(dev, 0x43,
+ (pci_read_config(dev, 0x43, 1) & 0x90) | 0x2a, 1);
+
+ /* set status register read retry */
+ pci_write_config(dev, 0x44, pci_read_config(dev, 0x44, 1) | 0x08, 1);
+
+ /* set DMA read & end-of-sector fifo flush */
+ pci_write_config(dev, 0x46,
+ (pci_read_config(dev, 0x46, 1) & 0x0c) | 0xf0, 1);
+
+ /* set sector size */
+ pci_write_config(dev, 0x60, DEV_BSIZE, 2);
+ pci_write_config(dev, 0x68, DEV_BSIZE, 2);
+
+ ctlr->setmode = ata_via_family_setmode;
+ return 0;
+}
+
+static void
+ata_via_southbridge_fixup(device_t dev)
+{
+ device_t *children;
+ int nchildren, i;
+
+ if (device_get_children(device_get_parent(dev), &children, &nchildren))
+ return;
+
+ for (i = 0; i < nchildren; i++) {
+ if (pci_get_devid(children[i]) == ATA_VIA8363 ||
+ pci_get_devid(children[i]) == ATA_VIA8371 ||
+ pci_get_devid(children[i]) == ATA_VIA8662 ||
+ pci_get_devid(children[i]) == ATA_VIA8361) {
+ u_int8_t reg76 = pci_read_config(children[i], 0x76, 1);
+
+ if ((reg76 & 0xf0) != 0xd0) {
+ device_printf(dev,
+ "Correcting VIA config for southbridge data corruption bug\n");
+ pci_write_config(children[i], 0x75, 0x80, 1);
+ pci_write_config(children[i], 0x76, (reg76 & 0x0f) | 0xd0, 1);
+ }
+ break;
+ }
+ }
+ free(children, M_TEMP);
+}
+
+/* common code for VIA, AMD & nVidia */
+static void
+ata_via_family_setmode(struct ata_device *atadev, int mode)
+{
+ device_t parent = device_get_parent(atadev->channel->dev);
+ struct ata_pci_controller *ctlr = device_get_softc(parent);
+ u_int8_t timings[] = { 0xff, 0xff, 0xff, 0x55, 0x51, 0xff, 0x55, 0x51,
+ 0x51, 0x51, 0x51, 0x51, 0x51, 0x51 };
+ int modes[][7] = {
+ { 0xc2, 0xc1, 0xc0, 0x00, 0x00, 0x00, 0x00 }, /* VIA ATA33 */
+ { 0xee, 0xec, 0xea, 0xe9, 0xe8, 0x00, 0x00 }, /* VIA ATA66 */
+ { 0xf7, 0xf6, 0xf4, 0xf2, 0xf1, 0xf0, 0x00 }, /* VIA ATA100 */
+ { 0xf7, 0xf7, 0xf6, 0xf4, 0xf2, 0xf1, 0xf0 }, /* VIA ATA133 */
+ { 0xc2, 0xc1, 0xc0, 0xc4, 0xc5, 0xc6, 0xc7 }}; /* AMD/nVIDIA */
+ int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit);
+ int reg = 0x53 - devno;
+ int error;
+
+ mode = ata_limit_mode(atadev, mode, ctlr->chip->max_dma);
+
+ if (ctlr->chip->cfg2 & AMDCABLE) {
+ if (mode > ATA_UDMA2 && !pci_read_config(parent, 0x42, 1) & (1<<devno)){
+ ata_prtdev(atadev,
+ "DMA limited to UDMA33, non-ATA66 cable or device\n");
+ mode = ATA_UDMA2;
+ }
+ }
+ else
+ mode = ata_check_80pin(atadev, mode);
+
+ if (ctlr->chip->cfg2 & NVIDIA)
+ reg += 0x10;
+
+ pci_write_config(parent, reg - 0x08, timings[ata_mode2idx(mode)], 1);
+
+ error = ata_command(atadev, ATA_C_SETFEATURES, 0, mode,
+ ATA_C_F_SETXFER, ATA_WAIT_READY);
+ if (bootverbose)
+ ata_prtdev(atadev, "%s setting %s on %s chip\n",
+ (error) ? "failed" : "success", ata_mode2str(mode),
+ ctlr->chip->text);
+ if (!error) {
+ if (mode >= ATA_UDMA0)
+ pci_write_config(parent, reg,
+ modes[ctlr->chip->cfg1][mode & ATA_MODE_MASK], 1);
+ else
+ pci_write_config(parent, reg, 0x8b, 1);
+ atadev->mode = mode;
+ }
+}
+
+/* misc functions */
+static int
+ata_mode2idx(int mode)
+{
+ if ((mode & ATA_DMA_MASK) == ATA_UDMA0)
+ return (mode & ATA_MODE_MASK) + 8;
+ if ((mode & ATA_DMA_MASK) == ATA_WDMA0)
+ return (mode & ATA_MODE_MASK) + 5;
+ return (mode & ATA_MODE_MASK) - ATA_PIO0;
+}
+
+static int
+ata_check_80pin(struct ata_device *atadev, int mode)
+{
+ if (mode > ATA_UDMA2 && !atadev->param->hwres_cblid) {
+ ata_prtdev(atadev,"DMA limited to UDMA33, non-ATA66 cable or device\n");
+ mode = ATA_UDMA2;
+ }
+ return mode;
+}
+
+static int
+ata_find_dev(device_t dev, u_int32_t devid, u_int32_t revid)
+{
+ device_t *children;
+ int nchildren, i;
+
+ if (device_get_children(device_get_parent(dev), &children, &nchildren))
+ return 0;
+
+ for (i = 0; i < nchildren; i++) {
+ if (pci_get_devid(children[i]) == devid &&
+ pci_get_revid(children[i]) >= revid) {
+ free(children, M_TEMP);
+ return 1;
+ }
+ }
+ free(children, M_TEMP);
+ return 0;
+}
+
+static struct ata_chip_id *
+ata_match_chip(device_t dev, struct ata_chip_id *index)
+{
+ while (index->chiptype != 0) {
+ if (ata_find_dev(dev, index->chiptype, index->chiprev))
+ return index;
+ index++;
+ }
+ return NULL;
+}
+
+static int
+ata_default_interrupt(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+ int rid = ATA_IRQ_RID;
+
+ if (!ATA_MASTERDEV(dev)) {
+ if (!(ctlr->r_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
+ RF_SHAREABLE | RF_ACTIVE))) {
+ device_printf(dev, "unable to map interrupt\n");
+ return ENXIO;
+ }
+ if ((bus_setup_intr(dev, ctlr->r_irq, INTR_TYPE_BIO | INTR_ENTROPY,
+ ata_generic_intr, ctlr, &ctlr->handle))) {
+ device_printf(dev, "unable to setup interrupt\n");
+ return ENXIO;
+ }
+ }
+ return 0;
+}
+
+static void
+ata_pci_serialize(struct ata_channel *ch, int flags)
+{
+ struct ata_pci_controller *scp =
+ device_get_softc(device_get_parent(ch->dev));
+
+ switch (flags) {
+ case ATA_LF_LOCK:
+ if (scp->locked_ch == ch->unit)
+ break;
+ while (!atomic_cmpset_acq_int(&scp->locked_ch, -1, ch->unit))
+ tsleep((caddr_t)ch->locking, PRIBIO, "atalck", 1);
+ break;
+
+ case ATA_LF_UNLOCK:
+ if (scp->locked_ch == -1 || scp->locked_ch != ch->unit)
+ break;
+ atomic_store_rel_int(&scp->locked_ch, -1);
+ wakeup((caddr_t)ch->locking);
+ break;
+ }
+ return;
+}
diff --git a/sys/dev/ata/ata-disk.c b/sys/dev/ata/ata-disk.c
index 49f2062..450011a 100644
--- a/sys/dev/ata/ata-disk.c
+++ b/sys/dev/ata/ata-disk.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -47,6 +47,7 @@
#include <machine/bus.h>
#include <sys/rman.h>
#include <dev/ata/ata-all.h>
+#include <dev/ata/ata-pci.h>
#include <dev/ata/ata-disk.h>
#include <dev/ata/ata-raid.h>
@@ -182,11 +183,10 @@ ad_attach(struct ata_device *atadev)
}
/* use DMA if allowed and if drive/controller supports it */
- if (ata_dma)
- ata_dmainit(atadev, ata_pmode(atadev->param),
- ata_wmode(atadev->param), ata_umode(atadev->param));
+ if (ata_dma && atadev->channel->dma)
+ atadev->setmode(atadev, ATA_DMA_MAX);
else
- ata_dmainit(atadev, ata_pmode(atadev->param), -1, -1);
+ atadev->setmode(atadev, ATA_PIO_MAX);
/* use tagged queueing if allowed and supported */
if (ata_tags && ad_tagsupported(adp)) {
@@ -249,7 +249,8 @@ ad_detach(struct ata_device *atadev, int flush) /* get rid of flush XXX SOS */
biofinish(request->bp, NULL, ENXIO);
ad_free(request);
}
- ata_dmafree(atadev);
+ if (atadev->channel->dma)
+ atadev->channel->dma->free(atadev);
while ((bp = bioq_first(&adp->queue))) {
bioq_remove(&adp->queue, bp);
biofinish(bp, NULL, ENXIO);
@@ -288,12 +289,12 @@ adclose(dev_t dev, int flags, int fmt, struct thread *td)
{
struct ad_softc *adp = dev->si_drv1;
- adp->device->channel->lock_func(adp->device->channel, ATA_LF_LOCK);
+ adp->device->channel->locking(adp->device->channel, ATA_LF_LOCK);
ATA_SLEEPLOCK_CH(adp->device->channel, ATA_CONTROL);
if (ata_command(adp->device, ATA_C_FLUSHCACHE, 0, 0, 0, ATA_WAIT_READY))
ata_prtdev(adp->device, "flushing cache on close failed\n");
ATA_UNLOCK_CH(adp->device->channel);
- adp->device->channel->lock_func(adp->device->channel, ATA_LF_UNLOCK);
+ adp->device->channel->locking(adp->device->channel, ATA_LF_UNLOCK);
return 0;
}
@@ -326,9 +327,9 @@ addump(dev_t dev, void *virtual, vm_offset_t physical, off_t offset, size_t leng
if (!once) {
/* force PIO mode for dumps */
adp->device->mode = ATA_PIO;
- adp->device->channel->lock_func(adp->device->channel, ATA_LF_LOCK);
+ adp->device->channel->locking(adp->device->channel, ATA_LF_LOCK);
ata_reinit(adp->device->channel);
- adp->device->channel->lock_func(adp->device->channel, ATA_LF_UNLOCK);
+ adp->device->channel->locking(adp->device->channel, ATA_LF_UNLOCK);
once = 1;
}
@@ -388,7 +389,7 @@ ad_start(struct ata_device *atadev)
if (bp->bio_cmd == BIO_READ)
request->flags |= ADR_F_READ;
- if (adp->device->mode >= ATA_DMA && ata_dmaalloc(atadev))
+ if (adp->device->mode >= ATA_DMA && atadev->channel->dma->alloc(atadev))
adp->device->mode = ATA_PIO;
/* insert in tag array */
@@ -452,7 +453,7 @@ ad_transfer(struct ad_request *request)
/* does this drive & transfer work with DMA ? */
request->flags &= ~ADR_F_DMA_USED;
if (adp->device->mode >= ATA_DMA &&
- !ata_dmasetup(adp->device, request->data, request->bytecount)) {
+ !adp->device->channel->dma->setup(adp->device, request->data, request->bytecount)) {
request->flags |= ADR_F_DMA_USED;
request->currentsize = request->bytecount;
@@ -501,7 +502,7 @@ ad_transfer(struct ad_request *request)
}
/* start transfer, return and wait for interrupt */
- ata_dmastart(adp->device, request->data, request->bytecount,
+ adp->device->channel->dma->start(adp->device, request->data, request->bytecount,
request->flags & ADR_F_READ);
return ATA_OP_CONTINUES;
}
@@ -571,7 +572,7 @@ ad_interrupt(struct ad_request *request)
/* finish DMA transfer */
if (request->flags & ADR_F_DMA_USED)
- dma_stat = ata_dmadone(adp->device);
+ dma_stat = adp->device->channel->dma->stop(adp->device);
/* do we have a corrected soft error ? */
if (adp->device->channel->status & ATA_S_CORR)
@@ -596,24 +597,24 @@ ad_interrupt(struct ad_request *request)
if (request->retries++ < AD_MAX_RETRIES)
printf(" retrying\n");
else {
- ata_dmainit(adp->device, ata_pmode(adp->device->param), -1, -1);
+ adp->device->setmode(adp->device, ATA_PIO_MAX);
printf(" falling back to PIO mode\n");
}
TAILQ_INSERT_HEAD(&adp->device->channel->ata_queue, request, chain);
return ATA_OP_FINISHED;
}
-
+#if 0 /* XXX*/
/* if using DMA, try once again in PIO mode */
if (request->flags & ADR_F_DMA_USED) {
untimeout((timeout_t *)ad_timeout, request,request->timeout_handle);
ad_invalidatequeue(adp, request);
- ata_dmainit(adp->device, ata_pmode(adp->device->param), -1, -1);
+ adp->device->setmode(adp->device, ATA_PIO_MAX);
request->flags |= ADR_F_FORCE_PIO;
printf(" trying PIO mode\n");
TAILQ_INSERT_HEAD(&adp->device->channel->ata_queue, request, chain);
return ATA_OP_FINISHED;
}
-
+#endif
request->flags |= ADR_F_ERROR;
printf(" status=%02x error=%02x\n",
adp->device->channel->status, adp->device->channel->error);
@@ -761,7 +762,7 @@ ad_service(struct ad_softc *adp, int change)
ad_invalidatequeue(adp, NULL);
return ATA_OP_FINISHED;
}
- ata_dmastart(adp->device, request->data, request->bytecount,
+ adp->device->channel->dma->start(adp->device, request->data, request->bytecount,
request->flags & ADR_F_READ);
return ATA_OP_CONTINUES;
}
@@ -802,12 +803,10 @@ ad_invalidatequeue(struct ad_softc *adp, struct ad_request *request)
static int
ad_tagsupported(struct ad_softc *adp)
{
+ /* check for controllers that we know doesn't support tags */
switch (adp->device->channel->chiptype) {
- case 0x0d30105a: /* Promises before TX2 doesn't work with tagged queuing */
- case 0x0d38105a:
- case 0x4d30105a:
- case 0x4d33105a:
- case 0x4d38105a:
+ case ATA_PDC20265: case ATA_PDC20263: case ATA_PDC20267:
+ case ATA_PDC20246: case ATA_PDC20262:
return 0;
}
@@ -851,10 +850,10 @@ ad_timeout(struct ad_request *request)
request->tag, request->serv);
if (request->flags & ADR_F_DMA_USED) {
- ata_dmadone(adp->device);
+ adp->device->channel->dma->stop(adp->device);
ad_invalidatequeue(adp, request);
if (request->retries == AD_MAX_RETRIES) {
- ata_dmainit(adp->device, ata_pmode(adp->device->param), -1, -1);
+ adp->device->setmode(adp->device, ATA_PIO_MAX);
ata_prtdev(adp->device, "trying fallback to PIO mode\n");
request->retries = 0;
}
@@ -883,12 +882,7 @@ ad_reinit(struct ata_device *atadev)
ad_invalidatequeue(atadev->driver, NULL);
ata_command(atadev, ATA_C_SET_MULTI, 0,
adp->transfersize / DEV_BSIZE, 0, ATA_WAIT_READY);
- if (adp->device->mode >= ATA_DMA)
- ata_dmainit(atadev, ata_pmode(adp->device->param),
- ata_wmode(adp->device->param),
- ata_umode(adp->device->param));
- else
- ata_dmainit(atadev, ata_pmode(adp->device->param), -1, -1);
+ atadev->setmode(atadev, adp->device->mode);
}
void
diff --git a/sys/dev/ata/ata-disk.h b/sys/dev/ata/ata-disk.h
index 0c190d1..db9156b 100644
--- a/sys/dev/ata/ata-disk.h
+++ b/sys/dev/ata/ata-disk.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/ata/ata-dma.c b/sys/dev/ata/ata-dma.c
index c6ab3a5..7f1353b 100644
--- a/sys/dev/ata/ata-dma.c
+++ b/sys/dev/ata/ata-dma.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,6 +31,7 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/ata.h>
+#include <sys/kernel.h>
#include <sys/endian.h>
#include <sys/malloc.h>
#include <sys/bus.h>
@@ -38,32 +39,54 @@
#include <machine/bus.h>
#include <sys/rman.h>
#include <dev/ata/ata-all.h>
+#include <dev/ata/ata-pci.h>
/* prototypes */
-static void ata_dmacreate(struct ata_device *, int, int);
-static void ata_dmasetupd_cb(void *, bus_dma_segment_t *, int, int);
static void ata_dmasetupc_cb(void *, bus_dma_segment_t *, int, int);
-static void cyrix_timing(struct ata_device *, int, int);
-static void promise_timing(struct ata_device *, int, int);
-static void hpt_timing(struct ata_device *, int, int);
-static int hpt_cable80(struct ata_device *);
+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 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 *);
-/* misc defines */
-#define ATAPI_DEVICE(atadev) \
- ((atadev->unit == ATA_MASTER && \
- atadev->channel->devices & ATA_ATAPI_MASTER) || \
- (atadev->unit == ATA_SLAVE && \
- atadev->channel->devices & ATA_ATAPI_SLAVE))
+/* local vars */
+static MALLOC_DEFINE(M_ATADMA, "ATA DMA", "ATA driver DMA");
-#define MAXSEGSZ PAGE_SIZE
-#define MAXTABSZ PAGE_SIZE
-#define MAXCTLDMASZ (2 * (MAXTABSZ + MAXPHYS))
+/* misc defines */
+#define MAXSEGSZ PAGE_SIZE
+#define MAXTABSZ PAGE_SIZE
+#define MAXCTLDMASZ (2 * (MAXTABSZ + MAXPHYS))
struct ata_dc_cb_args {
bus_addr_t maddr;
int error;
};
+int
+ata_dmainit(struct ata_channel *ch)
+{
+ if (!(ch->dma =
+ malloc(sizeof(struct ata_dma_funcs), 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;
+ ch->dma->start = ata_dmastart;
+ ch->dma->stop = ata_dmastop;
+ ch->dma->status = ata_dmastatus;
+ ch->dma->alignment = 2;
+ return 0;
+}
+
+
static void
ata_dmasetupc_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error)
{
@@ -73,7 +96,7 @@ ata_dmasetupc_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error)
cba->maddr = segs[0].ds_addr;
}
-int
+static int
ata_dmaalloc(struct ata_device *atadev)
{
struct ata_channel *ch;
@@ -92,7 +115,7 @@ ata_dmaalloc(struct ata_device *atadev)
return error;
}
if (!ds->ddmatag) {
- if ((error = bus_dma_tag_create(ch->dmatag, ch->alignment + 1, 0,
+ if ((error = bus_dma_tag_create(ch->dmatag, ch->dma->alignment, 0,
BUS_SPACE_MAXADDR_32BIT,
BUS_SPACE_MAXADDR, NULL, NULL,
MAXPHYS, ATA_DMA_ENTRIES, MAXSEGSZ,
@@ -119,7 +142,7 @@ ata_dmaalloc(struct ata_device *atadev)
return 0;
}
-void
+static void
ata_dmafree(struct ata_device *atadev)
{
struct ata_dmastate *ds;
@@ -146,1326 +169,27 @@ ata_dmafree(struct ata_device *atadev)
}
}
-void
-ata_dmafreetags(struct ata_channel *ch)
-{
-
- if (ch->dmatag) {
- bus_dma_tag_destroy(ch->dmatag);
- ch->dmatag = NULL;
- }
-}
-
static void
-ata_dmacreate(struct ata_device *atadev, int apiomode, int mode)
+ata_dmacreate(struct ata_channel *ch)
{
- atadev->mode = mode;
- if (!atadev->channel->dmatag) {
+ 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,
- &atadev->channel->dmatag)) {
- ata_prtdev(atadev, "DMA tag allocation failed, disabling DMA\n");
- ata_dmainit(atadev, apiomode, -1, -1);
+ BUS_SPACE_MAXSIZE_32BIT, 0, &ch->dmatag)) {
+ printf("DMA tag allocation failed, disabling DMA\n");
}
}
}
-void
-ata_dmainit(struct ata_device *atadev, int apiomode, int wdmamode, int udmamode)
+static void
+ata_dmadestroy(struct ata_channel *ch)
{
- device_t parent = device_get_parent(atadev->channel->dev);
- int chiptype = atadev->channel->chiptype;
- int chiprev = pci_get_revid(parent);
- int channel = atadev->channel->unit;
- int device = ATA_DEV(atadev->unit);
- int devno = (channel << 1) + device;
- int error;
-
- /* set our most pessimistic default mode */
- atadev->mode = ATA_PIO;
-
- if (!atadev->channel->r_bmio)
- return;
-
- /* if simplex controller, only allow DMA on primary channel */
- if (channel == 1) {
- ATA_OUTB(atadev->channel->r_bmio, ATA_BMSTAT_PORT,
- ATA_INB(atadev->channel->r_bmio, ATA_BMSTAT_PORT) &
- (ATA_BMSTAT_DMA_MASTER | ATA_BMSTAT_DMA_SLAVE));
- if (ATA_INB(atadev->channel->r_bmio, ATA_BMSTAT_PORT) &
- ATA_BMSTAT_DMA_SIMPLEX) {
- ata_prtdev(atadev, "simplex device, DMA on primary only\n");
- return;
- }
- }
-
- /* DMA engine address alignment is usually 1 word (2 bytes) */
- atadev->channel->alignment = 0x1;
-
-#if 1
- if (udmamode > 2 && !atadev->param->hwres_cblid) {
- ata_prtdev(atadev,"DMA limited to UDMA33, non-ATA66 cable or device\n");
- udmamode = 2;
- }
-#endif
- switch (chiptype) {
-
- case 0x24cb8086: /* Intel ICH4 */
- case 0x248a8086: /* Intel ICH3 mobile */
- case 0x248b8086: /* Intel ICH3 */
- case 0x244a8086: /* Intel ICH2 mobile */
- case 0x244b8086: /* Intel ICH2 */
- if (udmamode >= 5) {
- int32_t mask48, new48;
- int16_t word54;
-
- word54 = pci_read_config(parent, 0x54, 2);
- if (word54 & (0x10 << devno)) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA5, ATA_C_F_SETXFER,ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA5 on Intel chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- mask48 = (1 << devno) + (3 << (16 + (devno << 2)));
- new48 = (1 << devno) + (1 << (16 + (devno << 2)));
- pci_write_config(parent, 0x48,
- (pci_read_config(parent, 0x48, 4) &
- ~mask48) | new48, 4);
- pci_write_config(parent, 0x54, word54 | (0x1000<<devno), 2);
- ata_dmacreate(atadev, apiomode, ATA_UDMA5);
- return;
- }
- }
- }
- /* make sure eventual ATA100 mode from the BIOS is disabled */
- pci_write_config(parent, 0x54,
- pci_read_config(parent, 0x54, 2) & ~(0x1000<<devno),2);
- /* FALLTHROUGH */
-
- case 0x24118086: /* Intel ICH */
- case 0x76018086: /* Intel ICH */
- if (udmamode >= 4) {
- int32_t mask48, new48;
- int16_t word54;
-
- word54 = pci_read_config(parent, 0x54, 2);
- if (word54 & (0x10 << devno)) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA4 on Intel chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- mask48 = (1 << devno) + (3 << (16 + (devno << 2)));
- new48 = (1 << devno) + (2 << (16 + (devno << 2)));
- pci_write_config(parent, 0x48,
- (pci_read_config(parent, 0x48, 4) &
- ~mask48) | new48, 4);
- pci_write_config(parent, 0x54, word54 | (1 << devno), 2);
- ata_dmacreate(atadev, apiomode, ATA_UDMA4);
- return;
- }
- }
- }
- /* make sure eventual ATA66 mode from the BIOS is disabled */
- pci_write_config(parent, 0x54,
- pci_read_config(parent, 0x54, 2) & ~(1 << devno), 2);
- /* FALLTHROUGH */
-
- case 0x71118086: /* Intel PIIX4 */
- case 0x84CA8086: /* Intel PIIX4 */
- case 0x71998086: /* Intel PIIX4e */
- case 0x24218086: /* Intel ICH0 */
- if (udmamode >= 2) {
- int32_t mask48, new48;
-
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA2 on Intel chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- mask48 = (1 << devno) + (3 << (16 + (devno << 2)));
- new48 = (1 << devno) + (2 << (16 + (devno << 2)));
- pci_write_config(parent, 0x48,
- (pci_read_config(parent, 0x48, 4) &
- ~mask48) | new48, 4);
- ata_dmacreate(atadev, apiomode, ATA_UDMA2);
- return;
- }
- }
- /* make sure eventual ATA33 mode from the BIOS is disabled */
- pci_write_config(parent, 0x48,
- pci_read_config(parent, 0x48, 4) & ~(1 << devno), 4);
- /* FALLTHROUGH */
-
- case 0x70108086: /* Intel PIIX3 */
- if (wdmamode >= 2 && apiomode >= 4) {
- int32_t mask40, new40, mask44, new44;
-
- /* if SITRE not set doit for both channels */
- if (!((pci_read_config(parent, 0x40, 4) >> (channel<<8)) & 0x4000)){
- new40 = pci_read_config(parent, 0x40, 4);
- new44 = pci_read_config(parent, 0x44, 4);
- if (!(new40 & 0x00004000)) {
- new44 &= ~0x0000000f;
- new44 |= ((new40&0x00003000)>>10)|((new40&0x00000300)>>8);
- }
- if (!(new40 & 0x40000000)) {
- new44 &= ~0x000000f0;
- new44 |= ((new40&0x30000000)>>22)|((new40&0x03000000)>>20);
- }
- new40 |= 0x40004000;
- pci_write_config(parent, 0x40, new40, 4);
- pci_write_config(parent, 0x44, new44, 4);
- }
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting WDMA2 on Intel chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- if (device == ATA_MASTER) {
- mask40 = 0x0000330f;
- new40 = 0x00002307;
- mask44 = 0;
- new44 = 0;
- }
- else {
- mask40 = 0x000000f0;
- new40 = 0x00000070;
- mask44 = 0x0000000f;
- new44 = 0x0000000b;
- }
- if (channel) {
- mask40 <<= 16;
- new40 <<= 16;
- mask44 <<= 4;
- new44 <<= 4;
- }
- pci_write_config(parent, 0x40,
- (pci_read_config(parent, 0x40, 4) & ~mask40)|
- new40, 4);
- pci_write_config(parent, 0x44,
- (pci_read_config(parent, 0x44, 4) & ~mask44)|
- new44, 4);
- ata_dmacreate(atadev, apiomode, ATA_WDMA2);
- return;
- }
- }
- /* we could set PIO mode timings, but we assume the BIOS did that */
- break;
-
- case 0x12308086: /* Intel PIIX */
- if (wdmamode >= 2 && apiomode >= 4) {
- int32_t word40;
-
- word40 = pci_read_config(parent, 0x40, 4);
- word40 >>= channel * 16;
-
- /* Check for timing config usable for DMA on controller */
- if (!((word40 & 0x3300) == 0x2300 &&
- ((word40 >> (device ? 4 : 0)) & 1) == 1))
- break;
-
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting WDMA2 on Intel chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- ata_dmacreate(atadev, apiomode, ATA_WDMA2);
- return;
- }
- }
- break;
-
- case 0x522910b9: /* AcerLabs Aladdin IV/V */
- /* the older Aladdin doesn't support ATAPI DMA on both master & slave */
- if (chiprev < 0xc2 &&
- atadev->channel->devices & ATA_ATAPI_MASTER &&
- atadev->channel->devices & ATA_ATAPI_SLAVE) {
- ata_prtdev(atadev, "two atapi devices on this channel, no DMA\n");
- break;
- }
- pci_write_config(parent, 0x58 + (channel << 2), 0x00310001, 4);
- if (udmamode >= 5 && chiprev >= 0xc4) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA5, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA5 on Acer chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- int32_t word54 = pci_read_config(parent, 0x54, 4);
-
- pci_write_config(parent, 0x4b,
- pci_read_config(parent, 0x4b, 1) | 0x01, 1);
- word54 &= ~(0x000f000f << (devno << 2));
- word54 |= (0x000f0005 << (devno << 2));
- pci_write_config(parent, 0x54, word54, 4);
- pci_write_config(parent, 0x53,
- pci_read_config(parent, 0x53, 1) | 0x03, 1);
- ata_dmacreate(atadev, apiomode, ATA_UDMA5);
- return;
- }
- }
- if (udmamode >= 4 && chiprev >= 0xc2) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA4 on Acer chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- int32_t word54 = pci_read_config(parent, 0x54, 4);
-
- pci_write_config(parent, 0x4b,
- pci_read_config(parent, 0x4b, 1) | 0x01, 1);
- word54 &= ~(0x000f000f << (devno << 2));
- word54 |= (0x00080005 << (devno << 2));
- pci_write_config(parent, 0x54, word54, 4);
- pci_write_config(parent, 0x53,
- pci_read_config(parent, 0x53, 1) | 0x03, 1);
- ata_dmacreate(atadev, apiomode, ATA_UDMA4);
- return;
- }
- }
- if (udmamode >= 2 && chiprev >= 0x20) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA2 on Acer chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- int32_t word54 = pci_read_config(parent, 0x54, 4);
-
- word54 &= ~(0x000f000f << (devno << 2));
- word54 |= (0x000a0005 << (devno << 2));
- pci_write_config(parent, 0x54, word54, 4);
- pci_write_config(parent, 0x53,
- pci_read_config(parent, 0x53, 1) | 0x03, 1);
- atadev->channel->flags |= ATA_ATAPI_DMA_RO;
- ata_dmacreate(atadev, apiomode, ATA_UDMA2);
- return;
- }
- }
-
- /* make sure eventual UDMA mode from the BIOS is disabled */
- pci_write_config(parent, 0x56, pci_read_config(parent, 0x56, 2) &
- ~(0x0008 << (devno << 2)), 2);
-
- if (wdmamode >= 2 && apiomode >= 4) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting WDMA2 on Acer chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- pci_write_config(parent, 0x53,
- pci_read_config(parent, 0x53, 1) | 0x03, 1);
- atadev->channel->flags |= ATA_ATAPI_DMA_RO;
- ata_dmacreate(atadev, apiomode, ATA_WDMA2);
- return;
- }
- }
- pci_write_config(parent, 0x53,
- (pci_read_config(parent, 0x53, 1) & ~0x01) | 0x02, 1);
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_PIO0 + apiomode,
- ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting PIO%d on Acer chip\n",
- (error) ? "failed" : "success",
- (apiomode >= 0) ? apiomode : 0);
- if (!error) {
- int32_t word54 = pci_read_config(parent, 0x54, 4);
- int32_t timing;
-
- switch(ATA_PIO0 + apiomode) {
- case ATA_PIO0: timing = 0x006d0003;
- case ATA_PIO1: timing = 0x00580002;
- case ATA_PIO2: timing = 0x00440001;
- case ATA_PIO3: timing = 0x00330001;
- case ATA_PIO4: timing = 0x00310001;
- default: timing = 0x006d0003;
- }
- pci_write_config(parent, 0x58 + (channel << 2), timing, 4);
- word54 &= ~(0x000f000f << (devno << 2));
- word54 |= (0x00000004 << (devno << 2));
- pci_write_config(parent, 0x54, word54, 4);
- atadev->mode = ATA_PIO0 + apiomode;
- return;
- }
- break;
-
- case 0x01bc10de: /* nVIDIA nForce */
- case 0x006510de: /* nVIDIA nForce2 */
- case 0x74411022: /* AMD 768 */
- case 0x74111022: /* AMD 766 */
- case 0x74091022: /* AMD 756 */
- case 0x05711106: /* VIA 82C571, 82C586, 82C596, 82C686, 8231,8233,8235 */
- {
- int via_modes[5][7] = {
- { 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00 }, /* VIA ATA33 */
- { 0x00, 0x00, 0xea, 0x00, 0xe8, 0x00, 0x00 }, /* VIA ATA66 */
- { 0x00, 0x00, 0xf4, 0x00, 0xf1, 0xf0, 0x00 }, /* VIA ATA100 */
- { 0x00, 0x00, 0xf6, 0x00, 0xf2, 0xf1, 0xf0 }, /* VIA ATA133 */
- { 0x00, 0x00, 0xc0, 0x00, 0xc5, 0xc6, 0xc7 }}; /* AMD/nVIDIA */
- int reg = 0x53 - devno;
- int *reg_val = NULL;
- char *chip = "VIA";
-
- if (ata_find_dev(parent, 0x31471106, 0) || /* 8233a */
- ata_find_dev(parent, 0x31771106, 0)) { /* 8235 */
- udmamode = imin(udmamode, 6);
- reg_val = via_modes[3];
- }
- else if (ata_find_dev(parent, 0x06861106, 0x40) || /* 82C686b */
- ata_find_dev(parent, 0x82311106, 0) || /* 8231 */
- ata_find_dev(parent, 0x30741106, 0) || /* 8233 */
- ata_find_dev(parent, 0x31091106, 0)) { /* 8233c */
- udmamode = imin(udmamode, 5);
- reg_val = via_modes[2];
- }
- else if (ata_find_dev(parent, 0x06861106, 0x10) || /* 82C686a */
- ata_find_dev(parent, 0x05961106, 0x12)) { /* 82C596b */
- udmamode = imin(udmamode, 4);
- reg_val = via_modes[1];
- }
- else if (ata_find_dev(parent, 0x06861106, 0)) { /* 82C686 */
- udmamode = imin(udmamode, 2);
- reg_val = via_modes[1];
- }
- else if (ata_find_dev(parent, 0x05961106, 0) || /* 82C596a */
- ata_find_dev(parent, 0x05861106, 0x03)) { /* 82C586b */
- udmamode = imin(udmamode, 2);
- reg_val = via_modes[0];
- }
- else if (chiptype == 0x74411022 || /* AMD 768 */
- chiptype == 0x74111022) { /* AMD 766 */
- udmamode = imin(udmamode, 5);
- reg_val = via_modes[4];
- chip = "AMD";
- }
- else if (chiptype == 0x74091022) { /* AMD 756 */
- udmamode = imin(udmamode, 4);
- reg_val = via_modes[4];
- chip = "AMD";
- }
- else if (chiptype == 0x006510de) { /* nForce2 */
- udmamode = imin(udmamode, 6);
- reg += 0x10;
- reg_val = via_modes[4];
- chip = "nVidia";
- }
- else if (chiptype == 0x01bc10de) { /* nForce */
- udmamode = imin(udmamode, 5);
- reg += 0x10;
- reg_val = via_modes[4];
- chip = "nVidia";
- }
- else
- udmamode = 0;
-
- if (udmamode || wdmamode)
- pci_write_config(parent, reg - 0x08, 0x20, 1);
-
- if (udmamode >= 6) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA6, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA6 on %s chip\n",
- (error) ? "failed" : "success", chip);
- if (!error) {
- pci_write_config(parent, reg, reg_val[6], 1);
- ata_dmacreate(atadev, apiomode, ATA_UDMA6);
- return;
- }
- }
- if (udmamode >= 5) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA5, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA5 on %s chip\n",
- (error) ? "failed" : "success", chip);
- if (!error) {
- pci_write_config(parent, reg, reg_val[5], 1);
- ata_dmacreate(atadev, apiomode, ATA_UDMA5);
- return;
- }
- }
- if (udmamode >= 4) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA4 on %s chip\n",
- (error) ? "failed" : "success", chip);
- if (!error) {
- pci_write_config(parent, reg, reg_val[4], 1);
- ata_dmacreate(atadev, apiomode, ATA_UDMA4);
- return;
- }
- }
- if (udmamode >= 2) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA2 on %s chip\n",
- (error) ? "failed" : "success", chip);
- if (!error) {
- pci_write_config(parent, reg, reg_val[2], 1);
- ata_dmacreate(atadev, apiomode, ATA_UDMA2);
- return;
- }
- }
- if (wdmamode >= 2 && apiomode >= 4) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting WDMA2 on %s chip\n",
- (error) ? "failed" : "success", chip);
- if (!error) {
- pci_write_config(parent, reg, 0x0b, 1);
- pci_write_config(parent, reg - 0x08, 0x31, 1);
- ata_dmacreate(atadev, apiomode, ATA_WDMA2);
- return;
- }
- }
- }
- /* we could set PIO mode timings, but we assume the BIOS did that */
- break;
-
- case 0x55131039: /* SiS 5591 */
- if (ata_find_dev(parent, 0x06301039, 0x30) || /* SiS 630 */
- ata_find_dev(parent, 0x06331039, 0) || /* SiS 633 */
- ata_find_dev(parent, 0x06351039, 0) || /* SiS 635 */
- ata_find_dev(parent, 0x06401039, 0) || /* SiS 640 */
- ata_find_dev(parent, 0x06451039, 0) || /* SiS 645 */
- ata_find_dev(parent, 0x06501039, 0) || /* SiS 650 */
- ata_find_dev(parent, 0x07301039, 0) || /* SiS 730 */
- ata_find_dev(parent, 0x07331039, 0) || /* SiS 733 */
- ata_find_dev(parent, 0x07351039, 0) || /* SiS 735 */
- ata_find_dev(parent, 0x07401039, 0) || /* SiS 740 */
- ata_find_dev(parent, 0x07451039, 0) || /* SiS 745 */
- ata_find_dev(parent, 0x07501039, 0)) { /* SiS 750 */
- int8_t reg = 0x40 + (devno << 1);
- int16_t val = pci_read_config(parent, reg, 2) & 0x0fff;
-
- if (udmamode >= 5) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA5, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA5 on SiS chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- pci_write_config(parent, reg, val | 0x8000, 2);
- ata_dmacreate(atadev, apiomode, ATA_UDMA5);
- return;
- }
- }
- if (udmamode >= 4) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA4 on SiS chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- pci_write_config(parent, reg, val | 0x9000, 2);
- ata_dmacreate(atadev, apiomode, ATA_UDMA4);
- return;
- }
- }
- if (udmamode >= 2) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA2 on SiS chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- pci_write_config(parent, reg, val | 0xb000, 2);
- ata_dmacreate(atadev, apiomode, ATA_UDMA2);
- return;
- }
- }
- } else if (ata_find_dev(parent, 0x05301039, 0) || /* SiS 530 */
- ata_find_dev(parent, 0x05401039, 0) || /* SiS 540 */
- ata_find_dev(parent, 0x06201039, 0) || /* SiS 620 */
- ata_find_dev(parent, 0x06301039, 0)) { /* SiS 630 */
- int8_t reg = 0x40 + (devno << 1);
- int16_t val = pci_read_config(parent, reg, 2) & 0x0fff;
-
- if (udmamode >= 4) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA4 on SiS chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- pci_write_config(parent, reg, val | 0x9000, 2);
- ata_dmacreate(atadev, apiomode, ATA_UDMA4);
- return;
- }
- }
- if (udmamode >= 2) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA2 on SiS chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- pci_write_config(parent, reg, val | 0xa000, 2);
- ata_dmacreate(atadev, apiomode, ATA_UDMA2);
- return;
- }
- }
- } else if (udmamode >= 2 && chiprev > 0xc1) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA2 on SiS chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- pci_write_config(parent, 0x40 + (devno << 1), 0xa301, 2);
- ata_dmacreate(atadev, apiomode, ATA_UDMA2);
- return;
- }
- }
- if (wdmamode >=2 && apiomode >= 4) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting WDMA2 on SiS chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- pci_write_config(parent, 0x40 + (devno << 1), 0x0301, 2);
- ata_dmacreate(atadev, apiomode, ATA_WDMA2);
- return;
- }
- }
- /* we could set PIO mode timings, but we assume the BIOS did that */
- break;
-
- case 0x06801095: /* Sil 0680 ATA133 controller */
- {
- u_int8_t ureg = 0xac + (device * 0x02) + (channel * 0x10);
- u_int8_t uval = pci_read_config(parent, ureg, 1);
- u_int8_t mreg = channel ? 0x84 : 0x80;
- u_int8_t mask = device ? 0x30 : 0x03;
- u_int8_t mode = pci_read_config(parent, mreg, 1);
-
- /* enable UDMA mode */
- pci_write_config(parent, mreg,
- (mode & ~mask) | (device ? 0x30 : 0x03), 1);
- if (udmamode >= 6) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA6, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA6 on Sil chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- pci_write_config(parent, ureg, (uval & 0x3f) | 0x01, 1);
- ata_dmacreate(atadev, apiomode, ATA_UDMA6);
- return;
- }
- }
- if (udmamode >= 5) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA5, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA5 on Sil chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- pci_write_config(parent, ureg, (uval & 0x3f) | 0x02, 1);
- ata_dmacreate(atadev, apiomode, ATA_UDMA5);
- return;
- }
- }
- if (udmamode >= 4) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA4 on Sil chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- pci_write_config(parent, ureg, (uval & 0x3f) | 0x03, 1);
- ata_dmacreate(atadev, apiomode, ATA_UDMA4);
- return;
- }
- }
- if (udmamode >= 2) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA2 on Sil chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- pci_write_config(parent, ureg, (uval & 0x3f) | 0x07, 1);
- ata_dmacreate(atadev, apiomode, ATA_UDMA2);
- return;
- }
- }
-
- /* disable UDMA mode and enable WDMA mode */
- pci_write_config(parent, mreg,
- (mode & ~mask) | (device ? 0x20 : 0x02), 1);
- if (wdmamode >= 2 && apiomode >= 4) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting WDMA2 on Sil chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- pci_write_config(parent, ureg - 0x4, 0x10c1, 2);
- ata_dmacreate(atadev, apiomode, ATA_WDMA2);
- return;
- }
- }
-
- /* restore PIO mode */
- pci_write_config(parent, mreg, mode, 1);
- }
- /* we could set PIO mode timings, but we assume the BIOS did that */
- break;
-
- case 0x06491095: /* CMD 649 ATA100 controller */
- if (udmamode >= 5) {
- u_int8_t umode;
-
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA5, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA5 on CMD chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- umode = pci_read_config(parent, channel ? 0x7b : 0x73, 1);
- umode &= ~(device ? 0xca : 0x35);
- umode |= (device ? 0x0a : 0x05);
- pci_write_config(parent, channel ? 0x7b : 0x73, umode, 1);
- ata_dmacreate(atadev, apiomode, ATA_UDMA5);
- return;
- }
- }
- /* FALLTHROUGH */
-
- case 0x06481095: /* CMD 648 ATA66 controller */
- if (udmamode >= 4) {
- u_int8_t umode;
-
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA4 on CMD chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- umode = pci_read_config(parent, channel ? 0x7b : 0x73, 1);
- umode &= ~(device ? 0xca : 0x35);
- umode |= (device ? 0x4a : 0x15);
- pci_write_config(parent, channel ? 0x7b : 0x73, umode, 1);
- ata_dmacreate(atadev, apiomode, ATA_UDMA4);
- return;
- }
- }
- if (udmamode >= 2) {
- u_int8_t umode;
-
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA2 on CMD chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- umode = pci_read_config(parent, channel ? 0x7b : 0x73, 1);
- umode &= ~(device ? 0xca : 0x35);
- umode |= (device ? 0x42 : 0x11);
- pci_write_config(parent, channel ? 0x7b : 0x73, umode, 1);
- ata_dmacreate(atadev, apiomode, ATA_UDMA2);
- return;
- }
- }
- /* make sure eventual UDMA mode from the BIOS is disabled */
- pci_write_config(parent, channel ? 0x7b : 0x73,
- pci_read_config(parent, channel ? 0x7b : 0x73, 1) &
- ~(device ? 0xca : 0x53), 1);
- /* FALLTHROUGH */
-
- case 0x06461095: /* CMD 646 ATA controller */
- if (wdmamode >= 2 && apiomode >= 4) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting WDMA2 on CMD chip\n",
- error ? "failed" : "success");
- if (!error) {
- int32_t offset = (devno < 3) ? (devno << 1) : 7;
-
- pci_write_config(parent, 0x54 + offset, 0x3f, 1);
- ata_dmacreate(atadev, apiomode, ATA_WDMA2);
- return;
- }
- }
- /* we could set PIO mode timings, but we assume the BIOS did that */
- break;
-
- case 0xc6931080: /* Cypress 82c693 ATA controller */
- if (wdmamode >= 2 && apiomode >= 4) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting WDMA2 on Cypress chip\n",
- error ? "failed" : "success");
- if (!error) {
- pci_write_config(atadev->channel->dev,
- channel ? 0x4e:0x4c, 0x2020, 2);
- ata_dmacreate(atadev, apiomode, ATA_WDMA2);
- return;
- }
- }
- /* we could set PIO mode timings, but we assume the BIOS did that */
- break;
-
- case 0x01021078: /* Cyrix 5530 ATA33 controller */
- atadev->channel->alignment = 0xf;
- if (udmamode >= 2) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA2 on Cyrix chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- cyrix_timing(atadev, devno, ATA_UDMA2);
- ata_dmacreate(atadev, apiomode, ATA_UDMA2);
- return;
- }
- }
- if (wdmamode >= 2 && apiomode >= 4) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting WDMA2 on Cyrix chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- cyrix_timing(atadev, devno, ATA_WDMA2);
- ata_dmacreate(atadev, apiomode, ATA_WDMA2);
- return;
- }
- }
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_PIO0 + apiomode, ATA_C_F_SETXFER,
- ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting %s on Cyrix chip\n",
- (error) ? "failed" : "success",
- ata_mode2str(ATA_PIO0 + apiomode));
- cyrix_timing(atadev, devno, ATA_PIO0 + apiomode);
- atadev->mode = ATA_PIO0 + apiomode;
- return;
-
- case 0x02131166: /* ServerWorks CSB6 ATA 100 controller (chan 0+1) */
- case 0x02121166: /* ServerWorks CSB5 ATA66/100 controller */
- if (udmamode >= 5 && (chiptype == 0x02131166 ||
- (chiptype == 0x02121166 && chiprev >= 0x92))) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA5, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA5 on ServerWorks chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- u_int16_t reg56;
-
- pci_write_config(parent, 0x54,
- pci_read_config(parent, 0x54, 1) |
- (0x01 << devno), 1);
- reg56 = pci_read_config(parent, 0x56, 2);
- reg56 &= ~(0xf << (devno * 4));
- reg56 |= (0x5 << (devno * 4));
- pci_write_config(parent, 0x56, reg56, 2);
- ata_dmacreate(atadev, apiomode, ATA_UDMA5);
- return;
- }
- }
- /* FALLTHROUGH */
-
- case 0x02171166: /* ServerWorks CSB6 ATA 66 controller (chan 2) */
- if (udmamode >= 4) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA4 on ServerWorks chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- u_int16_t reg56;
-
- pci_write_config(parent, 0x54,
- pci_read_config(parent, 0x54, 1) |
- (0x01 << devno), 1);
- reg56 = pci_read_config(parent, 0x56, 2);
- reg56 &= ~(0xf << (devno * 4));
- reg56 |= (0x4 << (devno * 4));
- pci_write_config(parent, 0x56, reg56, 2);
- ata_dmacreate(atadev, apiomode, ATA_UDMA4);
- return;
- }
- }
- /* FALLTHROUGH */
-
- case 0x02111166: /* ServerWorks ROSB4 ATA33 controller */
- if (udmamode >= 2) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA2 on ServerWorks chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- u_int16_t reg56;
-
- pci_write_config(parent, 0x54,
- pci_read_config(parent, 0x54, 1) |
- (0x01 << devno), 1);
- reg56 = pci_read_config(parent, 0x56, 2);
- reg56 &= ~(0xf << (devno * 4));
- reg56 |= (0x2 << (devno * 4));
- pci_write_config(parent, 0x56, reg56, 2);
- ata_dmacreate(atadev, apiomode, ATA_UDMA2);
- return;
- }
- }
- if (wdmamode >= 2 && apiomode >= 4) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting WDMA2 on ServerWorks chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- int offset = devno ^ 0x01;
- int word44 = pci_read_config(parent, 0x44, 4);
-
- pci_write_config(parent, 0x54,
- pci_read_config(parent, 0x54, 1) &
- ~(0x01 << devno), 1);
- word44 &= ~(0xff << (offset << 8));
- word44 |= (0x20 << (offset << 8));
- pci_write_config(parent, 0x44, 0x20, 4);
- ata_dmacreate(atadev, apiomode, ATA_WDMA2);
- return;
- }
- }
- /* we could set PIO mode timings, but we assume the BIOS did that */
- break;
-
- case 0x4d69105a: /* Promise TX2 ATA133 controllers */
- case 0x6269105a: /* Promise TX2 ATA133 controllers */
- case 0x1275105a: /* Promise TX2 ATA133 controllers */
- case 0x5275105a: /* Promise TX2 ATA133 controllers */
- case 0x7275105a: /* Promise TX2 ATA133 controllers */
- ATA_OUTB(atadev->channel->r_bmio, ATA_BMDEVSPEC_0, 0x0b);
- if (udmamode >= 6 &&
- !(ATA_INB(atadev->channel->r_bmio, ATA_BMDEVSPEC_1) & 0x04)) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA6, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA6 on Promise chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- ata_dmacreate(atadev, apiomode, ATA_UDMA6);
- return;
- }
- }
- /* FALLTHROUGH */
-
- case 0x4d68105a: /* Promise TX2 ATA100 controllers */
- case 0x6268105a: /* Promise TX2 ATA100 controllers */
- ATA_OUTB(atadev->channel->r_bmio, ATA_BMDEVSPEC_0, 0x0b);
- if (udmamode >= 5 &&
- !(ATA_INB(atadev->channel->r_bmio, ATA_BMDEVSPEC_1) & 0x04)) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA5, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA5 on Promise chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- ata_dmacreate(atadev, apiomode, ATA_UDMA5);
- return;
- }
- }
- ATA_OUTB(atadev->channel->r_bmio, ATA_BMDEVSPEC_0, 0x0b);
- if (udmamode >= 4 &&
- !(ATA_INB(atadev->channel->r_bmio, ATA_BMDEVSPEC_1) & 0x04)) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA4 on Promise chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- ata_dmacreate(atadev, apiomode, ATA_UDMA4);
- return;
- }
- }
- if (udmamode >= 2) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA on Promise chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- ata_dmacreate(atadev, apiomode, ATA_UDMA2);
- return;
- }
- }
- if (wdmamode >= 2 && apiomode >= 4) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting WDMA2 on Promise chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- ata_dmacreate(atadev, apiomode, ATA_WDMA2);
- return;
- }
- }
- break;
-
- case 0x0d30105a: /* Promise OEM ATA100 controllers */
- case 0x4d30105a: /* Promise Ultra/FastTrak 100 controllers */
- if (!ATAPI_DEVICE(atadev) && udmamode >= 5 &&
- !(pci_read_config(parent, 0x50, 2) & (channel ? 1<<11 : 1<<10))) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA5, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA5 on Promise chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- promise_timing(atadev, devno, ATA_UDMA5);
- ata_dmacreate(atadev, apiomode, ATA_UDMA5);
- return;
- }
- }
- /* FALLTHROUGH */
- case 0x0d38105a: /* Promise FastTrak 66 controllers */
- case 0x4d38105a: /* Promise Ultra/FastTrak 66 controllers */
- if (!ATAPI_DEVICE(atadev) && udmamode >= 4 &&
- !(pci_read_config(parent, 0x50, 2) & (channel ? 1<<11 : 1<<10))) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA4 on Promise chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- promise_timing(atadev, devno, ATA_UDMA4);
- ata_dmacreate(atadev, apiomode, ATA_UDMA4);
- return;
- }
- }
- /* FALLTHROUGH */
-
- case 0x4d33105a: /* Promise Ultra/FastTrak 33 controllers */
- if (!ATAPI_DEVICE(atadev) && udmamode >= 2) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA2 on Promise chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- promise_timing(atadev, devno, ATA_UDMA2);
- ata_dmacreate(atadev, apiomode, ATA_UDMA2);
- return;
- }
- }
- if (!ATAPI_DEVICE(atadev) && wdmamode >= 2 && apiomode >= 4) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting WDMA2 on Promise chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- promise_timing(atadev, devno, ATA_WDMA2);
- ata_dmacreate(atadev, apiomode, ATA_WDMA2);
- return;
- }
- }
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_PIO0 + apiomode,
- ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting PIO%d on Promise chip\n",
- (error) ? "failed" : "success",
- (apiomode >= 0) ? apiomode : 0);
- promise_timing(atadev, devno, ATA_PIO0 + apiomode);
- atadev->mode = ATA_PIO0 + apiomode;
- return;
-
- case 0x00041103: /* HighPoint HPT366/368/370/372 controllers */
- case 0x00051103: /* HighPoint HPT372 controllers */
- case 0x00081103: /* HighPoint HPT374 controllers */
- if (!ATAPI_DEVICE(atadev) && udmamode >= 6 && hpt_cable80(atadev) &&
- ((chiptype == 0x00041103 && chiprev >= 0x05) ||
- (chiptype == 0x00051103 && chiprev >= 0x01) ||
- (chiptype == 0x00081103 && chiprev >= 0x07))) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA6, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA6 on HighPoint chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- hpt_timing(atadev, devno, ATA_UDMA6);
- ata_dmacreate(atadev, apiomode, ATA_UDMA6);
- return;
- }
- }
- if (!ATAPI_DEVICE(atadev) && udmamode >= 5 && hpt_cable80(atadev) &&
- ((chiptype == 0x00041103 && chiprev >= 0x03) ||
- (chiptype == 0x00051103 && chiprev >= 0x01) ||
- (chiptype == 0x00081103 && chiprev >= 0x07))) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA5, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA5 on HighPoint chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- hpt_timing(atadev, devno, ATA_UDMA5);
- ata_dmacreate(atadev, apiomode, ATA_UDMA5);
- return;
- }
- }
- if (!ATAPI_DEVICE(atadev) && udmamode >= 4 && hpt_cable80(atadev)) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA4 on HighPoint chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- hpt_timing(atadev, devno, ATA_UDMA4);
- ata_dmacreate(atadev, apiomode, ATA_UDMA4);
- return;
- }
- }
- if (!ATAPI_DEVICE(atadev) && udmamode >= 2) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting UDMA2 on HighPoint chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- hpt_timing(atadev, devno, ATA_UDMA2);
- ata_dmacreate(atadev, apiomode, ATA_UDMA2);
- return;
- }
- }
- if (!ATAPI_DEVICE(atadev) && wdmamode >= 2 && apiomode >= 4) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting WDMA2 on HighPoint chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- hpt_timing(atadev, devno, ATA_WDMA2);
- ata_dmacreate(atadev, apiomode, ATA_WDMA2);
- return;
- }
- }
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_PIO0 + apiomode,
- ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting PIO%d on HighPoint chip\n",
- (error) ? "failed" : "success",
- (apiomode >= 0) ? apiomode : 0);
- hpt_timing(atadev, devno, ATA_PIO0 + apiomode);
- atadev->mode = ATA_PIO0 + apiomode;
- return;
-
- case 0x00091191: /* Acard ATP865R controller */
- case 0x00081191: /* Acard ATP865 controller */
- if (ATAPI_DEVICE(atadev))
- break;
- if (udmamode >= 6) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA6, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting up UDMA6 mode on Acard chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- u_int16_t reg44 = pci_read_config(parent, 0x44, 2);
-
- reg44 &= ~(0x000f << (devno << 2));
- reg44 |= (0x0007 << (devno << 2));
- pci_write_config(parent, 0x44, reg44, 2);
- pci_write_config(parent, 0x4a, 0xa6, 1);
- pci_write_config(parent, 0x40 + devno, 0x031, 1);
- ata_dmacreate(atadev, apiomode, ATA_UDMA6);
- return;
- }
- }
- if (udmamode >= 5) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA5, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting up UDMA5 mode on Acard chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- u_int16_t reg44 = pci_read_config(parent, 0x44, 2);
-
- reg44 &= ~(0x000f << (devno << 2));
- reg44 |= (0x0006 << (devno << 2));
- pci_write_config(parent, 0x44, reg44, 2);
- pci_write_config(parent, 0x4a, 0xa6, 1);
- pci_write_config(parent, 0x40 + devno, 0x031, 1);
- ata_dmacreate(atadev, apiomode, ATA_UDMA5);
- return;
- }
- }
- /* FALLTHROUGH */
-
- case 0x00071191: /* Acard ATP860R controller */
- case 0x00061191: /* Acard ATP860 controller */
- if (ATAPI_DEVICE(atadev))
- break;
- if (udmamode >= 4) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting up UDMA4 mode on Acard chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- u_int16_t reg44 = pci_read_config(parent, 0x44, 2);
-
- reg44 &= ~(0x000f << (devno << 2));
- reg44 |= (0x0005 << (devno << 2));
- pci_write_config(parent, 0x44, reg44, 2);
- pci_write_config(parent, 0x4a, 0xa6, 1);
- pci_write_config(parent, 0x40 + devno, 0x031, 1);
- ata_dmacreate(atadev, apiomode, ATA_UDMA4);
- return;
- }
- }
- if (udmamode >= 2) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting up UDMA2 mode on Acard chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- u_int16_t reg44 = pci_read_config(parent, 0x44, 2);
-
- reg44 &= ~(0x000f << (devno << 2));
- reg44 |= (0x0003 << (devno << 2));
- pci_write_config(parent, 0x44, reg44, 2);
- pci_write_config(parent, 0x4a, 0xa6, 1);
- pci_write_config(parent, 0x40 + devno, 0x031, 1);
- ata_dmacreate(atadev, apiomode, ATA_UDMA2);
- return;
- }
- }
- if (wdmamode >= 2 && apiomode >= 4) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting up WDMA2 mode on Acard chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- u_int16_t reg44 = pci_read_config(parent, 0x44, 2);
-
- reg44 &= ~(0x000f << (devno << 2));
- pci_write_config(parent, 0x44, reg44, 2);
- pci_write_config(parent, 0x4a, 0xa6, 1);
- pci_write_config(parent, 0x40 + devno, 0x031, 1);
- ata_dmacreate(atadev, apiomode, ATA_WDMA2);
- return;
- }
- }
- /* we could set PIO mode timings, but we assume the BIOS did that */
- break;
-
- case 0x00051191: /* Acard ATP850UF controller */
- if (ATAPI_DEVICE(atadev))
- break;
- if (udmamode >= 2) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting up UDMA2 mode on Acard chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- u_int8_t reg54 = pci_read_config(parent, 0x54, 1);
-
- reg54 |= (0x03 << (devno << 1));
- pci_write_config(parent, 0x54, reg54, 1);
- pci_write_config(parent, 0x4a, 0xa6, 1);
- pci_write_config(parent, 0x40 + (devno << 1), 0x0301, 2);
- ata_dmacreate(atadev, apiomode, ATA_UDMA2);
- return;
- }
- }
- if (wdmamode >= 2 && apiomode >= 4) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting up WDMA2 mode on Acard chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- u_int8_t reg54 = pci_read_config(parent, 0x54, 1);
-
- reg54 &= ~(0x03 << (devno << 1));
- pci_write_config(parent, 0x54, reg54, 1);
- pci_write_config(parent, 0x4a, 0xa6, 1);
- pci_write_config(parent, 0x40 + (devno << 1), 0x0301, 2);
- ata_dmacreate(atadev, apiomode, ATA_WDMA2);
- return;
- }
- }
- /* we could set PIO mode timings, but we assume the BIOS did that */
- break;
-
- case 0x000116ca: /* Cenatek Rocket Drive controller */
- if (wdmamode >= 0 &&
- (ATA_INB(atadev->channel->r_bmio, ATA_BMSTAT_PORT) &
- (device ? ATA_BMSTAT_DMA_SLAVE : ATA_BMSTAT_DMA_MASTER)))
- ata_dmacreate(atadev, apiomode, ATA_DMA);
- else
- atadev->mode = ATA_PIO;
- return;
-
- default: /* unknown controller chip */
- /* better not try generic DMA on ATAPI devices it almost never works */
- if (ATAPI_DEVICE(atadev))
- break;
-
- /* if controller says its setup for DMA take the easy way out */
- /* the downside is we dont know what DMA mode we are in */
- if ((udmamode >= 0 || wdmamode >= 2) &&
- (ATA_INB(atadev->channel->r_bmio, ATA_BMSTAT_PORT) &
- (device ? ATA_BMSTAT_DMA_SLAVE : ATA_BMSTAT_DMA_MASTER))) {
- ata_dmacreate(atadev, apiomode, ATA_DMA);
- return;
- }
-
- /* well, we have no support for this, but try anyways */
- if ((wdmamode >= 2 && apiomode >= 4) && atadev->channel->r_bmio) {
- error = ata_command(atadev, ATA_C_SETFEATURES, 0,
- ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting WDMA2 on generic chip\n",
- (error) ? "failed" : "success");
- if (!error) {
- ata_dmacreate(atadev, apiomode, ATA_WDMA2);
- return;
- }
- }
- }
- error = ata_command(atadev, ATA_C_SETFEATURES, 0, ATA_PIO0 + apiomode,
- ATA_C_F_SETXFER, ATA_WAIT_READY);
- if (bootverbose)
- ata_prtdev(atadev, "%s setting PIO%d on generic chip\n",
- (error) ? "failed" : "success", apiomode < 0 ? 0 : apiomode);
- if (!error)
- atadev->mode = ATA_PIO0 + apiomode;
- else {
- if (bootverbose)
- ata_prtdev(atadev, "using PIO mode set by BIOS\n");
- atadev->mode = ATA_PIO;
+ if (ch->dmatag) {
+ bus_dma_tag_destroy(ch->dmatag);
+ ch->dmatag = NULL;
}
}
@@ -1501,12 +225,13 @@ ata_dmasetupd_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error)
cba->dmatab[j - 1].count = htole32(lastcount | ATA_DMA_EOT);
}
-int
+static int
ata_dmasetup(struct ata_device *atadev, caddr_t data, int32_t count)
{
struct ata_channel *ch = atadev->channel;
- if (((uintptr_t)data & ch->alignment) || (count & ch->alignment)) {
+ if (((uintptr_t)data & (ch->dma->alignment - 1)) ||
+ (count & (ch->dma->alignment - 1))) {
ata_prtdev(atadev, "non aligned DMA transfer attempted\n");
return -1;
}
@@ -1528,20 +253,6 @@ ata_dmastart(struct ata_device *atadev, caddr_t data, int32_t count, int dir)
if (ds->flags & ATA_DS_ACTIVE)
panic("ata_dmasetup: transfer active on this device!");
- switch(ch->chiptype) {
- case 0x0d38105a: /* Promise Fasttrak 66 */
- case 0x4d38105a: /* Promise Ultra/Fasttrak 66 */
- case 0x0d30105a: /* Promise OEM ATA 100 */
- case 0x4d30105a: /* Promise Ultra/Fasttrak 100 */
- 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),
- (dir ? 0x05000000 : 0x06000000) | (count >> 1));
- }
- }
-
cba.dmatab = ds->dmatab;
bus_dmamap_sync(ds->cdmatag, ds->cdmamap, BUS_DMASYNC_PREWRITE);
if (bus_dmamap_load(ds->ddmatag, ds->ddmamap, data, count,
@@ -1566,25 +277,12 @@ ata_dmastart(struct ata_device *atadev, caddr_t data, int32_t count, int dir)
}
int
-ata_dmadone(struct ata_device *atadev)
+ata_dmastop(struct ata_device *atadev)
{
struct ata_channel *ch = atadev->channel;
struct ata_dmastate *ds = &atadev->dmastate;
int error;
- switch(ch->chiptype) {
- case 0x0d38105a: /* Promise Fasttrak 66 */
- case 0x4d38105a: /* Promise Ultra/Fasttrak 66 */
- case 0x0d30105a: /* Promise OEM ATA 100 */
- case 0x4d30105a: /* Promise Ultra/Fasttrak 100 */
- 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);
- }
- }
-
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);
@@ -1599,210 +297,8 @@ ata_dmadone(struct ata_device *atadev)
return (error & ATA_BMSTAT_MASK);
}
-int
+static int
ata_dmastatus(struct ata_channel *ch)
{
return ATA_INB(ch->r_bmio, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
}
-
-static void
-cyrix_timing(struct ata_device *atadev, int devno, int mode)
-{
- u_int32_t reg20 = 0x0000e132;
- u_int32_t reg24 = 0x00017771;
-
- switch (mode) {
- case ATA_PIO0: reg20 = 0x0000e132; break;
- case ATA_PIO1: reg20 = 0x00018121; break;
- case ATA_PIO2: reg20 = 0x00024020; break;
- case ATA_PIO3: reg20 = 0x00032010; break;
- case ATA_PIO4: reg20 = 0x00040010; break;
- case ATA_WDMA2: reg24 = 0x00002020; break;
- case ATA_UDMA2: reg24 = 0x00911030; break;
- }
- ATA_OUTL(atadev->channel->r_bmio, (devno << 3) + 0x20, reg20);
- ATA_OUTL(atadev->channel->r_bmio, (devno << 3) + 0x24, reg24);
-}
-
-static void
-promise_timing(struct ata_device *atadev, int devno, int mode)
-{
- u_int32_t timing = 0;
- /* XXX: Endianess */
- struct promise_timing {
- u_int8_t pa:4;
- u_int8_t prefetch:1;
- u_int8_t iordy:1;
- u_int8_t errdy:1;
- u_int8_t syncin:1;
- u_int8_t pb:5;
- u_int8_t mb:3;
- u_int8_t mc:4;
- u_int8_t dmaw:1;
- u_int8_t dmar:1;
- u_int8_t iordyp:1;
- u_int8_t dmarqp:1;
- u_int8_t reserved:8;
- } *t = (struct promise_timing*)&timing;
-
- t->iordy = 1; t->iordyp = 1;
- if (mode >= ATA_DMA) {
- t->prefetch = 1; t->errdy = 1; t->syncin = 1;
- }
-
- switch (atadev->channel->chiptype) {
- case 0x4d33105a: /* Promise Ultra/Fasttrak 33 */
- switch (mode) {
- default:
- case ATA_PIO0: t->pa = 9; t->pb = 19; t->mb = 7; t->mc = 15; break;
- case ATA_PIO1: t->pa = 5; t->pb = 12; t->mb = 7; t->mc = 15; break;
- case ATA_PIO2: t->pa = 3; t->pb = 8; t->mb = 7; t->mc = 15; break;
- case ATA_PIO3: t->pa = 2; t->pb = 6; t->mb = 7; t->mc = 15; break;
- case ATA_PIO4: t->pa = 1; t->pb = 4; t->mb = 7; t->mc = 15; break;
- case ATA_WDMA2: t->pa = 3; t->pb = 7; t->mb = 3; t->mc = 3; break;
- case ATA_UDMA2: t->pa = 3; t->pb = 7; t->mb = 1; t->mc = 1; break;
- }
- break;
-
- case 0x0d38105a: /* Promise Fasttrak 66 */
- case 0x4d38105a: /* Promise Ultra/Fasttrak 66 */
- case 0x0d30105a: /* Promise OEM ATA 100 */
- case 0x4d30105a: /* Promise Ultra/Fasttrak 100 */
- switch (mode) {
- default:
- case ATA_PIO0: t->pa = 15; t->pb = 31; t->mb = 7; t->mc = 15; break;
- case ATA_PIO1: t->pa = 10; t->pb = 24; t->mb = 7; t->mc = 15; break;
- case ATA_PIO2: t->pa = 6; t->pb = 16; t->mb = 7; t->mc = 15; break;
- case ATA_PIO3: t->pa = 4; t->pb = 12; t->mb = 7; t->mc = 15; break;
- case ATA_PIO4: t->pa = 2; t->pb = 8; t->mb = 7; t->mc = 15; break;
- case ATA_WDMA2: t->pa = 6; t->pb = 14; t->mb = 6; t->mc = 6; break;
- case ATA_UDMA2: t->pa = 6; t->pb = 14; t->mb = 2; t->mc = 2; break;
- case ATA_UDMA4: t->pa = 3; t->pb = 7; t->mb = 1; t->mc = 1; break;
- case ATA_UDMA5: t->pa = 3; t->pb = 7; t->mb = 1; t->mc = 1; break;
- }
- break;
- }
- pci_write_config(device_get_parent(atadev->channel->dev),
- 0x60 + (devno << 2), timing, 4);
-}
-
-static void
-hpt_timing(struct ata_device *atadev, int devno, int mode)
-{
- device_t parent = device_get_parent(atadev->channel->dev);
- u_int32_t chiptype = atadev->channel->chiptype;
- int chiprev = pci_get_revid(parent);
- u_int32_t timing;
-
- if (chiptype == 0x00081103 && chiprev >= 0x07) {
- switch (mode) { /* HPT374 */
- case ATA_PIO0: timing = 0x0ac1f48a; break;
- case ATA_PIO1: timing = 0x0ac1f465; break;
- case ATA_PIO2: timing = 0x0a81f454; break;
- case ATA_PIO3: timing = 0x0a81f443; break;
- case ATA_PIO4: timing = 0x0a81f442; break;
- case ATA_WDMA2: timing = 0x22808242; break;
- case ATA_UDMA2: timing = 0x120c8242; break;
- case ATA_UDMA4: timing = 0x12ac8242; break;
- case ATA_UDMA5: timing = 0x12848242; break;
- case ATA_UDMA6: timing = 0x12808242; break;
- default: timing = 0x0d029d5e;
- }
- }
- else if ((chiptype == 0x00041103 && chiprev >= 0x05) ||
- (chiptype == 0x00051103 && chiprev >= 0x01)) {
- switch (mode) { /* HPT372 */
- case ATA_PIO0: timing = 0x0d029d5e; break;
- case ATA_PIO1: timing = 0x0d029d26; break;
- case ATA_PIO2: timing = 0x0c829ca6; break;
- case ATA_PIO3: timing = 0x0c829c84; break;
- case ATA_PIO4: timing = 0x0c829c62; break;
- case ATA_WDMA2: timing = 0x2c829262; break;
- case ATA_UDMA2: timing = 0x1c91dc62; break;
- case ATA_UDMA4: timing = 0x1c8ddc62; break;
- case ATA_UDMA5: timing = 0x1c6ddc62; break;
- case ATA_UDMA6: timing = 0x1c81dc62; break;
- default: timing = 0x0d029d5e;
- }
- }
- else if (chiptype == 0x00041103 && chiprev >= 0x03) {
- switch (mode) { /* HPT370 */
- case ATA_PIO0: timing = 0x06914e57; break;
- case ATA_PIO1: timing = 0x06914e43; break;
- case ATA_PIO2: timing = 0x06514e33; break;
- case ATA_PIO3: timing = 0x06514e22; break;
- case ATA_PIO4: timing = 0x06514e21; break;
- case ATA_WDMA2: timing = 0x26514e21; break;
- case ATA_UDMA2: timing = 0x16494e31; break;
- case ATA_UDMA4: timing = 0x16454e31; break;
- case ATA_UDMA5: timing = 0x16454e31; break;
- default: timing = 0x06514e57;
- }
- pci_write_config(parent, 0x40 + (devno << 2) , timing, 4);
- }
- else { /* HPT36[68] */
- switch (pci_read_config(parent, 0x41 + (devno << 2), 1)) {
- case 0x85: /* 25Mhz */
- switch (mode) {
- case ATA_PIO0: timing = 0x40d08585; break;
- case ATA_PIO1: timing = 0x40d08572; break;
- case ATA_PIO2: timing = 0x40ca8542; break;
- case ATA_PIO3: timing = 0x40ca8532; break;
- case ATA_PIO4: timing = 0x40ca8521; break;
- case ATA_WDMA2: timing = 0x20ca8521; break;
- case ATA_UDMA2: timing = 0x10cf8521; break;
- case ATA_UDMA4: timing = 0x10c98521; break;
- default: timing = 0x01208585;
- }
- break;
- default:
- case 0xa7: /* 33MHz */
- switch (mode) {
- case ATA_PIO0: timing = 0x40d0a7aa; break;
- case ATA_PIO1: timing = 0x40d0a7a3; break;
- case ATA_PIO2: timing = 0x40d0a753; break;
- case ATA_PIO3: timing = 0x40c8a742; break;
- case ATA_PIO4: timing = 0x40c8a731; break;
- case ATA_WDMA2: timing = 0x20c8a731; break;
- case ATA_UDMA2: timing = 0x10caa731; break;
- case ATA_UDMA4: timing = 0x10c9a731; break;
- default: timing = 0x0120a7a7;
- }
- break;
- case 0xd9: /* 40Mhz */
- switch (mode) {
- case ATA_PIO0: timing = 0x4018d9d9; break;
- case ATA_PIO1: timing = 0x4010d9c7; break;
- case ATA_PIO2: timing = 0x4010d997; break;
- case ATA_PIO3: timing = 0x4010d974; break;
- case ATA_PIO4: timing = 0x4008d963; break;
- case ATA_WDMA2: timing = 0x2008d943; break;
- case ATA_UDMA2: timing = 0x100bd943; break;
- case ATA_UDMA4: timing = 0x100fd943; break;
- default: timing = 0x0120d9d9;
- }
- }
- }
- pci_write_config(parent, 0x40 + (devno << 2) , timing, 4);
-}
-
-static int
-hpt_cable80(struct ata_device *atadev)
-{
- device_t parent = device_get_parent(atadev->channel->dev);
- u_int8_t reg, val, res;
-
- if (atadev->channel->chiptype==0x00081103 && pci_get_function(parent)==1) {
- reg = atadev->channel->unit ? 0x57 : 0x53;
- val = pci_read_config(parent, reg, 1);
- pci_write_config(parent, reg, val | 0x80, 1);
- }
- else {
- reg = 0x5b;
- val = pci_read_config(parent, reg, 1);
- pci_write_config(parent, reg, val & 0xfe, 1);
- }
- res = pci_read_config(parent, 0x5a, 1) & (atadev->channel->unit ? 0x1:0x2);
- pci_write_config(parent, reg, val, 1);
- return !res;
-}
diff --git a/sys/dev/ata/ata-isa.c b/sys/dev/ata/ata-isa.c
index 1034858..a8a6296 100644
--- a/sys/dev/ata/ata-isa.c
+++ b/sys/dev/ata/ata-isa.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -49,15 +49,11 @@ static struct isa_pnp_id ata_ids[] = {
{0x0106d041, "Plus Hardcard II"}, /* PNP0601 */
{0x0206d041, "Plus Hardcard IIXL/EZ"}, /* PNP0602 */
{0x0306d041, "Generic ATA"}, /* PNP0603 */
+ /* PNP0680 */
+ {0x8006d041, "Standard bus mastering IDE hard disk controller"},
{0}
};
-static int
-ata_isa_intrnoop(struct ata_channel *ch)
-{
- return 1;
-
-}
static void
ata_isa_lock(struct ata_channel *ch, int type)
{
@@ -91,8 +87,7 @@ ata_isa_probe(device_t dev)
bus_release_resource(dev, SYS_RES_IOPORT, rid, io);
ch->unit = 0;
ch->flags |= ATA_USE_16BIT;
- ch->intr_func = ata_isa_intrnoop;
- ch->lock_func = ata_isa_lock;
+ ch->locking = ata_isa_lock;
return ata_probe(dev);
}
diff --git a/sys/dev/ata/ata-pci.c b/sys/dev/ata/ata-pci.c
index d77d65a..065e0b0 100644
--- a/sys/dev/ata/ata-pci.c
+++ b/sys/dev/ata/ata-pci.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -45,364 +45,74 @@
#include <pci/pcivar.h>
#include <pci/pcireg.h>
#include <dev/ata/ata-all.h>
+#include <dev/ata/ata-pci.h>
-/* device structures */
-struct ata_pci_controller {
- struct resource *bmio;
- int bmaddr;
- struct resource *irq;
- int irqcnt;
- int lock;
-};
+/* local vars */
+static MALLOC_DEFINE(M_ATAPCI, "ATA PCI", "ATA driver PCI");
/* misc defines */
#define IOMASK 0xfffffffc
-#define GRANDPARENT(dev) device_get_parent(device_get_parent(dev))
-#define ATA_MASTERDEV(dev) ((pci_get_progif(dev) & 0x80) && \
- (pci_get_progif(dev) & 0x05) != 0x05)
-
-int
-ata_find_dev(device_t dev, u_int32_t devid, u_int32_t revid)
-{
- device_t *children;
- int nchildren, i;
-
- if (device_get_children(device_get_parent(dev), &children, &nchildren))
- return 0;
-
- for (i = 0; i < nchildren; i++) {
- if (pci_get_devid(children[i]) == devid &&
- pci_get_revid(children[i]) >= revid) {
- free(children, M_TEMP);
- return 1;
- }
- }
- free(children, M_TEMP);
- return 0;
-}
-static void
-ata_via_southbridge_fixup(device_t dev)
-{
- device_t *children;
- int nchildren, i;
-
- if (device_get_children(device_get_parent(dev), &children, &nchildren))
- return;
-
- for (i = 0; i < nchildren; i++) {
- if (pci_get_devid(children[i]) == 0x03051106 || /* VIA VT8363 */
- pci_get_devid(children[i]) == 0x03911106 || /* VIA VT8371 */
- pci_get_devid(children[i]) == 0x31021106 || /* VIA VT8662 */
- pci_get_devid(children[i]) == 0x31121106) { /* VIA VT8361 */
- u_int8_t reg76 = pci_read_config(children[i], 0x76, 1);
-
- if ((reg76 & 0xf0) != 0xd0) {
- device_printf(dev,
- "Correcting VIA config for southbridge data corruption bug\n");
- pci_write_config(children[i], 0x75, 0x80, 1);
- pci_write_config(children[i], 0x76, (reg76 & 0x0f) | 0xd0, 1);
- }
- break;
- }
- }
- free(children, M_TEMP);
-}
+/* prototypes */
+static int ata_pci_add_child(device_t, int);
+static void ata_pci_locknoop(struct ata_channel *, int);
-static const char *
-ata_pci_match(device_t dev)
+static int
+ata_pci_probe(device_t dev)
{
if (pci_get_class(dev) != PCIC_STORAGE)
- return NULL;
-
- switch (pci_get_devid(dev)) {
- /* supported chipsets */
- case 0x12308086:
- return "Intel PIIX ATA controller";
-
- case 0x70108086:
- return "Intel PIIX3 ATA controller";
-
- case 0x71118086:
- case 0x71998086:
- case 0x84ca8086:
- return "Intel PIIX4 ATA33 controller";
-
- case 0x24218086:
- return "Intel ICH0 ATA33 controller";
-
- case 0x24118086:
- case 0x76018086:
- return "Intel ICH ATA66 controller";
-
- case 0x244a8086:
- case 0x244b8086:
- return "Intel ICH2 ATA100 controller";
-
- case 0x248a8086:
- case 0x248b8086:
- return "Intel ICH3 ATA100 controller";
-
- case 0x24cb8086:
- return "Intel ICH4 ATA100 controller";
-
- case 0x522910b9:
- if (pci_get_revid(dev) >= 0xc4)
- return "AcerLabs Aladdin ATA100 controller";
- else if (pci_get_revid(dev) >= 0xc2)
- return "AcerLabs Aladdin ATA66 controller";
- else if (pci_get_revid(dev) >= 0x20)
- return "AcerLabs Aladdin ATA33 controller";
- else
- return "AcerLabs Aladdin ATA controller";
-
- case 0x05711106:
- if (ata_find_dev(dev, 0x05861106, 0x02))
- return "VIA 82C586 ATA33 controller";
- if (ata_find_dev(dev, 0x05861106, 0))
- return "VIA 82C586 ATA controller";
- if (ata_find_dev(dev, 0x05961106, 0x12))
- return "VIA 82C596 ATA66 controller";
- if (ata_find_dev(dev, 0x05961106, 0))
- return "VIA 82C596 ATA33 controller";
- if (ata_find_dev(dev, 0x06861106, 0x40))
- return "VIA 82C686 ATA100 controller";
- if (ata_find_dev(dev, 0x06861106, 0x10))
- return "VIA 82C686 ATA66 controller";
- if (ata_find_dev(dev, 0x06861106, 0))
- return "VIA 82C686 ATA33 controller";
- if (ata_find_dev(dev, 0x82311106, 0))
- return "VIA 8231 ATA100 controller";
- if (ata_find_dev(dev, 0x30741106, 0) ||
- ata_find_dev(dev, 0x31091106, 0))
- return "VIA 8233 ATA100 controller";
- if (ata_find_dev(dev, 0x31471106, 0))
- return "VIA 8233 ATA133 controller";
- if (ata_find_dev(dev, 0x31771106, 0))
- return "VIA 8235 ATA133 controller";
- return "VIA Apollo ATA controller";
-
- case 0x55131039:
- if (ata_find_dev(dev, 0x06301039, 0x30) ||
- ata_find_dev(dev, 0x06331039, 0) ||
- ata_find_dev(dev, 0x06351039, 0) ||
- ata_find_dev(dev, 0x06401039, 0) ||
- ata_find_dev(dev, 0x06451039, 0) ||
- ata_find_dev(dev, 0x06501039, 0) ||
- ata_find_dev(dev, 0x07301039, 0) ||
- ata_find_dev(dev, 0x07331039, 0) ||
- ata_find_dev(dev, 0x07351039, 0) ||
- ata_find_dev(dev, 0x07401039, 0) ||
- ata_find_dev(dev, 0x07451039, 0) ||
- ata_find_dev(dev, 0x07501039, 0))
- return "SiS 5591 ATA100 controller";
- else if (ata_find_dev(dev, 0x05301039, 0) ||
- ata_find_dev(dev, 0x05401039, 0) ||
- ata_find_dev(dev, 0x06201039, 0) ||
- ata_find_dev(dev, 0x06301039, 0))
- return "SiS 5591 ATA66 controller";
- else
- return "SiS 5591 ATA33 controller";
-
- case 0x06801095:
- return "Sil 0680 ATA133 controller";
-
- case 0x06491095:
- return "CMD 649 ATA100 controller";
-
- case 0x06481095:
- return "CMD 648 ATA66 controller";
-
- case 0x06461095:
- return "CMD 646 ATA controller";
-
- case 0xc6931080:
- if (pci_get_subclass(dev) == PCIS_STORAGE_IDE)
- return "Cypress 82C693 ATA controller";
- return NULL;
-
- case 0x01021078:
- return "Cyrix 5530 ATA33 controller";
-
- case 0x74091022:
- return "AMD 756 ATA66 controller";
-
- case 0x74111022:
- return "AMD 766 ATA100 controller";
-
- case 0x74411022:
- return "AMD 768 ATA100 controller";
-
- case 0x01bc10de:
- return "nVidia nForce ATA100 controller";
-
- case 0x006510de:
- return "nVidia nForce ATA133 controller";
-
- case 0x02111166:
- return "ServerWorks ROSB4 ATA33 controller";
-
- case 0x02121166:
- if (pci_get_revid(dev) >= 0x92)
- return "ServerWorks CSB5 ATA100 controller";
- else
- return "ServerWorks CSB5 ATA66 controller";
-
- case 0x02131166:
- return "ServerWorks CSB6 ATA100 controller (channel 0+1)";
-
- case 0x02171166:
- return "ServerWorks CSB6 ATA66 controller (channel 2)";
-
- case 0x4d33105a:
- return "Promise ATA33 controller";
-
- case 0x0d38105a:
- case 0x4d38105a:
- return "Promise ATA66 controller";
-
- case 0x0d30105a:
- case 0x4d30105a:
- return "Promise ATA100 controller";
-
- case 0x4d68105a:
- case 0x6268105a:
- {
- uintptr_t devid = 0;
-
- /* test if we are behind the right type of bridge */
- if (!BUS_READ_IVAR(device_get_parent(GRANDPARENT(dev)),
- GRANDPARENT(dev), PCI_IVAR_DEVID, &devid) &&
- devid == 0x00221011 &&
- pci_get_class(GRANDPARENT(dev)) == PCIC_BRIDGE) {
- static long start = 0, end = 0;
-
- /* we belive we are on a TX4, now do our (simple) magic */
- if (pci_get_slot(dev) == 1) {
- bus_get_resource(dev, SYS_RES_IRQ, 0, &start, &end);
- return "Promise TX4 ATA100 controller (channel 0+1)";
- }
- else if (pci_get_slot(dev) == 2 && start && end) {
- bus_set_resource(dev, SYS_RES_IRQ, 0, start, end);
- start = end = 0;
- return "Promise TX4 ATA100 controller (channel 2+3)";
- }
- else
- start = end = 0;
- }
- }
- return "Promise TX2 ATA100 controller";
-
- case 0x1275105a:
- case 0x5275105a:
- case 0x7275105a:
- {
- uintptr_t devid = 0;
-
- /* if we are on a SuperTrak SX6000 dont attach */
- if (!BUS_READ_IVAR(device_get_parent(GRANDPARENT(dev)),
- GRANDPARENT(dev), PCI_IVAR_DEVID, &devid) &&
- devid == 0x09628086 &&
- pci_get_class(GRANDPARENT(dev)) == PCIC_BRIDGE)
- break;
- }
- /* FALLTHROUGH */
-
- case 0x4d69105a:
- case 0x6269105a:
- return "Promise TX2 ATA133 controller";
-
- case 0x00041103:
- switch (pci_get_revid(dev)) {
- case 0x00:
- case 0x01:
- return "HighPoint HPT366 ATA66 controller";
- case 0x02:
- return "HighPoint HPT368 ATA66 controller";
- case 0x03:
- case 0x04:
- return "HighPoint HPT370 ATA100 controller";
- case 0x05:
- return "HighPoint HPT372 ATA133 controller";
- }
- return NULL;
+ return ENXIO;
- case 0x00051103:
- switch (pci_get_revid(dev)) {
- case 0x01:
- return "HighPoint HPT372 ATA133 controller";
- }
- return NULL;
-
- case 0x00081103:
- switch (pci_get_revid(dev)) {
- case 0x07:
- if (pci_get_function(dev) == 0)
- return "HighPoint HPT374 ATA133 controller (channel 0+1)";
- if (pci_get_function(dev) == 1)
- return "HighPoint HPT374 ATA133 controller (channel 2+3)";
- return "HighPoint HPT374 ATA133 controller";
+ switch (pci_get_vendor(dev)) {
+ case ATA_ACARD_ID:
+ return ata_acard_ident(dev);
+ case ATA_ACER_LABS_ID:
+ return ata_ali_ident(dev);
+ case ATA_AMD_ID:
+ return ata_amd_ident(dev);
+ case ATA_CYRIX_ID:
+ return ata_cyrix_ident(dev);
+ case ATA_CYPRESS_ID:
+ return ata_cypress_ident(dev);
+ case ATA_HIGHPOINT_ID:
+ return ata_highpoint_ident(dev);
+ case ATA_INTEL_ID:
+ return ata_intel_ident(dev);
+ case ATA_NVIDIA_ID:
+ return ata_nvidia_ident(dev);
+ case ATA_PROMISE_ID:
+ return ata_promise_ident(dev);
+ case ATA_SERVERWORKS_ID:
+ return ata_serverworks_ident(dev);
+ case ATA_SILICON_IMAGE_ID:
+ return ata_sii_ident(dev);
+ case ATA_SIS_ID:
+ return ata_sis_ident(dev);
+ case ATA_VIA_ID:
+ return ata_via_ident(dev);
+
+ case 0x16ca:
+ if (pci_get_devid(dev) == 0x000116ca) {
+ device_set_desc(dev, "Cenatek Rocket Drive controller");
+ return 0;
}
- return NULL;
-
- case 0x00051191:
- return "Acard ATP850 ATA-33 controller";
-
- case 0x00061191:
- case 0x00071191:
- return "Acard ATP860 ATA-66 controller";
-
- case 0x00081191:
- case 0x00091191:
- return "Acard ATP865 ATA-133 controller";
-
- case 0x000116ca:
- return "Cenatek Rocket Drive controller";
-
- /* unsupported but known chipsets, generic DMA only */
- case 0x10001042:
- case 0x10011042:
- return "RZ 100? ATA controller !WARNING! buggy chip data loss possible";
+ return ENXIO;
- case 0x06401095:
- return "CMD 640 ATA controller !WARNING! buggy chip data loss possible";
+ case 0x1042:
+ if (pci_get_devid(dev)==0x10001042 || pci_get_devid(dev)==0x10011042) {
+ device_set_desc(dev,
+ "RZ 100? ATA controller !WARNING! buggy HW data loss possible");
+ return 0;
+ }
+ return ENXIO;
- /* unknown chipsets, try generic DMA if it seems possible */
+ /* unknown chipset, try generic DMA if it seems possible */
default:
if (pci_get_class(dev) == PCIC_STORAGE &&
(pci_get_subclass(dev) == PCIS_STORAGE_IDE))
- return "Generic PCI ATA controller";
+ return ata_generic_ident(dev);
}
- return NULL;
-}
-
-static int
-ata_pci_probe(device_t dev)
-{
- const char *desc = ata_pci_match(dev);
-
- if (desc) {
- device_set_desc(dev, desc);
- return 0;
- }
- else
- return ENXIO;
-}
-
-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;
+ return ENXIO;
}
static int
@@ -436,155 +146,25 @@ ata_pci_attach(device_t dev)
/* is there a valid port range to connect to ? */
rid = 0x20;
- controller->bmio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
- 0, ~0, 1, RF_ACTIVE);
- if (!controller->bmio)
+ 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");
}
else
device_printf(dev, "Busmastering DMA not supported\n");
- /* do extra chipset specific setups */
- switch (type) {
-
- case 0x522910b9: /* AcerLabs Aladdin need to activate the ATAPI FIFO */
- pci_write_config(dev, 0x53,
- (pci_read_config(dev, 0x53, 1) & ~0x01) | 0x02, 1);
- break;
-
- case 0x0d30105a: /* Promise 66 & 100 (before TX2) need the clock changed */
- case 0x4d30105a:
- case 0x0d38105a:
- case 0x4d38105a:
- ATA_OUTB(controller->bmio, 0x11, ATA_INB(controller->bmio, 0x11)|0x0a);
- /* FALLTHROUGH */
-
- case 0x4d33105a: /* Promise (before TX2) need burst mode turned on */
- ATA_OUTB(controller->bmio, 0x1f, ATA_INB(controller->bmio, 0x1f)|0x01);
- break;
-
- case 0x00041103: /* HighPoint HPT366/368/370/372 default setup */
- if (pci_get_revid(dev) < 2) { /* HPT366 */
- /* turn off interrupt prediction */
- pci_write_config(dev, 0x51,
- (pci_read_config(dev, 0x51, 1) & ~0x80), 1);
- break;
- }
- if (pci_get_revid(dev) < 5) { /* HPT368/370 */
- /* turn off interrupt prediction */
- pci_write_config(dev, 0x51,
- (pci_read_config(dev, 0x51, 1) & ~0x03), 1);
- pci_write_config(dev, 0x55,
- (pci_read_config(dev, 0x55, 1) & ~0x03), 1);
-
- /* turn on interrupts */
- pci_write_config(dev, 0x5a,
- (pci_read_config(dev, 0x5a, 1) & ~0x10), 1);
-
- /* set clocks etc */
- pci_write_config(dev, 0x5b, 0x22, 1);
- break;
- }
- /* FALLTHROUGH */
-
- case 0x00051103: /* HighPoint HPT372 default setup */
- case 0x00081103: /* HighPoint HPT374 default setup */
- /* turn off interrupt prediction */
- pci_write_config(dev, 0x51, (pci_read_config(dev, 0x51, 1) & ~0x03), 1);
- pci_write_config(dev, 0x55, (pci_read_config(dev, 0x55, 1) & ~0x03), 1);
-
- /* turn on interrupts */
- pci_write_config(dev, 0x5a, (pci_read_config(dev, 0x5a, 1) & ~0x10), 1);
-
- /* set clocks etc */
- pci_write_config(dev, 0x5b,
- (pci_read_config(dev, 0x5b, 1) & 0x01) | 0x20, 1);
- break;
-
- case 0x05711106: /* VIA 82C586, '596, '686 default setup */
- /* prepare for ATA-66 on the 82C686a and 82C596b */
- if ((ata_find_dev(dev, 0x06861106, 0x10) &&
- !ata_find_dev(dev, 0x06861106, 0x40)) ||
- ata_find_dev(dev, 0x05961106, 0x12))
- pci_write_config(dev, 0x50, 0x030b030b, 4);
-
- /* the southbridge might need the data corruption fix */
- if (ata_find_dev(dev, 0x06861106, 0x40) ||
- ata_find_dev(dev, 0x82311106, 0x10))
- ata_via_southbridge_fixup(dev);
- /* FALLTHROUGH */
-
- case 0x74091022: /* AMD 756 default setup */
- case 0x74111022: /* AMD 766 default setup */
- case 0x74411022: /* AMD 768 default setup */
- case 0x01bc10de: /* nVIDIA nForce default setup */
- /* set prefetch, postwrite */
- pci_write_config(dev, 0x41, pci_read_config(dev, 0x41, 1) | 0xf0, 1);
-
- /* set fifo configuration half'n'half */
- pci_write_config(dev, 0x43,
- (pci_read_config(dev, 0x43, 1) & 0x90) | 0x2a, 1);
-
- /* set status register read retry */
- pci_write_config(dev, 0x44, pci_read_config(dev, 0x44, 1) | 0x08, 1);
-
- /* set DMA read & end-of-sector fifo flush */
- pci_write_config(dev, 0x46,
- (pci_read_config(dev, 0x46, 1) & 0x0c) | 0xf0, 1);
-
- /* set sector size */
- pci_write_config(dev, 0x60, DEV_BSIZE, 2);
- pci_write_config(dev, 0x68, DEV_BSIZE, 2);
- break;
-
- case 0x02111166: /* ServerWorks ROSB4 enable UDMA33 */
- pci_write_config(dev, 0x64,
- (pci_read_config(dev, 0x64, 4) & ~0x00002000) |
- 0x00004000, 4);
- break;
-
- case 0x02121166: /* ServerWorks CSB5 enable UDMA66/100 depending on rev */
- pci_write_config(dev, 0x5a,
- (pci_read_config(dev, 0x5a, 1) & ~0x40) |
- (pci_get_revid(dev) >= 0x92) ? 0x03 : 0x02, 1);
- break;
-
- case 0x06801095: /* Sil 0680 set ATA reference clock speed */
- if ((pci_read_config(dev, 0x8a, 1) & 0x30) != 0x10)
- pci_write_config(dev, 0x8a,
- (pci_read_config(dev, 0x8a, 1) & 0x0F) | 0x10, 1);
- if ((pci_read_config(dev, 0x8a, 1) & 0x30) != 0x10)
- device_printf(dev, "Sil 0680 could not set clock\n");
- break;
-
- case 0x06461095: /* CMD 646 enable interrupts, set DMA read mode */
- pci_write_config(dev, 0x71, 0x01, 1);
- break;
-
- case 0x10001042: /* RZ 100? known bad, no DMA */
- case 0x10011042:
- case 0x06401095: /* CMD 640 known bad, no DMA */
- controller->bmio = NULL;
- device_printf(dev, "Busmastering DMA disabled\n");
- }
+ /* do chipset specific setups only needed once */
+ controller->dmainit = ata_dmainit;
+ controller->locking = ata_pci_locknoop;
+ controller->chipinit(dev);
- if (controller->bmio) {
- controller->bmaddr = rman_get_start(controller->bmio);
+ 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->bmio);
- controller->bmio = NULL;
+ SYS_RES_IOPORT, rid, controller->r_bmio);
+ controller->r_bmio = NULL;
}
- controller->lock = -1;
-
- /*
- * the Cypress chip is a mess, it contains two ATA functions, but
- * both channels are visible on the first one.
- * simply ignore the second function for now, as the right
- * solution (ignoring the second channel on the first function)
- * doesn't work with the crappy ATA interrupt setup on the alpha.
- */
- if (pci_get_devid(dev) == 0xc6931080 && pci_get_function(dev) > 1)
- return 0;
ata_pci_add_child(dev, 0);
@@ -595,117 +175,19 @@ ata_pci_attach(device_t dev)
}
static int
-ata_pci_intr(struct ata_channel *ch)
+ata_pci_add_child(device_t dev, int unit)
{
- u_int8_t dmastat;
-
- /*
- * since we might share the IRQ with another device, and in some
- * cases with our twin channel, we only want to process interrupts
- * that we know this channel generated.
- */
- switch (ch->chiptype) {
- case 0x00041103: /* HighPoint HPT366/368/370/372 */
- case 0x00051103: /* HighPoint HPT372 */
- case 0x00081103: /* HighPoint HPT374 */
- if (((dmastat = ata_dmastatus(ch)) &
- (ATA_BMSTAT_ACTIVE | ATA_BMSTAT_INTERRUPT)) != ATA_BMSTAT_INTERRUPT)
- return 0;
- ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, dmastat | ATA_BMSTAT_INTERRUPT);
- DELAY(1);
- return 1;
-
- case 0x06481095: /* CMD 648 */
- case 0x06491095: /* CMD 649 */
- if (!(pci_read_config(device_get_parent(ch->dev), 0x71, 1) &
- (ch->unit ? 0x08 : 0x04)))
- return 0;
- break;
-
- case 0x4d33105a: /* Promise Ultra/Fasttrak 33 */
- case 0x0d38105a: /* Promise Fasttrak 66 */
- case 0x4d38105a: /* Promise Ultra/Fasttrak 66 */
- case 0x0d30105a: /* Promise OEM ATA100 */
- case 0x4d30105a: /* Promise Ultra/Fasttrak 100 */
- if (!(ATA_INL(ch->r_bmio, (ch->unit ? 0x14 : 0x1c)) &
- (ch->unit ? 0x00004000 : 0x00000400)))
- return 0;
- break;
-
- case 0x4d68105a: /* Promise TX2 ATA100 */
- case 0x6268105a: /* Promise TX2 ATA100 */
- case 0x4d69105a: /* Promise TX2 ATA133 */
- case 0x1275105a: /* Promise TX2 ATA133 */
- case 0x5275105a: /* Promise TX2 ATA133 */
- case 0x6269105a: /* Promise TX2 ATA133 */
- case 0x7275105a: /* Promise TX2 ATA133 */
- ATA_OUTB(ch->r_bmio, ATA_BMDEVSPEC_0, 0x0b);
- if (!(ATA_INB(ch->r_bmio, ATA_BMDEVSPEC_1) & 0x20))
- return 0;
- break;
-
- case 0x00051191: /* Acard ATP850 */
- {
- struct ata_pci_controller *scp =
- device_get_softc(device_get_parent(ch->dev));
-
- if (ch->unit != scp->lock)
- return 0;
- }
- /* FALLTHROUGH */
-
- case 0x00061191: /* Acard ATP860 */
- case 0x00071191: /* Acard ATP860R */
- case 0x00081191: /* Acard ATP865 */
- case 0x00091191: /* Acard ATP865R */
- if (ch->flags & ATA_DMA_ACTIVE) {
- if (!((dmastat = ata_dmastatus(ch)) & ATA_BMSTAT_INTERRUPT))
- return 0;
- ATA_OUTB(ch->r_bmio, 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);
- DELAY(1);
- }
- return 1;
- }
-
- if (ch->flags & ATA_DMA_ACTIVE) {
- if (!((dmastat = ata_dmastatus(ch)) & ATA_BMSTAT_INTERRUPT))
- return 0;
- ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, dmastat | ATA_BMSTAT_INTERRUPT);
- DELAY(1);
+ /* check if this is located at one of the std addresses */
+ if (ATA_MASTERDEV(dev)) {
+ if (!device_add_child(dev, "ata", unit))
+ return ENOMEM;
}
- return 1;
-}
-
-static void
-ata_pci_locknoop(struct ata_channel *ch, int type)
-{
-}
-
-static void
-ata_pci_serialize(struct ata_channel *ch, int flags)
-{
- struct ata_pci_controller *scp =
- device_get_softc(device_get_parent(ch->dev));
-
- switch (flags) {
- case ATA_LF_LOCK:
- if (scp->lock == ch->unit)
- break;
- while (!atomic_cmpset_acq_int(&scp->lock, -1, ch->unit))
- tsleep((caddr_t)ch->lock_func, PRIBIO, "atalck", 1);
- break;
-
- case ATA_LF_UNLOCK:
- if (scp->lock == -1 || scp->lock != ch->unit)
- break;
- atomic_store_rel_int(&scp->lock, -1);
- wakeup((caddr_t)ch->lock_func);
- break;
+ else {
+ if (!device_add_child(dev, "ata",
+ devclass_find_free_unit(ata_devclass, 2)))
+ return ENOMEM;
}
- return;
+ return 0;
}
static int
@@ -730,8 +212,8 @@ ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
u_long start, u_long end, u_long count, u_int flags)
{
struct ata_pci_controller *controller = device_get_softc(dev);
- struct resource *res = NULL;
int unit = ((struct ata_channel *)device_get_softc(child))->unit;
+ struct resource *res = NULL;
int myrid;
if (type == SYS_RES_IOPORT) {
@@ -798,24 +280,18 @@ ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
}
if (type == SYS_RES_IRQ && *rid == ATA_IRQ_RID) {
- if (ATA_MASTERDEV(dev)) {
+ if (ATA_MASTERDEV(dev)) {
#ifdef __alpha__
return alpha_platform_alloc_ide_intr(unit);
#else
int irq = (unit == 0 ? 14 : 15);
-
+
return BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
SYS_RES_IRQ, rid, irq, irq, 1, flags);
#endif
}
else {
- /* primary and secondary channels share interrupt, keep track */
- if (!controller->irq)
- controller->irq = BUS_ALLOC_RESOURCE(device_get_parent(dev),
- dev, SYS_RES_IRQ,
- rid, 0, ~0, 1, flags);
- controller->irqcnt++;
- return controller->irq;
+ return controller->r_irq;
}
}
return 0;
@@ -825,7 +301,6 @@ static int
ata_pci_release_resource(device_t dev, device_t child, int type, int rid,
struct resource *r)
{
- struct ata_pci_controller *controller = device_get_softc(dev);
int unit = ((struct ata_channel *)device_get_softc(child))->unit;
if (type == SYS_RES_IOPORT) {
@@ -867,34 +342,35 @@ ata_pci_release_resource(device_t dev, device_t child, int type, int rid,
SYS_RES_IRQ, rid, r);
#endif
}
- else {
- /* primary and secondary channels share interrupt, keep track */
- if (--controller->irqcnt)
- return 0;
- controller->irq = NULL;
- return BUS_RELEASE_RESOURCE(device_get_parent(dev), dev,
- SYS_RES_IRQ, rid, r);
- }
+ else
+ return 0;
}
return EINVAL;
}
static int
ata_pci_setup_intr(device_t dev, device_t child, struct resource *irq,
- int flags, driver_intr_t *intr, void *arg,
+ int flags, driver_intr_t *function, void *argument,
void **cookiep)
{
if (ATA_MASTERDEV(dev)) {
#ifdef __alpha__
- return alpha_platform_setup_ide_intr(child, irq, intr, arg, cookiep);
+ return alpha_platform_setup_ide_intr(child, irq, function, argument,
+ cookiep);
#else
return BUS_SETUP_INTR(device_get_parent(dev), child, irq,
- flags, intr, arg, cookiep);
+ flags, function, argument, cookiep);
#endif
}
- else
- return BUS_SETUP_INTR(device_get_parent(dev), dev, irq,
- flags, intr, arg, cookiep);
+ else {
+ struct ata_pci_controller *controller = device_get_softc(dev);
+ int unit = ((struct ata_channel *)device_get_softc(child))->unit;
+
+ controller->interrupt[unit].function = function;
+ controller->interrupt[unit].argument = argument;
+ *cookiep = controller;
+ return 0;
+ }
}
static int
@@ -909,9 +385,15 @@ ata_pci_teardown_intr(device_t dev, device_t child, struct resource *irq,
#endif
}
else
- return BUS_TEARDOWN_INTR(device_get_parent(dev), dev, irq, cookie);
+ 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),
@@ -944,9 +426,10 @@ DRIVER_MODULE(atapci, pci, ata_pci_driver, ata_pci_devclass, 0, 0);
static int
ata_pcisub_probe(device_t dev)
{
+ struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
device_t *children;
- int count, i;
+ int count, error, i;
/* find channel number on this controller */
device_get_children(device_get_parent(dev), &children, &count);
@@ -956,19 +439,24 @@ ata_pcisub_probe(device_t dev)
}
free(children, M_TEMP);
- ch->intr_func = ata_pci_intr;
+ 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));
- switch (ch->chiptype) {
- case 0x10001042: /* RZ 1000 */
- case 0x10011042: /* RZ 1001 */
- case 0x06401095: /* CMD 640 */
- case 0x00051191: /* Acard ATP850 */
- ch->lock_func = ata_pci_serialize;
- break;
- default:
- ch->lock_func = ata_pci_locknoop;
+
+ 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 ata_probe(dev);
+ return error;
}
static device_method_t ata_pcisub_methods[] = {
diff --git a/sys/dev/ata/ata-pci.h b/sys/dev/ata/ata-pci.h
new file mode 100644
index 0000000..157bc6a
--- /dev/null
+++ b/sys/dev/ata/ata-pci.h
@@ -0,0 +1,262 @@
+/*-
+ * Copyright (c) 2003 Søren Schmidt <sos@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification, immediately at the beginning of the file.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/* 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;
+};
+
+/* structure describing a PCI ATA controller */
+struct ata_pci_controller {
+ struct resource *r_bmio;
+ int bmaddr;
+ struct resource *r_irq;
+ void *handle;
+ struct ata_chip_id *chip;
+ int (*chipinit)(device_t);
+ int (*dmainit)(struct ata_channel *);
+ void (*setmode)(struct ata_device *, int);
+ void (*locking)(struct ata_channel *, int);
+ int locked_ch;
+ struct {
+ void (*function)(void *);
+ void *argument;
+ } interrupt[2];
+};
+
+#define ATA_MASTERDEV(dev) ((pci_get_progif(dev) & 0x80) && \
+ (pci_get_progif(dev) & 0x05) != 0x05)
+
+/* defines for known chipset PCI id's */
+#define ATA_ACARD_ID 0x1191
+#define ATA_ATP850 0x00021191
+#define ATA_ATP850A 0x00041191
+#define ATA_ATP850R 0x00051191
+#define ATA_ATP860A 0x00061191
+#define ATA_ATP860R 0x00071191
+#define ATA_ATP865A 0x00081191
+#define ATA_ATP865R 0x00091191
+
+#define ATA_AMD_ID 0x1022
+#define ATA_AMD755 0x74011022
+#define ATA_AMD756 0x74091022
+#define ATA_AMD766 0x74111022
+#define ATA_AMD768 0x74411022
+#define ATA_AMD8111 0x74691022
+
+#define ATA_ACER_LABS_ID 0x10b9
+#define ATA_ALI_5229 0x522910b9
+
+#define ATA_CYRIX_ID 0x1078
+#define ATA_CYRIX_5530 0x01021078
+
+#define ATA_CYPRESS_ID 0x1080
+#define ATA_CYPRESS_82C693 0xc6931080
+
+#define ATA_DEC_21150 0x00221011
+
+#define ATA_HIGHPOINT_ID 0x1103
+#define ATA_HPT366 0x00041103
+#define ATA_HPT372 0x00051103
+#define ATA_HPT302 0x00061103
+#define ATA_HPT371 0x00071103
+#define ATA_HPT374 0x00081103
+
+#define ATA_INTEL_ID 0x8086
+#define ATA_I960RM 0x09628086
+#define ATA_I82371FB 0x12308086
+#define ATA_I82371SB 0x70108086
+#define ATA_I82371AB 0x71118086
+#define ATA_I82443MX 0x71998086
+#define ATA_I82451NX 0x84ca8086
+#define ATA_I82372FB 0x76018086
+#define ATA_I82801AB 0x24218086
+#define ATA_I82801AA 0x24118086
+#define ATA_I82801BA 0x244a8086
+#define ATA_I82801BA_1 0x244b8086
+#define ATA_I82801CA 0x248a8086
+#define ATA_I82801CA_1 0x248b8086
+#define ATA_I82801DB 0x24cb8086
+
+#define ATA_NVIDIA_ID 0x10de
+#define ATA_NFORCE1 0x01bc10de
+#define ATA_NFORCE2 0x006510de
+
+#define ATA_PROMISE_ID 0x105a
+#define ATA_PDC20246 0x4d33105a
+#define ATA_PDC20262 0x4d38105a
+#define ATA_PDC20263 0x0d38105a
+#define ATA_PDC20265 0x0d30105a
+#define ATA_PDC20267 0x4d30105a
+#define ATA_PDC20268 0x4d68105a
+#define ATA_PDC20268R 0x6268105a
+#define ATA_PDC20269 0x4d69105a
+#define ATA_PDC20271 0x6269105a
+#define ATA_PDC20275 0x1275105a
+#define ATA_PDC20276 0x5275105a
+#define ATA_PDC20277 0x7275105a
+#define ATA_PDC20376 0x3376105a
+
+#define ATA_SERVERWORKS_ID 0x1166
+#define ATA_ROSB4 0x02111166
+#define ATA_CSB5 0x02121166
+#define ATA_CSB6 0x02131166
+#define ATA_CSB6_1 0x02171166
+
+#define ATA_SILICON_IMAGE_ID 0x1095
+#define ATA_SII0680 0x06801095
+#define ATA_CMD646 0x06461095
+#define ATA_CMD648 0x06481095
+#define ATA_CMD649 0x06491095
+
+#define ATA_SIS_ID 0x1039
+#define ATA_SISSOUTH 0x00081039
+#define ATA_SIS5511 0x55111039
+#define ATA_SIS5513 0x55131039
+#define ATA_SIS5518 0x55181039
+#define ATA_SIS5571 0x55711039
+#define ATA_SIS5591 0x55911039
+#define ATA_SIS5596 0x55961039
+#define ATA_SIS5597 0x55971039
+#define ATA_SIS5598 0x55981039
+#define ATA_SIS5600 0x56001039
+#define ATA_SIS530 0x05301039
+#define ATA_SIS540 0x05401039
+#define ATA_SIS550 0x05501039
+#define ATA_SIS620 0x06201039
+#define ATA_SIS630 0x06301039
+#define ATA_SIS635 0x06351039
+#define ATA_SIS633 0x06331039
+#define ATA_SIS640 0x06401039
+#define ATA_SIS645 0x06451039
+#define ATA_SIS646 0x06461039
+#define ATA_SIS648 0x06481039
+#define ATA_SIS650 0x06501039
+#define ATA_SIS651 0x06511039
+#define ATA_SIS652 0x06521039
+#define ATA_SIS655 0x06551039
+#define ATA_SIS658 0x06581039
+#define ATA_SIS730 0x07301039
+#define ATA_SIS733 0x07331039
+#define ATA_SIS735 0x07351039
+#define ATA_SIS740 0x07401039
+#define ATA_SIS745 0x07451039
+#define ATA_SIS746 0x07461039
+#define ATA_SIS748 0x07481039
+#define ATA_SIS750 0x07501039
+#define ATA_SIS751 0x07511039
+#define ATA_SIS752 0x07521039
+#define ATA_SIS755 0x07551039
+#define ATA_SIS961 0x09611039
+#define ATA_SIS962 0x09621039
+#define ATA_SIS963 0x09631039
+
+#define ATA_VIA_ID 0x1106
+#define ATA_VIA82C571 0x05711106
+#define ATA_VIA82C586 0x05861106
+#define ATA_VIA82C596 0x05961106
+#define ATA_VIA82C686 0x06861106
+#define ATA_VIA8231 0x82311106
+#define ATA_VIA8233 0x30741106
+#define ATA_VIA8233A 0x31471106
+#define ATA_VIA8233C 0x31091106
+#define ATA_VIA8235 0x31771106
+#define ATA_VIA8361 0x31121106
+#define ATA_VIA8363 0x03051106
+#define ATA_VIA8371 0x03911106
+#define ATA_VIA8662 0x31021106
+
+/* chipset setup related defines */
+#define ATPOLD 1
+
+#define ALIOLD 0x01
+#define ALICABLE 0x02
+
+#define HPT366 0
+#define HPT370 1
+#define HPT372 2
+#define HPT374 3
+#define HPTOLD 0x01
+
+#define PROLD 0
+#define PRNEW 1
+#define PRTX2 2
+#define PRTX4 0x01
+#define PRSX6K 0x02
+
+#define SWKS33 0
+#define SWKS66 1
+#define SWKS100 2
+
+#define SII_SETCLK 1
+#define SII_INTR 0x01
+
+#define SIS_SOUTH 1
+#define SIS133NEW 2
+#define SIS133OLD 3
+#define SIS100NEW 4
+#define SIS100OLD 5
+#define SIS66 6
+
+#define VIA33 0
+#define VIA66 1
+#define VIA100 2
+#define VIA133 3
+#define AMDNVIDIA 4
+#define AMDCABLE 0x01
+#define AMDBUG 0x02
+#define NVIDIA 0x04
+#define VIACLK 0x08
+#define VIABUG 0x10
+
+/* 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_generic_ident(device_t);
+int ata_acard_ident(device_t);
+int ata_ali_ident(device_t);
+int ata_amd_ident(device_t);
+int ata_cyrix_ident(device_t);
+int ata_cypress_ident(device_t);
+int ata_highpoint_ident(device_t);
+int ata_intel_ident(device_t);
+int ata_nvidia_ident(device_t);
+int ata_promise_ident(device_t);
+int ata_serverworks_ident(device_t);
+int ata_sii_ident(device_t);
+int ata_sis_ident(device_t);
+int ata_via_ident(device_t);
diff --git a/sys/dev/ata/ata-raid.c b/sys/dev/ata/ata-raid.c
index 6dae432..909f20f 100644
--- a/sys/dev/ata/ata-raid.c
+++ b/sys/dev/ata/ata-raid.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2000,2001,2002 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 2000 - 2003 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -46,6 +46,7 @@
#include <machine/bus.h>
#include <sys/rman.h>
#include <dev/ata/ata-all.h>
+#include <dev/ata/ata-pci.h>
#include <dev/ata/ata-disk.h>
#include <dev/ata/ata-raid.h>
@@ -119,16 +120,12 @@ ata_raiddisk_attach(struct ad_softc *adp)
return 0;
}
- switch(adp->device->channel->chiptype) {
- case 0x4d33105a: case 0x4d38105a: case 0x4d30105a:
- case 0x0d30105a: case 0x4d68105a: case 0x6268105a:
- case 0x4d69105a: case 0x5275105a: case 0x6269105a:
- case 0x7275105a:
-
+ switch(adp->device->channel->chiptype & 0xffff) {
+ case ATA_PROMISE_ID:
/* test RAID bit in PCI reg XXX */
return (ar_promise_read_conf(adp, ar_table, 0));
- case 0x00041103: case 0x00051103: case 0x00081103:
+ case ATA_HIGHPOINT_ID:
return (ar_highpoint_read_conf(adp, ar_table));
default:
@@ -228,7 +225,7 @@ ar_attach_raid(struct ar_softc *rdp, int update)
else
printf(" %d FREE ", disk);
ad_print(AD_SOFTC(rdp->disks[disk]));
- printf(" ");
+ printf(" ");
ata_enclosure_print(AD_SOFTC(rdp->disks[disk])->device);
}
else if (rdp->disks[disk].flags & AR_DF_ASSIGNED)
@@ -276,7 +273,7 @@ ata_raid_create(struct raid_setup *setup)
}
switch (rdp->disks[disk].device->channel->chiptype & 0xffff) {
- case 0x1103:
+ case ATA_HIGHPOINT_ID:
ctlr |= AR_F_HIGHPOINT_RAID;
rdp->disks[disk].disk_sectors =
AD_SOFTC(rdp->disks[disk])->total_secs;
@@ -286,7 +283,7 @@ ata_raid_create(struct raid_setup *setup)
ctlr |= AR_F_FREEBSD_RAID;
/* FALLTHROUGH */
- case 0x105a:
+ case ATA_PROMISE_ID:
ctlr |= AR_F_PROMISE_RAID;
rdp->disks[disk].disk_sectors =
PR_LBA(AD_SOFTC(rdp->disks[disk]));
@@ -302,7 +299,7 @@ ata_raid_create(struct raid_setup *setup)
rdp->flags |= ctlr;
if (disk_size)
- disk_size = min(rdp->disks[disk].disk_sectors, disk_size);
+ disk_size = min(rdp->disks[disk].disk_sectors, disk_size);
else
disk_size = rdp->disks[disk].disk_sectors;
rdp->disks[disk].flags =
@@ -376,7 +373,14 @@ ata_raid_create(struct raid_setup *setup)
rdp->flags |= AR_F_READY;
ar_table[array] = rdp;
+
+ /* kick off rebuild here */
+ if (setup->type == 2) {
+ rdp->disks[1].flags &= ~AR_DF_ONLINE;
+ rdp->disks[1].flags |= AR_DF_SPARE;
+ }
ar_attach_raid(rdp, 1);
+ ata_raid_rebuild(array);
setup->unit = array;
return 0;
}
@@ -1184,7 +1188,7 @@ ar_promise_read_conf(struct ad_softc *adp, struct ar_softc **raidp, int local)
if (!info->raid.generation || info->raid.generation > raid->generation){
raid->generation = info->raid.generation;
raid->flags = AR_F_PROMISE_RAID;
- if (local)
+ if (local)
raid->flags |= AR_F_FREEBSD_RAID;
raid->magic_0 = magic;
raid->lun = array;
diff --git a/sys/dev/ata/ata-raid.h b/sys/dev/ata/ata-raid.h
index 5853ead..687c698 100644
--- a/sys/dev/ata/ata-raid.h
+++ b/sys/dev/ata/ata-raid.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2000,2001,2002 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 2000 - 2003 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/ata/atapi-all.c b/sys/dev/ata/atapi-all.c
index 56e124b..d39c69b 100644
--- a/sys/dev/ata/atapi-all.c
+++ b/sys/dev/ata/atapi-all.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -72,18 +72,10 @@ atapi_attach(struct ata_device *atadev)
ata_umode(atadev->param), atadev->param->support_dma);
ATA_SLEEPLOCK_CH(atadev->channel, ATA_CONTROL);
- if (atapi_dma && !(atadev->param->drq_type == ATAPI_DRQT_INTR)) {
- ata_dmainit(atadev,
- (ata_pmode(atadev->param) < 0) ?
- (atadev->param->support_dma ? 4:0):ata_pmode(atadev->param),
- (ata_wmode(atadev->param) < 0) ?
- (atadev->param->support_dma ? 2:0):ata_wmode(atadev->param),
- ata_umode(atadev->param));
- }
+ if (atapi_dma && !(atadev->param->drq_type == ATAPI_DRQT_INTR))
+ atadev->setmode(atadev, ATA_DMA_MAX);
else
- ata_dmainit(atadev,
- ata_pmode(atadev->param) < 0 ? 0 : ata_pmode(atadev->param),
- -1, -1);
+ atadev->setmode(atadev, ATA_PIO_MAX);
ATA_UNLOCK_CH(atadev->channel);
if (!(atadev->result = malloc(sizeof(struct atapi_reqsense), M_ATAPI,
@@ -154,7 +146,7 @@ atapi_detach(struct ata_device *atadev)
}
free(request, M_ATAPI);
}
- ata_dmafree(atadev);
+ atadev->channel->dma->free(atadev);
free(atadev->result, M_ATAPI);
atadev->driver = NULL;
atadev->flags = 0;
@@ -186,7 +178,7 @@ atapi_queue_cmd(struct ata_device *atadev, int8_t *ccb, caddr_t data,
request->driver = driver;
}
if (atadev->mode >= ATA_DMA) {
- if (ata_dmaalloc(atadev))
+ if (atadev->channel->dma->alloc(atadev))
atadev->mode = ATA_PIO;
}
@@ -282,7 +274,7 @@ atapi_transfer(struct atapi_request *request)
((request->ccb[0] == ATAPI_WRITE ||
request->ccb[0] == ATAPI_WRITE_BIG) &&
!(atadev->channel->flags & ATA_ATAPI_DMA_RO))) &&
- !ata_dmasetup(atadev, (void *)request->data, request->bytecount)) {
+ !atadev->channel->dma->setup(atadev, (void *)request->data, request->bytecount)) {
request->flags |= ATPR_F_DMA_USED;
}
@@ -294,7 +286,7 @@ atapi_transfer(struct atapi_request *request)
ata_prtdev(atadev, "failure to send ATAPI packet command\n");
if (request->flags & ATPR_F_DMA_USED)
- ata_dmastart(atadev, request->data, request->bytecount,
+ atadev->channel->dma->start(atadev, request->data, request->bytecount,
request->flags & ATPR_F_READ);
/* command interrupt device ? just return */
@@ -324,7 +316,7 @@ atapi_transfer(struct atapi_request *request)
/* send actual command */
ATA_OUTSW_STRM(atadev->channel->r_io, ATA_DATA, (int16_t *)request->ccb,
- request->ccbsize / sizeof(int16_t));
+ request->ccbsize / sizeof(int16_t));
return ATA_OP_CONTINUES;
}
@@ -352,7 +344,7 @@ atapi_interrupt(struct atapi_request *request)
}
if (request->flags & ATPR_F_DMA_USED) {
- dma_stat = ata_dmadone(atadev);
+ dma_stat = atadev->channel->dma->stop(atadev);
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);
@@ -473,17 +465,7 @@ void
atapi_reinit(struct ata_device *atadev)
{
/* reinit device parameters */
- if (atadev->mode >= ATA_DMA)
- ata_dmainit(atadev,
- (ata_pmode(atadev->param) < 0) ?
- (atadev->param->support_dma ? 4:0):ata_pmode(atadev->param),
- (ata_wmode(atadev->param) < 0) ?
- (atadev->param->support_dma ? 2:0):ata_wmode(atadev->param),
- ata_umode(atadev->param));
- else
- ata_dmainit(atadev,
- ata_pmode(atadev->param)<0 ? 0 : ata_pmode(atadev->param),
- -1, -1);
+ atadev->setmode(atadev, atadev->mode);
}
int
@@ -608,11 +590,9 @@ atapi_timeout(struct atapi_request *request)
atapi_cmd2str(request->ccb[0]));
if (request->flags & ATPR_F_DMA_USED) {
- ata_dmadone(atadev);
+ atadev->channel->dma->stop(atadev);
if (request->retries == ATAPI_MAX_RETRIES) {
- ata_dmainit(atadev,
- (ata_pmode(atadev->param) < 0) ? 0 :
- ata_pmode(atadev->param), -1, -1);
+ atadev->setmode(atadev, ATA_PIO_MAX);
ata_prtdev(atadev, "trying fallback to PIO mode\n");
request->retries = 0;
}
diff --git a/sys/dev/ata/atapi-all.h b/sys/dev/ata/atapi-all.h
index e77db5a..d41b696 100644
--- a/sys/dev/ata/atapi-all.h
+++ b/sys/dev/ata/atapi-all.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/ata/atapi-cd.c b/sys/dev/ata/atapi-cd.c
index 9c1133e..60d2302 100644
--- a/sys/dev/ata/atapi-cd.c
+++ b/sys/dev/ata/atapi-cd.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -1033,7 +1033,7 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct thread *td)
break;
case CDRIOCWRITESPEED:
- {
+ {
int speed = *(int *)addr;
if (speed < 177)
@@ -1060,11 +1060,11 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct thread *td)
break;
case CDRIOCREADFORMATCAPS:
- error = acd_read_format_caps(cdp, (struct cdr_format_capacities *)addr);
+ error = acd_read_format_caps(cdp, (struct cdr_format_capacities *)addr);
break;
case CDRIOCFORMAT:
- error = acd_format(cdp, (struct cdr_format_params *)addr);
+ error = acd_format(cdp, (struct cdr_format_params *)addr);
break;
case DVDIOCREPORTKEY:
diff --git a/sys/dev/ata/atapi-cd.h b/sys/dev/ata/atapi-cd.h
index 4e21487..19d742c 100644
--- a/sys/dev/ata/atapi-cd.h
+++ b/sys/dev/ata/atapi-cd.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -299,7 +299,7 @@ struct write_param {
#define CDR_WTYPE_RAW 0x03
u_int8_t test_write :1; /* test write enable */
- u_int8_t link_size_valid :1;
+ u_int8_t link_size_valid :1;
u_int8_t burnproof :1; /* BurnProof enable */
u_int8_t reserved2_7 :1;
u_int8_t track_mode :4; /* track mode */
diff --git a/sys/dev/ata/atapi-fd.c b/sys/dev/ata/atapi-fd.c
index 5d6f66a..b0b0f76 100644
--- a/sys/dev/ata/atapi-fd.c
+++ b/sys/dev/ata/atapi-fd.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -204,8 +204,8 @@ afd_describe(struct afd_softc *fdp)
printf("Unknown (0x%x)", fdp->cap.medium_type);
}
if (fdp->cap.wp) printf(", writeprotected");
+ printf("\n");
}
- printf("\n");
}
else {
ata_prtdev(fdp->device, "%luMB <%.40s> [%d/%d/%d] at ata%d-%s %s\n",
diff --git a/sys/dev/ata/atapi-fd.h b/sys/dev/ata/atapi-fd.h
index ee4fc73..e92f79c 100644
--- a/sys/dev/ata/atapi-fd.h
+++ b/sys/dev/ata/atapi-fd.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/ata/atapi-tape.c b/sys/dev/ata/atapi-tape.c
index a0fdc2e..76a5c46 100644
--- a/sys/dev/ata/atapi-tape.c
+++ b/sys/dev/ata/atapi-tape.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/ata/atapi-tape.h b/sys/dev/ata/atapi-tape.h
index e4dab20..96ef84e 100644
--- a/sys/dev/ata/atapi-tape.h
+++ b/sys/dev/ata/atapi-tape.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
OpenPOWER on IntegriCloud