10dbe859dSJohn Baldwin /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni *
4179fa75eSJohn Baldwin * Copyright (c) 2011 Hudson River Trading LLC
50dbe859dSJohn Baldwin * Written by: John H. Baldwin <jhb@FreeBSD.org>
60dbe859dSJohn Baldwin * All rights reserved.
70dbe859dSJohn Baldwin *
80dbe859dSJohn Baldwin * Redistribution and use in source and binary forms, with or without
90dbe859dSJohn Baldwin * modification, are permitted provided that the following conditions
100dbe859dSJohn Baldwin * are met:
110dbe859dSJohn Baldwin * 1. Redistributions of source code must retain the above copyright
120dbe859dSJohn Baldwin * notice, this list of conditions and the following disclaimer.
130dbe859dSJohn Baldwin * 2. Redistributions in binary form must reproduce the above copyright
140dbe859dSJohn Baldwin * notice, this list of conditions and the following disclaimer in the
150dbe859dSJohn Baldwin * documentation and/or other materials provided with the distribution.
160dbe859dSJohn Baldwin *
170dbe859dSJohn Baldwin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
180dbe859dSJohn Baldwin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
190dbe859dSJohn Baldwin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
200dbe859dSJohn Baldwin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
210dbe859dSJohn Baldwin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
220dbe859dSJohn Baldwin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
230dbe859dSJohn Baldwin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
240dbe859dSJohn Baldwin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
250dbe859dSJohn Baldwin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
260dbe859dSJohn Baldwin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
270dbe859dSJohn Baldwin * SUCH DAMAGE.
280dbe859dSJohn Baldwin */
290dbe859dSJohn Baldwin
300dbe859dSJohn Baldwin #include <sys/cdefs.h>
310dbe859dSJohn Baldwin /*
320dbe859dSJohn Baldwin * Support APIs for Host to PCI bridge drivers and drivers that
330dbe859dSJohn Baldwin * provide PCI domains.
340dbe859dSJohn Baldwin */
350dbe859dSJohn Baldwin
3634ff71eeSJohn Baldwin #include <sys/param.h>
370dbe859dSJohn Baldwin #include <sys/bus.h>
384edef187SJohn Baldwin #include <sys/malloc.h>
390dbe859dSJohn Baldwin #include <sys/rman.h>
4034ff71eeSJohn Baldwin #include <sys/systm.h>
410dbe859dSJohn Baldwin
420dbe859dSJohn Baldwin #include <dev/pci/pcireg.h>
430dbe859dSJohn Baldwin #include <dev/pci/pcivar.h>
440dbe859dSJohn Baldwin #include <dev/pci/pcib_private.h>
450dbe859dSJohn Baldwin
460dbe859dSJohn Baldwin /*
470dbe859dSJohn Baldwin * Try to read the bus number of a host-PCI bridge using appropriate config
480dbe859dSJohn Baldwin * registers.
490dbe859dSJohn Baldwin */
500dbe859dSJohn Baldwin int
host_pcib_get_busno(pci_read_config_fn read_config,int bus,int slot,int func,uint8_t * busnum)510dbe859dSJohn Baldwin host_pcib_get_busno(pci_read_config_fn read_config, int bus, int slot, int func,
520dbe859dSJohn Baldwin uint8_t *busnum)
530dbe859dSJohn Baldwin {
540dbe859dSJohn Baldwin uint32_t id;
550dbe859dSJohn Baldwin
561587a9dbSJohn Baldwin id = read_config(0, bus, slot, func, PCIR_DEVVENDOR, 4);
570dbe859dSJohn Baldwin if (id == 0xffffffff)
580dbe859dSJohn Baldwin return (0);
590dbe859dSJohn Baldwin
600dbe859dSJohn Baldwin switch (id) {
610dbe859dSJohn Baldwin case 0x12258086:
620dbe859dSJohn Baldwin /* Intel 824?? */
630dbe859dSJohn Baldwin /* XXX This is a guess */
641587a9dbSJohn Baldwin /* *busnum = read_config(0, bus, slot, func, 0x41, 1); */
650dbe859dSJohn Baldwin *busnum = bus;
660dbe859dSJohn Baldwin break;
670dbe859dSJohn Baldwin case 0x84c48086:
680dbe859dSJohn Baldwin /* Intel 82454KX/GX (Orion) */
691587a9dbSJohn Baldwin *busnum = read_config(0, bus, slot, func, 0x4a, 1);
700dbe859dSJohn Baldwin break;
710dbe859dSJohn Baldwin case 0x84ca8086:
720dbe859dSJohn Baldwin /*
730dbe859dSJohn Baldwin * For the 450nx chipset, there is a whole bundle of
740dbe859dSJohn Baldwin * things pretending to be host bridges. The MIOC will
750dbe859dSJohn Baldwin * be seen first and isn't really a pci bridge (the
76db4fcadfSConrad Meyer * actual buses are attached to the PXB's). We need to
770dbe859dSJohn Baldwin * read the registers of the MIOC to figure out the
780dbe859dSJohn Baldwin * bus numbers for the PXB channels.
790dbe859dSJohn Baldwin *
800dbe859dSJohn Baldwin * Since the MIOC doesn't have a pci bus attached, we
810dbe859dSJohn Baldwin * pretend it wasn't there.
820dbe859dSJohn Baldwin */
830dbe859dSJohn Baldwin return (0);
840dbe859dSJohn Baldwin case 0x84cb8086:
850dbe859dSJohn Baldwin switch (slot) {
860dbe859dSJohn Baldwin case 0x12:
870dbe859dSJohn Baldwin /* Intel 82454NX PXB#0, Bus#A */
881587a9dbSJohn Baldwin *busnum = read_config(0, bus, 0x10, func, 0xd0, 1);
890dbe859dSJohn Baldwin break;
900dbe859dSJohn Baldwin case 0x13:
910dbe859dSJohn Baldwin /* Intel 82454NX PXB#0, Bus#B */
921587a9dbSJohn Baldwin *busnum = read_config(0, bus, 0x10, func, 0xd1, 1) + 1;
930dbe859dSJohn Baldwin break;
940dbe859dSJohn Baldwin case 0x14:
950dbe859dSJohn Baldwin /* Intel 82454NX PXB#1, Bus#A */
961587a9dbSJohn Baldwin *busnum = read_config(0, bus, 0x10, func, 0xd3, 1);
970dbe859dSJohn Baldwin break;
980dbe859dSJohn Baldwin case 0x15:
990dbe859dSJohn Baldwin /* Intel 82454NX PXB#1, Bus#B */
1001587a9dbSJohn Baldwin *busnum = read_config(0, bus, 0x10, func, 0xd4, 1) + 1;
1010dbe859dSJohn Baldwin break;
1020dbe859dSJohn Baldwin }
1030dbe859dSJohn Baldwin break;
1040dbe859dSJohn Baldwin
1050dbe859dSJohn Baldwin /* ServerWorks -- vendor 0x1166 */
1060dbe859dSJohn Baldwin case 0x00051166:
1070dbe859dSJohn Baldwin case 0x00061166:
1080dbe859dSJohn Baldwin case 0x00081166:
1090dbe859dSJohn Baldwin case 0x00091166:
1100dbe859dSJohn Baldwin case 0x00101166:
1110dbe859dSJohn Baldwin case 0x00111166:
1120dbe859dSJohn Baldwin case 0x00171166:
1130dbe859dSJohn Baldwin case 0x01011166:
1140dbe859dSJohn Baldwin case 0x010f1014:
1150dbe859dSJohn Baldwin case 0x01101166:
1160dbe859dSJohn Baldwin case 0x02011166:
1170dbe859dSJohn Baldwin case 0x02251166:
1180dbe859dSJohn Baldwin case 0x03021014:
1191587a9dbSJohn Baldwin *busnum = read_config(0, bus, slot, func, 0x44, 1);
1200dbe859dSJohn Baldwin break;
1210dbe859dSJohn Baldwin
1220dbe859dSJohn Baldwin /* Compaq/HP -- vendor 0x0e11 */
1230dbe859dSJohn Baldwin case 0x60100e11:
1241587a9dbSJohn Baldwin *busnum = read_config(0, bus, slot, func, 0xc8, 1);
1250dbe859dSJohn Baldwin break;
1260dbe859dSJohn Baldwin default:
1270dbe859dSJohn Baldwin /* Don't know how to read bus number. */
1280dbe859dSJohn Baldwin return 0;
1290dbe859dSJohn Baldwin }
1300dbe859dSJohn Baldwin
1310dbe859dSJohn Baldwin return 1;
1320dbe859dSJohn Baldwin }
13334ff71eeSJohn Baldwin
13434ff71eeSJohn Baldwin /*
13534ff71eeSJohn Baldwin * Return a pointer to a pretty name for a PCI device. If the device
13634ff71eeSJohn Baldwin * has a driver attached, the device's name is used, otherwise a name
13734ff71eeSJohn Baldwin * is generated from the device's PCI address.
13834ff71eeSJohn Baldwin */
13934ff71eeSJohn Baldwin const char *
pcib_child_name(device_t child)14034ff71eeSJohn Baldwin pcib_child_name(device_t child)
14134ff71eeSJohn Baldwin {
14234ff71eeSJohn Baldwin static char buf[64];
14334ff71eeSJohn Baldwin
14434ff71eeSJohn Baldwin if (device_get_nameunit(child) != NULL)
14534ff71eeSJohn Baldwin return (device_get_nameunit(child));
14634ff71eeSJohn Baldwin snprintf(buf, sizeof(buf), "pci%d:%d:%d:%d", pci_get_domain(child),
14734ff71eeSJohn Baldwin pci_get_bus(child), pci_get_slot(child), pci_get_function(child));
14834ff71eeSJohn Baldwin return (buf);
14934ff71eeSJohn Baldwin }
15034ff71eeSJohn Baldwin
15134ff71eeSJohn Baldwin /*
15234ff71eeSJohn Baldwin * Some Host-PCI bridge drivers know which resource ranges they can
15334ff71eeSJohn Baldwin * decode and should only allocate subranges to child PCI devices.
154e0c34b57SJohn Baldwin * This API provides a way to manage this. The bridge driver should
15534ff71eeSJohn Baldwin * initialize this structure during attach and call
15634ff71eeSJohn Baldwin * pcib_host_res_decodes() on each resource range it decodes. It can
15734ff71eeSJohn Baldwin * then use pcib_host_res_alloc() and pcib_host_res_adjust() as helper
15834ff71eeSJohn Baldwin * routines for BUS_ALLOC_RESOURCE() and BUS_ADJUST_RESOURCE(). This
15934ff71eeSJohn Baldwin * API assumes that resources for any decoded ranges can be safely
16034ff71eeSJohn Baldwin * allocated from the parent via bus_generic_alloc_resource().
16134ff71eeSJohn Baldwin */
16234ff71eeSJohn Baldwin int
pcib_host_res_init(device_t pcib,struct pcib_host_resources * hr)16334ff71eeSJohn Baldwin pcib_host_res_init(device_t pcib, struct pcib_host_resources *hr)
16434ff71eeSJohn Baldwin {
16534ff71eeSJohn Baldwin
16634ff71eeSJohn Baldwin hr->hr_pcib = pcib;
16734ff71eeSJohn Baldwin resource_list_init(&hr->hr_rl);
16834ff71eeSJohn Baldwin return (0);
16934ff71eeSJohn Baldwin }
17034ff71eeSJohn Baldwin
17134ff71eeSJohn Baldwin int
pcib_host_res_free(device_t pcib,struct pcib_host_resources * hr)17234ff71eeSJohn Baldwin pcib_host_res_free(device_t pcib, struct pcib_host_resources *hr)
17334ff71eeSJohn Baldwin {
17434ff71eeSJohn Baldwin
17534ff71eeSJohn Baldwin resource_list_free(&hr->hr_rl);
17634ff71eeSJohn Baldwin return (0);
17734ff71eeSJohn Baldwin }
17834ff71eeSJohn Baldwin
17934ff71eeSJohn Baldwin int
pcib_host_res_decodes(struct pcib_host_resources * hr,int type,rman_res_t start,rman_res_t end,u_int flags)1802dd1bdf1SJustin Hibbits pcib_host_res_decodes(struct pcib_host_resources *hr, int type, rman_res_t start,
1812dd1bdf1SJustin Hibbits rman_res_t end, u_int flags)
18234ff71eeSJohn Baldwin {
18334ff71eeSJohn Baldwin struct resource_list_entry *rle;
18434ff71eeSJohn Baldwin int rid;
18534ff71eeSJohn Baldwin
18634ff71eeSJohn Baldwin if (bootverbose)
187da1b038aSJustin Hibbits device_printf(hr->hr_pcib, "decoding %d %srange %#jx-%#jx\n",
18834ff71eeSJohn Baldwin type, flags & RF_PREFETCHABLE ? "prefetchable ": "", start,
18934ff71eeSJohn Baldwin end);
19034ff71eeSJohn Baldwin rid = resource_list_add_next(&hr->hr_rl, type, start, end,
19134ff71eeSJohn Baldwin end - start + 1);
19234ff71eeSJohn Baldwin if (flags & RF_PREFETCHABLE) {
19334ff71eeSJohn Baldwin KASSERT(type == SYS_RES_MEMORY,
19434ff71eeSJohn Baldwin ("only memory is prefetchable"));
19534ff71eeSJohn Baldwin rle = resource_list_find(&hr->hr_rl, type, rid);
19634ff71eeSJohn Baldwin rle->flags = RLE_PREFETCH;
19734ff71eeSJohn Baldwin }
19834ff71eeSJohn Baldwin return (0);
19934ff71eeSJohn Baldwin }
20034ff71eeSJohn Baldwin
20134ff71eeSJohn Baldwin struct resource *
pcib_host_res_alloc(struct pcib_host_resources * hr,device_t dev,int type,int * rid,rman_res_t start,rman_res_t end,rman_res_t count,u_int flags)20234ff71eeSJohn Baldwin pcib_host_res_alloc(struct pcib_host_resources *hr, device_t dev, int type,
2032dd1bdf1SJustin Hibbits int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
20434ff71eeSJohn Baldwin {
20534ff71eeSJohn Baldwin struct resource_list_entry *rle;
20634ff71eeSJohn Baldwin struct resource *r;
2072dd1bdf1SJustin Hibbits rman_res_t new_start, new_end;
20834ff71eeSJohn Baldwin
20934ff71eeSJohn Baldwin if (flags & RF_PREFETCHABLE)
21034ff71eeSJohn Baldwin KASSERT(type == SYS_RES_MEMORY,
21134ff71eeSJohn Baldwin ("only memory is prefetchable"));
21234ff71eeSJohn Baldwin
21334ff71eeSJohn Baldwin rle = resource_list_find(&hr->hr_rl, type, 0);
21434ff71eeSJohn Baldwin if (rle == NULL) {
21534ff71eeSJohn Baldwin /*
21634ff71eeSJohn Baldwin * No decoding ranges for this resource type, just pass
21734ff71eeSJohn Baldwin * the request up to the parent.
21834ff71eeSJohn Baldwin */
21934ff71eeSJohn Baldwin return (bus_generic_alloc_resource(hr->hr_pcib, dev, type, rid,
22034ff71eeSJohn Baldwin start, end, count, flags));
22134ff71eeSJohn Baldwin }
22234ff71eeSJohn Baldwin
22334ff71eeSJohn Baldwin restart:
22434ff71eeSJohn Baldwin /* Try to allocate from each decoded range. */
22534ff71eeSJohn Baldwin for (; rle != NULL; rle = STAILQ_NEXT(rle, link)) {
22634ff71eeSJohn Baldwin if (rle->type != type)
22734ff71eeSJohn Baldwin continue;
22834ff71eeSJohn Baldwin if (((flags & RF_PREFETCHABLE) != 0) !=
22934ff71eeSJohn Baldwin ((rle->flags & RLE_PREFETCH) != 0))
23034ff71eeSJohn Baldwin continue;
231da1b038aSJustin Hibbits new_start = ummax(start, rle->start);
232da1b038aSJustin Hibbits new_end = ummin(end, rle->end);
23334ff71eeSJohn Baldwin if (new_start > new_end ||
23434ff71eeSJohn Baldwin new_start + count - 1 > new_end ||
23534ff71eeSJohn Baldwin new_start + count < new_start)
23634ff71eeSJohn Baldwin continue;
23734ff71eeSJohn Baldwin r = bus_generic_alloc_resource(hr->hr_pcib, dev, type, rid,
23834ff71eeSJohn Baldwin new_start, new_end, count, flags);
23934ff71eeSJohn Baldwin if (r != NULL) {
24034ff71eeSJohn Baldwin if (bootverbose)
24134ff71eeSJohn Baldwin device_printf(hr->hr_pcib,
242da1b038aSJustin Hibbits "allocated type %d (%#jx-%#jx) for rid %x of %s\n",
24334ff71eeSJohn Baldwin type, rman_get_start(r), rman_get_end(r),
24434ff71eeSJohn Baldwin *rid, pcib_child_name(dev));
24534ff71eeSJohn Baldwin return (r);
24634ff71eeSJohn Baldwin }
24734ff71eeSJohn Baldwin }
24834ff71eeSJohn Baldwin
24934ff71eeSJohn Baldwin /*
25034ff71eeSJohn Baldwin * If we failed to find a prefetch range for a memory
25134ff71eeSJohn Baldwin * resource, try again without prefetch.
25234ff71eeSJohn Baldwin */
25334ff71eeSJohn Baldwin if (flags & RF_PREFETCHABLE) {
25434ff71eeSJohn Baldwin flags &= ~RF_PREFETCHABLE;
25534ff71eeSJohn Baldwin rle = resource_list_find(&hr->hr_rl, type, 0);
25634ff71eeSJohn Baldwin goto restart;
25734ff71eeSJohn Baldwin }
25834ff71eeSJohn Baldwin return (NULL);
25934ff71eeSJohn Baldwin }
26034ff71eeSJohn Baldwin
26134ff71eeSJohn Baldwin int
pcib_host_res_adjust(struct pcib_host_resources * hr,device_t dev,struct resource * r,rman_res_t start,rman_res_t end)262fef01f04SJohn Baldwin pcib_host_res_adjust(struct pcib_host_resources *hr, device_t dev,
2632dd1bdf1SJustin Hibbits struct resource *r, rman_res_t start, rman_res_t end)
26434ff71eeSJohn Baldwin {
26534ff71eeSJohn Baldwin struct resource_list_entry *rle;
26634ff71eeSJohn Baldwin
267fef01f04SJohn Baldwin rle = resource_list_find(&hr->hr_rl, rman_get_type(r), 0);
26834ff71eeSJohn Baldwin if (rle == NULL) {
26934ff71eeSJohn Baldwin /*
27034ff71eeSJohn Baldwin * No decoding ranges for this resource type, just pass
27134ff71eeSJohn Baldwin * the request up to the parent.
27234ff71eeSJohn Baldwin */
273fef01f04SJohn Baldwin return (bus_generic_adjust_resource(hr->hr_pcib, dev, r, start,
274fef01f04SJohn Baldwin end));
27534ff71eeSJohn Baldwin }
27634ff71eeSJohn Baldwin
27734ff71eeSJohn Baldwin /* Only allow adjustments that stay within a decoded range. */
27834ff71eeSJohn Baldwin for (; rle != NULL; rle = STAILQ_NEXT(rle, link)) {
27934ff71eeSJohn Baldwin if (rle->start <= start && rle->end >= end)
28034ff71eeSJohn Baldwin return (bus_generic_adjust_resource(hr->hr_pcib, dev,
281fef01f04SJohn Baldwin r, start, end));
28234ff71eeSJohn Baldwin }
28334ff71eeSJohn Baldwin return (ERANGE);
28434ff71eeSJohn Baldwin }
2854edef187SJohn Baldwin
2864edef187SJohn Baldwin struct pci_domain {
2874edef187SJohn Baldwin int pd_domain;
2884edef187SJohn Baldwin struct rman pd_bus_rman;
2894edef187SJohn Baldwin TAILQ_ENTRY(pci_domain) pd_link;
2904edef187SJohn Baldwin };
2914edef187SJohn Baldwin
2924edef187SJohn Baldwin static TAILQ_HEAD(, pci_domain) domains = TAILQ_HEAD_INITIALIZER(domains);
2934edef187SJohn Baldwin
2944edef187SJohn Baldwin /*
2954edef187SJohn Baldwin * Each PCI domain maintains its own resource manager for PCI bus
2964edef187SJohn Baldwin * numbers in that domain. Domain objects are created on first use.
2974edef187SJohn Baldwin * Host to PCI bridge drivers and PCI-PCI bridge drivers should
2984edef187SJohn Baldwin * allocate their bus ranges from their domain.
2994edef187SJohn Baldwin */
3004edef187SJohn Baldwin static struct pci_domain *
pci_find_domain(int domain)3014edef187SJohn Baldwin pci_find_domain(int domain)
3024edef187SJohn Baldwin {
3034edef187SJohn Baldwin struct pci_domain *d;
3044edef187SJohn Baldwin char buf[64];
3054edef187SJohn Baldwin int error;
3064edef187SJohn Baldwin
3074edef187SJohn Baldwin TAILQ_FOREACH(d, &domains, pd_link) {
3084edef187SJohn Baldwin if (d->pd_domain == domain)
3094edef187SJohn Baldwin return (d);
3104edef187SJohn Baldwin }
3114edef187SJohn Baldwin
3124edef187SJohn Baldwin snprintf(buf, sizeof(buf), "PCI domain %d bus numbers", domain);
3134edef187SJohn Baldwin d = malloc(sizeof(*d) + strlen(buf) + 1, M_DEVBUF, M_WAITOK | M_ZERO);
3144edef187SJohn Baldwin d->pd_domain = domain;
3154edef187SJohn Baldwin d->pd_bus_rman.rm_start = 0;
3164edef187SJohn Baldwin d->pd_bus_rman.rm_end = PCI_BUSMAX;
3174edef187SJohn Baldwin d->pd_bus_rman.rm_type = RMAN_ARRAY;
3184edef187SJohn Baldwin strcpy((char *)(d + 1), buf);
3194edef187SJohn Baldwin d->pd_bus_rman.rm_descr = (char *)(d + 1);
3204edef187SJohn Baldwin error = rman_init(&d->pd_bus_rman);
3214edef187SJohn Baldwin if (error == 0)
3224edef187SJohn Baldwin error = rman_manage_region(&d->pd_bus_rman, 0, PCI_BUSMAX);
3234edef187SJohn Baldwin if (error)
3244edef187SJohn Baldwin panic("Failed to initialize PCI domain %d rman", domain);
3254edef187SJohn Baldwin TAILQ_INSERT_TAIL(&domains, d, pd_link);
3264edef187SJohn Baldwin return (d);
3274edef187SJohn Baldwin }
3284edef187SJohn Baldwin
3294edef187SJohn Baldwin struct resource *
pci_domain_alloc_bus(int domain,device_t dev,int * rid,rman_res_t start,rman_res_t end,rman_res_t count,u_int flags)3302dd1bdf1SJustin Hibbits pci_domain_alloc_bus(int domain, device_t dev, int *rid, rman_res_t start,
3312dd1bdf1SJustin Hibbits rman_res_t end, rman_res_t count, u_int flags)
3324edef187SJohn Baldwin {
3334edef187SJohn Baldwin struct pci_domain *d;
3344edef187SJohn Baldwin struct resource *res;
3354edef187SJohn Baldwin
3364edef187SJohn Baldwin if (domain < 0 || domain > PCI_DOMAINMAX)
3374edef187SJohn Baldwin return (NULL);
3384edef187SJohn Baldwin d = pci_find_domain(domain);
3394edef187SJohn Baldwin res = rman_reserve_resource(&d->pd_bus_rman, start, end, count, flags,
3404edef187SJohn Baldwin dev);
3414edef187SJohn Baldwin if (res == NULL)
3424edef187SJohn Baldwin return (NULL);
3434edef187SJohn Baldwin
3444edef187SJohn Baldwin rman_set_rid(res, *rid);
3451b9bcfffSJohn Baldwin rman_set_type(res, PCI_RES_BUS);
3464edef187SJohn Baldwin return (res);
3474edef187SJohn Baldwin }
3484edef187SJohn Baldwin
3494edef187SJohn Baldwin int
pci_domain_adjust_bus(int domain,device_t dev,struct resource * r,rman_res_t start,rman_res_t end)3504edef187SJohn Baldwin pci_domain_adjust_bus(int domain, device_t dev, struct resource *r,
3512dd1bdf1SJustin Hibbits rman_res_t start, rman_res_t end)
3524edef187SJohn Baldwin {
3534edef187SJohn Baldwin #ifdef INVARIANTS
3544edef187SJohn Baldwin struct pci_domain *d;
3554edef187SJohn Baldwin #endif
3564edef187SJohn Baldwin
3574edef187SJohn Baldwin if (domain < 0 || domain > PCI_DOMAINMAX)
3584edef187SJohn Baldwin return (EINVAL);
3594edef187SJohn Baldwin #ifdef INVARIANTS
3604edef187SJohn Baldwin d = pci_find_domain(domain);
3614edef187SJohn Baldwin KASSERT(rman_is_region_manager(r, &d->pd_bus_rman), ("bad resource"));
3624edef187SJohn Baldwin #endif
3634edef187SJohn Baldwin return (rman_adjust_resource(r, start, end));
3644edef187SJohn Baldwin }
3654edef187SJohn Baldwin
3664edef187SJohn Baldwin int
pci_domain_release_bus(int domain,device_t dev,struct resource * r)367*9dbf5b0eSJohn Baldwin pci_domain_release_bus(int domain, device_t dev, struct resource *r)
3684edef187SJohn Baldwin {
3694edef187SJohn Baldwin #ifdef INVARIANTS
3704edef187SJohn Baldwin struct pci_domain *d;
3714edef187SJohn Baldwin #endif
3724edef187SJohn Baldwin
3734edef187SJohn Baldwin if (domain < 0 || domain > PCI_DOMAINMAX)
3744edef187SJohn Baldwin return (EINVAL);
3754edef187SJohn Baldwin #ifdef INVARIANTS
3764edef187SJohn Baldwin d = pci_find_domain(domain);
3774edef187SJohn Baldwin KASSERT(rman_is_region_manager(r, &d->pd_bus_rman), ("bad resource"));
3784edef187SJohn Baldwin #endif
3794edef187SJohn Baldwin return (rman_release_resource(r));
3804edef187SJohn Baldwin }
38123e3b83aSJohn Baldwin
38223e3b83aSJohn Baldwin int
pci_domain_activate_bus(int domain,device_t dev,struct resource * r)3832baed46eSJohn Baldwin pci_domain_activate_bus(int domain, device_t dev, struct resource *r)
38423e3b83aSJohn Baldwin {
38523e3b83aSJohn Baldwin #ifdef INVARIANTS
38623e3b83aSJohn Baldwin struct pci_domain *d;
38723e3b83aSJohn Baldwin #endif
38823e3b83aSJohn Baldwin
38923e3b83aSJohn Baldwin if (domain < 0 || domain > PCI_DOMAINMAX)
39023e3b83aSJohn Baldwin return (EINVAL);
39123e3b83aSJohn Baldwin #ifdef INVARIANTS
39223e3b83aSJohn Baldwin d = pci_find_domain(domain);
39323e3b83aSJohn Baldwin KASSERT(rman_is_region_manager(r, &d->pd_bus_rman), ("bad resource"));
39423e3b83aSJohn Baldwin #endif
39523e3b83aSJohn Baldwin return (rman_activate_resource(r));
39623e3b83aSJohn Baldwin }
39723e3b83aSJohn Baldwin
39823e3b83aSJohn Baldwin int
pci_domain_deactivate_bus(int domain,device_t dev,struct resource * r)3992baed46eSJohn Baldwin pci_domain_deactivate_bus(int domain, device_t dev, struct resource *r)
40023e3b83aSJohn Baldwin {
40123e3b83aSJohn Baldwin #ifdef INVARIANTS
40223e3b83aSJohn Baldwin struct pci_domain *d;
40323e3b83aSJohn Baldwin #endif
40423e3b83aSJohn Baldwin
40523e3b83aSJohn Baldwin if (domain < 0 || domain > PCI_DOMAINMAX)
40623e3b83aSJohn Baldwin return (EINVAL);
40723e3b83aSJohn Baldwin #ifdef INVARIANTS
40823e3b83aSJohn Baldwin d = pci_find_domain(domain);
40923e3b83aSJohn Baldwin KASSERT(rman_is_region_manager(r, &d->pd_bus_rman), ("bad resource"));
41023e3b83aSJohn Baldwin #endif
41123e3b83aSJohn Baldwin return (rman_deactivate_resource(r));
41223e3b83aSJohn Baldwin }
413