summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorChris Cappuccio <chris@cvs.openbsd.org>2001-08-03 22:03:45 +0000
committerChris Cappuccio <chris@cvs.openbsd.org>2001-08-03 22:03:45 +0000
commit48862fffe594b4e8de5552dfb2afc2b57894fc84 (patch)
tree13c73c12bfc974ecde805563d343ee878f3acaff /sys/dev/pci
parent17b6da627cb24572c6b4a25f85487e916be45b08 (diff)
from NetBSD:
Add support for Acard ATP850/860, Highpoint HPT370A, and ALi UDMA4/5 controllers Workaround some OPTi chipset bugs (opti_chip_map still disabled by default)
Diffstat (limited to 'sys/dev/pci')
-rw-r--r--sys/dev/pci/pciide.c328
-rw-r--r--sys/dev/pci/pciide_acard_reg.h62
-rw-r--r--sys/dev/pci/pciide_acer_reg.h26
-rw-r--r--sys/dev/pci/pciide_hpt_reg.h5
-rw-r--r--sys/dev/pci/pciide_pdc202xx_reg.h6
5 files changed, 406 insertions, 21 deletions
diff --git a/sys/dev/pci/pciide.c b/sys/dev/pci/pciide.c
index 7ee28e1141f..3a2b4ceeec7 100644
--- a/sys/dev/pci/pciide.c
+++ b/sys/dev/pci/pciide.c
@@ -1,8 +1,8 @@
-/* $OpenBSD: pciide.c,v 1.59 2001/07/31 06:14:05 csapuntz Exp $ */
-/* $NetBSD: pciide.c,v 1.110 2001/03/20 17:56:46 bouyer Exp $ */
+/* $OpenBSD: pciide.c,v 1.60 2001/08/03 22:03:44 chris Exp $ */
+/* $NetBSD: pciide.c,v 1.127 2001/08/03 01:31:08 tsutsui Exp $ */
/*
- * Copyright (c) 1999 Manuel Bouyer.
+ * Copyright (c) 1999, 2000, 2001 Manuel Bouyer.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -113,6 +113,7 @@ int wdcdebug_pciide_mask = 0;
#include <dev/pci/pciide_pdc202xx_reg.h>
#include <dev/pci/pciide_opti_reg.h>
#include <dev/pci/pciide_hpt_reg.h>
+#include <dev/pci/pciide_acard_reg.h>
#include <dev/pci/cy82c693var.h>
@@ -234,6 +235,10 @@ void opti_setup_channel __P((struct channel_softc*));
void hpt_chip_map __P((struct pciide_softc*, struct pci_attach_args*));
void hpt_setup_channel __P((struct channel_softc*));
int hpt_pci_intr __P((void *));
+
+void acard_chip_map __P((struct pciide_softc*, struct pci_attach_args*));
+void acard_setup_channel __P((struct channel_softc*));
+int acard_pci_intr __P((void *));
void pciide_channel_dma_setup __P((struct pciide_channel *));
int pciide_dma_table_setup __P((struct pciide_softc*, int, int));
@@ -411,6 +416,21 @@ const struct pciide_product_desc pciide_promise_products[] = {
}
};
+const struct pciide_product_desc pciide_acard_products[] = {
+ { PCI_PRODUCT_ACARD_ATP850U, /* Acard ATP850U Ultra33 Controller */
+ IDE_PCI_CLASS_OVERRIDE,
+ acard_chip_map,
+ },
+ { PCI_PRODUCT_ACARD_ATP860, /* Acard ATP860 Ultra66 Controller */
+ IDE_PCI_CLASS_OVERRIDE,
+ acard_chip_map,
+ },
+ { PCI_PRODUCT_ACARD_ATP860A, /* Acard ATP860-A Ultra66 Controller */
+ IDE_PCI_CLASS_OVERRIDE,
+ acard_chip_map,
+ }
+};
+
struct pciide_vendor_desc {
u_int32_t ide_vendor;
const struct pciide_product_desc *ide_products;
@@ -438,6 +458,8 @@ const struct pciide_vendor_desc pciide_vendors[] = {
sizeof(pciide_acer_products)/sizeof(pciide_acer_products[0]) },
{ PCI_VENDOR_TRIONES, pciide_triones_products,
sizeof(pciide_triones_products)/sizeof(pciide_triones_products[0]) },
+ { PCI_VENDOR_ACARD, pciide_acard_products,
+ sizeof(pciide_acard_products)/sizeof(pciide_acard_products[0]) },
{ PCI_VENDOR_PROMISE, pciide_promise_products,
sizeof(pciide_promise_products)/sizeof(pciide_promise_products[0]) }
};
@@ -2826,18 +2848,34 @@ sis_chip_map(sc, pa)
pcireg_t interface = PCI_INTERFACE(pa->pa_class);
pcireg_t rev = PCI_REVISION(pa->pa_class);
bus_size_t cmdsize, ctlsize;
+ pcitag_t pchb_tag;
+ pcireg_t pchb_id, pchb_class;
if (pciide_chipen(sc, pa) == 0)
return;
printf(": DMA");
pciide_mapreg_dma(sc, pa);
+
+ /* get a PCI tag for the host bridge (function 0 of the same device) */
+ pchb_tag = pci_make_tag(pa->pa_pc, pa->pa_bus, pa->pa_device, 0);
+ /* and read ID and rev of the ISA bridge */
+ pchb_id = pci_conf_read(sc->sc_pc, pchb_tag, PCI_ID_REG);
+ pchb_class = pci_conf_read(sc->sc_pc, pchb_tag, PCI_CLASS_REG);
+
sc->sc_wdcdev.cap = WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_DATA32 |
WDC_CAPABILITY_MODE;
if (sc->sc_dma_ok) {
sc->sc_wdcdev.cap |= WDC_CAPABILITY_DMA | WDC_CAPABILITY_IRQACK;
sc->sc_wdcdev.irqack = pciide_irqack;
- if (rev >= 0xd0)
+ /*
+ * controllers with rev > 0xd0 support UDMA 2 at least
+ * controllers associated to a rev 0x2 530 Host to PCI Bridge
+ * have problems with UDMA
+ */
+ if (rev >= 0xd0 &&
+ (PCI_PRODUCT(pchb_id) != PCI_PRODUCT_SIS_SiS530 ||
+ PCI_REVISION(pchb_class) >= 0x03))
sc->sc_wdcdev.cap |= WDC_CAPABILITY_UDMA;
}
@@ -2982,16 +3020,21 @@ acer_chip_map(sc, pa)
if (sc->sc_dma_ok) {
sc->sc_wdcdev.cap |= WDC_CAPABILITY_DMA;
- if (rev >= 0x20)
+ if (rev >= 0x20) {
sc->sc_wdcdev.cap |= WDC_CAPABILITY_UDMA;
+ if (rev >= 0xC4)
+ sc->sc_wdcdev.UDMA_cap = 5;
+ else if (rev >= 0xC2)
+ sc->sc_wdcdev.UDMA_cap = 4;
+ else
+ sc->sc_wdcdev.UDMA_cap = 2;
+ }
sc->sc_wdcdev.cap |= WDC_CAPABILITY_IRQACK;
sc->sc_wdcdev.irqack = pciide_irqack;
}
sc->sc_wdcdev.PIO_cap = 4;
sc->sc_wdcdev.DMA_cap = 2;
- if (sc->sc_wdcdev.cap & WDC_CAPABILITY_UDMA)
- sc->sc_wdcdev.UDMA_cap = 2;
sc->sc_wdcdev.set_modes = acer_setup_channel;
sc->sc_wdcdev.channels = sc->wdc_chanarray;
sc->sc_wdcdev.nchannels = PCIIDE_NUM_CHANNELS;
@@ -3018,6 +3061,24 @@ acer_chip_map(sc, pa)
pciide_print_channels(sc->sc_wdcdev.nchannels, interface);
+ /* From linux: enable "Cable Detection" */
+ if (rev >= 0xC2) {
+ pciide_pci_write(sc->sc_pc, sc->sc_tag, ACER_0x4B,
+ pciide_pci_read(sc->sc_pc, sc->sc_tag, ACER_0x4B)
+ | ACER_0x4B_CDETECT);
+ /* set south-bridge's enable bit, m1533, 0x79 */
+ if (rev == 0xC2)
+ /* 1543C-B0 (m1533, 0x79, bit 2) */
+ pciide_pci_write(sc->sc_pc, sc->sc_tag, ACER_0x79,
+ pciide_pci_read(sc->sc_pc, sc->sc_tag, ACER_0x79)
+ | ACER_0x79_REVC2_EN);
+ else
+ /* 1553/1535 (m1533, 0x79, bit 1) */
+ pciide_pci_write(sc->sc_pc, sc->sc_tag, ACER_0x79,
+ pciide_pci_read(sc->sc_pc, sc->sc_tag, ACER_0x79)
+ | ACER_0x79_EN);
+ }
+
for (channel = 0; channel < sc->sc_wdcdev.nchannels; channel++) {
cp = &sc->pciide_channels[channel];
if (pciide_chansetup(sc, channel, interface) == 0)
@@ -3031,7 +3092,7 @@ acer_chip_map(sc, pa)
if (cp->hw_ok == 0)
continue;
pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize,
- acer_pci_intr);
+ (rev >= 0xC2) ? pciide_pci_intr : acer_pci_intr);
if (cp->hw_ok == 0) {
pciide_unmap_compat_intr(pa, cp, channel, interface);
continue;
@@ -3067,6 +3128,17 @@ acer_setup_channel(chp)
/* setup DMA if needed */
pciide_channel_dma_setup(cp);
+ if ((chp->ch_drive[0].drive_flags | chp->ch_drive[1].drive_flags) &
+ DRIVE_UDMA) { /* check 80 pins cable */
+ if (pciide_pci_read(sc->sc_pc, sc->sc_tag, ACER_0x4A) &
+ ACER_0x4A_80PIN(chp->channel)) {
+ if (chp->ch_drive[0].UDMA_mode > 2)
+ chp->ch_drive[0].UDMA_mode = 2;
+ if (chp->ch_drive[1].UDMA_mode > 2)
+ chp->ch_drive[1].UDMA_mode = 2;
+ }
+ }
+
for (drive = 0; drive < 2; drive++) {
drvp = &chp->ch_drive[drive];
/* If no drive, skip */
@@ -3097,6 +3169,13 @@ acer_setup_channel(chp)
acer_fifo_udma |=
ACER_UDMA_TIM(chp->channel, drive,
acer_udma[drvp->UDMA_mode]);
+ /* XXX disable if one drive < UDMA3 ? */
+ if (drvp->UDMA_mode >= 3) {
+ pciide_pci_write(sc->sc_pc, sc->sc_tag,
+ ACER_0x4B,
+ pciide_pci_read(sc->sc_pc, sc->sc_tag,
+ ACER_0x4B) | ACER_0x4B_UDMA66);
+ }
} else {
/*
* use Multiword DMA
@@ -3180,7 +3259,7 @@ hpt_chip_map(sc, pa)
} else {
interface = PCIIDE_INTERFACE_BUS_MASTER_DMA |
PCIIDE_INTERFACE_PCI(0);
- if (revision == HPT370_REV)
+ if (revision == HPT370_REV || revision == HPT370A_REV)
interface |= PCIIDE_INTERFACE_PCI(1);
}
@@ -3247,7 +3326,7 @@ hpt_chip_map(sc, pa)
wdcattach(&cp->wdc_channel);
hpt_setup_channel(&cp->wdc_channel);
}
- if (revision == HPT370_REV) {
+ if (revision == HPT370_REV || revision == HPT370A_REV) {
/*
* HPT370_REV has a bit to disable interrupts, make sure
* to clear it
@@ -3763,10 +3842,24 @@ opti_chip_map(sc, pa)
if (pciide_chipen(sc, pa) == 0)
return;
printf(": DMA");
- pciide_mapreg_dma(sc, pa);
+ /*
+ * XXXSCW:
+ * There seem to be a couple of buggy revisions/implementations
+ * of the OPTi pciide chipset. This kludge seems to fix one of
+ * the reported problems (NetBSD PR/11644) but still fails for the
+ * other (NetBSD PR/13151), although the latter may be due to other
+ * issues too...
+ */
+ if (PCI_REVISION(pa->pa_class) <= 0x12) {
+ printf(" (disabled)");
+ sc->sc_dma_ok = 0;
+ sc->sc_wdcdev.cap = 0;
+ } else {
+ sc->sc_wdcdev.cap = WDC_CAPABILITY_DATA32;
+ pciide_mapreg_dma(sc, pa);
+ }
- sc->sc_wdcdev.cap = WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_DATA32 |
- WDC_CAPABILITY_MODE;
+ sc->sc_wdcdev.cap = WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_MODE;
sc->sc_wdcdev.PIO_cap = 4;
if (sc->sc_dma_ok) {
sc->sc_wdcdev.cap |= WDC_CAPABILITY_DMA | WDC_CAPABILITY_IRQACK;
@@ -3908,3 +4001,212 @@ opti_setup_channel(chp)
pciide_print_modes(cp);
}
+
+
+#define ACARD_IS_850(sc) \
+ ((sc)->sc_pp->ide_product == PCI_PRODUCT_ACARD_ATP850U)
+
+void
+acard_chip_map(sc, pa)
+ struct pciide_softc *sc;
+ struct pci_attach_args *pa;
+{
+ struct pciide_channel *cp;
+ int i;
+ pcireg_t interface;
+ bus_size_t cmdsize, ctlsize;
+
+ if (pciide_chipen(sc, pa) == 0)
+ return;
+
+ /*
+ * when the chip is in native mode it identifies itself as a
+ * 'misc mass storage'. Fake interface in this case.
+ */
+ if (PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MASS_STORAGE_IDE) {
+ interface = PCI_INTERFACE(pa->pa_class);
+ } else {
+ interface = PCIIDE_INTERFACE_BUS_MASTER_DMA |
+ PCIIDE_INTERFACE_PCI(0) | PCIIDE_INTERFACE_PCI(1);
+ }
+
+ printf(": DMA");
+ pciide_mapreg_dma(sc, pa);
+ printf("\n");
+ sc->sc_wdcdev.cap = WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_DATA32 |
+ WDC_CAPABILITY_MODE;
+
+ if (sc->sc_dma_ok) {
+ sc->sc_wdcdev.cap |= WDC_CAPABILITY_DMA | WDC_CAPABILITY_UDMA;
+ sc->sc_wdcdev.cap |= WDC_CAPABILITY_IRQACK;
+ sc->sc_wdcdev.irqack = pciide_irqack;
+ }
+ sc->sc_wdcdev.PIO_cap = 4;
+ sc->sc_wdcdev.DMA_cap = 2;
+ sc->sc_wdcdev.UDMA_cap = ACARD_IS_850(sc) ? 2 : 4;
+
+ sc->sc_wdcdev.set_modes = acard_setup_channel;
+ sc->sc_wdcdev.channels = sc->wdc_chanarray;
+ sc->sc_wdcdev.nchannels = 2;
+
+ for (i = 0; i < sc->sc_wdcdev.nchannels; i++) {
+ cp = &sc->pciide_channels[i];
+ if (pciide_chansetup(sc, i, interface) == 0)
+ continue;
+ if (interface & PCIIDE_INTERFACE_PCI(i)) {
+ cp->hw_ok = pciide_mapregs_native(pa, cp, &cmdsize,
+ &ctlsize, pciide_pci_intr);
+ } else {
+ cp->hw_ok = pciide_mapregs_compat(pa, cp, i,
+ &cmdsize, &ctlsize);
+ }
+ if (cp->hw_ok == 0)
+ return;
+ cp->wdc_channel.data32iot = cp->wdc_channel.cmd_iot;
+ cp->wdc_channel.data32ioh = cp->wdc_channel.cmd_ioh;
+ wdcattach(&cp->wdc_channel);
+ acard_setup_channel(&cp->wdc_channel);
+ }
+ if (!ACARD_IS_850(sc)) {
+ u_int32_t reg;
+ reg = pci_conf_read(sc->sc_pc, sc->sc_tag, ATP8x0_CTRL);
+ reg &= ~ATP860_CTRL_INT;
+ pci_conf_write(sc->sc_pc, sc->sc_tag, ATP8x0_CTRL, reg);
+ }
+}
+
+void
+acard_setup_channel(chp)
+ struct channel_softc *chp;
+{
+ struct ata_drive_datas *drvp;
+ struct pciide_channel *cp = (struct pciide_channel*)chp;
+ struct pciide_softc *sc = (struct pciide_softc *)cp->wdc_channel.wdc;
+ int channel = chp->channel;
+ int drive;
+ u_int32_t idetime, udma_mode;
+ u_int32_t idedma_ctl;
+
+ /* setup DMA if needed */
+ pciide_channel_dma_setup(cp);
+
+ if (ACARD_IS_850(sc)) {
+ idetime = 0;
+ udma_mode = pci_conf_read(sc->sc_pc, sc->sc_tag, ATP850_UDMA);
+ udma_mode &= ~ATP850_UDMA_MASK(channel);
+ } else {
+ idetime = pci_conf_read(sc->sc_pc, sc->sc_tag, ATP860_IDETIME);
+ idetime &= ~ATP860_SETTIME_MASK(channel);
+ udma_mode = pci_conf_read(sc->sc_pc, sc->sc_tag, ATP860_UDMA);
+ udma_mode &= ~ATP860_UDMA_MASK(channel);
+ }
+
+ idedma_ctl = 0;
+
+ /* Per drive settings */
+ for (drive = 0; drive < 2; drive++) {
+ drvp = &chp->ch_drive[drive];
+ /* If no drive, skip */
+ if ((drvp->drive_flags & DRIVE) == 0)
+ continue;
+ /* add timing values, setup DMA if needed */
+ if ((chp->wdc->cap & WDC_CAPABILITY_UDMA) &&
+ (drvp->drive_flags & DRIVE_UDMA)) {
+ /* use Ultra/DMA */
+ if (ACARD_IS_850(sc)) {
+ idetime |= ATP850_SETTIME(drive,
+ acard_act_udma[drvp->UDMA_mode],
+ acard_rec_udma[drvp->UDMA_mode]);
+ udma_mode |= ATP850_UDMA_MODE(channel, drive,
+ acard_udma_conf[drvp->UDMA_mode]);
+ } else {
+ idetime |= ATP860_SETTIME(channel, drive,
+ acard_act_udma[drvp->UDMA_mode],
+ acard_rec_udma[drvp->UDMA_mode]);
+ udma_mode |= ATP860_UDMA_MODE(channel, drive,
+ acard_udma_conf[drvp->UDMA_mode]);
+ }
+ idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
+ } else if ((chp->wdc->cap & WDC_CAPABILITY_DMA) &&
+ (drvp->drive_flags & DRIVE_DMA)) {
+ /* use Multiword DMA */
+ drvp->drive_flags &= ~DRIVE_UDMA;
+ if (ACARD_IS_850(sc)) {
+ idetime |= ATP850_SETTIME(drive,
+ acard_act_dma[drvp->DMA_mode],
+ acard_rec_dma[drvp->DMA_mode]);
+ } else {
+ idetime |= ATP860_SETTIME(channel, drive,
+ acard_act_dma[drvp->DMA_mode],
+ acard_rec_dma[drvp->DMA_mode]);
+ }
+ idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
+ } else {
+ /* PIO only */
+ drvp->drive_flags &= ~(DRIVE_UDMA | DRIVE_DMA);
+ if (ACARD_IS_850(sc)) {
+ idetime |= ATP850_SETTIME(drive,
+ acard_act_pio[drvp->PIO_mode],
+ acard_rec_pio[drvp->PIO_mode]);
+ } else {
+ idetime |= ATP860_SETTIME(channel, drive,
+ acard_act_pio[drvp->PIO_mode],
+ acard_rec_pio[drvp->PIO_mode]);
+ }
+ pci_conf_write(sc->sc_pc, sc->sc_tag, ATP8x0_CTRL,
+ pci_conf_read(sc->sc_pc, sc->sc_tag, ATP8x0_CTRL)
+ | ATP8x0_CTRL_EN(channel));
+ }
+ }
+
+ if (idedma_ctl != 0) {
+ /* Add software bits in status register */
+ bus_space_write_1(sc->sc_dma_iot, sc->sc_dma_ioh,
+ IDEDMA_CTL + IDEDMA_SCH_OFFSET * channel, idedma_ctl);
+ }
+ pciide_print_modes(cp);
+
+ if (ACARD_IS_850(sc)) {
+ pci_conf_write(sc->sc_pc, sc->sc_tag,
+ ATP850_IDETIME(channel), idetime);
+ pci_conf_write(sc->sc_pc, sc->sc_tag, ATP850_UDMA, udma_mode);
+ } else {
+ pci_conf_write(sc->sc_pc, sc->sc_tag, ATP860_IDETIME, idetime);
+ pci_conf_write(sc->sc_pc, sc->sc_tag, ATP860_UDMA, udma_mode);
+ }
+}
+
+int
+acard_pci_intr(arg)
+ void *arg;
+{
+ struct pciide_softc *sc = arg;
+ struct pciide_channel *cp;
+ struct channel_softc *wdc_cp;
+ int rv = 0;
+ int dmastat, i, crv;
+
+ for (i = 0; i < sc->sc_wdcdev.nchannels; i++) {
+ dmastat = bus_space_read_1(sc->sc_dma_iot, sc->sc_dma_ioh,
+ IDEDMA_CTL + IDEDMA_SCH_OFFSET * i);
+ if ((dmastat & IDEDMA_CTL_INTR) == 0)
+ continue;
+ cp = &sc->pciide_channels[i];
+ wdc_cp = &cp->wdc_channel;
+ if ((wdc_cp->ch_flags & WDCF_IRQ_WAIT) == 0) {
+ (void)wdcintr(wdc_cp);
+ bus_space_write_1(sc->sc_dma_iot, sc->sc_dma_ioh,
+ IDEDMA_CTL + IDEDMA_SCH_OFFSET * i, dmastat);
+ continue;
+ }
+ crv = wdcintr(wdc_cp);
+ if (crv == 0)
+ printf("%s:%d: bogus intr\n",
+ sc->sc_wdcdev.sc_dev.dv_xname, i);
+ else if (crv == 1)
+ rv = 1;
+ else if (rv == 0)
+ rv = crv;
+ }
+ return rv;
+}
diff --git a/sys/dev/pci/pciide_acard_reg.h b/sys/dev/pci/pciide_acard_reg.h
new file mode 100644
index 00000000000..601da4579c4
--- /dev/null
+++ b/sys/dev/pci/pciide_acard_reg.h
@@ -0,0 +1,62 @@
+/* $NetBSD: pciide_acard_reg.h,v 1.1 2001/04/21 16:36:38 tsutsui Exp $ */
+
+/*
+ * Copyright (c) 2001 Izumi Tsutsui.
+ *
+ * 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.
+ * 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.
+ *
+ */
+
+#define ATP850_IDETIME(channel) (0x40 + (channel) * 4)
+#define ATP860_IDETIME 0x40
+
+#define ATP850_SETTIME(drive, act, rec) \
+ (((((act) & 0xf) << 8) | ((rec) & 0xf)) << ((drive) * 16))
+#define ATP860_SETTIME(channel, drive, act, rec) \
+ (((((act) & 0xf) << 4) | ((rec) & 0xf)) << \
+ ((channel) * 16 + (drive) * 8))
+#define ATP860_SETTIME_MASK(channel) (0xffff << ((channel) * 16))
+
+static const u_int8_t acard_act_udma[] = {0x3, 0x3, 0x3, 0x3, 0x3};
+static const u_int8_t acard_rec_udma[] = {0x1, 0x1, 0x1, 0x1, 0x1};
+static const u_int8_t acard_act_dma[] = {0x0, 0x3, 0x3};
+static const u_int8_t acard_rec_dma[] = {0xa, 0x3, 0x1};
+static const u_int8_t acard_act_pio[] = {0x0, 0x0, 0x0, 0x3, 0x3};
+static const u_int8_t acard_rec_pio[] = {0x0, 0xa, 0x8, 0x3, 0x1};
+
+#define ATP850_UDMA 0x54
+#define ATP860_UDMA 0x44
+
+#define ATP850_UDMA_MODE(channel, drive, x) \
+ (((x) & 0x3) << ((channel) * 4 + (drive) * 2))
+#define ATP860_UDMA_MODE(channel, drive, x) \
+ (((x) & 0xf) << ((channel) * 8 + (drive) * 4))
+#define ATP850_UDMA_MASK(channel) (0xf << ((channel) * 4))
+#define ATP860_UDMA_MASK(channel) (0xff << ((channel) * 8))
+
+static const u_int8_t acard_udma_conf[] = {0x1, 0x2, 0x3, 0x4, 0x5};
+
+#define ATP8x0_CTRL 0x48
+#define ATP8x0_CTRL_EN(chan) (0x00020000 << (chan))
+#define ATP860_CTRL_INT 0x00010000
+#define ATP860_CTRL_80P(chan) (0x00000100 << (chan))
diff --git a/sys/dev/pci/pciide_acer_reg.h b/sys/dev/pci/pciide_acer_reg.h
index 023164917e7..6befb6105af 100644
--- a/sys/dev/pci/pciide_acer_reg.h
+++ b/sys/dev/pci/pciide_acer_reg.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: pciide_acer_reg.h,v 1.3 2001/04/04 07:02:52 csapuntz Exp $ */
-/* $NetBSD: pciide_acer_reg.h,v 1.3 2000/05/15 08:46:01 bouyer Exp $ */
+/* $OpenBSD: pciide_acer_reg.h,v 1.4 2001/08/03 22:03:44 chris Exp $ */
+/* $NetBSD: pciide_acer_reg.h,v 1.4 2001/07/26 20:02:22 bouyer Exp $ */
/*
* Copyright (c) 1999 Manuel Bouyer.
@@ -38,6 +38,20 @@
#define ACER_CHANSTATUS_RO 0x40
#define PCIIDE_CHAN_RO(chan) (0x20 >> (chan))
+/* from Linux, 80 pins cable detect */
+#define ACER_0x4A 0x4a
+/*
+ * bit 0 is 0 -> primary has 80 pin cable
+ * bit 1 is 0 -> secondary has 80 pin cable
+ */
+#define ACER_0x4A_80PIN(chan) (0x1 << (chan))
+
+/* From FreeBSD, for UDMA mode > 2 */
+#define ACER_0x4B 0x4b
+#define ACER_0x4B_UDMA66 0x01
+/* From Linux */
+#define ACER_0x4B_CDETECT 0x08
+
/* class code attribute register 2 (1 byte) */
#define ACER_CCAR2 0x4d
#define ACER_CHANSTATUSREGS_RO 0x80
@@ -74,13 +88,19 @@
#define ACER_CHIDS_DRV(channel) ((0x4) << (channel))
#define ACER_CHIDS_INT(channel) ((0x1) << (channel))
+/* Linux: south-bridge's enable bit (m1533) */
+#define ACER_0x79 0x79
+#define ACER_0x79_REVC2_EN 0x4
+#define ACER_0x79_EN 0x2
+
/*
* IDE bus frequency (1 byte)
* This should be setup by the BIOS - can we rely on this ?
*/
#define ACER_IDE_CLK 0x78
-static int8_t acer_udma[] = {0x4, 0x3, 0x2};
+/* acer UDMA3/4/5 from FreeBSD */
+static int8_t acer_udma[] = {0x4, 0x3, 0x2, 0x1, 0x0, 0x7};
static int8_t acer_pio[] = {0x0c, 0x58, 0x44, 0x33, 0x31};
#ifdef unused
static int8_t acer_dma[] = {0x08, 0x33, 0x31};
diff --git a/sys/dev/pci/pciide_hpt_reg.h b/sys/dev/pci/pciide_hpt_reg.h
index cce13448285..e1d11f14616 100644
--- a/sys/dev/pci/pciide_hpt_reg.h
+++ b/sys/dev/pci/pciide_hpt_reg.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: pciide_hpt_reg.h,v 1.1 2001/03/26 22:17:06 chris Exp $ */
-/* $NetBSD: pciide_hpt_reg.h,v 1.3 2001/01/05 15:20:53 bouyer Exp $ */
+/* $OpenBSD: pciide_hpt_reg.h,v 1.2 2001/08/03 22:03:44 chris Exp $ */
+/* $NetBSD: pciide_hpt_reg.h,v 1.4 2001/07/23 14:55:27 bouyer Exp $ */
/*
* Copyright (c) 2000 Manuel Bouyer.
@@ -47,6 +47,7 @@
*/
#define HPT366_REV 0x01
#define HPT370_REV 0x03
+#define HPT370A_REV 0x04
#define HPT_IDETIM(chan, drive) (0x40 + ((drive) * 4) + ((chan) * 8))
#define HPT_IDETIM_BUFEN 0x80000000
diff --git a/sys/dev/pci/pciide_pdc202xx_reg.h b/sys/dev/pci/pciide_pdc202xx_reg.h
index e87c736f723..5dfcbc91c1b 100644
--- a/sys/dev/pci/pciide_pdc202xx_reg.h
+++ b/sys/dev/pci/pciide_pdc202xx_reg.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: pciide_pdc202xx_reg.h,v 1.4 2001/04/04 07:02:54 csapuntz Exp $ */
-/* $NetBSD: pciide_pdc202xx_reg.h,v 1.4 2001/03/12 09:51:21 bouyer Exp $ */
+/* $OpenBSD: pciide_pdc202xx_reg.h,v 1.5 2001/08/03 22:03:44 chris Exp $ */
+/* $NetBSD: pciide_pdc202xx_reg.h,v 1.5 2001/07/05 08:38:27 toshii Exp $ */
/*
* Copyright (c) 1999 Manuel Bouyer.
@@ -68,7 +68,7 @@
#define PDC2xx_TIM_IORDYp 0x00400000
#define PDC2xx_TIM_DMARQp 0x00800000
-/* The following are extentions of the DMA registers */
+/* The following are extensions of the DMA registers */
/* Ultra-DMA mode 3/4 control (PDC20262 only, 1 byte) */
#define PDC262_U66 0x11