Line data Source code
1 : /* $OpenBSD: ppb.c,v 1.66 2018/04/06 13:59:30 kettenis Exp $ */
2 : /* $NetBSD: ppb.c,v 1.16 1997/06/06 23:48:05 thorpej Exp $ */
3 :
4 : /*
5 : * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
6 : *
7 : * Redistribution and use in source and binary forms, with or without
8 : * modification, are permitted provided that the following conditions
9 : * are met:
10 : * 1. Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : * 2. Redistributions in binary form must reproduce the above copyright
13 : * notice, this list of conditions and the following disclaimer in the
14 : * documentation and/or other materials provided with the distribution.
15 : * 3. All advertising materials mentioning features or use of this software
16 : * must display the following acknowledgement:
17 : * This product includes software developed by Christopher G. Demetriou
18 : * for the NetBSD Project.
19 : * 4. The name of the author may not be used to endorse or promote products
20 : * derived from this software without specific prior written permission
21 : *
22 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 : * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 : */
33 :
34 : #include <sys/param.h>
35 : #include <sys/systm.h>
36 : #include <sys/device.h>
37 : #include <sys/task.h>
38 : #include <sys/timeout.h>
39 :
40 : #include <dev/pci/pcireg.h>
41 : #include <dev/pci/pcivar.h>
42 : #include <dev/pci/pcidevs.h>
43 : #include <dev/pci/ppbreg.h>
44 :
45 : #ifndef PCI_IO_START
46 : #define PCI_IO_START 0
47 : #endif
48 :
49 : #ifndef PCI_IO_END
50 : #define PCI_IO_END 0xffffffff
51 : #endif
52 :
53 : #ifndef PCI_MEM_START
54 : #define PCI_MEM_START 0
55 : #endif
56 :
57 : #ifndef PCI_MEM_END
58 : #define PCI_MEM_END 0xffffffff
59 : #endif
60 :
61 : #define PPB_EXNAMLEN 32
62 :
63 : struct ppb_softc {
64 : struct device sc_dev; /* generic device glue */
65 : pci_chipset_tag_t sc_pc; /* our PCI chipset... */
66 : pcitag_t sc_tag; /* ...and tag. */
67 : pci_intr_handle_t sc_ih[4];
68 : void *sc_intrhand;
69 : struct extent *sc_busex;
70 : struct extent *sc_ioex;
71 : struct extent *sc_memex;
72 : struct extent *sc_pmemex;
73 : struct device *sc_psc;
74 : int sc_cap_off;
75 : struct task sc_insert_task;
76 : struct task sc_rescan_task;
77 : struct task sc_remove_task;
78 : struct timeout sc_to;
79 :
80 : bus_addr_t sc_iobase, sc_iolimit;
81 : bus_addr_t sc_membase, sc_memlimit;
82 : bus_addr_t sc_pmembase, sc_pmemlimit;
83 :
84 : pcireg_t sc_csr;
85 : pcireg_t sc_bhlcr;
86 : pcireg_t sc_bir;
87 : pcireg_t sc_bcr;
88 : pcireg_t sc_int;
89 : pcireg_t sc_slcsr;
90 : pcireg_t sc_msi_mc;
91 : pcireg_t sc_msi_ma;
92 : pcireg_t sc_msi_mau32;
93 : pcireg_t sc_msi_md;
94 : int sc_pmcsr_state;
95 : };
96 :
97 : int ppbmatch(struct device *, void *, void *);
98 : void ppbattach(struct device *, struct device *, void *);
99 : int ppbdetach(struct device *self, int flags);
100 : int ppbactivate(struct device *self, int act);
101 :
102 : struct cfattach ppb_ca = {
103 : sizeof(struct ppb_softc), ppbmatch, ppbattach, ppbdetach, ppbactivate
104 : };
105 :
106 : struct cfdriver ppb_cd = {
107 : NULL, "ppb", DV_DULL
108 : };
109 :
110 : void ppb_alloc_busrange(struct ppb_softc *, struct pci_attach_args *,
111 : pcireg_t *);
112 : void ppb_alloc_resources(struct ppb_softc *, struct pci_attach_args *);
113 : int ppb_intr(void *);
114 : void ppb_hotplug_insert(void *);
115 : void ppb_hotplug_insert_finish(void *);
116 : int ppb_hotplug_fixup(struct pci_attach_args *);
117 : int ppb_hotplug_fixup_type0(pci_chipset_tag_t, pcitag_t, pcitag_t);
118 : int ppb_hotplug_fixup_type1(pci_chipset_tag_t, pcitag_t, pcitag_t);
119 : void ppb_hotplug_rescan(void *);
120 : void ppb_hotplug_remove(void *);
121 : int ppbprint(void *, const char *pnp);
122 :
123 : int
124 0 : ppbmatch(struct device *parent, void *match, void *aux)
125 : {
126 0 : struct pci_attach_args *pa = aux;
127 :
128 : /*
129 : * This device is mislabeled. It is not a PCI bridge.
130 : */
131 0 : if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_VIATECH &&
132 0 : PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_VIATECH_VT82C586_PWR)
133 0 : return (0);
134 : /*
135 : * Check the ID register to see that it's a PCI bridge.
136 : * If it is, we assume that we can deal with it; it _should_
137 : * work in a standardized way...
138 : */
139 0 : if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE &&
140 0 : PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_PCI)
141 0 : return (1);
142 :
143 0 : return (0);
144 0 : }
145 :
146 : void
147 0 : ppbattach(struct device *parent, struct device *self, void *aux)
148 : {
149 0 : struct ppb_softc *sc = (struct ppb_softc *)self;
150 0 : struct pci_attach_args *pa = aux;
151 0 : pci_chipset_tag_t pc = pa->pa_pc;
152 0 : struct pcibus_attach_args pba;
153 : pci_interface_t interface;
154 0 : pci_intr_handle_t ih;
155 0 : pcireg_t busdata, reg, blr;
156 : char *name;
157 : int sec, sub;
158 : int pin;
159 :
160 0 : sc->sc_pc = pc;
161 0 : sc->sc_tag = pa->pa_tag;
162 :
163 0 : busdata = pci_conf_read(pc, pa->pa_tag, PPB_REG_BUSINFO);
164 :
165 : /*
166 : * When the bus number isn't configured, try to allocate one
167 : * ourselves.
168 : */
169 0 : if (busdata == 0 && pa->pa_busex)
170 0 : ppb_alloc_busrange(sc, pa, &busdata);
171 :
172 : /*
173 : * When the bus number still isn't set correctly, give up.
174 : */
175 0 : if (PPB_BUSINFO_SECONDARY(busdata) == 0) {
176 0 : printf(": not configured by system firmware\n");
177 0 : return;
178 : }
179 :
180 : #if 0
181 : /*
182 : * XXX can't do this, because we're not given our bus number
183 : * (we shouldn't need it), and because we've no way to
184 : * decompose our tag.
185 : */
186 : /* sanity check. */
187 : if (pa->pa_bus != PPB_BUSINFO_PRIMARY(busdata))
188 : panic("ppbattach: bus in tag (%d) != bus in reg (%d)",
189 : pa->pa_bus, PPB_BUSINFO_PRIMARY(busdata));
190 : #endif
191 :
192 : sec = PPB_BUSINFO_SECONDARY(busdata);
193 0 : sub = PPB_BUSINFO_SUBORDINATE(busdata);
194 0 : if (sub > sec) {
195 0 : name = malloc(PPB_EXNAMLEN, M_DEVBUF, M_NOWAIT);
196 0 : if (name) {
197 0 : snprintf(name, PPB_EXNAMLEN, "%s pcibus", sc->sc_dev.dv_xname);
198 0 : sc->sc_busex = extent_create(name, 0, 0xff,
199 : M_DEVBUF, NULL, 0, EX_NOWAIT | EX_FILLED);
200 0 : extent_free(sc->sc_busex, sec + 1,
201 0 : sub - sec, EX_NOWAIT);
202 0 : }
203 : }
204 :
205 : /* Check for PCI Express capabilities and setup hotplug support. */
206 0 : if (pci_get_capability(pc, pa->pa_tag, PCI_CAP_PCIEXPRESS,
207 0 : &sc->sc_cap_off, ®) && (reg & PCI_PCIE_XCAP_SI)) {
208 0 : task_set(&sc->sc_insert_task, ppb_hotplug_insert, sc);
209 0 : task_set(&sc->sc_rescan_task, ppb_hotplug_rescan, sc);
210 0 : task_set(&sc->sc_remove_task, ppb_hotplug_remove, sc);
211 0 : timeout_set(&sc->sc_to, ppb_hotplug_insert_finish, sc);
212 :
213 : #ifdef __i386__
214 : if (pci_intr_map(pa, &ih) == 0)
215 : sc->sc_intrhand = pci_intr_establish(pc, ih, IPL_BIO,
216 : ppb_intr, sc, self->dv_xname);
217 : #else
218 0 : if (pci_intr_map_msi(pa, &ih) == 0 ||
219 0 : pci_intr_map(pa, &ih) == 0)
220 0 : sc->sc_intrhand = pci_intr_establish(pc, ih, IPL_BIO,
221 0 : ppb_intr, sc, self->dv_xname);
222 : #endif
223 :
224 0 : if (sc->sc_intrhand) {
225 0 : printf(": %s", pci_intr_string(pc, ih));
226 :
227 : /* Enable hotplug interrupt. */
228 0 : reg = pci_conf_read(pc, pa->pa_tag,
229 0 : sc->sc_cap_off + PCI_PCIE_SLCSR);
230 0 : reg |= (PCI_PCIE_SLCSR_HPE | PCI_PCIE_SLCSR_PDE);
231 0 : pci_conf_write(pc, pa->pa_tag,
232 0 : sc->sc_cap_off + PCI_PCIE_SLCSR, reg);
233 0 : }
234 : }
235 :
236 0 : printf("\n");
237 :
238 0 : interface = PCI_INTERFACE(pa->pa_class);
239 :
240 : /*
241 : * The Intel 82801BAM Hub-to-PCI can decode subtractively but
242 : * doesn't advertise itself as such.
243 : */
244 0 : if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL &&
245 0 : (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801BA_HPB ||
246 0 : PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801BAM_HPB))
247 0 : interface = PPB_INTERFACE_SUBTRACTIVE;
248 :
249 0 : if (interface != PPB_INTERFACE_SUBTRACTIVE)
250 0 : ppb_alloc_resources(sc, pa);
251 :
252 0 : for (pin = PCI_INTERRUPT_PIN_A; pin <= PCI_INTERRUPT_PIN_D; pin++) {
253 0 : pa->pa_intrpin = pa->pa_rawintrpin = pin;
254 0 : pa->pa_intrline = 0;
255 0 : pci_intr_map(pa, &sc->sc_ih[pin - PCI_INTERRUPT_PIN_A]);
256 : }
257 :
258 : /*
259 : * The UltraSPARC-IIi APB doesn't implement the standard
260 : * address range registers.
261 : */
262 0 : if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_SUN &&
263 0 : PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SUN_SIMBA)
264 : goto attach;
265 :
266 : /* Figure out the I/O address range of the bridge. */
267 0 : blr = pci_conf_read(pc, pa->pa_tag, PPB_REG_IOSTATUS);
268 0 : sc->sc_iobase = (blr & 0x000000f0) << 8;
269 0 : sc->sc_iolimit = (blr & 0x000f000) | 0x00000fff;
270 0 : blr = pci_conf_read(pc, pa->pa_tag, PPB_REG_IO_HI);
271 0 : sc->sc_iobase |= (blr & 0x0000ffff) << 16;
272 0 : sc->sc_iolimit |= (blr & 0xffff0000);
273 0 : if (sc->sc_iolimit > sc->sc_iobase) {
274 0 : name = malloc(PPB_EXNAMLEN, M_DEVBUF, M_NOWAIT);
275 0 : if (name) {
276 0 : snprintf(name, PPB_EXNAMLEN, "%s pciio", sc->sc_dev.dv_xname);
277 0 : sc->sc_ioex = extent_create(name, 0, 0xffffffff,
278 : M_DEVBUF, NULL, 0, EX_NOWAIT | EX_FILLED);
279 0 : extent_free(sc->sc_ioex, sc->sc_iobase,
280 0 : sc->sc_iolimit - sc->sc_iobase + 1, EX_NOWAIT);
281 0 : }
282 : }
283 :
284 : /* Figure out the memory mapped I/O address range of the bridge. */
285 0 : blr = pci_conf_read(pc, pa->pa_tag, PPB_REG_MEM);
286 0 : sc->sc_membase = (blr & 0x0000fff0) << 16;
287 0 : sc->sc_memlimit = (blr & 0xfff00000) | 0x000fffff;
288 0 : if (sc->sc_memlimit > sc->sc_membase) {
289 0 : name = malloc(PPB_EXNAMLEN, M_DEVBUF, M_NOWAIT);
290 0 : if (name) {
291 0 : snprintf(name, PPB_EXNAMLEN, "%s pcimem", sc->sc_dev.dv_xname);
292 0 : sc->sc_memex = extent_create(name, 0, (u_long)-1L,
293 : M_DEVBUF, NULL, 0, EX_NOWAIT | EX_FILLED);
294 0 : extent_free(sc->sc_memex, sc->sc_membase,
295 0 : sc->sc_memlimit - sc->sc_membase + 1,
296 : EX_NOWAIT);
297 0 : }
298 : }
299 :
300 : /* Figure out the prefetchable MMI/O address range of the bridge. */
301 0 : blr = pci_conf_read(pc, pa->pa_tag, PPB_REG_PREFMEM);
302 0 : sc->sc_pmembase = (blr & 0x0000fff0) << 16;
303 0 : sc->sc_pmemlimit = (blr & 0xfff00000) | 0x000fffff;
304 : #ifdef __LP64__
305 0 : blr = pci_conf_read(pc, pa->pa_tag, PPB_REG_PREFBASE_HI32);
306 0 : sc->sc_pmembase |= ((uint64_t)blr) << 32;
307 0 : blr = pci_conf_read(pc, pa->pa_tag, PPB_REG_PREFLIM_HI32);
308 0 : sc->sc_pmemlimit |= ((uint64_t)blr) << 32;
309 : #endif
310 0 : if (sc->sc_pmemlimit > sc->sc_pmembase) {
311 0 : name = malloc(PPB_EXNAMLEN, M_DEVBUF, M_NOWAIT);
312 0 : if (name) {
313 0 : snprintf(name, PPB_EXNAMLEN, "%s pcipmem", sc->sc_dev.dv_xname);
314 0 : sc->sc_pmemex = extent_create(name, 0, (u_long)-1L,
315 : M_DEVBUF, NULL, 0, EX_NOWAIT | EX_FILLED);
316 0 : extent_free(sc->sc_pmemex, sc->sc_pmembase,
317 0 : sc->sc_pmemlimit - sc->sc_pmembase + 1,
318 : EX_NOWAIT);
319 0 : }
320 : }
321 :
322 0 : if (interface == PPB_INTERFACE_SUBTRACTIVE) {
323 0 : if (sc->sc_ioex == NULL)
324 0 : sc->sc_ioex = pa->pa_ioex;
325 0 : if (sc->sc_memex == NULL)
326 0 : sc->sc_memex = pa->pa_memex;
327 : }
328 :
329 : attach:
330 : /*
331 : * Attach the PCI bus that hangs off of it.
332 : *
333 : * XXX Don't pass-through Memory Read Multiple. Should we?
334 : * XXX Consult the spec...
335 : */
336 0 : bzero(&pba, sizeof(pba));
337 0 : pba.pba_busname = "pci";
338 0 : pba.pba_iot = pa->pa_iot;
339 0 : pba.pba_memt = pa->pa_memt;
340 0 : pba.pba_dmat = pa->pa_dmat;
341 0 : pba.pba_pc = pc;
342 0 : pba.pba_flags = pa->pa_flags & ~PCI_FLAGS_MRM_OKAY;
343 0 : pba.pba_busex = sc->sc_busex;
344 0 : pba.pba_ioex = sc->sc_ioex;
345 0 : pba.pba_memex = sc->sc_memex;
346 0 : pba.pba_pmemex = sc->sc_pmemex;
347 0 : pba.pba_domain = pa->pa_domain;
348 0 : pba.pba_bus = PPB_BUSINFO_SECONDARY(busdata);
349 0 : pba.pba_bridgeih = sc->sc_ih;
350 0 : pba.pba_bridgetag = &sc->sc_tag;
351 0 : pba.pba_intrswiz = pa->pa_intrswiz;
352 0 : pba.pba_intrtag = pa->pa_intrtag;
353 :
354 0 : sc->sc_psc = config_found(self, &pba, ppbprint);
355 0 : }
356 :
357 : int
358 0 : ppbdetach(struct device *self, int flags)
359 : {
360 0 : struct ppb_softc *sc = (struct ppb_softc *)self;
361 : char *name;
362 : int rv;
363 :
364 0 : if (sc->sc_intrhand)
365 0 : pci_intr_disestablish(sc->sc_pc, sc->sc_intrhand);
366 :
367 0 : rv = config_detach_children(self, flags);
368 :
369 0 : if (sc->sc_busex) {
370 0 : name = sc->sc_busex->ex_name;
371 0 : extent_destroy(sc->sc_busex);
372 0 : free(name, M_DEVBUF, PPB_EXNAMLEN);
373 0 : }
374 :
375 0 : if (sc->sc_ioex) {
376 0 : name = sc->sc_ioex->ex_name;
377 0 : extent_destroy(sc->sc_ioex);
378 0 : free(name, M_DEVBUF, PPB_EXNAMLEN);
379 0 : }
380 :
381 0 : if (sc->sc_memex) {
382 0 : name = sc->sc_memex->ex_name;
383 0 : extent_destroy(sc->sc_memex);
384 0 : free(name, M_DEVBUF, PPB_EXNAMLEN);
385 0 : }
386 :
387 0 : if (sc->sc_pmemex) {
388 0 : name = sc->sc_pmemex->ex_name;
389 0 : extent_destroy(sc->sc_pmemex);
390 0 : free(name, M_DEVBUF, PPB_EXNAMLEN);
391 0 : }
392 :
393 0 : return (rv);
394 : }
395 :
396 : int
397 0 : ppbactivate(struct device *self, int act)
398 : {
399 0 : struct ppb_softc *sc = (void *)self;
400 0 : pci_chipset_tag_t pc = sc->sc_pc;
401 0 : pcitag_t tag = sc->sc_tag;
402 0 : pcireg_t blr, reg;
403 0 : int off, rv = 0;
404 :
405 0 : switch (act) {
406 : case DVACT_SUSPEND:
407 0 : rv = config_activate_children(self, act);
408 :
409 : /* Save registers that may get lost. */
410 0 : sc->sc_csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
411 0 : sc->sc_bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
412 0 : sc->sc_bir = pci_conf_read(pc, tag, PPB_REG_BUSINFO);
413 0 : sc->sc_bcr = pci_conf_read(pc, tag, PPB_REG_BRIDGECONTROL);
414 0 : sc->sc_int = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
415 0 : if (sc->sc_cap_off)
416 0 : sc->sc_slcsr = pci_conf_read(pc, tag,
417 0 : sc->sc_cap_off + PCI_PCIE_SLCSR);
418 :
419 0 : if (pci_get_capability(pc, tag, PCI_CAP_MSI, &off, ®)) {
420 0 : sc->sc_msi_ma = pci_conf_read(pc, tag,
421 0 : off + PCI_MSI_MA);
422 0 : if (reg & PCI_MSI_MC_C64) {
423 0 : sc->sc_msi_mau32 = pci_conf_read(pc, tag,
424 : off + PCI_MSI_MAU32);
425 0 : sc->sc_msi_md = pci_conf_read(pc, tag,
426 0 : off + PCI_MSI_MD64);
427 0 : } else {
428 0 : sc->sc_msi_md = pci_conf_read(pc, tag,
429 : off + PCI_MSI_MD32);
430 : }
431 0 : sc->sc_msi_mc = reg;
432 0 : }
433 : break;
434 : case DVACT_RESUME:
435 0 : if (pci_dopm) {
436 : /* Restore power. */
437 0 : pci_set_powerstate(pc, tag, sc->sc_pmcsr_state);
438 0 : }
439 :
440 : /* Restore the registers saved above. */
441 0 : pci_conf_write(pc, tag, PCI_BHLC_REG, sc->sc_bhlcr);
442 0 : pci_conf_write(pc, tag, PPB_REG_BUSINFO, sc->sc_bir);
443 0 : pci_conf_write(pc, tag, PPB_REG_BRIDGECONTROL, sc->sc_bcr);
444 0 : pci_conf_write(pc, tag, PCI_INTERRUPT_REG, sc->sc_int);
445 0 : if (sc->sc_cap_off)
446 0 : pci_conf_write(pc, tag,
447 0 : sc->sc_cap_off + PCI_PCIE_SLCSR, sc->sc_slcsr);
448 :
449 : /* Restore I/O window. */
450 0 : blr = pci_conf_read(pc, tag, PPB_REG_IOSTATUS);
451 0 : blr &= 0xffff0000;
452 0 : blr |= sc->sc_iolimit & PPB_IO_MASK;
453 0 : blr |= (sc->sc_iobase >> PPB_IO_SHIFT);
454 0 : pci_conf_write(pc, tag, PPB_REG_IOSTATUS, blr);
455 0 : blr = (sc->sc_iobase & 0xffff0000) >> 16;
456 0 : blr |= sc->sc_iolimit & 0xffff0000;
457 0 : pci_conf_write(pc, tag, PPB_REG_IO_HI, blr);
458 :
459 : /* Restore memory mapped I/O window. */
460 0 : blr = sc->sc_memlimit & PPB_MEM_MASK;
461 0 : blr |= (sc->sc_membase >> PPB_MEM_SHIFT);
462 0 : pci_conf_write(pc, tag, PPB_REG_MEM, blr);
463 :
464 : /* Restore prefetchable MMI/O window. */
465 0 : blr = sc->sc_pmemlimit & PPB_MEM_MASK;
466 0 : blr |= ((sc->sc_pmembase & PPB_MEM_MASK) >> PPB_MEM_SHIFT);
467 0 : pci_conf_write(pc, tag, PPB_REG_PREFMEM, blr);
468 : #ifdef __LP64__
469 0 : pci_conf_write(pc, tag, PPB_REG_PREFBASE_HI32,
470 0 : sc->sc_pmembase >> 32);
471 0 : pci_conf_write(pc, tag, PPB_REG_PREFLIM_HI32,
472 0 : sc->sc_pmemlimit >> 32);
473 : #endif
474 :
475 0 : if (pci_get_capability(pc, tag, PCI_CAP_MSI, &off, ®)) {
476 0 : pci_conf_write(pc, tag, off + PCI_MSI_MA,
477 0 : sc->sc_msi_ma);
478 0 : if (reg & PCI_MSI_MC_C64) {
479 0 : pci_conf_write(pc, tag, off + PCI_MSI_MAU32,
480 0 : sc->sc_msi_mau32);
481 0 : pci_conf_write(pc, tag, off + PCI_MSI_MD64,
482 0 : sc->sc_msi_md);
483 0 : } else {
484 0 : pci_conf_write(pc, tag, off + PCI_MSI_MD32,
485 0 : sc->sc_msi_md);
486 : }
487 0 : pci_conf_write(pc, tag, off + PCI_MSI_MC,
488 0 : sc->sc_msi_mc);
489 0 : }
490 :
491 : /*
492 : * Restore command register last to avoid exposing
493 : * uninitialised windows.
494 : */
495 0 : reg = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
496 0 : pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG,
497 0 : (reg & 0xffff0000) | (sc->sc_csr & 0x0000ffff));
498 :
499 0 : rv = config_activate_children(self, act);
500 0 : break;
501 : case DVACT_POWERDOWN:
502 0 : rv = config_activate_children(self, act);
503 :
504 0 : if (pci_dopm) {
505 : /*
506 : * Place the bridge into the lowest possible
507 : * power state.
508 : */
509 0 : sc->sc_pmcsr_state = pci_get_powerstate(pc, tag);
510 0 : pci_set_powerstate(pc, tag,
511 0 : pci_min_powerstate(pc, tag));
512 0 : }
513 : break;
514 : default:
515 0 : rv = config_activate_children(self, act);
516 0 : break;
517 : }
518 0 : return (rv);
519 0 : }
520 :
521 : void
522 0 : ppb_alloc_busrange(struct ppb_softc *sc, struct pci_attach_args *pa,
523 : pcireg_t *busdata)
524 : {
525 0 : pci_chipset_tag_t pc = sc->sc_pc;
526 0 : u_long busnum, busrange;
527 :
528 0 : for (busrange = 16; busrange > 0; busrange >>= 1) {
529 0 : if (extent_alloc(pa->pa_busex, busrange, 1, 0, 0,
530 : EX_NOWAIT, &busnum))
531 : continue;
532 0 : *busdata |= pa->pa_bus;
533 0 : *busdata |= (busnum << 8);
534 0 : *busdata |= ((busnum + busrange - 1) << 16);
535 0 : pci_conf_write(pc, pa->pa_tag, PPB_REG_BUSINFO, *busdata);
536 0 : return;
537 : }
538 0 : }
539 :
540 : void
541 0 : ppb_alloc_resources(struct ppb_softc *sc, struct pci_attach_args *pa)
542 : {
543 0 : pci_chipset_tag_t pc = sc->sc_pc;
544 0 : pcireg_t id, busdata, blr, bhlcr, type, csr;
545 : pcireg_t addr, mask;
546 : pcitag_t tag;
547 : int bus, dev;
548 : int reg, reg_start, reg_end, reg_rom;
549 : int io_count = 0;
550 : int mem_count = 0;
551 : bus_addr_t start, end;
552 0 : u_long base, size;
553 :
554 0 : if (pa->pa_memex == NULL)
555 0 : return;
556 :
557 0 : busdata = pci_conf_read(pc, sc->sc_tag, PPB_REG_BUSINFO);
558 0 : bus = PPB_BUSINFO_SECONDARY(busdata);
559 0 : if (bus == 0)
560 0 : return;
561 :
562 : /*
563 : * Count number of devices. If there are no devices behind
564 : * this bridge, there's no point in allocating any address
565 : * space.
566 : */
567 0 : for (dev = 0; dev < pci_bus_maxdevs(pc, bus); dev++) {
568 0 : tag = pci_make_tag(pc, bus, dev, 0);
569 0 : id = pci_conf_read(pc, tag, PCI_ID_REG);
570 :
571 0 : if (PCI_VENDOR(id) == PCI_VENDOR_INVALID ||
572 0 : PCI_VENDOR(id) == 0)
573 : continue;
574 :
575 0 : bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
576 0 : switch (PCI_HDRTYPE_TYPE(bhlcr)) {
577 : case 0:
578 : reg_start = PCI_MAPREG_START;
579 : reg_end = PCI_MAPREG_END;
580 : reg_rom = PCI_ROM_REG;
581 0 : break;
582 : case 1: /* PCI-PCI bridge */
583 : reg_start = PCI_MAPREG_START;
584 : reg_end = PCI_MAPREG_PPB_END;
585 : reg_rom = 0; /* 0x38 */
586 0 : io_count++;
587 0 : mem_count++;
588 0 : break;
589 : case 2: /* PCI-Cardbus bridge */
590 : reg_start = PCI_MAPREG_START;
591 : reg_end = PCI_MAPREG_PCB_END;
592 : reg_rom = 0;
593 0 : io_count++;
594 0 : mem_count++;
595 0 : break;
596 : default:
597 0 : return;
598 : }
599 :
600 0 : for (reg = reg_start; reg < reg_end; reg += 4) {
601 0 : if (pci_mapreg_probe(pc, tag, reg, &type) == 0)
602 : continue;
603 :
604 0 : if (type == PCI_MAPREG_TYPE_IO)
605 0 : io_count++;
606 : else
607 0 : mem_count++;
608 : }
609 :
610 0 : if (reg_rom != 0) {
611 0 : addr = pci_conf_read(pc, tag, reg_rom);
612 0 : pci_conf_write(pc, tag, reg_rom, ~PCI_ROM_ENABLE);
613 0 : mask = pci_conf_read(pc, tag, reg_rom);
614 0 : pci_conf_write(pc, tag, reg_rom, addr);
615 0 : if (PCI_ROM_SIZE(mask))
616 0 : mem_count++;
617 : }
618 : }
619 :
620 0 : csr = pci_conf_read(pc, sc->sc_tag, PCI_COMMAND_STATUS_REG);
621 :
622 : /*
623 : * Get the bridge in a consistent state. If memory mapped I/O or
624 : * port I/O is disabled, disabled the associated windows as well.
625 : */
626 0 : if ((csr & PCI_COMMAND_MEM_ENABLE) == 0) {
627 0 : pci_conf_write(pc, sc->sc_tag, PPB_REG_MEM, 0x0000ffff);
628 0 : pci_conf_write(pc, sc->sc_tag, PPB_REG_PREFMEM, 0x0000ffff);
629 0 : pci_conf_write(pc, sc->sc_tag, PPB_REG_PREFBASE_HI32, 0);
630 0 : pci_conf_write(pc, sc->sc_tag, PPB_REG_PREFLIM_HI32, 0);
631 0 : }
632 0 : if ((csr & PCI_COMMAND_IO_ENABLE) == 0) {
633 0 : pci_conf_write(pc, sc->sc_tag, PPB_REG_IOSTATUS, 0x000000ff);
634 0 : pci_conf_write(pc, sc->sc_tag, PPB_REG_IO_HI, 0x0000ffff);
635 0 : }
636 :
637 : /* Allocate I/O address space if necessary. */
638 0 : if (io_count > 0 && pa->pa_ioex) {
639 0 : blr = pci_conf_read(pc, sc->sc_tag, PPB_REG_IOSTATUS);
640 0 : sc->sc_iobase = (blr << PPB_IO_SHIFT) & PPB_IO_MASK;
641 0 : sc->sc_iolimit = (blr & PPB_IO_MASK) | 0x00000fff;
642 0 : blr = pci_conf_read(pc, sc->sc_tag, PPB_REG_IO_HI);
643 0 : sc->sc_iobase |= (blr & 0x0000ffff) << 16;
644 0 : sc->sc_iolimit |= (blr & 0xffff0000);
645 0 : if (sc->sc_iolimit < sc->sc_iobase || sc->sc_iobase == 0) {
646 0 : start = max(PCI_IO_START, pa->pa_ioex->ex_start);
647 0 : end = min(PCI_IO_END, pa->pa_ioex->ex_end);
648 0 : for (size = 0x2000; size >= PPB_IO_MIN; size >>= 1)
649 0 : if (extent_alloc_subregion(pa->pa_ioex, start,
650 0 : end, size, size, 0, 0, 0, &base) == 0)
651 : break;
652 0 : if (size >= PPB_IO_MIN) {
653 0 : sc->sc_iobase = base;
654 0 : sc->sc_iolimit = base + size - 1;
655 0 : blr = pci_conf_read(pc, sc->sc_tag,
656 : PPB_REG_IOSTATUS);
657 0 : blr &= 0xffff0000;
658 0 : blr |= sc->sc_iolimit & PPB_IO_MASK;
659 0 : blr |= (sc->sc_iobase >> PPB_IO_SHIFT);
660 0 : pci_conf_write(pc, sc->sc_tag,
661 : PPB_REG_IOSTATUS, blr);
662 0 : blr = (sc->sc_iobase & 0xffff0000) >> 16;
663 0 : blr |= sc->sc_iolimit & 0xffff0000;
664 0 : pci_conf_write(pc, sc->sc_tag,
665 : PPB_REG_IO_HI, blr);
666 :
667 0 : csr |= PCI_COMMAND_IO_ENABLE;
668 0 : }
669 : }
670 : }
671 :
672 : /* Allocate memory mapped I/O address space if necessary. */
673 0 : if (mem_count > 0 && pa->pa_memex) {
674 0 : blr = pci_conf_read(pc, sc->sc_tag, PPB_REG_MEM);
675 0 : sc->sc_membase = (blr << PPB_MEM_SHIFT) & PPB_MEM_MASK;
676 0 : sc->sc_memlimit = (blr & PPB_MEM_MASK) | 0x000fffff;
677 0 : if (sc->sc_memlimit < sc->sc_membase || sc->sc_membase == 0) {
678 0 : start = max(PCI_MEM_START, pa->pa_memex->ex_start);
679 0 : end = min(PCI_MEM_END, pa->pa_memex->ex_end);
680 0 : for (size = 0x2000000; size >= PPB_MEM_MIN; size >>= 1)
681 0 : if (extent_alloc_subregion(pa->pa_memex, start,
682 0 : end, size, size, 0, 0, 0, &base) == 0)
683 : break;
684 0 : if (size >= PPB_MEM_MIN) {
685 0 : sc->sc_membase = base;
686 0 : sc->sc_memlimit = base + size - 1;
687 0 : blr = sc->sc_memlimit & PPB_MEM_MASK;
688 0 : blr |= (sc->sc_membase >> PPB_MEM_SHIFT);
689 0 : pci_conf_write(pc, sc->sc_tag,
690 : PPB_REG_MEM, blr);
691 :
692 0 : csr |= PCI_COMMAND_MEM_ENABLE;
693 0 : }
694 : }
695 : }
696 :
697 : /* Enable bus master. */
698 0 : csr |= PCI_COMMAND_MASTER_ENABLE;
699 :
700 0 : pci_conf_write(pc, sc->sc_tag, PCI_COMMAND_STATUS_REG, csr);
701 0 : }
702 :
703 : int
704 0 : ppb_intr(void *arg)
705 : {
706 0 : struct ppb_softc *sc = arg;
707 : pcireg_t reg;
708 :
709 : /*
710 : * XXX ignore hotplug events while in autoconf. On some
711 : * machines with onboard re(4), we get a bogus hotplug remove
712 : * event when we reset that device. Ignoring that event makes
713 : * sure we will not try to forcibly detach re(4) when it isn't
714 : * ready to deal with that.
715 : */
716 0 : if (cold)
717 0 : return (0);
718 :
719 0 : reg = pci_conf_read(sc->sc_pc, sc->sc_tag,
720 0 : sc->sc_cap_off + PCI_PCIE_SLCSR);
721 0 : if (reg & PCI_PCIE_SLCSR_PDC) {
722 0 : if (reg & PCI_PCIE_SLCSR_PDS)
723 0 : task_add(systq, &sc->sc_insert_task);
724 : else
725 0 : task_add(systq, &sc->sc_remove_task);
726 :
727 : /* Clear interrupts. */
728 0 : pci_conf_write(sc->sc_pc, sc->sc_tag,
729 0 : sc->sc_cap_off + PCI_PCIE_SLCSR, reg);
730 0 : return (1);
731 : }
732 :
733 0 : return (0);
734 0 : }
735 :
736 : #ifdef PCI_MACHDEP_ENUMERATE_BUS
737 : #define pci_enumerate_bus PCI_MACHDEP_ENUMERATE_BUS
738 : #else
739 : extern int pci_enumerate_bus(struct pci_softc *,
740 : int (*)(struct pci_attach_args *), struct pci_attach_args *);
741 : #endif
742 :
743 : void
744 0 : ppb_hotplug_insert(void *xsc)
745 : {
746 0 : struct ppb_softc *sc = xsc;
747 0 : struct pci_softc *psc = (struct pci_softc *)sc->sc_psc;
748 :
749 0 : if (!LIST_EMPTY(&psc->sc_devs))
750 0 : return;
751 :
752 : /* XXX Powerup the card. */
753 :
754 : /* XXX Turn on LEDs. */
755 :
756 : /* Wait a second for things to settle. */
757 0 : timeout_add_sec(&sc->sc_to, 1);
758 0 : }
759 :
760 : void
761 0 : ppb_hotplug_insert_finish(void *arg)
762 : {
763 0 : struct ppb_softc *sc = arg;
764 :
765 0 : task_add(systq, &sc->sc_rescan_task);
766 0 : }
767 :
768 : int
769 0 : ppb_hotplug_fixup(struct pci_attach_args *pa)
770 : {
771 : pcireg_t bhlcr;
772 :
773 0 : bhlcr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG);
774 0 : switch (PCI_HDRTYPE_TYPE(bhlcr)) {
775 : case 0:
776 0 : return ppb_hotplug_fixup_type0(pa->pa_pc,
777 0 : pa->pa_tag, *pa->pa_bridgetag);
778 : case 1:
779 0 : return ppb_hotplug_fixup_type1(pa->pa_pc,
780 0 : pa->pa_tag, *pa->pa_bridgetag);
781 : default:
782 0 : return (0);
783 : }
784 0 : }
785 :
786 : int
787 0 : ppb_hotplug_fixup_type0(pci_chipset_tag_t pc, pcitag_t tag, pcitag_t bridgetag)
788 : {
789 : pcireg_t intr;
790 : int line;
791 :
792 : /*
793 : * Fill in the interrupt line for platforms that need it.
794 : *
795 : * XXX We assume that the interrupt line matches the line used
796 : * by the PCI Express bridge. This may not be true.
797 : */
798 0 : intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
799 0 : if (PCI_INTERRUPT_PIN(intr) != PCI_INTERRUPT_PIN_NONE &&
800 0 : PCI_INTERRUPT_LINE(intr) == 0) {
801 : /* Get the interrupt line from our parent. */
802 0 : intr = pci_conf_read(pc, bridgetag, PCI_INTERRUPT_REG);
803 0 : line = PCI_INTERRUPT_LINE(intr);
804 :
805 0 : intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
806 0 : intr &= ~(PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT);
807 0 : intr |= line << PCI_INTERRUPT_LINE_SHIFT;
808 0 : pci_conf_write(pc, tag, PCI_INTERRUPT_REG, intr);
809 0 : }
810 :
811 0 : return (0);
812 : }
813 :
814 : int
815 0 : ppb_hotplug_fixup_type1(pci_chipset_tag_t pc, pcitag_t tag, pcitag_t bridgetag)
816 : {
817 : pcireg_t bhlcr, bir, csr, val;
818 : int bus, dev, reg;
819 :
820 0 : bir = pci_conf_read(pc, bridgetag, PPB_REG_BUSINFO);
821 0 : if (PPB_BUSINFO_SUBORDINATE(bir) <= PPB_BUSINFO_SECONDARY(bir))
822 0 : return (0);
823 :
824 : bus = PPB_BUSINFO_SECONDARY(bir);
825 0 : bir = pci_conf_read(pc, tag, PPB_REG_BUSINFO);
826 0 : bir &= (0xff << 24);
827 0 : bir |= bus++;
828 0 : bir |= (bus << 8);
829 0 : bir |= (bus << 16);
830 0 : pci_conf_write(pc, tag, PPB_REG_BUSINFO, bir);
831 :
832 0 : for (reg = PPB_REG_IOSTATUS; reg < PPB_REG_BRIDGECONTROL; reg += 4) {
833 0 : val = pci_conf_read(pc, bridgetag, reg);
834 0 : pci_conf_write(pc, tag, reg, val);
835 : }
836 :
837 0 : csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
838 0 : csr |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE;
839 0 : csr |= PCI_COMMAND_MASTER_ENABLE;
840 0 : csr |= PCI_COMMAND_INVALIDATE_ENABLE;
841 0 : csr |= PCI_COMMAND_SERR_ENABLE;
842 0 : pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr);
843 :
844 0 : for (dev = 0; dev < pci_bus_maxdevs(pc, bus); dev++) {
845 0 : tag = pci_make_tag(pc, bus, dev, 0);
846 :
847 0 : bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
848 0 : if (PCI_HDRTYPE_TYPE(bhlcr) != 0)
849 : continue;
850 :
851 0 : ppb_hotplug_fixup_type0(pc, tag, bridgetag);
852 0 : }
853 :
854 0 : return (0);
855 0 : }
856 :
857 : void
858 0 : ppb_hotplug_rescan(void *xsc)
859 : {
860 0 : struct ppb_softc *sc = xsc;
861 0 : struct pci_softc *psc = (struct pci_softc *)sc->sc_psc;
862 :
863 0 : if (psc) {
864 : /* Assign resources. */
865 0 : pci_enumerate_bus(psc, ppb_hotplug_fixup, NULL);
866 :
867 : /* Attach devices. */
868 0 : pci_enumerate_bus(psc, NULL, NULL);
869 0 : }
870 0 : }
871 :
872 : void
873 0 : ppb_hotplug_remove(void *xsc)
874 : {
875 0 : struct ppb_softc *sc = xsc;
876 0 : struct pci_softc *psc = (struct pci_softc *)sc->sc_psc;
877 :
878 0 : if (psc) {
879 0 : pci_detach_devices(psc, DETACH_FORCE);
880 :
881 : /*
882 : * XXX Allocate the entire window with EX_CONFLICTOK
883 : * such that we can easily free it.
884 : */
885 0 : if (sc->sc_ioex != NULL) {
886 0 : extent_alloc_region(sc->sc_ioex, sc->sc_iobase,
887 0 : sc->sc_iolimit - sc->sc_iobase + 1,
888 : EX_NOWAIT | EX_CONFLICTOK);
889 0 : extent_free(sc->sc_ioex, sc->sc_iobase,
890 0 : sc->sc_iolimit - sc->sc_iobase + 1, EX_NOWAIT);
891 0 : }
892 :
893 0 : if (sc->sc_memex != NULL) {
894 0 : extent_alloc_region(sc->sc_memex, sc->sc_membase,
895 0 : sc->sc_memlimit - sc->sc_membase + 1,
896 : EX_NOWAIT | EX_CONFLICTOK);
897 0 : extent_free(sc->sc_memex, sc->sc_membase,
898 0 : sc->sc_memlimit - sc->sc_membase + 1, EX_NOWAIT);
899 0 : }
900 :
901 0 : if (sc->sc_pmemex != NULL) {
902 0 : extent_alloc_region(sc->sc_pmemex, sc->sc_pmembase,
903 0 : sc->sc_pmemlimit - sc->sc_pmembase + 1,
904 : EX_NOWAIT | EX_CONFLICTOK);
905 0 : extent_free(sc->sc_pmemex, sc->sc_pmembase,
906 0 : sc->sc_pmemlimit - sc->sc_pmembase + 1, EX_NOWAIT);
907 0 : }
908 : }
909 0 : }
910 :
911 : int
912 0 : ppbprint(void *aux, const char *pnp)
913 : {
914 0 : struct pcibus_attach_args *pba = aux;
915 :
916 : /* only PCIs can attach to PPBs; easy. */
917 0 : if (pnp)
918 0 : printf("pci at %s", pnp);
919 0 : printf(" bus %d", pba->pba_bus);
920 0 : return (UNCONF);
921 : }
|