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/satalink.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: satalink.c,v 1.12.2.1 2004/05/11 12:33:39 tron Exp $   */
    2 
    3 /*-
    4  * Copyright (c) 2003 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Jason R. Thorpe of Wasabi Systems, Inc.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *      This product includes software developed by the NetBSD
   21  *      Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 #include <sys/param.h>
   40 #include <sys/systm.h>
   41 #include <sys/malloc.h>
   42 
   43 #include <dev/pci/pcivar.h>
   44 #include <dev/pci/pcidevs.h>
   45 #include <dev/pci/pciidereg.h>
   46 #include <dev/pci/pciidevar.h>
   47 #include <dev/pci/pciide_sii3112_reg.h>
   48 
   49 #include <dev/ata/satareg.h>
   50 #include <dev/ata/atareg.h>
   51 
   52 /*
   53  * Register map for BA5 register space, indexed by channel.
   54  */
   55 static const struct {
   56         bus_addr_t      ba5_IDEDMA_CMD;
   57         bus_addr_t      ba5_IDEDMA_CTL;
   58         bus_addr_t      ba5_IDEDMA_TBL;
   59         bus_addr_t      ba5_IDEDMA_CMD2;
   60         bus_addr_t      ba5_IDEDMA_CTL2;
   61         bus_addr_t      ba5_IDE_TF0;
   62         bus_addr_t      ba5_IDE_TF1;
   63         bus_addr_t      ba5_IDE_TF2;
   64         bus_addr_t      ba5_IDE_TF3;
   65         bus_addr_t      ba5_IDE_TF4;
   66         bus_addr_t      ba5_IDE_TF5;
   67         bus_addr_t      ba5_IDE_TF6;
   68         bus_addr_t      ba5_IDE_TF7;
   69         bus_addr_t      ba5_IDE_TF8;
   70         bus_addr_t      ba5_IDE_RAD;
   71         bus_addr_t      ba5_IDE_TF9;
   72         bus_addr_t      ba5_IDE_TF10;
   73         bus_addr_t      ba5_IDE_TF11;
   74         bus_addr_t      ba5_IDE_TF12;
   75         bus_addr_t      ba5_IDE_TF13;
   76         bus_addr_t      ba5_IDE_TF14;
   77         bus_addr_t      ba5_IDE_TF15;
   78         bus_addr_t      ba5_IDE_TF16;
   79         bus_addr_t      ba5_IDE_TF17;
   80         bus_addr_t      ba5_IDE_TF18;
   81         bus_addr_t      ba5_IDE_TF19;
   82         bus_addr_t      ba5_IDE_RABC;
   83         bus_addr_t      ba5_IDE_CMD_STS;
   84         bus_addr_t      ba5_IDE_CFG_STS;
   85         bus_addr_t      ba5_IDE_DTM;
   86         bus_addr_t      ba5_SControl;
   87         bus_addr_t      ba5_SStatus;
   88         bus_addr_t      ba5_SError;
   89         bus_addr_t      ba5_SActive;            /* 3114 */
   90         bus_addr_t      ba5_SMisc;
   91         bus_addr_t      ba5_PHY_CONFIG;
   92         bus_addr_t      ba5_SIEN;
   93         bus_addr_t      ba5_SFISCfg;
   94 } satalink_ba5_regmap[] = {
   95         {       /* Channel 0 */
   96                 .ba5_IDEDMA_CMD         =       0x000,
   97                 .ba5_IDEDMA_CTL         =       0x002,
   98                 .ba5_IDEDMA_TBL         =       0x004,
   99                 .ba5_IDEDMA_CMD2        =       0x010,
  100                 .ba5_IDEDMA_CTL2        =       0x012,
  101                 .ba5_IDE_TF0            =       0x080,  /* wd_data */
  102                 .ba5_IDE_TF1            =       0x081,  /* wd_error */
  103                 .ba5_IDE_TF2            =       0x082,  /* wd_seccnt */
  104                 .ba5_IDE_TF3            =       0x083,  /* wd_sector */
  105                 .ba5_IDE_TF4            =       0x084,  /* wd_cyl_lo */
  106                 .ba5_IDE_TF5            =       0x085,  /* wd_cyl_hi */
  107                 .ba5_IDE_TF6            =       0x086,  /* wd_sdh */
  108                 .ba5_IDE_TF7            =       0x087,  /* wd_command */
  109                 .ba5_IDE_TF8            =       0x08a,  /* wd_altsts */
  110                 .ba5_IDE_RAD            =       0x08c,
  111                 .ba5_IDE_TF9            =       0x091,  /* Features 2 */
  112                 .ba5_IDE_TF10           =       0x092,  /* Sector Count 2 */
  113                 .ba5_IDE_TF11           =       0x093,  /* Start Sector 2 */
  114                 .ba5_IDE_TF12           =       0x094,  /* Cylinder Low 2 */
  115                 .ba5_IDE_TF13           =       0x095,  /* Cylinder High 2 */
  116                 .ba5_IDE_TF14           =       0x096,  /* Device/Head 2 */
  117                 .ba5_IDE_TF15           =       0x097,  /* Cmd Sts 2 */
  118                 .ba5_IDE_TF16           =       0x098,  /* Sector Count 2 ext */
  119                 .ba5_IDE_TF17           =       0x099,  /* Start Sector 2 ext */
  120                 .ba5_IDE_TF18           =       0x09a,  /* Cyl Low 2 ext */
  121                 .ba5_IDE_TF19           =       0x09b,  /* Cyl High 2 ext */
  122                 .ba5_IDE_RABC           =       0x09c,
  123                 .ba5_IDE_CMD_STS        =       0x0a0,
  124                 .ba5_IDE_CFG_STS        =       0x0a1,
  125                 .ba5_IDE_DTM            =       0x0b4,
  126                 .ba5_SControl           =       0x100,
  127                 .ba5_SStatus            =       0x104,
  128                 .ba5_SError             =       0x108,
  129                 .ba5_SActive            =       0x10c,
  130                 .ba5_SMisc              =       0x140,
  131                 .ba5_PHY_CONFIG         =       0x144,
  132                 .ba5_SIEN               =       0x148,
  133                 .ba5_SFISCfg            =       0x14c,
  134         },
  135         {       /* Channel 1 */
  136                 .ba5_IDEDMA_CMD         =       0x008,
  137                 .ba5_IDEDMA_CTL         =       0x00a,
  138                 .ba5_IDEDMA_TBL         =       0x00c,
  139                 .ba5_IDEDMA_CMD2        =       0x018,
  140                 .ba5_IDEDMA_CTL2        =       0x01a,
  141                 .ba5_IDE_TF0            =       0x0c0,  /* wd_data */
  142                 .ba5_IDE_TF1            =       0x0c1,  /* wd_error */
  143                 .ba5_IDE_TF2            =       0x0c2,  /* wd_seccnt */
  144                 .ba5_IDE_TF3            =       0x0c3,  /* wd_sector */
  145                 .ba5_IDE_TF4            =       0x0c4,  /* wd_cyl_lo */
  146                 .ba5_IDE_TF5            =       0x0c5,  /* wd_cyl_hi */
  147                 .ba5_IDE_TF6            =       0x0c6,  /* wd_sdh */
  148                 .ba5_IDE_TF7            =       0x0c7,  /* wd_command */
  149                 .ba5_IDE_TF8            =       0x0ca,  /* wd_altsts */
  150                 .ba5_IDE_RAD            =       0x0cc,
  151                 .ba5_IDE_TF9            =       0x0d1,  /* Features 2 */
  152                 .ba5_IDE_TF10           =       0x0d2,  /* Sector Count 2 */
  153                 .ba5_IDE_TF11           =       0x0d3,  /* Start Sector 2 */
  154                 .ba5_IDE_TF12           =       0x0d4,  /* Cylinder Low 2 */
  155                 .ba5_IDE_TF13           =       0x0d5,  /* Cylinder High 2 */
  156                 .ba5_IDE_TF14           =       0x0d6,  /* Device/Head 2 */
  157                 .ba5_IDE_TF15           =       0x0d7,  /* Cmd Sts 2 */
  158                 .ba5_IDE_TF16           =       0x0d8,  /* Sector Count 2 ext */
  159                 .ba5_IDE_TF17           =       0x0d9,  /* Start Sector 2 ext */
  160                 .ba5_IDE_TF18           =       0x0da,  /* Cyl Low 2 ext */
  161                 .ba5_IDE_TF19           =       0x0db,  /* Cyl High 2 ext */
  162                 .ba5_IDE_RABC           =       0x0dc,
  163                 .ba5_IDE_CMD_STS        =       0x0e0,
  164                 .ba5_IDE_CFG_STS        =       0x0e1,
  165                 .ba5_IDE_DTM            =       0x0f4,
  166                 .ba5_SControl           =       0x180,
  167                 .ba5_SStatus            =       0x184,
  168                 .ba5_SError             =       0x188,
  169                 .ba5_SActive            =       0x18c,
  170                 .ba5_SMisc              =       0x1c0,
  171                 .ba5_PHY_CONFIG         =       0x1c4,
  172                 .ba5_SIEN               =       0x1c8,
  173                 .ba5_SFISCfg            =       0x1cc,
  174         },
  175         {       /* Channel 2 (3114) */
  176                 .ba5_IDEDMA_CMD         =       0x200,
  177                 .ba5_IDEDMA_CTL         =       0x202,
  178                 .ba5_IDEDMA_TBL         =       0x204,
  179                 .ba5_IDEDMA_CMD2        =       0x210,
  180                 .ba5_IDEDMA_CTL2        =       0x212,
  181                 .ba5_IDE_TF0            =       0x280,  /* wd_data */
  182                 .ba5_IDE_TF1            =       0x281,  /* wd_error */
  183                 .ba5_IDE_TF2            =       0x282,  /* wd_seccnt */
  184                 .ba5_IDE_TF3            =       0x283,  /* wd_sector */
  185                 .ba5_IDE_TF4            =       0x284,  /* wd_cyl_lo */
  186                 .ba5_IDE_TF5            =       0x285,  /* wd_cyl_hi */
  187                 .ba5_IDE_TF6            =       0x286,  /* wd_sdh */
  188                 .ba5_IDE_TF7            =       0x287,  /* wd_command */
  189                 .ba5_IDE_TF8            =       0x28a,  /* wd_altsts */
  190                 .ba5_IDE_RAD            =       0x28c,
  191                 .ba5_IDE_TF9            =       0x291,  /* Features 2 */
  192                 .ba5_IDE_TF10           =       0x292,  /* Sector Count 2 */
  193                 .ba5_IDE_TF11           =       0x293,  /* Start Sector 2 */
  194                 .ba5_IDE_TF12           =       0x294,  /* Cylinder Low 2 */
  195                 .ba5_IDE_TF13           =       0x295,  /* Cylinder High 2 */
  196                 .ba5_IDE_TF14           =       0x296,  /* Device/Head 2 */
  197                 .ba5_IDE_TF15           =       0x297,  /* Cmd Sts 2 */
  198                 .ba5_IDE_TF16           =       0x298,  /* Sector Count 2 ext */
  199                 .ba5_IDE_TF17           =       0x299,  /* Start Sector 2 ext */
  200                 .ba5_IDE_TF18           =       0x29a,  /* Cyl Low 2 ext */
  201                 .ba5_IDE_TF19           =       0x29b,  /* Cyl High 2 ext */
  202                 .ba5_IDE_RABC           =       0x29c,
  203                 .ba5_IDE_CMD_STS        =       0x2a0,
  204                 .ba5_IDE_CFG_STS        =       0x2a1,
  205                 .ba5_IDE_DTM            =       0x2b4,
  206                 .ba5_SControl           =       0x300,
  207                 .ba5_SStatus            =       0x304,
  208                 .ba5_SError             =       0x308,
  209                 .ba5_SActive            =       0x30c,
  210                 .ba5_SMisc              =       0x340,
  211                 .ba5_PHY_CONFIG         =       0x344,
  212                 .ba5_SIEN               =       0x348,
  213                 .ba5_SFISCfg            =       0x34c,
  214         },
  215         {       /* Channel 3 (3114) */
  216                 .ba5_IDEDMA_CMD         =       0x208,
  217                 .ba5_IDEDMA_CTL         =       0x20a,
  218                 .ba5_IDEDMA_TBL         =       0x20c,
  219                 .ba5_IDEDMA_CMD2        =       0x218,
  220                 .ba5_IDEDMA_CTL2        =       0x21a,
  221                 .ba5_IDE_TF0            =       0x2c0,  /* wd_data */
  222                 .ba5_IDE_TF1            =       0x2c1,  /* wd_error */
  223                 .ba5_IDE_TF2            =       0x2c2,  /* wd_seccnt */
  224                 .ba5_IDE_TF3            =       0x2c3,  /* wd_sector */
  225                 .ba5_IDE_TF4            =       0x2c4,  /* wd_cyl_lo */
  226                 .ba5_IDE_TF5            =       0x2c5,  /* wd_cyl_hi */
  227                 .ba5_IDE_TF6            =       0x2c6,  /* wd_sdh */
  228                 .ba5_IDE_TF7            =       0x2c7,  /* wd_command */
  229                 .ba5_IDE_TF8            =       0x2ca,  /* wd_altsts */
  230                 .ba5_IDE_RAD            =       0x2cc,
  231                 .ba5_IDE_TF9            =       0x2d1,  /* Features 2 */
  232                 .ba5_IDE_TF10           =       0x2d2,  /* Sector Count 2 */
  233                 .ba5_IDE_TF11           =       0x2d3,  /* Start Sector 2 */
  234                 .ba5_IDE_TF12           =       0x2d4,  /* Cylinder Low 2 */
  235                 .ba5_IDE_TF13           =       0x2d5,  /* Cylinder High 2 */
  236                 .ba5_IDE_TF14           =       0x2d6,  /* Device/Head 2 */
  237                 .ba5_IDE_TF15           =       0x2d7,  /* Cmd Sts 2 */
  238                 .ba5_IDE_TF16           =       0x2d8,  /* Sector Count 2 ext */
  239                 .ba5_IDE_TF17           =       0x2d9,  /* Start Sector 2 ext */
  240                 .ba5_IDE_TF18           =       0x2da,  /* Cyl Low 2 ext */
  241                 .ba5_IDE_TF19           =       0x2db,  /* Cyl High 2 ext */
  242                 .ba5_IDE_RABC           =       0x2dc,
  243                 .ba5_IDE_CMD_STS        =       0x2e0,
  244                 .ba5_IDE_CFG_STS        =       0x2e1,
  245                 .ba5_IDE_DTM            =       0x2f4,
  246                 .ba5_SControl           =       0x380,
  247                 .ba5_SStatus            =       0x384,
  248                 .ba5_SError             =       0x388,
  249                 .ba5_SActive            =       0x38c,
  250                 .ba5_SMisc              =       0x3c0,
  251                 .ba5_PHY_CONFIG         =       0x3c4,
  252                 .ba5_SIEN               =       0x3c8,
  253                 .ba5_SFISCfg            =       0x3cc,
  254         },
  255 };
  256 
  257 #define ba5_SIS         0x214           /* summary interrupt status */
  258 
  259 /* Interrupt steering bit in BA5[0x200]. */
  260 #define IDEDMA_CMD_INT_STEER    (1U << 1)
  261 
  262 static int  satalink_match(struct device *, struct cfdata *, void *);
  263 static void satalink_attach(struct device *, struct device *, void *);
  264 
  265 CFATTACH_DECL(satalink, sizeof(struct pciide_softc),
  266     satalink_match, satalink_attach, NULL, NULL);
  267 
  268 static void sii3112_chip_map(struct pciide_softc*, struct pci_attach_args*);
  269 static void sii3114_chip_map(struct pciide_softc*, struct pci_attach_args*);
  270 static void sii3112_drv_probe(struct wdc_channel*);
  271 static void sii3112_setup_channel(struct wdc_channel*);
  272 
  273 static const struct pciide_product_desc pciide_satalink_products[] =  {
  274         { PCI_PRODUCT_CMDTECH_3112,
  275           0,
  276           "Silicon Image SATALink 3112",
  277           sii3112_chip_map,
  278         },
  279         { PCI_PRODUCT_CMDTECH_3512,
  280           0,
  281           "Silicon Image SATALink 3512",
  282           sii3112_chip_map,
  283         },
  284         { PCI_PRODUCT_CMDTECH_3114,
  285           0,
  286           "Silicon Image SATALink 3114",
  287           sii3114_chip_map,
  288         },
  289         { 0,
  290           0,
  291           NULL,
  292           NULL
  293         }
  294 };
  295 
  296 static int
  297 satalink_match(struct device *parent, struct cfdata *match, void *aux)
  298 {
  299         struct pci_attach_args *pa = aux;
  300 
  301         if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_CMDTECH) {
  302                 if (pciide_lookup_product(pa->pa_id, pciide_satalink_products))
  303                         return (2);
  304         }
  305         return (0);
  306 }
  307 
  308 static void
  309 satalink_attach(struct device *parent, struct device *self, void *aux)
  310 {
  311         struct pci_attach_args *pa = aux;
  312         struct pciide_softc *sc = (struct pciide_softc *)self;
  313 
  314         pciide_common_attach(sc, pa,
  315             pciide_lookup_product(pa->pa_id, pciide_satalink_products));
  316 
  317 }
  318 
  319 static __inline uint32_t
  320 ba5_read_4_ind(struct pciide_softc *sc, bus_addr_t reg)
  321 {
  322         uint32_t rv;
  323         int s;
  324 
  325         s = splbio();
  326         pci_conf_write(sc->sc_pc, sc->sc_tag, SII3112_BA5_IND_ADDR, reg);
  327         rv = pci_conf_read(sc->sc_pc, sc->sc_tag, SII3112_BA5_IND_DATA);
  328         splx(s);
  329 
  330         return (rv);
  331 }
  332 
  333 static __inline uint32_t
  334 ba5_read_4(struct pciide_softc *sc, bus_addr_t reg)
  335 {
  336 
  337         if (__predict_true(sc->sc_ba5_en != 0))
  338                 return (bus_space_read_4(sc->sc_ba5_st, sc->sc_ba5_sh, reg));
  339 
  340         return (ba5_read_4_ind(sc, reg));
  341 }
  342 
  343 #define BA5_READ_4(sc, chan, reg)                                       \
  344         ba5_read_4((sc), satalink_ba5_regmap[(chan)].reg)
  345 
  346 static __inline void
  347 ba5_write_4_ind(struct pciide_softc *sc, bus_addr_t reg, uint32_t val)
  348 {
  349         int s;
  350 
  351         s = splbio();
  352         pci_conf_write(sc->sc_pc, sc->sc_tag, SII3112_BA5_IND_ADDR, reg);
  353         pci_conf_write(sc->sc_pc, sc->sc_tag, SII3112_BA5_IND_DATA, val);
  354         splx(s);
  355 }
  356 
  357 static __inline void
  358 ba5_write_4(struct pciide_softc *sc, bus_addr_t reg, uint32_t val)
  359 {
  360 
  361         if (__predict_true(sc->sc_ba5_en != 0))
  362                 bus_space_write_4(sc->sc_ba5_st, sc->sc_ba5_sh, reg, val);
  363         else
  364                 ba5_write_4_ind(sc, reg, val);
  365 }
  366 
  367 #define BA5_WRITE_4(sc, chan, reg, val)                                 \
  368         ba5_write_4((sc), satalink_ba5_regmap[(chan)].reg, (val))
  369 
  370 static void
  371 sii3112_chip_map(struct pciide_softc *sc, struct pci_attach_args *pa)
  372 {
  373         struct pciide_channel *cp;
  374         bus_size_t cmdsize, ctlsize;
  375         pcireg_t interface, scs_cmd, cfgctl;
  376         int channel;
  377 
  378         if (pciide_chipen(sc, pa) == 0)
  379                 return;
  380 
  381 #define SII3112_RESET_BITS                                              \
  382         (SCS_CMD_PBM_RESET | SCS_CMD_ARB_RESET |                        \
  383          SCS_CMD_FF1_RESET | SCS_CMD_FF0_RESET |                        \
  384          SCS_CMD_IDE1_RESET | SCS_CMD_IDE0_RESET)
  385 
  386         /*
  387          * Reset everything and then unblock all of the interrupts.
  388          */
  389         scs_cmd = pci_conf_read(pa->pa_pc, pa->pa_tag, SII3112_SCS_CMD);
  390         pci_conf_write(pa->pa_pc, pa->pa_tag, SII3112_SCS_CMD,
  391                        scs_cmd | SII3112_RESET_BITS);
  392         delay(50 * 1000);
  393         pci_conf_write(pa->pa_pc, pa->pa_tag, SII3112_SCS_CMD,
  394                        scs_cmd & SCS_CMD_BA5_EN);
  395         delay(50 * 1000);
  396 
  397         if (scs_cmd & SCS_CMD_BA5_EN) {
  398                 aprint_verbose("%s: SATALink BA5 register space enabled\n",
  399                     sc->sc_wdcdev.sc_dev.dv_xname);
  400                 if (pci_mapreg_map(pa, PCI_MAPREG_START + 0x14,
  401                                    PCI_MAPREG_TYPE_MEM|
  402                                    PCI_MAPREG_MEM_TYPE_32BIT, 0,
  403                                    &sc->sc_ba5_st, &sc->sc_ba5_sh,
  404                                    NULL, NULL) != 0)
  405                         aprint_error("%s: unable to map SATALink BA5 "
  406                             "register space\n", sc->sc_wdcdev.sc_dev.dv_xname);
  407                 else
  408                         sc->sc_ba5_en = 1;
  409         } else {
  410                 aprint_verbose("%s: SATALink BA5 register space disabled\n",
  411                     sc->sc_wdcdev.sc_dev.dv_xname);
  412 
  413                 cfgctl = pci_conf_read(pa->pa_pc, pa->pa_tag,
  414                                        SII3112_PCI_CFGCTL);
  415                 pci_conf_write(pa->pa_pc, pa->pa_tag, SII3112_PCI_CFGCTL,
  416                                cfgctl | CFGCTL_BA5INDEN);
  417         }
  418 
  419         aprint_normal("%s: bus-master DMA support present",
  420             sc->sc_wdcdev.sc_dev.dv_xname);
  421         pciide_mapreg_dma(sc, pa);
  422         aprint_normal("\n");
  423 
  424         /*
  425          * Rev. <= 0x01 of the 3112 have a bug that can cause data
  426          * corruption if DMA transfers cross an 8K boundary.  This is
  427          * apparently hard to tickle, but we'll go ahead and play it
  428          * safe.
  429          */
  430         if (PCI_REVISION(pa->pa_class) <= 0x01) {
  431                 sc->sc_dma_maxsegsz = 8192;
  432                 sc->sc_dma_boundary = 8192;
  433         }
  434 
  435         sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_DATA32 |
  436             WDC_CAPABILITY_MODE;
  437         sc->sc_wdcdev.PIO_cap = 4;
  438         if (sc->sc_dma_ok) {
  439                 sc->sc_wdcdev.cap |= WDC_CAPABILITY_DMA | WDC_CAPABILITY_UDMA;
  440                 sc->sc_wdcdev.cap |= WDC_CAPABILITY_IRQACK;
  441                 sc->sc_wdcdev.irqack = pciide_irqack;
  442                 sc->sc_wdcdev.DMA_cap = 2;
  443                 sc->sc_wdcdev.UDMA_cap = 6;
  444         }
  445         sc->sc_wdcdev.set_modes = sii3112_setup_channel;
  446 
  447         /* We can use SControl and SStatus to probe for drives. */
  448         sc->sc_wdcdev.drv_probe = sii3112_drv_probe;
  449 
  450         sc->sc_wdcdev.channels = sc->wdc_chanarray;
  451         sc->sc_wdcdev.nchannels = PCIIDE_NUM_CHANNELS;
  452 
  453         /* 
  454          * The 3112 either identifies itself as a RAID storage device
  455          * or a Misc storage device.  Fake up the interface bits for
  456          * what our driver expects.
  457          */
  458         if (PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MASS_STORAGE_IDE) {
  459                 interface = PCI_INTERFACE(pa->pa_class);
  460         } else {
  461                 interface = PCIIDE_INTERFACE_BUS_MASTER_DMA |
  462                     PCIIDE_INTERFACE_PCI(0) | PCIIDE_INTERFACE_PCI(1);
  463         }
  464 
  465         for (channel = 0; channel < sc->sc_wdcdev.nchannels; channel++) {
  466                 cp = &sc->pciide_channels[channel];
  467                 if (pciide_chansetup(sc, channel, interface) == 0)
  468                         continue;
  469                 pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize,
  470                     pciide_pci_intr);
  471         }
  472 }
  473 
  474 static void
  475 sii3114_mapreg_dma(struct pciide_softc *sc, struct pci_attach_args *pa)
  476 {
  477         struct pciide_channel *pc;
  478         int chan, reg;
  479         bus_size_t size;
  480 
  481         sc->sc_wdcdev.dma_arg = sc;
  482         sc->sc_wdcdev.dma_init = pciide_dma_init;
  483         sc->sc_wdcdev.dma_start = pciide_dma_start;
  484         sc->sc_wdcdev.dma_finish = pciide_dma_finish;
  485 
  486         if (sc->sc_wdcdev.sc_dev.dv_cfdata->cf_flags &
  487             PCIIDE_OPTIONS_NODMA) {
  488                 aprint_normal(
  489                     ", but unused (forced off by config file)");
  490                 sc->sc_dma_ok = 0;
  491                 return;
  492         }
  493 
  494         /*
  495          * Slice off a subregion of BA5 for each of the channel's DMA
  496          * registers.
  497          */
  498 
  499         sc->sc_dma_iot = sc->sc_ba5_st;
  500         for (chan = 0; chan < 4; chan++) {
  501                 pc = &sc->pciide_channels[chan];
  502                 for (reg = 0; reg < IDEDMA_NREGS; reg++) {
  503                         size = 4;
  504                         if (size > (IDEDMA_SCH_OFFSET - reg))
  505                                 size = IDEDMA_SCH_OFFSET - reg;
  506                         if (bus_space_subregion(sc->sc_ba5_st,
  507                             sc->sc_ba5_sh,
  508                             satalink_ba5_regmap[chan].ba5_IDEDMA_CMD + reg,
  509                             size, &pc->dma_iohs[reg]) != 0) {
  510                                 sc->sc_dma_ok = 0;
  511                                 aprint_normal(", but can't subregion offset "
  512                                     "%lu size %lu",
  513                                     (u_long) satalink_ba5_regmap[
  514                                                 chan].ba5_IDEDMA_CMD + reg,
  515                                     (u_long) size);
  516                                 return;
  517                         }
  518                 }
  519         }
  520 
  521         /* DMA registers all set up! */
  522         sc->sc_dmat = pa->pa_dmat;
  523         sc->sc_dma_ok = 1;
  524 }
  525 
  526 static int
  527 sii3114_chansetup(struct pciide_softc *sc, int channel)
  528 {
  529         static const char *channel_names[] = {
  530                 "port 0",
  531                 "port 1",
  532                 "port 2",
  533                 "port 3",
  534         };
  535         struct pciide_channel *cp = &sc->pciide_channels[channel];
  536 
  537         sc->wdc_chanarray[channel] = &cp->wdc_channel;
  538 
  539         /*
  540          * We must always keep the Interrupt Steering bit set in channel 2's
  541          * IDEDMA_CMD register.
  542          */
  543         if (channel == 2)
  544                 cp->idedma_cmd = IDEDMA_CMD_INT_STEER;
  545 
  546         cp->name = channel_names[channel];
  547         cp->wdc_channel.ch_channel = channel;
  548         cp->wdc_channel.ch_wdc = &sc->sc_wdcdev;
  549         cp->wdc_channel.ch_queue =
  550             malloc(sizeof(struct ata_queue), M_DEVBUF, M_NOWAIT);
  551         if (cp->wdc_channel.ch_queue == NULL) {
  552                 aprint_error("%s %s channel: "
  553                     "can't allocate memory for command queue",
  554                     sc->sc_wdcdev.sc_dev.dv_xname, cp->name);
  555                 return (0);
  556         }
  557         return (1);
  558 }
  559 
  560 static void
  561 sii3114_mapchan(struct pciide_channel *cp)
  562 {
  563         struct pciide_softc *sc = (struct pciide_softc *)cp->wdc_channel.ch_wdc;
  564         struct wdc_channel *wdc_cp = &cp->wdc_channel;
  565         int i;
  566 
  567         cp->compat = 0;
  568         cp->ih = sc->sc_pci_ih;
  569 
  570         wdc_cp->cmd_iot = sc->sc_ba5_st;
  571         if (bus_space_subregion(sc->sc_ba5_st, sc->sc_ba5_sh,
  572                         satalink_ba5_regmap[wdc_cp->ch_channel].ba5_IDE_TF0,
  573                         9, &wdc_cp->cmd_baseioh) != 0) {
  574                 aprint_error("%s: couldn't subregion %s cmd base\n",
  575                     sc->sc_wdcdev.sc_dev.dv_xname, cp->name);
  576                 goto bad;
  577         }
  578 
  579         wdc_cp->ctl_iot = sc->sc_ba5_st;
  580         if (bus_space_subregion(sc->sc_ba5_st, sc->sc_ba5_sh,
  581                         satalink_ba5_regmap[wdc_cp->ch_channel].ba5_IDE_TF8,
  582                         1, &cp->ctl_baseioh) != 0) {
  583                 aprint_error("%s: couldn't subregion %s ctl base\n",
  584                     sc->sc_wdcdev.sc_dev.dv_xname, cp->name);
  585                 goto bad;
  586         }
  587         wdc_cp->ctl_ioh = cp->ctl_baseioh;
  588 
  589         for (i = 0; i < WDC_NREG; i++) {
  590                 if (bus_space_subregion(wdc_cp->cmd_iot, wdc_cp->cmd_baseioh,
  591                                         i, i == 0 ? 4 : 1,
  592                                         &wdc_cp->cmd_iohs[i]) != 0) {
  593                         aprint_error("%s: couldn't subregion %s channel "
  594                                      "cmd regs\n",
  595                             sc->sc_wdcdev.sc_dev.dv_xname, cp->name);
  596                         goto bad;
  597                 }
  598         }
  599         wdc_cp->data32iot = wdc_cp->cmd_iot;
  600         wdc_cp->data32ioh = wdc_cp->cmd_iohs[0];
  601         wdcattach(wdc_cp);
  602         return;
  603 
  604  bad:
  605         cp->wdc_channel.ch_flags |= WDCF_DISABLED;
  606 }
  607 
  608 static void
  609 sii3114_chip_map(struct pciide_softc *sc, struct pci_attach_args *pa)
  610 {
  611         struct pciide_channel *cp;
  612         pcireg_t scs_cmd;
  613         pci_intr_handle_t intrhandle;
  614         const char *intrstr;
  615         int channel;
  616 
  617         if (pciide_chipen(sc, pa) == 0)
  618                 return;
  619 
  620 #define SII3114_RESET_BITS                                              \
  621         (SCS_CMD_PBM_RESET | SCS_CMD_ARB_RESET |                        \
  622          SCS_CMD_FF1_RESET | SCS_CMD_FF0_RESET |                        \
  623          SCS_CMD_FF3_RESET | SCS_CMD_FF2_RESET |                        \
  624          SCS_CMD_IDE1_RESET | SCS_CMD_IDE0_RESET |                      \
  625          SCS_CMD_IDE3_RESET | SCS_CMD_IDE2_RESET)
  626 
  627         /*
  628          * Reset everything and then unblock all of the interrupts.
  629          */
  630         scs_cmd = pci_conf_read(pa->pa_pc, pa->pa_tag, SII3112_SCS_CMD);
  631         pci_conf_write(pa->pa_pc, pa->pa_tag, SII3112_SCS_CMD,
  632                        scs_cmd | SII3114_RESET_BITS);
  633         delay(50 * 1000);
  634         pci_conf_write(pa->pa_pc, pa->pa_tag, SII3112_SCS_CMD,
  635                        scs_cmd & SCS_CMD_M66EN);
  636         delay(50 * 1000);
  637 
  638         /*
  639          * On the 3114, the BA5 register space is always enabled.  In
  640          * order to use the 3114 in any sane way, we must use this BA5
  641          * register space, and so we consider it an error if we cannot
  642          * map it.
  643          *
  644          * As a consequence of using BA5, our register mapping is different
  645          * from a normal PCI IDE controller's, and so we are unable to use
  646          * most of the common PCI IDE register mapping functions.
  647          */
  648         if (pci_mapreg_map(pa, PCI_MAPREG_START + 0x14,
  649                            PCI_MAPREG_TYPE_MEM|
  650                            PCI_MAPREG_MEM_TYPE_32BIT, 0,
  651                            &sc->sc_ba5_st, &sc->sc_ba5_sh,
  652                            NULL, NULL) != 0) {
  653                 aprint_error("%s: unable to map SATALink BA5 "
  654                     "register space\n", sc->sc_wdcdev.sc_dev.dv_xname);
  655                 return;
  656         }
  657         sc->sc_ba5_en = 1;
  658 
  659         aprint_verbose("%s: %dMHz PCI bus\n", sc->sc_wdcdev.sc_dev.dv_xname,
  660             (scs_cmd & SCS_CMD_M66EN) ? 66 : 33);
  661 
  662         /*
  663          * Set the Interrupt Steering bit in the IDEDMA_CMD register of
  664          * channel 2.  This is required at all times for proper operation
  665          * when using the BA5 register space (otherwise interrupts from
  666          * all 4 channels won't work).
  667          */
  668         BA5_WRITE_4(sc, 2, ba5_IDEDMA_CMD, IDEDMA_CMD_INT_STEER);
  669 
  670         aprint_normal("%s: bus-master DMA support present",
  671             sc->sc_wdcdev.sc_dev.dv_xname);
  672         sii3114_mapreg_dma(sc, pa);
  673         aprint_normal("\n");
  674 
  675         sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_DATA32 |
  676             WDC_CAPABILITY_MODE;
  677         sc->sc_wdcdev.PIO_cap = 4;
  678         if (sc->sc_dma_ok) {
  679                 sc->sc_wdcdev.cap |= WDC_CAPABILITY_DMA | WDC_CAPABILITY_UDMA;
  680                 sc->sc_wdcdev.cap |= WDC_CAPABILITY_IRQACK;
  681                 sc->sc_wdcdev.irqack = pciide_irqack;
  682                 sc->sc_wdcdev.DMA_cap = 2;
  683                 sc->sc_wdcdev.UDMA_cap = 6;
  684         }
  685         sc->sc_wdcdev.set_modes = sii3112_setup_channel;
  686 
  687         /* We can use SControl and SStatus to probe for drives. */
  688         sc->sc_wdcdev.drv_probe = sii3112_drv_probe;
  689 
  690         sc->sc_wdcdev.channels = sc->wdc_chanarray;
  691         sc->sc_wdcdev.nchannels = 4;
  692 
  693         /* Map and establish the interrupt handler. */
  694         if (pci_intr_map(pa, &intrhandle) != 0) {
  695                 aprint_error("%s: couldn't map native-PCI interrupt\n",
  696                     sc->sc_wdcdev.sc_dev.dv_xname);
  697                 return;
  698         }
  699         intrstr = pci_intr_string(pa->pa_pc, intrhandle);
  700         sc->sc_pci_ih = pci_intr_establish(pa->pa_pc, intrhandle, IPL_BIO,
  701                                            /* XXX */
  702                                            pciide_pci_intr, sc);
  703         if (sc->sc_pci_ih != NULL) {
  704                 aprint_normal("%s: using %s for native-PCI interrupt\n",
  705                               sc->sc_wdcdev.sc_dev.dv_xname,
  706                               intrstr ? intrstr : "unknown interrupt");
  707         } else {
  708                 aprint_error("%s: couldn't establish native-PCI interrupt",
  709                              sc->sc_wdcdev.sc_dev.dv_xname);
  710                 if (intrstr != NULL)
  711                         aprint_normal(" at %s", intrstr);
  712                 aprint_normal("\n");
  713                 return;
  714         }
  715 
  716         for (channel = 0; channel < sc->sc_wdcdev.nchannels; channel++) {
  717                 cp = &sc->pciide_channels[channel];
  718                 if (sii3114_chansetup(sc, channel) == 0)
  719                         continue;
  720                 sii3114_mapchan(cp);
  721         }
  722 }
  723 
  724 static const char *sata_speed[] = {
  725         "no negotiated speed",
  726         "1.5Gb/s",
  727         "<unknown 2>",
  728         "<unknown 3>",
  729         "<unknown 4>",
  730         "<unknown 5>",
  731         "<unknown 6>",
  732         "<unknown 7>",
  733         "<unknown 8>",
  734         "<unknown 9>",
  735         "<unknown 10>",
  736         "<unknown 11>",
  737         "<unknown 12>",
  738         "<unknown 13>",
  739         "<unknown 14>",
  740         "<unknown 15>",
  741 };
  742 
  743 static void
  744 sii3112_drv_probe(struct wdc_channel *chp)
  745 {
  746         struct pciide_channel *cp = (struct pciide_channel *)chp;
  747         struct pciide_softc *sc = (struct pciide_softc *)cp->wdc_channel.ch_wdc;
  748         uint32_t scontrol, sstatus;
  749         uint8_t scnt, sn, cl, ch;
  750         int i;
  751 
  752         /* XXX This should be done by other code. */
  753         for (i = 0; i < 2; i++) {
  754                 chp->ch_drive[i].chnl_softc = chp;
  755                 chp->ch_drive[i].drive = i;
  756         }
  757 
  758         /*
  759          * The 3112 is a 2-port part, and only has one drive per channel
  760          * (each port emulates a master drive).
  761          *
  762          * The 3114 is similar, but has 4 channels.
  763          */
  764 
  765         /*
  766          * Request communication initialization sequence, any speed.
  767          * Performing this is the equivalent of an ATA Reset.
  768          */
  769         scontrol = SControl_DET_INIT | SControl_SPD_ANY;
  770 
  771         /*
  772          * XXX We don't yet support SATA power management; disable all
  773          * power management state transitions.
  774          */
  775         scontrol |= SControl_IPM_NONE;
  776 
  777         BA5_WRITE_4(sc, chp->ch_channel, ba5_SControl, scontrol);
  778         delay(50 * 1000);
  779         scontrol &= ~SControl_DET_INIT;
  780         BA5_WRITE_4(sc, chp->ch_channel, ba5_SControl, scontrol);
  781         delay(50 * 1000);
  782 
  783         sstatus = BA5_READ_4(sc, chp->ch_channel, ba5_SStatus);
  784 #if 0
  785         aprint_normal("%s: port %d: SStatus=0x%08x, SControl=0x%08x\n",
  786             sc->sc_wdcdev.sc_dev.dv_xname, chp->ch_channel, sstatus,
  787             BA5_READ_4(sc, chp->ch_channel, ba5_SControl));
  788 #endif
  789         switch (sstatus & SStatus_DET_mask) {
  790         case SStatus_DET_NODEV:
  791                 /* No device; be silent. */
  792                 break;
  793 
  794         case SStatus_DET_DEV_NE:
  795                 aprint_error("%s: port %d: device connected, but "
  796                     "communication not established\n",
  797                     sc->sc_wdcdev.sc_dev.dv_xname, chp->ch_channel);
  798                 break;
  799 
  800         case SStatus_DET_OFFLINE:
  801                 aprint_error("%s: port %d: PHY offline\n",
  802                     sc->sc_wdcdev.sc_dev.dv_xname, chp->ch_channel);
  803                 break;
  804 
  805         case SStatus_DET_DEV:
  806                 /*
  807                  * XXX ATAPI detection doesn't currently work.  Don't
  808                  * XXX know why.  But, it's not like the standard method
  809                  * XXX can detect an ATAPI device connected via a SATA/PATA
  810                  * XXX bridge, so at least this is no worse.  --thorpej
  811                  */
  812                 bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh], 0,
  813                     WDSD_IBM | (0 << 4));
  814                 delay(10);      /* 400ns delay */
  815                 /* Save register contents. */
  816                 scnt = bus_space_read_1(chp->cmd_iot,
  817                                         chp->cmd_iohs[wd_seccnt], 0);
  818                 sn = bus_space_read_1(chp->cmd_iot,
  819                                       chp->cmd_iohs[wd_sector], 0);
  820                 cl = bus_space_read_1(chp->cmd_iot,
  821                                       chp->cmd_iohs[wd_cyl_lo], 0);
  822                 ch = bus_space_read_1(chp->cmd_iot,
  823                                       chp->cmd_iohs[wd_cyl_hi], 0);
  824 #if 0
  825                 printf("%s: port %d: scnt=0x%x sn=0x%x cl=0x%x ch=0x%x\n",
  826                     sc->sc_wdcdev.sc_dev.dv_xname, chp->ch_channel,
  827                     scnt, sn, cl, ch);
  828 #endif
  829                 /*
  830                  * scnt and sn are supposed to be 0x1 for ATAPI, but in some
  831                  * cases we get wrong values here, so ignore it.
  832                  */
  833                 if (cl == 0x14 && ch == 0xeb)
  834                         chp->ch_drive[0].drive_flags |= DRIVE_ATAPI;
  835                 else
  836                         chp->ch_drive[0].drive_flags |= DRIVE_ATA;
  837 
  838                 aprint_normal("%s: port %d: device present, speed: %s\n",
  839                     sc->sc_wdcdev.sc_dev.dv_xname, chp->ch_channel,
  840                     sata_speed[(sstatus & SStatus_SPD_mask) >> 
  841                                SStatus_SPD_shift]);
  842                 break;
  843 
  844         default:
  845                 aprint_error("%s: port %d: unknown SStatus: 0x%08x\n",
  846                     sc->sc_wdcdev.sc_dev.dv_xname, chp->ch_channel, sstatus);
  847         }
  848 }
  849 
  850 static void
  851 sii3112_setup_channel(struct wdc_channel *chp)
  852 {
  853         struct ata_drive_datas *drvp;
  854         int drive;
  855         u_int32_t idedma_ctl, dtm;
  856         struct pciide_channel *cp = (struct pciide_channel*)chp;
  857         struct pciide_softc *sc = (struct pciide_softc*)cp->wdc_channel.ch_wdc;
  858 
  859         /* setup DMA if needed */
  860         pciide_channel_dma_setup(cp);
  861 
  862         idedma_ctl = 0;
  863         dtm = 0;
  864 
  865         for (drive = 0; drive < 2; drive++) {
  866                 drvp = &chp->ch_drive[drive];
  867                 /* If no drive, skip */
  868                 if ((drvp->drive_flags & DRIVE) == 0)
  869                         continue;
  870                 if (drvp->drive_flags & DRIVE_UDMA) {
  871                         /* use Ultra/DMA */
  872                         drvp->drive_flags &= ~DRIVE_DMA;
  873                         idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
  874                         dtm |= DTM_IDEx_DMA;
  875                 } else if (drvp->drive_flags & DRIVE_DMA) {
  876                         idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive);
  877                         dtm |= DTM_IDEx_DMA;
  878                 } else {
  879                         dtm |= DTM_IDEx_PIO;
  880                 }
  881         }
  882 
  883         /*
  884          * Nothing to do to setup modes; it is meaningless in S-ATA
  885          * (but many S-ATA drives still want to get the SET_FEATURE
  886          * command).
  887          */
  888         if (idedma_ctl != 0) {
  889                 /* Add software bits in status register */
  890                 bus_space_write_1(sc->sc_dma_iot, cp->dma_iohs[IDEDMA_CTL], 0,
  891                     idedma_ctl);
  892         }
  893         BA5_WRITE_4(sc, chp->ch_channel, ba5_IDE_DTM, dtm);
  894 }

Cache object: 2c1342b4767103715701f735b09c0fa5


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