1 /*-
2 * Copyright (c) 2011 Nathan Whitehorn
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27 #include <sys/cdefs.h>
28 #include <sys/param.h>
29 #include <sys/systm.h>
30 #include <sys/module.h>
31 #include <sys/bus.h>
32 #include <sys/conf.h>
33 #include <sys/kernel.h>
34 #include <sys/rman.h>
35
36 #include <dev/ofw/openfirm.h>
37 #include <dev/ofw/ofw_pci.h>
38 #include <dev/ofw/ofw_bus.h>
39 #include <dev/ofw/ofw_bus_subr.h>
40 #include <dev/ofw/ofwpci.h>
41
42 #include <dev/pci/pcivar.h>
43 #include <dev/pci/pcireg.h>
44 #include <dev/pci/pcib_private.h>
45
46 #include <machine/bus.h>
47 #include <machine/md_var.h>
48 #include <machine/resource.h>
49
50 #include <vm/vm.h>
51 #include <vm/pmap.h>
52
53 #include "pcib_if.h"
54
55 /*
56 * If it is necessary to set another value of this for
57 * some platforms it should be set at fdt.h file
58 */
59 #ifndef PCI_MAP_INTR
60 #define PCI_MAP_INTR 4
61 #endif
62
63 #define PCI_INTR_PINS 4
64
65 /*
66 * bus interface.
67 */
68 static struct resource * ofw_pcib_alloc_resource(device_t, device_t,
69 int, int *, rman_res_t, rman_res_t, rman_res_t, u_int);
70 static int ofw_pcib_release_resource(device_t, device_t, int, int,
71 struct resource *);
72 static int ofw_pcib_activate_resource(device_t, device_t, int, int,
73 struct resource *);
74 static int ofw_pcib_deactivate_resource(device_t, device_t, int, int,
75 struct resource *);
76 static int ofw_pcib_adjust_resource(device_t, device_t, int,
77 struct resource *, rman_res_t, rman_res_t);
78 static int ofw_pcib_translate_resource(device_t bus, int type,
79 rman_res_t start, rman_res_t *newstart);
80
81 #ifdef __powerpc__
82 static bus_space_tag_t ofw_pcib_bus_get_bus_tag(device_t, device_t);
83 #endif
84
85 /*
86 * pcib interface
87 */
88 static int ofw_pcib_maxslots(device_t);
89
90 /*
91 * ofw_bus interface
92 */
93 static phandle_t ofw_pcib_get_node(device_t, device_t);
94
95 /*
96 * local methods
97 */
98 static int ofw_pcib_fill_ranges(phandle_t, struct ofw_pci_range *);
99 static struct rman *ofw_pcib_get_rman(struct ofw_pci_softc *, int, u_int);
100
101 /*
102 * Driver methods.
103 */
104 static device_method_t ofw_pcib_methods[] = {
105 /* Device interface */
106 DEVMETHOD(device_attach, ofw_pcib_attach),
107
108 /* Bus interface */
109 DEVMETHOD(bus_print_child, bus_generic_print_child),
110 DEVMETHOD(bus_read_ivar, ofw_pcib_read_ivar),
111 DEVMETHOD(bus_write_ivar, ofw_pcib_write_ivar),
112 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
113 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
114 DEVMETHOD(bus_alloc_resource, ofw_pcib_alloc_resource),
115 DEVMETHOD(bus_release_resource, ofw_pcib_release_resource),
116 DEVMETHOD(bus_activate_resource, ofw_pcib_activate_resource),
117 DEVMETHOD(bus_deactivate_resource, ofw_pcib_deactivate_resource),
118 DEVMETHOD(bus_adjust_resource, ofw_pcib_adjust_resource),
119 DEVMETHOD(bus_translate_resource, ofw_pcib_translate_resource),
120 #ifdef __powerpc__
121 DEVMETHOD(bus_get_bus_tag, ofw_pcib_bus_get_bus_tag),
122 #endif
123
124 /* pcib interface */
125 DEVMETHOD(pcib_maxslots, ofw_pcib_maxslots),
126 DEVMETHOD(pcib_route_interrupt, ofw_pcib_route_interrupt),
127 DEVMETHOD(pcib_request_feature, pcib_request_feature_allow),
128
129 /* ofw_bus interface */
130 DEVMETHOD(ofw_bus_get_node, ofw_pcib_get_node),
131
132 DEVMETHOD_END
133 };
134
135 DEFINE_CLASS_0(ofw_pcib, ofw_pcib_driver, ofw_pcib_methods, 0);
136
137 int
ofw_pcib_init(device_t dev)138 ofw_pcib_init(device_t dev)
139 {
140 struct ofw_pci_softc *sc;
141 phandle_t node;
142 u_int32_t busrange[2];
143 struct ofw_pci_range *rp;
144 int i, error;
145 struct ofw_pci_cell_info *cell_info;
146
147 node = ofw_bus_get_node(dev);
148 sc = device_get_softc(dev);
149 sc->sc_initialized = 1;
150 sc->sc_range = NULL;
151 sc->sc_pci_domain = device_get_unit(dev);
152
153 cell_info = (struct ofw_pci_cell_info *)malloc(sizeof(*cell_info),
154 M_DEVBUF, M_WAITOK | M_ZERO);
155
156 sc->sc_cell_info = cell_info;
157
158 if (OF_getencprop(node, "bus-range", busrange, sizeof(busrange)) != 8)
159 busrange[0] = 0;
160
161 sc->sc_dev = dev;
162 sc->sc_node = node;
163 sc->sc_bus = busrange[0];
164
165 if (sc->sc_quirks & OFW_PCI_QUIRK_RANGES_ON_CHILDREN) {
166 phandle_t c;
167 int n, i;
168
169 sc->sc_nrange = 0;
170 for (c = OF_child(node); c != 0; c = OF_peer(c)) {
171 n = ofw_pcib_nranges(c, cell_info);
172 if (n > 0)
173 sc->sc_nrange += n;
174 }
175 if (sc->sc_nrange == 0) {
176 error = ENXIO;
177 goto out;
178 }
179 sc->sc_range = malloc(sc->sc_nrange * sizeof(sc->sc_range[0]),
180 M_DEVBUF, M_WAITOK);
181 i = 0;
182 for (c = OF_child(node); c != 0; c = OF_peer(c)) {
183 n = ofw_pcib_fill_ranges(c, &sc->sc_range[i]);
184 if (n > 0)
185 i += n;
186 }
187 KASSERT(i == sc->sc_nrange, ("range count mismatch"));
188 } else {
189 sc->sc_nrange = ofw_pcib_nranges(node, cell_info);
190 if (sc->sc_nrange <= 0) {
191 device_printf(dev, "could not getranges\n");
192 error = ENXIO;
193 goto out;
194 }
195 sc->sc_range = malloc(sc->sc_nrange * sizeof(sc->sc_range[0]),
196 M_DEVBUF, M_WAITOK);
197 ofw_pcib_fill_ranges(node, sc->sc_range);
198 }
199
200 sc->sc_io_rman.rm_type = RMAN_ARRAY;
201 sc->sc_io_rman.rm_descr = "PCI I/O Ports";
202 error = rman_init(&sc->sc_io_rman);
203 if (error != 0) {
204 device_printf(dev, "rman_init() failed. error = %d\n", error);
205 goto out;
206 }
207
208 sc->sc_mem_rman.rm_type = RMAN_ARRAY;
209 sc->sc_mem_rman.rm_descr = "PCI Non Prefetchable Memory";
210 error = rman_init(&sc->sc_mem_rman);
211 if (error != 0) {
212 device_printf(dev, "rman_init() failed. error = %d\n", error);
213 goto out_mem_rman;
214 }
215
216 sc->sc_pmem_rman.rm_type = RMAN_ARRAY;
217 sc->sc_pmem_rman.rm_descr = "PCI Prefetchable Memory";
218 error = rman_init(&sc->sc_pmem_rman);
219 if (error != 0) {
220 device_printf(dev, "rman_init() failed. error = %d\n", error);
221 goto out_pmem_rman;
222 }
223
224 for (i = 0; i < sc->sc_nrange; i++) {
225 error = 0;
226 rp = sc->sc_range + i;
227
228 if (sc->sc_range_mask & ((uint64_t)1 << i))
229 continue;
230 switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) {
231 case OFW_PCI_PHYS_HI_SPACE_CONFIG:
232 break;
233 case OFW_PCI_PHYS_HI_SPACE_IO:
234 error = rman_manage_region(&sc->sc_io_rman, rp->pci,
235 rp->pci + rp->size - 1);
236 break;
237 case OFW_PCI_PHYS_HI_SPACE_MEM32:
238 case OFW_PCI_PHYS_HI_SPACE_MEM64:
239 if (rp->pci_hi & OFW_PCI_PHYS_HI_PREFETCHABLE) {
240 sc->sc_have_pmem = 1;
241 error = rman_manage_region(&sc->sc_pmem_rman,
242 rp->pci, rp->pci + rp->size - 1);
243 } else {
244 error = rman_manage_region(&sc->sc_mem_rman,
245 rp->pci, rp->pci + rp->size - 1);
246 }
247 break;
248 }
249
250 if (error != 0) {
251 device_printf(dev,
252 "rman_manage_region(%x, %#jx, %#jx) failed. "
253 "error = %d\n", rp->pci_hi &
254 OFW_PCI_PHYS_HI_SPACEMASK, rp->pci,
255 rp->pci + rp->size - 1, error);
256 goto out_full;
257 }
258 }
259
260 ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(cell_t));
261 return (0);
262
263 out_full:
264 rman_fini(&sc->sc_pmem_rman);
265 out_pmem_rman:
266 rman_fini(&sc->sc_mem_rman);
267 out_mem_rman:
268 rman_fini(&sc->sc_io_rman);
269 out:
270 free(sc->sc_cell_info, M_DEVBUF);
271 free(sc->sc_range, M_DEVBUF);
272
273 return (error);
274 }
275
276 void
ofw_pcib_fini(device_t dev)277 ofw_pcib_fini(device_t dev)
278 {
279 struct ofw_pci_softc *sc;
280
281 sc = device_get_softc(dev);
282 free(sc->sc_cell_info, M_DEVBUF);
283 free(sc->sc_range, M_DEVBUF);
284 rman_fini(&sc->sc_io_rman);
285 rman_fini(&sc->sc_mem_rman);
286 rman_fini(&sc->sc_pmem_rman);
287 }
288
289 int
ofw_pcib_attach(device_t dev)290 ofw_pcib_attach(device_t dev)
291 {
292 struct ofw_pci_softc *sc;
293 int error;
294
295 sc = device_get_softc(dev);
296 if (!sc->sc_initialized) {
297 error = ofw_pcib_init(dev);
298 if (error != 0)
299 return (error);
300 }
301
302 device_add_child(dev, "pci", -1);
303 return (bus_generic_attach(dev));
304 }
305
306 static int
ofw_pcib_maxslots(device_t dev)307 ofw_pcib_maxslots(device_t dev)
308 {
309
310 return (PCI_SLOTMAX);
311 }
312
313 int
ofw_pcib_route_interrupt(device_t bus,device_t dev,int pin)314 ofw_pcib_route_interrupt(device_t bus, device_t dev, int pin)
315 {
316 struct ofw_pci_softc *sc;
317 struct ofw_pci_register reg;
318 uint32_t pintr, mintr[PCI_MAP_INTR];
319 int intrcells;
320 phandle_t iparent;
321
322 sc = device_get_softc(bus);
323 pintr = pin;
324
325 /* Fabricate imap information in case this isn't an OFW device */
326 bzero(®, sizeof(reg));
327 reg.phys_hi = (pci_get_bus(dev) << OFW_PCI_PHYS_HI_BUSSHIFT) |
328 (pci_get_slot(dev) << OFW_PCI_PHYS_HI_DEVICESHIFT) |
329 (pci_get_function(dev) << OFW_PCI_PHYS_HI_FUNCTIONSHIFT);
330
331 intrcells = ofw_bus_lookup_imap(ofw_bus_get_node(dev),
332 &sc->sc_pci_iinfo, ®, sizeof(reg), &pintr, sizeof(pintr),
333 mintr, sizeof(mintr), &iparent);
334 if (intrcells != 0) {
335 pintr = ofw_bus_map_intr(dev, iparent, intrcells, mintr);
336 return (pintr);
337 }
338
339 /*
340 * Maybe it's a real interrupt, not an intpin
341 */
342 if (pin > PCI_INTR_PINS)
343 return (pin);
344
345 device_printf(bus, "could not route pin %d for device %d.%d\n",
346 pin, pci_get_slot(dev), pci_get_function(dev));
347 return (PCI_INVALID_IRQ);
348 }
349
350 int
ofw_pcib_read_ivar(device_t dev,device_t child,int which,uintptr_t * result)351 ofw_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
352 {
353 struct ofw_pci_softc *sc;
354
355 sc = device_get_softc(dev);
356
357 switch (which) {
358 case PCIB_IVAR_DOMAIN:
359 *result = sc->sc_pci_domain;
360 return (0);
361 case PCIB_IVAR_BUS:
362 *result = sc->sc_bus;
363 return (0);
364 default:
365 break;
366 }
367
368 return (ENOENT);
369 }
370
371 int
ofw_pcib_write_ivar(device_t dev,device_t child,int which,uintptr_t value)372 ofw_pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
373 {
374 struct ofw_pci_softc *sc;
375
376 sc = device_get_softc(dev);
377
378 switch (which) {
379 case PCIB_IVAR_BUS:
380 sc->sc_bus = value;
381 return (0);
382 default:
383 break;
384 }
385
386 return (ENOENT);
387 }
388
389 int
ofw_pcib_nranges(phandle_t node,struct ofw_pci_cell_info * info)390 ofw_pcib_nranges(phandle_t node, struct ofw_pci_cell_info *info)
391 {
392 ssize_t nbase_ranges;
393
394 if (info == NULL)
395 return (-1);
396
397 info->host_address_cells = 1;
398 info->size_cells = 2;
399 info->pci_address_cell = 3;
400
401 OF_getencprop(OF_parent(node), "#address-cells",
402 &(info->host_address_cells), sizeof(info->host_address_cells));
403 OF_getencprop(node, "#address-cells",
404 &(info->pci_address_cell), sizeof(info->pci_address_cell));
405 OF_getencprop(node, "#size-cells", &(info->size_cells),
406 sizeof(info->size_cells));
407
408 nbase_ranges = OF_getproplen(node, "ranges");
409 if (nbase_ranges <= 0)
410 return (-1);
411
412 return (nbase_ranges / sizeof(cell_t) /
413 (info->pci_address_cell + info->host_address_cells +
414 info->size_cells));
415 }
416
417 static struct resource *
ofw_pcib_alloc_resource(device_t bus,device_t child,int type,int * rid,rman_res_t start,rman_res_t end,rman_res_t count,u_int flags)418 ofw_pcib_alloc_resource(device_t bus, device_t child, int type, int *rid,
419 rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
420 {
421 struct ofw_pci_softc *sc;
422 struct resource *rv;
423 struct rman *rm;
424 int needactivate;
425
426 needactivate = flags & RF_ACTIVE;
427 flags &= ~RF_ACTIVE;
428
429 sc = device_get_softc(bus);
430
431 #if defined(NEW_PCIB) && defined(PCI_RES_BUS)
432 if (type == PCI_RES_BUS) {
433 return (pci_domain_alloc_bus(sc->sc_pci_domain, child, rid,
434 start, end, count, flags | needactivate));
435 }
436 #endif
437
438 rm = ofw_pcib_get_rman(sc, type, flags);
439 if (rm == NULL) {
440 return (bus_generic_alloc_resource(bus, child, type, rid,
441 start, end, count, flags | needactivate));
442 }
443
444 rv = rman_reserve_resource(rm, start, end, count, flags, child);
445 if (rv == NULL) {
446 device_printf(bus, "failed to reserve resource for %s\n",
447 device_get_nameunit(child));
448 return (NULL);
449 }
450
451 rman_set_rid(rv, *rid);
452
453 if (needactivate) {
454 if (bus_activate_resource(child, type, *rid, rv) != 0) {
455 device_printf(bus,
456 "failed to activate resource for %s\n",
457 device_get_nameunit(child));
458 rman_release_resource(rv);
459 return (NULL);
460 }
461 }
462
463 return (rv);
464 }
465
466 static int
ofw_pcib_release_resource(device_t bus,device_t child,int type,int rid,struct resource * res)467 ofw_pcib_release_resource(device_t bus, device_t child, int type, int rid,
468 struct resource *res)
469 {
470 struct ofw_pci_softc *sc;
471 struct rman *rm;
472 int error;
473
474 sc = device_get_softc(bus);
475
476 #if defined(NEW_PCIB) && defined(PCI_RES_BUS)
477 if (type == PCI_RES_BUS)
478 return (pci_domain_release_bus(sc->sc_pci_domain, child, rid,
479 res));
480 #endif
481
482 rm = ofw_pcib_get_rman(sc, type, rman_get_flags(res));
483 if (rm == NULL) {
484 return (bus_generic_release_resource(bus, child, type, rid,
485 res));
486 }
487 KASSERT(rman_is_region_manager(res, rm), ("rman mismatch"));
488
489 if (rman_get_flags(res) & RF_ACTIVE) {
490 error = bus_deactivate_resource(child, type, rid, res);
491 if (error != 0)
492 return (error);
493 }
494 return (rman_release_resource(res));
495 }
496
497 static int
ofw_pcib_translate_resource(device_t bus,int type,rman_res_t start,rman_res_t * newstart)498 ofw_pcib_translate_resource(device_t bus, int type, rman_res_t start,
499 rman_res_t *newstart)
500 {
501 struct ofw_pci_softc *sc;
502 struct ofw_pci_range *rp;
503 int space;
504
505 sc = device_get_softc(bus);
506
507 /*
508 * Map this through the ranges list
509 */
510 for (rp = sc->sc_range; rp < sc->sc_range + sc->sc_nrange &&
511 rp->pci_hi != 0; rp++) {
512 if (start < rp->pci || start >= rp->pci + rp->size)
513 continue;
514
515 switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) {
516 case OFW_PCI_PHYS_HI_SPACE_IO:
517 space = SYS_RES_IOPORT;
518 break;
519 case OFW_PCI_PHYS_HI_SPACE_MEM32:
520 case OFW_PCI_PHYS_HI_SPACE_MEM64:
521 space = SYS_RES_MEMORY;
522 break;
523 default:
524 space = -1;
525 }
526
527 if (type == space) {
528 start += (rp->host - rp->pci);
529 *newstart = start;
530 return (0);
531 }
532 }
533 return (ENOENT);
534 }
535
536 static int
ofw_pcib_activate_resource(device_t bus,device_t child,int type,int rid,struct resource * res)537 ofw_pcib_activate_resource(device_t bus, device_t child, int type, int rid,
538 struct resource *res)
539 {
540 struct ofw_pci_softc *sc;
541 bus_space_handle_t handle;
542 bus_space_tag_t tag;
543 struct ofw_pci_range *rp;
544 vm_paddr_t start;
545 int space;
546 int rv;
547
548 sc = device_get_softc(bus);
549
550 if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY) {
551 return (bus_generic_activate_resource(bus, child, type, rid,
552 res));
553 }
554
555 start = (vm_paddr_t)rman_get_start(res);
556
557 /*
558 * Map this through the ranges list
559 */
560 for (rp = sc->sc_range; rp < sc->sc_range + sc->sc_nrange &&
561 rp->pci_hi != 0; rp++) {
562 if (start < rp->pci || start >= rp->pci + rp->size)
563 continue;
564
565 switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) {
566 case OFW_PCI_PHYS_HI_SPACE_IO:
567 space = SYS_RES_IOPORT;
568 break;
569 case OFW_PCI_PHYS_HI_SPACE_MEM32:
570 case OFW_PCI_PHYS_HI_SPACE_MEM64:
571 space = SYS_RES_MEMORY;
572 break;
573 default:
574 space = -1;
575 }
576
577 if (type == space) {
578 start += (rp->host - rp->pci);
579 break;
580 }
581 }
582
583 if (bootverbose)
584 printf("ofw_pci mapdev: start %jx, len %jd\n",
585 (rman_res_t)start, rman_get_size(res));
586
587 tag = BUS_GET_BUS_TAG(child, child);
588 if (tag == NULL)
589 return (ENOMEM);
590
591 rman_set_bustag(res, tag);
592 rv = bus_space_map(tag, start,
593 rman_get_size(res), 0, &handle);
594 if (rv != 0)
595 return (ENOMEM);
596
597 rman_set_bushandle(res, handle);
598 rman_set_virtual(res, (void *)handle); /* XXX for powerpc only ? */
599
600 return (rman_activate_resource(res));
601 }
602
603 #ifdef __powerpc__
604 static bus_space_tag_t
ofw_pcib_bus_get_bus_tag(device_t bus,device_t child)605 ofw_pcib_bus_get_bus_tag(device_t bus, device_t child)
606 {
607
608 return (&bs_le_tag);
609 }
610 #endif
611
612 static int
ofw_pcib_deactivate_resource(device_t bus,device_t child,int type,int rid,struct resource * res)613 ofw_pcib_deactivate_resource(device_t bus, device_t child, int type, int rid,
614 struct resource *res)
615 {
616 vm_size_t psize;
617
618 if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY) {
619 return (bus_generic_deactivate_resource(bus, child, type, rid,
620 res));
621 }
622
623 psize = rman_get_size(res);
624 pmap_unmapdev(rman_get_virtual(res), psize);
625
626 return (rman_deactivate_resource(res));
627 }
628
629 static int
ofw_pcib_adjust_resource(device_t bus,device_t child,int type,struct resource * res,rman_res_t start,rman_res_t end)630 ofw_pcib_adjust_resource(device_t bus, device_t child, int type,
631 struct resource *res, rman_res_t start, rman_res_t end)
632 {
633 struct rman *rm;
634 struct ofw_pci_softc *sc;
635
636 sc = device_get_softc(bus);
637 #if defined(NEW_PCIB) && defined(PCI_RES_BUS)
638 if (type == PCI_RES_BUS)
639 return (pci_domain_adjust_bus(sc->sc_pci_domain, child, res,
640 start, end));
641 #endif
642
643 rm = ofw_pcib_get_rman(sc, type, rman_get_flags(res));
644 if (rm == NULL) {
645 return (bus_generic_adjust_resource(bus, child, type, res,
646 start, end));
647 }
648 KASSERT(rman_is_region_manager(res, rm), ("rman mismatch"));
649 KASSERT(!(rman_get_flags(res) & RF_ACTIVE),
650 ("active resources cannot be adjusted"));
651
652 return (rman_adjust_resource(res, start, end));
653 }
654
655 static phandle_t
ofw_pcib_get_node(device_t bus,device_t dev)656 ofw_pcib_get_node(device_t bus, device_t dev)
657 {
658 struct ofw_pci_softc *sc;
659
660 sc = device_get_softc(bus);
661 /* We only have one child, the PCI bus, which needs our own node. */
662
663 return (sc->sc_node);
664 }
665
666 static int
ofw_pcib_fill_ranges(phandle_t node,struct ofw_pci_range * ranges)667 ofw_pcib_fill_ranges(phandle_t node, struct ofw_pci_range *ranges)
668 {
669 int host_address_cells = 1, pci_address_cells = 3, size_cells = 2;
670 cell_t *base_ranges;
671 ssize_t nbase_ranges;
672 int nranges;
673 int i, j, k;
674
675 OF_getencprop(OF_parent(node), "#address-cells", &host_address_cells,
676 sizeof(host_address_cells));
677 OF_getencprop(node, "#address-cells", &pci_address_cells,
678 sizeof(pci_address_cells));
679 OF_getencprop(node, "#size-cells", &size_cells, sizeof(size_cells));
680
681 nbase_ranges = OF_getproplen(node, "ranges");
682 if (nbase_ranges <= 0)
683 return (-1);
684 nranges = nbase_ranges / sizeof(cell_t) /
685 (pci_address_cells + host_address_cells + size_cells);
686
687 base_ranges = malloc(nbase_ranges, M_DEVBUF, M_WAITOK);
688 OF_getencprop(node, "ranges", base_ranges, nbase_ranges);
689
690 for (i = 0, j = 0; i < nranges; i++) {
691 ranges[i].pci_hi = base_ranges[j++];
692 ranges[i].pci = 0;
693 for (k = 0; k < pci_address_cells - 1; k++) {
694 ranges[i].pci <<= 32;
695 ranges[i].pci |= base_ranges[j++];
696 }
697 ranges[i].host = 0;
698 for (k = 0; k < host_address_cells; k++) {
699 ranges[i].host <<= 32;
700 ranges[i].host |= base_ranges[j++];
701 }
702 ranges[i].size = 0;
703 for (k = 0; k < size_cells; k++) {
704 ranges[i].size <<= 32;
705 ranges[i].size |= base_ranges[j++];
706 }
707 }
708
709 free(base_ranges, M_DEVBUF);
710 return (nranges);
711 }
712
713 static struct rman *
ofw_pcib_get_rman(struct ofw_pci_softc * sc,int type,u_int flags)714 ofw_pcib_get_rman(struct ofw_pci_softc *sc, int type, u_int flags)
715 {
716
717 switch (type) {
718 case SYS_RES_IOPORT:
719 return (&sc->sc_io_rman);
720 case SYS_RES_MEMORY:
721 if (sc->sc_have_pmem && (flags & RF_PREFETCHABLE))
722 return (&sc->sc_pmem_rman);
723 else
724 return (&sc->sc_mem_rman);
725 default:
726 break;
727 }
728
729 return (NULL);
730 }
731