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