LCOV - code coverage report
Current view: top level - dev/pci - ahci_pci.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 119 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 17 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: ahci_pci.c,v 1.15 2018/08/03 22:18:13 kettenis Exp $ */
       2             : 
       3             : /*
       4             :  * Copyright (c) 2006 David Gwynne <dlg@openbsd.org>
       5             :  * Copyright (c) 2010 Conformal Systems LLC <info@conformal.com>
       6             :  * Copyright (c) 2010 Jonathan Matthew <jonathan@d14n.org>
       7             :  *
       8             :  * Permission to use, copy, modify, and distribute this software for any
       9             :  * purpose with or without fee is hereby granted, provided that the above
      10             :  * copyright notice and this permission notice appear in all copies.
      11             :  *
      12             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      13             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      14             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      15             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      16             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      17             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      18             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      19             :  */
      20             : 
      21             : #include <sys/param.h>
      22             : #include <sys/systm.h>
      23             : #include <sys/buf.h>
      24             : #include <sys/kernel.h>
      25             : #include <sys/malloc.h>
      26             : #include <sys/device.h>
      27             : #include <sys/timeout.h>
      28             : #include <sys/queue.h>
      29             : #include <sys/mutex.h>
      30             : #include <sys/pool.h>
      31             : 
      32             : #include <machine/bus.h>
      33             : 
      34             : #include <dev/pci/pcireg.h>
      35             : #include <dev/pci/pcivar.h>
      36             : #include <dev/pci/pcidevs.h>
      37             : 
      38             : #include <dev/ata/pmreg.h>
      39             : 
      40             : #include <dev/ic/ahcireg.h>
      41             : #include <dev/ic/ahcivar.h>
      42             : 
      43             : #define AHCI_PCI_BAR            0x24
      44             : #define AHCI_PCI_ATI_SB600_MAGIC        0x40
      45             : #define AHCI_PCI_ATI_SB600_LOCKED       0x01
      46             : 
      47             : struct ahci_pci_softc {
      48             :         struct ahci_softc       psc_ahci;
      49             : 
      50             :         pci_chipset_tag_t       psc_pc;
      51             :         pcitag_t                psc_tag;
      52             : 
      53             :         int                     psc_flags;
      54             : };
      55             : 
      56             : struct ahci_device {
      57             :         pci_vendor_id_t         ad_vendor;
      58             :         pci_product_id_t        ad_product;
      59             :         int                     (*ad_match)(struct pci_attach_args *);
      60             :         int                     (*ad_attach)(struct ahci_softc *,
      61             :                                     struct pci_attach_args *);
      62             : };
      63             : 
      64             : const struct ahci_device *ahci_lookup_device(struct pci_attach_args *);
      65             : 
      66             : int                     ahci_no_match(struct pci_attach_args *);
      67             : int                     ahci_vt8251_attach(struct ahci_softc *,
      68             :                             struct pci_attach_args *);
      69             : void                    ahci_ati_sb_idetoahci(struct ahci_softc *,
      70             :                             struct pci_attach_args *pa);
      71             : int                     ahci_ati_sb600_attach(struct ahci_softc *,
      72             :                             struct pci_attach_args *);
      73             : int                     ahci_ati_sb700_attach(struct ahci_softc *,
      74             :                             struct pci_attach_args *);
      75             : int                     ahci_amd_hudson2_attach(struct ahci_softc *,
      76             :                             struct pci_attach_args *);
      77             : int                     ahci_intel_attach(struct ahci_softc *,
      78             :                             struct pci_attach_args *);
      79             : int                     ahci_samsung_attach(struct ahci_softc *,
      80             :                             struct pci_attach_args *);
      81             : 
      82             : static const struct ahci_device ahci_devices[] = {
      83             :         { PCI_VENDOR_AMD,       PCI_PRODUCT_AMD_HUDSON2_SATA_1,
      84             :             NULL,               ahci_amd_hudson2_attach },
      85             :         { PCI_VENDOR_AMD,       PCI_PRODUCT_AMD_HUDSON2_SATA_2,
      86             :             NULL,               ahci_amd_hudson2_attach },
      87             :         { PCI_VENDOR_AMD,       PCI_PRODUCT_AMD_HUDSON2_SATA_3,
      88             :             NULL,               ahci_amd_hudson2_attach },
      89             :         { PCI_VENDOR_AMD,       PCI_PRODUCT_AMD_HUDSON2_SATA_4,
      90             :             NULL,               ahci_amd_hudson2_attach },
      91             :         { PCI_VENDOR_AMD,       PCI_PRODUCT_AMD_HUDSON2_SATA_5,
      92             :             NULL,               ahci_amd_hudson2_attach },
      93             :         { PCI_VENDOR_AMD,       PCI_PRODUCT_AMD_HUDSON2_SATA_6,
      94             :             NULL,               ahci_amd_hudson2_attach },
      95             : 
      96             :         { PCI_VENDOR_ATI,       PCI_PRODUCT_ATI_SB600_SATA,
      97             :             NULL,               ahci_ati_sb600_attach },
      98             :         { PCI_VENDOR_ATI,       PCI_PRODUCT_ATI_SBX00_SATA_1,
      99             :             NULL,               ahci_ati_sb700_attach },
     100             :         { PCI_VENDOR_ATI,       PCI_PRODUCT_ATI_SBX00_SATA_2,
     101             :             NULL,               ahci_ati_sb700_attach },
     102             :         { PCI_VENDOR_ATI,       PCI_PRODUCT_ATI_SBX00_SATA_3,
     103             :             NULL,               ahci_ati_sb700_attach },
     104             :         { PCI_VENDOR_ATI,       PCI_PRODUCT_ATI_SBX00_SATA_4,
     105             :             NULL,               ahci_ati_sb700_attach },
     106             :         { PCI_VENDOR_ATI,       PCI_PRODUCT_ATI_SBX00_SATA_5,
     107             :             NULL,               ahci_ati_sb700_attach },
     108             :         { PCI_VENDOR_ATI,       PCI_PRODUCT_ATI_SBX00_SATA_6,
     109             :             NULL,               ahci_ati_sb700_attach },
     110             : 
     111             :         { PCI_VENDOR_ASMEDIA,   PCI_PRODUCT_ASMEDIA_ASM1061_SATA },
     112             : 
     113             :         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_6SERIES_AHCI_1,
     114             :             NULL,               ahci_intel_attach },
     115             :         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_6SERIES_AHCI_2,
     116             :             NULL,               ahci_intel_attach },
     117             :         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_6321ESB_AHCI,
     118             :             NULL,               ahci_intel_attach },
     119             :         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801GR_AHCI,
     120             :             NULL,               ahci_intel_attach },
     121             :         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801GBM_AHCI,
     122             :             NULL,               ahci_intel_attach },
     123             :         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801H_AHCI_6P,
     124             :             NULL,               ahci_intel_attach },
     125             :         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801H_AHCI_4P,
     126             :             NULL,               ahci_intel_attach },
     127             :         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801HBM_AHCI,
     128             :             NULL,               ahci_intel_attach },
     129             :         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801I_AHCI_1,
     130             :             NULL,               ahci_intel_attach },
     131             :         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801I_AHCI_2,
     132             :             NULL,               ahci_intel_attach },
     133             :         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801I_AHCI_3,
     134             :             NULL,               ahci_intel_attach },
     135             :         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801JD_AHCI,
     136             :             NULL,               ahci_intel_attach },
     137             :         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_82801JI_AHCI,
     138             :             NULL,               ahci_intel_attach },
     139             :         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_3400_AHCI_1,
     140             :             NULL,               ahci_intel_attach },
     141             :         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_3400_AHCI_2,
     142             :             NULL,               ahci_intel_attach },
     143             :         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_3400_AHCI_3,
     144             :             NULL,               ahci_intel_attach },
     145             :         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_3400_AHCI_4,
     146             :             NULL,               ahci_intel_attach },
     147             :         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_EP80579_AHCI,
     148             :             NULL,               ahci_intel_attach },
     149             : 
     150             :         { PCI_VENDOR_SAMSUNG2,  PCI_PRODUCT_SAMSUNG2_S4LN053X01,
     151             :             NULL,               ahci_samsung_attach },
     152             :         { PCI_VENDOR_SAMSUNG2,  PCI_PRODUCT_SAMSUNG2_XP941,
     153             :             NULL,               ahci_samsung_attach },
     154             :         { PCI_VENDOR_SAMSUNG2,  PCI_PRODUCT_SAMSUNG2_SM951_AHCI,
     155             :             NULL,               ahci_samsung_attach },
     156             : 
     157             :         { PCI_VENDOR_VIATECH,   PCI_PRODUCT_VIATECH_VT8251_SATA,
     158             :           ahci_no_match,        ahci_vt8251_attach }
     159             : };
     160             : 
     161             : int                     ahci_pci_match(struct device *, void *, void *);
     162             : void                    ahci_pci_attach(struct device *, struct device *,
     163             :                             void *);
     164             : int                     ahci_pci_detach(struct device *, int);
     165             : int                     ahci_pci_activate(struct device *, int);
     166             : 
     167             : struct cfattach ahci_pci_ca = {
     168             :         sizeof(struct ahci_pci_softc),
     169             :         ahci_pci_match,
     170             :         ahci_pci_attach,
     171             :         ahci_pci_detach,
     172             :         ahci_pci_activate
     173             : };
     174             : 
     175             : struct cfattach ahci_jmb_ca = {
     176             :         sizeof(struct ahci_pci_softc),
     177             :         ahci_pci_match,
     178             :         ahci_pci_attach,
     179             :         ahci_pci_detach
     180             : };
     181             : 
     182             : int                     ahci_map_regs(struct ahci_pci_softc *,
     183             :                             struct pci_attach_args *);
     184             : void                    ahci_unmap_regs(struct ahci_pci_softc *);
     185             : int                     ahci_map_intr(struct ahci_pci_softc *,
     186             :                             struct pci_attach_args *, pci_intr_handle_t);
     187             : void                    ahci_unmap_intr(struct ahci_pci_softc *);
     188             : 
     189             : const struct ahci_device *
     190           0 : ahci_lookup_device(struct pci_attach_args *pa)
     191             : {
     192             :         int                             i;
     193             :         const struct ahci_device        *ad;
     194             : 
     195           0 :         for (i = 0; i < (sizeof(ahci_devices) / sizeof(ahci_devices[0])); i++) {
     196           0 :                 ad = &ahci_devices[i];
     197           0 :                 if (ad->ad_vendor == PCI_VENDOR(pa->pa_id) &&
     198           0 :                     ad->ad_product == PCI_PRODUCT(pa->pa_id))
     199           0 :                         return (ad);
     200             :         }
     201             : 
     202           0 :         return (NULL);
     203           0 : }
     204             : 
     205             : int
     206           0 : ahci_no_match(struct pci_attach_args *pa)
     207             : {
     208           0 :         return (0);
     209             : }
     210             : 
     211             : int
     212           0 : ahci_vt8251_attach(struct ahci_softc *sc, struct pci_attach_args *pa)
     213             : {
     214           0 :         sc->sc_flags |= AHCI_F_NO_NCQ;
     215             : 
     216           0 :         return (0);
     217             : }
     218             : 
     219             : void
     220           0 : ahci_ati_sb_idetoahci(struct ahci_softc *sc, struct pci_attach_args *pa)
     221             : {
     222             :         pcireg_t                        magic;
     223             : 
     224           0 :         if (PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MASS_STORAGE_IDE) {
     225           0 :                 magic = pci_conf_read(pa->pa_pc, pa->pa_tag,
     226             :                     AHCI_PCI_ATI_SB600_MAGIC);
     227           0 :                 pci_conf_write(pa->pa_pc, pa->pa_tag,
     228             :                     AHCI_PCI_ATI_SB600_MAGIC,
     229           0 :                     magic | AHCI_PCI_ATI_SB600_LOCKED);
     230             : 
     231           0 :                 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG,
     232             :                     PCI_CLASS_MASS_STORAGE << PCI_CLASS_SHIFT |
     233             :                     PCI_SUBCLASS_MASS_STORAGE_SATA << PCI_SUBCLASS_SHIFT |
     234           0 :                     PCI_INTERFACE_SATA_AHCI10 << PCI_INTERFACE_SHIFT |
     235           0 :                     PCI_REVISION(pa->pa_class) << PCI_REVISION_SHIFT);
     236             : 
     237           0 :                 pci_conf_write(pa->pa_pc, pa->pa_tag,
     238             :                     AHCI_PCI_ATI_SB600_MAGIC, magic);
     239           0 :         }
     240           0 : }
     241             : 
     242             : int
     243           0 : ahci_ati_sb600_attach(struct ahci_softc *sc, struct pci_attach_args *pa)
     244             : {
     245           0 :         ahci_ati_sb_idetoahci(sc, pa);
     246             : 
     247           0 :         sc->sc_flags |= AHCI_F_IPMS_PROBE;
     248             : 
     249           0 :         return (0);
     250             : }
     251             : 
     252             : int
     253           0 : ahci_ati_sb700_attach(struct ahci_softc *sc, struct pci_attach_args *pa)
     254             : {
     255           0 :         ahci_ati_sb_idetoahci(sc, pa);
     256             : 
     257           0 :         sc->sc_flags |= AHCI_F_IPMS_PROBE;
     258             : 
     259           0 :         return (0);
     260             : }
     261             : 
     262             : int
     263           0 : ahci_amd_hudson2_attach(struct ahci_softc *sc, struct pci_attach_args *pa)
     264             : {
     265           0 :         ahci_ati_sb_idetoahci(sc, pa);
     266             : 
     267           0 :         sc->sc_flags |= AHCI_F_IPMS_PROBE;
     268             : 
     269           0 :         return (0);
     270             : }
     271             : 
     272             : int
     273           0 : ahci_intel_attach(struct ahci_softc *sc, struct pci_attach_args *pa)
     274             : {
     275           0 :         sc->sc_flags |= AHCI_F_NO_PMP;
     276             : 
     277           0 :         return (0);
     278             : }
     279             : 
     280             : int
     281           0 : ahci_samsung_attach(struct ahci_softc *sc, struct pci_attach_args *pa)
     282             : {
     283             :         /*
     284             :          * Disable MSI with the Samsung S4LN053X01 SSD controller as found
     285             :          * in some Apple MacBook Air models such as the 6,1 and 6,2, as well
     286             :          * as the XP941 SSD controller.
     287             :          * https://bugzilla.kernel.org/show_bug.cgi?id=60731
     288             :          * https://bugzilla.kernel.org/show_bug.cgi?id=89171
     289             :          */
     290           0 :         sc->sc_flags |= AHCI_F_NO_MSI;
     291             : 
     292           0 :         return (0);
     293             : }
     294             : 
     295             : int
     296           0 : ahci_pci_match(struct device *parent, void *match, void *aux)
     297             : {
     298           0 :         struct pci_attach_args          *pa = aux;
     299             :         const struct ahci_device        *ad;
     300             : 
     301           0 :         ad = ahci_lookup_device(pa);
     302           0 :         if (ad != NULL) {
     303             :                 /* the device may need special checks to see if it matches */
     304           0 :                 if (ad->ad_match != NULL)
     305           0 :                         return (ad->ad_match(pa));
     306             : 
     307           0 :                 return (2); /* match higher than pciide */
     308             :         }
     309             : 
     310           0 :         if (PCI_CLASS(pa->pa_class) == PCI_CLASS_MASS_STORAGE &&
     311           0 :             PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MASS_STORAGE_SATA &&
     312           0 :             PCI_INTERFACE(pa->pa_class) == PCI_INTERFACE_SATA_AHCI10)
     313           0 :                 return (2);
     314             : 
     315           0 :         return (0);
     316           0 : }
     317             : 
     318             : void
     319           0 : ahci_pci_attach(struct device *parent, struct device *self, void *aux)
     320             : {
     321           0 :         struct ahci_pci_softc           *psc = (struct ahci_pci_softc *)self;
     322           0 :         struct ahci_softc               *sc = &psc->psc_ahci;
     323           0 :         struct pci_attach_args          *pa = aux;
     324             :         const struct ahci_device        *ad;
     325           0 :         pci_intr_handle_t               ih;
     326             : 
     327           0 :         psc->psc_pc = pa->pa_pc;
     328           0 :         psc->psc_tag = pa->pa_tag;
     329           0 :         sc->sc_dmat = pa->pa_dmat;
     330             : 
     331           0 :         ad = ahci_lookup_device(pa);
     332           0 :         if (ad != NULL && ad->ad_attach != NULL) {
     333           0 :                 if (ad->ad_attach(sc, pa) != 0) {
     334             :                         /* error should be printed by ad_attach */
     335           0 :                         return;
     336             :                 }
     337             :         }
     338             : 
     339           0 :         if (sc->sc_flags & AHCI_F_NO_MSI)
     340           0 :                 pa->pa_flags &= ~PCI_FLAGS_MSI_ENABLED;
     341             : 
     342           0 :         if (pci_intr_map_msi(pa, &ih) != 0 && pci_intr_map(pa, &ih) != 0) {
     343           0 :                 printf(": unable to map interrupt\n");
     344           0 :                 return;
     345             :         }
     346           0 :         printf(": %s,", pci_intr_string(pa->pa_pc, ih));
     347             : 
     348           0 :         if (ahci_map_regs(psc, pa) != 0) {
     349             :                 /* error already printed by ahci_map_regs */
     350           0 :                 return;
     351             :         }
     352             : 
     353           0 :         if (ahci_map_intr(psc, pa, ih) != 0) {
     354             :                 /* error already printed by ahci_map_intr */
     355             :                 goto unmap;
     356             :         }
     357             : 
     358           0 :         if (ahci_attach(sc) != 0) {
     359             :                 /* error printed by ahci_attach */
     360             :                 goto unmap;
     361             :         }
     362             : 
     363           0 :         return;
     364             : 
     365             : unmap:
     366           0 :         ahci_unmap_regs(psc);
     367           0 :         return;
     368           0 : }
     369             : 
     370             : int
     371           0 : ahci_pci_detach(struct device *self, int flags)
     372             : {
     373           0 :         struct ahci_pci_softc           *psc = (struct ahci_pci_softc *)self;
     374           0 :         struct ahci_softc               *sc = &psc->psc_ahci;
     375             : 
     376           0 :         ahci_detach(sc, flags);
     377             : 
     378           0 :         ahci_unmap_intr(psc);
     379           0 :         ahci_unmap_regs(psc);
     380             : 
     381           0 :         return (0);
     382             : }
     383             : 
     384             : int
     385           0 : ahci_map_regs(struct ahci_pci_softc *psc, struct pci_attach_args *pa)
     386             : {
     387             :         pcireg_t                        maptype;
     388           0 :         struct ahci_softc               *sc = &psc->psc_ahci;
     389             : 
     390           0 :         maptype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, AHCI_PCI_BAR);
     391           0 :         if (pci_mapreg_map(pa, AHCI_PCI_BAR, maptype, 0, &sc->sc_iot,
     392           0 :             &sc->sc_ioh, NULL, &sc->sc_ios, 0) != 0) {
     393           0 :                 printf(" unable to map registers\n");
     394           0 :                 return (1);
     395             :         }
     396             : 
     397           0 :         return (0);
     398           0 : }
     399             : 
     400             : void
     401           0 : ahci_unmap_regs(struct ahci_pci_softc *psc)
     402             : {
     403           0 :         struct ahci_softc               *sc = &psc->psc_ahci;
     404             : 
     405           0 :         bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
     406           0 :         sc->sc_ios = 0;
     407           0 : }
     408             : 
     409             : int
     410           0 : ahci_map_intr(struct ahci_pci_softc *psc, struct pci_attach_args *pa,
     411             :     pci_intr_handle_t ih)
     412             : {
     413           0 :         struct ahci_softc               *sc = &psc->psc_ahci;
     414           0 :         sc->sc_ih = pci_intr_establish(psc->psc_pc, ih, IPL_BIO,
     415           0 :             ahci_intr, sc, DEVNAME(sc));
     416           0 :         if (sc->sc_ih == NULL) {
     417           0 :                 printf("%s: unable to map interrupt\n", DEVNAME(sc));
     418           0 :                 return (1);
     419             :         }
     420             : 
     421           0 :         return (0);
     422           0 : }
     423             : 
     424             : void
     425           0 : ahci_unmap_intr(struct ahci_pci_softc *psc)
     426             : {
     427           0 :         struct ahci_softc               *sc = &psc->psc_ahci;
     428           0 :         pci_intr_disestablish(psc->psc_pc, sc->sc_ih);
     429           0 : }
     430             : 
     431             : int
     432           0 : ahci_pci_activate(struct device *self, int act)
     433             : {
     434           0 :         struct ahci_pci_softc           *psc = (struct ahci_pci_softc *)self;
     435           0 :         struct ahci_softc               *sc = &psc->psc_ahci;
     436           0 :         return ahci_activate((struct device *)sc, act);
     437             : }

Generated by: LCOV version 1.13