diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2009-08-18 19:32:00 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2009-08-18 19:32:00 +0000 |
commit | 1a7308cc4310273bbad33aeb36d1c5d0c6896a13 (patch) | |
tree | cc384d7f777d0b8d97004687bc2df85379e46815 /sys/arch | |
parent | 631da8807b408a5ced5809908d37ed46ca97dfdb (diff) |
Blind support for SGI PIC PCI-X controller found on Origin 350 and Tezro
systems. PIC was supposed to be mostly XBridge compatible, but a silicon
bug prevents it from working correctly if 32 bit register writes are used,
so the xbridge(4) code now needs to issue 64 bit writes.
In order to make this a bit more transparent, rebase all widget registers to
a 8 byte boundary, and provide a few inline accessors which will do the right
thing if you want 32 bit writes.
Tested to not cause regressions on Octane, Origin 200 and Fuel; covering
Bridge < 4, Bridge >= 4 and XBridge flavours.
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/sgi/sgi/ip27_machdep.c | 4 | ||||
-rw-r--r-- | sys/arch/sgi/sgi/ip30_machdep.c | 8 | ||||
-rw-r--r-- | sys/arch/sgi/xbow/xbow.h | 81 | ||||
-rw-r--r-- | sys/arch/sgi/xbow/xbridge.c | 1156 | ||||
-rw-r--r-- | sys/arch/sgi/xbow/xbridgereg.h | 57 |
5 files changed, 745 insertions, 561 deletions
diff --git a/sys/arch/sgi/sgi/ip27_machdep.c b/sys/arch/sgi/sgi/ip27_machdep.c index b1da5c94ba3..c8859142a75 100644 --- a/sys/arch/sgi/sgi/ip27_machdep.c +++ b/sys/arch/sgi/sgi/ip27_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip27_machdep.c,v 1.18 2009/07/25 19:17:25 miod Exp $ */ +/* $OpenBSD: ip27_machdep.c,v 1.19 2009/08/18 19:31:56 miod Exp $ */ /* * Copyright (c) 2008, 2009 Miodrag Vallat. @@ -381,7 +381,7 @@ ip27_widget_id(int16_t nasid, u_int widget, uint32_t *wid) } wpa = ip27_widget_short(nasid, widget); - if (guarded_read_4(wpa + WIDGET_ID, &id) != 0) + if (guarded_read_4(wpa + (WIDGET_ID | 4), &id) != 0) return ENXIO; if (wid != NULL) diff --git a/sys/arch/sgi/sgi/ip30_machdep.c b/sys/arch/sgi/sgi/ip30_machdep.c index 768d5e550b9..55df4a85791 100644 --- a/sys/arch/sgi/sgi/ip30_machdep.c +++ b/sys/arch/sgi/sgi/ip30_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip30_machdep.c,v 1.8 2009/07/06 22:46:43 miod Exp $ */ +/* $OpenBSD: ip30_machdep.c,v 1.9 2009/08/18 19:31:56 miod Exp $ */ /* * Copyright (c) 2008 Miodrag Vallat. @@ -114,7 +114,7 @@ ip30_setup() */ xbow_build_bus_space(&sys_config.console_io, 0, 15); sys_config.console_io.bus_base = ip30_widget_long(0, 15) + - BRIDGE_PCI_MEM_SPACE_BASE; + BRIDGE_PCI0_MEM_SPACE_BASE; comconsaddr = 0x500000 + IOC3_UARTA_BASE; comconsfreq = 22000000 / 3; @@ -168,14 +168,14 @@ ip30_widget_id(int16_t nasid, u_int widget, uint32_t *wid) return EINVAL; linkpa = ip30_widget_short(nasid, 0) + XBOW_WIDGET_LINK(widget); - if (!ISSET(*(uint32_t *)(linkpa + WIDGET_LINK_STATUS), + if (!ISSET(*(uint32_t *)(linkpa + (WIDGET_LINK_STATUS | 4)), WIDGET_STATUS_ALIVE)) return ENXIO; /* not connected */ } wpa = ip30_widget_short(nasid, widget); if (wid != NULL) - *wid = *(uint32_t *)(wpa + WIDGET_ID); + *wid = *(uint32_t *)(wpa + (WIDGET_ID | 4)); return 0; } diff --git a/sys/arch/sgi/xbow/xbow.h b/sys/arch/sgi/xbow/xbow.h index 22797bd137a..875028b2a64 100644 --- a/sys/arch/sgi/xbow/xbow.h +++ b/sys/arch/sgi/xbow/xbow.h @@ -1,4 +1,4 @@ -/* $OpenBSD: xbow.h,v 1.6 2009/07/06 22:46:43 miod Exp $ */ +/* $OpenBSD: xbow.h,v 1.7 2009/08/18 19:31:59 miod Exp $ */ /* * Copyright (c) 2008 Miodrag Vallat. @@ -55,50 +55,54 @@ extern void (*xbow_intr_widget_intr_disestablish)(int); /* * Common Widget Registers. Every widget provides them. + * + * Registers are 32 or 64 bit wide (depending on the particular widget + * or register) on 64 bit boundaries. + * The widget_{read,write}_[48] functions below hide the addressing + * games required to perform 32 bit accesses. */ -/* all registers are 32 bits within big-endian 64 bit blocks */ -#define WIDGET_ID 0x0004 +#define WIDGET_ID 0x0000 #define WIDGET_ID_REV_MASK 0xf0000000 #define WIDGET_ID_REV_SHIFT 28 #define WIDGET_ID_PRODUCT_MASK 0x0ffff000 #define WIDGET_ID_PRODUCT_SHIFT 12 #define WIDGET_ID_VENDOR_MASK 0x00000ffe #define WIDGET_ID_VENDOR_SHIFT 1 -#define WIDGET_STATUS 0x000c -#define WIDGET_ERR_ADDR_UPPER 0x0014 -#define WIDGET_ERR_ADDR_LOWER 0x001c -#define WIDGET_CONTROL 0x0024 -#define WIDGET_REQ_TIMEOUT 0x002c -#define WIDGET_INTDEST_ADDR_UPPER 0x0034 -#define WIDGET_INTDEST_ADDR_LOWER 0x003c -#define WIDGET_ERR_CMD_WORD 0x0044 -#define WIDGET_LLP_CFG 0x004c -#define WIDGET_TFLUSH 0x0054 +#define WIDGET_STATUS 0x0008 +#define WIDGET_ERR_ADDR_UPPER 0x0010 +#define WIDGET_ERR_ADDR_LOWER 0x0018 +#define WIDGET_CONTROL 0x0020 +#define WIDGET_REQ_TIMEOUT 0x0028 +#define WIDGET_INTDEST_ADDR_UPPER 0x0030 +#define WIDGET_INTDEST_ADDR_LOWER 0x0038 +#define WIDGET_ERR_CMD_WORD 0x0040 +#define WIDGET_LLP_CFG 0x0048 +#define WIDGET_TFLUSH 0x0050 /* * Crossbow Specific Registers. */ -#define XBOW_WID_ARB_RELOAD 0x005c -#define XBOW_PERFCNTR_A 0x0064 -#define XBOW_PERFCNTR_B 0x006c -#define XBOW_NIC 0x0074 +#define XBOW_WID_ARB_RELOAD 0x0058 +#define XBOW_PERFCNTR_A 0x0060 +#define XBOW_PERFCNTR_B 0x0068 +#define XBOW_NIC 0x0070 #define XBOW_WIDGET_LINK(w) (0x0100 + ((w) & 7) * 0x0040) /* * Per-widget ``Link'' Register Set. */ -#define WIDGET_LINK_IBF 0x0004 -#define WIDGET_LINK_CONTROL 0x000c +#define WIDGET_LINK_IBF 0x0000 +#define WIDGET_LINK_CONTROL 0x0008 #define WIDGET_CONTROL_ALIVE 0x80000000 -#define WIDGET_LINK_STATUS 0x0014 +#define WIDGET_LINK_STATUS 0x0010 #define WIDGET_STATUS_ALIVE 0x80000000 -#define WIDGET_LINK_ARB_UPPER 0x001c -#define WIDGET_LINK_ARB_LOWER 0x0024 -#define WIDGET_LINK_STATUS_CLEAR 0x002c -#define WIDGET_LINK_RESET 0x0034 -#define WIDGET_LINK_AUX_STATUS 0x003c +#define WIDGET_LINK_ARB_UPPER 0x0018 +#define WIDGET_LINK_ARB_LOWER 0x0020 +#define WIDGET_LINK_STATUS_CLEAR 0x0028 +#define WIDGET_LINK_RESET 0x0030 +#define WIDGET_LINK_AUX_STATUS 0x0038 /* * Valid widget values @@ -139,4 +143,31 @@ void xbow_write_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, void xbow_write_raw_2(bus_space_tag_t, bus_space_handle_t, bus_addr_t, const uint8_t *, bus_size_t); +/* + * Widget register access routines hiding addressing games depending upon + * the access width. + */ +static __inline__ uint32_t +widget_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t a) +{ + return bus_space_read_4(t, h, a | 4); +} +static __inline__ uint64_t +widget_read_8(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t a) +{ + return bus_space_read_8(t, h, a); +} +static __inline__ void +widget_write_4(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t a, + uint32_t v) +{ + bus_space_write_4(t, h, a | 4, v); +} +static __inline__ void +widget_write_8(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t a, + uint64_t v) +{ + bus_space_write_8(t, h, a, v); +} + #endif /* _XBOW_H_ */ diff --git a/sys/arch/sgi/xbow/xbridge.c b/sys/arch/sgi/xbow/xbridge.c index a209a18c5b7..3b307d57215 100644 --- a/sys/arch/sgi/xbow/xbridge.c +++ b/sys/arch/sgi/xbow/xbridge.c @@ -1,4 +1,4 @@ -/* $OpenBSD: xbridge.c,v 1.44 2009/07/27 17:49:55 miod Exp $ */ +/* $OpenBSD: xbridge.c,v 1.45 2009/08/18 19:31:59 miod Exp $ */ /* * Copyright (c) 2008, 2009 Miodrag Vallat. @@ -17,7 +17,7 @@ */ /* - * XBow Bridge (and XBridge) Widget driver. + * XBow Bridge (as well as XBridge and PIC) Widget driver. */ /* @@ -68,27 +68,42 @@ int xbridge_match(struct device *, void *, void *); void xbridge_attach(struct device *, struct device *, void *); int xbridge_print(void *, const char *); -struct xbridge_intr; struct xbridge_ate; +struct xbridge_intr; +struct xbridge_softc; -struct xbridge_softc { - struct device sc_dev; - int sc_flags; -#define XBRIDGE_FLAGS_XBRIDGE 0x01 /* is XBridge vs Bridge */ -#define XBRIDGE_FLAGS_NO_DIRECT_IO 0x02 /* no direct I/O mapping */ - int16_t sc_nasid; - int sc_widget; - uint sc_devio_skew; - struct mips_pci_chipset sc_pc; +struct xbridge_bus { + struct xbridge_softc *xb_sc; + + /* + * Bridge register accessors. + * Due to hardware bugs, PIC registers can only be accessed + * with 64 bit operations, although the hardware was supposed + * to be directly compatible with XBridge on that aspect. + */ + uint32_t (*xb_read_reg)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t); + void (*xb_write_reg)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint32_t); + + uint xb_busno; + uint xb_nslots; + + int xb_flags; /* copy of xbridge_softc value */ + int16_t xb_nasid; /* copy of xbridge_softc value */ + int xb_widget; /* copy of xbridge_softc value */ + uint xb_devio_skew; /* copy of xbridge_softc value */ + + struct mips_pci_chipset xb_pc; - bus_space_tag_t sc_iot; - bus_space_handle_t sc_regh; + bus_space_tag_t xb_regt; + bus_space_handle_t xb_regh; - struct mips_bus_space *sc_mem_bus_space; - struct mips_bus_space *sc_io_bus_space; - struct machine_bus_dma_tag *sc_dmat; + struct mips_bus_space *xb_mem_bus_space; + struct mips_bus_space *xb_io_bus_space; + struct machine_bus_dma_tag *xb_dmat; - struct xbridge_intr *sc_intr[BRIDGE_NINTRS]; + struct xbridge_intr *xb_intr[BRIDGE_NINTRS]; /* * Device information. @@ -96,33 +111,50 @@ struct xbridge_softc { struct { pcireg_t id; uint32_t devio; - } sc_devices[BRIDGE_NSLOTS]; + } xb_devices[MAX_SLOTS]; /* * ATE management. */ - struct mutex sc_atemtx; - uint sc_atecnt; - struct xbridge_ate *sc_ate; - LIST_HEAD(, xbridge_ate) sc_free_ate; - LIST_HEAD(, xbridge_ate) sc_used_ate; + struct mutex xb_atemtx; + uint xb_atecnt; + struct xbridge_ate *xb_ate; + LIST_HEAD(, xbridge_ate) xb_free_ate; + LIST_HEAD(, xbridge_ate) xb_used_ate; /* * Large resource view sizes */ - bus_addr_t sc_iostart, sc_ioend; - bus_addr_t sc_memstart, sc_memend; + bus_addr_t xb_iostart, xb_ioend; + bus_addr_t xb_memstart, xb_memend; /* * Resource extents for the large resource views, used during * resource setup, then cleaned up for the MI code. */ - char sc_ioexname[32]; - struct extent *sc_ioex; - char sc_memexname[32]; - struct extent *sc_memex; + char xb_ioexname[32]; + struct extent *xb_ioex; + char xb_memexname[32]; + struct extent *xb_memex; }; +struct xbridge_softc { + struct device sc_dev; + int sc_flags; +#define XF_XBRIDGE 0x01 /* is either PIC or XBridge */ +#define XF_PIC 0x02 /* is PIC */ +#define XF_NO_DIRECT_IO 0x04 /* no direct I/O mapping */ + int16_t sc_nasid; + int sc_widget; + uint sc_devio_skew; + uint sc_nbuses; + + struct mips_bus_space sc_regt; + struct xbridge_bus sc_bus[MAX_BUSES]; +}; + +#define DEVNAME(xb) ((xb)->xb_sc->sc_dev.dv_xname) + const struct cfattach xbridge_ca = { sizeof(struct xbridge_softc), xbridge_match, xbridge_attach, }; @@ -131,6 +163,8 @@ struct cfdriver xbridge_cd = { NULL, "xbridge", DV_DULL, }; +void xbridge_attach_bus(struct xbridge_softc *, uint, bus_space_tag_t); + void xbridge_attach_hook(struct device *, struct device *, struct pcibus_attach_args *); int xbridge_bus_maxdevs(void *, int); @@ -196,32 +230,50 @@ int xbridge_rbus_space_map(bus_space_tag_t, bus_addr_t, bus_size_t, void xbridge_rbus_space_unmap(bus_space_tag_t, bus_space_handle_t, bus_size_t, bus_addr_t *); -int xbridge_address_map(struct xbridge_softc *, paddr_t, bus_addr_t *, +int xbridge_address_map(struct xbridge_bus *, paddr_t, bus_addr_t *, bus_addr_t *); -void xbridge_address_unmap(struct xbridge_softc *, bus_addr_t, bus_size_t); -uint xbridge_ate_add(struct xbridge_softc *, paddr_t); -void xbridge_ate_dump(struct xbridge_softc *); -uint xbridge_ate_find(struct xbridge_softc *, paddr_t); -uint64_t xbridge_ate_read(struct xbridge_softc *, uint); -void xbridge_ate_unref(struct xbridge_softc *, uint, uint); -void xbridge_ate_write(struct xbridge_softc *, uint, uint64_t); - -int xbridge_allocate_devio(struct xbridge_softc *, int, int); -void xbridge_set_devio(struct xbridge_softc *, int, uint32_t); - -int xbridge_resource_explore(struct xbridge_softc *, pcitag_t, +void xbridge_address_unmap(struct xbridge_bus *, bus_addr_t, bus_size_t); +uint xbridge_ate_add(struct xbridge_bus *, paddr_t); +void xbridge_ate_dump(struct xbridge_bus *); +uint xbridge_ate_find(struct xbridge_bus *, paddr_t); +uint64_t xbridge_ate_read(struct xbridge_bus *, uint); +void xbridge_ate_unref(struct xbridge_bus *, uint, uint); +void xbridge_ate_write(struct xbridge_bus *, uint, uint64_t); + +int xbridge_allocate_devio(struct xbridge_bus *, int, int); +void xbridge_set_devio(struct xbridge_bus *, int, uint32_t); + +int xbridge_resource_explore(struct xbridge_bus *, pcitag_t, struct extent *, struct extent *); -void xbridge_resource_manage(struct xbridge_softc *, pcitag_t, +void xbridge_resource_manage(struct xbridge_bus *, pcitag_t, struct extent *, struct extent *); -void xbridge_ate_setup(struct xbridge_softc *); -void xbridge_device_setup(struct xbridge_softc *, int, int, uint32_t); -void xbridge_extent_setup(struct xbridge_softc *); +void xbridge_ate_setup(struct xbridge_bus *); +void xbridge_device_setup(struct xbridge_bus *, int, int, uint32_t); +void xbridge_extent_setup(struct xbridge_bus *); struct extent * - xbridge_mapping_setup(struct xbridge_softc *, int); -void xbridge_resource_setup(struct xbridge_softc *); -void xbridge_rrb_setup(struct xbridge_softc *, int); -void xbridge_setup(struct xbridge_softc *); + xbridge_mapping_setup(struct xbridge_bus *, int); +void xbridge_resource_setup(struct xbridge_bus *); +void xbridge_rrb_setup(struct xbridge_bus *, int); +void xbridge_setup(struct xbridge_bus *); + +uint32_t bridge_read_reg(bus_space_tag_t, bus_space_handle_t, bus_addr_t); +void bridge_write_reg(bus_space_tag_t, bus_space_handle_t, bus_addr_t, + uint32_t); +uint32_t pic_read_reg(bus_space_tag_t, bus_space_handle_t, bus_addr_t); +void pic_write_reg(bus_space_tag_t, bus_space_handle_t, bus_addr_t, + uint32_t); + +static __inline__ uint32_t +xbridge_read_reg(struct xbridge_bus *xb, bus_addr_t a) +{ + return (*xb->xb_read_reg)(xb->xb_regt, xb->xb_regh, a); +} +static __inline__ void +xbridge_write_reg(struct xbridge_bus *xb, bus_addr_t a, uint32_t v) +{ + (*xb->xb_write_reg)(xb->xb_regt, xb->xb_regh, a, v); +} const struct machine_bus_dma_tag xbridge_dma_tag = { NULL, /* _cookie */ @@ -248,18 +300,31 @@ const struct machine_bus_dma_tag xbridge_dma_tag = { ********************* Autoconf glue. */ +static const struct { + uint32_t vendor; + uint32_t product; + int flags; +} xbridge_devices[] = { + /* original Bridge */ + { XBOW_VENDOR_SGI4, XBOW_PRODUCT_SGI4_BRIDGE, 0 }, + /* XBridge */ + { XBOW_VENDOR_SGI3, XBOW_PRODUCT_SGI3_XBRIDGE, XF_XBRIDGE }, + /* PIC first half */ + { XBOW_VENDOR_SGI3, XBOW_PRODUCT_SGI3_PIC0, XF_PIC }, + /* PIC second half */ + { XBOW_VENDOR_SGI3, XBOW_PRODUCT_SGI3_PIC1, XF_PIC } +}; + int xbridge_match(struct device *parent, void *match, void *aux) { struct xbow_attach_args *xaa = aux; + uint i; - if (xaa->xaa_vendor == XBOW_VENDOR_SGI4 && - xaa->xaa_product == XBOW_PRODUCT_SGI4_BRIDGE) - return 1; - - if (xaa->xaa_vendor == XBOW_VENDOR_SGI3 && - xaa->xaa_product == XBOW_PRODUCT_SGI3_XBRIDGE) - return 1; + for (i = 0; i < nitems(xbridge_devices); i++) + if (xaa->xaa_vendor == xbridge_devices[i].vendor && + xaa->xaa_product == xbridge_devices[i].product) + return 1; return 0; } @@ -268,31 +333,83 @@ void xbridge_attach(struct device *parent, struct device *self, void *aux) { struct xbridge_softc *sc = (struct xbridge_softc *)self; - struct pcibus_attach_args pba; struct xbow_attach_args *xaa = aux; + uint i; sc->sc_nasid = xaa->xaa_nasid; sc->sc_widget = xaa->xaa_widget; printf(" revision %d\n", xaa->xaa_revision); - if (xaa->xaa_vendor == XBOW_VENDOR_SGI3 && - xaa->xaa_product == XBOW_PRODUCT_SGI3_XBRIDGE) - sc->sc_flags |= XBRIDGE_FLAGS_XBRIDGE; - else if (xaa->xaa_revision < 4) - sc->sc_flags |= XBRIDGE_FLAGS_NO_DIRECT_IO; + + for (i = 0; i < nitems(xbridge_devices); i++) + if (xaa->xaa_vendor == xbridge_devices[i].vendor && + xaa->xaa_product == xbridge_devices[i].product) { + sc->sc_flags = xbridge_devices[i].flags; + break; + } + + /* PICs are XBridges without an I/O window */ + if (ISSET(sc->sc_flags, XF_PIC)) + SET(sc->sc_flags, XF_XBRIDGE | XF_NO_DIRECT_IO); + /* Bridge < D lacks an I/O window */ + if (!ISSET(sc->sc_flags, XF_XBRIDGE) && xaa->xaa_revision < 4) + SET(sc->sc_flags, XF_NO_DIRECT_IO); + + /* + * Figure out where the devio mappings will go. + * On Octane, they are relative to the start of the widget. + * On Origin, they are computed from the widget number. + */ + if (sys_config.system_type == SGI_OCTANE) + sc->sc_devio_skew = 0; + else + sc->sc_devio_skew = sc->sc_widget; + + sc->sc_nbuses = + ISSET(sc->sc_flags, XF_PIC) ? PIC_NBUSES : BRIDGE_NBUSES; + + /* make a permanent copy of the on-stack bus_space_tag */ + bcopy(xaa->xaa_iot, &sc->sc_regt, sizeof(struct mips_bus_space)); + + /* configure and attach PCI buses */ + for (i = 0; i < sc->sc_nbuses; i++) + xbridge_attach_bus(sc, i, &sc->sc_regt); +} + +void +xbridge_attach_bus(struct xbridge_softc *sc, uint busno, bus_space_tag_t regt) +{ + struct xbridge_bus *xb = &sc->sc_bus[busno]; + struct pcibus_attach_args pba; + + xb->xb_sc = sc; + xb->xb_busno = busno; + xb->xb_flags = sc->sc_flags; + xb->xb_nasid = sc->sc_nasid; + xb->xb_widget = sc->sc_widget; + xb->xb_devio_skew = sc->sc_devio_skew; + + if (ISSET(sc->sc_flags, XF_PIC)) { + xb->xb_nslots = PIC_NSLOTS; + + xb->xb_read_reg = pic_read_reg; + xb->xb_write_reg = pic_write_reg; + } else { + xb->xb_nslots = BRIDGE_NSLOTS; + + xb->xb_read_reg = bridge_read_reg; + xb->xb_write_reg = bridge_write_reg; + } /* * Map Bridge registers. */ - sc->sc_iot = malloc(sizeof (*sc->sc_iot), M_DEVBUF, M_NOWAIT); - if (sc->sc_iot == NULL) - goto fail0; - bcopy(xaa->xaa_iot, sc->sc_iot, sizeof (*sc->sc_iot)); - if (bus_space_map(sc->sc_iot, 0, BRIDGE_REGISTERS_SIZE, 0, - &sc->sc_regh)) { - printf("%s: unable to map control registers\n", self->dv_xname); - free(sc->sc_iot, M_DEVBUF); + xb->xb_regt = regt; + if (bus_space_map(regt, busno != 0 ? BRIDGE_BUS_OFFSET : 0, + BRIDGE_REGISTERS_SIZE, 0, &xb->xb_regh)) { + printf("%s: unable to map control registers for bus %u\n", + DEVNAME(xb), busno); return; } @@ -302,74 +419,72 @@ xbridge_attach(struct device *parent, struct device *self, void *aux) * low-order address bits. */ - sc->sc_mem_bus_space = malloc(sizeof (*sc->sc_mem_bus_space), + xb->xb_mem_bus_space = malloc(sizeof (*xb->xb_mem_bus_space), M_DEVBUF, M_NOWAIT); - if (sc->sc_mem_bus_space == NULL) + if (xb->xb_mem_bus_space == NULL) goto fail1; - sc->sc_io_bus_space = malloc(sizeof (*sc->sc_io_bus_space), + xb->xb_io_bus_space = malloc(sizeof (*xb->xb_io_bus_space), M_DEVBUF, M_NOWAIT); - if (sc->sc_io_bus_space == NULL) + if (xb->xb_io_bus_space == NULL) goto fail2; - bcopy(xaa->xaa_iot, sc->sc_mem_bus_space, - sizeof(*sc->sc_mem_bus_space)); - sc->sc_mem_bus_space->bus_private = sc; - sc->sc_mem_bus_space->_space_map = xbridge_space_map_devio; - sc->sc_mem_bus_space->_space_subregion = xbridge_space_region_devio; - sc->sc_mem_bus_space->_space_read_1 = xbridge_read_1; - sc->sc_mem_bus_space->_space_write_1 = xbridge_write_1; - sc->sc_mem_bus_space->_space_read_2 = xbridge_read_2; - sc->sc_mem_bus_space->_space_write_2 = xbridge_write_2; - sc->sc_mem_bus_space->_space_read_raw_2 = xbridge_read_raw_2; - sc->sc_mem_bus_space->_space_write_raw_2 = xbridge_write_raw_2; - sc->sc_mem_bus_space->_space_read_raw_4 = xbridge_read_raw_4; - sc->sc_mem_bus_space->_space_write_raw_4 = xbridge_write_raw_4; - sc->sc_mem_bus_space->_space_read_raw_8 = xbridge_read_raw_8; - sc->sc_mem_bus_space->_space_write_raw_8 = xbridge_write_raw_8; - - bcopy(xaa->xaa_iot, sc->sc_io_bus_space, - sizeof(*sc->sc_io_bus_space)); - sc->sc_io_bus_space->bus_private = sc; - sc->sc_io_bus_space->_space_map = xbridge_space_map_devio; - sc->sc_io_bus_space->_space_subregion = xbridge_space_region_devio; - sc->sc_io_bus_space->_space_read_1 = xbridge_read_1; - sc->sc_io_bus_space->_space_write_1 = xbridge_write_1; - sc->sc_io_bus_space->_space_read_2 = xbridge_read_2; - sc->sc_io_bus_space->_space_write_2 = xbridge_write_2; - sc->sc_io_bus_space->_space_read_raw_2 = xbridge_read_raw_2; - sc->sc_io_bus_space->_space_write_raw_2 = xbridge_write_raw_2; - sc->sc_io_bus_space->_space_read_raw_4 = xbridge_read_raw_4; - sc->sc_io_bus_space->_space_write_raw_4 = xbridge_write_raw_4; - sc->sc_io_bus_space->_space_read_raw_8 = xbridge_read_raw_8; - sc->sc_io_bus_space->_space_write_raw_8 = xbridge_write_raw_8; - - sc->sc_dmat = malloc(sizeof (*sc->sc_dmat), M_DEVBUF, M_NOWAIT); - if (sc->sc_dmat == NULL) + bcopy(regt, xb->xb_mem_bus_space, sizeof(*xb->xb_mem_bus_space)); + xb->xb_mem_bus_space->bus_private = xb; + xb->xb_mem_bus_space->_space_map = xbridge_space_map_devio; + xb->xb_mem_bus_space->_space_subregion = xbridge_space_region_devio; + xb->xb_mem_bus_space->_space_read_1 = xbridge_read_1; + xb->xb_mem_bus_space->_space_write_1 = xbridge_write_1; + xb->xb_mem_bus_space->_space_read_2 = xbridge_read_2; + xb->xb_mem_bus_space->_space_write_2 = xbridge_write_2; + xb->xb_mem_bus_space->_space_read_raw_2 = xbridge_read_raw_2; + xb->xb_mem_bus_space->_space_write_raw_2 = xbridge_write_raw_2; + xb->xb_mem_bus_space->_space_read_raw_4 = xbridge_read_raw_4; + xb->xb_mem_bus_space->_space_write_raw_4 = xbridge_write_raw_4; + xb->xb_mem_bus_space->_space_read_raw_8 = xbridge_read_raw_8; + xb->xb_mem_bus_space->_space_write_raw_8 = xbridge_write_raw_8; + + bcopy(regt, xb->xb_io_bus_space, sizeof(*xb->xb_io_bus_space)); + xb->xb_io_bus_space->bus_private = xb; + xb->xb_io_bus_space->_space_map = xbridge_space_map_devio; + xb->xb_io_bus_space->_space_subregion = xbridge_space_region_devio; + xb->xb_io_bus_space->_space_read_1 = xbridge_read_1; + xb->xb_io_bus_space->_space_write_1 = xbridge_write_1; + xb->xb_io_bus_space->_space_read_2 = xbridge_read_2; + xb->xb_io_bus_space->_space_write_2 = xbridge_write_2; + xb->xb_io_bus_space->_space_read_raw_2 = xbridge_read_raw_2; + xb->xb_io_bus_space->_space_write_raw_2 = xbridge_write_raw_2; + xb->xb_io_bus_space->_space_read_raw_4 = xbridge_read_raw_4; + xb->xb_io_bus_space->_space_write_raw_4 = xbridge_write_raw_4; + xb->xb_io_bus_space->_space_read_raw_8 = xbridge_read_raw_8; + xb->xb_io_bus_space->_space_write_raw_8 = xbridge_write_raw_8; + + xb->xb_dmat = malloc(sizeof (*xb->xb_dmat), M_DEVBUF, M_NOWAIT); + if (xb->xb_dmat == NULL) goto fail3; - memcpy(sc->sc_dmat, &xbridge_dma_tag, sizeof(*sc->sc_dmat)); - sc->sc_dmat->_cookie = sc; + memcpy(xb->xb_dmat, &xbridge_dma_tag, sizeof(*xb->xb_dmat)); + xb->xb_dmat->_cookie = xb; /* * Initialize PCI methods. */ - sc->sc_pc.pc_conf_v = sc; - sc->sc_pc.pc_attach_hook = xbridge_attach_hook; - sc->sc_pc.pc_make_tag = xbridge_make_tag; - sc->sc_pc.pc_decompose_tag = xbridge_decompose_tag; - sc->sc_pc.pc_bus_maxdevs = xbridge_bus_maxdevs; - sc->sc_pc.pc_conf_read = xbridge_conf_read; - sc->sc_pc.pc_conf_write = xbridge_conf_write; - sc->sc_pc.pc_intr_v = sc; - sc->sc_pc.pc_intr_map = xbridge_intr_map; - sc->sc_pc.pc_intr_string = xbridge_intr_string; - sc->sc_pc.pc_intr_establish = xbridge_intr_establish; - sc->sc_pc.pc_intr_disestablish = xbridge_intr_disestablish; - sc->sc_pc.pc_intr_line = xbridge_intr_line; - sc->sc_pc.pc_ppb_setup = xbridge_ppb_setup; + xb->xb_pc.pc_conf_v = xb; + xb->xb_pc.pc_attach_hook = xbridge_attach_hook; + xb->xb_pc.pc_make_tag = xbridge_make_tag; + xb->xb_pc.pc_decompose_tag = xbridge_decompose_tag; + xb->xb_pc.pc_bus_maxdevs = xbridge_bus_maxdevs; + xb->xb_pc.pc_conf_read = xbridge_conf_read; + xb->xb_pc.pc_conf_write = xbridge_conf_write; + xb->xb_pc.pc_intr_v = xb; + xb->xb_pc.pc_intr_map = xbridge_intr_map; + xb->xb_pc.pc_intr_string = xbridge_intr_string; + xb->xb_pc.pc_intr_establish = xbridge_intr_establish; + xb->xb_pc.pc_intr_disestablish = xbridge_intr_disestablish; + xb->xb_pc.pc_intr_line = xbridge_intr_line; + xb->xb_pc.pc_ppb_setup = xbridge_ppb_setup; #if NCARDBUS > 0 - sc->sc_pc.pc_rbus_parent_io = xbridge_rbus_parent_io; - sc->sc_pc.pc_rbus_parent_mem = xbridge_rbus_parent_mem; + xb->xb_pc.pc_rbus_parent_io = xbridge_rbus_parent_io; + xb->xb_pc.pc_rbus_parent_mem = xbridge_rbus_parent_mem; #endif /* @@ -377,37 +492,35 @@ xbridge_attach(struct device *parent, struct device *self, void *aux) * RRB allocation, etc). */ - xbridge_setup(sc); + xbridge_setup(xb); /* * Attach children. */ - xbridge_extent_setup(sc); + xbridge_extent_setup(xb); bzero(&pba, sizeof(pba)); pba.pba_busname = "pci"; - pba.pba_iot = sc->sc_io_bus_space; - pba.pba_memt = sc->sc_mem_bus_space; - pba.pba_dmat = sc->sc_dmat; - pba.pba_ioex = sc->sc_ioex; - pba.pba_memex = sc->sc_memex; - pba.pba_pc = &sc->sc_pc; + pba.pba_iot = xb->xb_io_bus_space; + pba.pba_memt = xb->xb_mem_bus_space; + pba.pba_dmat = xb->xb_dmat; + pba.pba_ioex = xb->xb_ioex; + pba.pba_memex = xb->xb_memex; + pba.pba_pc = &xb->xb_pc; pba.pba_domain = pci_ndomains++; pba.pba_bus = 0; - config_found(self, &pba, xbridge_print); + config_found(&sc->sc_dev, &pba, xbridge_print); return; fail3: - free(sc->sc_io_bus_space, M_DEVBUF); + free(xb->xb_io_bus_space, M_DEVBUF); fail2: - free(sc->sc_mem_bus_space, M_DEVBUF); + free(xb->xb_mem_bus_space, M_DEVBUF); fail1: - free(sc->sc_iot, M_DEVBUF); -fail0: - printf("%s: not enough memory to build access structures\n", - self->dv_xname); + printf("%s: not enough memory to build bus %u access structures\n", + DEVNAME(xb), busno); return; } @@ -454,13 +567,15 @@ xbridge_decompose_tag(void *cookie, pcitag_t tag, int *busp, int *devp, int xbridge_bus_maxdevs(void *cookie, int busno) { - return busno == 0 ? BRIDGE_NSLOTS : 32; + struct xbridge_bus *xb = cookie; + + return busno == 0 ? xb->xb_nslots : 32; } pcireg_t xbridge_conf_read(void *cookie, pcitag_t tag, int offset) { - struct xbridge_softc *sc = cookie; + struct xbridge_bus *xb = cookie; pcireg_t data; int bus, dev, fn; paddr_t pa; @@ -472,11 +587,20 @@ xbridge_conf_read(void *cookie, pcitag_t tag, int offset) xbridge_decompose_tag(cookie, tag, &bus, &dev, &fn); if (bus != 0) { - bus_space_write_4(sc->sc_iot, sc->sc_regh, BRIDGE_PCI_CFG, + xbridge_write_reg(xb, BRIDGE_PCI_CFG, (bus << 16) | (dev << 11)); - pa = sc->sc_regh + BRIDGE_PCI_CFG1_SPACE; - } else - pa = sc->sc_regh + BRIDGE_PCI_CFG_SPACE + (dev << 12); + pa = xb->xb_regh + BRIDGE_PCI_CFG1_SPACE; + } else { + if (ISSET(xb->xb_flags, XF_PIC)) { + /* + * On PIC, device 0 in configuration space is the + * PIC itself, device slots are offset by one. + */ + pa = xb->xb_regh + BRIDGE_PCI_CFG_SPACE + + ((dev + 1) << 12); + } else + pa = xb->xb_regh + BRIDGE_PCI_CFG_SPACE + (dev << 12); + } /* * IOC3 devices only implement a subset of the PCI configuration @@ -492,7 +616,7 @@ xbridge_conf_read(void *cookie, pcitag_t tag, int offset) */ skip = 0; - if (bus == 0 && sc->sc_devices[dev].id == + if (bus == 0 && xb->xb_devices[dev].id == PCI_ID_CODE(PCI_VENDOR_SGI, PCI_PRODUCT_SGI_IOC3)) { switch (offset) { case PCI_ID_REG: @@ -530,7 +654,7 @@ xbridge_conf_read(void *cookie, pcitag_t tag, int offset) void xbridge_conf_write(void *cookie, pcitag_t tag, int offset, pcireg_t data) { - struct xbridge_softc *sc = cookie; + struct xbridge_bus *xb = cookie; int bus, dev, fn; paddr_t pa; int skip; @@ -541,11 +665,20 @@ xbridge_conf_write(void *cookie, pcitag_t tag, int offset, pcireg_t data) xbridge_decompose_tag(cookie, tag, &bus, &dev, &fn); if (bus != 0) { - bus_space_write_4(sc->sc_iot, sc->sc_regh, BRIDGE_PCI_CFG, + xbridge_write_reg(xb, BRIDGE_PCI_CFG, (bus << 16) | (dev << 11)); - pa = sc->sc_regh + BRIDGE_PCI_CFG1_SPACE; - } else - pa = sc->sc_regh + BRIDGE_PCI_CFG_SPACE + (dev << 12); + pa = xb->xb_regh + BRIDGE_PCI_CFG1_SPACE; + } else { + if (ISSET(xb->xb_flags, XF_PIC)) { + /* + * On PIC, device 0 in configuration space is the + * PIC itself, device slots are offset by one. + */ + pa = xb->xb_regh + BRIDGE_PCI_CFG_SPACE + + ((dev + 1) << 12); + } else + pa = xb->xb_regh + BRIDGE_PCI_CFG_SPACE + (dev << 12); + } /* * IOC3 devices only implement a subset of the PCI configuration @@ -559,7 +692,7 @@ xbridge_conf_write(void *cookie, pcitag_t tag, int offset, pcireg_t data) */ skip = 0; - if (bus == 0 && sc->sc_devices[dev].id == + if (bus == 0 && xb->xb_devices[dev].id == PCI_ID_CODE(PCI_VENDOR_SGI, PCI_PRODUCT_SGI_IOC3)) { switch (offset) { case PCI_COMMAND_STATUS_REG: @@ -611,7 +744,7 @@ struct xbridge_intrhandler { }; struct xbridge_intr { - struct xbridge_softc *xi_bridge; + struct xbridge_bus *xi_bus; int xi_intrsrc; /* interrupt source on interrupt widget */ int xi_intrbit; /* interrupt source on BRIDGE */ LIST_HEAD(, xbridge_intrhandler) xi_handlers; @@ -626,7 +759,7 @@ struct xbridge_intr { int xbridge_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) { - struct xbridge_softc *sc = pa->pa_pc->pc_conf_v; + struct xbridge_bus *xb = pa->pa_pc->pc_conf_v; int bus, device, intr; int pin; @@ -655,7 +788,7 @@ xbridge_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) /* * For IOC devices, the real information is in pa_intrline. */ - if (sc->sc_devices[device].id == + if (xb->xb_devices[device].id == PCI_ID_CODE(PCI_VENDOR_SGI, PCI_PRODUCT_SGI_IOC3)) { intr = pa->pa_intrline; } else { @@ -684,7 +817,7 @@ void * xbridge_intr_establish(void *cookie, pci_intr_handle_t ih, int level, int (*func)(void *), void *arg, char *name) { - struct xbridge_softc *sc = (struct xbridge_softc *)cookie; + struct xbridge_bus *xb = (struct xbridge_bus *)cookie; struct xbridge_intr *xi; struct xbridge_intrhandler *xih; uint32_t int_addr; @@ -697,23 +830,23 @@ xbridge_intr_establish(void *cookie, pci_intr_handle_t ih, int level, * Allocate bookkeeping structure if this is the * first time we're using this interrupt source. */ - if ((xi = sc->sc_intr[intrbit]) == NULL) { + if ((xi = xb->xb_intr[intrbit]) == NULL) { xi = (struct xbridge_intr *) malloc(sizeof(*xi), M_DEVBUF, M_NOWAIT); if (xi == NULL) return NULL; - xi->xi_bridge = sc; + xi->xi_bus = xb; xi->xi_intrbit = intrbit; LIST_INIT(&xi->xi_handlers); - if (xbow_intr_register(sc->sc_widget, level, &intrsrc) != 0) { + if (xbow_intr_register(xb->xb_widget, level, &intrsrc) != 0) { free(xi, M_DEVBUF); return NULL; } xi->xi_intrsrc = intrsrc; - sc->sc_intr[intrbit] = xi; + xb->xb_intr[intrbit] = xi; } /* @@ -730,7 +863,7 @@ xbridge_intr_establish(void *cookie, pci_intr_handle_t ih, int level, if (xbow_intr_establish(xbridge_intr_handler, xi, intrsrc, IPL_BIO, NULL)) { printf("%s: unable to register interrupt handler\n", - sc->sc_dev.dv_xname); + DEVNAME(xb)); return NULL; } } @@ -749,14 +882,16 @@ xbridge_intr_establish(void *cookie, pci_intr_handle_t ih, int level, LIST_INSERT_HEAD(&xi->xi_handlers, xih, xih_nxt); if (new) { - int_addr = - ((xbow_intr_widget_register >> 30) & 0x0003ff00) | intrsrc; - - bus_space_write_4(sc->sc_iot, sc->sc_regh, - BRIDGE_INT_ADDR(intrbit), int_addr); - bus_space_write_4(sc->sc_iot, sc->sc_regh, BRIDGE_IER, - bus_space_read_4(sc->sc_iot, sc->sc_regh, BRIDGE_IER) | - (1 << intrbit)); + if (ISSET(xb->xb_flags, XF_PIC)) + int_addr = ((uint64_t)intrsrc << 48) | + (xbow_intr_widget_register & ((1UL << 48) - 1)); + else + int_addr = ((xbow_intr_widget_register >> 30) & + 0x0003ff00) | intrsrc; + + xbridge_write_reg(xb, BRIDGE_INT_ADDR(intrbit), int_addr); + xbridge_write_reg(xb, BRIDGE_IER, + xbridge_read_reg(xb, BRIDGE_IER) | (1 << intrbit)); /* * INT_MODE register controls which interrupt pins cause * ``interrupt clear'' packets to be sent for high->low @@ -764,13 +899,12 @@ xbridge_intr_establish(void *cookie, pci_intr_handle_t ih, int level, * We enable such packets to be sent in order not to have to * clear interrupts ourselves. */ - bus_space_write_4(sc->sc_iot, sc->sc_regh, BRIDGE_INT_MODE, - bus_space_read_4(sc->sc_iot, sc->sc_regh, BRIDGE_INT_MODE) | - (1 << intrbit)); - bus_space_write_4(sc->sc_iot, sc->sc_regh, BRIDGE_INT_DEV, - bus_space_read_4(sc->sc_iot, sc->sc_regh, BRIDGE_INT_DEV) | + xbridge_write_reg(xb, BRIDGE_INT_MODE, + xbridge_read_reg(xb, BRIDGE_INT_MODE) | (1 << intrbit)); + xbridge_write_reg(xb, BRIDGE_INT_DEV, + xbridge_read_reg(xb, BRIDGE_INT_DEV) | (device << (intrbit * 3))); - (void)bus_space_read_4(sc->sc_iot, sc->sc_regh, WIDGET_TFLUSH); + (void)xbridge_read_reg(xb, WIDGET_TFLUSH); } return (void *)xih; @@ -779,7 +913,7 @@ xbridge_intr_establish(void *cookie, pci_intr_handle_t ih, int level, void xbridge_intr_disestablish(void *cookie, void *vih) { - struct xbridge_softc *sc = cookie; + struct xbridge_bus *xb = cookie; struct xbridge_intrhandler *xih = (struct xbridge_intrhandler *)vih; struct xbridge_intr *xi = xih->xih_main; int intrbit = xi->xi_intrbit; @@ -788,22 +922,19 @@ xbridge_intr_disestablish(void *cookie, void *vih) LIST_REMOVE(xih, xih_nxt); if (LIST_EMPTY(&xi->xi_handlers)) { - bus_space_write_4(sc->sc_iot, sc->sc_regh, - BRIDGE_INT_ADDR(intrbit), 0); - bus_space_write_4(sc->sc_iot, sc->sc_regh, BRIDGE_IER, - bus_space_read_4(sc->sc_iot, sc->sc_regh, BRIDGE_IER) & - ~(1 << intrbit)); - bus_space_write_4(sc->sc_iot, sc->sc_regh, BRIDGE_INT_MODE, - bus_space_read_4(sc->sc_iot, sc->sc_regh, BRIDGE_INT_MODE) & - ~(1 << intrbit)); - bus_space_write_4(sc->sc_iot, sc->sc_regh, BRIDGE_INT_DEV, - bus_space_read_4(sc->sc_iot, sc->sc_regh, BRIDGE_INT_DEV) & + xbridge_write_reg(xb, BRIDGE_INT_ADDR(intrbit), 0); + xbridge_write_reg(xb, BRIDGE_IER, + xbridge_read_reg(xb, BRIDGE_IER) & ~(1 << intrbit)); + xbridge_write_reg(xb, BRIDGE_INT_MODE, + xbridge_read_reg(xb, BRIDGE_INT_MODE) & ~(1 << intrbit)); + xbridge_write_reg(xb, BRIDGE_INT_DEV, + xbridge_read_reg(xb, BRIDGE_INT_DEV) & ~(7 << (intrbit * 3))); - (void)bus_space_read_4(sc->sc_iot, sc->sc_regh, WIDGET_TFLUSH); + (void)xbridge_read_reg(xb, WIDGET_TFLUSH); xbow_intr_disestablish(xi->xi_intrsrc); /* - * Note we could free sc->sc_intr[intrbit] at this point, + * Note we could free xb->xb_intr[intrbit] at this point, * but it's not really worth doing. */ } @@ -821,14 +952,14 @@ int xbridge_intr_handler(void *v) { struct xbridge_intr *xi = (struct xbridge_intr *)v; - struct xbridge_softc *sc = xi->xi_bridge; + struct xbridge_bus *xb = xi->xi_bus; struct xbridge_intrhandler *xih; int rc = 0; int spurious; + uint32_t isr; if (LIST_EMPTY(&xi->xi_handlers)) { - printf("%s: spurious irq %d\n", - sc->sc_dev.dv_xname, xi->xi_intrbit); + printf("%s: spurious irq %d\n", DEVNAME(xb), xi->xi_intrbit); return 0; } @@ -836,16 +967,14 @@ xbridge_intr_handler(void *v) * Flush PCI write buffers before servicing the interrupt. */ LIST_FOREACH(xih, &xi->xi_handlers, xih_nxt) - bus_space_read_4(sc->sc_iot, sc->sc_regh, - BRIDGE_DEVICE_WBFLUSH(xih->xih_device)); + xbridge_read_reg(xb, BRIDGE_DEVICE_WBFLUSH(xih->xih_device)); - if ((bus_space_read_4(sc->sc_iot, sc->sc_regh, BRIDGE_ISR) & - (1 << xi->xi_intrbit)) == 0) { + isr = xbridge_read_reg(xb, BRIDGE_ISR); + if ((isr & (1 << xi->xi_intrbit)) == 0) { spurious = 1; #ifdef DEBUG printf("%s: irq %d but not pending in ISR %08x\n", - sc->sc_dev.dv_xname, xi->xi_intrbit, - bus_space_read_4(sc->sc_iot, sc->sc_regh, BRIDGE_ISR)); + DEVNAME(xb), xi->xi_intrbit, isr); #endif } else spurious = 0; @@ -858,8 +987,7 @@ xbridge_intr_handler(void *v) } } if (rc == 0 && spurious == 0) - printf("%s: spurious irq %d\n", - sc->sc_dev.dv_xname, xi->xi_intrbit); + printf("%s: spurious irq %d\n", DEVNAME(xb), xi->xi_intrbit); /* * There is a known BRIDGE race in which, if two interrupts @@ -875,12 +1003,10 @@ xbridge_intr_handler(void *v) * do not even have to check if our interrupt is pending. */ - if (ISSET(sc->sc_flags, XBRIDGE_FLAGS_XBRIDGE)) { - bus_space_write_4(sc->sc_iot, sc->sc_regh, - BRIDGE_INT_FORCE_PIN(xi->xi_intrbit), 1); - } else { - if (bus_space_read_4(sc->sc_iot, sc->sc_regh, - BRIDGE_ISR) & (1 << xi->xi_intrbit)) { + if (ISSET(xb->xb_flags, XF_XBRIDGE)) + xbridge_write_reg(xb, BRIDGE_INT_FORCE_PIN(xi->xi_intrbit), 1); + else { + if (xbridge_read_reg(xb, BRIDGE_ISR) & (1 << xi->xi_intrbit)) { switch (sys_config.system_type) { #if defined(TGT_OCTANE) case SGI_OCTANE: @@ -890,7 +1016,7 @@ xbridge_intr_handler(void *v) #if defined(TGT_ORIGIN200) || defined(TGT_ORIGIN2000) case SGI_O200: case SGI_O300: - IP27_RHUB_PI_S(sc->sc_nasid, 0, HUBPI_IR_CHANGE, + IP27_RHUB_PI_S(xb->xb_nasid, 0, HUBPI_IR_CHANGE, PI_IR_SET | xi->xi_intrsrc); break; #endif @@ -902,6 +1028,35 @@ xbridge_intr_handler(void *v) } /* + ********************* chip register access. + */ + +uint32_t +bridge_read_reg(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t a) +{ + return widget_read_4(t, h, a); +} +void +bridge_write_reg(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t a, + uint32_t v) +{ + widget_write_4(t, h, a, v); +} + +uint32_t +pic_read_reg(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t a) +{ + return (uint32_t)widget_read_8(t, h, a); +} + +void +pic_write_reg(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t a, + uint32_t v) +{ + widget_write_8(t, h, a, (uint64_t)v); +} + +/* ********************* bus_space glue. */ @@ -1007,14 +1162,14 @@ int xbridge_space_map_devio(bus_space_tag_t t, bus_addr_t offs, bus_size_t size, int flags, bus_space_handle_t *bshp) { - struct xbridge_softc *sc = (struct xbridge_softc *)t->bus_private; + struct xbridge_bus *xb = (struct xbridge_bus *)t->bus_private; bus_addr_t bpa; #ifdef DIAGNOSTIC bus_addr_t start, end; uint d; #endif - if ((offs >> 24) != sc->sc_devio_skew) + if ((offs >> 24) != xb->xb_devio_skew) return EINVAL; /* not a devio mapping */ /* @@ -1023,8 +1178,8 @@ xbridge_space_map_devio(bus_space_tag_t t, bus_addr_t offs, bus_size_t size, */ bpa = offs & ((1UL << 24) - 1); #ifdef DIAGNOSTIC - for (d = 0; d < BRIDGE_NSLOTS; d++) { - start = BRIDGE_DEVIO_OFFS(d); + for (d = 0; d < xb->xb_nslots; d++) { + start = PIC_DEVIO_OFFS(xb->xb_busno, d); end = start + BRIDGE_DEVIO_SIZE(d); if (bpa >= start && bpa < end) { if (bpa + size > end) @@ -1033,7 +1188,7 @@ xbridge_space_map_devio(bus_space_tag_t t, bus_addr_t offs, bus_size_t size, break; } } - if (d == BRIDGE_NSLOTS) + if (d == xb->xb_nslots) return EINVAL; #endif @@ -1042,7 +1197,7 @@ xbridge_space_map_devio(bus_space_tag_t t, bus_addr_t offs, bus_size_t size, * to our small window. Instead, use the one used by the xbridge * driver itself, which _always_ points to the short window. */ - *bshp = sc->sc_iot->bus_base + bpa; + *bshp = xb->xb_regt->bus_base + bpa; return 0; } @@ -1050,19 +1205,19 @@ int xbridge_space_map_io(bus_space_tag_t t, bus_addr_t offs, bus_size_t size, int flags, bus_space_handle_t *bshp) { - struct xbridge_softc *sc = (struct xbridge_softc *)t->bus_private; + struct xbridge_bus *xb = (struct xbridge_bus *)t->bus_private; /* * Base address is either within the devio area, or our direct * window. */ - if ((offs >> 24) == sc->sc_devio_skew) + if ((offs >> 24) == xb->xb_devio_skew) return xbridge_space_map_devio(t, offs, size, flags, bshp); #ifdef DIAGNOSTIC /* check that this does not overflow the mapping */ - if (offs < sc->sc_iostart || offs + size - 1 > sc->sc_ioend) + if (offs < xb->xb_iostart || offs + size - 1 > xb->xb_ioend) return EINVAL; #endif @@ -1074,7 +1229,7 @@ int xbridge_space_map_mem(bus_space_tag_t t, bus_addr_t offs, bus_size_t size, int flags, bus_space_handle_t *bshp) { - struct xbridge_softc *sc = (struct xbridge_softc *)t->bus_private; + struct xbridge_bus *xb = (struct xbridge_bus *)t->bus_private; /* * Base address is either within the devio area, or our direct @@ -1083,12 +1238,12 @@ xbridge_space_map_mem(bus_space_tag_t t, bus_addr_t offs, bus_size_t size, */ if (sys_config.system_type != SGI_OCTANE && - (offs >> 24) == sc->sc_devio_skew) + (offs >> 24) == xb->xb_devio_skew) return xbridge_space_map_devio(t, offs, size, flags, bshp); #ifdef DIAGNOSTIC /* check that this does not overflow the mapping */ - if (offs < sc->sc_memstart || offs + size - 1 > sc->sc_memend) + if (offs < xb->xb_memstart || offs + size - 1 > xb->xb_memend) return EINVAL; #endif @@ -1101,7 +1256,7 @@ xbridge_space_region_devio(bus_space_tag_t t , bus_space_handle_t bsh, bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp) { #ifdef DIAGNOSTIC - struct xbridge_softc *sc = (struct xbridge_softc *)t->bus_private; + struct xbridge_bus *xb = (struct xbridge_bus *)t->bus_private; bus_addr_t bpa; bus_addr_t start, end; uint d; @@ -1113,7 +1268,7 @@ xbridge_space_region_devio(bus_space_tag_t t , bus_space_handle_t bsh, * to our small window. Instead, use the one used by the xbridge * driver itself, which _always_ points to the short window. */ - bpa = (bus_addr_t)bsh - sc->sc_iot->bus_base; + bpa = (bus_addr_t)bsh - xb->xb_regt->bus_base; if ((bpa >> 24) != 0) return EINVAL; /* not a devio mapping */ @@ -1122,8 +1277,8 @@ xbridge_space_region_devio(bus_space_tag_t t , bus_space_handle_t bsh, * Figure out which devio `slot' we are using, and make sure * we do not overrun it. */ - for (d = 0; d < BRIDGE_NSLOTS; d++) { - start = BRIDGE_DEVIO_OFFS(d); + for (d = 0; d < xb->xb_nslots; d++) { + start = PIC_DEVIO_OFFS(xb->xb_busno, d); end = start + BRIDGE_DEVIO_SIZE(d); if (bpa >= start && bpa < end) { if (bpa + offset + size > end) @@ -1132,7 +1287,7 @@ xbridge_space_region_devio(bus_space_tag_t t , bus_space_handle_t bsh, break; } } - if (d == BRIDGE_NSLOTS) + if (d == xb->xb_nslots) return EINVAL; #endif @@ -1144,7 +1299,7 @@ int xbridge_space_region_io(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp) { - struct xbridge_softc *sc = (struct xbridge_softc *)t->bus_private; + struct xbridge_bus *xb = (struct xbridge_bus *)t->bus_private; bus_addr_t bpa; /* @@ -1152,7 +1307,7 @@ xbridge_space_region_io(bus_space_tag_t t, bus_space_handle_t bsh, * to our small window. Instead, use the one used by the xbridge * driver itself, which _always_ points to the short window. */ - bpa = (bus_addr_t)bsh - sc->sc_iot->bus_base; + bpa = (bus_addr_t)bsh - xb->xb_regt->bus_base; if ((bpa >> 24) == 0) return xbridge_space_region_devio(t, bsh, offset, size, nbshp); @@ -1160,7 +1315,7 @@ xbridge_space_region_io(bus_space_tag_t t, bus_space_handle_t bsh, #ifdef DIAGNOSTIC /* check that this does not overflow the mapping */ bpa = (bus_addr_t)bsh - t->bus_base; - if (bpa + offset + size - 1 > sc->sc_ioend) + if (bpa + offset + size - 1 > xb->xb_ioend) return EINVAL; #endif @@ -1172,7 +1327,7 @@ int xbridge_space_region_mem(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp) { - struct xbridge_softc *sc = (struct xbridge_softc *)t->bus_private; + struct xbridge_bus *xb = (struct xbridge_bus *)t->bus_private; bus_addr_t bpa; /* @@ -1187,7 +1342,7 @@ xbridge_space_region_mem(bus_space_tag_t t, bus_space_handle_t bsh, * the xbridge driver itself, which _always_ points to the * short window. */ - bpa = (bus_addr_t)bsh - sc->sc_iot->bus_base; + bpa = (bus_addr_t)bsh - xb->xb_regt->bus_base; if ((bpa >> 24) == 0) return xbridge_space_region_devio(t, bsh, offset, size, @@ -1197,7 +1352,7 @@ xbridge_space_region_mem(bus_space_tag_t t, bus_space_handle_t bsh, #ifdef DIAGNOSTIC /* check that this does not overflow the mapping */ bpa = (bus_addr_t)bsh - t->bus_base; - if (bpa + offset + size - 1 > sc->sc_memend) + if (bpa + offset + size - 1 > xb->xb_memend) return EINVAL; #endif @@ -1255,13 +1410,13 @@ struct xbridge_ate { #ifdef ATE_DEBUG void -xbridge_ate_dump(struct xbridge_softc *sc) +xbridge_ate_dump(struct xbridge_bus *xb) { struct xbridge_ate *ate; uint a; - printf("%s ATE list (in array order)\n", sc->sc_dev.dv_xname); - for (a = 0, ate = sc->sc_ate; a < sc->sc_atecnt; a++, ate++) { + printf("%s ATE list (in array order)\n", DEVNAME(xb)); + for (a = 0, ate = xb->xb_ate; a < xb->xb_atecnt; a++, ate++) { printf("%03x %p %02u", a, ate->xa_pa, ate->xa_refcnt); if ((a % 3) == 2) printf("\n"); @@ -1271,11 +1426,11 @@ xbridge_ate_dump(struct xbridge_softc *sc) if ((a % 3) != 0) printf("\n"); - printf("%s USED ATE list (in link order)\n", sc->sc_dev.dv_xname); + printf("%s USED ATE list (in link order)\n", DEVNAME(xb)); a = 0; - LIST_FOREACH(ate, &sc->sc_used_ate, xa_nxt) { + LIST_FOREACH(ate, &xb->xb_used_ate, xa_nxt) { printf("%03x %p %02u", - ate - sc->sc_ate, ate->xa_pa, ate->xa_refcnt); + ate - xb->xb_ate, ate->xa_pa, ate->xa_refcnt); if ((a % 3) == 2) printf("\n"); else @@ -1285,11 +1440,11 @@ xbridge_ate_dump(struct xbridge_softc *sc) if ((a % 3) != 0) printf("\n"); - printf("%s FREE ATE list (in link order)\n", sc->sc_dev.dv_xname); + printf("%s FREE ATE list (in link order)\n", DEVNAME(xb)); a = 0; - LIST_FOREACH(ate, &sc->sc_free_ate, xa_nxt) { + LIST_FOREACH(ate, &xb->xb_free_ate, xa_nxt) { printf("%03x %p %02u", - ate - sc->sc_ate, ate->xa_pa, ate->xa_refcnt); + ate - xb->xb_ate, ate->xa_pa, ate->xa_refcnt); if ((a % 3) == 2) printf("\n"); else @@ -1302,22 +1457,22 @@ xbridge_ate_dump(struct xbridge_softc *sc) #endif void -xbridge_ate_setup(struct xbridge_softc *sc) +xbridge_ate_setup(struct xbridge_bus *xb) { uint32_t ctrl; uint a; struct xbridge_ate *ate; - mtx_init(&sc->sc_atemtx, IPL_HIGH); + mtx_init(&xb->xb_atemtx, IPL_HIGH); - if (ISSET(sc->sc_flags, XBRIDGE_FLAGS_XBRIDGE)) - sc->sc_atecnt = XBRIDGE_INTERNAL_ATE; + if (ISSET(xb->xb_flags, XF_XBRIDGE)) + xb->xb_atecnt = XBRIDGE_INTERNAL_ATE; else - sc->sc_atecnt = BRIDGE_INTERNAL_ATE; + xb->xb_atecnt = BRIDGE_INTERNAL_ATE; - sc->sc_ate = (struct xbridge_ate *)malloc(sc->sc_atecnt * + xb->xb_ate = (struct xbridge_ate *)malloc(xb->xb_atecnt * sizeof(struct xbridge_ate), M_DEVBUF, M_ZERO | M_NOWAIT); - if (sc->sc_ate == NULL) { + if (xb->xb_ate == NULL) { /* we could run without, but this would be a PITA */ panic("%s: no memory for ATE management", __func__); } @@ -1325,29 +1480,29 @@ xbridge_ate_setup(struct xbridge_softc *sc) /* * Setup the ATE lists. */ - LIST_INIT(&sc->sc_free_ate); - LIST_INIT(&sc->sc_used_ate); - for (ate = sc->sc_ate; ate != sc->sc_ate + sc->sc_atecnt; ate++) - LIST_INSERT_HEAD(&sc->sc_free_ate, ate, xa_nxt); + LIST_INIT(&xb->xb_free_ate); + LIST_INIT(&xb->xb_used_ate); + for (ate = xb->xb_ate; ate != xb->xb_ate + xb->xb_atecnt; ate++) + LIST_INSERT_HEAD(&xb->xb_free_ate, ate, xa_nxt); /* * Switch to 16KB pages. */ - ctrl = bus_space_read_4(sc->sc_iot, sc->sc_regh, WIDGET_CONTROL); - bus_space_write_4(sc->sc_iot, sc->sc_regh, WIDGET_CONTROL, + ctrl = xbridge_read_reg(xb, WIDGET_CONTROL); + xbridge_write_reg(xb, WIDGET_CONTROL, ctrl | BRIDGE_WIDGET_CONTROL_LARGE_PAGES); - (void)bus_space_read_4(sc->sc_iot, sc->sc_regh, WIDGET_TFLUSH); + (void)xbridge_read_reg(xb, WIDGET_TFLUSH); /* * Initialize all ATE entries to invalid. */ - for (a = 0; a < sc->sc_atecnt; a++) - xbridge_ate_write(sc, a, ATE_NV); + for (a = 0; a < xb->xb_atecnt; a++) + xbridge_ate_write(xb, a, ATE_NV); } #ifdef unused uint64_t -xbridge_ate_read(struct xbridge_softc *sc, uint a) +xbridge_ate_read(struct xbridge_bus *xb, uint a) { uint32_t lo, hi; uint64_t ate; @@ -1355,13 +1510,11 @@ xbridge_ate_read(struct xbridge_softc *sc, uint a) /* * ATE can not be read as a whole, and need two 32 bit accesses. */ - hi = bus_space_read_4(sc->sc_iot, sc->sc_regh, BRIDGE_ATE(a) + 4); - if (ISSET(sc->sc_flags, XBRIDGE_FLAGS_XBRIDGE)) - lo = bus_space_read_4(sc->sc_iot, sc->sc_regh, - BRIDGE_ATE(a + 1024) + 4); + hi = xbridge_read_reg(xb, BRIDGE_ATE(a) + 4); + if (ISSET(xb->xb_flags, XF_XBRIDGE)) + lo = xbridge_read_reg(xb, BRIDGE_ATE(a + 1024) + 4); else - lo = bus_space_read_4(sc->sc_iot, sc->sc_regh, - BRIDGE_ATE(a + 512) + 4); + lo = xbridge_read_reg(xb, BRIDGE_ATE(a + 512) + 4); ate = (uint64_t)hi; ate <<= 32; @@ -1372,13 +1525,13 @@ xbridge_ate_read(struct xbridge_softc *sc, uint a) #endif void -xbridge_ate_write(struct xbridge_softc *sc, uint a, uint64_t ate) +xbridge_ate_write(struct xbridge_bus *xb, uint a, uint64_t ate) { - bus_space_write_8(sc->sc_iot, sc->sc_regh, BRIDGE_ATE(a), ate); + widget_write_8(xb->xb_regt, xb->xb_regh, BRIDGE_ATE(a), ate); } uint -xbridge_ate_find(struct xbridge_softc *sc, paddr_t pa) +xbridge_ate_find(struct xbridge_bus *xb, paddr_t pa) { uint a; struct xbridge_ate *ate; @@ -1391,9 +1544,9 @@ xbridge_ate_find(struct xbridge_softc *sc, paddr_t pa) * XXX that stupid linear search. On the other hand there * XXX aren't many ATE entries. */ - LIST_FOREACH(ate, &sc->sc_used_ate, xa_nxt) + LIST_FOREACH(ate, &xb->xb_used_ate, xa_nxt) if (ate->xa_pa == pa) { - a = ate - sc->sc_ate; + a = ate - xb->xb_ate; #ifdef ATE_DEBUG printf("%s: pa %p ate %u (r %u)\n", __func__, pa, a, ate->xa_refcnt); @@ -1405,7 +1558,7 @@ xbridge_ate_find(struct xbridge_softc *sc, paddr_t pa) } uint -xbridge_ate_add(struct xbridge_softc *sc, paddr_t pa) +xbridge_ate_add(struct xbridge_bus *xb, paddr_t pa) { uint a; struct xbridge_ate *ate; @@ -1413,49 +1566,49 @@ xbridge_ate_add(struct xbridge_softc *sc, paddr_t pa) /* round to ATE page */ pa &= ~BRIDGE_ATE_LMASK; - if (LIST_EMPTY(&sc->sc_free_ate)) { + if (LIST_EMPTY(&xb->xb_free_ate)) { #ifdef ATE_DEBUG - printf("%s: out of ATEs\n", sc->sc_dev.dv_xname); + printf("%s: out of ATEs\n", DEVNAME(xb)); #endif return (uint)-1; } - ate = LIST_FIRST(&sc->sc_free_ate); + ate = LIST_FIRST(&xb->xb_free_ate); LIST_REMOVE(ate, xa_nxt); - LIST_INSERT_HEAD(&sc->sc_used_ate, ate, xa_nxt); + LIST_INSERT_HEAD(&xb->xb_used_ate, ate, xa_nxt); ate->xa_refcnt = 1; ate->xa_pa = pa; - a = ate - sc->sc_ate; + a = ate - xb->xb_ate; #ifdef ATE_DEBUG printf("%s: pa %p ate %u\n", __func__, pa, a); #endif - xbridge_ate_write(sc, a, ate->xa_pa | + xbridge_ate_write(xb, a, ate->xa_pa | (xbow_intr_widget << ATE_WIDGET_SHIFT) | ATE_COH | ATE_V); return a; } void -xbridge_ate_unref(struct xbridge_softc *sc, uint a, uint ref) +xbridge_ate_unref(struct xbridge_bus *xb, uint a, uint ref) { struct xbridge_ate *ate; - ate = sc->sc_ate + a; + ate = xb->xb_ate + a; #ifdef DIAGNOSTIC if (ref > ate->xa_refcnt) panic("%s: ate #%u %p has only %u refs but needs to drop %u", - sc->sc_dev.dv_xname, a, ate, ate->xa_refcnt, ref); + DEVNAME(xb), a, ate, ate->xa_refcnt, ref); #endif ate->xa_refcnt -= ref; if (ate->xa_refcnt == 0) { #ifdef ATE_DEBUG printf("%s: free ate %u\n", __func__, a); #endif - xbridge_ate_write(sc, a, ATE_NV); + xbridge_ate_write(xb, a, ATE_NV); LIST_REMOVE(ate, xa_nxt); - LIST_INSERT_HEAD(&sc->sc_free_ate, ate, xa_nxt); + LIST_INSERT_HEAD(&xb->xb_free_ate, ate, xa_nxt); } else { #ifdef ATE_DEBUG printf("%s: unref ate %u (r %u)\n", __func__, a, ate->xa_refcnt); @@ -1468,7 +1621,7 @@ xbridge_ate_unref(struct xbridge_softc *sc, uint a, uint ref) * using an ATE. */ int -xbridge_address_map(struct xbridge_softc *sc, paddr_t pa, bus_addr_t *mapping, +xbridge_address_map(struct xbridge_bus *xb, paddr_t pa, bus_addr_t *mapping, bus_addr_t *limit) { struct xbridge_ate *ate; @@ -1498,14 +1651,14 @@ xbridge_address_map(struct xbridge_softc *sc, paddr_t pa, bus_addr_t *mapping, * allocate a new one. */ - mtx_enter(&sc->sc_atemtx); + mtx_enter(&xb->xb_atemtx); - a = xbridge_ate_find(sc, pa); + a = xbridge_ate_find(xb, pa); if (a != (uint)-1) { - ate = sc->sc_ate + a; + ate = xb->xb_ate + a; ate->xa_refcnt++; } else - a = xbridge_ate_add(sc, pa); + a = xbridge_ate_add(xb, pa); if (a != (uint)-1) { ba = ATE_ADDRESS(a, BRIDGE_ATE_LSHIFT); @@ -1514,23 +1667,23 @@ xbridge_address_map(struct xbridge_softc *sc, paddr_t pa, bus_addr_t *mapping, * this setting is device-global and is enforced by * BRIDGE_DEVICE_SWAP_PMU set in the devio register. */ - if (ISSET(sc->sc_flags, XBRIDGE_FLAGS_XBRIDGE)) + if (ISSET(xb->xb_flags, XF_XBRIDGE)) ba |= XBRIDGE_DMA_TRANSLATED_SWAP; #ifdef ATE_DEBUG printf("%s: ate %u through %p\n", __func__, a, ba); #endif *mapping = ba + (pa & BRIDGE_ATE_LMASK); *limit = ba + BRIDGE_ATE_LSIZE; - mtx_leave(&sc->sc_atemtx); + mtx_leave(&xb->xb_atemtx); return 0; } - printf("%s: out of ATE\n", sc->sc_dev.dv_xname); + printf("%s: out of ATE\n", DEVNAME(xb)); #ifdef ATE_DEBUG - xbridge_ate_dump(sc); + xbridge_ate_dump(xb); #endif - mtx_leave(&sc->sc_atemtx); + mtx_leave(&xb->xb_atemtx); /* * We could try allocating a bounce buffer here. @@ -1541,7 +1694,7 @@ xbridge_address_map(struct xbridge_softc *sc, paddr_t pa, bus_addr_t *mapping, } void -xbridge_address_unmap(struct xbridge_softc *sc, bus_addr_t ba, bus_size_t len) +xbridge_address_unmap(struct xbridge_bus *xb, bus_addr_t ba, bus_size_t len) { uint a; uint refs; @@ -1558,9 +1711,9 @@ xbridge_address_unmap(struct xbridge_softc *sc, bus_addr_t ba, bus_size_t len) a = ATE_INDEX(ba, BRIDGE_ATE_LSHIFT); #ifdef DIAGNOSTIC - if (a >= sc->sc_atecnt) + if (a >= xb->xb_atecnt) panic("%s: bus address %p references nonexisting ATE %u/%u", - __func__, ba, a, sc->sc_atecnt); + __func__, ba, a, xb->xb_atecnt); #endif /* @@ -1571,9 +1724,9 @@ xbridge_address_unmap(struct xbridge_softc *sc, bus_addr_t ba, bus_size_t len) */ refs = 1 + atop(ba + len - 1) - atop(ba); - mtx_enter(&sc->sc_atemtx); - xbridge_ate_unref(sc, a, refs); - mtx_leave(&sc->sc_atemtx); + mtx_enter(&xb->xb_atemtx); + xbridge_ate_unref(xb, a, refs); + mtx_leave(&xb->xb_atemtx); } /* @@ -1584,7 +1737,7 @@ xbridge_dmamap_load_buffer(bus_dma_tag_t t, bus_dmamap_t map, void *buf, bus_size_t buflen, struct proc *p, int flags, paddr_t *lastaddrp, int *segp, int first) { - struct xbridge_softc *sc = t->_cookie; + struct xbridge_bus *xb = t->_cookie; bus_size_t sgsize; bus_addr_t lastaddr, baddr, bmask; bus_addr_t busaddr, endaddr; @@ -1621,7 +1774,7 @@ xbridge_dmamap_load_buffer(bus_dma_tag_t t, bus_dmamap_t map, void *buf, * Compute the DMA address and the physical range * this mapping can cover. */ - if (xbridge_address_map(sc, pa, &busaddr, &endaddr) != 0) { + if (xbridge_address_map(xb, pa, &busaddr, &endaddr) != 0) { rc = ENOMEM; goto fail_unmap; } @@ -1664,7 +1817,7 @@ xbridge_dmamap_load_buffer(bus_dma_tag_t t, bus_dmamap_t map, void *buf, else { if (++seg >= map->_dm_segcnt) { /* drop partial ATE reference */ - xbridge_address_unmap(sc, busaddr, + xbridge_address_unmap(xb, busaddr, sgsize); break; } @@ -1699,7 +1852,7 @@ fail_unmap: * If control goes there, we need to unref all our ATE, if any. */ for (seg = 0; seg < map->_dm_segcnt; seg++) { - xbridge_address_unmap(sc, map->dm_segs[seg].ds_addr, + xbridge_address_unmap(xb, map->dm_segs[seg].ds_addr, map->dm_segs[seg].ds_len); map->dm_segs[seg].ds_addr = 0; } @@ -1713,11 +1866,11 @@ fail_unmap: void xbridge_dmamap_unload(bus_dma_tag_t t, bus_dmamap_t map) { - struct xbridge_softc *sc = t->_cookie; + struct xbridge_bus *xb = t->_cookie; int seg; for (seg = 0; seg < map->_dm_segcnt; seg++) { - xbridge_address_unmap(sc, map->dm_segs[seg].ds_addr, + xbridge_address_unmap(xb, map->dm_segs[seg].ds_addr, map->dm_segs[seg].ds_len); map->dm_segs[seg].ds_addr = 0; } @@ -1798,7 +1951,7 @@ xbridge_device_to_pa(bus_addr_t addr) */ void -xbridge_setup(struct xbridge_softc *sc) +xbridge_setup(struct xbridge_bus *xb) { paddr_t pa; uint32_t ctrl; @@ -1810,11 +1963,11 @@ xbridge_setup(struct xbridge_softc *sc) * to be able to check quickly whether a given device is an IOC3. */ - for (dev = 0; dev < BRIDGE_NSLOTS; dev++) { - pa = sc->sc_regh + BRIDGE_PCI_CFG_SPACE + + for (dev = 0; dev < xb->xb_nslots; dev++) { + pa = xb->xb_regh + BRIDGE_PCI_CFG_SPACE + (dev << 12) + PCI_ID_REG; - if (guarded_read_4(pa, &sc->sc_devices[dev].id) != 0) - sc->sc_devices[dev].id = + if (guarded_read_4(pa, &xb->xb_devices[dev].id) != 0) + xb->xb_devices[dev].id = PCI_ID_CODE(PCI_VENDOR_INVALID, 0xffff); } @@ -1824,11 +1977,10 @@ xbridge_setup(struct xbridge_softc *sc) */ if (sys_config.system_type == SGI_OCTANE) - bus_space_write_4(sc->sc_iot, sc->sc_regh, BRIDGE_DIR_MAP, - (xbow_intr_widget << BRIDGE_DIRMAP_WIDGET_SHIFT) | - BRIDGE_DIRMAP_ADD_512MB); + xbridge_write_reg(xb, BRIDGE_DIR_MAP, BRIDGE_DIRMAP_ADD_512MB | + (xbow_intr_widget << BRIDGE_DIRMAP_WIDGET_SHIFT)); else - bus_space_write_4(sc->sc_iot, sc->sc_regh, BRIDGE_DIR_MAP, + xbridge_write_reg(xb, BRIDGE_DIR_MAP, xbow_intr_widget << BRIDGE_DIRMAP_WIDGET_SHIFT); /* @@ -1836,14 +1988,14 @@ xbridge_setup(struct xbridge_softc *sc) * setup our ATE management code. */ - xbridge_ate_setup(sc); + xbridge_ate_setup(xb); /* * Allocate RRB for the existing devices. */ - xbridge_rrb_setup(sc, 0); - xbridge_rrb_setup(sc, 1); + xbridge_rrb_setup(xb, 0); + xbridge_rrb_setup(xb, 1); /* * Disable byteswapping on PIO accesses through the large window @@ -1852,42 +2004,42 @@ xbridge_setup(struct xbridge_softc *sc) * but better enforce this anyway. */ - ctrl = bus_space_read_4(sc->sc_iot, sc->sc_regh, WIDGET_CONTROL); + ctrl = xbridge_read_reg(xb, WIDGET_CONTROL); ctrl &= ~BRIDGE_WIDGET_CONTROL_IO_SWAP; ctrl &= ~BRIDGE_WIDGET_CONTROL_MEM_SWAP; - bus_space_write_4(sc->sc_iot, sc->sc_regh, WIDGET_CONTROL, ctrl); - (void)bus_space_read_4(sc->sc_iot, sc->sc_regh, WIDGET_TFLUSH); + xbridge_write_reg(xb, WIDGET_CONTROL, ctrl); + (void)xbridge_read_reg(xb, WIDGET_TFLUSH); /* * The PROM will only configure the onboard devices. Set up * any other device we might encounter. */ - xbridge_resource_setup(sc); + xbridge_resource_setup(xb); /* * Setup interrupt handling. */ - bus_space_write_4(sc->sc_iot, sc->sc_regh, BRIDGE_IER, 0); - bus_space_write_4(sc->sc_iot, sc->sc_regh, BRIDGE_INT_MODE, 0); - bus_space_write_4(sc->sc_iot, sc->sc_regh, BRIDGE_INT_DEV, 0); + xbridge_write_reg(xb, BRIDGE_IER, 0); + xbridge_write_reg(xb, BRIDGE_INT_MODE, 0); + xbridge_write_reg(xb, BRIDGE_INT_DEV, 0); - bus_space_write_4(sc->sc_iot, sc->sc_regh, WIDGET_INTDEST_ADDR_UPPER, + xbridge_write_reg(xb, WIDGET_INTDEST_ADDR_UPPER, (xbow_intr_widget_register >> 32) | (xbow_intr_widget << 16)); - bus_space_write_4(sc->sc_iot, sc->sc_regh, WIDGET_INTDEST_ADDR_LOWER, + xbridge_write_reg(xb, WIDGET_INTDEST_ADDR_LOWER, (uint32_t)xbow_intr_widget_register); - (void)bus_space_read_4(sc->sc_iot, sc->sc_regh, WIDGET_TFLUSH); + (void)xbridge_read_reg(xb, WIDGET_TFLUSH); } /* * Build a not-so-pessimistic RRB allocation register value. */ void -xbridge_rrb_setup(struct xbridge_softc *sc, int odd) +xbridge_rrb_setup(struct xbridge_bus *xb, int odd) { - uint rrb[BRIDGE_NSLOTS / 2]; /* tentative rrb assignment */ + uint rrb[MAX_SLOTS / 2]; /* tentative rrb assignment */ uint total; /* rrb count */ uint32_t proto; /* proto rrb value */ int dev, i, j; @@ -1897,9 +2049,10 @@ xbridge_rrb_setup(struct xbridge_softc *sc, int odd) */ total = 0; - for (i = 0; i < BRIDGE_NSLOTS / 2; i++) { + for (i = 0; i < nitems(rrb); i++) { dev = (i << 1) + !!odd; - if (PCI_VENDOR(sc->sc_devices[dev].id) == PCI_VENDOR_INVALID) + if (dev >= xb->xb_nslots || + PCI_VENDOR(xb->xb_devices[dev].id) == PCI_VENDOR_INVALID) rrb[i] = 0; else rrb[i] = 4; /* optimistic value */ @@ -1916,7 +2069,7 @@ xbridge_rrb_setup(struct xbridge_softc *sc, int odd) * All devices should be able to live with 3 RRBs, so * reduce their allocation from 4 to 3. */ - for (i = 0; i < BRIDGE_NSLOTS / 2; i++) { + for (i = 0; i < nitems(rrb); i++) { if (rrb[i] == 4) { rrb[i]--; if (--total == 8) @@ -1931,10 +2084,10 @@ xbridge_rrb_setup(struct xbridge_softc *sc, int odd) * be possible. Attempt to reduce from 3 to 2, except * for isp(4) devices. */ - for (i = 0; i < BRIDGE_NSLOTS / 2; i++) { + for (i = 0; i < nitems(rrb); i++) { if (rrb[i] == 3) { dev = (i << 1) + !!odd; - if (PCI_VENDOR(sc->sc_devices[dev].id) != + if (PCI_VENDOR(xb->xb_devices[dev].id) != PCI_VENDOR_QLOGIC) { rrb[i]--; if (--total == 8) @@ -1950,7 +2103,7 @@ xbridge_rrb_setup(struct xbridge_softc *sc, int odd) * isp devices too. We'll try to favour the lowest * slots, though, hence the reversed loop order. */ - for (i = BRIDGE_NSLOTS / 2 - 1; i >= 0; i--) { + for (i = nitems(rrb) - 1; i >= 0; i--) { if (rrb[i] == 3) { rrb[i]--; if (--total == 8) @@ -1964,22 +2117,21 @@ xbridge_rrb_setup(struct xbridge_softc *sc, int odd) */ proto = 0; - for (i = 0; i < BRIDGE_NSLOTS / 2; i++) { + for (i = 0; i < nitems(rrb); i++) { for (j = 0; j < rrb[i]; j++) proto = (proto << RRB_SHIFT) | (RRB_VALID | i); } - bus_space_write_4(sc->sc_iot, sc->sc_regh, - odd ? BRIDGE_RRB_ODD : BRIDGE_RRB_EVEN, proto); + xbridge_write_reg(xb, odd ? BRIDGE_RRB_ODD : BRIDGE_RRB_EVEN, proto); } /* * Configure PCI resources for all devices. */ void -xbridge_resource_setup(struct xbridge_softc *sc) +xbridge_resource_setup(struct xbridge_bus *xb) { - pci_chipset_tag_t pc = &sc->sc_pc; + pci_chipset_tag_t pc = &xb->xb_pc; int dev, nfuncs; pcitag_t tag; pcireg_t id, bhlcr; @@ -1989,17 +2141,6 @@ xbridge_resource_setup(struct xbridge_softc *sc) const struct pci_quirkdata *qd; /* - * Figure out where the devio mappings will go. - * On Octane, they are relative to the start of the widget. - * On Origin, they are computed from the widget number. - */ - - if (sys_config.system_type == SGI_OCTANE) - sc->sc_devio_skew = 0; - else - sc->sc_devio_skew = sc->sc_widget; - - /* * On Octane, we will want to map everything through the large * windows, whenever possible. * @@ -2007,8 +2148,8 @@ xbridge_resource_setup(struct xbridge_softc *sc) */ if (sys_config.system_type == SGI_OCTANE) { - sc->sc_ioex = xbridge_mapping_setup(sc, 1); - sc->sc_memex = xbridge_mapping_setup(sc, 0); + xb->xb_ioex = xbridge_mapping_setup(xb, 1); + xb->xb_memex = xbridge_mapping_setup(xb, 0); } /* @@ -2016,8 +2157,8 @@ xbridge_resource_setup(struct xbridge_softc *sc) */ nppb = npccbb = 0; - for (dev = 0; dev < BRIDGE_NSLOTS; dev++) { - id = sc->sc_devices[dev].id; + for (dev = 0; dev < xb->xb_nslots; dev++) { + id = xb->xb_devices[dev].id; if (PCI_VENDOR(id) == PCI_VENDOR_INVALID || PCI_VENDOR(id) == 0) continue; @@ -2050,15 +2191,14 @@ xbridge_resource_setup(struct xbridge_softc *sc) * we'll need to perform proper PCI resource allocation. */ - devio = bus_space_read_4(sc->sc_iot, sc->sc_regh, - BRIDGE_DEVICE(dev)); + devio = xbridge_read_reg(xb, BRIDGE_DEVICE(dev)); #ifdef DEBUG printf("device %d: devio %08x\n", dev, devio); #endif if (id != PCI_ID_CODE(PCI_VENDOR_SGI, PCI_PRODUCT_SGI_IOC3)) need_setup = 1; else - need_setup = sc->sc_devio_skew != + need_setup = xb->xb_devio_skew != ((devio & BRIDGE_DEVICE_BASE_MASK) >> (24 - BRIDGE_DEVICE_BASE_SHIFT)); @@ -2066,7 +2206,7 @@ xbridge_resource_setup(struct xbridge_softc *sc) * Enable byte swapping for DMA, except on IOC3 and * RAD1 devices. */ - if (ISSET(sc->sc_flags, XBRIDGE_FLAGS_XBRIDGE)) + if (ISSET(xb->xb_flags, XF_XBRIDGE)) devio &= ~BRIDGE_DEVICE_SWAP_PMU; else devio |= BRIDGE_DEVICE_SWAP_PMU; @@ -2089,7 +2229,7 @@ xbridge_resource_setup(struct xbridge_softc *sc) devio |= BRIDGE_DEVICE_COHERENT; if (need_setup == 0) { - xbridge_set_devio(sc, dev, devio); + xbridge_set_devio(xb, dev, devio); continue; } @@ -2098,7 +2238,7 @@ xbridge_resource_setup(struct xbridge_softc *sc) */ devio &= ~BRIDGE_DEVICE_BASE_MASK; devio &= ~BRIDGE_DEVICE_IO_MEM; - xbridge_set_devio(sc, dev, devio); + xbridge_set_devio(xb, dev, devio); /* * We now need to perform the resource allocation for this @@ -2112,7 +2252,7 @@ xbridge_resource_setup(struct xbridge_softc *sc) else nfuncs = 1; - xbridge_device_setup(sc, dev, nfuncs, devio); + xbridge_device_setup(xb, dev, nfuncs, devio); } /* @@ -2127,16 +2267,16 @@ xbridge_resource_setup(struct xbridge_softc *sc) * If there are PCI-CardBus bridges, we really want to be * able to have large resource spaces... */ - if (sc->sc_ioex == NULL) - sc->sc_ioex = xbridge_mapping_setup(sc, 1); - if (sc->sc_memex == NULL) - sc->sc_memex = xbridge_mapping_setup(sc, 0); + if (xb->xb_ioex == NULL) + xb->xb_ioex = xbridge_mapping_setup(xb, 1); + if (xb->xb_memex == NULL) + xb->xb_memex = xbridge_mapping_setup(xb, 0); } secondary = 1; ppbstride = nppb == 0 ? 0 : (255 - npccbb) / nppb; - for (dev = 0; dev < BRIDGE_NSLOTS; dev++) { - id = sc->sc_devices[dev].id; + for (dev = 0; dev < xb->xb_nslots; dev++) { + id = xb->xb_devices[dev].id; if (PCI_VENDOR(id) == PCI_VENDOR_INVALID || PCI_VENDOR(id) == 0) continue; @@ -2162,13 +2302,13 @@ xbridge_resource_setup(struct xbridge_softc *sc) } } - if (sc->sc_ioex != NULL) { - extent_destroy(sc->sc_ioex); - sc->sc_ioex = NULL; + if (xb->xb_ioex != NULL) { + extent_destroy(xb->xb_ioex); + xb->xb_ioex = NULL; } - if (sc->sc_memex != NULL) { - extent_destroy(sc->sc_memex); - sc->sc_memex = NULL; + if (xb->xb_memex != NULL) { + extent_destroy(xb->xb_memex); + xb->xb_memex = NULL; } } @@ -2178,23 +2318,23 @@ xbridge_resource_setup(struct xbridge_softc *sc) * views, if applicable. */ void -xbridge_extent_setup(struct xbridge_softc *sc) +xbridge_extent_setup(struct xbridge_bus *xb) { int dev; int errors; bus_addr_t start, end; uint32_t devio; - snprintf(sc->sc_ioexname, sizeof(sc->sc_ioexname), "%s_io", - sc->sc_dev.dv_xname); - sc->sc_ioex = extent_create(sc->sc_ioexname, 0, 0xffffffff, + snprintf(xb->xb_ioexname, sizeof(xb->xb_ioexname), "%s_io", + DEVNAME(xb)); + xb->xb_ioex = extent_create(xb->xb_ioexname, 0, 0xffffffff, M_DEVBUF, NULL, 0, EX_NOWAIT | EX_FILLED); - if (sc->sc_ioex != NULL) { + if (xb->xb_ioex != NULL) { errors = 0; /* make all configured devio ranges available... */ - for (dev = 0; dev < BRIDGE_NSLOTS; dev++) { - devio = sc->sc_devices[dev].devio; + for (dev = 0; dev < xb->xb_nslots; dev++) { + devio = xb->xb_devices[dev].devio; if (devio == 0) continue; if (ISSET(devio, BRIDGE_DEVICE_IO_MEM)) @@ -2203,89 +2343,89 @@ xbridge_extent_setup(struct xbridge_softc *sc) BRIDGE_DEVICE_BASE_SHIFT; if (start == 0) continue; - if (extent_free(sc->sc_ioex, start, + if (extent_free(xb->xb_ioex, start, BRIDGE_DEVIO_SIZE(dev), EX_NOWAIT) != 0) { errors++; break; } } /* ...as well as the large views, if any */ - if (sc->sc_ioend != 0) { - start = sc->sc_iostart; + if (xb->xb_ioend != 0) { + start = xb->xb_iostart; if (start == 0) start = 1; - end = sc->sc_devio_skew << 24; + end = xb->xb_devio_skew << 24; if (start < end) - if (extent_free(sc->sc_ioex, start, + if (extent_free(xb->xb_ioex, start, end, EX_NOWAIT) != 0) errors++; - start = (sc->sc_devio_skew + 1) << 24; - if (start < sc->sc_iostart) - start = sc->sc_iostart; - if (extent_free(sc->sc_ioex, start, - sc->sc_ioend + 1 - start, EX_NOWAIT) != 0) + start = (xb->xb_devio_skew + 1) << 24; + if (start < xb->xb_iostart) + start = xb->xb_iostart; + if (extent_free(xb->xb_ioex, start, + xb->xb_ioend + 1 - start, EX_NOWAIT) != 0) errors++; } if (errors != 0) { - extent_destroy(sc->sc_ioex); - sc->sc_ioex = NULL; + extent_destroy(xb->xb_ioex); + xb->xb_ioex = NULL; } } - snprintf(sc->sc_memexname, sizeof(sc->sc_memexname), "%s_mem", - sc->sc_dev.dv_xname); - sc->sc_memex = extent_create(sc->sc_memexname, 0, 0xffffffff, + snprintf(xb->xb_memexname, sizeof(xb->xb_memexname), "%s_mem", + DEVNAME(xb)); + xb->xb_memex = extent_create(xb->xb_memexname, 0, 0xffffffff, M_DEVBUF, NULL, 0, EX_NOWAIT | EX_FILLED); - if (sc->sc_memex != NULL) { + if (xb->xb_memex != NULL) { errors = 0; /* make all configured devio ranges available... */ - for (dev = 0; dev < BRIDGE_NSLOTS; dev++) { - devio = sc->sc_devices[dev].devio; + for (dev = 0; dev < xb->xb_nslots; dev++) { + devio = xb->xb_devices[dev].devio; if (devio == 0 || !ISSET(devio, BRIDGE_DEVICE_IO_MEM)) continue; start = (devio & BRIDGE_DEVICE_BASE_MASK) << BRIDGE_DEVICE_BASE_SHIFT; if (start == 0) continue; - if (extent_free(sc->sc_memex, start, + if (extent_free(xb->xb_memex, start, BRIDGE_DEVIO_SIZE(dev), EX_NOWAIT) != 0) { errors++; break; } } /* ...as well as the large views, if any */ - if (sc->sc_memend != 0) { - start = sc->sc_memstart; + if (xb->xb_memend != 0) { + start = xb->xb_memstart; if (start == 0) start = 1; - end = sc->sc_devio_skew << 24; + end = xb->xb_devio_skew << 24; if (start < end) - if (extent_free(sc->sc_memex, start, + if (extent_free(xb->xb_memex, start, end, EX_NOWAIT) != 0) errors++; - start = (sc->sc_devio_skew + 1) << 24; - if (start < sc->sc_memstart) - start = sc->sc_memstart; - if (extent_free(sc->sc_memex, start, - sc->sc_memend + 1 - start, EX_NOWAIT) != 0) + start = (xb->xb_devio_skew + 1) << 24; + if (start < xb->xb_memstart) + start = xb->xb_memstart; + if (extent_free(xb->xb_memex, start, + xb->xb_memend + 1 - start, EX_NOWAIT) != 0) errors++; } if (errors != 0) { - extent_destroy(sc->sc_memex); - sc->sc_memex = NULL; + extent_destroy(xb->xb_memex); + xb->xb_memex = NULL; } } } struct extent * -xbridge_mapping_setup(struct xbridge_softc *sc, int io) +xbridge_mapping_setup(struct xbridge_bus *xb, int io) { - bus_addr_t offs; + bus_addr_t membase, offs; bus_size_t len; paddr_t base; u_long start, end; @@ -2299,11 +2439,11 @@ xbridge_mapping_setup(struct xbridge_softc *sc, int io) * didn't work was the byteswap logic). */ - if (!ISSET(sc->sc_flags, XBRIDGE_FLAGS_NO_DIRECT_IO)) { + if (!ISSET(xb->xb_flags, XF_NO_DIRECT_IO)) { offs = BRIDGE_PCI_IO_SPACE_BASE; len = BRIDGE_PCI_IO_SPACE_LENGTH; - base = xbow_widget_map_space(sc->sc_dev.dv_parent, - sc->sc_widget, &offs, &len); + base = xbow_widget_map_space(xb->xb_sc->sc_dev.dv_parent, + xb->xb_widget, &offs, &len); } else base = 0; @@ -2324,26 +2464,28 @@ xbridge_mapping_setup(struct xbridge_softc *sc, int io) M_DEVBUF, NULL, 0, EX_NOWAIT); if (ex != NULL) { - sc->sc_io_bus_space->bus_base = base - offs; - sc->sc_io_bus_space->_space_map = + xb->xb_io_bus_space->bus_base = base - offs; + xb->xb_io_bus_space->_space_map = xbridge_space_map_io; - sc->sc_io_bus_space->_space_subregion = + xb->xb_io_bus_space->_space_subregion = xbridge_space_region_io; - sc->sc_iostart = offs; - sc->sc_ioend = offs + len - 1; + xb->xb_iostart = offs; + xb->xb_ioend = offs + len - 1; } } } else { /* * Memory mappings are available in the widget at offset - * BRIDGE_PCI_MEM_SPACE_BASE onwards. + * BRIDGE_PCI#_MEM_SPACE_BASE onwards. */ - offs = BRIDGE_PCI_MEM_SPACE_BASE; + membase = xb->xb_busno == 0 ? BRIDGE_PCI0_MEM_SPACE_BASE : + BRIDGE_PCI1_MEM_SPACE_BASE; + offs = membase; len = BRIDGE_PCI_MEM_SPACE_LENGTH; - base = xbow_widget_map_space(sc->sc_dev.dv_parent, - sc->sc_widget, &offs, &len); + base = xbow_widget_map_space(xb->xb_sc->sc_dev.dv_parent, + xb->xb_widget, &offs, &len); if (base != 0) { /* @@ -2351,30 +2493,29 @@ xbridge_mapping_setup(struct xbridge_softc *sc, int io) * by the hardware, thus restricting memory mappings * to 1GB. */ - if (offs + len > BRIDGE_PCI_MEM_SPACE_BASE + - BRIDGE_PCI_MEM_SPACE_LENGTH) - len = BRIDGE_PCI_MEM_SPACE_BASE + - BRIDGE_PCI_MEM_SPACE_LENGTH - offs; + if (offs + len > membase + BRIDGE_PCI_MEM_SPACE_LENGTH) + len = membase + BRIDGE_PCI_MEM_SPACE_LENGTH - + offs; #ifdef DEBUG printf("direct mem %p-%p base %p\n", offs, offs + len - 1, base); #endif - offs -= BRIDGE_PCI_MEM_SPACE_BASE; + offs -= membase; ex = extent_create("xbridge_direct_mem", offs == 0 ? 1 : offs, offs + len - 1, M_DEVBUF, NULL, 0, EX_NOWAIT); if (ex != NULL) { - sc->sc_mem_bus_space->bus_base = base - offs; - sc->sc_mem_bus_space->_space_map = + xb->xb_mem_bus_space->bus_base = base - offs; + xb->xb_mem_bus_space->_space_map = xbridge_space_map_mem; - sc->sc_mem_bus_space->_space_subregion = + xb->xb_mem_bus_space->_space_subregion = xbridge_space_region_mem; - sc->sc_memstart = offs; - sc->sc_memend = offs + len - 1; + xb->xb_memstart = offs; + xb->xb_memend = offs + len - 1; } } } @@ -2387,8 +2528,8 @@ xbridge_mapping_setup(struct xbridge_softc *sc, int io) * Note that xbow_widget_map_space() may have returned * a range in which the devio area does not appear. */ - start = sc->sc_devio_skew << 24; - end = (sc->sc_devio_skew + 1) << 24; + start = xb->xb_devio_skew << 24; + end = (xb->xb_devio_skew + 1) << 24; if (end >= ex->ex_start && start <= ex->ex_end) { if (start < ex->ex_start) @@ -2399,8 +2540,7 @@ xbridge_mapping_setup(struct xbridge_softc *sc, int io) EX_NOWAIT | EX_MALLOCOK) != 0) { printf("%s: failed to expurge devio range" " from %s large extent\n", - sc->sc_dev.dv_xname, - io ? "i/o" : "mem"); + DEVNAME(xb), io ? "i/o" : "mem"); extent_destroy(ex); ex = NULL; } @@ -2421,10 +2561,10 @@ xbridge_mapping_setup(struct xbridge_softc *sc, int io) #define XR_MEM_OFLOW 0x20 /* can't fit memory in a large devio */ int -xbridge_resource_explore(struct xbridge_softc *sc, pcitag_t tag, +xbridge_resource_explore(struct xbridge_bus *xb, pcitag_t tag, struct extent *ioex, struct extent *memex) { - pci_chipset_tag_t pc = &sc->sc_pc; + pci_chipset_tag_t pc = &xb->xb_pc; pcireg_t bhlc, type, addr, mask; bus_addr_t base; bus_size_t size; @@ -2518,10 +2658,10 @@ xbridge_resource_explore(struct xbridge_softc *sc, pcitag_t tag, } void -xbridge_resource_manage(struct xbridge_softc *sc, pcitag_t tag, +xbridge_resource_manage(struct xbridge_bus *xb, pcitag_t tag, struct extent *ioex, struct extent *memex) { - pci_chipset_tag_t pc = &sc->sc_pc; + pci_chipset_tag_t pc = &xb->xb_pc; pcireg_t bhlc, type, mask; bus_addr_t base; bus_size_t size; @@ -2631,14 +2771,14 @@ xbridge_resource_manage(struct xbridge_softc *sc, pcitag_t tag, } void -xbridge_device_setup(struct xbridge_softc *sc, int dev, int nfuncs, +xbridge_device_setup(struct xbridge_bus *xb, int dev, int nfuncs, uint32_t devio) { - pci_chipset_tag_t pc = &sc->sc_pc; + pci_chipset_tag_t pc = &xb->xb_pc; int function; pcitag_t tag; pcireg_t id, csr; - uint32_t basewin; + uint32_t baseio; int resources; int io_devio, mem_devio; struct extent *ioex, *memex; @@ -2656,13 +2796,13 @@ xbridge_device_setup(struct xbridge_softc *sc, int dev, int nfuncs, * This can fail; in that case we'll try to use a large mapping * whenever possible, or silently fail to configure the device. */ - if (sc->sc_ioex != NULL) + if (xb->xb_ioex != NULL) ioex = NULL; else ioex = extent_create("xbridge_io", 0, BRIDGE_DEVIO_LARGE - 1, M_DEVBUF, NULL, 0, EX_NOWAIT); - if (sc->sc_memex != NULL) + if (xb->xb_memex != NULL) memex = NULL; else memex = extent_create("xbridge_mem", @@ -2682,7 +2822,7 @@ xbridge_device_setup(struct xbridge_softc *sc, int dev, int nfuncs, pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr & ~(PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE)); - resources |= xbridge_resource_explore(sc, tag, ioex, memex); + resources |= xbridge_resource_explore(xb, tag, ioex, memex); } if (memex != NULL) { @@ -2708,25 +2848,25 @@ xbridge_device_setup(struct xbridge_softc *sc, int dev, int nfuncs, if (ISSET(resources, XR_IO)) { if (!ISSET(resources, XR_IO_OFLOW) && (sys_config.system_type != SGI_OCTANE || - sc->sc_ioex == NULL)) - io_devio = xbridge_allocate_devio(sc, dev, + xb->xb_ioex == NULL)) + io_devio = xbridge_allocate_devio(xb, dev, ISSET(resources, XR_IO_OFLOW_S)); if (io_devio >= 0) { - basewin = (sc->sc_devio_skew << 24) | - BRIDGE_DEVIO_OFFS(io_devio); - xbridge_set_devio(sc, io_devio, devio | - (basewin >> BRIDGE_DEVICE_BASE_SHIFT)); + baseio = (xb->xb_devio_skew << 24) | + PIC_DEVIO_OFFS(xb->xb_busno, io_devio); + xbridge_set_devio(xb, io_devio, devio | + (baseio >> BRIDGE_DEVICE_BASE_SHIFT)); - ioex = extent_create("xbridge_io", basewin, - basewin + BRIDGE_DEVIO_SIZE(io_devio) - 1, + ioex = extent_create("xbridge_io", baseio, + baseio + BRIDGE_DEVIO_SIZE(io_devio) - 1, M_DEVBUF, NULL, 0, EX_NOWAIT); } else { /* * Try to get a large window mapping if we don't * have one already. */ - if (sc->sc_ioex == NULL) - sc->sc_ioex = xbridge_mapping_setup(sc, 1); + if (xb->xb_ioex == NULL) + xb->xb_ioex = xbridge_mapping_setup(xb, 1); } } @@ -2734,25 +2874,25 @@ xbridge_device_setup(struct xbridge_softc *sc, int dev, int nfuncs, if (ISSET(resources, XR_MEM)) { if (!ISSET(resources, XR_MEM_OFLOW) && sys_config.system_type != SGI_OCTANE) - mem_devio = xbridge_allocate_devio(sc, dev, + mem_devio = xbridge_allocate_devio(xb, dev, ISSET(resources, XR_MEM_OFLOW_S)); if (mem_devio >= 0) { - basewin = (sc->sc_devio_skew << 24) | - BRIDGE_DEVIO_OFFS(mem_devio); - xbridge_set_devio(sc, mem_devio, devio | + baseio = (xb->xb_devio_skew << 24) | + PIC_DEVIO_OFFS(xb->xb_busno, mem_devio); + xbridge_set_devio(xb, mem_devio, devio | BRIDGE_DEVICE_IO_MEM | - (basewin >> BRIDGE_DEVICE_BASE_SHIFT)); + (baseio >> BRIDGE_DEVICE_BASE_SHIFT)); - memex = extent_create("xbridge_mem", basewin, - basewin + BRIDGE_DEVIO_SIZE(mem_devio) - 1, + memex = extent_create("xbridge_mem", baseio, + baseio + BRIDGE_DEVIO_SIZE(mem_devio) - 1, M_DEVBUF, NULL, 0, EX_NOWAIT); } else { /* * Try to get a large window mapping if we don't * have one already. */ - if (sc->sc_memex == NULL) - sc->sc_memex = xbridge_mapping_setup(sc, 0); + if (xb->xb_memex == NULL) + xb->xb_memex = xbridge_mapping_setup(xb, 0); } } @@ -2769,9 +2909,9 @@ xbridge_device_setup(struct xbridge_softc *sc, int dev, int nfuncs, PCI_VENDOR(id) == 0) continue; - xbridge_resource_manage(sc, tag, - ioex != NULL ? ioex : sc->sc_ioex, - memex != NULL ? memex : sc->sc_memex); + xbridge_resource_manage(xb, tag, + ioex != NULL ? ioex : xb->xb_ioex, + memex != NULL ? memex : xb->xb_memex); } if (memex != NULL) @@ -2784,15 +2924,15 @@ int xbridge_ppb_setup(void *cookie, pcitag_t tag, bus_addr_t *iostart, bus_addr_t *ioend, bus_addr_t *memstart, bus_addr_t *memend) { - struct xbridge_softc *sc = cookie; - pci_chipset_tag_t pc = &sc->sc_pc; + struct xbridge_bus *xb = cookie; + pci_chipset_tag_t pc = &xb->xb_pc; uint32_t base, devio; bus_size_t exsize; u_long exstart; int dev, devio_idx, tries; pci_decompose_tag(pc, tag, NULL, &dev, NULL); - devio = bus_space_read_4(sc->sc_iot, sc->sc_regh, BRIDGE_DEVICE(dev)); + devio = xbridge_read_reg(xb, BRIDGE_DEVICE(dev)); /* * Since our caller computes resource needs starting at zero, we @@ -2806,33 +2946,33 @@ xbridge_ppb_setup(void *cookie, pcitag_t tag, bus_addr_t *iostart, if (exsize++ != 0) { /* try to allocate through a devio slot whenever possible... */ if (exsize < BRIDGE_DEVIO_SHORT) - devio_idx = xbridge_allocate_devio(sc, dev, 0); + devio_idx = xbridge_allocate_devio(xb, dev, 0); else if (exsize < BRIDGE_DEVIO_LARGE) - devio_idx = xbridge_allocate_devio(sc, dev, 1); + devio_idx = xbridge_allocate_devio(xb, dev, 1); else devio_idx = -1; /* ...if it fails, try the large view.... */ - if (devio_idx < 0 && sc->sc_memex == NULL) - sc->sc_memex = xbridge_mapping_setup(sc, 0); + if (devio_idx < 0 && xb->xb_memex == NULL) + xb->xb_memex = xbridge_mapping_setup(xb, 0); /* ...if it is not available, try to get a devio slot anyway. */ - if (devio_idx < 0 && sc->sc_memex == NULL) { + if (devio_idx < 0 && xb->xb_memex == NULL) { if (exsize > BRIDGE_DEVIO_SHORT) - devio_idx = xbridge_allocate_devio(sc, dev, 1); + devio_idx = xbridge_allocate_devio(xb, dev, 1); if (devio_idx < 0) - devio_idx = xbridge_allocate_devio(sc, dev, 0); + devio_idx = xbridge_allocate_devio(xb, dev, 0); } if (devio_idx >= 0) { - base = (sc->sc_devio_skew << 24) | - BRIDGE_DEVIO_OFFS(devio_idx); - xbridge_set_devio(sc, devio_idx, devio | + base = (xb->xb_devio_skew << 24) | + PIC_DEVIO_OFFS(xb->xb_busno, devio_idx); + xbridge_set_devio(xb, devio_idx, devio | BRIDGE_DEVICE_IO_MEM | (base >> BRIDGE_DEVICE_BASE_SHIFT)); *memstart = base; *memend = base + BRIDGE_DEVIO_SIZE(devio_idx) - 1; - } else if (sc->sc_memex != NULL) { + } else if (xb->xb_memex != NULL) { /* * We know that the direct memory resource range fits * within the 32 bit address space, and is limited to @@ -2842,7 +2982,7 @@ xbridge_ppb_setup(void *cookie, pcitag_t tag, bus_addr_t *iostart, if (exsize < 1UL << 20) exsize = 1UL << 20; for (tries = 0; tries < 5; tries++) { - if (extent_alloc(sc->sc_memex, exsize, + if (extent_alloc(xb->xb_memex, exsize, 1UL << 20, 0, 0, EX_NOWAIT | EX_MALLOCOK, &exstart) == 0) { *memstart = exstart; @@ -2862,32 +3002,32 @@ xbridge_ppb_setup(void *cookie, pcitag_t tag, bus_addr_t *iostart, if (exsize++ != 0) { /* try to allocate through a devio slot whenever possible... */ if (exsize < BRIDGE_DEVIO_SHORT) - devio_idx = xbridge_allocate_devio(sc, dev, 0); + devio_idx = xbridge_allocate_devio(xb, dev, 0); else if (exsize < BRIDGE_DEVIO_LARGE) - devio_idx = xbridge_allocate_devio(sc, dev, 1); + devio_idx = xbridge_allocate_devio(xb, dev, 1); else devio_idx = -1; /* ...if it fails, try the large view.... */ - if (devio_idx < 0 && sc->sc_ioex == NULL) - sc->sc_ioex = xbridge_mapping_setup(sc, 1); + if (devio_idx < 0 && xb->xb_ioex == NULL) + xb->xb_ioex = xbridge_mapping_setup(xb, 1); /* ...if it is not available, try to get a devio slot anyway. */ - if (devio_idx < 0 && sc->sc_ioex == NULL) { + if (devio_idx < 0 && xb->xb_ioex == NULL) { if (exsize > BRIDGE_DEVIO_SHORT) - devio_idx = xbridge_allocate_devio(sc, dev, 1); + devio_idx = xbridge_allocate_devio(xb, dev, 1); if (devio_idx < 0) - devio_idx = xbridge_allocate_devio(sc, dev, 0); + devio_idx = xbridge_allocate_devio(xb, dev, 0); } if (devio_idx >= 0) { - base = (sc->sc_devio_skew << 24) | - BRIDGE_DEVIO_OFFS(devio_idx); - xbridge_set_devio(sc, devio_idx, devio | + base = (xb->xb_devio_skew << 24) | + PIC_DEVIO_OFFS(xb->xb_busno, devio_idx); + xbridge_set_devio(xb, devio_idx, devio | (base >> BRIDGE_DEVICE_BASE_SHIFT)); *iostart = base; *ioend = base + BRIDGE_DEVIO_SIZE(devio_idx) - 1; - } else if (sc->sc_ioex != NULL) { + } else if (xb->xb_ioex != NULL) { /* * We know that the direct I/O resource range fits * within the 32 bit address space, so our allocation, @@ -2896,7 +3036,7 @@ xbridge_ppb_setup(void *cookie, pcitag_t tag, bus_addr_t *iostart, if (exsize < 1UL << 12) exsize = 1UL << 12; for (tries = 0; tries < 5; tries++) { - if (extent_alloc(sc->sc_ioex, exsize, + if (extent_alloc(xb->xb_ioex, exsize, 1UL << 12, 0, 0, EX_NOWAIT | EX_MALLOCOK, &exstart) == 0) { *iostart = exstart; @@ -2978,7 +3118,7 @@ xbridge_rbus_parent_io(struct pci_attach_args *pa) void * xbridge_rbus_parent_mem(struct pci_attach_args *pa) { - struct xbridge_softc *sc = pa->pa_pc->pc_conf_v; + struct xbridge_bus *xb = pa->pa_pc->pc_conf_v; struct extent *ex = pa->pa_memex; bus_addr_t start; rbus_tag_t rb = NULL; @@ -2989,7 +3129,7 @@ xbridge_rbus_parent_mem(struct pci_attach_args *pa) * devio range (for md_space_unmap to work correctly). */ if (ex != NULL) { - start = (sc->sc_devio_skew + 1) << 24; + start = (xb->xb_devio_skew + 1) << 24; if (start < ex->ex_start) start = ex->ex_start; @@ -3015,7 +3155,7 @@ xbridge_rbus_parent_mem(struct pci_attach_args *pa) #endif /* NCARDBUS > 0 */ int -xbridge_allocate_devio(struct xbridge_softc *sc, int dev, int wantlarge) +xbridge_allocate_devio(struct xbridge_bus *xb, int dev, int wantlarge) { pcireg_t id; @@ -3024,7 +3164,7 @@ xbridge_allocate_devio(struct xbridge_softc *sc, int dev, int wantlarge) * use it. */ - if (sc->sc_devices[dev].devio == 0) { + if (xb->xb_devices[dev].devio == 0) { if (BRIDGE_DEVIO_SIZE(dev) >= wantlarge ? BRIDGE_DEVIO_LARGE : BRIDGE_DEVIO_SHORT) return dev; @@ -3035,11 +3175,11 @@ xbridge_allocate_devio(struct xbridge_softc *sc, int dev, int wantlarge) * request. */ - for (dev = 0; dev < BRIDGE_NSLOTS; dev++) { - if (sc->sc_devices[dev].devio != 0) + for (dev = 0; dev < xb->xb_nslots; dev++) { + if (xb->xb_devices[dev].devio != 0) continue; /* devio in use */ - id = sc->sc_devices[dev].id; + id = xb->xb_devices[dev].id; if (PCI_VENDOR(id) != PCI_VENDOR_INVALID && PCI_VENDOR(id) != 0) continue; /* devio to be used soon */ @@ -3052,11 +3192,11 @@ xbridge_allocate_devio(struct xbridge_softc *sc, int dev, int wantlarge) } void -xbridge_set_devio(struct xbridge_softc *sc, int dev, uint32_t devio) +xbridge_set_devio(struct xbridge_bus *xb, int dev, uint32_t devio) { - bus_space_write_4(sc->sc_iot, sc->sc_regh, BRIDGE_DEVICE(dev), devio); - (void)bus_space_read_4(sc->sc_iot, sc->sc_regh, WIDGET_TFLUSH); - sc->sc_devices[dev].devio = devio; + xbridge_write_reg(xb, BRIDGE_DEVICE(dev), devio); + (void)xbridge_read_reg(xb, WIDGET_TFLUSH); + xb->xb_devices[dev].devio = devio; #ifdef DEBUG printf("device %d: new devio %08x\n", dev, devio); #endif diff --git a/sys/arch/sgi/xbow/xbridgereg.h b/sys/arch/sgi/xbow/xbridgereg.h index 7537172842e..7039f126a64 100644 --- a/sys/arch/sgi/xbow/xbridgereg.h +++ b/sys/arch/sgi/xbow/xbridgereg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: xbridgereg.h,v 1.7 2009/07/06 22:46:43 miod Exp $ */ +/* $OpenBSD: xbridgereg.h,v 1.8 2009/08/18 19:31:59 miod Exp $ */ /* * Copyright (c) 2008 Miodrag Vallat. @@ -17,11 +17,21 @@ */ /* - * IP27/IP30 Bridge Registers + * IP27/IP30/IP35 Bridge and XBridge Registers + * IP35 PIC Registers */ #define BRIDGE_REGISTERS_SIZE 0x00030000 +#define BRIDGE_BUS_OFFSET 0x00800000 + +#define BRIDGE_NBUSES 1 +#define PIC_NBUSES 2 +#define MAX_BUSES PIC_NBUSES + #define BRIDGE_NSLOTS 8 +#define PIC_NSLOTS 4 +#define MAX_SLOTS BRIDGE_NSLOTS + #define BRIDGE_NINTRS 8 #define BRIDGE_WIDGET_CONTROL_IO_SWAP 0x00800000 @@ -37,38 +47,39 @@ * bits of the register. */ -#define BRIDGE_DIR_MAP 0x00000084 +#define BRIDGE_DIR_MAP 0x00000080 #define BRIDGE_DIRMAP_WIDGET_SHIFT 20 #define BRIDGE_DIRMAP_ADD_512MB 0x00020000 /* add 512MB */ #define BRIDGE_DIRMAP_BASE_MASK 0x00001fff #define BRIDGE_DIRMAP_BASE_SHIFT 31 -#define BRIDGE_PCI_MEM_SPACE_BASE 0x0000000040000000ULL +#define BRIDGE_PCI0_MEM_SPACE_BASE 0x0000000040000000ULL #define BRIDGE_PCI_MEM_SPACE_LENGTH 0x0000000040000000ULL +#define BRIDGE_PCI1_MEM_SPACE_BASE 0x00000000c0000000ULL #define BRIDGE_PCI_IO_SPACE_BASE 0x0000000100000000ULL #define BRIDGE_PCI_IO_SPACE_LENGTH 0x0000000100000000ULL -#define BRIDGE_NIC 0x000000b4 -#define BRIDGE_BUS_TIMEOUT 0x000000c4 -#define BRIDGE_PCI_CFG 0x000000cc -#define BRIDGE_PCI_ERR_UPPER 0x000000d4 -#define BRIDGE_PCI_ERR_LOWER 0x000000dc +#define BRIDGE_NIC 0x000000b0 +#define BRIDGE_BUS_TIMEOUT 0x000000c0 +#define BRIDGE_PCI_CFG 0x000000c8 +#define BRIDGE_PCI_ERR_UPPER 0x000000d0 +#define BRIDGE_PCI_ERR_LOWER 0x000000d8 /* * Interrupt handling */ -#define BRIDGE_ISR 0x00000104 -#define BRIDGE_IER 0x0000010c -#define BRIDGE_ICR 0x00000114 -#define BRIDGE_INT_MODE 0x0000011c -#define BRIDGE_INT_DEV 0x00000124 -#define BRIDGE_INT_HOST_ERR 0x0000012c -#define BRIDGE_INT_ADDR(d) (0x00000134 + 8 * (d)) +#define BRIDGE_ISR 0x00000100 +#define BRIDGE_IER 0x00000108 +#define BRIDGE_ICR 0x00000110 +#define BRIDGE_INT_MODE 0x00000118 +#define BRIDGE_INT_DEV 0x00000120 +#define BRIDGE_INT_HOST_ERR 0x00000128 +#define BRIDGE_INT_ADDR(d) (0x00000130 + 8 * (d)) /* the following two are XBridge-only */ -#define BRIDGE_INT_FORCE_ALWAYS(d) (0x00000184 + 8 * (d)) -#define BRIDGE_INT_FORCE_PIN(d) (0x000001c4 + 8 * (d)) +#define BRIDGE_INT_FORCE_ALWAYS(d) (0x00000180 + 8 * (d)) +#define BRIDGE_INT_FORCE_PIN(d) (0x000001c0 + 8 * (d)) /* * PCI Resource Mapping control @@ -86,7 +97,7 @@ * the selected address will match BAR0. */ -#define BRIDGE_DEVICE(d) (0x00000204 + 8 * (d)) +#define BRIDGE_DEVICE(d) (0x00000200 + 8 * (d)) /* flags applying to the device itself */ /* byteswap DMA done through ATE */ #define BRIDGE_DEVICE_SWAP_PMU 0x00100000 @@ -114,9 +125,11 @@ BRIDGE_DEVIO_SHORT * ((d) < 2 ? 0 : (d) - 2)) #define BRIDGE_DEVIO_SIZE(d) \ ((d) < 2 ? BRIDGE_DEVIO_LARGE : BRIDGE_DEVIO_SHORT) +#define PIC_DEVIO_OFFS(bus,d) \ + (BRIDGE_DEVIO_OFFS(d) + ((bus) != 0 ? BRIDGE_BUS_OFFSET : 0)) -#define BRIDGE_DEVICE_WBFLUSH(d) (0x00000244 + 8 * (d)) +#define BRIDGE_DEVICE_WBFLUSH(d) (0x00000240 + 8 * (d)) /* * Read Response Buffer configuration registers @@ -131,8 +144,8 @@ * PCI slots. */ -#define BRIDGE_RRB_EVEN 0x00000284 -#define BRIDGE_RRB_ODD 0x0000028c +#define BRIDGE_RRB_EVEN 0x00000280 +#define BRIDGE_RRB_ODD 0x00000288 #define RRB_VALID 0x8 #define RRB_VCHAN 0x4 |