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 */ |
|