ofw_pcibus.c (144033) | ofw_pcibus.c (152684) |
---|---|
1/*- 2 * Copyright (c) 1997, Stefan Esser <se@freebsd.org> 3 * Copyright (c) 2000, Michael Smith <msmith@freebsd.org> 4 * Copyright (c) 2000, BSDi 5 * Copyright (c) 2003, Thomas Moestl <tmm@FreeBSD.org> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 11 unchanged lines hidden (view full) --- 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 1/*- 2 * Copyright (c) 1997, Stefan Esser <se@freebsd.org> 3 * Copyright (c) 2000, Michael Smith <msmith@freebsd.org> 4 * Copyright (c) 2000, BSDi 5 * Copyright (c) 2003, Thomas Moestl <tmm@FreeBSD.org> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 11 unchanged lines hidden (view full) --- 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
28 * 29 * $FreeBSD: head/sys/sparc64/pci/ofw_pcibus.c 144033 2005-03-23 18:16:26Z jmg $ | |
30 */ 31 | 28 */ 29 |
30#include <sys/cdefs.h> 31__FBSDID("$FreeBSD: head/sys/sparc64/pci/ofw_pcibus.c 152684 2005-11-22 16:39:44Z marius $"); 32 |
|
32#include "opt_ofw_pci.h" 33 34#include <sys/param.h> 35#include <sys/bus.h> 36#include <sys/kernel.h> 37#include <sys/libkern.h> 38#include <sys/module.h> 39#include <sys/pciio.h> 40 41#include <dev/ofw/ofw_bus.h> | 33#include "opt_ofw_pci.h" 34 35#include <sys/param.h> 36#include <sys/bus.h> 37#include <sys/kernel.h> 38#include <sys/libkern.h> 39#include <sys/module.h> 40#include <sys/pciio.h> 41 42#include <dev/ofw/ofw_bus.h> |
43#include <dev/ofw/ofw_bus_subr.h> |
|
42#include <dev/ofw/ofw_pci.h> 43#include <dev/ofw/openfirm.h> 44 45#include <machine/bus.h> 46#include <machine/bus_common.h> 47#include <machine/cache.h> 48#include <machine/iommureg.h> 49#include <machine/resource.h> --- 9 unchanged lines hidden (view full) --- 59 60/* Helper functions. */ 61static void ofw_pcibus_setup_device(device_t, u_int, u_int, u_int); 62 63/* Methods. */ 64static device_probe_t ofw_pcibus_probe; 65static device_attach_t ofw_pcibus_attach; 66static pci_assign_interrupt_t ofw_pcibus_assign_interrupt; | 44#include <dev/ofw/ofw_pci.h> 45#include <dev/ofw/openfirm.h> 46 47#include <machine/bus.h> 48#include <machine/bus_common.h> 49#include <machine/cache.h> 50#include <machine/iommureg.h> 51#include <machine/resource.h> --- 9 unchanged lines hidden (view full) --- 61 62/* Helper functions. */ 63static void ofw_pcibus_setup_device(device_t, u_int, u_int, u_int); 64 65/* Methods. */ 66static device_probe_t ofw_pcibus_probe; 67static device_attach_t ofw_pcibus_attach; 68static pci_assign_interrupt_t ofw_pcibus_assign_interrupt; |
67static ofw_bus_get_compat_t ofw_pcibus_get_compat; 68static ofw_bus_get_model_t ofw_pcibus_get_model; 69static ofw_bus_get_name_t ofw_pcibus_get_name; 70static ofw_bus_get_node_t ofw_pcibus_get_node; 71static ofw_bus_get_type_t ofw_pcibus_get_type; | 69static ofw_bus_get_devinfo_t ofw_pcibus_get_devinfo; |
72 73static device_method_t ofw_pcibus_methods[] = { 74 /* Device interface */ 75 DEVMETHOD(device_probe, ofw_pcibus_probe), 76 DEVMETHOD(device_attach, ofw_pcibus_attach), 77 DEVMETHOD(device_shutdown, bus_generic_shutdown), 78 DEVMETHOD(device_suspend, bus_generic_suspend), 79 DEVMETHOD(device_resume, bus_generic_resume), --- 25 unchanged lines hidden (view full) --- 105 DEVMETHOD(pci_disable_busmaster, pci_disable_busmaster_method), 106 DEVMETHOD(pci_enable_io, pci_enable_io_method), 107 DEVMETHOD(pci_disable_io, pci_disable_io_method), 108 DEVMETHOD(pci_get_powerstate, pci_get_powerstate_method), 109 DEVMETHOD(pci_set_powerstate, pci_set_powerstate_method), 110 DEVMETHOD(pci_assign_interrupt, ofw_pcibus_assign_interrupt), 111 112 /* ofw_bus interface */ | 70 71static device_method_t ofw_pcibus_methods[] = { 72 /* Device interface */ 73 DEVMETHOD(device_probe, ofw_pcibus_probe), 74 DEVMETHOD(device_attach, ofw_pcibus_attach), 75 DEVMETHOD(device_shutdown, bus_generic_shutdown), 76 DEVMETHOD(device_suspend, bus_generic_suspend), 77 DEVMETHOD(device_resume, bus_generic_resume), --- 25 unchanged lines hidden (view full) --- 103 DEVMETHOD(pci_disable_busmaster, pci_disable_busmaster_method), 104 DEVMETHOD(pci_enable_io, pci_enable_io_method), 105 DEVMETHOD(pci_disable_io, pci_disable_io_method), 106 DEVMETHOD(pci_get_powerstate, pci_get_powerstate_method), 107 DEVMETHOD(pci_set_powerstate, pci_set_powerstate_method), 108 DEVMETHOD(pci_assign_interrupt, ofw_pcibus_assign_interrupt), 109 110 /* ofw_bus interface */ |
113 DEVMETHOD(ofw_bus_get_compat, ofw_pcibus_get_compat), 114 DEVMETHOD(ofw_bus_get_model, ofw_pcibus_get_model), 115 DEVMETHOD(ofw_bus_get_name, ofw_pcibus_get_name), 116 DEVMETHOD(ofw_bus_get_node, ofw_pcibus_get_node), 117 DEVMETHOD(ofw_bus_get_type, ofw_pcibus_get_type), | 111 DEVMETHOD(ofw_bus_get_devinfo, ofw_pcibus_get_devinfo), 112 DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), 113 DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), 114 DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), 115 DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), 116 DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), |
118 119 { 0, 0 } 120}; 121 122struct ofw_pcibus_devinfo { 123 struct pci_devinfo opd_dinfo; | 117 118 { 0, 0 } 119}; 120 121struct ofw_pcibus_devinfo { 122 struct pci_devinfo opd_dinfo; |
124 char *opd_compat; 125 char *opd_model; 126 char *opd_name; 127 char *opd_type; 128 phandle_t opd_node; | 123 struct ofw_bus_devinfo opd_obdinfo; |
129}; 130 131struct ofw_pcibus_softc { 132 phandle_t ops_node; 133}; 134 135static driver_t ofw_pcibus_driver = { 136 "pci", --- 67 unchanged lines hidden (view full) --- 204 205static int 206ofw_pcibus_attach(device_t dev) 207{ 208 device_t pcib = device_get_parent(dev); 209 struct ofw_pci_register pcir; 210 struct ofw_pcibus_devinfo *dinfo; 211 phandle_t node, child; | 124}; 125 126struct ofw_pcibus_softc { 127 phandle_t ops_node; 128}; 129 130static driver_t ofw_pcibus_driver = { 131 "pci", --- 67 unchanged lines hidden (view full) --- 199 200static int 201ofw_pcibus_attach(device_t dev) 202{ 203 device_t pcib = device_get_parent(dev); 204 struct ofw_pci_register pcir; 205 struct ofw_pcibus_devinfo *dinfo; 206 phandle_t node, child; |
212 char *cname; | |
213 u_int slot, busno, func; 214 215 /* 216 * Ask the bridge for the bus number - in some cases, we need to 217 * renumber buses, so the firmware information cannot be trusted. 218 */ 219 busno = pcib_get_bus(dev); 220 if (bootverbose) 221 device_printf(dev, "physical bus=%d\n", busno); 222 223 node = ofw_bus_get_node(dev); 224 for (child = OF_child(node); child != 0; child = OF_peer(child)) { | 207 u_int slot, busno, func; 208 209 /* 210 * Ask the bridge for the bus number - in some cases, we need to 211 * renumber buses, so the firmware information cannot be trusted. 212 */ 213 busno = pcib_get_bus(dev); 214 if (bootverbose) 215 device_printf(dev, "physical bus=%d\n", busno); 216 217 node = ofw_bus_get_node(dev); 218 for (child = OF_child(node); child != 0; child = OF_peer(child)) { |
225 if ((OF_getprop_alloc(child, "name", 1, (void **)&cname)) == -1) | 219 if (OF_getprop(child, "reg", &pcir, sizeof(pcir)) == -1) |
226 continue; | 220 continue; |
227 228 if (OF_getprop(child, "reg", &pcir, sizeof(pcir)) == -1) { 229 device_printf(dev, "<%s>: incomplete\n", cname); 230 free(cname, M_OFWPROP); 231 continue; 232 } | |
233 slot = OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi); 234 func = OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi); 235 ofw_pcibus_setup_device(pcib, busno, slot, func); 236 dinfo = (struct ofw_pcibus_devinfo *)pci_read_device(pcib, 237 busno, slot, func, sizeof(*dinfo)); | 221 slot = OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi); 222 func = OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi); 223 ofw_pcibus_setup_device(pcib, busno, slot, func); 224 dinfo = (struct ofw_pcibus_devinfo *)pci_read_device(pcib, 225 busno, slot, func, sizeof(*dinfo)); |
238 if (dinfo != NULL) { 239 dinfo->opd_name = cname; 240 dinfo->opd_node = child; 241 OF_getprop_alloc(child, "compatible", 1, 242 (void **)&dinfo->opd_compat); 243 OF_getprop_alloc(child, "device_type", 1, 244 (void **)&dinfo->opd_type); 245 OF_getprop_alloc(child, "model", 1, 246 (void **)&dinfo->opd_model); 247 pci_add_child(dev, (struct pci_devinfo *)dinfo); 248 } else 249 free(cname, M_OFWPROP); | 226 if (dinfo == NULL) 227 continue; 228 if (ofw_bus_gen_setup_devinfo(&dinfo->opd_obdinfo, child) != 229 0) { 230 pci_freecfg((struct pci_devinfo *)dinfo); 231 continue; 232 } 233 pci_add_child(dev, (struct pci_devinfo *)dinfo); |
250 } 251 252 return (bus_generic_attach(dev)); 253} 254 255static int 256ofw_pcibus_assign_interrupt(device_t dev, device_t child) 257{ | 234 } 235 236 return (bus_generic_attach(dev)); 237} 238 239static int 240ofw_pcibus_assign_interrupt(device_t dev, device_t child) 241{ |
258 struct ofw_pcibus_devinfo *dinfo = device_get_ivars(child); 259 pcicfgregs *cfg = &dinfo->opd_dinfo.cfg; | |
260 ofw_pci_intr_t intr; 261 int isz; 262 | 242 ofw_pci_intr_t intr; 243 int isz; 244 |
263 isz = OF_getprop(dinfo->opd_node, "interrupts", &intr, sizeof(intr)); | 245 isz = OF_getprop(ofw_bus_get_node(child), "interrupts", &intr, 246 sizeof(intr)); |
264 if (isz != sizeof(intr)) { 265 /* No property; our best guess is the intpin. */ | 247 if (isz != sizeof(intr)) { 248 /* No property; our best guess is the intpin. */ |
266 intr = cfg->intpin; | 249 intr = pci_get_intpin(child); |
267 } else if (intr >= 255) { 268 /* 269 * A fully specified interrupt (including IGN), as present on 270 * SPARCengine Ultra AX and e450. Extract the INO and return it. 271 */ 272 return (INTINO(intr)); 273 } 274 /* 275 * If we got intr from a property, it may or may not be an intpin. 276 * For on-board devices, it frequently is not, and is completely out 277 * of the valid intpin range. For PCI slots, it hopefully is, otherwise 278 * we will have trouble interfacing with non-OFW buses such as cardbus. 279 * Since we cannot tell which it is without violating layering, we 280 * will always use the route_interrupt method, and treat exceptions on 281 * the level they become apparent. 282 */ 283 return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, intr)); 284} 285 | 250 } else if (intr >= 255) { 251 /* 252 * A fully specified interrupt (including IGN), as present on 253 * SPARCengine Ultra AX and e450. Extract the INO and return it. 254 */ 255 return (INTINO(intr)); 256 } 257 /* 258 * If we got intr from a property, it may or may not be an intpin. 259 * For on-board devices, it frequently is not, and is completely out 260 * of the valid intpin range. For PCI slots, it hopefully is, otherwise 261 * we will have trouble interfacing with non-OFW buses such as cardbus. 262 * Since we cannot tell which it is without violating layering, we 263 * will always use the route_interrupt method, and treat exceptions on 264 * the level they become apparent. 265 */ 266 return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, intr)); 267} 268 |
286static const char * 287ofw_pcibus_get_compat(device_t bus, device_t dev) | 269static const struct ofw_bus_devinfo * 270ofw_pcibus_get_devinfo(device_t bus, device_t dev) |
288{ 289 struct ofw_pcibus_devinfo *dinfo; | 271{ 272 struct ofw_pcibus_devinfo *dinfo; |
290 291 dinfo = device_get_ivars(dev); 292 return (dinfo->opd_compat); 293} 294 295static const char * 296ofw_pcibus_get_model(device_t bus, device_t dev) 297{ 298 struct ofw_pcibus_devinfo *dinfo; | |
299 300 dinfo = device_get_ivars(dev); | 273 274 dinfo = device_get_ivars(dev); |
301 return (dinfo->opd_model); | 275 return (&dinfo->opd_obdinfo); |
302} | 276} |
303 304static const char * 305ofw_pcibus_get_name(device_t bus, device_t dev) 306{ 307 struct ofw_pcibus_devinfo *dinfo; 308 309 dinfo = device_get_ivars(dev); 310 return (dinfo->opd_name); 311} 312 313static phandle_t 314ofw_pcibus_get_node(device_t bus, device_t dev) 315{ 316 struct ofw_pcibus_devinfo *dinfo; 317 318 dinfo = device_get_ivars(dev); 319 return (dinfo->opd_node); 320} 321 322static const char * 323ofw_pcibus_get_type(device_t bus, device_t dev) 324{ 325 struct ofw_pcibus_devinfo *dinfo; 326 327 dinfo = device_get_ivars(dev); 328 return (dinfo->opd_type); 329} | |