Deleted Added
full compact
ofw_pci.c (115417) ofw_pci.c (117119)
1/*
2 * Copyright (c) 1999, 2000 Matthew R. Green
1/*
2 * Copyright (c) 1999, 2000 Matthew R. Green
3 * Copyright (c) 2001 - 2003 by Thomas Moestl <tmm@FreeBSD.org>
3 * All rights reserved.
4 * All rights reserved.
4 * Copyright 2001 by Thomas Moestl <tmm@FreeBSD.org>. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the

--- 10 unchanged lines hidden (view full) ---

23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * from: NetBSD: psycho.c,v 1.35 2001/09/10 16:17:06 eeh Exp
30 *
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the

--- 10 unchanged lines hidden (view full) ---

23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * from: NetBSD: psycho.c,v 1.35 2001/09/10 16:17:06 eeh Exp
30 *
31 * $FreeBSD: head/sys/sparc64/pci/ofw_pci.c 115417 2003-05-30 20:48:05Z tmm $
31 * $FreeBSD: head/sys/sparc64/pci/ofw_pci.c 117119 2003-07-01 14:52:47Z tmm $
32 */
33
34#include "opt_ofw_pci.h"
35
36#include <sys/param.h>
37#include <sys/kernel.h>
38#include <sys/systm.h>
39#include <sys/bus.h>
40
32 */
33
34#include "opt_ofw_pci.h"
35
36#include <sys/param.h>
37#include <sys/kernel.h>
38#include <sys/systm.h>
39#include <sys/bus.h>
40
41#include <dev/pci/pcivar.h>
42#include <dev/pci/pcireg.h>
41#include <dev/pci/pcireg.h>
42#include <dev/pci/pcivar.h>
43
44#include <dev/ofw/ofw_pci.h>
45#include <dev/ofw/openfirm.h>
46
43
44#include <dev/ofw/ofw_pci.h>
45#include <dev/ofw/openfirm.h>
46
47#include <sparc64/pci/ofw_pci.h>
48
49#include <machine/bus.h>
50#include <machine/cache.h>
51#include <machine/iommureg.h>
52#include <machine/ofw_bus.h>
53#include <machine/ver.h>
54
47#include <machine/bus.h>
48#include <machine/cache.h>
49#include <machine/iommureg.h>
50#include <machine/ofw_bus.h>
51#include <machine/ver.h>
52
53#include <sparc64/pci/ofw_pci.h>
54
55#include "pcib_if.h"
55#include "pcib_if.h"
56#include "sparcbus_if.h"
57
58u_int8_t pci_bus_cnt;
59phandle_t *pci_bus_map;
60int pci_bus_map_sz;
61
56
57u_int8_t pci_bus_cnt;
58phandle_t *pci_bus_map;
59int pci_bus_map_sz;
60
61#define PCI_BUS_MAP_INC 10
62
63#ifndef OFW_NEWPCI
62/* Do not swizzle on a PCI bus node with no interrupt-map propery. */
63#define OPQ_NO_SWIZZLE 1
64/*
65 * INOs < 255 are really intpin numbers; use a driver method to figure out
66 * the real INO.
67 */
68#define OPQ_INO_CALLBACK 2
69/*

--- 10 unchanged lines hidden (view full) ---

80 { "SUNW,Ultra-1-Engine", OPQ_NO_SWIZZLE },
81};
82#define OPQ_NENT (sizeof(ofw_pci_quirks) / sizeof(ofw_pci_quirks[0]))
83
84static int pci_quirks;
85
86#define OFW_PCI_PCIBUS "pci"
87#define OFW_PCI_EBUS "ebus"
64/* Do not swizzle on a PCI bus node with no interrupt-map propery. */
65#define OPQ_NO_SWIZZLE 1
66/*
67 * INOs < 255 are really intpin numbers; use a driver method to figure out
68 * the real INO.
69 */
70#define OPQ_INO_CALLBACK 2
71/*

--- 10 unchanged lines hidden (view full) ---

82 { "SUNW,Ultra-1-Engine", OPQ_NO_SWIZZLE },
83};
84#define OPQ_NENT (sizeof(ofw_pci_quirks) / sizeof(ofw_pci_quirks[0]))
85
86static int pci_quirks;
87
88#define OFW_PCI_PCIBUS "pci"
89#define OFW_PCI_EBUS "ebus"
88#define PCI_BUS_MAP_INC 10
89
90int
91ofw_pci_orb_callback(phandle_t node, u_int8_t *pintptr, int pintsz,
92 u_int8_t *pregptr, int pregsz, u_int8_t **rintr, int *terminate,
93 void *cookie)
94{
95 device_t dev = cookie;
96 struct ofw_pci_register preg;
90
91int
92ofw_pci_orb_callback(phandle_t node, u_int8_t *pintptr, int pintsz,
93 u_int8_t *pregptr, int pregsz, u_int8_t **rintr, int *terminate,
94 void *cookie)
95{
96 device_t dev = cookie;
97 struct ofw_pci_register preg;
97 u_int32_t pintr, intr;
98 ofw_pci_intr_t pintr, intr;
98 u_int slot;
99 char type[32];
100 int found = 0;
101
102 if ((pci_quirks & OPQ_EBUS_NOMAP) != 0 &&
103 OF_getprop(node, "name", type, sizeof(type)) != -1 &&
104 strcmp(type, OFW_PCI_EBUS) == 0) {
105 *terminate = 1;
106 return (-1);
107 }
99 u_int slot;
100 char type[32];
101 int found = 0;
102
103 if ((pci_quirks & OPQ_EBUS_NOMAP) != 0 &&
104 OF_getprop(node, "name", type, sizeof(type)) != -1 &&
105 strcmp(type, OFW_PCI_EBUS) == 0) {
106 *terminate = 1;
107 return (-1);
108 }
108 if (pintsz != sizeof(u_int32_t) || pregsz < sizeof(preg))
109 if (pintsz != sizeof(pintr) || pregsz < sizeof(preg))
109 return (-1);
110 bcopy(pintptr, &pintr, sizeof(pintr));
111 bcopy(pregptr, &preg, sizeof(preg));
112 slot = OFW_PCI_PHYS_HI_DEVICE(preg.phys_hi);
113
114 if ((pci_quirks & OPQ_INO_CALLBACK) != 0 && pintr <= 255) {
115 /*
116 * The e450 has no interrupt maps at all, and it usually has
117 * full interrupt numbers, including IGN, in the interrupt
118 * properties. There is one exception, however: the property
119 * values for external PCI devices seem to always be below 255
120 * and describe the interrupt pin to be used on the slot, while
121 * we have to figure out the base INO by looking at the slot
110 return (-1);
111 bcopy(pintptr, &pintr, sizeof(pintr));
112 bcopy(pregptr, &preg, sizeof(preg));
113 slot = OFW_PCI_PHYS_HI_DEVICE(preg.phys_hi);
114
115 if ((pci_quirks & OPQ_INO_CALLBACK) != 0 && pintr <= 255) {
116 /*
117 * The e450 has no interrupt maps at all, and it usually has
118 * full interrupt numbers, including IGN, in the interrupt
119 * properties. There is one exception, however: the property
120 * values for external PCI devices seem to always be below 255
121 * and describe the interrupt pin to be used on the slot, while
122 * we have to figure out the base INO by looking at the slot
122 * number (which we do using a sparcbus method).
123 * number (which we do using an ofw_pci method).
123 *
124 * Of course, there is an exception to that nice rule:
125 * in the ebus case, the interrupt property has the correct
126 * INO (but without IGN). This is dealt with above.
127 */
124 *
125 * Of course, there is an exception to that nice rule:
126 * in the ebus case, the interrupt property has the correct
127 * INO (but without IGN). This is dealt with above.
128 */
128 intr = SPARCBUS_GUESS_INO(dev, node, slot, pintr);
129 intr = OFW_PCI_GUESS_INO(dev, node, slot, pintr);
129 found = intr != 255;
130 *terminate = found;
131 }
132 if (!found && (pci_quirks & OPQ_NO_SWIZZLE) == 0 &&
133 OF_getprop(node, "device_type", type, sizeof(type)) != -1 &&
134 strcmp(type, OFW_PCI_PCIBUS) == 0 && pintr >= 1 && pintr <= 4) {
135 /*
136 * Handle a quirk found on some Netra t1 models: there exist

--- 8 unchanged lines hidden (view full) ---

145 if (found) {
146 *rintr = malloc(sizeof(intr), M_OFWPROP, M_WAITOK);
147 bcopy(&intr, *rintr, sizeof(intr));
148 return (sizeof(intr));
149 } else
150 return (-1);
151}
152
130 found = intr != 255;
131 *terminate = found;
132 }
133 if (!found && (pci_quirks & OPQ_NO_SWIZZLE) == 0 &&
134 OF_getprop(node, "device_type", type, sizeof(type)) != -1 &&
135 strcmp(type, OFW_PCI_PCIBUS) == 0 && pintr >= 1 && pintr <= 4) {
136 /*
137 * Handle a quirk found on some Netra t1 models: there exist

--- 8 unchanged lines hidden (view full) ---

146 if (found) {
147 *rintr = malloc(sizeof(intr), M_OFWPROP, M_WAITOK);
148 bcopy(&intr, *rintr, sizeof(intr));
149 return (sizeof(intr));
150 } else
151 return (-1);
152}
153
153static u_int32_t
154ofw_pci_route_intr(device_t dev, phandle_t node, u_int32_t ign)
154static ofw_pci_intr_t
155ofw_pci_route_intr(device_t dev, phandle_t node, ofw_pci_intr_t ign)
155{
156 u_int32_t rv;
157
158 rv = ofw_bus_route_intr(node, ORIP_NOINT, ofw_pci_orb_callback, dev);
159 if (rv == ORIR_NOTFOUND)
156{
157 u_int32_t rv;
158
159 rv = ofw_bus_route_intr(node, ORIP_NOINT, ofw_pci_orb_callback, dev);
160 if (rv == ORIR_NOTFOUND)
160 return (255);
161 return (PCI_INVALID_IRQ);
161 /*
162 * Some machines (notably the SPARCengine Ultra AX and the e450) have
163 * no mappings at all, but use complete interrupt vector number
164 * including the IGN. Catch this case and remove the IGN.
165 */
166 if (rv > ign)
167 rv -= ign;
168 return (rv);
169}
162 /*
163 * Some machines (notably the SPARCengine Ultra AX and the e450) have
164 * no mappings at all, but use complete interrupt vector number
165 * including the IGN. Catch this case and remove the IGN.
166 */
167 if (rv > ign)
168 rv -= ign;
169 return (rv);
170}
171#endif /* !OFW_NEWCPI */
170
171u_int8_t
172ofw_pci_alloc_busno(phandle_t node)
173{
174 phandle_t *om;
175 int osz;
176 u_int8_t n;
177

--- 9 unchanged lines hidden (view full) ---

187 bcopy(om, pci_bus_map, sizeof(*om) * osz);
188 free(om, M_DEVBUF);
189 }
190 }
191 pci_bus_map[n] = node;
192 return (n);
193}
194
172
173u_int8_t
174ofw_pci_alloc_busno(phandle_t node)
175{
176 phandle_t *om;
177 int osz;
178 u_int8_t n;
179

--- 9 unchanged lines hidden (view full) ---

189 bcopy(om, pci_bus_map, sizeof(*om) * osz);
190 free(om, M_DEVBUF);
191 }
192 }
193 pci_bus_map[n] = node;
194 return (n);
195}
196
197#ifndef OFW_NEWPCI
195/*
196 * Initialize bridge bus numbers for bridges that implement the primary,
197 * secondary and subordinate bus number registers.
198 */
199void
200ofw_pci_binit(device_t busdev, struct ofw_pci_bdesc *obd)
201{
202

--- 12 unchanged lines hidden (view full) ---

215
216/*
217 * Walk the PCI bus hierarchy, starting with the root PCI bus and descending
218 * through bridges, and initialize the interrupt line and latency timer
219 * configuration registers of attached devices using firmware information,
220 * as well as the the bus numbers and ranges of the bridges.
221 */
222void
198/*
199 * Initialize bridge bus numbers for bridges that implement the primary,
200 * secondary and subordinate bus number registers.
201 */
202void
203ofw_pci_binit(device_t busdev, struct ofw_pci_bdesc *obd)
204{
205

--- 12 unchanged lines hidden (view full) ---

218
219/*
220 * Walk the PCI bus hierarchy, starting with the root PCI bus and descending
221 * through bridges, and initialize the interrupt line and latency timer
222 * configuration registers of attached devices using firmware information,
223 * as well as the the bus numbers and ranges of the bridges.
224 */
225void
223ofw_pci_init(device_t dev, phandle_t bushdl, u_int32_t ign,
226ofw_pci_init(device_t dev, phandle_t bushdl, ofw_pci_intr_t ign,
224 struct ofw_pci_bdesc *obd)
225{
226 struct ofw_pci_register pcir;
227 struct ofw_pci_bdesc subobd, *tobd;
228 phandle_t node;
229 char type[32];
230 int i, intr, freemap;
231 u_int slot, busno, func, sub, lat;

--- 84 unchanged lines hidden (view full) ---

316 PCIB_READ_CONFIG(dev, busno, slot, func,
317 PCIR_LATTIMER, 1), lat);
318#endif /* OFW_PCI_DEBUG */
319 PCIB_WRITE_CONFIG(dev, busno, slot, func,
320 PCIR_LATTIMER, imin(lat, 255), 1);
321 }
322
323 /* Initialize the intline registers. */
227 struct ofw_pci_bdesc *obd)
228{
229 struct ofw_pci_register pcir;
230 struct ofw_pci_bdesc subobd, *tobd;
231 phandle_t node;
232 char type[32];
233 int i, intr, freemap;
234 u_int slot, busno, func, sub, lat;

--- 84 unchanged lines hidden (view full) ---

319 PCIB_READ_CONFIG(dev, busno, slot, func,
320 PCIR_LATTIMER, 1), lat);
321#endif /* OFW_PCI_DEBUG */
322 PCIB_WRITE_CONFIG(dev, busno, slot, func,
323 PCIR_LATTIMER, imin(lat, 255), 1);
324 }
325
326 /* Initialize the intline registers. */
324 if ((intr = ofw_pci_route_intr(dev, node, ign)) != 255) {
327 if ((intr = ofw_pci_route_intr(dev, node, ign)) !=
328 PCI_INVALID_IRQ) {
325#ifdef OFW_PCI_DEBUG
326 device_printf(dev, "%s: mapping intr for "
327 "%d/%d/%d to %d (preset was %d)\n",
328 __func__, busno, slot, func, intr,
329 (int)PCIB_READ_CONFIG(dev, busno, slot,
330 func, PCIR_INTLINE, 1));
331#endif /* OFW_PCI_DEBUG */
332 PCIB_WRITE_CONFIG(dev, busno, slot, func,

--- 6 unchanged lines hidden (view full) ---

339 (int)PCIB_READ_CONFIG(dev, busno, slot,
340 func, PCIR_INTLINE, 1));
341#endif /* OFW_PCI_DEBUG */
342 /*
343 * The firmware initializes to 0 instead of
344 * 255.
345 */
346 PCIB_WRITE_CONFIG(dev, busno, slot, func,
329#ifdef OFW_PCI_DEBUG
330 device_printf(dev, "%s: mapping intr for "
331 "%d/%d/%d to %d (preset was %d)\n",
332 __func__, busno, slot, func, intr,
333 (int)PCIB_READ_CONFIG(dev, busno, slot,
334 func, PCIR_INTLINE, 1));
335#endif /* OFW_PCI_DEBUG */
336 PCIB_WRITE_CONFIG(dev, busno, slot, func,

--- 6 unchanged lines hidden (view full) ---

343 (int)PCIB_READ_CONFIG(dev, busno, slot,
344 func, PCIR_INTLINE, 1));
345#endif /* OFW_PCI_DEBUG */
346 /*
347 * The firmware initializes to 0 instead of
348 * 255.
349 */
350 PCIB_WRITE_CONFIG(dev, busno, slot, func,
347 PCIR_INTLINE, 255, 1);
351 PCIR_INTLINE, PCI_INVALID_IRQ, 1);
348 }
349 }
350 } while ((node = OF_peer(node)) != 0);
351}
352
353phandle_t
354ofw_pci_find_node(int bus, int slot, int func)
355{

--- 23 unchanged lines hidden (view full) ---

379
380phandle_t
381ofw_pci_node(device_t dev)
382{
383
384 return (ofw_pci_find_node(pci_get_bus(dev), pci_get_slot(dev),
385 pci_get_function(dev)));
386}
352 }
353 }
354 } while ((node = OF_peer(node)) != 0);
355}
356
357phandle_t
358ofw_pci_find_node(int bus, int slot, int func)
359{

--- 23 unchanged lines hidden (view full) ---

383
384phandle_t
385ofw_pci_node(device_t dev)
386{
387
388 return (ofw_pci_find_node(pci_get_bus(dev), pci_get_slot(dev),
389 pci_get_function(dev)));
390}
391#endif /* OFW_NEWPCI */