diff options
Diffstat (limited to 'sys/sparc64/isa')
-rw-r--r-- | sys/sparc64/isa/isa.c | 62 | ||||
-rw-r--r-- | sys/sparc64/isa/ofw_isa.c | 33 | ||||
-rw-r--r-- | sys/sparc64/isa/ofw_isa.h | 18 |
3 files changed, 84 insertions, 29 deletions
diff --git a/sys/sparc64/isa/isa.c b/sys/sparc64/isa/isa.c index 2df0257d..4916b1e 100644 --- a/sys/sparc64/isa/isa.c +++ b/sys/sparc64/isa/isa.c @@ -29,6 +29,8 @@ * $FreeBSD$ */ +#include "opt_ofw_pci.h" + #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> @@ -57,8 +59,6 @@ #include <sparc64/pci/ofw_pci.h> #include <sparc64/isa/ofw_isa.h> -#include "sparcbus_if.h" - /* There can be only one ISA bus, so it is safe to use globals. */ bus_space_tag_t isa_io_bt = NULL; bus_space_handle_t isa_io_hdl; @@ -73,7 +73,11 @@ u_int64_t isa_mem_limit; device_t isa_bus_device; static phandle_t isab_node; -static u_int32_t isa_ino[8]; +static ofw_pci_intr_t isa_ino[8]; + +#ifdef OFW_NEWPCI +struct ofw_bus_iinfo isa_iinfo; +#endif /* * XXX: This is really partly partly PCI-specific, but unfortunately is @@ -98,9 +102,9 @@ isa_irq_pending(void) /* XXX: Is this correct? */ for (i = 7, pending = 0; i >= 0; i--) { - pending <<= 1; - if (isa_ino[i] != ORIR_NOTFOUND) { - pending |= (SPARCBUS_INTR_PENDING(isa_bus_device, + pending <<= 1; + if (isa_ino[i] != PCI_INVALID_IRQ) { + pending |= (OFW_PCI_INTR_PENDING(isa_bus_device, isa_ino[i]) == 0) ? 0 : 1; } } @@ -112,29 +116,47 @@ isa_init(device_t dev) { device_t bridge; phandle_t node; - u_int32_t ino; + ofw_isa_intr_t ino; +#ifndef OFW_NEWPCI + ofw_pci_intr_t rino; +#endif struct isa_ranges *br; int nbr, i; /* The parent of the bus must be a PCI-ISA bridge. */ bridge = device_get_parent(dev); +#ifdef OFW_NEWPCI + isab_node = ofw_pci_get_node(bridge); +#else isab_node = ofw_pci_node(bridge); +#endif nbr = OF_getprop_alloc(isab_node, "ranges", sizeof(*br), (void **)&br); if (nbr <= 0) panic("isa_init: cannot get bridge range property"); + +#ifdef OFW_NEWPCI + ofw_bus_setup_iinfo(isab_node, &isa_iinfo, sizeof(ofw_isa_intr_t)); +#endif + /* - * This is really a bad kluge; however, it is needed to provide - * isa_irq_pending(). + * This is really a bad kludge; however, it is needed to provide + * isa_irq_pending(), which is unfortunately still used by some + * drivers. */ for (i = 0; i < 8; i++) - isa_ino[i] = ORIR_NOTFOUND; + isa_ino[i] = PCI_INVALID_IRQ; for (node = OF_child(isab_node); node != 0; node = OF_peer(node)) { if (OF_getprop(node, "interrupts", &ino, sizeof(ino)) == -1) continue; if (ino > 7) panic("isa_init: XXX: ino too large"); - isa_ino[ino] = ofw_bus_route_intr(node, ino, - ofw_pci_orb_callback, dev); +#ifdef OFW_NEWPCI + isa_ino[ino] = ofw_isa_route_intr(bridge, node, &isa_iinfo, + ino); +#else + rino = ofw_bus_route_intr(node, ino, ofw_pci_orb_callback, dev); + isa_ino[ino] = rino == ORIR_NOTFOUND ? PCI_INVALID_IRQ : rino; +#endif } for (nbr -= 1; nbr >= 0; nbr--) { @@ -143,15 +165,15 @@ isa_init(device_t dev) /* This is probably always 0. */ isa_io_base = ISAB_RANGE_PHYS(&br[nbr]); isa_io_limit = br[nbr].size; - isa_io_hdl = SPARCBUS_GET_BUS_HANDLE(bridge, SBBT_IO, - isa_io_base, &isa_io_bt); + isa_io_hdl = OFW_PCI_GET_BUS_HANDLE(bridge, + SYS_RES_IOPORT, isa_io_base, &isa_io_bt); break; case ISAR_SPACE_MEM: /* This is probably always 0. */ isa_mem_base = ISAB_RANGE_PHYS(&br[nbr]); isa_mem_limit = br[nbr].size; - isa_mem_hdl = SPARCBUS_GET_BUS_HANDLE(bridge, SBBT_MEM, - isa_mem_base, &isa_mem_bt); + isa_mem_hdl = OFW_PCI_GET_BUS_HANDLE(bridge, + SYS_RES_MEMORY, isa_mem_base, &isa_mem_bt); break; } } @@ -170,7 +192,7 @@ isa_route_intr_res(device_t bus, u_long start, u_long end) if (start > 7) panic("isa_route_intr_res: start out of isa range"); res = isa_ino[start]; - if (res == ORIR_NOTFOUND) + if (res == PCI_INVALID_IRQ) device_printf(bus, "could not map interrupt %d\n", res); return (res); } @@ -244,7 +266,7 @@ isa_alloc_resource(device_t bus, device_t child, int type, int *rid, "irq allocation"); if (!isdefault) { start = end = isa_route_intr_res(bus, start, end); - if (start == 255) + if (start == PCI_INVALID_IRQ) return (NULL); } break; @@ -255,7 +277,7 @@ isa_alloc_resource(device_t bus, device_t child, int type, int *rid, start = ulmin(start + base, limit); end = ulmin(end + base, limit); } - + /* * This inlines a modified resource_list_alloc(); this is needed * because the resources need to have offsets added to them, which @@ -289,7 +311,7 @@ isa_alloc_resource(device_t bus, device_t child, int type, int *rid, break; case SYS_RES_IRQ: start = end = isa_route_intr_res(bus, start, end); - if (start == 255) + if (start == PCI_INVALID_IRQ) return (NULL); break; } diff --git a/sys/sparc64/isa/ofw_isa.c b/sys/sparc64/isa/ofw_isa.c index a87665e..986220d 100644 --- a/sys/sparc64/isa/ofw_isa.c +++ b/sys/sparc64/isa/ofw_isa.c @@ -1,6 +1,6 @@ /* * Copyright (c) 1999, 2000 Matthew R. Green - * Copyright (c) 2001 Thomas Moestl <tmm@FreeBSD.org> + * Copyright (c) 2001, 2003 Thomas Moestl <tmm@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -35,6 +35,8 @@ * Helper functions which can be used in both ISA and EBus code. */ +#include "opt_ofw_pci.h" + #include <sys/param.h> #include <sys/systm.h> #include <sys/bus.h> @@ -42,11 +44,14 @@ #include <ofw/openfirm.h> #include <ofw/ofw_pci.h> +#include <machine/bus.h> #include <machine/resource.h> #include <machine/ofw_bus.h> -#include <sparc64/isa/ofw_isa.h> #include <sparc64/pci/ofw_pci.h> +#include <sparc64/isa/ofw_isa.h> + +#include "pcib_if.h" /* XXX: this only supports PCI as parent bus right now. */ int @@ -86,3 +91,27 @@ ofw_isa_map_iorange(struct isa_ranges *range, int nrange, u_long *start, panic("ofw_isa_map_iorange: could not map range %#lx - %#lx", *start, *end); } + +#ifdef OFW_NEWPCI +ofw_pci_intr_t +ofw_isa_route_intr(device_t bridge, phandle_t node, struct ofw_bus_iinfo *ii, + ofw_isa_intr_t intr) +{ + struct isa_regs reg; + u_int8_t maskbuf[sizeof(reg) + sizeof(intr)]; + device_t pbridge; + ofw_isa_intr_t mintr; + + pbridge = device_get_parent(device_get_parent(bridge)); + /* + * If we get a match from using the map, the resulting INO is + * fully specified, so we may not continue to map. + */ + if (!ofw_bus_lookup_imap(node, ii, ®, sizeof(reg), + &intr, sizeof(intr), &mintr, sizeof(mintr), maskbuf)) { + /* Try routing at the parent bridge. */ + mintr = PCIB_ROUTE_INTERRUPT(pbridge, bridge, intr); + } + return (mintr); +} +#endif /* OFW_NEWPCI */ diff --git a/sys/sparc64/isa/ofw_isa.h b/sys/sparc64/isa/ofw_isa.h index 9402657..dd534ad 100644 --- a/sys/sparc64/isa/ofw_isa.h +++ b/sys/sparc64/isa/ofw_isa.h @@ -60,24 +60,28 @@ struct isa_ranges { ((((u_int64_t)((r)->child_hi)) << 32) | ((u_int64_t)(r)->child_lo)) #define ISA_RANGE_PS(r) (((r)->phys_hi >> 24) & 0x03) +typedef u_int32_t ofw_isa_intr_t; + struct isa_imap { u_int32_t phys_hi; /* high phys addr mask */ u_int32_t phys_lo; /* low phys addr mask */ - u_int32_t intr; /* interrupt mask */ - int32_t cnode; /* child node */ - u_int32_t cintr; /* child interrupt */ + ofw_isa_intr_t intr; /* interrupt mask */ + phandle_t cnode; /* child node */ + ofw_pci_intr_t cintr; /* child interrupt */ }; struct isa_imap_msk { u_int32_t phys_hi; /* high phys addr */ u_int32_t phys_lo; /* low phys addr */ - u_int32_t intr; /* interrupt */ + ofw_isa_intr_t intr; /* interrupt */ }; -/* Map an interrupt property to an INO */ -int ofw_isa_map_intr(struct isa_imap *, int, struct isa_imap_msk *, int, - struct isa_regs *, int); /* Map an IO range. Returns the resource type of the range. */ int ofw_isa_map_iorange(struct isa_ranges *, int, u_long *, u_long *); +#ifdef OFW_NEWPCI +ofw_pci_intr_t ofw_isa_route_intr(device_t, phandle_t, struct ofw_bus_iinfo *, + ofw_isa_intr_t); +#endif + #endif /* !_SPARC64_ISA_OFW_ISA_H_ */ |