pci_subr.c revision 294883
190792Sgshapiro/*- 2261370Sgshapiro * Copyright (c) 2011 Hudson River Trading LLC 390792Sgshapiro * Written by: John H. Baldwin <jhb@FreeBSD.org> 490792Sgshapiro * All rights reserved. 590792Sgshapiro * 690792Sgshapiro * Redistribution and use in source and binary forms, with or without 790792Sgshapiro * modification, are permitted provided that the following conditions 890792Sgshapiro * are met: 990792Sgshapiro * 1. Redistributions of source code must retain the above copyright 10168515Sgshapiro * notice, this list of conditions and the following disclaimer. 11168515Sgshapiro * 2. Redistributions in binary form must reproduce the above copyright 12168515Sgshapiro * notice, this list of conditions and the following disclaimer in the 1390792Sgshapiro * documentation and/or other materials provided with the distribution. 14266711Sgshapiro * 1590792Sgshapiro * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1690792Sgshapiro * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1790792Sgshapiro * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1890792Sgshapiro * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1990792Sgshapiro * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2090792Sgshapiro * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2190792Sgshapiro * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2290792Sgshapiro * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2390792Sgshapiro * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2490792Sgshapiro * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2590792Sgshapiro * SUCH DAMAGE. 2690792Sgshapiro */ 2790792Sgshapiro 2890792Sgshapiro#include <sys/cdefs.h> 2990792Sgshapiro__FBSDID("$FreeBSD: head/sys/dev/pci/pci_subr.c 294883 2016-01-27 02:23:54Z jhibbits $"); 3094334Sgshapiro 3194334Sgshapiro/* 3294334Sgshapiro * Support APIs for Host to PCI bridge drivers and drivers that 3390792Sgshapiro * provide PCI domains. 3490792Sgshapiro */ 3590792Sgshapiro 3690792Sgshapiro#include <sys/param.h> 3790792Sgshapiro#include <sys/bus.h> 3890792Sgshapiro#include <sys/malloc.h> 39141858Sgshapiro#include <sys/rman.h> 40141858Sgshapiro#include <sys/systm.h> 4190792Sgshapiro 4290792Sgshapiro#include <dev/pci/pcireg.h> 4390792Sgshapiro#include <dev/pci/pcivar.h> 4490792Sgshapiro#include <dev/pci/pcib_private.h> 4590792Sgshapiro 4690792Sgshapiro/* 4790792Sgshapiro * Try to read the bus number of a host-PCI bridge using appropriate config 4890792Sgshapiro * registers. 4990792Sgshapiro */ 5090792Sgshapiroint 5190792Sgshapirohost_pcib_get_busno(pci_read_config_fn read_config, int bus, int slot, int func, 5290792Sgshapiro uint8_t *busnum) 53157001Sgshapiro{ 54157001Sgshapiro uint32_t id; 55157001Sgshapiro 56157001Sgshapiro id = read_config(bus, slot, func, PCIR_DEVVENDOR, 4); 57157001Sgshapiro if (id == 0xffffffff) 58157001Sgshapiro return (0); 59157001Sgshapiro 60157001Sgshapiro switch (id) { 61157001Sgshapiro case 0x12258086: 62157001Sgshapiro /* Intel 824?? */ 63157001Sgshapiro /* XXX This is a guess */ 64157001Sgshapiro /* *busnum = read_config(bus, slot, func, 0x41, 1); */ 6590792Sgshapiro *busnum = bus; 6690792Sgshapiro break; 6790792Sgshapiro case 0x84c48086: 6890792Sgshapiro /* Intel 82454KX/GX (Orion) */ 6990792Sgshapiro *busnum = read_config(bus, slot, func, 0x4a, 1); 7090792Sgshapiro break; 7190792Sgshapiro case 0x84ca8086: 72132943Sgshapiro /* 7390792Sgshapiro * For the 450nx chipset, there is a whole bundle of 74132943Sgshapiro * things pretending to be host bridges. The MIOC will 75157001Sgshapiro * be seen first and isn't really a pci bridge (the 7690792Sgshapiro * actual busses are attached to the PXB's). We need to 7790792Sgshapiro * read the registers of the MIOC to figure out the 7890792Sgshapiro * bus numbers for the PXB channels. 7990792Sgshapiro * 8090792Sgshapiro * Since the MIOC doesn't have a pci bus attached, we 8190792Sgshapiro * pretend it wasn't there. 8290792Sgshapiro */ 8390792Sgshapiro return (0); 8490792Sgshapiro case 0x84cb8086: 8590792Sgshapiro switch (slot) { 8690792Sgshapiro case 0x12: 8790792Sgshapiro /* Intel 82454NX PXB#0, Bus#A */ 8890792Sgshapiro *busnum = read_config(bus, 0x10, func, 0xd0, 1); 8990792Sgshapiro break; 9090792Sgshapiro case 0x13: 9190792Sgshapiro /* Intel 82454NX PXB#0, Bus#B */ 9290792Sgshapiro *busnum = read_config(bus, 0x10, func, 0xd1, 1) + 1; 9390792Sgshapiro break; 9490792Sgshapiro case 0x14: 9590792Sgshapiro /* Intel 82454NX PXB#1, Bus#A */ 9694334Sgshapiro *busnum = read_config(bus, 0x10, func, 0xd3, 1); 9794334Sgshapiro break; 9890792Sgshapiro case 0x15: 9990792Sgshapiro /* Intel 82454NX PXB#1, Bus#B */ 10090792Sgshapiro *busnum = read_config(bus, 0x10, func, 0xd4, 1) + 1; 101168515Sgshapiro break; 10290792Sgshapiro } 10390792Sgshapiro break; 10490792Sgshapiro 10590792Sgshapiro /* ServerWorks -- vendor 0x1166 */ 10690792Sgshapiro case 0x00051166: 10790792Sgshapiro case 0x00061166: 10890792Sgshapiro case 0x00081166: 10990792Sgshapiro case 0x00091166: 11090792Sgshapiro case 0x00101166: 11190792Sgshapiro case 0x00111166: 11290792Sgshapiro case 0x00171166: 11390792Sgshapiro case 0x01011166: 11490792Sgshapiro case 0x010f1014: 11590792Sgshapiro case 0x01101166: 11690792Sgshapiro case 0x02011166: 11790792Sgshapiro case 0x02251166: 11890792Sgshapiro case 0x03021014: 11990792Sgshapiro *busnum = read_config(bus, slot, func, 0x44, 1); 12090792Sgshapiro break; 12190792Sgshapiro 12290792Sgshapiro /* Compaq/HP -- vendor 0x0e11 */ 12390792Sgshapiro case 0x60100e11: 12490792Sgshapiro *busnum = read_config(bus, slot, func, 0xc8, 1); 12590792Sgshapiro break; 12690792Sgshapiro default: 12790792Sgshapiro /* Don't know how to read bus number. */ 12890792Sgshapiro return 0; 12990792Sgshapiro } 13090792Sgshapiro 13190792Sgshapiro return 1; 13290792Sgshapiro} 13390792Sgshapiro 13490792Sgshapiro#ifdef NEW_PCIB 13590792Sgshapiro/* 13690792Sgshapiro * Return a pointer to a pretty name for a PCI device. If the device 13790792Sgshapiro * has a driver attached, the device's name is used, otherwise a name 13890792Sgshapiro * is generated from the device's PCI address. 13990792Sgshapiro */ 14090792Sgshapiroconst char * 14190792Sgshapiropcib_child_name(device_t child) 14290792Sgshapiro{ 14390792Sgshapiro static char buf[64]; 14490792Sgshapiro 14590792Sgshapiro if (device_get_nameunit(child) != NULL) 14690792Sgshapiro return (device_get_nameunit(child)); 147141858Sgshapiro snprintf(buf, sizeof(buf), "pci%d:%d:%d:%d", pci_get_domain(child), 148132943Sgshapiro pci_get_bus(child), pci_get_slot(child), pci_get_function(child)); 14990792Sgshapiro return (buf); 150132943Sgshapiro} 15190792Sgshapiro 15290792Sgshapiro/* 15390792Sgshapiro * Some Host-PCI bridge drivers know which resource ranges they can 15490792Sgshapiro * decode and should only allocate subranges to child PCI devices. 155132943Sgshapiro * This API provides a way to manage this. The bridge driver should 156132943Sgshapiro * initialize this structure during attach and call 157132943Sgshapiro * pcib_host_res_decodes() on each resource range it decodes. It can 158132943Sgshapiro * then use pcib_host_res_alloc() and pcib_host_res_adjust() as helper 159132943Sgshapiro * routines for BUS_ALLOC_RESOURCE() and BUS_ADJUST_RESOURCE(). This 160132943Sgshapiro * API assumes that resources for any decoded ranges can be safely 161132943Sgshapiro * allocated from the parent via bus_generic_alloc_resource(). 16290792Sgshapiro */ 163132943Sgshapiroint 164132943Sgshapiropcib_host_res_init(device_t pcib, struct pcib_host_resources *hr) 165132943Sgshapiro{ 166132943Sgshapiro 167132943Sgshapiro hr->hr_pcib = pcib; 168132943Sgshapiro resource_list_init(&hr->hr_rl); 169132943Sgshapiro return (0); 170132943Sgshapiro} 17190792Sgshapiro 172132943Sgshapiroint 173132943Sgshapiropcib_host_res_free(device_t pcib, struct pcib_host_resources *hr) 174132943Sgshapiro{ 175132943Sgshapiro 176132943Sgshapiro resource_list_free(&hr->hr_rl); 177132943Sgshapiro return (0); 178132943Sgshapiro} 179132943Sgshapiro 180132943Sgshapiroint 181132943Sgshapiropcib_host_res_decodes(struct pcib_host_resources *hr, int type, rman_res_t start, 182132943Sgshapiro rman_res_t end, u_int flags) 183132943Sgshapiro{ 184132943Sgshapiro struct resource_list_entry *rle; 185132943Sgshapiro int rid; 186132943Sgshapiro 187132943Sgshapiro if (bootverbose) 188132943Sgshapiro device_printf(hr->hr_pcib, "decoding %d %srange %#lx-%#lx\n", 189132943Sgshapiro type, flags & RF_PREFETCHABLE ? "prefetchable ": "", start, 190132943Sgshapiro end); 191132943Sgshapiro rid = resource_list_add_next(&hr->hr_rl, type, start, end, 192132943Sgshapiro end - start + 1); 193132943Sgshapiro if (flags & RF_PREFETCHABLE) { 194132943Sgshapiro KASSERT(type == SYS_RES_MEMORY, 195132943Sgshapiro ("only memory is prefetchable")); 196132943Sgshapiro rle = resource_list_find(&hr->hr_rl, type, rid); 197132943Sgshapiro rle->flags = RLE_PREFETCH; 198132943Sgshapiro } 199132943Sgshapiro return (0); 200132943Sgshapiro} 201132943Sgshapiro 202132943Sgshapirostruct resource * 20390792Sgshapiropcib_host_res_alloc(struct pcib_host_resources *hr, device_t dev, int type, 204132943Sgshapiro int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) 205132943Sgshapiro{ 20690792Sgshapiro struct resource_list_entry *rle; 207132943Sgshapiro struct resource *r; 208132943Sgshapiro rman_res_t new_start, new_end; 209132943Sgshapiro 210132943Sgshapiro if (flags & RF_PREFETCHABLE) 211132943Sgshapiro KASSERT(type == SYS_RES_MEMORY, 21290792Sgshapiro ("only memory is prefetchable")); 213132943Sgshapiro 214132943Sgshapiro rle = resource_list_find(&hr->hr_rl, type, 0); 215132943Sgshapiro if (rle == NULL) { 21690792Sgshapiro /* 217132943Sgshapiro * No decoding ranges for this resource type, just pass 218132943Sgshapiro * the request up to the parent. 21990792Sgshapiro */ 220132943Sgshapiro return (bus_generic_alloc_resource(hr->hr_pcib, dev, type, rid, 22190792Sgshapiro start, end, count, flags)); 22290792Sgshapiro } 22390792Sgshapiro 22490792Sgshapirorestart: 22590792Sgshapiro /* Try to allocate from each decoded range. */ 22690792Sgshapiro for (; rle != NULL; rle = STAILQ_NEXT(rle, link)) { 22790792Sgshapiro if (rle->type != type) 22890792Sgshapiro continue; 22990792Sgshapiro if (((flags & RF_PREFETCHABLE) != 0) != 23090792Sgshapiro ((rle->flags & RLE_PREFETCH) != 0)) 23190792Sgshapiro continue; 23290792Sgshapiro new_start = ulmax(start, rle->start); 23390792Sgshapiro new_end = ulmin(end, rle->end); 23490792Sgshapiro if (new_start > new_end || 23590792Sgshapiro new_start + count - 1 > new_end || 23690792Sgshapiro new_start + count < new_start) 23790792Sgshapiro continue; 23890792Sgshapiro r = bus_generic_alloc_resource(hr->hr_pcib, dev, type, rid, 23990792Sgshapiro new_start, new_end, count, flags); 24090792Sgshapiro if (r != NULL) { 24190792Sgshapiro if (bootverbose) 24290792Sgshapiro device_printf(hr->hr_pcib, 24390792Sgshapiro "allocated type %d (%#lx-%#lx) for rid %x of %s\n", 24490792Sgshapiro type, rman_get_start(r), rman_get_end(r), 24590792Sgshapiro *rid, pcib_child_name(dev)); 24690792Sgshapiro return (r); 24790792Sgshapiro } 24890792Sgshapiro } 24990792Sgshapiro 25090792Sgshapiro /* 25190792Sgshapiro * If we failed to find a prefetch range for a memory 25290792Sgshapiro * resource, try again without prefetch. 25390792Sgshapiro */ 25490792Sgshapiro if (flags & RF_PREFETCHABLE) { 25590792Sgshapiro flags &= ~RF_PREFETCHABLE; 25690792Sgshapiro rle = resource_list_find(&hr->hr_rl, type, 0); 25790792Sgshapiro goto restart; 25890792Sgshapiro } 25990792Sgshapiro return (NULL); 26090792Sgshapiro} 26190792Sgshapiro 26290792Sgshapiroint 26390792Sgshapiropcib_host_res_adjust(struct pcib_host_resources *hr, device_t dev, int type, 26490792Sgshapiro struct resource *r, rman_res_t start, rman_res_t end) 26590792Sgshapiro{ 26690792Sgshapiro struct resource_list_entry *rle; 26790792Sgshapiro 26890792Sgshapiro rle = resource_list_find(&hr->hr_rl, type, 0); 26990792Sgshapiro if (rle == NULL) { 27090792Sgshapiro /* 27190792Sgshapiro * No decoding ranges for this resource type, just pass 27290792Sgshapiro * the request up to the parent. 27390792Sgshapiro */ 27490792Sgshapiro return (bus_generic_adjust_resource(hr->hr_pcib, dev, type, r, 27590792Sgshapiro start, end)); 27690792Sgshapiro } 27790792Sgshapiro 27890792Sgshapiro /* Only allow adjustments that stay within a decoded range. */ 27990792Sgshapiro for (; rle != NULL; rle = STAILQ_NEXT(rle, link)) { 28090792Sgshapiro if (rle->start <= start && rle->end >= end) 28190792Sgshapiro return (bus_generic_adjust_resource(hr->hr_pcib, dev, 28290792Sgshapiro type, r, start, end)); 28390792Sgshapiro } 28490792Sgshapiro return (ERANGE); 28590792Sgshapiro} 28690792Sgshapiro 287168515Sgshapiro#ifdef PCI_RES_BUS 28890792Sgshapirostruct pci_domain { 28990792Sgshapiro int pd_domain; 29090792Sgshapiro struct rman pd_bus_rman; 29190792Sgshapiro TAILQ_ENTRY(pci_domain) pd_link; 29290792Sgshapiro}; 29390792Sgshapiro 294168515Sgshapirostatic TAILQ_HEAD(, pci_domain) domains = TAILQ_HEAD_INITIALIZER(domains); 295168515Sgshapiro 296168515Sgshapiro/* 29790792Sgshapiro * Each PCI domain maintains its own resource manager for PCI bus 29890792Sgshapiro * numbers in that domain. Domain objects are created on first use. 299168515Sgshapiro * Host to PCI bridge drivers and PCI-PCI bridge drivers should 30090792Sgshapiro * allocate their bus ranges from their domain. 30190792Sgshapiro */ 30290792Sgshapirostatic struct pci_domain * 30390792Sgshapiropci_find_domain(int domain) 304168515Sgshapiro{ 30590792Sgshapiro struct pci_domain *d; 306168515Sgshapiro char buf[64]; 30790792Sgshapiro int error; 30890792Sgshapiro 30990792Sgshapiro TAILQ_FOREACH(d, &domains, pd_link) { 31090792Sgshapiro if (d->pd_domain == domain) 31190792Sgshapiro return (d); 312168515Sgshapiro } 313168515Sgshapiro 314168515Sgshapiro snprintf(buf, sizeof(buf), "PCI domain %d bus numbers", domain); 315168515Sgshapiro d = malloc(sizeof(*d) + strlen(buf) + 1, M_DEVBUF, M_WAITOK | M_ZERO); 31690792Sgshapiro d->pd_domain = domain; 31790792Sgshapiro d->pd_bus_rman.rm_start = 0; 31890792Sgshapiro d->pd_bus_rman.rm_end = PCI_BUSMAX; 31990792Sgshapiro d->pd_bus_rman.rm_type = RMAN_ARRAY; 32090792Sgshapiro strcpy((char *)(d + 1), buf); 321168515Sgshapiro d->pd_bus_rman.rm_descr = (char *)(d + 1); 322168515Sgshapiro error = rman_init(&d->pd_bus_rman); 323168515Sgshapiro if (error == 0) 324168515Sgshapiro error = rman_manage_region(&d->pd_bus_rman, 0, PCI_BUSMAX); 325168515Sgshapiro if (error) 326168515Sgshapiro panic("Failed to initialize PCI domain %d rman", domain); 327168515Sgshapiro TAILQ_INSERT_TAIL(&domains, d, pd_link); 328168515Sgshapiro return (d); 329168515Sgshapiro} 330168515Sgshapiro 331168515Sgshapirostruct resource * 332168515Sgshapiropci_domain_alloc_bus(int domain, device_t dev, int *rid, rman_res_t start, 333168515Sgshapiro rman_res_t end, rman_res_t count, u_int flags) 334168515Sgshapiro{ 335168515Sgshapiro struct pci_domain *d; 336168515Sgshapiro struct resource *res; 337168515Sgshapiro 338168515Sgshapiro if (domain < 0 || domain > PCI_DOMAINMAX) 339168515Sgshapiro return (NULL); 340168515Sgshapiro d = pci_find_domain(domain); 341168515Sgshapiro res = rman_reserve_resource(&d->pd_bus_rman, start, end, count, flags, 342168515Sgshapiro dev); 343168515Sgshapiro if (res == NULL) 344168515Sgshapiro return (NULL); 345168515Sgshapiro 346168515Sgshapiro rman_set_rid(res, *rid); 347168515Sgshapiro return (res); 34890792Sgshapiro} 34990792Sgshapiro 35090792Sgshapiroint 35190792Sgshapiropci_domain_adjust_bus(int domain, device_t dev, struct resource *r, 35290792Sgshapiro rman_res_t start, rman_res_t end) 35390792Sgshapiro{ 35490792Sgshapiro#ifdef INVARIANTS 355168515Sgshapiro struct pci_domain *d; 356168515Sgshapiro#endif 35790792Sgshapiro 35890792Sgshapiro if (domain < 0 || domain > PCI_DOMAINMAX) 35990792Sgshapiro return (EINVAL); 36090792Sgshapiro#ifdef INVARIANTS 36190792Sgshapiro d = pci_find_domain(domain); 36290792Sgshapiro KASSERT(rman_is_region_manager(r, &d->pd_bus_rman), ("bad resource")); 36390792Sgshapiro#endif 36490792Sgshapiro return (rman_adjust_resource(r, start, end)); 36590792Sgshapiro} 36690792Sgshapiro 36790792Sgshapiroint 36890792Sgshapiropci_domain_release_bus(int domain, device_t dev, int rid, struct resource *r) 36990792Sgshapiro{ 37090792Sgshapiro#ifdef INVARIANTS 37190792Sgshapiro struct pci_domain *d; 37290792Sgshapiro#endif 37390792Sgshapiro 37490792Sgshapiro if (domain < 0 || domain > PCI_DOMAINMAX) 37590792Sgshapiro return (EINVAL); 37690792Sgshapiro#ifdef INVARIANTS 37790792Sgshapiro d = pci_find_domain(domain); 37890792Sgshapiro KASSERT(rman_is_region_manager(r, &d->pd_bus_rman), ("bad resource")); 37990792Sgshapiro#endif 38090792Sgshapiro return (rman_release_resource(r)); 38190792Sgshapiro} 38290792Sgshapiro#endif /* PCI_RES_BUS */ 38390792Sgshapiro 38490792Sgshapiro#endif /* NEW_PCIB */ 38590792Sgshapiro