1 1.168 riastrad /* $NetBSD: pci.c,v 1.168 2024/06/23 00:53:34 riastradh Exp $ */ 2 1.3 cgd 3 1.1 mycroft /* 4 1.37 cgd * Copyright (c) 1995, 1996, 1997, 1998 5 1.27 cgd * Christopher G. Demetriou. All rights reserved. 6 1.39 mycroft * Copyright (c) 1994 Charles M. Hannum. All rights reserved. 7 1.1 mycroft * 8 1.1 mycroft * Redistribution and use in source and binary forms, with or without 9 1.1 mycroft * modification, are permitted provided that the following conditions 10 1.1 mycroft * are met: 11 1.1 mycroft * 1. Redistributions of source code must retain the above copyright 12 1.1 mycroft * notice, this list of conditions and the following disclaimer. 13 1.1 mycroft * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 mycroft * notice, this list of conditions and the following disclaimer in the 15 1.1 mycroft * documentation and/or other materials provided with the distribution. 16 1.1 mycroft * 3. All advertising materials mentioning features or use of this software 17 1.1 mycroft * must display the following acknowledgement: 18 1.39 mycroft * This product includes software developed by Charles M. Hannum. 19 1.1 mycroft * 4. The name of the author may not be used to endorse or promote products 20 1.1 mycroft * derived from this software without specific prior written permission. 21 1.1 mycroft * 22 1.1 mycroft * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 1.1 mycroft * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 1.1 mycroft * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 1.1 mycroft * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 1.1 mycroft * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 1.1 mycroft * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 1.1 mycroft * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 1.1 mycroft * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 1.1 mycroft * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 1.1 mycroft * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 1.1 mycroft */ 33 1.1 mycroft 34 1.1 mycroft /* 35 1.10 cgd * PCI bus autoconfiguration. 36 1.1 mycroft */ 37 1.58 lukem 38 1.58 lukem #include <sys/cdefs.h> 39 1.168 riastrad __KERNEL_RCSID(0, "$NetBSD: pci.c,v 1.168 2024/06/23 00:53:34 riastradh Exp $"); 40 1.1 mycroft 41 1.148 pooka #ifdef _KERNEL_OPT 42 1.45 cgd #include "opt_pci.h" 43 1.148 pooka #endif 44 1.45 cgd 45 1.1 mycroft #include <sys/param.h> 46 1.107 jmcneill #include <sys/malloc.h> 47 1.10 cgd #include <sys/systm.h> 48 1.1 mycroft #include <sys/device.h> 49 1.142 jmcneill #include <sys/module.h> 50 1.1 mycroft 51 1.10 cgd #include <dev/pci/pcireg.h> 52 1.7 cgd #include <dev/pci/pcivar.h> 53 1.33 cgd #include <dev/pci/pcidevs.h> 54 1.152 msaitoh #include <dev/pci/ppbvar.h> 55 1.76 christos 56 1.162 thorpej #include <dev/pci/pci_calls.h> 57 1.162 thorpej 58 1.107 jmcneill #include <net/if.h> 59 1.107 jmcneill 60 1.76 christos #include "locators.h" 61 1.10 cgd 62 1.165 riastrad static void pci_child_register(device_t); 63 1.107 jmcneill 64 1.45 cgd #ifdef PCI_CONFIG_DUMP 65 1.45 cgd int pci_config_dump = 1; 66 1.45 cgd #else 67 1.45 cgd int pci_config_dump = 0; 68 1.45 cgd #endif 69 1.45 cgd 70 1.91 perry int pciprint(void *, const char *); 71 1.10 cgd 72 1.168 riastrad #ifdef PCI_MACHDEP_ENUMERATE_BUS1 73 1.168 riastrad #define pci_enumerate_bus1 PCI_MACHDEP_ENUMERATE_BUS1 74 1.86 drochner #endif 75 1.86 drochner 76 1.25 cgd /* 77 1.38 thorpej * Important note about PCI-ISA bridges: 78 1.38 thorpej * 79 1.38 thorpej * Callbacks are used to configure these devices so that ISA/EISA bridges 80 1.38 thorpej * can attach their child busses after PCI configuration is done. 81 1.25 cgd * 82 1.25 cgd * This works because: 83 1.25 cgd * (1) there can be at most one ISA/EISA bridge per PCI bus, and 84 1.25 cgd * (2) any ISA/EISA bridges must be attached to primary PCI 85 1.25 cgd * busses (i.e. bus zero). 86 1.25 cgd * 87 1.25 cgd * That boils down to: there can only be one of these outstanding 88 1.25 cgd * at a time, it is cleared when configuring PCI bus 0 before any 89 1.25 cgd * subdevices have been found, and it is run after all subdevices 90 1.25 cgd * of PCI bus 0 have been found. 91 1.25 cgd * 92 1.25 cgd * This is needed because there are some (legacy) PCI devices which 93 1.25 cgd * can show up as ISA/EISA devices as well (the prime example of which 94 1.25 cgd * are VGA controllers). If you attach ISA from a PCI-ISA/EISA bridge, 95 1.25 cgd * and the bridge is seen before the video board is, the board can show 96 1.25 cgd * up as an ISA device, and that can (bogusly) complicate the PCI device's 97 1.25 cgd * attach code, or make the PCI device not be properly attached at all. 98 1.38 thorpej * 99 1.38 thorpej * We use the generic config_defer() facility to achieve this. 100 1.25 cgd */ 101 1.25 cgd 102 1.116 dyoung int 103 1.114 dyoung pcirescan(device_t self, const char *ifattr, const int *locators) 104 1.93 thorpej { 105 1.114 dyoung struct pci_softc *sc = device_private(self); 106 1.93 thorpej 107 1.93 thorpej KASSERT(ifattr && !strcmp(ifattr, "pci")); 108 1.93 thorpej KASSERT(locators); 109 1.93 thorpej 110 1.114 dyoung pci_enumerate_bus(sc, locators, NULL, NULL); 111 1.128 pgoyette 112 1.114 dyoung return 0; 113 1.93 thorpej } 114 1.93 thorpej 115 1.116 dyoung int 116 1.115 cube pcimatch(device_t parent, cfdata_t cf, void *aux) 117 1.10 cgd { 118 1.10 cgd struct pcibus_attach_args *pba = aux; 119 1.10 cgd 120 1.10 cgd /* Check the locators */ 121 1.89 drochner if (cf->cf_loc[PCIBUSCF_BUS] != PCIBUSCF_BUS_DEFAULT && 122 1.89 drochner cf->cf_loc[PCIBUSCF_BUS] != pba->pba_bus) 123 1.123 cegger return 0; 124 1.10 cgd 125 1.10 cgd /* sanity */ 126 1.10 cgd if (pba->pba_bus < 0 || pba->pba_bus > 255) 127 1.123 cegger return 0; 128 1.10 cgd 129 1.10 cgd /* 130 1.10 cgd * XXX check other (hardware?) indicators 131 1.10 cgd */ 132 1.10 cgd 133 1.123 cegger return 1; 134 1.10 cgd } 135 1.1 mycroft 136 1.116 dyoung void 137 1.114 dyoung pciattach(device_t parent, device_t self, void *aux) 138 1.34 drochner { 139 1.34 drochner struct pcibus_attach_args *pba = aux; 140 1.114 dyoung struct pci_softc *sc = device_private(self); 141 1.43 thorpej int io_enabled, mem_enabled, mrl_enabled, mrm_enabled, mwi_enabled; 142 1.43 thorpej const char *sep = ""; 143 1.96 drochner static const int wildcard[PCICF_NLOCS] = { 144 1.96 drochner PCICF_DEV_DEFAULT, PCICF_FUNCTION_DEFAULT 145 1.96 drochner }; 146 1.34 drochner 147 1.115 cube sc->sc_dev = self; 148 1.115 cube 149 1.34 drochner pci_attach_hook(parent, self, pba); 150 1.78 thorpej 151 1.78 thorpej aprint_naive("\n"); 152 1.78 thorpej aprint_normal("\n"); 153 1.34 drochner 154 1.140 dyoung io_enabled = (pba->pba_flags & PCI_FLAGS_IO_OKAY); 155 1.140 dyoung mem_enabled = (pba->pba_flags & PCI_FLAGS_MEM_OKAY); 156 1.43 thorpej mrl_enabled = (pba->pba_flags & PCI_FLAGS_MRL_OKAY); 157 1.43 thorpej mrm_enabled = (pba->pba_flags & PCI_FLAGS_MRM_OKAY); 158 1.43 thorpej mwi_enabled = (pba->pba_flags & PCI_FLAGS_MWI_OKAY); 159 1.34 drochner 160 1.34 drochner if (io_enabled == 0 && mem_enabled == 0) { 161 1.114 dyoung aprint_error_dev(self, "no spaces enabled!\n"); 162 1.107 jmcneill goto fail; 163 1.34 drochner } 164 1.34 drochner 165 1.78 thorpej #define PRINT(str) \ 166 1.78 thorpej do { \ 167 1.106 ad aprint_verbose("%s%s", sep, str); \ 168 1.78 thorpej sep = ", "; \ 169 1.78 thorpej } while (/*CONSTCOND*/0) 170 1.43 thorpej 171 1.115 cube aprint_verbose_dev(self, ""); 172 1.43 thorpej 173 1.34 drochner if (io_enabled) 174 1.43 thorpej PRINT("i/o space"); 175 1.43 thorpej if (mem_enabled) 176 1.43 thorpej PRINT("memory space"); 177 1.106 ad aprint_verbose(" enabled"); 178 1.43 thorpej 179 1.43 thorpej if (mrl_enabled || mrm_enabled || mwi_enabled) { 180 1.43 thorpej if (mrl_enabled) 181 1.43 thorpej PRINT("rd/line"); 182 1.43 thorpej if (mrm_enabled) 183 1.43 thorpej PRINT("rd/mult"); 184 1.43 thorpej if (mwi_enabled) 185 1.43 thorpej PRINT("wr/inv"); 186 1.106 ad aprint_verbose(" ok"); 187 1.34 drochner } 188 1.43 thorpej 189 1.106 ad aprint_verbose("\n"); 190 1.43 thorpej 191 1.43 thorpej #undef PRINT 192 1.34 drochner 193 1.34 drochner sc->sc_iot = pba->pba_iot; 194 1.34 drochner sc->sc_memt = pba->pba_memt; 195 1.34 drochner sc->sc_dmat = pba->pba_dmat; 196 1.80 fvdl sc->sc_dmat64 = pba->pba_dmat64; 197 1.34 drochner sc->sc_pc = pba->pba_pc; 198 1.34 drochner sc->sc_bus = pba->pba_bus; 199 1.62 thorpej sc->sc_bridgetag = pba->pba_bridgetag; 200 1.34 drochner sc->sc_maxndevs = pci_bus_maxdevs(pba->pba_pc, pba->pba_bus); 201 1.34 drochner sc->sc_intrswiz = pba->pba_intrswiz; 202 1.34 drochner sc->sc_intrtag = pba->pba_intrtag; 203 1.34 drochner sc->sc_flags = pba->pba_flags; 204 1.100 jmcneill 205 1.115 cube device_pmf_driver_set_child_register(sc->sc_dev, pci_child_register); 206 1.100 jmcneill 207 1.115 cube pcirescan(sc->sc_dev, "pci", wildcard); 208 1.107 jmcneill 209 1.107 jmcneill fail: 210 1.107 jmcneill if (!pmf_device_register(self, NULL, NULL)) 211 1.107 jmcneill aprint_error_dev(self, "couldn't establish power handler\n"); 212 1.107 jmcneill } 213 1.107 jmcneill 214 1.116 dyoung int 215 1.114 dyoung pcidetach(device_t self, int flags) 216 1.107 jmcneill { 217 1.108 dyoung int rc; 218 1.108 dyoung 219 1.108 dyoung if ((rc = config_detach_children(self, flags)) != 0) 220 1.108 dyoung return rc; 221 1.107 jmcneill pmf_device_deregister(self); 222 1.107 jmcneill return 0; 223 1.87 drochner } 224 1.87 drochner 225 1.87 drochner int 226 1.93 thorpej pciprint(void *aux, const char *pnp) 227 1.1 mycroft { 228 1.46 augustss struct pci_attach_args *pa = aux; 229 1.10 cgd char devinfo[256]; 230 1.37 cgd const struct pci_quirkdata *qd; 231 1.1 mycroft 232 1.10 cgd if (pnp) { 233 1.83 itojun pci_devinfo(pa->pa_id, pa->pa_class, 1, devinfo, sizeof(devinfo)); 234 1.75 thorpej aprint_normal("%s at %s", devinfo, pnp); 235 1.10 cgd } 236 1.75 thorpej aprint_normal(" dev %d function %d", pa->pa_device, pa->pa_function); 237 1.45 cgd if (pci_config_dump) { 238 1.45 cgd printf(": "); 239 1.45 cgd pci_conf_print(pa->pa_pc, pa->pa_tag, NULL); 240 1.45 cgd if (!pnp) 241 1.83 itojun pci_devinfo(pa->pa_id, pa->pa_class, 1, devinfo, sizeof(devinfo)); 242 1.45 cgd printf("%s at %s", devinfo, pnp ? pnp : "?"); 243 1.45 cgd printf(" dev %d function %d (", pa->pa_device, pa->pa_function); 244 1.37 cgd #ifdef __i386__ 245 1.45 cgd printf("tag %#lx, intrtag %#lx, intrswiz %#lx, intrpin %#lx", 246 1.45 cgd *(long *)&pa->pa_tag, *(long *)&pa->pa_intrtag, 247 1.45 cgd (long)pa->pa_intrswiz, (long)pa->pa_intrpin); 248 1.37 cgd #else 249 1.54 mrg printf("intrswiz %#lx, intrpin %#lx", 250 1.54 mrg (long)pa->pa_intrswiz, (long)pa->pa_intrpin); 251 1.36 cgd #endif 252 1.45 cgd printf(", i/o %s, mem %s,", 253 1.140 dyoung pa->pa_flags & PCI_FLAGS_IO_OKAY ? "on" : "off", 254 1.140 dyoung pa->pa_flags & PCI_FLAGS_MEM_OKAY ? "on" : "off"); 255 1.45 cgd qd = pci_lookup_quirkdata(PCI_VENDOR(pa->pa_id), 256 1.45 cgd PCI_PRODUCT(pa->pa_id)); 257 1.45 cgd if (qd == NULL) { 258 1.45 cgd printf(" no quirks"); 259 1.45 cgd } else { 260 1.121 christos snprintb(devinfo, sizeof (devinfo), 261 1.82 itojun "\002\001multifn\002singlefn\003skipfunc0" 262 1.82 itojun "\004skipfunc1\005skipfunc2\006skipfunc3" 263 1.82 itojun "\007skipfunc4\010skipfunc5\011skipfunc6" 264 1.121 christos "\012skipfunc7", qd->quirks); 265 1.45 cgd printf(" quirks %s", devinfo); 266 1.45 cgd } 267 1.45 cgd printf(")"); 268 1.37 cgd } 269 1.123 cegger return UNCONF; 270 1.6 mycroft } 271 1.6 mycroft 272 1.160 thorpej static devhandle_t 273 1.160 thorpej pci_bus_get_child_devhandle(struct pci_softc *sc, pcitag_t tag) 274 1.160 thorpej { 275 1.160 thorpej struct pci_bus_get_child_devhandle_args args = { 276 1.160 thorpej .pc = sc->sc_pc, 277 1.160 thorpej .tag = tag, 278 1.160 thorpej }; 279 1.160 thorpej 280 1.162 thorpej if (device_call(sc->sc_dev, PCI_BUS_GET_CHILD_DEVHANDLE(&args)) != 0) { 281 1.160 thorpej /* 282 1.160 thorpej * The call is either not supported or the requested 283 1.160 thorpej * device was not found in the platform device tree. 284 1.160 thorpej * Return an invalid handle. 285 1.160 thorpej */ 286 1.164 thorpej return devhandle_invalid(); 287 1.160 thorpej } 288 1.160 thorpej 289 1.160 thorpej return args.devhandle; 290 1.160 thorpej } 291 1.160 thorpej 292 1.6 mycroft int 293 1.168 riastrad pci_probe_device1(struct pci_softc *sc, pcitag_t tag, 294 1.168 riastrad int (*match)(void *, const struct pci_attach_args *), void *cookie, 295 1.136 dyoung struct pci_attach_args *pap) 296 1.59 thorpej { 297 1.59 thorpej pci_chipset_tag_t pc = sc->sc_pc; 298 1.59 thorpej struct pci_attach_args pa; 299 1.145 matt pcireg_t id, /* csr, */ pciclass, intr, bhlcr, bar, endbar; 300 1.146 knakahar #ifdef __HAVE_PCI_MSI_MSIX 301 1.146 knakahar pcireg_t cap; 302 1.146 knakahar int off; 303 1.146 knakahar #endif 304 1.132 jmcneill int ret, pin, bus, device, function, i, width; 305 1.94 drochner int locs[PCICF_NLOCS]; 306 1.59 thorpej 307 1.59 thorpej pci_decompose_tag(pc, tag, &bus, &device, &function); 308 1.59 thorpej 309 1.87 drochner /* a driver already attached? */ 310 1.117 dyoung if (sc->PCI_SC_DEVICESC(device, function).c_dev != NULL && !match) 311 1.123 cegger return 0; 312 1.87 drochner 313 1.59 thorpej id = pci_conf_read(pc, tag, PCI_ID_REG); 314 1.59 thorpej 315 1.59 thorpej /* Invalid vendor ID value? */ 316 1.59 thorpej if (PCI_VENDOR(id) == PCI_VENDOR_INVALID) 317 1.123 cegger return 0; 318 1.59 thorpej /* XXX Not invalid, but we've done this ~forever. */ 319 1.59 thorpej if (PCI_VENDOR(id) == 0) 320 1.123 cegger return 0; 321 1.59 thorpej 322 1.157 jmcneill bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG); 323 1.157 jmcneill if (PCI_HDRTYPE_TYPE(bhlcr) > 2) 324 1.157 jmcneill return 0; 325 1.157 jmcneill 326 1.157 jmcneill /* csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); */ 327 1.157 jmcneill pciclass = pci_conf_read(pc, tag, PCI_CLASS_REG); 328 1.157 jmcneill 329 1.132 jmcneill /* Collect memory range info */ 330 1.132 jmcneill memset(sc->PCI_SC_DEVICESC(device, function).c_range, 0, 331 1.132 jmcneill sizeof(sc->PCI_SC_DEVICESC(device, function).c_range)); 332 1.132 jmcneill i = 0; 333 1.135 matt switch (PCI_HDRTYPE_TYPE(bhlcr)) { 334 1.138 dyoung case PCI_HDRTYPE_PPB: 335 1.138 dyoung endbar = PCI_MAPREG_PPB_END; 336 1.138 dyoung break; 337 1.138 dyoung case PCI_HDRTYPE_PCB: 338 1.138 dyoung endbar = PCI_MAPREG_PCB_END; 339 1.138 dyoung break; 340 1.138 dyoung default: 341 1.138 dyoung endbar = PCI_MAPREG_END; 342 1.138 dyoung break; 343 1.135 matt } 344 1.135 matt for (bar = PCI_MAPREG_START; bar < endbar; bar += width) { 345 1.132 jmcneill struct pci_range *r; 346 1.134 jmcneill pcireg_t type; 347 1.132 jmcneill 348 1.132 jmcneill width = 4; 349 1.134 jmcneill if (pci_mapreg_probe(pc, tag, bar, &type) == 0) 350 1.134 jmcneill continue; 351 1.134 jmcneill 352 1.132 jmcneill if (PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_MEM) { 353 1.132 jmcneill if (PCI_MAPREG_MEM_TYPE(type) == 354 1.132 jmcneill PCI_MAPREG_MEM_TYPE_64BIT) 355 1.132 jmcneill width = 8; 356 1.132 jmcneill 357 1.132 jmcneill r = &sc->PCI_SC_DEVICESC(device, function).c_range[i++]; 358 1.132 jmcneill if (pci_mapreg_info(pc, tag, bar, type, 359 1.132 jmcneill &r->r_offset, &r->r_size, &r->r_flags) != 0) 360 1.132 jmcneill break; 361 1.133 macallan if ((PCI_VENDOR(id) == PCI_VENDOR_ATI) && (bar == 0x10) 362 1.137 macallan && (r->r_size == 0x1000000)) { 363 1.133 macallan struct pci_range *nr; 364 1.133 macallan /* 365 1.133 macallan * this has to be a mach64 366 1.133 macallan * split things up so each half-aperture can 367 1.133 macallan * be mapped PREFETCHABLE except the last page 368 1.133 macallan * which may contain registers 369 1.133 macallan */ 370 1.133 macallan r->r_size = 0x7ff000; 371 1.133 macallan r->r_flags = BUS_SPACE_MAP_LINEAR | 372 1.133 macallan BUS_SPACE_MAP_PREFETCHABLE; 373 1.133 macallan nr = &sc->PCI_SC_DEVICESC(device, 374 1.133 macallan function).c_range[i++]; 375 1.133 macallan nr->r_offset = r->r_offset + 0x800000; 376 1.133 macallan nr->r_size = 0x7ff000; 377 1.133 macallan nr->r_flags = BUS_SPACE_MAP_LINEAR | 378 1.133 macallan BUS_SPACE_MAP_PREFETCHABLE; 379 1.151 macallan } else if ((PCI_VENDOR(id) == PCI_VENDOR_SILMOTION) && 380 1.151 macallan (PCI_PRODUCT(id) == PCI_PRODUCT_SILMOTION_SM502) && 381 1.151 macallan (bar == 0x10)) { 382 1.151 macallan r->r_flags = BUS_SPACE_MAP_LINEAR | 383 1.151 macallan BUS_SPACE_MAP_PREFETCHABLE; 384 1.133 macallan } 385 1.132 jmcneill } 386 1.132 jmcneill } 387 1.132 jmcneill 388 1.59 thorpej pa.pa_iot = sc->sc_iot; 389 1.59 thorpej pa.pa_memt = sc->sc_memt; 390 1.59 thorpej pa.pa_dmat = sc->sc_dmat; 391 1.80 fvdl pa.pa_dmat64 = sc->sc_dmat64; 392 1.59 thorpej pa.pa_pc = pc; 393 1.63 thorpej pa.pa_bus = bus; 394 1.59 thorpej pa.pa_device = device; 395 1.59 thorpej pa.pa_function = function; 396 1.59 thorpej pa.pa_tag = tag; 397 1.59 thorpej pa.pa_id = id; 398 1.145 matt pa.pa_class = pciclass; 399 1.59 thorpej 400 1.59 thorpej /* 401 1.59 thorpej * Set up memory, I/O enable, and PCI command flags 402 1.59 thorpej * as appropriate. 403 1.59 thorpej */ 404 1.59 thorpej pa.pa_flags = sc->sc_flags; 405 1.59 thorpej 406 1.59 thorpej /* 407 1.59 thorpej * If the cache line size is not configured, then 408 1.59 thorpej * clear the MRL/MRM/MWI command-ok flags. 409 1.59 thorpej */ 410 1.138 dyoung if (PCI_CACHELINE(bhlcr) == 0) { 411 1.59 thorpej pa.pa_flags &= ~(PCI_FLAGS_MRL_OKAY| 412 1.59 thorpej PCI_FLAGS_MRM_OKAY|PCI_FLAGS_MWI_OKAY); 413 1.138 dyoung } 414 1.59 thorpej 415 1.64 sommerfe if (sc->sc_bridgetag == NULL) { 416 1.59 thorpej pa.pa_intrswiz = 0; 417 1.59 thorpej pa.pa_intrtag = tag; 418 1.59 thorpej } else { 419 1.59 thorpej pa.pa_intrswiz = sc->sc_intrswiz + device; 420 1.59 thorpej pa.pa_intrtag = sc->sc_intrtag; 421 1.59 thorpej } 422 1.81 itojun 423 1.81 itojun intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG); 424 1.81 itojun 425 1.59 thorpej pin = PCI_INTERRUPT_PIN(intr); 426 1.65 sommerfe pa.pa_rawintrpin = pin; 427 1.59 thorpej if (pin == PCI_INTERRUPT_PIN_NONE) { 428 1.59 thorpej /* no interrupt */ 429 1.59 thorpej pa.pa_intrpin = 0; 430 1.59 thorpej } else { 431 1.59 thorpej /* 432 1.59 thorpej * swizzle it based on the number of busses we're 433 1.59 thorpej * behind and our device number. 434 1.59 thorpej */ 435 1.59 thorpej pa.pa_intrpin = /* XXX */ 436 1.59 thorpej ((pin + pa.pa_intrswiz - 1) % 4) + 1; 437 1.59 thorpej } 438 1.59 thorpej pa.pa_intrline = PCI_INTERRUPT_LINE(intr); 439 1.59 thorpej 440 1.160 thorpej devhandle_t devhandle = pci_bus_get_child_devhandle(sc, pa.pa_tag); 441 1.160 thorpej 442 1.146 knakahar #ifdef __HAVE_PCI_MSI_MSIX 443 1.146 knakahar if (pci_get_ht_capability(pc, tag, PCI_HT_CAP_MSIMAP, &off, &cap)) { 444 1.146 knakahar /* 445 1.146 knakahar * XXX Should we enable MSI mapping ourselves on 446 1.146 knakahar * systems that have it disabled? 447 1.146 knakahar */ 448 1.146 knakahar if (cap & PCI_HT_MSI_ENABLED) { 449 1.146 knakahar uint64_t addr; 450 1.146 knakahar if ((cap & PCI_HT_MSI_FIXED) == 0) { 451 1.146 knakahar addr = pci_conf_read(pc, tag, 452 1.146 knakahar off + PCI_HT_MSI_ADDR_LO); 453 1.146 knakahar addr |= (uint64_t)pci_conf_read(pc, tag, 454 1.146 knakahar off + PCI_HT_MSI_ADDR_HI) << 32; 455 1.146 knakahar } else 456 1.146 knakahar addr = PCI_HT_MSI_FIXED_ADDR; 457 1.146 knakahar 458 1.146 knakahar /* 459 1.146 knakahar * XXX This will fail to enable MSI on systems 460 1.146 knakahar * that don't use the canonical address. 461 1.146 knakahar */ 462 1.146 knakahar if (addr == PCI_HT_MSI_FIXED_ADDR) { 463 1.146 knakahar pa.pa_flags |= PCI_FLAGS_MSI_OKAY; 464 1.146 knakahar pa.pa_flags |= PCI_FLAGS_MSIX_OKAY; 465 1.150 knakahar } else 466 1.150 knakahar aprint_verbose_dev(sc->sc_dev, 467 1.150 knakahar "HyperTransport MSI mapping is not supported yet. Disable MSI/MSI-X.\n"); 468 1.146 knakahar } 469 1.146 knakahar } 470 1.146 knakahar #endif 471 1.146 knakahar 472 1.59 thorpej if (match != NULL) { 473 1.168 riastrad ret = (*match)(cookie, &pa); 474 1.59 thorpej if (ret != 0 && pap != NULL) 475 1.59 thorpej *pap = pa; 476 1.59 thorpej } else { 477 1.117 dyoung struct pci_child *c; 478 1.94 drochner locs[PCICF_DEV] = device; 479 1.94 drochner locs[PCICF_FUNCTION] = function; 480 1.87 drochner 481 1.117 dyoung c = &sc->PCI_SC_DEVICESC(device, function); 482 1.117 dyoung pci_conf_capture(pc, tag, &c->c_conf); 483 1.117 dyoung if (pci_get_powerstate(pc, tag, &c->c_powerstate) == 0) 484 1.117 dyoung c->c_psok = true; 485 1.117 dyoung else 486 1.117 dyoung c->c_psok = false; 487 1.124 dyoung 488 1.159 thorpej c->c_dev = config_found(sc->sc_dev, &pa, pciprint, 489 1.161 thorpej CFARGS(.submatch = config_stdsubmatch, 490 1.161 thorpej .locators = locs, 491 1.161 thorpej .devhandle = devhandle)); 492 1.124 dyoung 493 1.124 dyoung ret = (c->c_dev != NULL); 494 1.59 thorpej } 495 1.59 thorpej 496 1.123 cegger return ret; 497 1.59 thorpej } 498 1.59 thorpej 499 1.116 dyoung void 500 1.114 dyoung pcidevdetached(device_t self, device_t child) 501 1.87 drochner { 502 1.117 dyoung struct pci_softc *sc = device_private(self); 503 1.87 drochner int d, f; 504 1.117 dyoung pcitag_t tag; 505 1.117 dyoung struct pci_child *c; 506 1.87 drochner 507 1.114 dyoung d = device_locator(child, PCICF_DEV); 508 1.114 dyoung f = device_locator(child, PCICF_FUNCTION); 509 1.87 drochner 510 1.117 dyoung c = &sc->PCI_SC_DEVICESC(d, f); 511 1.117 dyoung 512 1.117 dyoung KASSERT(c->c_dev == child); 513 1.87 drochner 514 1.117 dyoung tag = pci_make_tag(sc->sc_pc, sc->sc_bus, d, f); 515 1.117 dyoung if (c->c_psok) 516 1.117 dyoung pci_set_powerstate(sc->sc_pc, tag, c->c_powerstate); 517 1.117 dyoung pci_conf_restore(sc->sc_pc, tag, &c->c_conf); 518 1.117 dyoung c->c_dev = NULL; 519 1.87 drochner } 520 1.87 drochner 521 1.122 dyoung CFATTACH_DECL3_NEW(pci, sizeof(struct pci_softc), 522 1.122 dyoung pcimatch, pciattach, pcidetach, NULL, pcirescan, pcidevdetached, 523 1.122 dyoung DVF_DETACH_SHUTDOWN); 524 1.107 jmcneill 525 1.59 thorpej int 526 1.93 thorpej pci_get_capability(pci_chipset_tag_t pc, pcitag_t tag, int capid, 527 1.93 thorpej int *offset, pcireg_t *value) 528 1.40 drochner { 529 1.40 drochner pcireg_t reg; 530 1.40 drochner unsigned int ofs; 531 1.40 drochner 532 1.40 drochner reg = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); 533 1.40 drochner if (!(reg & PCI_STATUS_CAPLIST_SUPPORT)) 534 1.123 cegger return 0; 535 1.40 drochner 536 1.48 kleink /* Determine the Capability List Pointer register to start with. */ 537 1.47 kleink reg = pci_conf_read(pc, tag, PCI_BHLC_REG); 538 1.47 kleink switch (PCI_HDRTYPE_TYPE(reg)) { 539 1.47 kleink case 0: /* standard device header */ 540 1.104 joerg case 1: /* PCI-PCI bridge header */ 541 1.47 kleink ofs = PCI_CAPLISTPTR_REG; 542 1.47 kleink break; 543 1.47 kleink case 2: /* PCI-CardBus Bridge header */ 544 1.47 kleink ofs = PCI_CARDBUS_CAPLISTPTR_REG; 545 1.47 kleink break; 546 1.47 kleink default: 547 1.123 cegger return 0; 548 1.47 kleink } 549 1.47 kleink 550 1.47 kleink ofs = PCI_CAPLIST_PTR(pci_conf_read(pc, tag, ofs)); 551 1.40 drochner while (ofs != 0) { 552 1.119 joerg if ((ofs & 3) || (ofs < 0x40)) { 553 1.119 joerg int bus, device, function; 554 1.119 joerg 555 1.119 joerg pci_decompose_tag(pc, tag, &bus, &device, &function); 556 1.119 joerg 557 1.119 joerg printf("Skipping broken PCI header on %d:%d:%d\n", 558 1.119 joerg bus, device, function); 559 1.119 joerg break; 560 1.119 joerg } 561 1.40 drochner reg = pci_conf_read(pc, tag, ofs); 562 1.40 drochner if (PCI_CAPLIST_CAP(reg) == capid) { 563 1.40 drochner if (offset) 564 1.40 drochner *offset = ofs; 565 1.40 drochner if (value) 566 1.40 drochner *value = reg; 567 1.123 cegger return 1; 568 1.40 drochner } 569 1.40 drochner ofs = PCI_CAPLIST_NEXT(reg); 570 1.40 drochner } 571 1.40 drochner 572 1.123 cegger return 0; 573 1.55 fvdl } 574 1.55 fvdl 575 1.55 fvdl int 576 1.146 knakahar pci_get_ht_capability(pci_chipset_tag_t pc, pcitag_t tag, int capid, 577 1.146 knakahar int *offset, pcireg_t *value) 578 1.146 knakahar { 579 1.146 knakahar pcireg_t reg; 580 1.146 knakahar unsigned int ofs; 581 1.146 knakahar 582 1.146 knakahar if (pci_get_capability(pc, tag, PCI_CAP_LDT, &ofs, NULL) == 0) 583 1.146 knakahar return 0; 584 1.146 knakahar 585 1.146 knakahar while (ofs != 0) { 586 1.146 knakahar #ifdef DIAGNOSTIC 587 1.146 knakahar if ((ofs & 3) || (ofs < 0x40)) 588 1.146 knakahar panic("pci_get_ht_capability"); 589 1.146 knakahar #endif 590 1.146 knakahar reg = pci_conf_read(pc, tag, ofs); 591 1.146 knakahar if (PCI_HT_CAP(reg) == capid) { 592 1.146 knakahar if (offset) 593 1.146 knakahar *offset = ofs; 594 1.146 knakahar if (value) 595 1.146 knakahar *value = reg; 596 1.146 knakahar return 1; 597 1.146 knakahar } 598 1.146 knakahar ofs = PCI_CAPLIST_NEXT(reg); 599 1.146 knakahar } 600 1.146 knakahar 601 1.146 knakahar return 0; 602 1.146 knakahar } 603 1.146 knakahar 604 1.147 msaitoh /* 605 1.147 msaitoh * return number of the devices's MSI vectors 606 1.147 msaitoh * return 0 if the device does not support MSI 607 1.147 msaitoh */ 608 1.147 msaitoh int 609 1.147 msaitoh pci_msi_count(pci_chipset_tag_t pc, pcitag_t tag) 610 1.147 msaitoh { 611 1.147 msaitoh pcireg_t reg; 612 1.147 msaitoh uint32_t mmc; 613 1.147 msaitoh int count, offset; 614 1.147 msaitoh 615 1.147 msaitoh if (pci_get_capability(pc, tag, PCI_CAP_MSI, &offset, NULL) == 0) 616 1.147 msaitoh return 0; 617 1.147 msaitoh 618 1.147 msaitoh reg = pci_conf_read(pc, tag, offset + PCI_MSI_CTL); 619 1.147 msaitoh mmc = PCI_MSI_CTL_MMC(reg); 620 1.147 msaitoh count = 1 << mmc; 621 1.147 msaitoh if (count > PCI_MSI_MAX_VECTORS) { 622 1.147 msaitoh aprint_error("detect an illegal device! The device use reserved MMC values.\n"); 623 1.147 msaitoh return 0; 624 1.147 msaitoh } 625 1.147 msaitoh 626 1.147 msaitoh return count; 627 1.147 msaitoh } 628 1.147 msaitoh 629 1.147 msaitoh /* 630 1.147 msaitoh * return number of the devices's MSI-X vectors 631 1.147 msaitoh * return 0 if the device does not support MSI-X 632 1.147 msaitoh */ 633 1.147 msaitoh int 634 1.147 msaitoh pci_msix_count(pci_chipset_tag_t pc, pcitag_t tag) 635 1.147 msaitoh { 636 1.147 msaitoh pcireg_t reg; 637 1.147 msaitoh int offset; 638 1.147 msaitoh 639 1.147 msaitoh if (pci_get_capability(pc, tag, PCI_CAP_MSIX, &offset, NULL) == 0) 640 1.147 msaitoh return 0; 641 1.147 msaitoh 642 1.147 msaitoh reg = pci_conf_read(pc, tag, offset + PCI_MSIX_CTL); 643 1.147 msaitoh 644 1.147 msaitoh return PCI_MSIX_CTL_TBLSIZE(reg); 645 1.147 msaitoh } 646 1.147 msaitoh 647 1.146 knakahar int 648 1.149 msaitoh pci_get_ext_capability(pci_chipset_tag_t pc, pcitag_t tag, int capid, 649 1.149 msaitoh int *offset, pcireg_t *value) 650 1.149 msaitoh { 651 1.149 msaitoh pcireg_t reg; 652 1.149 msaitoh unsigned int ofs; 653 1.149 msaitoh 654 1.149 msaitoh /* Only supported for PCI-express devices */ 655 1.149 msaitoh if (!pci_get_capability(pc, tag, PCI_CAP_PCIEXPRESS, NULL, NULL)) 656 1.149 msaitoh return 0; 657 1.149 msaitoh 658 1.149 msaitoh ofs = PCI_EXTCAPLIST_BASE; 659 1.149 msaitoh reg = pci_conf_read(pc, tag, ofs); 660 1.149 msaitoh if (reg == 0xffffffff || reg == 0) 661 1.149 msaitoh return 0; 662 1.149 msaitoh 663 1.149 msaitoh for (;;) { 664 1.149 msaitoh #ifdef DIAGNOSTIC 665 1.149 msaitoh if ((ofs & 3) || ofs < PCI_EXTCAPLIST_BASE) 666 1.149 msaitoh panic("%s: invalid offset %u", __func__, ofs); 667 1.149 msaitoh #endif 668 1.149 msaitoh if (PCI_EXTCAPLIST_CAP(reg) == capid) { 669 1.149 msaitoh if (offset != NULL) 670 1.149 msaitoh *offset = ofs; 671 1.149 msaitoh if (value != NULL) 672 1.149 msaitoh *value = reg; 673 1.149 msaitoh return 1; 674 1.149 msaitoh } 675 1.149 msaitoh ofs = PCI_EXTCAPLIST_NEXT(reg); 676 1.149 msaitoh if (ofs == 0) 677 1.149 msaitoh break; 678 1.149 msaitoh reg = pci_conf_read(pc, tag, ofs); 679 1.149 msaitoh } 680 1.149 msaitoh 681 1.149 msaitoh return 0; 682 1.149 msaitoh } 683 1.149 msaitoh 684 1.168 riastrad static int 685 1.168 riastrad pci_match_cookieless(void *cookie, const struct pci_attach_args *pa) 686 1.168 riastrad { 687 1.168 riastrad int (*match)(const struct pci_attach_args *) = cookie; 688 1.168 riastrad 689 1.168 riastrad return (*match)(pa); 690 1.168 riastrad } 691 1.168 riastrad 692 1.149 msaitoh int 693 1.55 fvdl pci_find_device(struct pci_attach_args *pa, 694 1.168 riastrad int (*match)(const struct pci_attach_args *)) 695 1.168 riastrad { 696 1.168 riastrad void *cookie = match; 697 1.168 riastrad 698 1.168 riastrad return (match == NULL 699 1.168 riastrad ? pci_find_device1(pa, NULL, NULL) 700 1.168 riastrad : pci_find_device1(pa, &pci_match_cookieless, cookie)); 701 1.168 riastrad } 702 1.168 riastrad 703 1.168 riastrad int 704 1.168 riastrad pci_find_device1(struct pci_attach_args *pa, 705 1.168 riastrad int (*match)(void *, const struct pci_attach_args *), void *cookie) 706 1.55 fvdl { 707 1.59 thorpej extern struct cfdriver pci_cd; 708 1.114 dyoung device_t pcidev; 709 1.55 fvdl int i; 710 1.87 drochner static const int wildcard[2] = { 711 1.87 drochner PCICF_DEV_DEFAULT, 712 1.87 drochner PCICF_FUNCTION_DEFAULT 713 1.87 drochner }; 714 1.55 fvdl 715 1.55 fvdl for (i = 0; i < pci_cd.cd_ndevs; i++) { 716 1.118 cegger pcidev = device_lookup(&pci_cd, i); 717 1.59 thorpej if (pcidev != NULL && 718 1.168 riastrad pci_enumerate_bus1(device_private(pcidev), wildcard, 719 1.168 riastrad match, cookie, pa) != 0) 720 1.123 cegger return 1; 721 1.59 thorpej } 722 1.123 cegger return 0; 723 1.59 thorpej } 724 1.59 thorpej 725 1.168 riastrad int 726 1.168 riastrad pci_enumerate_bus(struct pci_softc *sc, const int *locators, 727 1.168 riastrad int (*match)(const struct pci_attach_args *), struct pci_attach_args *pap) 728 1.168 riastrad { 729 1.168 riastrad void *cookie = match; 730 1.168 riastrad 731 1.168 riastrad return (match == NULL 732 1.168 riastrad ? pci_enumerate_bus1(sc, locators, NULL, NULL, pap) 733 1.168 riastrad : pci_enumerate_bus1(sc, locators, &pci_match_cookieless, cookie, 734 1.168 riastrad pap)); 735 1.168 riastrad } 736 1.168 riastrad 737 1.168 riastrad #ifndef PCI_MACHDEP_ENUMERATE_BUS1 738 1.59 thorpej /* 739 1.59 thorpej * Generic PCI bus enumeration routine. Used unless machine-dependent 740 1.59 thorpej * code needs to provide something else. 741 1.59 thorpej */ 742 1.59 thorpej int 743 1.168 riastrad pci_enumerate_bus1(struct pci_softc *sc, const int *locators, 744 1.168 riastrad int (*match)(void *, const struct pci_attach_args *), void *cookie, 745 1.168 riastrad struct pci_attach_args *pap) 746 1.59 thorpej { 747 1.59 thorpej pci_chipset_tag_t pc = sc->sc_pc; 748 1.59 thorpej int device, function, nfunctions, ret; 749 1.59 thorpej const struct pci_quirkdata *qd; 750 1.59 thorpej pcireg_t id, bhlcr; 751 1.59 thorpej pcitag_t tag; 752 1.141 dyoung uint8_t devs[32]; 753 1.141 dyoung int i, n; 754 1.141 dyoung 755 1.152 msaitoh device_t bridgedev; 756 1.152 msaitoh bool arien = false; 757 1.156 jmcneill bool downstream_port = false; 758 1.152 msaitoh 759 1.156 jmcneill /* Check PCIe ARI and port type */ 760 1.152 msaitoh bridgedev = device_parent(sc->sc_dev); 761 1.152 msaitoh if (device_is_a(bridgedev, "ppb")) { 762 1.152 msaitoh struct ppb_softc *ppbsc = device_private(bridgedev); 763 1.152 msaitoh pci_chipset_tag_t ppbpc = ppbsc->sc_pc; 764 1.152 msaitoh pcitag_t ppbtag = ppbsc->sc_tag; 765 1.156 jmcneill pcireg_t pciecap, capreg, reg; 766 1.152 msaitoh 767 1.152 msaitoh if (pci_get_capability(ppbpc, ppbtag, PCI_CAP_PCIEXPRESS, 768 1.156 jmcneill &pciecap, &capreg) != 0) { 769 1.156 jmcneill switch (PCIE_XCAP_TYPE(capreg)) { 770 1.163 msaitoh case PCIE_XCAP_TYPE_RP: 771 1.156 jmcneill case PCIE_XCAP_TYPE_DOWN: 772 1.156 jmcneill case PCIE_XCAP_TYPE_PCI2PCIE: 773 1.156 jmcneill downstream_port = true; 774 1.156 jmcneill break; 775 1.156 jmcneill } 776 1.156 jmcneill 777 1.152 msaitoh reg = pci_conf_read(ppbpc, ppbtag, pciecap 778 1.152 msaitoh + PCIE_DCSR2); 779 1.152 msaitoh if ((reg & PCIE_DCSR2_ARI_FWD) != 0) 780 1.152 msaitoh arien = true; 781 1.152 msaitoh } 782 1.152 msaitoh } 783 1.152 msaitoh 784 1.141 dyoung n = pci_bus_devorder(sc->sc_pc, sc->sc_bus, devs, __arraycount(devs)); 785 1.156 jmcneill if (downstream_port) { 786 1.156 jmcneill /* PCIe downstream ports only have a single child device */ 787 1.156 jmcneill n = 1; 788 1.156 jmcneill } 789 1.156 jmcneill 790 1.141 dyoung for (i = 0; i < n; i++) { 791 1.141 dyoung device = devs[i]; 792 1.59 thorpej 793 1.87 drochner if ((locators[PCICF_DEV] != PCICF_DEV_DEFAULT) && 794 1.87 drochner (locators[PCICF_DEV] != device)) 795 1.87 drochner continue; 796 1.87 drochner 797 1.59 thorpej tag = pci_make_tag(pc, sc->sc_bus, device, 0); 798 1.81 itojun 799 1.59 thorpej id = pci_conf_read(pc, tag, PCI_ID_REG); 800 1.59 thorpej 801 1.59 thorpej /* Invalid vendor ID value? */ 802 1.59 thorpej if (PCI_VENDOR(id) == PCI_VENDOR_INVALID) 803 1.59 thorpej continue; 804 1.59 thorpej /* XXX Not invalid, but we've done this ~forever. */ 805 1.59 thorpej if (PCI_VENDOR(id) == 0) 806 1.59 thorpej continue; 807 1.59 thorpej 808 1.155 jmcneill bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG); 809 1.155 jmcneill if (PCI_HDRTYPE_TYPE(bhlcr) > 2) 810 1.155 jmcneill continue; 811 1.155 jmcneill 812 1.59 thorpej qd = pci_lookup_quirkdata(PCI_VENDOR(id), PCI_PRODUCT(id)); 813 1.59 thorpej 814 1.81 itojun if (qd != NULL && 815 1.81 itojun (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0) 816 1.59 thorpej nfunctions = 8; 817 1.81 itojun else if (qd != NULL && 818 1.81 itojun (qd->quirks & PCI_QUIRK_MONOFUNCTION) != 0) 819 1.81 itojun nfunctions = 1; 820 1.152 msaitoh else if (arien) 821 1.152 msaitoh nfunctions = 8; /* Scan all if ARI is enabled */ 822 1.59 thorpej else 823 1.81 itojun nfunctions = PCI_HDRTYPE_MULTIFN(bhlcr) ? 8 : 1; 824 1.59 thorpej 825 1.143 matt #ifdef __PCI_DEV_FUNCORDER 826 1.143 matt char funcs[8]; 827 1.143 matt int j; 828 1.143 matt for (j = 0; j < nfunctions; j++) { 829 1.143 matt funcs[j] = j; 830 1.143 matt } 831 1.143 matt if (j < __arraycount(funcs)) 832 1.143 matt funcs[j] = -1; 833 1.143 matt if (nfunctions > 1) { 834 1.143 matt pci_dev_funcorder(sc->sc_pc, sc->sc_bus, device, 835 1.143 matt nfunctions, funcs); 836 1.143 matt } 837 1.143 matt for (j = 0; 838 1.143 matt j < 8 && (function = funcs[j]) < 8 && function >= 0; 839 1.143 matt j++) { 840 1.143 matt #else 841 1.59 thorpej for (function = 0; function < nfunctions; function++) { 842 1.143 matt #endif 843 1.87 drochner if ((locators[PCICF_FUNCTION] != PCICF_FUNCTION_DEFAULT) 844 1.87 drochner && (locators[PCICF_FUNCTION] != function)) 845 1.87 drochner continue; 846 1.87 drochner 847 1.81 itojun if (qd != NULL && 848 1.81 itojun (qd->quirks & PCI_QUIRK_SKIP_FUNC(function)) != 0) 849 1.81 itojun continue; 850 1.59 thorpej tag = pci_make_tag(pc, sc->sc_bus, device, function); 851 1.168 riastrad ret = pci_probe_device1(sc, tag, match, cookie, pap); 852 1.59 thorpej if (match != NULL && ret != 0) 853 1.123 cegger return ret; 854 1.59 thorpej } 855 1.55 fvdl } 856 1.123 cegger return 0; 857 1.66 tshiozak } 858 1.168 riastrad #endif /* PCI_MACHDEP_ENUMERATE_BUS1 */ 859 1.66 tshiozak 860 1.77 thorpej 861 1.77 thorpej /* 862 1.77 thorpej * Vital Product Data (PCI 2.2) 863 1.77 thorpej */ 864 1.77 thorpej 865 1.77 thorpej int 866 1.77 thorpej pci_vpd_read(pci_chipset_tag_t pc, pcitag_t tag, int offset, int count, 867 1.77 thorpej pcireg_t *data) 868 1.77 thorpej { 869 1.77 thorpej uint32_t reg; 870 1.77 thorpej int ofs, i, j; 871 1.77 thorpej 872 1.77 thorpej KASSERT(data != NULL); 873 1.77 thorpej KASSERT((offset + count) < 0x7fff); 874 1.77 thorpej 875 1.77 thorpej if (pci_get_capability(pc, tag, PCI_CAP_VPD, &ofs, ®) == 0) 876 1.123 cegger return 1; 877 1.77 thorpej 878 1.77 thorpej for (i = 0; i < count; offset += sizeof(*data), i++) { 879 1.77 thorpej reg &= 0x0000ffff; 880 1.77 thorpej reg &= ~PCI_VPD_OPFLAG; 881 1.77 thorpej reg |= PCI_VPD_ADDRESS(offset); 882 1.77 thorpej pci_conf_write(pc, tag, ofs, reg); 883 1.77 thorpej 884 1.77 thorpej /* 885 1.77 thorpej * PCI 2.2 does not specify how long we should poll 886 1.77 thorpej * for completion nor whether the operation can fail. 887 1.77 thorpej */ 888 1.77 thorpej j = 0; 889 1.77 thorpej do { 890 1.77 thorpej if (j++ == 20) 891 1.123 cegger return 1; 892 1.77 thorpej delay(4); 893 1.77 thorpej reg = pci_conf_read(pc, tag, ofs); 894 1.77 thorpej } while ((reg & PCI_VPD_OPFLAG) == 0); 895 1.77 thorpej data[i] = pci_conf_read(pc, tag, PCI_VPD_DATAREG(ofs)); 896 1.77 thorpej } 897 1.77 thorpej 898 1.123 cegger return 0; 899 1.77 thorpej } 900 1.77 thorpej 901 1.77 thorpej int 902 1.77 thorpej pci_vpd_write(pci_chipset_tag_t pc, pcitag_t tag, int offset, int count, 903 1.77 thorpej pcireg_t *data) 904 1.77 thorpej { 905 1.77 thorpej pcireg_t reg; 906 1.77 thorpej int ofs, i, j; 907 1.77 thorpej 908 1.77 thorpej KASSERT(data != NULL); 909 1.77 thorpej KASSERT((offset + count) < 0x7fff); 910 1.77 thorpej 911 1.77 thorpej if (pci_get_capability(pc, tag, PCI_CAP_VPD, &ofs, ®) == 0) 912 1.123 cegger return 1; 913 1.77 thorpej 914 1.77 thorpej for (i = 0; i < count; offset += sizeof(*data), i++) { 915 1.77 thorpej pci_conf_write(pc, tag, PCI_VPD_DATAREG(ofs), data[i]); 916 1.77 thorpej 917 1.77 thorpej reg &= 0x0000ffff; 918 1.79 thorpej reg |= PCI_VPD_OPFLAG; 919 1.77 thorpej reg |= PCI_VPD_ADDRESS(offset); 920 1.77 thorpej pci_conf_write(pc, tag, ofs, reg); 921 1.77 thorpej 922 1.77 thorpej /* 923 1.77 thorpej * PCI 2.2 does not specify how long we should poll 924 1.77 thorpej * for completion nor whether the operation can fail. 925 1.77 thorpej */ 926 1.77 thorpej j = 0; 927 1.77 thorpej do { 928 1.77 thorpej if (j++ == 20) 929 1.123 cegger return 1; 930 1.77 thorpej delay(1); 931 1.77 thorpej reg = pci_conf_read(pc, tag, ofs); 932 1.79 thorpej } while (reg & PCI_VPD_OPFLAG); 933 1.77 thorpej } 934 1.77 thorpej 935 1.123 cegger return 0; 936 1.80 fvdl } 937 1.80 fvdl 938 1.80 fvdl int 939 1.136 dyoung pci_dma64_available(const struct pci_attach_args *pa) 940 1.92 perry { 941 1.80 fvdl #ifdef _PCI_HAVE_DMA64 942 1.120 bouyer if (BUS_DMA_TAG_VALID(pa->pa_dmat64)) 943 1.80 fvdl return 1; 944 1.80 fvdl #endif 945 1.80 fvdl return 0; 946 1.1 mycroft } 947 1.90 jmcneill 948 1.90 jmcneill void 949 1.90 jmcneill pci_conf_capture(pci_chipset_tag_t pc, pcitag_t tag, 950 1.90 jmcneill struct pci_conf_state *pcs) 951 1.90 jmcneill { 952 1.90 jmcneill int off; 953 1.90 jmcneill 954 1.90 jmcneill for (off = 0; off < 16; off++) 955 1.90 jmcneill pcs->reg[off] = pci_conf_read(pc, tag, (off * 4)); 956 1.90 jmcneill 957 1.153 msaitoh /* For PCI-X */ 958 1.153 msaitoh if (pci_get_capability(pc, tag, PCI_CAP_PCIX, &off, NULL) != 0) 959 1.153 msaitoh pcs->x_csr = pci_conf_read(pc, tag, off + PCIX_CMD); 960 1.153 msaitoh 961 1.153 msaitoh /* For PCIe */ 962 1.153 msaitoh if (pci_get_capability(pc, tag, PCI_CAP_PCIEXPRESS, &off, NULL) != 0) { 963 1.153 msaitoh pcireg_t xcap = pci_conf_read(pc, tag, off + PCIE_XCAP); 964 1.153 msaitoh unsigned int devtype; 965 1.153 msaitoh 966 1.153 msaitoh devtype = PCIE_XCAP_TYPE(xcap); 967 1.153 msaitoh pcs->e_dcr = (uint16_t)pci_conf_read(pc, tag, off + PCIE_DCSR); 968 1.153 msaitoh 969 1.153 msaitoh if (PCIE_HAS_LINKREGS(devtype)) 970 1.153 msaitoh pcs->e_lcr = (uint16_t)pci_conf_read(pc, tag, 971 1.153 msaitoh off + PCIE_LCSR); 972 1.153 msaitoh 973 1.153 msaitoh if ((xcap & PCIE_XCAP_SI) != 0) 974 1.153 msaitoh pcs->e_slcr = (uint16_t)pci_conf_read(pc, tag, 975 1.153 msaitoh off + PCIE_SLCSR); 976 1.153 msaitoh 977 1.153 msaitoh if (PCIE_HAS_ROOTREGS(devtype)) 978 1.153 msaitoh pcs->e_rcr = (uint16_t)pci_conf_read(pc, tag, 979 1.153 msaitoh off + PCIE_RCR); 980 1.153 msaitoh 981 1.153 msaitoh if (__SHIFTOUT(xcap, PCIE_XCAP_VER_MASK) >= 2) { 982 1.153 msaitoh pcs->e_dcr2 = (uint16_t)pci_conf_read(pc, tag, 983 1.153 msaitoh off + PCIE_DCSR2); 984 1.153 msaitoh 985 1.153 msaitoh if (PCIE_HAS_LINKREGS(devtype)) 986 1.153 msaitoh pcs->e_lcr2 = (uint16_t)pci_conf_read(pc, tag, 987 1.153 msaitoh off + PCIE_LCSR2); 988 1.153 msaitoh 989 1.153 msaitoh /* XXX PCIE_SLCSR2 (It's reserved by the PCIe spec) */ 990 1.153 msaitoh } 991 1.153 msaitoh } 992 1.153 msaitoh 993 1.153 msaitoh /* For MSI */ 994 1.153 msaitoh if (pci_get_capability(pc, tag, PCI_CAP_MSI, &off, NULL) != 0) { 995 1.153 msaitoh bool bit64, pvmask; 996 1.158 skrll 997 1.153 msaitoh pcs->msi_ctl = pci_conf_read(pc, tag, off + PCI_MSI_CTL); 998 1.153 msaitoh 999 1.153 msaitoh bit64 = pcs->msi_ctl & PCI_MSI_CTL_64BIT_ADDR; 1000 1.153 msaitoh pvmask = pcs->msi_ctl & PCI_MSI_CTL_PERVEC_MASK; 1001 1.153 msaitoh 1002 1.153 msaitoh /* Address */ 1003 1.153 msaitoh pcs->msi_maddr = pci_conf_read(pc, tag, off + PCI_MSI_MADDR); 1004 1.153 msaitoh if (bit64) 1005 1.153 msaitoh pcs->msi_maddr64_hi = pci_conf_read(pc, tag, 1006 1.153 msaitoh off + PCI_MSI_MADDR64_HI); 1007 1.153 msaitoh 1008 1.153 msaitoh /* Data */ 1009 1.153 msaitoh pcs->msi_mdata = pci_conf_read(pc, tag, 1010 1.153 msaitoh off + (bit64 ? PCI_MSI_MDATA64 : PCI_MSI_MDATA)); 1011 1.153 msaitoh 1012 1.153 msaitoh /* Per-vector masking */ 1013 1.153 msaitoh if (pvmask) 1014 1.153 msaitoh pcs->msi_mask = pci_conf_read(pc, tag, 1015 1.153 msaitoh off + (bit64 ? PCI_MSI_MASK64 : PCI_MSI_MASK)); 1016 1.153 msaitoh } 1017 1.153 msaitoh 1018 1.153 msaitoh /* For MSI-X */ 1019 1.153 msaitoh if (pci_get_capability(pc, tag, PCI_CAP_MSIX, &off, NULL) != 0) 1020 1.153 msaitoh pcs->msix_ctl = pci_conf_read(pc, tag, off + PCI_MSIX_CTL); 1021 1.90 jmcneill } 1022 1.90 jmcneill 1023 1.90 jmcneill void 1024 1.90 jmcneill pci_conf_restore(pci_chipset_tag_t pc, pcitag_t tag, 1025 1.90 jmcneill struct pci_conf_state *pcs) 1026 1.90 jmcneill { 1027 1.90 jmcneill int off; 1028 1.107 jmcneill pcireg_t val; 1029 1.90 jmcneill 1030 1.107 jmcneill for (off = 15; off >= 0; off--) { 1031 1.107 jmcneill val = pci_conf_read(pc, tag, (off * 4)); 1032 1.107 jmcneill if (val != pcs->reg[off]) 1033 1.107 jmcneill pci_conf_write(pc, tag, (off * 4), pcs->reg[off]); 1034 1.107 jmcneill } 1035 1.90 jmcneill 1036 1.153 msaitoh /* For PCI-X */ 1037 1.153 msaitoh if (pci_get_capability(pc, tag, PCI_CAP_PCIX, &off, NULL) != 0) 1038 1.153 msaitoh pci_conf_write(pc, tag, off + PCIX_CMD, pcs->x_csr); 1039 1.153 msaitoh 1040 1.153 msaitoh /* For PCIe */ 1041 1.153 msaitoh if (pci_get_capability(pc, tag, PCI_CAP_PCIEXPRESS, &off, NULL) != 0) { 1042 1.153 msaitoh pcireg_t xcap = pci_conf_read(pc, tag, off + PCIE_XCAP); 1043 1.153 msaitoh unsigned int devtype; 1044 1.153 msaitoh 1045 1.153 msaitoh devtype = PCIE_XCAP_TYPE(xcap); 1046 1.153 msaitoh pci_conf_write(pc, tag, off + PCIE_DCSR, pcs->e_dcr); 1047 1.153 msaitoh 1048 1.153 msaitoh /* 1049 1.153 msaitoh * PCIe capability is variable sized. To not to write the next 1050 1.153 msaitoh * area, check the existence of each register. 1051 1.153 msaitoh */ 1052 1.153 msaitoh if (PCIE_HAS_LINKREGS(devtype)) 1053 1.153 msaitoh pci_conf_write(pc, tag, off + PCIE_LCSR, pcs->e_lcr); 1054 1.153 msaitoh 1055 1.153 msaitoh if ((xcap & PCIE_XCAP_SI) != 0) 1056 1.153 msaitoh pci_conf_write(pc, tag, off + PCIE_SLCSR, pcs->e_slcr); 1057 1.153 msaitoh 1058 1.153 msaitoh if (PCIE_HAS_ROOTREGS(devtype)) 1059 1.153 msaitoh pci_conf_write(pc, tag, off + PCIE_RCR, pcs->e_rcr); 1060 1.153 msaitoh 1061 1.153 msaitoh if (__SHIFTOUT(xcap, PCIE_XCAP_VER_MASK) >= 2) { 1062 1.153 msaitoh pci_conf_write(pc, tag, off + PCIE_DCSR2, pcs->e_dcr2); 1063 1.153 msaitoh 1064 1.153 msaitoh if (PCIE_HAS_LINKREGS(devtype)) 1065 1.153 msaitoh pci_conf_write(pc, tag, off + PCIE_LCSR2, 1066 1.153 msaitoh pcs->e_lcr2); 1067 1.153 msaitoh 1068 1.153 msaitoh /* XXX PCIE_SLCSR2 (It's reserved by the PCIe spec) */ 1069 1.153 msaitoh } 1070 1.153 msaitoh } 1071 1.153 msaitoh 1072 1.153 msaitoh /* For MSI */ 1073 1.153 msaitoh if (pci_get_capability(pc, tag, PCI_CAP_MSI, &off, NULL) != 0) { 1074 1.153 msaitoh pcireg_t reg; 1075 1.153 msaitoh bool bit64, pvmask; 1076 1.153 msaitoh 1077 1.153 msaitoh /* First, drop Enable bit in case it's already set. */ 1078 1.153 msaitoh reg = pci_conf_read(pc, tag, off + PCI_MSI_CTL); 1079 1.153 msaitoh pci_conf_write(pc, tag, off + PCI_MSI_CTL, 1080 1.153 msaitoh reg & ~PCI_MSI_CTL_MSI_ENABLE); 1081 1.153 msaitoh 1082 1.153 msaitoh bit64 = pcs->msi_ctl & PCI_MSI_CTL_64BIT_ADDR; 1083 1.153 msaitoh pvmask = pcs->msi_ctl & PCI_MSI_CTL_PERVEC_MASK; 1084 1.153 msaitoh 1085 1.153 msaitoh /* Address */ 1086 1.153 msaitoh pci_conf_write(pc, tag, off + PCI_MSI_MADDR, pcs->msi_maddr); 1087 1.153 msaitoh 1088 1.153 msaitoh if (bit64) 1089 1.153 msaitoh pci_conf_write(pc, tag, 1090 1.153 msaitoh off + PCI_MSI_MADDR64_HI, pcs->msi_maddr64_hi); 1091 1.153 msaitoh 1092 1.153 msaitoh /* Data */ 1093 1.153 msaitoh pci_conf_write(pc, tag, 1094 1.153 msaitoh off + (bit64 ? PCI_MSI_MDATA64 : PCI_MSI_MDATA), 1095 1.153 msaitoh pcs->msi_mdata); 1096 1.153 msaitoh 1097 1.153 msaitoh /* Per-vector masking */ 1098 1.153 msaitoh if (pvmask) 1099 1.153 msaitoh pci_conf_write(pc, tag, 1100 1.153 msaitoh off + (bit64 ? PCI_MSI_MASK64 : PCI_MSI_MASK), 1101 1.153 msaitoh pcs->msi_mask); 1102 1.153 msaitoh 1103 1.153 msaitoh /* Write CTRL register in the end */ 1104 1.153 msaitoh pci_conf_write(pc, tag, off + PCI_MSI_CTL, pcs->msi_ctl); 1105 1.153 msaitoh } 1106 1.153 msaitoh 1107 1.153 msaitoh /* For MSI-X */ 1108 1.153 msaitoh if (pci_get_capability(pc, tag, PCI_CAP_MSIX, &off, NULL) != 0) 1109 1.153 msaitoh pci_conf_write(pc, tag, off + PCI_MSIX_CTL, pcs->msix_ctl); 1110 1.90 jmcneill } 1111 1.93 thorpej 1112 1.99 christos /* 1113 1.99 christos * Power Management Capability (Rev 2.2) 1114 1.99 christos */ 1115 1.107 jmcneill static int 1116 1.107 jmcneill pci_get_powerstate_int(pci_chipset_tag_t pc, pcitag_t tag , pcireg_t *state, 1117 1.107 jmcneill int offset) 1118 1.99 christos { 1119 1.107 jmcneill pcireg_t value, now; 1120 1.99 christos 1121 1.99 christos value = pci_conf_read(pc, tag, offset + PCI_PMCSR); 1122 1.99 christos now = value & PCI_PMCSR_STATE_MASK; 1123 1.99 christos switch (now) { 1124 1.99 christos case PCI_PMCSR_STATE_D0: 1125 1.99 christos case PCI_PMCSR_STATE_D1: 1126 1.99 christos case PCI_PMCSR_STATE_D2: 1127 1.99 christos case PCI_PMCSR_STATE_D3: 1128 1.99 christos *state = now; 1129 1.99 christos return 0; 1130 1.99 christos default: 1131 1.99 christos return EINVAL; 1132 1.99 christos } 1133 1.99 christos } 1134 1.99 christos 1135 1.99 christos int 1136 1.107 jmcneill pci_get_powerstate(pci_chipset_tag_t pc, pcitag_t tag , pcireg_t *state) 1137 1.99 christos { 1138 1.99 christos int offset; 1139 1.107 jmcneill pcireg_t value; 1140 1.99 christos 1141 1.99 christos if (!pci_get_capability(pc, tag, PCI_CAP_PWRMGMT, &offset, &value)) 1142 1.99 christos return EOPNOTSUPP; 1143 1.99 christos 1144 1.107 jmcneill return pci_get_powerstate_int(pc, tag, state, offset); 1145 1.107 jmcneill } 1146 1.107 jmcneill 1147 1.107 jmcneill static int 1148 1.107 jmcneill pci_set_powerstate_int(pci_chipset_tag_t pc, pcitag_t tag, pcireg_t state, 1149 1.107 jmcneill int offset, pcireg_t cap_reg) 1150 1.107 jmcneill { 1151 1.107 jmcneill pcireg_t value, cap, now; 1152 1.107 jmcneill 1153 1.107 jmcneill cap = cap_reg >> PCI_PMCR_SHIFT; 1154 1.99 christos value = pci_conf_read(pc, tag, offset + PCI_PMCSR); 1155 1.99 christos now = value & PCI_PMCSR_STATE_MASK; 1156 1.99 christos value &= ~PCI_PMCSR_STATE_MASK; 1157 1.99 christos 1158 1.99 christos if (now == state) 1159 1.99 christos return 0; 1160 1.99 christos switch (state) { 1161 1.99 christos case PCI_PMCSR_STATE_D0: 1162 1.99 christos break; 1163 1.99 christos case PCI_PMCSR_STATE_D1: 1164 1.107 jmcneill if (now == PCI_PMCSR_STATE_D2 || now == PCI_PMCSR_STATE_D3) { 1165 1.107 jmcneill printf("invalid transition from %d to D1\n", (int)now); 1166 1.99 christos return EINVAL; 1167 1.107 jmcneill } 1168 1.107 jmcneill if (!(cap & PCI_PMCR_D1SUPP)) { 1169 1.107 jmcneill printf("D1 not supported\n"); 1170 1.99 christos return EOPNOTSUPP; 1171 1.107 jmcneill } 1172 1.99 christos break; 1173 1.99 christos case PCI_PMCSR_STATE_D2: 1174 1.107 jmcneill if (now == PCI_PMCSR_STATE_D3) { 1175 1.107 jmcneill printf("invalid transition from %d to D2\n", (int)now); 1176 1.99 christos return EINVAL; 1177 1.107 jmcneill } 1178 1.107 jmcneill if (!(cap & PCI_PMCR_D2SUPP)) { 1179 1.107 jmcneill printf("D2 not supported\n"); 1180 1.99 christos return EOPNOTSUPP; 1181 1.107 jmcneill } 1182 1.99 christos break; 1183 1.99 christos case PCI_PMCSR_STATE_D3: 1184 1.99 christos break; 1185 1.99 christos default: 1186 1.99 christos return EINVAL; 1187 1.99 christos } 1188 1.112 dyoung value |= state; 1189 1.99 christos pci_conf_write(pc, tag, offset + PCI_PMCSR, value); 1190 1.111 drochner /* delay according to pcipm1.2, ch. 5.6.1 */ 1191 1.112 dyoung if (state == PCI_PMCSR_STATE_D3 || now == PCI_PMCSR_STATE_D3) 1192 1.110 jmcneill DELAY(10000); 1193 1.112 dyoung else if (state == PCI_PMCSR_STATE_D2 || now == PCI_PMCSR_STATE_D2) 1194 1.110 jmcneill DELAY(200); 1195 1.110 jmcneill 1196 1.99 christos return 0; 1197 1.99 christos } 1198 1.99 christos 1199 1.99 christos int 1200 1.107 jmcneill pci_set_powerstate(pci_chipset_tag_t pc, pcitag_t tag, pcireg_t state) 1201 1.107 jmcneill { 1202 1.107 jmcneill int offset; 1203 1.107 jmcneill pcireg_t value; 1204 1.107 jmcneill 1205 1.107 jmcneill if (!pci_get_capability(pc, tag, PCI_CAP_PWRMGMT, &offset, &value)) { 1206 1.107 jmcneill printf("pci_set_powerstate not supported\n"); 1207 1.107 jmcneill return EOPNOTSUPP; 1208 1.107 jmcneill } 1209 1.107 jmcneill 1210 1.107 jmcneill return pci_set_powerstate_int(pc, tag, state, offset, value); 1211 1.107 jmcneill } 1212 1.107 jmcneill 1213 1.107 jmcneill int 1214 1.114 dyoung pci_activate(pci_chipset_tag_t pc, pcitag_t tag, device_t dev, 1215 1.114 dyoung int (*wakefun)(pci_chipset_tag_t, pcitag_t, device_t, pcireg_t)) 1216 1.99 christos { 1217 1.99 christos pcireg_t pmode; 1218 1.99 christos int error; 1219 1.99 christos 1220 1.99 christos if ((error = pci_get_powerstate(pc, tag, &pmode))) 1221 1.99 christos return error; 1222 1.99 christos 1223 1.99 christos switch (pmode) { 1224 1.99 christos case PCI_PMCSR_STATE_D0: 1225 1.99 christos break; 1226 1.99 christos case PCI_PMCSR_STATE_D3: 1227 1.99 christos if (wakefun == NULL) { 1228 1.99 christos /* 1229 1.99 christos * The card has lost all configuration data in 1230 1.99 christos * this state, so punt. 1231 1.99 christos */ 1232 1.114 dyoung aprint_error_dev(dev, 1233 1.114 dyoung "unable to wake up from power state D3\n"); 1234 1.99 christos return EOPNOTSUPP; 1235 1.99 christos } 1236 1.99 christos /*FALLTHROUGH*/ 1237 1.99 christos default: 1238 1.99 christos if (wakefun) { 1239 1.114 dyoung error = (*wakefun)(pc, tag, dev, pmode); 1240 1.99 christos if (error) 1241 1.99 christos return error; 1242 1.99 christos } 1243 1.114 dyoung aprint_normal_dev(dev, "waking up from power state D%d\n", 1244 1.114 dyoung pmode); 1245 1.99 christos if ((error = pci_set_powerstate(pc, tag, PCI_PMCSR_STATE_D0))) 1246 1.99 christos return error; 1247 1.99 christos } 1248 1.99 christos return 0; 1249 1.99 christos } 1250 1.99 christos 1251 1.99 christos int 1252 1.103 christos pci_activate_null(pci_chipset_tag_t pc, pcitag_t tag, 1253 1.114 dyoung device_t dev, pcireg_t state) 1254 1.99 christos { 1255 1.99 christos return 0; 1256 1.99 christos } 1257 1.99 christos 1258 1.107 jmcneill struct pci_child_power { 1259 1.107 jmcneill struct pci_conf_state p_pciconf; 1260 1.107 jmcneill pci_chipset_tag_t p_pc; 1261 1.107 jmcneill pcitag_t p_tag; 1262 1.107 jmcneill bool p_has_pm; 1263 1.107 jmcneill int p_pm_offset; 1264 1.107 jmcneill pcireg_t p_pm_cap; 1265 1.107 jmcneill pcireg_t p_class; 1266 1.131 dyoung pcireg_t p_csr; 1267 1.107 jmcneill }; 1268 1.107 jmcneill 1269 1.107 jmcneill static bool 1270 1.127 dyoung pci_child_suspend(device_t dv, const pmf_qual_t *qual) 1271 1.107 jmcneill { 1272 1.107 jmcneill struct pci_child_power *priv = device_pmf_bus_private(dv); 1273 1.111 drochner pcireg_t ocsr, csr; 1274 1.107 jmcneill 1275 1.107 jmcneill pci_conf_capture(priv->p_pc, priv->p_tag, &priv->p_pciconf); 1276 1.107 jmcneill 1277 1.111 drochner if (!priv->p_has_pm) 1278 1.111 drochner return true; /* ??? hopefully handled by ACPI */ 1279 1.111 drochner if (PCI_CLASS(priv->p_class) == PCI_CLASS_DISPLAY) 1280 1.111 drochner return true; /* XXX */ 1281 1.111 drochner 1282 1.111 drochner /* disable decoding and busmastering, see pcipm1.2 ch. 8.2.1 */ 1283 1.111 drochner ocsr = pci_conf_read(priv->p_pc, priv->p_tag, PCI_COMMAND_STATUS_REG); 1284 1.111 drochner csr = ocsr & ~(PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE 1285 1.111 drochner | PCI_COMMAND_MASTER_ENABLE); 1286 1.111 drochner pci_conf_write(priv->p_pc, priv->p_tag, PCI_COMMAND_STATUS_REG, csr); 1287 1.111 drochner if (pci_set_powerstate_int(priv->p_pc, priv->p_tag, 1288 1.107 jmcneill PCI_PMCSR_STATE_D3, priv->p_pm_offset, priv->p_pm_cap)) { 1289 1.111 drochner pci_conf_write(priv->p_pc, priv->p_tag, 1290 1.111 drochner PCI_COMMAND_STATUS_REG, ocsr); 1291 1.107 jmcneill aprint_error_dev(dv, "unsupported state, continuing.\n"); 1292 1.107 jmcneill return false; 1293 1.107 jmcneill } 1294 1.107 jmcneill return true; 1295 1.107 jmcneill } 1296 1.107 jmcneill 1297 1.154 msaitoh static void 1298 1.154 msaitoh pci_pme_check_and_clear(device_t dv, pci_chipset_tag_t pc, pcitag_t tag, 1299 1.154 msaitoh int off) 1300 1.154 msaitoh { 1301 1.154 msaitoh pcireg_t pmcsr; 1302 1.154 msaitoh 1303 1.154 msaitoh pmcsr = pci_conf_read(pc, tag, off + PCI_PMCSR); 1304 1.154 msaitoh 1305 1.154 msaitoh if (pmcsr & PCI_PMCSR_PME_STS) { 1306 1.154 msaitoh /* Clear W1C bit */ 1307 1.154 msaitoh pmcsr |= PCI_PMCSR_PME_STS; 1308 1.154 msaitoh pci_conf_write(pc, tag, off + PCI_PMCSR, pmcsr); 1309 1.154 msaitoh aprint_verbose_dev(dv, "Clear PME# now\n"); 1310 1.154 msaitoh } 1311 1.154 msaitoh } 1312 1.154 msaitoh 1313 1.107 jmcneill static bool 1314 1.127 dyoung pci_child_resume(device_t dv, const pmf_qual_t *qual) 1315 1.107 jmcneill { 1316 1.107 jmcneill struct pci_child_power *priv = device_pmf_bus_private(dv); 1317 1.107 jmcneill 1318 1.154 msaitoh if (priv->p_has_pm) { 1319 1.154 msaitoh if (pci_set_powerstate_int(priv->p_pc, priv->p_tag, 1320 1.154 msaitoh PCI_PMCSR_STATE_D0, priv->p_pm_offset, priv->p_pm_cap)) { 1321 1.154 msaitoh aprint_error_dev(dv, 1322 1.154 msaitoh "unsupported state, continuing.\n"); 1323 1.154 msaitoh return false; 1324 1.154 msaitoh } 1325 1.154 msaitoh pci_pme_check_and_clear(dv, priv->p_pc, priv->p_tag, 1326 1.154 msaitoh priv->p_pm_offset); 1327 1.107 jmcneill } 1328 1.107 jmcneill 1329 1.107 jmcneill pci_conf_restore(priv->p_pc, priv->p_tag, &priv->p_pciconf); 1330 1.107 jmcneill 1331 1.107 jmcneill return true; 1332 1.107 jmcneill } 1333 1.107 jmcneill 1334 1.113 drochner static bool 1335 1.113 drochner pci_child_shutdown(device_t dv, int how) 1336 1.113 drochner { 1337 1.113 drochner struct pci_child_power *priv = device_pmf_bus_private(dv); 1338 1.113 drochner pcireg_t csr; 1339 1.113 drochner 1340 1.131 dyoung /* restore original bus-mastering state */ 1341 1.113 drochner csr = pci_conf_read(priv->p_pc, priv->p_tag, PCI_COMMAND_STATUS_REG); 1342 1.113 drochner csr &= ~PCI_COMMAND_MASTER_ENABLE; 1343 1.131 dyoung csr |= priv->p_csr & PCI_COMMAND_MASTER_ENABLE; 1344 1.113 drochner pci_conf_write(priv->p_pc, priv->p_tag, PCI_COMMAND_STATUS_REG, csr); 1345 1.113 drochner return true; 1346 1.113 drochner } 1347 1.113 drochner 1348 1.107 jmcneill static void 1349 1.107 jmcneill pci_child_deregister(device_t dv) 1350 1.107 jmcneill { 1351 1.107 jmcneill struct pci_child_power *priv = device_pmf_bus_private(dv); 1352 1.107 jmcneill 1353 1.107 jmcneill free(priv, M_DEVBUF); 1354 1.107 jmcneill } 1355 1.107 jmcneill 1356 1.165 riastrad static void 1357 1.107 jmcneill pci_child_register(device_t child) 1358 1.107 jmcneill { 1359 1.107 jmcneill device_t self = device_parent(child); 1360 1.107 jmcneill struct pci_softc *sc = device_private(self); 1361 1.107 jmcneill struct pci_child_power *priv; 1362 1.107 jmcneill int device, function, off; 1363 1.107 jmcneill pcireg_t reg; 1364 1.107 jmcneill 1365 1.107 jmcneill priv = malloc(sizeof(*priv), M_DEVBUF, M_WAITOK); 1366 1.107 jmcneill 1367 1.107 jmcneill device = device_locator(child, PCICF_DEV); 1368 1.107 jmcneill function = device_locator(child, PCICF_FUNCTION); 1369 1.107 jmcneill 1370 1.107 jmcneill priv->p_pc = sc->sc_pc; 1371 1.107 jmcneill priv->p_tag = pci_make_tag(priv->p_pc, sc->sc_bus, device, 1372 1.107 jmcneill function); 1373 1.107 jmcneill priv->p_class = pci_conf_read(priv->p_pc, priv->p_tag, PCI_CLASS_REG); 1374 1.131 dyoung priv->p_csr = pci_conf_read(priv->p_pc, priv->p_tag, 1375 1.131 dyoung PCI_COMMAND_STATUS_REG); 1376 1.107 jmcneill 1377 1.107 jmcneill if (pci_get_capability(priv->p_pc, priv->p_tag, 1378 1.107 jmcneill PCI_CAP_PWRMGMT, &off, ®)) { 1379 1.107 jmcneill priv->p_has_pm = true; 1380 1.107 jmcneill priv->p_pm_offset = off; 1381 1.107 jmcneill priv->p_pm_cap = reg; 1382 1.154 msaitoh pci_pme_check_and_clear(child, priv->p_pc, priv->p_tag, off); 1383 1.107 jmcneill } else { 1384 1.107 jmcneill priv->p_has_pm = false; 1385 1.107 jmcneill priv->p_pm_offset = -1; 1386 1.107 jmcneill } 1387 1.107 jmcneill 1388 1.107 jmcneill device_pmf_bus_register(child, priv, pci_child_suspend, 1389 1.113 drochner pci_child_resume, pci_child_shutdown, pci_child_deregister); 1390 1.107 jmcneill } 1391 1.142 jmcneill 1392 1.142 jmcneill MODULE(MODULE_CLASS_DRIVER, pci, NULL); 1393 1.142 jmcneill 1394 1.142 jmcneill static int 1395 1.142 jmcneill pci_modcmd(modcmd_t cmd, void *priv) 1396 1.142 jmcneill { 1397 1.142 jmcneill if (cmd == MODULE_CMD_INIT || cmd == MODULE_CMD_FINI) 1398 1.142 jmcneill return 0; 1399 1.142 jmcneill return ENOTTY; 1400 1.142 jmcneill } 1401