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/hptide.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: hptide.c,v 1.9.2.1 2004/08/11 19:46:13 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 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 
   35 #include <dev/pci/pcivar.h>
   36 #include <dev/pci/pcidevs.h>
   37 #include <dev/pci/pciidereg.h>
   38 #include <dev/pci/pciidevar.h>
   39 #include <dev/pci/pciide_hpt_reg.h>
   40 
   41 static void hpt_chip_map(struct pciide_softc*, struct pci_attach_args*);
   42 static void hpt_setup_channel(struct wdc_channel*);
   43 static int  hpt_pci_intr(void *);
   44 
   45 static int  hptide_match(struct device *, struct cfdata *, void *);
   46 static void hptide_attach(struct device *, struct device *, void *);
   47 
   48 CFATTACH_DECL(hptide, sizeof(struct pciide_softc),
   49     hptide_match, hptide_attach, NULL, NULL);
   50 
   51 static const struct pciide_product_desc pciide_triones_products[] =  {
   52         { PCI_PRODUCT_TRIONES_HPT302,
   53           0,
   54           NULL,
   55           hpt_chip_map
   56         },
   57         { PCI_PRODUCT_TRIONES_HPT366,
   58           0,
   59           NULL,
   60           hpt_chip_map,
   61         },
   62         { PCI_PRODUCT_TRIONES_HPT371,
   63           0,
   64           NULL,
   65           hpt_chip_map,
   66         },
   67         { PCI_PRODUCT_TRIONES_HPT372A,
   68           0,
   69           NULL,
   70           hpt_chip_map
   71         },
   72         { PCI_PRODUCT_TRIONES_HPT374,
   73           0,
   74           NULL,
   75           hpt_chip_map
   76         },
   77         { 0,
   78           0,
   79           NULL,
   80           NULL
   81         }
   82 };
   83 
   84 static int
   85 hptide_match(struct device *parent, struct cfdata *match, void *aux)
   86 {
   87         struct pci_attach_args *pa = aux;
   88 
   89         if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_TRIONES) {
   90                 if (pciide_lookup_product(pa->pa_id, pciide_triones_products))
   91                         return (2);
   92         }
   93         return (0);
   94 }
   95 
   96 static void
   97 hptide_attach(struct device *parent, struct device *self, void *aux)
   98 {
   99         struct pci_attach_args *pa = aux;
  100         struct pciide_softc *sc = (struct pciide_softc *)self;
  101 
  102         pciide_common_attach(sc, pa,
  103             pciide_lookup_product(pa->pa_id, pciide_triones_products));
  104 
  105 }
  106 
  107 static void
  108 hpt_chip_map(struct pciide_softc *sc, struct pci_attach_args *pa)
  109 {
  110         struct pciide_channel *cp;
  111         int i, compatchan, revision;
  112         pcireg_t interface;
  113         bus_size_t cmdsize, ctlsize;
  114 
  115         if (pciide_chipen(sc, pa) == 0)
  116                 return;
  117 
  118         revision = PCI_REVISION(pa->pa_class);
  119         aprint_normal("%s: Triones/Highpoint ",
  120             sc->sc_wdcdev.sc_dev.dv_xname);
  121         switch (sc->sc_pp->ide_product) {
  122         case PCI_PRODUCT_TRIONES_HPT302:
  123                 aprint_normal("HPT302 IDE Controller\n");
  124                 break;
  125         case PCI_PRODUCT_TRIONES_HPT371:
  126                 aprint_normal("HPT371 IDE Controller\n");
  127                 break;
  128         case PCI_PRODUCT_TRIONES_HPT374:
  129                 aprint_normal("HPT374 IDE Controller\n");
  130                 break;
  131         case PCI_PRODUCT_TRIONES_HPT372A:
  132                 aprint_normal("HPT372A IDE Controller\n");
  133                 break;
  134         case PCI_PRODUCT_TRIONES_HPT366:
  135                 if (revision == HPT372_REV)
  136                         aprint_normal("HPT372 IDE Controller\n");
  137                 else if (revision == HPT370_REV)
  138                         aprint_normal("HPT370 IDE Controller\n");
  139                 else if (revision == HPT370A_REV)
  140                         aprint_normal("HPT370A IDE Controller\n");
  141                 else if (revision == HPT366_REV)
  142                         aprint_normal("HPT366 IDE Controller\n");
  143                 else
  144                         aprint_normal("unknown HPT IDE controller rev %d\n",
  145                             revision);
  146                 break;
  147         default:
  148                 aprint_normal("unknown HPT IDE controller 0x%x\n",
  149                     sc->sc_pp->ide_product);
  150         }
  151 
  152         /* 
  153          * when the chip is in native mode it identifies itself as a
  154          * 'misc mass storage'. Fake interface in this case.
  155          */
  156         if (PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MASS_STORAGE_IDE) {
  157                 interface = PCI_INTERFACE(pa->pa_class);
  158         } else {
  159                 interface = PCIIDE_INTERFACE_BUS_MASTER_DMA |
  160                     PCIIDE_INTERFACE_PCI(0);
  161                 if ((sc->sc_pp->ide_product == PCI_PRODUCT_TRIONES_HPT366 &&
  162                     (revision == HPT370_REV || revision == HPT370A_REV ||
  163                      revision == HPT372_REV)) ||
  164                     sc->sc_pp->ide_product == PCI_PRODUCT_TRIONES_HPT302 ||
  165                     sc->sc_pp->ide_product == PCI_PRODUCT_TRIONES_HPT371 ||
  166                     sc->sc_pp->ide_product == PCI_PRODUCT_TRIONES_HPT372A ||
  167                     sc->sc_pp->ide_product == PCI_PRODUCT_TRIONES_HPT374)
  168                         interface |= PCIIDE_INTERFACE_PCI(1);
  169         }
  170 
  171         aprint_normal("%s: bus-master DMA support present",
  172             sc->sc_wdcdev.sc_dev.dv_xname);
  173         pciide_mapreg_dma(sc, pa);
  174         aprint_normal("\n");
  175         sc->sc_wdcdev.cap = WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_DATA32 |
  176             WDC_CAPABILITY_MODE;
  177         if (sc->sc_dma_ok) {
  178                 sc->sc_wdcdev.cap |= WDC_CAPABILITY_DMA | WDC_CAPABILITY_UDMA;
  179                 sc->sc_wdcdev.cap |= WDC_CAPABILITY_IRQACK;
  180                 sc->sc_wdcdev.irqack = pciide_irqack;
  181         }
  182         sc->sc_wdcdev.PIO_cap = 4;
  183         sc->sc_wdcdev.DMA_cap = 2;
  184 
  185         sc->sc_wdcdev.set_modes = hpt_setup_channel;
  186         sc->sc_wdcdev.channels = sc->wdc_chanarray;
  187         if (sc->sc_pp->ide_product == PCI_PRODUCT_TRIONES_HPT366 &&
  188             revision == HPT366_REV) {
  189                 sc->sc_wdcdev.nchannels = 1;
  190                 sc->sc_wdcdev.UDMA_cap = 4;
  191         } else {
  192                 sc->sc_wdcdev.nchannels = 2;
  193                 if (sc->sc_pp->ide_product == PCI_PRODUCT_TRIONES_HPT374 ||
  194                     sc->sc_pp->ide_product == PCI_PRODUCT_TRIONES_HPT372A ||
  195                     sc->sc_pp->ide_product == PCI_PRODUCT_TRIONES_HPT371 ||
  196                     sc->sc_pp->ide_product == PCI_PRODUCT_TRIONES_HPT302 ||
  197                     (sc->sc_pp->ide_product == PCI_PRODUCT_TRIONES_HPT366 &&
  198                     revision == HPT372_REV))
  199                         sc->sc_wdcdev.UDMA_cap = 6;
  200                 else
  201                         sc->sc_wdcdev.UDMA_cap = 5;
  202         }
  203         for (i = 0; i < sc->sc_wdcdev.nchannels; i++) {
  204                 cp = &sc->pciide_channels[i];
  205                 if (sc->sc_wdcdev.nchannels > 1) {
  206                         compatchan = i;
  207                         if((pciide_pci_read(sc->sc_pc, sc->sc_tag,
  208                            HPT370_CTRL1(i)) & HPT370_CTRL1_EN) == 0) {
  209                                 aprint_normal(
  210                                     "%s: %s channel ignored (disabled)\n",
  211                                     sc->sc_wdcdev.sc_dev.dv_xname, cp->name);
  212                                 cp->wdc_channel.ch_flags |= WDCF_DISABLED;
  213                                 continue;
  214                         }
  215                 } else {
  216                         /*
  217                          * The 366 has 2 PCI IDE functions, one for primary and
  218                          * one for secondary. So we need to call
  219                          * pciide_mapregs_compat() with the real channel.
  220                          */
  221                         if (pa->pa_function == 0)
  222                                 compatchan = 0;
  223                         else if (pa->pa_function == 1)
  224                                 compatchan = 1;
  225                         else {
  226                                 aprint_error("%s: unexpected PCI function %d\n",
  227                                     sc->sc_wdcdev.sc_dev.dv_xname, pa->pa_function);
  228                                 return;
  229                         }
  230                 }
  231                 if (pciide_chansetup(sc, i, interface) == 0)
  232                         continue;
  233                 if (interface & PCIIDE_INTERFACE_PCI(i)) {
  234                         pciide_mapregs_native(pa, cp, &cmdsize,
  235                             &ctlsize, hpt_pci_intr);
  236                 } else {
  237                         pciide_mapregs_compat(pa, cp, compatchan,
  238                             &cmdsize, &ctlsize);
  239                         if ((cp->wdc_channel.ch_flags & WDCF_DISABLED) == 0)
  240                                 pciide_map_compat_intr(pa, cp,
  241                                     sc->sc_cy_compatchan);
  242                 }
  243                 wdcattach(&cp->wdc_channel);
  244         }
  245         if ((sc->sc_pp->ide_product == PCI_PRODUCT_TRIONES_HPT366 &&
  246             (revision == HPT370_REV || revision == HPT370A_REV ||
  247              revision == HPT372_REV)) || 
  248             sc->sc_pp->ide_product == PCI_PRODUCT_TRIONES_HPT302 ||
  249             sc->sc_pp->ide_product == PCI_PRODUCT_TRIONES_HPT371 ||
  250             sc->sc_pp->ide_product == PCI_PRODUCT_TRIONES_HPT372A ||
  251             sc->sc_pp->ide_product == PCI_PRODUCT_TRIONES_HPT374) {
  252                 /*
  253                  * HPT370_REV and highter has a bit to disable interrupts,
  254                  * make sure to clear it
  255                  */
  256                 pciide_pci_write(sc->sc_pc, sc->sc_tag, HPT_CSEL,
  257                     pciide_pci_read(sc->sc_pc, sc->sc_tag, HPT_CSEL) &
  258                     ~HPT_CSEL_IRQDIS);
  259         }
  260         /* set clocks, etc (mandatory on 372/4, optional otherwise) */
  261         if ((sc->sc_pp->ide_product == PCI_PRODUCT_TRIONES_HPT366 &&
  262              revision == HPT372_REV ) ||
  263             sc->sc_pp->ide_product == PCI_PRODUCT_TRIONES_HPT302 ||
  264             sc->sc_pp->ide_product == PCI_PRODUCT_TRIONES_HPT371 ||
  265             sc->sc_pp->ide_product == PCI_PRODUCT_TRIONES_HPT372A ||
  266             sc->sc_pp->ide_product == PCI_PRODUCT_TRIONES_HPT374)
  267                 pciide_pci_write(sc->sc_pc, sc->sc_tag, HPT_SC2,
  268                     (pciide_pci_read(sc->sc_pc, sc->sc_tag, HPT_SC2) &
  269                      HPT_SC2_MAEN) | HPT_SC2_OSC_EN);
  270         return;
  271 }
  272 
  273 static void
  274 hpt_setup_channel(struct wdc_channel *chp)
  275 {
  276         struct ata_drive_datas *drvp;
  277         int drive;
  278         int cable;
  279         u_int32_t before, after;
  280         u_int32_t idedma_ctl;
  281         struct pciide_channel *cp = (struct pciide_channel*)chp;
  282         struct pciide_softc *sc = (struct pciide_softc *)cp->wdc_channel.ch_wdc;
  283         int revision =
  284              PCI_REVISION(pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_CLASS_REG));
  285         const u_int32_t *tim_pio, *tim_dma, *tim_udma;
  286 
  287         cable = pciide_pci_read(sc->sc_pc, sc->sc_tag, HPT_CSEL);
  288 
  289         /* setup DMA if needed */
  290         pciide_channel_dma_setup(cp);
  291 
  292         idedma_ctl = 0;
  293 
  294         /* select the timing arrays for the chip */
  295         switch (sc->sc_pp->ide_product) {
  296         case PCI_PRODUCT_TRIONES_HPT374:
  297                 tim_udma = hpt374_udma;
  298                 tim_dma = hpt374_dma;
  299                 tim_pio = hpt374_pio;
  300                 break;
  301         case PCI_PRODUCT_TRIONES_HPT302:
  302         case PCI_PRODUCT_TRIONES_HPT371:
  303         case PCI_PRODUCT_TRIONES_HPT372A:
  304                 tim_udma = hpt372_udma;
  305                 tim_dma = hpt372_dma;
  306                 tim_pio = hpt372_pio;
  307                 break;
  308         case PCI_PRODUCT_TRIONES_HPT366:
  309         default:
  310                 switch (revision) {
  311                 case HPT372_REV:
  312                         tim_udma = hpt372_udma;
  313                         tim_dma = hpt372_dma;
  314                         tim_pio = hpt372_pio;
  315                         break;
  316                 case HPT370_REV:
  317                 case HPT370A_REV:
  318                         tim_udma = hpt370_udma;
  319                         tim_dma = hpt370_dma;
  320                         tim_pio = hpt370_pio;
  321                         break;
  322                 case HPT366_REV:
  323                 default:
  324                         tim_udma = hpt366_udma;
  325                         tim_dma = hpt366_dma;
  326                         tim_pio = hpt366_pio;
  327                         break;
  328                 }
  329         }
  330 
  331         /* Per drive settings */
  332         for (drive = 0; drive < 2; drive++) {
  333                 drvp = &chp->ch_drive[drive];
  334                 /* If no drive, skip */
  335                 if ((drvp->drive_flags & DRIVE) == 0)
  336                         continue;
  337                 before = pci_conf_read(sc->sc_pc, sc->sc_tag,
  338                                         HPT_IDETIM(chp->ch_channel, drive));
  339 
  340                 /* add timing values, setup DMA if needed */
  341                 if (drvp->drive_flags & DRIVE_UDMA) {
  342                         /* use Ultra/DMA */
  343                         drvp->drive_flags &= ~DRIVE_DMA;
  344                         if ((cable & HPT_CSEL_CBLID(chp->ch_channel)) != 0 &&
  345                             drvp->UDMA_mode > 2)
  346                                 drvp->UDMA_mode = 2;
  347                         after = tim_udma[drvp->UDMA_mode];
  348                         idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
  349                 } else if (drvp->drive_flags & DRIVE_DMA) {
  350                         /*
  351                          * use Multiword DMA.
  352                          * Timings will be used for both PIO and DMA, so adjust
  353                          * DMA mode if needed
  354                          */
  355                         if (drvp->PIO_mode >= 3 &&
  356                             (drvp->DMA_mode + 2) > drvp->PIO_mode) {
  357                                 drvp->DMA_mode = drvp->PIO_mode - 2;
  358                         }
  359                         after = tim_dma[drvp->DMA_mode];
  360                         idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
  361                 } else {
  362                         /* PIO only */
  363                         after = tim_pio[drvp->PIO_mode];
  364                 }
  365                 pci_conf_write(sc->sc_pc, sc->sc_tag,
  366                     HPT_IDETIM(chp->ch_channel, drive), after);
  367                 WDCDEBUG_PRINT(("%s: bus speed register set to 0x%08x "
  368                     "(BIOS 0x%08x)\n", drvp->drv_softc->dv_xname,
  369                     after, before), DEBUG_PROBE);
  370         }
  371         if (idedma_ctl != 0) {
  372                 /* Add software bits in status register */
  373                 bus_space_write_1(sc->sc_dma_iot, cp->dma_iohs[IDEDMA_CTL], 0,
  374                     idedma_ctl);
  375         }
  376 }
  377 
  378 static int
  379 hpt_pci_intr(void *arg)
  380 {
  381         struct pciide_softc *sc = arg;
  382         struct pciide_channel *cp;
  383         struct wdc_channel *wdc_cp;
  384         int rv = 0;
  385         int dmastat, i, crv;
  386 
  387         for (i = 0; i < sc->sc_wdcdev.nchannels; i++) {
  388                 cp = &sc->pciide_channels[i];
  389                 dmastat = bus_space_read_1(sc->sc_dma_iot,
  390                     cp->dma_iohs[IDEDMA_CTL], 0);
  391                 if((dmastat & ( IDEDMA_CTL_ACT | IDEDMA_CTL_INTR)) !=
  392                     IDEDMA_CTL_INTR)
  393                         continue;
  394                 wdc_cp = &cp->wdc_channel;
  395                 crv = wdcintr(wdc_cp);
  396                 if (crv == 0) {
  397                         printf("%s:%d: bogus intr\n",
  398                             sc->sc_wdcdev.sc_dev.dv_xname, i);
  399                         bus_space_write_1(sc->sc_dma_iot,
  400                             cp->dma_iohs[IDEDMA_CTL], 0, dmastat);
  401                 } else
  402                         rv = 1;
  403         }
  404         return rv;
  405 }

Cache object: a37da4bfe77c5b90aae0505630e1741b


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