xref: /freebsd/sys/dev/pci/pci_host_generic.c (revision 59c8e88e72633afbc47a4ace0d2170d00d51f7dc)
1 /*-
2  * Copyright (c) 2015, 2020 Ruslan Bukin <br@bsdpad.com>
3  * Copyright (c) 2014 The FreeBSD Foundation
4  * All rights reserved.
5  *
6  * This software was developed by Semihalf under
7  * the sponsorship of the FreeBSD Foundation.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 
31 /* Generic ECAM PCIe driver */
32 
33 #include <sys/cdefs.h>
34 #include "opt_platform.h"
35 
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/malloc.h>
39 #include <sys/kernel.h>
40 #include <sys/rman.h>
41 #include <sys/module.h>
42 #include <sys/bus.h>
43 #include <sys/endian.h>
44 
45 #include <dev/pci/pcivar.h>
46 #include <dev/pci/pcireg.h>
47 #include <dev/pci/pcib_private.h>
48 #include <dev/pci/pci_host_generic.h>
49 
50 #include <machine/bus.h>
51 #include <machine/intr.h>
52 
53 #include "pcib_if.h"
54 
55 #if defined(VM_MEMATTR_DEVICE_NP)
56 #define	PCI_UNMAPPED
57 #define	PCI_RF_FLAGS	RF_UNMAPPED
58 #else
59 #define	PCI_RF_FLAGS	0
60 #endif
61 
62 
63 /* Forward prototypes */
64 
65 static uint32_t generic_pcie_read_config(device_t dev, u_int bus, u_int slot,
66     u_int func, u_int reg, int bytes);
67 static void generic_pcie_write_config(device_t dev, u_int bus, u_int slot,
68     u_int func, u_int reg, uint32_t val, int bytes);
69 static int generic_pcie_maxslots(device_t dev);
70 static int generic_pcie_read_ivar(device_t dev, device_t child, int index,
71     uintptr_t *result);
72 static int generic_pcie_write_ivar(device_t dev, device_t child, int index,
73     uintptr_t value);
74 
75 int
76 pci_host_generic_core_attach(device_t dev)
77 {
78 #ifdef PCI_UNMAPPED
79 	struct resource_map_request req;
80 	struct resource_map map;
81 #endif
82 	struct generic_pcie_core_softc *sc;
83 	uint64_t phys_base;
84 	uint64_t pci_base;
85 	uint64_t size;
86 	const char *range_descr;
87 	char buf[64];
88 	int domain, error;
89 	int flags, rid, tuple, type;
90 
91 	sc = device_get_softc(dev);
92 	sc->dev = dev;
93 
94 	/* Create the parent DMA tag to pass down the coherent flag */
95 	error = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */
96 	    1, 0,				/* alignment, bounds */
97 	    BUS_SPACE_MAXADDR,			/* lowaddr */
98 	    BUS_SPACE_MAXADDR,			/* highaddr */
99 	    NULL, NULL,				/* filter, filterarg */
100 	    BUS_SPACE_MAXSIZE,			/* maxsize */
101 	    BUS_SPACE_UNRESTRICTED,		/* nsegments */
102 	    BUS_SPACE_MAXSIZE,			/* maxsegsize */
103 	    sc->coherent ? BUS_DMA_COHERENT : 0, /* flags */
104 	    NULL, NULL,				/* lockfunc, lockarg */
105 	    &sc->dmat);
106 	if (error != 0)
107 		return (error);
108 
109 	/*
110 	 * Attempt to set the domain. If it's missing, or we are unable to
111 	 * set it then memory allocations may be placed in the wrong domain.
112 	 */
113 	if (bus_get_domain(dev, &domain) == 0)
114 		(void)bus_dma_tag_set_domain(sc->dmat, domain);
115 
116 	if ((sc->quirks & PCIE_CUSTOM_CONFIG_SPACE_QUIRK) == 0) {
117 		rid = 0;
118 		sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
119 		    PCI_RF_FLAGS | RF_ACTIVE);
120 		if (sc->res == NULL) {
121 			device_printf(dev, "could not allocate memory.\n");
122 			error = ENXIO;
123 			goto err_resource;
124 		}
125 #ifdef PCI_UNMAPPED
126 		resource_init_map_request(&req);
127 		req.memattr = VM_MEMATTR_DEVICE_NP;
128 		error = bus_map_resource(dev, SYS_RES_MEMORY, sc->res, &req,
129 		    &map);
130 		if (error != 0) {
131 			device_printf(dev, "could not map memory.\n");
132 			return (error);
133 		}
134 		rman_set_mapping(sc->res, &map);
135 #endif
136 	}
137 
138 	sc->has_pmem = false;
139 	sc->pmem_rman.rm_type = RMAN_ARRAY;
140 	snprintf(buf, sizeof(buf), "%s prefetch window",
141 	    device_get_nameunit(dev));
142 	sc->pmem_rman.rm_descr = strdup(buf, M_DEVBUF);
143 
144 	sc->mem_rman.rm_type = RMAN_ARRAY;
145 	snprintf(buf, sizeof(buf), "%s memory window",
146 	    device_get_nameunit(dev));
147 	sc->mem_rman.rm_descr = strdup(buf, M_DEVBUF);
148 
149 	sc->io_rman.rm_type = RMAN_ARRAY;
150 	snprintf(buf, sizeof(buf), "%s I/O port window",
151 	    device_get_nameunit(dev));
152 	sc->io_rman.rm_descr = strdup(buf, M_DEVBUF);
153 
154 	/* Initialize rman and allocate memory regions */
155 	error = rman_init(&sc->pmem_rman);
156 	if (error) {
157 		device_printf(dev, "rman_init() failed. error = %d\n", error);
158 		goto err_pmem_rman;
159 	}
160 
161 	error = rman_init(&sc->mem_rman);
162 	if (error) {
163 		device_printf(dev, "rman_init() failed. error = %d\n", error);
164 		goto err_mem_rman;
165 	}
166 
167 	error = rman_init(&sc->io_rman);
168 	if (error) {
169 		device_printf(dev, "rman_init() failed. error = %d\n", error);
170 		goto err_io_rman;
171 	}
172 
173 	for (tuple = 0; tuple < MAX_RANGES_TUPLES; tuple++) {
174 		phys_base = sc->ranges[tuple].phys_base;
175 		pci_base = sc->ranges[tuple].pci_base;
176 		size = sc->ranges[tuple].size;
177 		rid = tuple + 1;
178 		if (size == 0)
179 			continue; /* empty range element */
180 		switch (FLAG_TYPE(sc->ranges[tuple].flags)) {
181 		case FLAG_TYPE_PMEM:
182 			sc->has_pmem = true;
183 			range_descr = "prefetch";
184 			flags = RF_PREFETCHABLE;
185 			type = SYS_RES_MEMORY;
186 			error = rman_manage_region(&sc->pmem_rman,
187 			   pci_base, pci_base + size - 1);
188 			break;
189 		case FLAG_TYPE_MEM:
190 			range_descr = "memory";
191 			flags = 0;
192 			type = SYS_RES_MEMORY;
193 			error = rman_manage_region(&sc->mem_rman,
194 			   pci_base, pci_base + size - 1);
195 			break;
196 		case FLAG_TYPE_IO:
197 			range_descr = "I/O port";
198 			flags = 0;
199 			type = SYS_RES_IOPORT;
200 			error = rman_manage_region(&sc->io_rman,
201 			   pci_base, pci_base + size - 1);
202 			break;
203 		default:
204 			continue;
205 		}
206 		if (error) {
207 			device_printf(dev, "rman_manage_region() failed."
208 						"error = %d\n", error);
209 			goto err_rman_manage;
210 		}
211 		error = bus_set_resource(dev, type, rid, phys_base, size);
212 		if (error != 0) {
213 			device_printf(dev,
214 			    "failed to set resource for range %d: %d\n", tuple,
215 			    error);
216 			goto err_rman_manage;
217 		}
218 		sc->ranges[tuple].res = bus_alloc_resource_any(dev, type, &rid,
219 		    RF_ACTIVE | RF_UNMAPPED | flags);
220 		if (sc->ranges[tuple].res == NULL) {
221 			device_printf(dev,
222 			    "failed to allocate resource for range %d\n", tuple);
223 			error = ENXIO;
224 			goto err_rman_manage;
225 		}
226 		if (bootverbose)
227 			device_printf(dev,
228 			    "PCI addr: 0x%jx, CPU addr: 0x%jx, Size: 0x%jx, Type: %s\n",
229 			    pci_base, phys_base, size, range_descr);
230 	}
231 
232 	return (0);
233 
234 err_rman_manage:
235 	for (tuple = 0; tuple < MAX_RANGES_TUPLES; tuple++) {
236 		if (sc->ranges[tuple].size == 0)
237 			continue; /* empty range element */
238 		switch (FLAG_TYPE(sc->ranges[tuple].flags)) {
239 		case FLAG_TYPE_PMEM:
240 		case FLAG_TYPE_MEM:
241 			type = SYS_RES_MEMORY;
242 			break;
243 		case FLAG_TYPE_IO:
244 			type = SYS_RES_IOPORT;
245 			break;
246 		default:
247 			continue;
248 		}
249 		if (sc->ranges[tuple].res != NULL)
250 			bus_release_resource(dev, type, tuple + 1,
251 			    sc->ranges[tuple].res);
252 		bus_delete_resource(dev, type, tuple + 1);
253 	}
254 	rman_fini(&sc->io_rman);
255 err_io_rman:
256 	rman_fini(&sc->mem_rman);
257 err_mem_rman:
258 	rman_fini(&sc->pmem_rman);
259 err_pmem_rman:
260 	free(__DECONST(char *, sc->io_rman.rm_descr), M_DEVBUF);
261 	free(__DECONST(char *, sc->mem_rman.rm_descr), M_DEVBUF);
262 	free(__DECONST(char *, sc->pmem_rman.rm_descr), M_DEVBUF);
263 	if (sc->res != NULL)
264 		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->res);
265 err_resource:
266 	bus_dma_tag_destroy(sc->dmat);
267 	return (error);
268 }
269 
270 int
271 pci_host_generic_core_detach(device_t dev)
272 {
273 	struct generic_pcie_core_softc *sc;
274 	int error, tuple, type;
275 
276 	sc = device_get_softc(dev);
277 
278 	error = bus_generic_detach(dev);
279 	if (error != 0)
280 		return (error);
281 
282 	for (tuple = 0; tuple < MAX_RANGES_TUPLES; tuple++) {
283 		if (sc->ranges[tuple].size == 0)
284 			continue; /* empty range element */
285 		switch (FLAG_TYPE(sc->ranges[tuple].flags)) {
286 		case FLAG_TYPE_PMEM:
287 		case FLAG_TYPE_MEM:
288 			type = SYS_RES_MEMORY;
289 			break;
290 		case FLAG_TYPE_IO:
291 			type = SYS_RES_IOPORT;
292 			break;
293 		default:
294 			continue;
295 		}
296 		if (sc->ranges[tuple].res != NULL)
297 			bus_release_resource(dev, type, tuple + 1,
298 			    sc->ranges[tuple].res);
299 		bus_delete_resource(dev, type, tuple + 1);
300 	}
301 	rman_fini(&sc->io_rman);
302 	rman_fini(&sc->mem_rman);
303 	rman_fini(&sc->pmem_rman);
304 	free(__DECONST(char *, sc->io_rman.rm_descr), M_DEVBUF);
305 	free(__DECONST(char *, sc->mem_rman.rm_descr), M_DEVBUF);
306 	free(__DECONST(char *, sc->pmem_rman.rm_descr), M_DEVBUF);
307 	if (sc->res != NULL)
308 		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->res);
309 	bus_dma_tag_destroy(sc->dmat);
310 
311 	return (0);
312 }
313 
314 static uint32_t
315 generic_pcie_read_config(device_t dev, u_int bus, u_int slot,
316     u_int func, u_int reg, int bytes)
317 {
318 	struct generic_pcie_core_softc *sc;
319 	uint64_t offset;
320 	uint32_t data;
321 
322 	sc = device_get_softc(dev);
323 	if ((bus < sc->bus_start) || (bus > sc->bus_end))
324 		return (~0U);
325 	if ((slot > PCI_SLOTMAX) || (func > PCI_FUNCMAX) ||
326 	    (reg > PCIE_REGMAX))
327 		return (~0U);
328 	if ((sc->quirks & PCIE_ECAM_DESIGNWARE_QUIRK) && bus == 0 && slot > 0)
329 		return (~0U);
330 
331 	offset = PCIE_ADDR_OFFSET(bus - sc->bus_start, slot, func, reg);
332 
333 	switch (bytes) {
334 	case 1:
335 		data = bus_read_1(sc->res, offset);
336 		break;
337 	case 2:
338 		data = le16toh(bus_read_2(sc->res, offset));
339 		break;
340 	case 4:
341 		data = le32toh(bus_read_4(sc->res, offset));
342 		break;
343 	default:
344 		return (~0U);
345 	}
346 
347 	return (data);
348 }
349 
350 static void
351 generic_pcie_write_config(device_t dev, u_int bus, u_int slot,
352     u_int func, u_int reg, uint32_t val, int bytes)
353 {
354 	struct generic_pcie_core_softc *sc;
355 	uint64_t offset;
356 
357 	sc = device_get_softc(dev);
358 	if ((bus < sc->bus_start) || (bus > sc->bus_end))
359 		return;
360 	if ((slot > PCI_SLOTMAX) || (func > PCI_FUNCMAX) ||
361 	    (reg > PCIE_REGMAX))
362 		return;
363 
364 	offset = PCIE_ADDR_OFFSET(bus - sc->bus_start, slot, func, reg);
365 
366 	switch (bytes) {
367 	case 1:
368 		bus_write_1(sc->res, offset, val);
369 		break;
370 	case 2:
371 		bus_write_2(sc->res, offset, htole16(val));
372 		break;
373 	case 4:
374 		bus_write_4(sc->res, offset, htole32(val));
375 		break;
376 	default:
377 		return;
378 	}
379 }
380 
381 static int
382 generic_pcie_maxslots(device_t dev)
383 {
384 
385 	return (31); /* max slots per bus acc. to standard */
386 }
387 
388 static int
389 generic_pcie_read_ivar(device_t dev, device_t child, int index,
390     uintptr_t *result)
391 {
392 	struct generic_pcie_core_softc *sc;
393 
394 	sc = device_get_softc(dev);
395 
396 	if (index == PCIB_IVAR_BUS) {
397 		*result = sc->bus_start;
398 		return (0);
399 	}
400 
401 	if (index == PCIB_IVAR_DOMAIN) {
402 		*result = sc->ecam;
403 		return (0);
404 	}
405 
406 	if (bootverbose)
407 		device_printf(dev, "ERROR: Unknown index %d.\n", index);
408 	return (ENOENT);
409 }
410 
411 static int
412 generic_pcie_write_ivar(device_t dev, device_t child, int index,
413     uintptr_t value)
414 {
415 
416 	return (ENOENT);
417 }
418 
419 static struct rman *
420 generic_pcie_get_rman(device_t dev, int type, u_int flags)
421 {
422 	struct generic_pcie_core_softc *sc = device_get_softc(dev);
423 
424 	switch (type) {
425 	case SYS_RES_IOPORT:
426 		return (&sc->io_rman);
427 	case SYS_RES_MEMORY:
428 		if (sc->has_pmem && (flags & RF_PREFETCHABLE) != 0)
429 			return (&sc->pmem_rman);
430 		return (&sc->mem_rman);
431 	default:
432 		break;
433 	}
434 
435 	return (NULL);
436 }
437 
438 int
439 pci_host_generic_core_release_resource(device_t dev, device_t child, int type,
440     int rid, struct resource *res)
441 {
442 #if defined(NEW_PCIB) && defined(PCI_RES_BUS)
443 	struct generic_pcie_core_softc *sc;
444 
445 	sc = device_get_softc(dev);
446 #endif
447 	switch (type) {
448 #if defined(NEW_PCIB) && defined(PCI_RES_BUS)
449 	case PCI_RES_BUS:
450 		return (pci_domain_release_bus(sc->ecam, child, rid, res));
451 #endif
452 	case SYS_RES_IOPORT:
453 	case SYS_RES_MEMORY:
454 		return (bus_generic_rman_release_resource(dev, child, type, rid,
455 		    res));
456 	default:
457 		return (bus_generic_release_resource(dev, child, type, rid,
458 		    res));
459 	}
460 }
461 
462 static struct pcie_range *
463 generic_pcie_containing_range(device_t dev, int type, rman_res_t start,
464     rman_res_t end)
465 {
466 	struct generic_pcie_core_softc *sc = device_get_softc(dev);
467 	uint64_t pci_base;
468 	uint64_t size;
469 	int i, space;
470 
471 	switch (type) {
472 	case SYS_RES_IOPORT:
473 	case SYS_RES_MEMORY:
474 		break;
475 	default:
476 		return (NULL);
477 	}
478 
479 	for (i = 0; i < MAX_RANGES_TUPLES; i++) {
480 		pci_base = sc->ranges[i].pci_base;
481 		size = sc->ranges[i].size;
482 		if (size == 0)
483 			continue; /* empty range element */
484 
485 		if (start < pci_base || end >= pci_base + size)
486 			continue;
487 
488 		switch (FLAG_TYPE(sc->ranges[i].flags)) {
489 		case FLAG_TYPE_MEM:
490 		case FLAG_TYPE_PMEM:
491 			space = SYS_RES_MEMORY;
492 			break;
493 		case FLAG_TYPE_IO:
494 			space = SYS_RES_IOPORT;
495 			break;
496 		default:
497 			continue;
498 		}
499 
500 		if (type == space)
501 			return (&sc->ranges[i]);
502 	}
503 	return (NULL);
504 }
505 
506 static int
507 generic_pcie_translate_resource(device_t dev, int type, rman_res_t start,
508     rman_res_t *new_start)
509 {
510 	struct pcie_range *range;
511 
512 	/* Translate the address from a PCI address to a physical address */
513 	switch (type) {
514 	case SYS_RES_IOPORT:
515 	case SYS_RES_MEMORY:
516 		range = generic_pcie_containing_range(dev, type, start, start);
517 		if (range == NULL)
518 			return (ENOENT);
519 		*new_start = start - range->pci_base + range->phys_base;
520 		break;
521 	default:
522 		/* No translation for non-memory types */
523 		*new_start = start;
524 		break;
525 	}
526 
527 	return (0);
528 }
529 
530 struct resource *
531 pci_host_generic_core_alloc_resource(device_t dev, device_t child, int type,
532     int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
533 {
534 #if defined(NEW_PCIB) && defined(PCI_RES_BUS)
535 	struct generic_pcie_core_softc *sc;
536 #endif
537 	struct resource *res;
538 
539 #if defined(NEW_PCIB) && defined(PCI_RES_BUS)
540 	sc = device_get_softc(dev);
541 #endif
542 
543 	switch (type) {
544 #if defined(NEW_PCIB) && defined(PCI_RES_BUS)
545 	case PCI_RES_BUS:
546 		res = pci_domain_alloc_bus(sc->ecam, child, rid, start, end,
547 		    count, flags);
548 		break;
549 #endif
550 	case SYS_RES_IOPORT:
551 	case SYS_RES_MEMORY:
552 		res = bus_generic_rman_alloc_resource(dev, child, type, rid,
553 		    start, end, count, flags);
554 		break;
555 	default:
556 		res = bus_generic_alloc_resource(dev, child, type, rid, start,
557 		    end, count, flags);
558 		break;
559 	}
560 	if (res == NULL) {
561 		device_printf(dev, "%s FAIL: type=%d, rid=%d, "
562 		    "start=%016jx, end=%016jx, count=%016jx, flags=%x\n",
563 		    __func__, type, *rid, start, end, count, flags);
564 	}
565 	return (res);
566 }
567 
568 static int
569 generic_pcie_activate_resource(device_t dev, device_t child, int type,
570     int rid, struct resource *r)
571 {
572 #if defined(NEW_PCIB) && defined(PCI_RES_BUS)
573 	struct generic_pcie_core_softc *sc;
574 
575 	sc = device_get_softc(dev);
576 #endif
577 	switch (type) {
578 #if defined(NEW_PCIB) && defined(PCI_RES_BUS)
579 	case PCI_RES_BUS:
580 		return (pci_domain_activate_bus(sc->ecam, child, rid, r));
581 #endif
582 	case SYS_RES_IOPORT:
583 	case SYS_RES_MEMORY:
584 		return (bus_generic_rman_activate_resource(dev, child, type,
585 		    rid, r));
586 	default:
587 		return (bus_generic_activate_resource(dev, child, type, rid,
588 		    r));
589 	}
590 }
591 
592 static int
593 generic_pcie_deactivate_resource(device_t dev, device_t child, int type,
594     int rid, struct resource *r)
595 {
596 #if defined(NEW_PCIB) && defined(PCI_RES_BUS)
597 	struct generic_pcie_core_softc *sc;
598 
599 	sc = device_get_softc(dev);
600 #endif
601 	switch (type) {
602 #if defined(NEW_PCIB) && defined(PCI_RES_BUS)
603 	case PCI_RES_BUS:
604 		return (pci_domain_deactivate_bus(sc->ecam, child, rid, r));
605 #endif
606 	case SYS_RES_IOPORT:
607 	case SYS_RES_MEMORY:
608 		return (bus_generic_rman_deactivate_resource(dev, child, type,
609 		    rid, r));
610 	default:
611 		return (bus_generic_deactivate_resource(dev, child, type, rid,
612 		    r));
613 	}
614 }
615 
616 static int
617 generic_pcie_adjust_resource(device_t dev, device_t child, int type,
618     struct resource *res, rman_res_t start, rman_res_t end)
619 {
620 #if defined(NEW_PCIB) && defined(PCI_RES_BUS)
621 	struct generic_pcie_core_softc *sc;
622 
623 	sc = device_get_softc(dev);
624 #endif
625 	switch (type) {
626 #if defined(NEW_PCIB) && defined(PCI_RES_BUS)
627 	case PCI_RES_BUS:
628 		return (pci_domain_adjust_bus(sc->ecam, child, res, start,
629 		    end));
630 #endif
631 	case SYS_RES_IOPORT:
632 	case SYS_RES_MEMORY:
633 		return (bus_generic_rman_adjust_resource(dev, child, type, res,
634 		    start, end));
635 	default:
636 		return (bus_generic_adjust_resource(dev, child, type, res,
637 		    start, end));
638 	}
639 }
640 
641 static int
642 generic_pcie_map_resource(device_t dev, device_t child, int type,
643     struct resource *r, struct resource_map_request *argsp,
644     struct resource_map *map)
645 {
646 	struct resource_map_request args;
647 	struct pcie_range *range;
648 	rman_res_t length, start;
649 	int error;
650 
651 	switch (type) {
652 #if defined(NEW_PCIB) && defined(PCI_RES_BUS)
653 	case PCI_RES_BUS:
654 		return (EINVAL);
655 #endif
656 	case SYS_RES_IOPORT:
657 	case SYS_RES_MEMORY:
658 		break;
659 	default:
660 		return (bus_generic_map_resource(dev, child, type, r, argsp,
661 		    map));
662 	}
663 
664 	/* Resources must be active to be mapped. */
665 	if (!(rman_get_flags(r) & RF_ACTIVE))
666 		return (ENXIO);
667 
668 	resource_init_map_request(&args);
669 	error = resource_validate_map_request(r, argsp, &args, &start, &length);
670 	if (error)
671 		return (error);
672 
673 	range = generic_pcie_containing_range(dev, type, rman_get_start(r),
674 	    rman_get_end(r));
675 	if (range == NULL || range->res == NULL)
676 		return (ENOENT);
677 
678 	args.offset = start - range->pci_base;
679 	args.length = length;
680 	return (bus_generic_map_resource(dev, child, type, range->res, &args,
681 	    map));
682 }
683 
684 static int
685 generic_pcie_unmap_resource(device_t dev, device_t child, int type,
686     struct resource *r, struct resource_map *map)
687 {
688 	struct pcie_range *range;
689 
690 	switch (type) {
691 #if defined(NEW_PCIB) && defined(PCI_RES_BUS)
692 	case PCI_RES_BUS:
693 		return (EINVAL);
694 #endif
695 	case SYS_RES_IOPORT:
696 	case SYS_RES_MEMORY:
697 		range = generic_pcie_containing_range(dev, type,
698 		    rman_get_start(r), rman_get_end(r));
699 		if (range == NULL || range->res == NULL)
700 			return (ENOENT);
701 		r = range->res;
702 		break;
703 	default:
704 		break;
705 	}
706 	return (bus_generic_unmap_resource(dev, child, type, r, map));
707 }
708 
709 static bus_dma_tag_t
710 generic_pcie_get_dma_tag(device_t dev, device_t child)
711 {
712 	struct generic_pcie_core_softc *sc;
713 
714 	sc = device_get_softc(dev);
715 	return (sc->dmat);
716 }
717 
718 static device_method_t generic_pcie_methods[] = {
719 	DEVMETHOD(device_attach,		pci_host_generic_core_attach),
720 	DEVMETHOD(device_detach,		pci_host_generic_core_detach),
721 
722 	DEVMETHOD(bus_get_rman,			generic_pcie_get_rman),
723 	DEVMETHOD(bus_read_ivar,		generic_pcie_read_ivar),
724 	DEVMETHOD(bus_write_ivar,		generic_pcie_write_ivar),
725 	DEVMETHOD(bus_alloc_resource,		pci_host_generic_core_alloc_resource),
726 	DEVMETHOD(bus_adjust_resource,		generic_pcie_adjust_resource),
727 	DEVMETHOD(bus_activate_resource,	generic_pcie_activate_resource),
728 	DEVMETHOD(bus_deactivate_resource,	generic_pcie_deactivate_resource),
729 	DEVMETHOD(bus_release_resource,		pci_host_generic_core_release_resource),
730 	DEVMETHOD(bus_translate_resource,	generic_pcie_translate_resource),
731 	DEVMETHOD(bus_map_resource,		generic_pcie_map_resource),
732 	DEVMETHOD(bus_unmap_resource,		generic_pcie_unmap_resource),
733 	DEVMETHOD(bus_setup_intr,		bus_generic_setup_intr),
734 	DEVMETHOD(bus_teardown_intr,		bus_generic_teardown_intr),
735 
736 	DEVMETHOD(bus_get_dma_tag,		generic_pcie_get_dma_tag),
737 
738 	/* pcib interface */
739 	DEVMETHOD(pcib_maxslots,		generic_pcie_maxslots),
740 	DEVMETHOD(pcib_read_config,		generic_pcie_read_config),
741 	DEVMETHOD(pcib_write_config,		generic_pcie_write_config),
742 
743 	DEVMETHOD_END
744 };
745 
746 DEFINE_CLASS_0(pcib, generic_pcie_core_driver,
747     generic_pcie_methods, sizeof(struct generic_pcie_core_softc));
748