Subject: pciide for Acer M5229 controller
To: None <port-i386@netbsd.org>
From: Manuel Bouyer <bouyer@antioche.lip6.fr>
List: port-i386
Date: 01/28/1999 19:12:29
--9vaYmALEf/7YXxc3
Content-Type: text/plain; charset=us-ascii
Hi,
below is a patch that should add support for the M5229 IDE controller
to pciide. Could people which have a chance to play with such hardware
give it a try and report me how it goes ?
--
Manuel Bouyer, LIP6, Universite Paris VI. Manuel.Bouyer@lip6.fr
--
--9vaYmALEf/7YXxc3
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="pciide.diff"
Index: pciide.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/pciide.c,v
retrieving revision 1.29
diff -u -r1.29 pciide.c
--- pciide.c 1998/12/16 13:21:26 1.29
+++ pciide.c 1999/01/28 17:04:51
@@ -74,6 +74,7 @@
#include <dev/pci/pciide_cmd_reg.h>
#include <dev/pci/pciide_cy693_reg.h>
#include <dev/pci/pciide_sis_reg.h>
+#include <dev/pci/pciide_acer_reg.h>
#include <dev/ata/atavar.h>
#include <dev/ic/wdcreg.h>
#include <dev/ic/wdcvar.h>
@@ -174,6 +175,11 @@
void sis_setup_channel __P((struct channel_softc*));
void sis_channel_map __P((struct pci_attach_args *, struct pciide_channel *));
+void acer_setup_cap __P((struct pciide_softc*));
+void acer_setup_chip __P((struct pciide_softc*));
+void acer_setup_channel __P((struct channel_softc*));
+void acer_channel_map __P((struct pci_attach_args *, struct pciide_channel *));
+
void pciide_channel_dma_setup __P((struct pciide_channel *));
int pciide_dma_table_setup __P((struct pciide_softc*, int, int));
int pciide_dma_init __P((void*, int, int, void *, size_t, int));
@@ -338,6 +344,22 @@
}
};
+const struct pciide_product_desc pciide_acer_products[] = {
+ { PCI_PRODUCT_ALI_M5229,
+ 0,
+ PCIIDE_NUM_CHANNELS,
+ "Acer Labs M5229 UDMA IDE Controller",
+ acer_setup_cap,
+ acer_setup_chip,
+ acer_channel_map
+ },
+ { 0,
+ 0,
+ 0,
+ NULL,
+ }
+};
+
struct pciide_vendor_desc {
u_int32_t ide_vendor;
const struct pciide_product_desc *ide_products;
@@ -349,6 +371,7 @@
{ PCI_VENDOR_VIATECH, pciide_via_products },
{ PCI_VENDOR_CONTAQ, pciide_cypress_products },
{ PCI_VENDOR_SIS, pciide_sis_products },
+ { PCI_VENDOR_ALI, pciide_acer_products },
{ 0, NULL }
};
@@ -2056,6 +2079,141 @@
else
sis_ctr0 &= ~SIS_CTRL0_CHAN1_EN;
pciide_pci_write(sc->sc_pc, sc->sc_tag, SIS_CTRL0, sis_ctr0);
+ }
+ pciide_map_compat_intr(pa, cp, wdc_cp->channel, interface);
+}
+
+void
+acer_setup_cap(sc)
+ struct pciide_softc *sc;
+{
+ sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA32 | WDC_CAPABILITY_MODE |
+ WDC_CAPABILITY_DMA | WDC_CAPABILITY_UDMA;
+ sc->sc_wdcdev.PIO_cap = 4;
+ sc->sc_wdcdev.DMA_cap = 2;
+ sc->sc_wdcdev.UDMA_cap = 2;
+ sc->sc_wdcdev.set_modes = acer_setup_channel;
+}
+
+void
+acer_setup_chip(sc)
+ struct pciide_softc *sc;
+{
+ int channel;
+
+ for (channel = 0; channel < sc->sc_wdcdev.nchannels; channel++) {
+ acer_setup_channel(&sc->pciide_channels[channel].wdc_channel);
+ }
+}
+
+void
+acer_setup_channel(chp)
+ struct channel_softc *chp;
+{
+ struct ata_drive_datas *drvp;
+ int drive;
+ u_int32_t acer_fifo_udma;
+ u_int32_t idedma_ctl;
+ struct pciide_channel *cp = (struct pciide_channel*)chp;
+ struct pciide_softc *sc = (struct pciide_softc *)cp->wdc_channel.wdc;
+
+ idedma_ctl = 0;
+ acer_fifo_udma = pci_conf_read(sc->sc_pc, sc->sc_tag, ACER_FTH_UDMA);
+ WDCDEBUG_PRINT(("acer_setup_chip: old fifo/udma reg 0x%x\n",
+ acer_fifo_udma), DEBUG_PROBE);
+ /* 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;
+ WDCDEBUG_PRINT(("acer_setup_chip: old timings reg for "
+ "channel %d drive %d 0x%x\n", chp->channel, drive,
+ pciide_pci_read(sc->sc_pc, sc->sc_tag,
+ ACER_IDETIM(chp->channel, drive))), DEBUG_PROBE);
+ /* clear FIFO/DMA mode */
+ acer_fifo_udma &= ~(ACER_FTH_OPL(chp->channel, drive, 0x3) |
+ ACER_UDMA_EN(chp->channel, drive) |
+ ACER_UDMA_TIM(chp->channel, drive, 0x7));
+
+ /* add timing values, setup DMA if needed */
+ if ((drvp->drive_flags & DRIVE_DMA) == 0 &&
+ (drvp->drive_flags & DRIVE_UDMA) == 0) {
+ acer_fifo_udma |=
+ ACER_FTH_OPL(chp->channel, drive, 0x1);
+ goto pio;
+ }
+
+ acer_fifo_udma |= ACER_FTH_OPL(chp->channel, drive, 0x2);
+ if (drvp->drive_flags & DRIVE_UDMA) {
+ /* use Ultra/DMA */
+ drvp->drive_flags &= ~DRIVE_DMA;
+ acer_fifo_udma |= ACER_UDMA_EN(chp->channel, drive);
+ acer_fifo_udma |=
+ ACER_UDMA_TIM(chp->channel, drive,
+ acer_udma[drvp->UDMA_mode]);
+ } else {
+ /*
+ * use Multiword DMA
+ * Timings will be used for both PIO and DMA,
+ * so adjust DMA mode if needed
+ */
+ if (drvp->PIO_mode > (drvp->DMA_mode + 2))
+ drvp->PIO_mode = drvp->DMA_mode + 2;
+ if (drvp->DMA_mode == 0)
+ drvp->PIO_mode = 0;
+ }
+ idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
+pio: pciide_pci_write(sc->sc_pc, sc->sc_tag,
+ ACER_IDETIM(chp->channel, drive),
+ acer_pio[drvp->PIO_mode]);
+ }
+ WDCDEBUG_PRINT(("acer_setup_chip: old fifo/udma reg 0x%x\n",
+ acer_fifo_udma), DEBUG_PROBE);
+ pci_conf_write(sc->sc_pc, sc->sc_tag, ACER_FTH_UDMA, acer_fifo_udma);
+ 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_ctl);
+ }
+ pciide_print_modes(cp);
+}
+
+void
+acer_channel_map(pa, cp)
+ struct pci_attach_args *pa;
+ struct pciide_channel *cp;
+{
+ struct pciide_softc *sc = (struct pciide_softc *)cp->wdc_channel.wdc;
+ bus_size_t cmdsize, ctlsize;
+ struct channel_softc *wdc_cp = &cp->wdc_channel;
+ u_int32_t cr = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_CLASS_REG);
+ int interface = PCI_INTERFACE(cr);
+
+ /* Enable "microsoft register bits" R/W */
+ pciide_pci_write(sc->sc_pc, sc->sc_tag, ACER_CCAR3,
+ pciide_pci_read(sc->sc_pc, sc->sc_tag, ACER_CCAR3) | ACER_CCAR3_PI);
+ pciide_pci_write(sc->sc_pc, sc->sc_tag, ACER_CCAR1,
+ pciide_pci_read(sc->sc_pc, sc->sc_tag, ACER_CCAR1) &
+ ~(ACER_CHANSTATUS_RO|PCIIDE_CHAN_RO(0)|PCIIDE_CHAN_RO(1)));
+ pciide_pci_write(sc->sc_pc, sc->sc_tag, ACER_CCAR2,
+ pciide_pci_read(sc->sc_pc, sc->sc_tag, ACER_CCAR2) &
+ ~ACER_CHANSTATUSREGS_RO);
+
+ if ((interface & PCIIDE_CHAN_EN(wdc_cp->channel)) == 0) {
+ printf("%s: %s channel ignored (disabled)\n",
+ sc->sc_wdcdev.sc_dev.dv_xname, cp->name);
+ return;
+ }
+
+ pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize);
+ if (cp->hw_ok == 0)
+ return;
+ if (pciiide_chan_candisable(cp)) {
+ cr &= ~(PCIIDE_CHAN_EN(wdc_cp->channel) << PCI_INTERFACE_SHIFT);
+ pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_CLASS_REG, cr);
}
pciide_map_compat_intr(pa, cp, wdc_cp->channel, interface);
}
Index: pciide_acer_reg.h
===================================================================
RCS file: pciide_acer_reg.h
diff -N pciide_acer_reg.h
--- /dev/null Thu Jan 28 03:36:12 1999
+++ pciide_acer_reg.h Thu Jan 28 09:04:51 1999
@@ -0,0 +1,73 @@
+/* $NetBSD: $ */
+
+/*
+ * Copyright (c) 1999 Manuel Bouyer.
+ *
+ * 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.
+ *
+ */
+
+/* class code attribute register 1 (1 byte) */
+#define ACER_CCAR1 0x43
+#define ACER_CHANSTATUS_RO 0x40
+#define PCIIDE_CHAN_RO(chan) (0x10 << (chan))
+
+/* class code attribute register 2 (1 byte) */
+#define ACER_CCAR2 0x4d
+#define ACER_CHANSTATUSREGS_RO 0x80
+
+/* class code attribute register 3 (1 byte) */
+#define ACER_CCAR3 0x50
+#define ACER_CCAR3_PI 0x02
+
+/* Fifo threshold and Ultra-DMA settings (4 bytes). */
+#define ACER_FTH_UDMA 0x54
+#define ACER_FTH_VAL(chan, drv, val) \
+ (((val) & 0x3) << ((drv) * 4 + (chan) * 8))
+#define ACER_FTH_OPL(chan, drv, val) \
+ (((val) & 0x3) << (2 + (drv) * 4 + (chan) * 8))
+#define ACER_UDMA_EN(chan, drv) \
+ (0x8 << (16 + (drv) * 4 + (chan) * 8))
+#define ACER_UDMA_TIM(chan, drv, val) \
+ (((val) & 0x7) << (16 + (drv) * 4 + (chan) * 8))
+
+/* drives timings setup (1 byte) */
+#define ACER_IDETIM(chan, drv) (0x5a + (drv) + (chan) * 4)
+
+/*
+ * 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};
+static int8_t acer_pio[] = {0x0c, 0x58, 0x44, 0x33, 0x31};
+#ifdef unused
+static int8_t acer_dma[] = {0x08, 0x33, 0x31};
+#endif
Index: pciidereg.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/pciidereg.h,v
retrieving revision 1.3
diff -u -r1.3 pciidereg.h
--- pciidereg.h 1998/10/12 16:09:22 1.3
+++ pciidereg.h 1999/01/28 17:04:51
@@ -55,7 +55,12 @@
/*
* Bits in the PCI Programming Interface register (some are per-channel).
+ * Bits 6-4 are defined as read-only in PCI 2.1 specification.
+ * Microsoft proposed to use these bits for independant channels
+ * enable/disable. This feature is enabled based on the value of bit 6.
*/
+#define PCIIDE_CHANSTATUS_EN 0x40
+#define PCIIDE_CHAN_EN(chan) (0x10 << (chan))
#define PCIIDE_INTERFACE_PCI(chan) (0x01 << (2 * (chan)))
#define PCIIDE_INTERFACE_SETTABLE(chan) (0x02 << (2 * (chan)))
#define PCIIDE_INTERFACE_BUS_MASTER_DMA 0x80
--9vaYmALEf/7YXxc3--