The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/pci/geodeide.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: geodeide.c,v 1.1.2.3 2004/07/28 10:56:06 tron Exp $    */
    2 
    3 /*
    4  * Copyright (c) 2004 Manuel Bouyer.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  * 3. All advertising materials mentioning features or use of this software
   15  *    must display the following acknowledgement:
   16  *      This product includes software developed by Manuel Bouyer.
   17  * 4. The name of the author may not be used to endorse or promote products
   18  *    derived from this software without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   30  *
   31  */
   32 
   33 /*
   34  * Driver for the IDE part of the AMD Geode CS5530A companion chip
   35  * and AMD Geode SC1100.
   36  * Docs available from AMD's web site
   37  */
   38 
   39 #include <sys/cdefs.h>
   40 __KERNEL_RCSID(0, "$NetBSD: geodeide.c,v 1.1.2.3 2004/07/28 10:56:06 tron Exp $");
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 
   45 #include <uvm/uvm_extern.h>
   46 
   47 #include <dev/pci/pcivar.h>
   48 #include <dev/pci/pcidevs.h>
   49 #include <dev/pci/pciidereg.h>
   50 #include <dev/pci/pciidevar.h>
   51 
   52 #include <dev/pci/pciide_geode_reg.h>
   53 
   54 static void geodeide_chip_map(struct pciide_softc *,
   55                                  struct pci_attach_args *);
   56 static void geodeide_setup_channel(struct wdc_channel *);
   57 
   58 static int  geodeide_match(struct device *, struct cfdata *, void *);
   59 static void geodeide_attach(struct device *, struct device *, void *);
   60 
   61 CFATTACH_DECL(geodeide, sizeof(struct pciide_softc),
   62     geodeide_match, geodeide_attach, NULL, NULL);
   63 
   64 static const struct pciide_product_desc pciide_geode_products[] = {
   65         { PCI_PRODUCT_CYRIX_CX5530_IDE,
   66           0,
   67           "AMD Geode CX5530 IDE controller",
   68           geodeide_chip_map,
   69         },
   70         { PCI_PRODUCT_NS_SC1100_IDE,
   71           0,
   72           "AMD Geode SC1100 IDE controller",
   73           geodeide_chip_map,
   74         },
   75         { 0,
   76           0,
   77           NULL,
   78           NULL,
   79         },
   80 };
   81 
   82 static int
   83 geodeide_match(struct device *parent, struct cfdata *match, void *aux)
   84 {
   85         struct pci_attach_args *pa = aux;
   86 
   87         if ((PCI_VENDOR(pa->pa_id) == PCI_VENDOR_CYRIX ||
   88              PCI_VENDOR(pa->pa_id) == PCI_VENDOR_NS) &&
   89              PCI_CLASS(pa->pa_class) == PCI_CLASS_MASS_STORAGE &&
   90              PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MASS_STORAGE_IDE &&
   91              pciide_lookup_product(pa->pa_id, pciide_geode_products)) 
   92                 return(2);
   93         return (0);
   94 }
   95 
   96 static void
   97 geodeide_attach(struct device *parent, struct device *self, void *aux)
   98 {
   99         struct pci_attach_args *pa = aux;
  100         struct pciide_softc *sc = (void *)self;
  101 
  102         pciide_common_attach(sc, pa,
  103             pciide_lookup_product(pa->pa_id, pciide_geode_products));
  104 }
  105 
  106 static void
  107 geodeide_chip_map(struct pciide_softc *sc, struct pci_attach_args *pa)
  108 {
  109         struct pciide_channel *cp;
  110         int channel;
  111         bus_size_t cmdsize, ctlsize;
  112 
  113         if (pciide_chipen(sc, pa) == 0)
  114                 return;
  115 
  116         aprint_normal("%s: bus-master DMA support present",
  117             sc->sc_wdcdev.sc_dev.dv_xname);
  118         pciide_mapreg_dma(sc, pa);
  119         aprint_normal("\n");
  120         if (sc->sc_dma_ok) {
  121                 sc->sc_wdcdev.cap = WDC_CAPABILITY_DMA | WDC_CAPABILITY_UDMA |
  122                     WDC_CAPABILITY_IRQACK;
  123                 sc->sc_wdcdev.irqack = pciide_irqack;
  124         }
  125         sc->sc_wdcdev.PIO_cap = 4;
  126         sc->sc_wdcdev.DMA_cap = 2;
  127         sc->sc_wdcdev.UDMA_cap = 2;
  128         sc->sc_wdcdev.set_modes = geodeide_setup_channel;
  129         sc->sc_wdcdev.channels = sc->wdc_chanarray;
  130         sc->sc_wdcdev.nchannels = PCIIDE_NUM_CHANNELS;
  131         sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_DATA32 |
  132             WDC_CAPABILITY_MODE;
  133 
  134         /*
  135          * Soekris Engineering Issue #0003:
  136          *      "The SC1100 built in busmaster IDE controller is pretty
  137          *       standard, but have two bugs: data transfers need to be
  138          *       dword aligned and it cannot do an exact 64Kbyte data
  139          *       transfer."
  140          */
  141         if (sc->sc_pp->ide_product == PCI_PRODUCT_NS_SC1100_IDE) {
  142                 if (sc->sc_dma_boundary == 0x10000)
  143                         sc->sc_dma_boundary -= PAGE_SIZE;
  144 
  145                 if (sc->sc_dma_maxsegsz == 0x10000)
  146                         sc->sc_dma_maxsegsz -= PAGE_SIZE;
  147         }
  148 
  149         for (channel = 0; channel < sc->sc_wdcdev.nchannels; channel++) {
  150                 cp = &sc->pciide_channels[channel];
  151                 /* controller is compat-only */
  152                 if (pciide_chansetup(sc, channel, 0) == 0)
  153                         continue;
  154                 pciide_mapchan(pa, cp, 0, &cmdsize, &ctlsize, pciide_pci_intr);
  155         }
  156 }
  157 
  158 static void
  159 geodeide_setup_channel(struct wdc_channel *chp)
  160 {
  161         struct ata_drive_datas *drvp;
  162         struct pciide_channel *cp = (struct pciide_channel*)chp;
  163         struct pciide_softc *sc = (struct pciide_softc *)cp->wdc_channel.ch_wdc;
  164         int channel = chp->ch_channel;
  165         int drive;
  166         u_int32_t dma_timing;
  167         u_int8_t idedma_ctl;
  168         const int32_t *geode_pio;
  169         const int32_t *geode_dma;
  170         const int32_t *geode_udma;
  171         bus_size_t dmaoff, piooff;
  172 
  173         switch (sc->sc_pp->ide_product) {
  174         case PCI_PRODUCT_CYRIX_CX5530_IDE:
  175                 geode_pio = geode_cs5530_pio;
  176                 geode_dma = geode_cs5530_dma;
  177                 geode_udma = geode_cs5530_udma;
  178                 break;
  179 
  180         case PCI_PRODUCT_NS_SC1100_IDE:
  181         default: /* XXX gcc */
  182                 geode_pio = geode_sc1100_pio;
  183                 geode_dma = geode_sc1100_dma;
  184                 geode_udma = geode_sc1100_udma;
  185                 break;
  186         }
  187 
  188         /* setup DMA if needed */
  189         pciide_channel_dma_setup(cp);
  190 
  191         idedma_ctl = 0;
  192 
  193         /* Per drive settings */
  194         for (drive = 0; drive < 2; drive++) {
  195                 drvp = &chp->ch_drive[drive];
  196                 /* If no drive, skip */
  197                 if ((drvp->drive_flags & DRIVE) == 0)
  198                         continue;
  199 
  200                 switch (sc->sc_pp->ide_product) {
  201                 case PCI_PRODUCT_CYRIX_CX5530_IDE:
  202                         dmaoff = CS5530_DMA_REG(channel, drive);
  203                         piooff = CS5530_PIO_REG(channel, drive);
  204                         dma_timing = CS5530_DMA_REG_PIO_FORMAT;
  205                         break;
  206 
  207                 case PCI_PRODUCT_NS_SC1100_IDE:
  208                 default: /* XXX gcc */
  209                         dmaoff = SC1100_DMA_REG(channel, drive);
  210                         piooff = SC1100_PIO_REG(channel, drive);
  211                         dma_timing = 0;
  212                         break;
  213                 }
  214 
  215                 /* add timing values, setup DMA if needed */
  216                 if (drvp->drive_flags & DRIVE_UDMA) {
  217                         /* Use Ultra-DMA */
  218                         dma_timing |= geode_udma[drvp->UDMA_mode];
  219                         idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
  220                 } else if (drvp->drive_flags & DRIVE_DMA) {
  221                         /* use Multiword DMA */
  222                         dma_timing |= geode_dma[drvp->DMA_mode];
  223                         idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
  224                 } else {
  225                         /* PIO only */
  226                         drvp->drive_flags &= ~(DRIVE_UDMA | DRIVE_DMA);
  227                 }
  228 
  229                 switch (sc->sc_pp->ide_product) {
  230                 case PCI_PRODUCT_CYRIX_CX5530_IDE:
  231                         bus_space_write_4(sc->sc_dma_iot, sc->sc_dma_ioh,
  232                             dmaoff, dma_timing);
  233                         bus_space_write_4(sc->sc_dma_iot, sc->sc_dma_ioh,
  234                             piooff, geode_pio[drvp->PIO_mode]);
  235                         break;
  236 
  237                 case PCI_PRODUCT_NS_SC1100_IDE:
  238                         pci_conf_write(sc->sc_pc, sc->sc_tag, dmaoff,
  239                             dma_timing);
  240                         pci_conf_write(sc->sc_pc, sc->sc_tag, piooff,
  241                             geode_pio[drvp->PIO_mode]);
  242                         break;
  243                 }
  244         }
  245 
  246         if (idedma_ctl != 0) {
  247                 /* Add software bits in status register */
  248                 bus_space_write_1(sc->sc_dma_iot, cp->dma_iohs[IDEDMA_CTL], 0,
  249                     idedma_ctl);
  250         }
  251 }

Cache object: f7becd2c7a41146c58109902733cd44d


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.