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