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/acardide.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: acardide.c,v 1.8 2004/01/03 22:56:53 thorpej Exp $     */
    2 
    3 /*
    4  * Copyright (c) 2001 Izumi Tsutsui.
    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. The name of the author may not be used to endorse or promote products
   15  *    derived from this software without specific prior written permission.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/param.h>
   30 #include <sys/systm.h>
   31 
   32 #include <dev/pci/pcivar.h>
   33 #include <dev/pci/pcidevs.h>
   34 #include <dev/pci/pciidereg.h>
   35 #include <dev/pci/pciidevar.h>
   36 #include <dev/pci/pciide_acard_reg.h>
   37 
   38 static void acard_chip_map(struct pciide_softc*, struct pci_attach_args*);
   39 static void acard_setup_channel(struct wdc_channel*);
   40 #if 0 /* XXX !! */
   41 static int  acard_pci_intr(void *);
   42 #endif
   43 
   44 static int  acardide_match(struct device *, struct cfdata *, void *);
   45 static void acardide_attach(struct device *, struct device *, void *);
   46 
   47 CFATTACH_DECL(acardide, sizeof(struct pciide_softc),
   48     acardide_match, acardide_attach, NULL, NULL);
   49 
   50 static const struct pciide_product_desc pciide_acard_products[] =  {
   51         { PCI_PRODUCT_ACARD_ATP850U,
   52           0,
   53           "Acard ATP850U Ultra33 IDE Controller",
   54           acard_chip_map,
   55         },
   56         { PCI_PRODUCT_ACARD_ATP860,
   57           0,
   58           "Acard ATP860 Ultra66 IDE Controller",
   59           acard_chip_map,
   60         },
   61         { PCI_PRODUCT_ACARD_ATP860A,
   62           0,
   63           "Acard ATP860-A Ultra66 IDE Controller",
   64           acard_chip_map,
   65         },
   66         { PCI_PRODUCT_ACARD_ATP865,
   67           0,
   68           "Acard ATP865 Ultra100 IDE Controller",
   69           acard_chip_map,
   70         },
   71         { PCI_PRODUCT_ACARD_ATP865A,
   72           0,
   73           "Acard ATP865-A Ultra100 IDE Controller",
   74           acard_chip_map,
   75         },
   76         { 0,
   77           0,
   78           NULL,
   79           NULL
   80         }
   81 };
   82 
   83 static int
   84 acardide_match(struct device *parent, struct cfdata *match, void *aux)
   85 {
   86         struct pci_attach_args *pa = aux;
   87 
   88         if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ACARD) {
   89                 if (pciide_lookup_product(pa->pa_id, pciide_acard_products))
   90                         return (2);
   91         }
   92         return (0);
   93 }
   94 
   95 static void
   96 acardide_attach(struct device *parent, struct device *self, void *aux)
   97 {
   98         struct pci_attach_args *pa = aux;
   99         struct pciide_softc *sc = (struct pciide_softc *)self;
  100 
  101         pciide_common_attach(sc, pa,
  102             pciide_lookup_product(pa->pa_id, pciide_acard_products));
  103 
  104 }
  105 
  106 #define ACARD_IS_850(sc)                                                \
  107         ((sc)->sc_pp->ide_product == PCI_PRODUCT_ACARD_ATP850U)
  108 
  109 static void
  110 acard_chip_map(struct pciide_softc *sc, struct pci_attach_args *pa)
  111 {
  112         struct pciide_channel *cp;
  113         int i;
  114         pcireg_t interface;
  115         bus_size_t cmdsize, ctlsize;
  116 
  117         if (pciide_chipen(sc, pa) == 0)
  118                 return;
  119 
  120         /*
  121          * when the chip is in native mode it identifies itself as a
  122          * 'misc mass storage'. Fake interface in this case.
  123          */
  124         if (PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MASS_STORAGE_IDE) {
  125                 interface = PCI_INTERFACE(pa->pa_class);
  126         } else {
  127                 interface = PCIIDE_INTERFACE_BUS_MASTER_DMA |
  128                     PCIIDE_INTERFACE_PCI(0) | PCIIDE_INTERFACE_PCI(1);
  129         }
  130 
  131         aprint_normal("%s: bus-master DMA support present",
  132             sc->sc_wdcdev.sc_dev.dv_xname);
  133         pciide_mapreg_dma(sc, pa);
  134         aprint_normal("\n");
  135         sc->sc_wdcdev.cap = WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_DATA32 |
  136             WDC_CAPABILITY_MODE;
  137 
  138         if (sc->sc_dma_ok) {
  139                 sc->sc_wdcdev.cap |= WDC_CAPABILITY_DMA | WDC_CAPABILITY_UDMA;
  140                 sc->sc_wdcdev.cap |= WDC_CAPABILITY_IRQACK;
  141                 sc->sc_wdcdev.irqack = pciide_irqack;
  142         }
  143         sc->sc_wdcdev.PIO_cap = 4;
  144         sc->sc_wdcdev.DMA_cap = 2;
  145         switch (sc->sc_pp->ide_product) {
  146         case PCI_PRODUCT_ACARD_ATP860:
  147         case PCI_PRODUCT_ACARD_ATP860A:
  148                 sc->sc_wdcdev.UDMA_cap = 4;
  149                 break;
  150         case PCI_PRODUCT_ACARD_ATP865:
  151         case PCI_PRODUCT_ACARD_ATP865A:
  152                 sc->sc_wdcdev.UDMA_cap = 5;
  153                 break;
  154         default:
  155                 sc->sc_wdcdev.UDMA_cap = 2;
  156                 break;
  157         }
  158 
  159         sc->sc_wdcdev.set_modes = acard_setup_channel;
  160         sc->sc_wdcdev.channels = sc->wdc_chanarray;
  161         sc->sc_wdcdev.nchannels = 2;
  162 
  163         for (i = 0; i < sc->sc_wdcdev.nchannels; i++) {
  164                 cp = &sc->pciide_channels[i];
  165                 if (pciide_chansetup(sc, i, interface) == 0)
  166                         continue;
  167                 pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize,
  168                     pciide_pci_intr);
  169         }
  170         if (!ACARD_IS_850(sc)) {
  171                 u_int32_t reg;
  172                 reg = pci_conf_read(sc->sc_pc, sc->sc_tag, ATP8x0_CTRL);
  173                 reg &= ~ATP860_CTRL_INT;
  174                 pci_conf_write(sc->sc_pc, sc->sc_tag, ATP8x0_CTRL, reg);
  175         }
  176 }
  177 
  178 static void
  179 acard_setup_channel(struct wdc_channel *chp)
  180 {
  181         struct ata_drive_datas *drvp;
  182         struct pciide_channel *cp = (struct pciide_channel*)chp;
  183         struct pciide_softc *sc = (struct pciide_softc *)cp->wdc_channel.ch_wdc;
  184         struct wdc_softc *wdc = &sc->sc_wdcdev;
  185         int channel = chp->ch_channel;
  186         int drive;
  187         u_int32_t idetime, udma_mode;
  188         u_int32_t idedma_ctl;
  189 
  190         /* setup DMA if needed */
  191         pciide_channel_dma_setup(cp);
  192 
  193         if (ACARD_IS_850(sc)) {
  194                 idetime = 0;
  195                 udma_mode = pci_conf_read(sc->sc_pc, sc->sc_tag, ATP850_UDMA);
  196                 udma_mode &= ~ATP850_UDMA_MASK(channel);
  197         } else {
  198                 idetime = pci_conf_read(sc->sc_pc, sc->sc_tag, ATP860_IDETIME);
  199                 idetime &= ~ATP860_SETTIME_MASK(channel);
  200                 udma_mode = pci_conf_read(sc->sc_pc, sc->sc_tag, ATP860_UDMA);
  201                 udma_mode &= ~ATP860_UDMA_MASK(channel);
  202 
  203                 /* check 80 pins cable */
  204                 if ((chp->ch_drive[0].drive_flags & DRIVE_UDMA) ||
  205                     (chp->ch_drive[1].drive_flags & DRIVE_UDMA)) {
  206                         if (pci_conf_read(sc->sc_pc, sc->sc_tag, ATP8x0_CTRL)
  207                             & ATP860_CTRL_80P(chp->ch_channel)) {
  208                                 if (chp->ch_drive[0].UDMA_mode > 2)
  209                                         chp->ch_drive[0].UDMA_mode = 2;
  210                                 if (chp->ch_drive[1].UDMA_mode > 2)
  211                                         chp->ch_drive[1].UDMA_mode = 2;
  212                         }
  213                 }
  214         }
  215 
  216         idedma_ctl = 0;
  217 
  218         /* Per drive settings */
  219         for (drive = 0; drive < 2; drive++) {
  220                 drvp = &chp->ch_drive[drive];
  221                 /* If no drive, skip */
  222                 if ((drvp->drive_flags & DRIVE) == 0)
  223                         continue;
  224                 /* add timing values, setup DMA if needed */
  225                 if ((wdc->cap & WDC_CAPABILITY_UDMA) &&
  226                     (drvp->drive_flags & DRIVE_UDMA)) {
  227                         /* use Ultra/DMA */
  228                         if (ACARD_IS_850(sc)) {
  229                                 idetime |= ATP850_SETTIME(drive,
  230                                     acard_act_udma[drvp->UDMA_mode],
  231                                     acard_rec_udma[drvp->UDMA_mode]);
  232                                 udma_mode |= ATP850_UDMA_MODE(channel, drive,
  233                                     acard_udma_conf[drvp->UDMA_mode]);
  234                         } else {
  235                                 idetime |= ATP860_SETTIME(channel, drive,
  236                                     acard_act_udma[drvp->UDMA_mode],
  237                                     acard_rec_udma[drvp->UDMA_mode]);
  238                                 udma_mode |= ATP860_UDMA_MODE(channel, drive,
  239                                     acard_udma_conf[drvp->UDMA_mode]);
  240                         }
  241                         idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
  242                 } else if ((wdc->cap & WDC_CAPABILITY_DMA) &&
  243                     (drvp->drive_flags & DRIVE_DMA)) {
  244                         /* use Multiword DMA */
  245                         drvp->drive_flags &= ~DRIVE_UDMA;
  246                         if (ACARD_IS_850(sc)) {
  247                                 idetime |= ATP850_SETTIME(drive,
  248                                     acard_act_dma[drvp->DMA_mode],
  249                                     acard_rec_dma[drvp->DMA_mode]);
  250                         } else {
  251                                 idetime |= ATP860_SETTIME(channel, drive,
  252                                     acard_act_dma[drvp->DMA_mode],
  253                                     acard_rec_dma[drvp->DMA_mode]);
  254                         }
  255                         idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
  256                 } else {
  257                         /* PIO only */
  258                         drvp->drive_flags &= ~(DRIVE_UDMA | DRIVE_DMA);
  259                         if (ACARD_IS_850(sc)) {
  260                                 idetime |= ATP850_SETTIME(drive,
  261                                     acard_act_pio[drvp->PIO_mode],
  262                                     acard_rec_pio[drvp->PIO_mode]);
  263                         } else {
  264                                 idetime |= ATP860_SETTIME(channel, drive,
  265                                     acard_act_pio[drvp->PIO_mode],
  266                                     acard_rec_pio[drvp->PIO_mode]);
  267                         }
  268                 pci_conf_write(sc->sc_pc, sc->sc_tag, ATP8x0_CTRL,
  269                     pci_conf_read(sc->sc_pc, sc->sc_tag, ATP8x0_CTRL)
  270                     | ATP8x0_CTRL_EN(channel));
  271                 }
  272         }
  273 
  274         if (idedma_ctl != 0) {
  275                 /* Add software bits in status register */
  276                 bus_space_write_1(sc->sc_dma_iot, cp->dma_iohs[IDEDMA_CTL], 0,
  277                     idedma_ctl);
  278         }
  279 
  280         if (ACARD_IS_850(sc)) {
  281                 pci_conf_write(sc->sc_pc, sc->sc_tag,
  282                     ATP850_IDETIME(channel), idetime);
  283                 pci_conf_write(sc->sc_pc, sc->sc_tag, ATP850_UDMA, udma_mode);
  284         } else {
  285                 pci_conf_write(sc->sc_pc, sc->sc_tag, ATP860_IDETIME, idetime);
  286                 pci_conf_write(sc->sc_pc, sc->sc_tag, ATP860_UDMA, udma_mode);
  287         }
  288 }
  289 
  290 #if 0 /* XXX !! */
  291 static int
  292 acard_pci_intr(void *arg)
  293 {
  294         struct pciide_softc *sc = arg;
  295         struct pciide_channel *cp;
  296         struct wdc_channel *wdc_cp;
  297         int rv = 0;
  298         int dmastat, i, crv;
  299 
  300         for (i = 0; i < sc->sc_wdcdev.nchannels; i++) {
  301                 cp = &sc->pciide_channels[i];
  302                 dmastat = bus_space_read_1(sc->sc_dma_iot,
  303                     cp->dma_iohs[IDEDMA_CTL], 0);
  304                 if ((dmastat & IDEDMA_CTL_INTR) == 0)
  305                         continue;
  306                 wdc_cp = &cp->wdc_channel;
  307                 if ((wdc_cp->ch_flags & WDCF_IRQ_WAIT) == 0) {
  308                         (void)wdcintr(wdc_cp);
  309                         bus_space_write_1(sc->sc_dma_iot,
  310                             cp->dma_iohs[IDEDMA_CTL], 0, dmastat);
  311                         continue;
  312                 }
  313                 crv = wdcintr(wdc_cp);
  314                 if (crv == 0)
  315                         printf("%s:%d: bogus intr\n",
  316                             sc->sc_wdcdev.sc_dev.dv_xname, i);
  317                 else if (crv == 1)
  318                         rv = 1;
  319                 else if (rv == 0)
  320                         rv = crv;
  321         }
  322         return rv;
  323 }
  324 #endif

Cache object: d614ecf6b2d6742db7cf134f5a8e6ae7


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