aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Schmidt <sos@FreeBSD.org>2003-02-20 20:02:32 +0000
committerSøren Schmidt <sos@FreeBSD.org>2003-02-20 20:02:32 +0000
commitbb5bdd386ebd744a72fb2426f8bd1bc03fb38ebd (patch)
tree21f00885355e44a0cfacbbf172b07133dc03eb36
parent4b25d7a6e4ab0be9c7cb456372a80bcfc9fdcc17 (diff)
downloadsrc-bb5bdd386ebd744a72fb2426f8bd1bc03fb38ebd.tar.gz
src-bb5bdd386ebd744a72fb2426f8bd1bc03fb38ebd.zip
First round off updates/fixes to the ATA driver.
This moves all chipset specific code to a new file 'ata-chipset.c'. Extensive use of tables and pointers to avoid having the same switch on chipset type in several places, and to allow substituting various functions for different HW arch needs. Added PIO mode setup and all DMA modes. Support for all known SiS chipsets. Thanks to Christoph Kukulies for sponsoring a nice ASUS P4S8X SiS648 based board for this work! Tested on: i386, PC98, alpha and sparc64
Notes
Notes: svn path=/head/; revision=111188
-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 a67a535b3431..9f739db3ab4d 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 9fb6aa574ac6..183bdb28e681 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 323a99d54912..52d434877af7 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 ef1c338c9043..31ff4ab6bb24 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 854b55e1dd77..38a2d20a73af 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 000000000000..88602269151e
--- /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 49f20624a9e9..450011a34bbd 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 0c190d1e4420..db9156b615c2 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 c6ab3a5c0d91..7f1353ba5b62 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 10348588cf07..a8a629678e73 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 d77d65a9d554..065e0b0673cb 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 000000000000..157bc6a29a1b
--- /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 6dae4322de78..909f20fe30ec 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 5853ead0365b..687c698f31af 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 56e124b6f6dd..d39c69b6e4db 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 e77db5a2db61..d41b696f5d71 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 9c1133e414e6..60d2302096b3 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 4e21487082be..19d742cc18a5 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 5d6f66ae81f9..b0b0f7610e5a 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 ee4fc73f36e0..e92f79c2322c 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 a0fdc2e0366a..76a5c463bcff 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 e4dab207bc63..96ef84e34d98 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