ebus.c (91967) | ebus.c (93067) |
---|---|
1/* 2 * Copyright (c) 1999, 2000 Matthew R. Green 3 * Copyright (c) 2001 Thomas Moestl <tmm@FreeBSD.org> 4 * 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: --- 14 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: ebus.c,v 1.26 2001/09/10 16:27:53 eeh Exp 30 * | 1/* 2 * Copyright (c) 1999, 2000 Matthew R. Green 3 * Copyright (c) 2001 Thomas Moestl <tmm@FreeBSD.org> 4 * 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: --- 14 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: ebus.c,v 1.26 2001/09/10 16:27:53 eeh Exp 30 * |
31 * $FreeBSD: head/sys/sparc64/ebus/ebus.c 91967 2002-03-09 22:02:02Z tmm $ | 31 * $FreeBSD: head/sys/sparc64/ebus/ebus.c 93067 2002-03-24 02:11:06Z tmm $ |
32 */ 33 34#include "opt_ebus.h" 35 36/* 37 * UltraSPARC 5 and beyond ebus support. 38 * 39 * note that this driver is not complete: --- 9 unchanged lines hidden (view full) --- 49 */ 50 51#include <sys/param.h> 52#include <sys/systm.h> 53#include <sys/bus.h> 54#include <sys/kernel.h> 55#include <sys/malloc.h> 56 | 32 */ 33 34#include "opt_ebus.h" 35 36/* 37 * UltraSPARC 5 and beyond ebus support. 38 * 39 * note that this driver is not complete: --- 9 unchanged lines hidden (view full) --- 49 */ 50 51#include <sys/param.h> 52#include <sys/systm.h> 53#include <sys/bus.h> 54#include <sys/kernel.h> 55#include <sys/malloc.h> 56 |
57#include <ofw/openfirm.h> 58#include <ofw/ofw_pci.h> 59 |
|
57#include <machine/bus.h> 58#include <machine/ofw_bus.h> 59#include <machine/resource.h> 60 | 60#include <machine/bus.h> 61#include <machine/ofw_bus.h> 62#include <machine/resource.h> 63 |
61#include <ofw/openfirm.h> 62#include <ofw/ofw_pci.h> 63 | |
64#include <pci/pcireg.h> 65#include <pci/pcivar.h> 66 67#include <sparc64/pci/ofw_pci.h> 68 69/* 70 * The register, ranges and interrupt map properties are identical to the ISA 71 * ones. --- 22 unchanged lines hidden (view full) --- 94 struct resource_list edi_rl; 95}; 96 97struct ebus_softc { 98 phandle_t sc_node; 99 100 struct isa_ranges *sc_range; 101 | 64#include <pci/pcireg.h> 65#include <pci/pcivar.h> 66 67#include <sparc64/pci/ofw_pci.h> 68 69/* 70 * The register, ranges and interrupt map properties are identical to the ISA 71 * ones. --- 22 unchanged lines hidden (view full) --- 94 struct resource_list edi_rl; 95}; 96 97struct ebus_softc { 98 phandle_t sc_node; 99 100 struct isa_ranges *sc_range; 101 |
102 struct ofw_pci_register *sc_reg; 103 104 int sc_imap_type; 105 106 struct isa_imap *sc_ebus_imap; 107 struct isa_imap_msk sc_ebus_imapmsk; 108 109 struct ofw_pci_imap *sc_pci_imap; 110 struct ofw_pci_imap_msk sc_pci_imapmsk; 111 | |
112 int sc_nrange; | 102 int sc_nrange; |
113 int sc_nreg; | |
114 int sc_nimap; 115}; 116 117static int ebus_probe(device_t); 118static int ebus_print_child(device_t, device_t); 119static void ebus_probe_nomatch(device_t, device_t); 120static int ebus_read_ivar(device_t, device_t, int, uintptr_t *); 121static int ebus_write_ivar(device_t, device_t, int, uintptr_t); 122static struct resource *ebus_alloc_resource(device_t, device_t, int, int *, 123 u_long, u_long, u_long, u_int); 124static struct resource_list *ebus_get_resource_list(device_t, device_t); 125 126static struct ebus_devinfo *ebus_setup_dinfo(struct ebus_softc *, 127 phandle_t, char *); 128static void ebus_destroy_dinfo(struct ebus_devinfo *); 129static int ebus_print_res(struct ebus_devinfo *); | 103 int sc_nimap; 104}; 105 106static int ebus_probe(device_t); 107static int ebus_print_child(device_t, device_t); 108static void ebus_probe_nomatch(device_t, device_t); 109static int ebus_read_ivar(device_t, device_t, int, uintptr_t *); 110static int ebus_write_ivar(device_t, device_t, int, uintptr_t); 111static struct resource *ebus_alloc_resource(device_t, device_t, int, int *, 112 u_long, u_long, u_long, u_int); 113static struct resource_list *ebus_get_resource_list(device_t, device_t); 114 115static struct ebus_devinfo *ebus_setup_dinfo(struct ebus_softc *, 116 phandle_t, char *); 117static void ebus_destroy_dinfo(struct ebus_devinfo *); 118static int ebus_print_res(struct ebus_devinfo *); |
130static int ebus_map_intr(struct ebus_softc *, int, struct isa_regs *, int); | |
131 132static device_method_t ebus_methods[] = { 133 /* Device interface */ 134 DEVMETHOD(device_probe, ebus_probe), 135 DEVMETHOD(device_attach, bus_generic_attach), 136 137 /* Bus interface */ 138 DEVMETHOD(bus_print_child, ebus_print_child), --- 55 unchanged lines hidden (view full) --- 194 else 195 return (ENXIO); 196 197 device_printf(dev, "revision 0x%02x\n", pci_get_revid(dev)); 198 199 sc = device_get_softc(dev); 200 sc->sc_node = node; 201 | 119 120static device_method_t ebus_methods[] = { 121 /* Device interface */ 122 DEVMETHOD(device_probe, ebus_probe), 123 DEVMETHOD(device_attach, bus_generic_attach), 124 125 /* Bus interface */ 126 DEVMETHOD(bus_print_child, ebus_print_child), --- 55 unchanged lines hidden (view full) --- 182 else 183 return (ENXIO); 184 185 device_printf(dev, "revision 0x%02x\n", pci_get_revid(dev)); 186 187 sc = device_get_softc(dev); 188 sc->sc_node = node; 189 |
202 /* 203 * Fill in our softc with information from the prom. 204 * There are two possible cases how interrupt mapping needs to be 205 * handled: 206 * - if the ebus node has an interrupt-map properties, the interrut 207 * numbers in child nodes can be mapped using lookups in this map, 208 * using the registers of the child node in question to find the 209 * map entry 210 * - if it does not have such a properties, the interrupts are mapped 211 * in the next higher interrupt map (PCI in our case), using the 212 * interrupt number of the child, but the registers of the ebus 213 * node, to find the mapping. 214 */ 215 sc->sc_imap_type = EBUS_IT_EBUS; 216 sc->sc_nimap = OF_getprop_alloc(node, "interrupt-map", 217 sizeof(*sc->sc_ebus_imap), (void **)&sc->sc_ebus_imap); 218 if (sc->sc_nimap == -1) { 219 sc->sc_nimap = ofw_pci_find_imap(node, &sc->sc_pci_imap, 220 &sc->sc_pci_imapmsk); 221 if (sc->sc_nimap == -1) 222 panic("ebus_probe: no interrupt map found"); 223 sc->sc_imap_type = EBUS_IT_PCI; 224 } else { 225 if (OF_getprop(node, "interrupt-map-mask", 226 &sc->sc_ebus_imapmsk, sizeof(sc->sc_ebus_imapmsk)) == -1) { 227 panic("ebus_probe: could not get ebus " 228 "interrupt-map-mask"); 229 } 230 } 231 | |
232 sc->sc_nrange = OF_getprop_alloc(node, "ranges", 233 sizeof(*sc->sc_range), (void **)&sc->sc_range); | 190 sc->sc_nrange = OF_getprop_alloc(node, "ranges", 191 sizeof(*sc->sc_range), (void **)&sc->sc_range); |
234 sc->sc_nreg = OF_getprop_alloc(node, "reg", 235 sizeof(*sc->sc_reg), (void **)&sc->sc_reg); 236 if (sc->sc_nrange == -1 || sc->sc_nreg == -1) 237 panic("ebus_attach: could not get ranges/reg property"); | 192 if (sc->sc_nrange == -1) 193 panic("ebus_attach: could not get ranges property"); |
238 239 /* 240 * now attach all our children 241 */ 242 DPRINTF(EDB_CHILD, ("ebus node %08x, searching children...\n", node)); 243 for (node = OF_child(node); node > 0; node = OF_peer(node)) { 244 if ((OF_getprop_alloc(node, "name", 1, (void **)&cname)) == -1) 245 continue; --- 160 unchanged lines hidden (view full) --- 406 return (&edi->edi_rl); 407} 408 409static struct ebus_devinfo * 410ebus_setup_dinfo(struct ebus_softc *sc, phandle_t node, char *name) 411{ 412 struct ebus_devinfo *edi; 413 struct isa_regs *reg; | 194 195 /* 196 * now attach all our children 197 */ 198 DPRINTF(EDB_CHILD, ("ebus node %08x, searching children...\n", node)); 199 for (node = OF_child(node); node > 0; node = OF_peer(node)) { 200 if ((OF_getprop_alloc(node, "name", 1, (void **)&cname)) == -1) 201 continue; --- 160 unchanged lines hidden (view full) --- 362 return (&edi->edi_rl); 363} 364 365static struct ebus_devinfo * 366ebus_setup_dinfo(struct ebus_softc *sc, phandle_t node, char *name) 367{ 368 struct ebus_devinfo *edi; 369 struct isa_regs *reg; |
414 u_int32_t *intrs; | 370 u_int32_t *intrs, intr; |
415 u_int64_t start; | 371 u_int64_t start; |
416 int nreg, nintr, i, intr; | 372 int nreg, nintr, i; |
417 418 edi = malloc(sizeof(*edi), M_DEVBUF, M_ZERO | M_WAITOK); 419 if (edi == NULL) 420 return (NULL); 421 resource_list_init(&edi->edi_rl); 422 edi->edi_name = name; 423 edi->edi_node = node; 424 --- 12 unchanged lines hidden (view full) --- 437 */ 438 resource_list_add(&edi->edi_rl, SYS_RES_IOPORT, i, 439 start, start + reg[i].size - 1, reg[i].size); 440 } 441 442 nintr = OF_getprop_alloc(node, "interrupts", sizeof(*intrs), 443 (void **)&intrs); 444 for (i = 0; i < nintr; i++) { | 373 374 edi = malloc(sizeof(*edi), M_DEVBUF, M_ZERO | M_WAITOK); 375 if (edi == NULL) 376 return (NULL); 377 resource_list_init(&edi->edi_rl); 378 edi->edi_name = name; 379 edi->edi_node = node; 380 --- 12 unchanged lines hidden (view full) --- 393 */ 394 resource_list_add(&edi->edi_rl, SYS_RES_IOPORT, i, 395 start, start + reg[i].size - 1, reg[i].size); 396 } 397 398 nintr = OF_getprop_alloc(node, "interrupts", sizeof(*intrs), 399 (void **)&intrs); 400 for (i = 0; i < nintr; i++) { |
445 intr = ebus_map_intr(sc, intrs[i], reg, nreg); 446 if (intr == -1) | 401 intr = ofw_bus_route_intr(node, intrs[i]); 402 if (intr == ORIR_NOTFOUND) { |
447 panic("ebus_setup_dinfo: could not map ebus " 448 "interrupt %d", intrs[i]); | 403 panic("ebus_setup_dinfo: could not map ebus " 404 "interrupt %d", intrs[i]); |
405 } |
|
449 resource_list_add(&edi->edi_rl, SYS_RES_IRQ, i, 450 intr, intr, 1); 451 } 452 free(reg, M_OFWPROP); 453 454 return (edi); 455} 456 --- 17 unchanged lines hidden (view full) --- 474 475 retval = 0; 476 retval += resource_list_print_type(&edi->edi_rl, "addr", SYS_RES_IOPORT, 477 "%#lx"); 478 retval += resource_list_print_type(&edi->edi_rl, "irq", SYS_RES_IRQ, 479 "%ld"); 480 return (retval); 481} | 406 resource_list_add(&edi->edi_rl, SYS_RES_IRQ, i, 407 intr, intr, 1); 408 } 409 free(reg, M_OFWPROP); 410 411 return (edi); 412} 413 --- 17 unchanged lines hidden (view full) --- 431 432 retval = 0; 433 retval += resource_list_print_type(&edi->edi_rl, "addr", SYS_RES_IOPORT, 434 "%#lx"); 435 retval += resource_list_print_type(&edi->edi_rl, "irq", SYS_RES_IRQ, 436 "%ld"); 437 return (retval); 438} |
482 483static int 484ebus_map_intr(struct ebus_softc *sc, int intr, struct isa_regs *regs, 485 int nregs) 486{ 487 int rv; 488 489 if (sc->sc_imap_type == EBUS_IT_PCI) { 490 rv = ofw_pci_route_intr2(intr, sc->sc_reg, sc->sc_pci_imap, 491 sc->sc_nimap, &sc->sc_pci_imapmsk); 492 if (rv == 255) 493 return (-1); 494 return (rv); 495 } 496 return (ofw_isa_map_intr(sc->sc_ebus_imap, sc->sc_nimap, 497 &sc->sc_ebus_imapmsk, intr, regs, nregs)); 498} | |