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