Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-1-5]: src/sys/dev/pci Pull up revisions 1.112, 1.118, 1.125, 1.128 (...



details:   https://anonhg.NetBSD.org/src/rev/e91b5a8d78a6
branches:  netbsd-1-5
changeset: 492667:e91b5a8d78a6
user:      he <he%NetBSD.org@localhost>
date:      Wed Feb 06 14:17:51 2002 +0000

description:
Pull up revisions 1.112,1.118,1.125,1.128 (via patch, requested by tsutsui):
  Add support for Acard ATP-850/860 pciide controllers.

diffstat:

 sys/dev/pci/pciide.c |  251 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 250 insertions(+), 1 deletions(-)

diffs (290 lines):

diff -r cdfee633bd95 -r e91b5a8d78a6 sys/dev/pci/pciide.c
--- a/sys/dev/pci/pciide.c      Wed Feb 06 14:17:28 2002 +0000
+++ b/sys/dev/pci/pciide.c      Wed Feb 06 14:17:51 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pciide.c,v 1.68.2.29 2002/01/05 18:05:58 he Exp $      */
+/*     $NetBSD: pciide.c,v 1.68.2.30 2002/02/06 14:17:51 he Exp $      */
 
 
 /*
@@ -117,6 +117,7 @@
 #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>
 
 #include "opt_pciide.h"
@@ -198,6 +199,10 @@
 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));
 int  pciide_dma_init __P((void*, int, int, void *, size_t, int));
@@ -445,6 +450,28 @@
        }
 };
 
+const struct pciide_product_desc pciide_acard_products[] =  {
+       { PCI_PRODUCT_ACARD_ATP850U,
+         IDE_PCI_CLASS_OVERRIDE,
+         "Acard ATP850U Ultra33 IDE Controller",
+         acard_chip_map,
+       },
+       { PCI_PRODUCT_ACARD_ATP860,
+         IDE_PCI_CLASS_OVERRIDE,
+         "Acard ATP860 Ultra66 IDE Controller",
+         acard_chip_map,
+       },
+       { PCI_PRODUCT_ACARD_ATP860A,
+         IDE_PCI_CLASS_OVERRIDE,
+         "Acard ATP860-A Ultra66 IDE Controller",
+         acard_chip_map,
+       },
+       { 0,
+         0,
+         NULL,
+       }
+};
+
 struct pciide_vendor_desc {
        u_int32_t ide_vendor;
        const struct pciide_product_desc *ide_products;
@@ -461,6 +488,7 @@
        { PCI_VENDOR_AMD, pciide_amd_products },
        { PCI_VENDOR_OPTI, pciide_opti_products },
        { PCI_VENDOR_TRIONES, pciide_triones_products },
+       { PCI_VENDOR_ACARD, pciide_acard_products },
        { 0, NULL }
 };
 
@@ -3714,3 +3742,224 @@
 
        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("%s: bus-master DMA support present",
+           sc->sc_wdcdev.sc_dev.dv_xname);
+       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);
+
+               /* check 80 pins cable */
+               if ((chp->ch_drive[0].drive_flags & DRIVE_UDMA) ||
+                   (chp->ch_drive[1].drive_flags & DRIVE_UDMA)) {
+                       if (pci_conf_read(sc->sc_pc, sc->sc_tag, ATP8x0_CTRL)
+                           & ATP860_CTRL_80P(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;
+                       }
+               }
+       }
+
+       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;
+}



Home | Main Index | Thread Index | Old Index