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/cypide.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: cypide.c,v 1.7.2.1 2004/08/11 19:46:16 jmc Exp $       */
    2 
    3 /*
    4  * Copyright (c) 1999, 2000, 2001 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 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 #include <sys/malloc.h>
   36 
   37 #include <dev/pci/pcivar.h>
   38 #include <dev/pci/pcidevs.h>
   39 #include <dev/pci/pciidereg.h>
   40 #include <dev/pci/pciidevar.h>
   41 #include <dev/pci/pciide_cy693_reg.h>
   42 #include <dev/pci/cy82c693var.h>
   43 
   44 static void cy693_chip_map(struct pciide_softc*, struct pci_attach_args*);
   45 static void cy693_setup_channel(struct wdc_channel*);
   46 
   47 static int  cypide_match(struct device *, struct cfdata *, void *);
   48 static void cypide_attach(struct device *, struct device *, void *);
   49 
   50 CFATTACH_DECL(cypide, sizeof(struct pciide_softc),
   51     cypide_match, cypide_attach, NULL, NULL);
   52 
   53 static const struct pciide_product_desc pciide_cypress_products[] =  {
   54         { PCI_PRODUCT_CONTAQ_82C693,
   55           IDE_16BIT_IOSPACE,
   56           "Cypress 82C693 IDE Controller",
   57           cy693_chip_map,
   58         },
   59         { 0,
   60           0,
   61           NULL,
   62           NULL
   63         }
   64 };
   65 
   66 static int
   67 cypide_match(struct device *parent, struct cfdata *match, void *aux)
   68 {
   69         struct pci_attach_args *pa = aux;
   70 
   71         if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_CONTAQ &&
   72             PCI_CLASS(pa->pa_class) == PCI_CLASS_MASS_STORAGE &&
   73             PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MASS_STORAGE_IDE) {
   74                 if (pciide_lookup_product(pa->pa_id, pciide_cypress_products))
   75                         return (2);
   76         }
   77         return (0);
   78 }
   79 
   80 static void
   81 cypide_attach(struct device *parent, struct device *self, void *aux)
   82 {
   83         struct pci_attach_args *pa = aux;
   84         struct pciide_softc *sc = (struct pciide_softc *)self;
   85 
   86         pciide_common_attach(sc, pa,
   87             pciide_lookup_product(pa->pa_id, pciide_cypress_products));
   88 
   89 }
   90 
   91 static void
   92 cy693_chip_map(struct pciide_softc *sc, struct pci_attach_args *pa)
   93 {        
   94         struct pciide_channel *cp;
   95         pcireg_t interface = PCI_INTERFACE(pa->pa_class);
   96         bus_size_t cmdsize, ctlsize;
   97 
   98         if (pciide_chipen(sc, pa) == 0)
   99                 return;
  100 
  101         /*
  102          * this chip has 2 PCI IDE functions, one for primary and one for
  103          * secondary. So we need to call pciide_mapregs_compat() with
  104          * the real channel
  105          */
  106         if (pa->pa_function == 1) {
  107                 sc->sc_cy_compatchan = 0;
  108         } else if (pa->pa_function == 2) {
  109                 sc->sc_cy_compatchan = 1;
  110         } else {
  111                 aprint_error("%s: unexpected PCI function %d\n",
  112                     sc->sc_wdcdev.sc_dev.dv_xname, pa->pa_function);
  113                 return;
  114         }
  115         if (interface & PCIIDE_INTERFACE_BUS_MASTER_DMA) {
  116                 aprint_normal("%s: bus-master DMA support present",
  117                     sc->sc_wdcdev.sc_dev.dv_xname);
  118                 pciide_mapreg_dma(sc, pa);
  119         } else {
  120                 aprint_normal("%s: hardware does not support DMA",
  121                     sc->sc_wdcdev.sc_dev.dv_xname);
  122                 sc->sc_dma_ok = 0;
  123         }
  124         aprint_normal("\n");
  125 
  126         sc->sc_cy_handle = cy82c693_init(pa->pa_iot);
  127         if (sc->sc_cy_handle == NULL) {
  128                 aprint_error("%s: unable to map hyperCache control registers\n",
  129                     sc->sc_wdcdev.sc_dev.dv_xname);
  130                 sc->sc_dma_ok = 0;
  131         }
  132 
  133         sc->sc_wdcdev.cap = WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_DATA32 |
  134             WDC_CAPABILITY_MODE;
  135         if (sc->sc_dma_ok) {
  136                 sc->sc_wdcdev.cap |= WDC_CAPABILITY_DMA | WDC_CAPABILITY_IRQACK;
  137                 sc->sc_wdcdev.irqack = pciide_irqack;
  138         }
  139         sc->sc_wdcdev.PIO_cap = 4;
  140         sc->sc_wdcdev.DMA_cap = 2;
  141         sc->sc_wdcdev.set_modes = cy693_setup_channel;
  142 
  143         sc->sc_wdcdev.channels = sc->wdc_chanarray;
  144         sc->sc_wdcdev.nchannels = 1;
  145 
  146         /* Only one channel for this chip; if we are here it's enabled */
  147         cp = &sc->pciide_channels[0];
  148         sc->wdc_chanarray[0] = &cp->wdc_channel;
  149         cp->name = PCIIDE_CHANNEL_NAME(0);
  150         cp->wdc_channel.ch_channel = 0;
  151         cp->wdc_channel.ch_wdc = &sc->sc_wdcdev;
  152         cp->wdc_channel.ch_queue =
  153             malloc(sizeof(struct ata_queue), M_DEVBUF, M_NOWAIT);
  154         if (cp->wdc_channel.ch_queue == NULL) {
  155                 aprint_error("%s primary channel: "
  156                     "can't allocate memory for command queue",
  157                 sc->sc_wdcdev.sc_dev.dv_xname);
  158                 return;
  159         }
  160         aprint_normal("%s: primary channel %s to ",
  161             sc->sc_wdcdev.sc_dev.dv_xname, 
  162             (interface & PCIIDE_INTERFACE_SETTABLE(0)) ?
  163             "configured" : "wired");
  164         if (interface & PCIIDE_INTERFACE_PCI(0)) {
  165                 aprint_normal("native-PCI mode\n");
  166                 pciide_mapregs_native(pa, cp, &cmdsize, &ctlsize,
  167                     pciide_pci_intr);
  168         } else {
  169                 aprint_normal("compatibility mode\n");
  170                 pciide_mapregs_compat(pa, cp, sc->sc_cy_compatchan, &cmdsize,
  171                     &ctlsize);
  172                 if ((cp->wdc_channel.ch_flags & WDCF_DISABLED) == 0)
  173                         pciide_map_compat_intr(pa, cp, sc->sc_cy_compatchan);
  174         }
  175         wdcattach(&cp->wdc_channel);
  176 }
  177 
  178 static void
  179 cy693_setup_channel(struct wdc_channel *chp)
  180 {
  181         struct ata_drive_datas *drvp;
  182         int drive;
  183         u_int32_t cy_cmd_ctrl;
  184         u_int32_t idedma_ctl;
  185         struct pciide_channel *cp = (struct pciide_channel*)chp;
  186         struct pciide_softc *sc = (struct pciide_softc *)cp->wdc_channel.ch_wdc;
  187         int dma_mode = -1;
  188 
  189         WDCDEBUG_PRINT(("cy693_chip_map: old timings reg 0x%x\n",
  190             pci_conf_read(sc->sc_pc, sc->sc_tag, CY_CMD_CTRL)),DEBUG_PROBE);
  191 
  192         cy_cmd_ctrl = idedma_ctl = 0;
  193 
  194         /* setup DMA if needed */
  195         pciide_channel_dma_setup(cp);
  196 
  197         for (drive = 0; drive < 2; drive++) {
  198                 drvp = &chp->ch_drive[drive];
  199                 /* If no drive, skip */
  200                 if ((drvp->drive_flags & DRIVE) == 0)
  201                         continue;
  202                 /* add timing values, setup DMA if needed */
  203                 if (drvp->drive_flags & DRIVE_DMA) {
  204                         idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
  205                         /* use Multiword DMA */
  206                         if (dma_mode == -1 || dma_mode > drvp->DMA_mode)
  207                                 dma_mode = drvp->DMA_mode;
  208                 }
  209                 cy_cmd_ctrl |= (cy_pio_pulse[drvp->PIO_mode] <<
  210                     CY_CMD_CTRL_IOW_PULSE_OFF(drive));
  211                 cy_cmd_ctrl |= (cy_pio_rec[drvp->PIO_mode] <<
  212                     CY_CMD_CTRL_IOW_REC_OFF(drive));
  213                 cy_cmd_ctrl |= (cy_pio_pulse[drvp->PIO_mode] <<
  214                     CY_CMD_CTRL_IOR_PULSE_OFF(drive));
  215                 cy_cmd_ctrl |= (cy_pio_rec[drvp->PIO_mode] <<
  216                     CY_CMD_CTRL_IOR_REC_OFF(drive));
  217         }
  218         pci_conf_write(sc->sc_pc, sc->sc_tag, CY_CMD_CTRL, cy_cmd_ctrl);
  219         chp->ch_drive[0].DMA_mode = dma_mode;
  220         chp->ch_drive[1].DMA_mode = dma_mode;
  221 
  222         if (dma_mode == -1)
  223                 dma_mode = 0;
  224 
  225         if (sc->sc_cy_handle != NULL) {
  226                 /* Note: `multiple' is implied. */
  227                 cy82c693_write(sc->sc_cy_handle,
  228                     (sc->sc_cy_compatchan == 0) ?
  229                     CY_DMA_IDX_PRIMARY : CY_DMA_IDX_SECONDARY, dma_mode);
  230         }
  231 
  232         if (idedma_ctl != 0) {
  233                 /* Add software bits in status register */
  234                 bus_space_write_1(sc->sc_dma_iot, cp->dma_iohs[IDEDMA_CTL], 0,
  235                     idedma_ctl);
  236         }
  237         WDCDEBUG_PRINT(("cy693_chip_map: new timings reg 0x%x\n",
  238             pci_conf_read(sc->sc_pc, sc->sc_tag, CY_CMD_CTRL)), DEBUG_PROBE);
  239 }

Cache object: d4e56f3a4fd31098a9c0dcbc4221154b


[ 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.