-/* $OpenBSD: pciide.c,v 1.20 2000/01/17 17:12:34 chris Exp $ */
+/* $OpenBSD: pciide.c,v 1.21 2000/03/24 17:47:41 chris Exp $ */
/* $NetBSD: pciide.c,v 1.48 1999/11/28 20:05:18 bouyer Exp $ */
/*
#include <dev/pci/pciidereg.h>
#include <dev/pci/pciidevar.h>
#include <dev/pci/pciide_piix_reg.h>
+#include <dev/pci/pciide_amd_reg.h>
#include <dev/pci/pciide_apollo_reg.h>
#include <dev/pci/pciide_cmd_reg.h>
#include <dev/pci/pciide_cy693_reg.h>
static u_int32_t piix_setup_idetim_drvs __P((struct ata_drive_datas*));
static u_int32_t piix_setup_sidetim_timings __P((u_int8_t, u_int8_t, u_int8_t));
+void amd756_chip_map __P((struct pciide_softc*, struct pci_attach_args*));
+void amd756_setup_channel __P((struct channel_softc*));
+
void apollo_chip_map __P((struct pciide_softc*, struct pci_attach_args*));
void apollo_setup_channel __P((struct channel_softc*));
},
{ PCI_PRODUCT_INTEL_82801AA_IDE, /* Intel 82801AA IDE (ICH) */
0,
- piix_chip_map,
+ piix_chip_map
},
{ PCI_PRODUCT_INTEL_82801AB_IDE, /* Intel 82801AB IDE (ICH0) */
0,
- piix_chip_map,
+ piix_chip_map
+ },
+};
+
+const struct pciide_product_desc pciide_amd_products[] = {
+ { PCI_PRODUCT_AMD_PBC756_IDE, /* AMD 756 */
+ 0,
+ amd756_chip_map
},
};
const struct pciide_vendor_desc pciide_vendors[] = {
{ PCI_VENDOR_INTEL, pciide_intel_products,
sizeof(pciide_intel_products)/sizeof(pciide_intel_products[0]) },
+ { PCI_VENDOR_AMD, pciide_amd_products,
+ sizeof(pciide_amd_products)/sizeof(pciide_amd_products[0]) },
{ PCI_VENDOR_CMDTECH, pciide_cmd_products,
sizeof(pciide_cmd_products)/sizeof(pciide_cmd_products[0]) },
{ PCI_VENDOR_VIATECH, pciide_via_products,
PIIX_SIDETIM_RTC_SET(piix_rtc_pio[mode], channel);
}
+void
+amd756_chip_map(sc, pa)
+ struct pciide_softc *sc;
+ struct pci_attach_args *pa;
+{
+ struct pciide_channel *cp;
+ pcireg_t interface = PCI_INTERFACE(pci_conf_read(sc->sc_pc,
+ sc->sc_tag, PCI_CLASS_REG));
+ int channel;
+ pcireg_t chanenable;
+ bus_size_t cmdsize, ctlsize;
+
+ if (pciide_chipen(sc, pa) == 0)
+ return;
+
+ printf(": DMA");
+ pciide_mapreg_dma(sc, pa);
+
+ if (sc->sc_dma_ok)
+ sc->sc_wdcdev.cap |= WDC_CAPABILITY_DMA | WDC_CAPABILITY_UDMA;
+ sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_DATA32 |
+ WDC_CAPABILITY_MODE;
+ sc->sc_wdcdev.PIO_cap = 4;
+ sc->sc_wdcdev.DMA_cap = 2;
+ sc->sc_wdcdev.UDMA_cap = 4;
+ sc->sc_wdcdev.set_modes = amd756_setup_channel;
+ sc->sc_wdcdev.channels = sc->wdc_chanarray;
+ sc->sc_wdcdev.nchannels = PCIIDE_NUM_CHANNELS;
+ chanenable = pci_conf_read(sc->sc_pc, sc->sc_tag, AMD756_CHANSTATUS_EN);
+
+ pciide_print_channels(sc->sc_wdcdev.nchannels, interface);
+
+ for (channel = 0; channel < sc->sc_wdcdev.nchannels; channel++) {
+ cp = &sc->pciide_channels[channel];
+ if (pciide_chansetup(sc, channel, interface) == 0)
+ continue;
+
+ if ((chanenable & AMD756_CHAN_EN(channel)) == 0) {
+ printf("%s: %s ignored (disabled)\n",
+ sc->sc_wdcdev.sc_dev.dv_xname, cp->name);
+ continue;
+ }
+ pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize,
+ pciide_pci_intr);
+
+ if (pciiide_chan_candisable(cp))
+ chanenable &= ~AMD756_CHAN_EN(channel);
+ pciide_map_compat_intr(pa, cp, channel, interface);
+ if (cp->hw_ok == 0)
+ continue;
+
+ amd756_setup_channel(&cp->wdc_channel);
+ }
+ pci_conf_write(sc->sc_pc, sc->sc_tag, AMD756_CHANSTATUS_EN,
+ chanenable);
+ return;
+}
+
+void
+amd756_setup_channel(chp)
+ struct channel_softc *chp;
+{
+ u_int32_t udmatim_reg, datatim_reg;
+ u_int8_t idedma_ctl;
+ int mode, drive;
+ struct ata_drive_datas *drvp;
+ struct pciide_channel *cp = (struct pciide_channel*)chp;
+ struct pciide_softc *sc = (struct pciide_softc *)cp->wdc_channel.wdc;
+
+ idedma_ctl = 0;
+ datatim_reg = pci_conf_read(sc->sc_pc, sc->sc_tag, AMD756_DATATIM);
+ udmatim_reg = pci_conf_read(sc->sc_pc, sc->sc_tag, AMD756_UDMA);
+ datatim_reg &= ~AMD756_DATATIM_MASK(chp->channel);
+ udmatim_reg &= ~AMD756_UDMA_MASK(chp->channel);
+
+ /* setup DMA if needed */
+ pciide_channel_dma_setup(cp);
+
+ 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 (((drvp->drive_flags & DRIVE_DMA) == 0 &&
+ (drvp->drive_flags & DRIVE_UDMA) == 0)) {
+ mode = drvp->PIO_mode;
+ goto pio;
+ }
+ if ((chp->wdc->cap & WDC_CAPABILITY_UDMA) &&
+ (drvp->drive_flags & DRIVE_UDMA)) {
+ /* use Ultra/DMA */
+ drvp->drive_flags &= ~DRIVE_DMA;
+ udmatim_reg |= AMD756_UDMA_EN(chp->channel, drive) |
+ AMD756_UDMA_EN_MTH(chp->channel, drive) |
+ AMD756_UDMA_TIME(chp->channel, drive,
+ amd756_udma_tim[drvp->UDMA_mode]);
+ /* can use PIO timings, MW DMA unused */
+ mode = drvp->PIO_mode;
+ } else {
+ /* use Multiword DMA */
+ drvp->drive_flags &= ~DRIVE_UDMA;
+ /* mode = min(pio, dma+2) */
+ if (drvp->PIO_mode <= (drvp->DMA_mode +2))
+ mode = drvp->PIO_mode;
+ else
+ mode = drvp->DMA_mode + 2;
+ }
+ idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
+
+pio: /* setup PIO mode */
+ if (mode <= 2) {
+ drvp->DMA_mode = 0;
+ drvp->PIO_mode = 0;
+ mode = 0;
+ } else {
+ drvp->PIO_mode = mode;
+ drvp->DMA_mode = mode - 2;
+ }
+ datatim_reg |=
+ AMD756_DATATIM_PULSE(chp->channel, drive,
+ amd756_pio_set[mode]) |
+ AMD756_DATATIM_RECOV(chp->channel, drive,
+ amd756_pio_rec[mode]);
+ }
+ 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 * chp->channel),
+ idedma_ctl);
+ }
+ pciide_print_modes(cp);
+ pci_conf_write(sc->sc_pc, sc->sc_tag, AMD756_DATATIM, datatim_reg);
+ pci_conf_write(sc->sc_pc, sc->sc_tag, AMD756_UDMA, udmatim_reg);
+}
+
void
apollo_chip_map(sc, pa)
struct pciide_softc *sc;
} else {
printf("%s: unexpected PCI function %d\n",
sc->sc_wdcdev.sc_dev.dv_xname, pa->pa_function);
- cp->hw_ok = 0;
return;
}
if (interface & PCIIDE_INTERFACE_BUS_MASTER_DMA) {
--- /dev/null
+/* $OpenBSD: pciide_amd_reg.h,v 1.1 2000/03/24 17:47:41 chris Exp $ */
+
+/*
+ * Copyright (c) 2000 David Sainty.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ *
+ */
+
+/*
+ * Registers definitions for AMD 756 PCI IDE controller. Documentation
+ * available at: http://www.amd.com/products/cpg/athlon/techdocs/pdf/22548.pdf
+ */
+
+/* Channel enable */
+#define AMD756_CHANSTATUS_EN 0x40
+#define AMD756_CHAN_EN(chan) (0x01 << (1 - (chan)))
+
+/* Data port timing controls */
+#define AMD756_DATATIM 0x48
+#define AMD756_DATATIM_MASK(channel) (0xffff << ((1 - (channel)) << 4))
+#define AMD756_DATATIM_RECOV(channel, drive, x) (((x) & 0xf) << \
+ (((1 - (channel)) << 4) + ((1 - (drive)) << 3)))
+#define AMD756_DATATIM_PULSE(channel, drive, x) (((x) & 0xf) << \
+ (((1 - (channel)) << 4) + ((1 - (drive)) << 3) + 4))
+
+static const int8_t amd756_pio_set[] = {0x0a, 0x0a, 0x0a, 0x02, 0x02};
+static const int8_t amd756_pio_rec[] = {0x08, 0x08, 0x08, 0x02, 0x00};
+
+/* Ultra-DMA/33 control */
+#define AMD756_UDMA 0x50
+#define AMD756_UDMA_MASK(channel) (0xffff << ((1 - (channel)) << 4))
+#define AMD756_UDMA_TIME(channel, drive, x) (((x) & 0x7) << \
+ (((1 - (channel)) << 4) + ((1 - (drive)) << 3)))
+#define AMD756_UDMA_EN(channel, drive) (0x40 << \
+ (((1 - (channel)) << 4) + ((1 - (drive)) << 3)))
+#define AMD756_UDMA_EN_MTH(channel, drive) (0x80 << \
+ (((1 - (channel)) << 4) + ((1 - (drive)) << 3)))
+
+static const int8_t amd756_udma_tim[] = {0x02, 0x01, 0x00, 0x04, 0x05};