diff options
author | Visa Hankala <visa@cvs.openbsd.org> | 2021-05-01 16:11:18 +0000 |
---|---|---|
committer | Visa Hankala <visa@cvs.openbsd.org> | 2021-05-01 16:11:18 +0000 |
commit | 58b3d2ba77817cf3ac54cf921bf87b95844589c4 (patch) | |
tree | 8d0e4f6d500b406f61850688259f6ae7ae3c77c9 /sys/arch/sgi/xbow | |
parent | 2c481e94e93c02c0c859d4f32d311d2e71b82054 (diff) |
Retire OpenBSD/sgi.
OK deraadt@
Diffstat (limited to 'sys/arch/sgi/xbow')
-rw-r--r-- | sys/arch/sgi/xbow/Makefile | 7 | ||||
-rw-r--r-- | sys/arch/sgi/xbow/devlist2h.awk | 168 | ||||
-rw-r--r-- | sys/arch/sgi/xbow/files.xbow | 28 | ||||
-rw-r--r-- | sys/arch/sgi/xbow/hub.h | 233 | ||||
-rw-r--r-- | sys/arch/sgi/xbow/impact_xbow.c | 168 | ||||
-rw-r--r-- | sys/arch/sgi/xbow/odyssey.c | 1149 | ||||
-rw-r--r-- | sys/arch/sgi/xbow/odysseyreg.h | 43 | ||||
-rw-r--r-- | sys/arch/sgi/xbow/odysseyvar.h | 19 | ||||
-rw-r--r-- | sys/arch/sgi/xbow/widget.h | 79 | ||||
-rw-r--r-- | sys/arch/sgi/xbow/xbow.c | 727 | ||||
-rw-r--r-- | sys/arch/sgi/xbow/xbow.h | 132 | ||||
-rw-r--r-- | sys/arch/sgi/xbow/xbowdevs | 80 | ||||
-rw-r--r-- | sys/arch/sgi/xbow/xbowdevs.h | 85 | ||||
-rw-r--r-- | sys/arch/sgi/xbow/xbowdevs_data.h | 99 | ||||
-rw-r--r-- | sys/arch/sgi/xbow/xbridge.c | 3596 | ||||
-rw-r--r-- | sys/arch/sgi/xbow/xbridgereg.h | 340 | ||||
-rw-r--r-- | sys/arch/sgi/xbow/xheart.c | 487 | ||||
-rw-r--r-- | sys/arch/sgi/xbow/xheartreg.h | 120 |
18 files changed, 0 insertions, 7560 deletions
diff --git a/sys/arch/sgi/xbow/Makefile b/sys/arch/sgi/xbow/Makefile deleted file mode 100644 index b0a96ac8d49..00000000000 --- a/sys/arch/sgi/xbow/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# $OpenBSD: Makefile,v 1.1 2008/04/07 22:47:40 miod Exp $ - -AWK= awk - -xbowdevs.h xbowdevs_data.h: xbowdevs devlist2h.awk - /bin/rm -f xbowdevs.h xbowdevs_data.h - ${AWK} -f devlist2h.awk xbowdevs diff --git a/sys/arch/sgi/xbow/devlist2h.awk b/sys/arch/sgi/xbow/devlist2h.awk deleted file mode 100644 index a7106aa986b..00000000000 --- a/sys/arch/sgi/xbow/devlist2h.awk +++ /dev/null @@ -1,168 +0,0 @@ -#! /usr/bin/awk -f -# $OpenBSD: devlist2h.awk,v 1.2 2008/07/28 18:50:59 miod Exp $ -# $NetBSD: devlist2h.awk,v 1.2 1996/01/22 21:08:09 cgd Exp $ -# -# Copyright (c) 1995, 1996 Christopher G. Demetriou -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. All advertising materials mentioning features or use of this software -# must display the following acknowledgement: -# This product includes software developed by Christopher G. Demetriou. -# 4. The name of the author may not be used to endorse or promote products -# derived from this software without specific prior written permission -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -BEGIN { - nproducts = nvendor_dup = nvendors = 0 - dfile="xbowdevs_data.h" - hfile="xbowdevs.h" -} -NR == 1 { - VERSION = $0 - gsub("\\$", "", VERSION) - - printf("/*\n") > dfile - printf(" * THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT.\n") \ - > dfile - printf(" *\n") > dfile - printf(" * generated from:\n") > dfile - printf(" *\t%s\n", VERSION) > dfile - printf(" */\n\n") > dfile - - printf("/*\n") > hfile - printf(" * THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT.\n") \ - > hfile - printf(" *\n") > hfile - printf(" * generated from:\n") > hfile - printf(" *\t%s\n", VERSION) > hfile - printf(" */\n") > hfile - - next -} -$1 == "vendor" { - nvendors++ - - if ($2 in vendorindex) { - printf("duplicate vendor name %s\n", $2); - nvendor_dup++; - } - - vendorindex[$2] = nvendors; # record index for this name, for later. - vendors[nvendors, 1] = $2; # name - vendors[nvendors, 2] = $3; # id - printf("#define\tXBOW_VENDOR_%s\t%s\n", vendors[nvendors, 1], - vendors[nvendors, 2]) > hfile - - next -} -$1 == "product" { - nproducts++ - - products[nproducts, 1] = $2; # vendor name - products[nproducts, 2] = $3; # product id - products[nproducts, 3] = $4; # id - printf("#define\tXBOW_PRODUCT_%s_%s\t%s\t", products[nproducts, 1], - products[nproducts, 2], products[nproducts, 3]) > hfile - - i=4; f = 5; - - # comments - ocomment = oparen = 0 - if (f <= NF) { - printf("\t/* ") > hfile - ocomment = 1; - } - while (f <= NF) { - if ($f == "#") { - printf("(") > hfile - oparen = 1 - f++ - continue - } - if (oparen) { - printf("%s", $f) > hfile - if (f < NF) - printf(" ") > hfile - f++ - continue - } - products[nproducts, i] = $f - printf("%s", products[nproducts, i]) > hfile - if (f < NF) - printf(" ") > hfile - i++; f++; - } - if (oparen) - printf(")") > hfile - if (ocomment) - printf(" */") > hfile - printf("\n") > hfile - - next -} -{ - if ($0 == "") - blanklines++ - print $0 > hfile - if (blanklines < 2) - print $0 > dfile -} -END { - # print out the match tables - - printf("\n") > dfile - - if (nvendor_dup > 0) - exit(1); - - printf("/* Descriptions of known devices. */\n") > dfile - - printf("struct xbow_product {\n") > dfile - printf("\tuint32_t vendor;\n") > dfile - printf("\tuint32_t product;\n") > dfile - printf("\tconst char *productname;\n") > dfile - printf("};\n\n") > dfile - - - printf("static const struct xbow_product xbow_products[] = {\n") \ - > dfile - for (i = 1; i <= nproducts; i++) { - printf("\t{\n") > dfile - printf("\t XBOW_VENDOR_%s, XBOW_PRODUCT_%s_%s,\n", - products[i, 1], products[i, 1], products[i, 2]) \ - > dfile - - printf("\t \"") > dfile - j = 4; - needspace = 0; - while (products[i, j] != "") { - if (needspace) - printf(" ") > dfile - printf("%s", products[i, j]) > dfile - needspace = 1 - j++ - } - printf("\",\n") > dfile - printf("\t},\n") > dfile - } - printf("\t{ 0, 0, NULL, }\n") > dfile - printf("};\n\n") > dfile -} diff --git a/sys/arch/sgi/xbow/files.xbow b/sys/arch/sgi/xbow/files.xbow deleted file mode 100644 index a58bd3f16ee..00000000000 --- a/sys/arch/sgi/xbow/files.xbow +++ /dev/null @@ -1,28 +0,0 @@ -# $OpenBSD: files.xbow,v 1.9 2012/05/10 21:30:09 miod Exp $ - -# IP30 and IP27 planar XBow bus -define xbow {[widget = -1], [vendor = -1], [product = -1]} -device xbow -attach xbow at mainbus -file arch/sgi/xbow/xbow.c xbow - -# IP30 Heart -device xheart {} : onewirebus -attach xheart at xbow -file arch/sgi/xbow/xheart.c xheart - -# PCI Bridge -device xbridge {} -attach xbridge at xbow -device xbpci {[bus = -1]} : pcibus -attach xbpci at xbridge -file arch/sgi/xbow/xbridge.c xbridge - -# Odyssey graphics -device odyssey: wsemuldisplaydev, rasops32 -attach odyssey at xbow -file arch/sgi/xbow/odyssey.c odyssey needs-flag - -# ImpactSR graphics -attach impact at xbow with impact_xbow -file arch/sgi/xbow/impact_xbow.c impact_xbow diff --git a/sys/arch/sgi/xbow/hub.h b/sys/arch/sgi/xbow/hub.h deleted file mode 100644 index 485ac09f6a2..00000000000 --- a/sys/arch/sgi/xbow/hub.h +++ /dev/null @@ -1,233 +0,0 @@ -/* $OpenBSD: hub.h,v 1.11 2016/01/02 05:49:36 visa Exp $ */ - -/* - * Copyright (c) 2009 Miodrag Vallat. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * HUB access macros. - */ -#define LWIN_SIZE_BITS 24 -#define LWIN_SIZE (1ULL << LWIN_SIZE_BITS) - -#define NODE_LWIN_BASE(nasid, widget) \ - (IP27_NODE_IO_BASE(nasid) + ((uint64_t)(widget) << LWIN_SIZE_BITS)) - -#define IP27_LHUB_ADDR(_x) \ - ((volatile uint64_t *)(NODE_LWIN_BASE(0, 1) + (_x))) -#define IP27_RHUB_ADDR(_n, _x) \ - ((volatile uint64_t *)(NODE_LWIN_BASE(_n, 1) + 0x800000 + (_x))) -#define IP27_RHUB_PI_ADDR(_n, _sn, _x) \ - ((volatile uint64_t *)(NODE_LWIN_BASE(_n, 1) + 0x800000 + \ - ((_sn) ? HUBPI_OFFSET : 0) + (_x))) - -#define IP27_LHUB_L(r) *(IP27_LHUB_ADDR(r)) -#define IP27_LHUB_S(r, d) *(IP27_LHUB_ADDR(r)) = (d) -#define IP27_RHUB_L(n, r) *(IP27_RHUB_ADDR((n), (r))) -#define IP27_RHUB_S(n, r, d) *(IP27_RHUB_ADDR((n), (r))) = (d) -#define IP27_RHUB_PI_L(n, s, r) *(IP27_RHUB_PI_ADDR((n), (s), (r))) -#define IP27_RHUB_PI_S(n, s, r, d) *(IP27_RHUB_PI_ADDR((n), (s), (r))) = (d) - -#define NODE_HSPEC_BASE(nasid) \ - (IP27_NODE_HSPEC_BASE(nasid)) - -#define IP27_LHSPEC_ADDR(_x) \ - ((volatile uint64_t *)(NODE_HSPEC_BASE(0) + (_x))) -#define IP27_RHSPEC_ADDR(_n, _x) \ - ((volatile uint64_t *)(NODE_HSPEC_BASE(_n) + 0x20000000 + (_x))) - -#define IP27_LHSPEC_L(r) *(IP27_LHSPEC_ADDR(r)) -#define IP27_LHSPEC_S(r, d) *(IP27_LHSPEC_ADDR(r)) = (d) -#define IP27_RHSPEC_L(n, r) *(IP27_RHSPEC_ADDR((n), (r))) -#define IP27_RHSPEC_S(n, r, d) *(IP27_RHSPEC_ADDR((n), (r))) = (d) - -/* - * HUB SPECIAL space (very incomplete) - */ - -#define LBOOTBASE_IP27 0x10000000 -#define LBOOTSIZE_IP27 0x10000000 - -#define LREGBASE_IP35 0x10000000 -#define LREGSIZE_IP35 0x08000000 -#define LBOOTBASE_IP35 0x18000000 -#define LBOOTSIZE_IP35 0x08000000 - -#define HSPEC_L1_UARTBASE 0x00000080 -#define HSPEC_SYNERGY0 0x04000000 /* synergy #0 base */ -#define HSPEC_SYNERGY1 0x05000000 /* synergy #1 base */ - -#define HSPEC_L1_UART(r) \ - (LREGBASE_IP35 + HSPEC_L1_UARTBASE + ((r) << 3)) -#define HSPEC_SYNERGY(s,r) \ - (LREGBASE_IP35 + ((s) ? HSPEC_SYNERGY1 : HSPEC_SYNERGY0) + ((r) << 3)) - -/* - * HUB IO space (very incomplete) - */ - -/* - * HUB PI - Processor Interface - */ - -#define HUBPIBASE 0x00000000 - -#define HUBPI_REGION_PRESENT 0x00000018 -#define HUBPI_CPU_NUMBER 0x00000020 -#define HUBPI_CALIAS_SIZE 0x00000028 -#define PI_CALIAS_SIZE_0 0 - - -#define HUBPI_CPU0_PRESENT 0x00000040 -#define HUBPI_CPU1_PRESENT 0x00000048 -#define HUBPI_CPU0_ENABLED 0x00000050 -#define HUBPI_CPU1_ENABLED 0x00000058 - -#define HUBPI_IR_CHANGE 0x00000090 -#define PI_IR_SET 0x100 -#define PI_IR_CLR 0x000 -#define HUBPI_IR0 0x00000098 -#define HUBPI_IR1 0x000000a0 -#define HUBPI_CPU0_IMR0 0x000000a8 -#define HUBPI_CPU0_IMR1 0x000000b0 -#define HUBPI_CPU1_IMR0 0x000000b8 -#define HUBPI_CPU1_IMR1 0x000000c0 - -#define HUBPI_RT_COUNT 0x00030100 - -/* - * Offset to use to access the second PI over the remote hub interface - * on IP35. - */ -#define HUBPI_OFFSET 0x00200000 - -/* - * ISR bit assignments. - */ - -/** Level 1 interrupt */ -/* ?? MSC panic */ -#define HUBPI_ISR1_MSC_ERROR 63 -/* NI interface error */ -#define HUBPI_ISR1_NI_ERROR 62 -/* MD correctable error */ -#define HUBPI_ISR1_MD_COR_ERROR 61 -/* cpu correctable error B */ -#define HUBPI_ISR1_COR_ERROR_B 60 -/* cpu correctable error A */ -#define HUBPI_ISR1_COR_ERROR_A 59 -/* clock error */ -#define HUBPI_ISR1_CLOCK_ERROR 58 -/* IP35 NACK interrupts */ -#define HUBPI_ISR1_NACK_B 57 -#define HUBPI_ISR1_NACK_A 56 -/* IP35 LB error */ -#define HUBPI_ISR1_LB 55 -/* IP35 XB error */ -#define HUBPI_ISR1_XB 54 -/* 53-45 used by PROM */ -/* 44-43 available */ -/* 42-41 LLP errors */ -/* NI broadcast errors */ -#define HUBPI_ISR1_NI_ERROR_B 40 -#define HUBPI_ISR1_NI_ERROR_A 39 -/* 38-36 used by IP35 PROM */ -/* 35-0 available */ - -/** Level 0 interrupt */ -/* 63-11 available */ -/* IPI interrupts */ -#define HUBPI_ISR0_IPI_D 10 -#define HUBPI_ISR0_IPI_C 9 -#define HUBPI_ISR0_IPI_B 8 -#define HUBPI_ISR0_IPI_A 7 -/* ? */ -#define HUBPI_CC_PEND_B 6 -#define HUBPI_CC_PEND_A 5 -/* ? */ -#define HUBPI_ISR0_UART 4 -/* page migration interrupt */ -#define HUBPI_ISR0_PAGE_MIGRATION 3 -/* graphics->cpu interrupts */ -#define HUBPI_ISR0_GFX_B 2 -#define HUBPI_ISR0_GFX_A 1 -/* 0 reserved */ - -#define HUBPI_INTR1_WIDGET_MAX 35 -#define HUBPI_INTR1_WIDGET_MIN 0 -#define HUBPI_INTR0_WIDGET_MAX 63 -#define HUBPI_INTR0_WIDGET_MIN 11 - -#define HUBPI_NINTS 64 /* per register */ - -/* - * HUB MD - Memory/Directory - */ - -#define HUBMDBASE_IP27 0x00200000 -#define HUBMDBASE_IP35 0x00780000 - -#define HUBMD_LED0 0x00020050 - - -/* - * HUB IO - Widget I/O - */ - -#define HUBIOBASE 0x00400000 - -#define HUBIO_IOTTE(x) (0x00000160 + (x) * 8) -#define IOTTE_MAX 7 -#define IOTTE_SWIN0 (IOTTE_MAX - 1) - -#define IOTTE(space,widget,offset) \ - (((space) << 12) | ((widget) << 8) | (offset)) -#define IOTTE_SPACE_DEVICE 1 -#define IOTTE_SPACE_MEMORY 0 -#define IOTTE_SPACE(iotte) (((iotte) >> 12) & 0x01) -#define IOTTE_WIDGET(iotte) (((iotte) >> 8) & 0x0f) -#define IOTTE_OFFSET(iotte) ((iotte) & 0xff) - - -/* - * HUB LB - Local Bedrock - */ - -#define HUBLBBASE_IP35 0x00600000 - -/* - * HUB NI - Network Interface - */ - -#define HUBNIBASE_IP27 0x00600000 -#define HUBNIBASE_IP35 0x00680000 - -#define HUBNI_STATUS 0x00000000 -#define NI_MORENODES 0x0000000000040000 -#define HUBNI_RESET 0x00000008 -#define NI_RESET_ACTION_IP27 0x02 -#define NI_RESET_PORT_IP27 0x80 -#define NI_RESET_LOCAL_IP27 0x01 -#define NI_RESET_ACTION_IP35 0x01 -#define NI_RESET_PORT_IP35 0x02 -#define NI_RESET_LOCAL_IP35 0x04 -#define HUBNI_RESET_ENABLE 0x00000010 -#define NI_RESET_ENABLE 0x01 - -/* - * HUB XB - Crossbar interface - */ - -#define HUBXBBASE_IP35 0x00700000 diff --git a/sys/arch/sgi/xbow/impact_xbow.c b/sys/arch/sgi/xbow/impact_xbow.c deleted file mode 100644 index bfe2bb350a3..00000000000 --- a/sys/arch/sgi/xbow/impact_xbow.c +++ /dev/null @@ -1,168 +0,0 @@ -/* $OpenBSD: impact_xbow.c,v 1.2 2017/09/08 05:36:52 deraadt Exp $ */ - -/* - * Copyright (c) 2010, 2012 Miodrag Vallat. - * Copyright (c) 2009, 2010 Joel Sing <jsing@openbsd.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * Driver for the SGI ImpactSR graphics board (XBow attachment). - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/device.h> - -#include <machine/autoconf.h> - -#include <mips64/arcbios.h> - -#include <sgi/dev/impactvar.h> -#include <sgi/xbow/widget.h> -#include <sgi/xbow/xbow.h> -#include <sgi/xbow/xbowdevs.h> - -#define IMPACTSR_REG_OFFSET 0x00000000 -#define IMPACTSR_REG_SIZE 0x00200000 - -struct impact_xbow_softc { - struct impact_softc sc_base; - - struct mips_bus_space iot_store; -}; - -int impact_xbow_match(struct device *, void *, void *); -void impact_xbow_attach(struct device *, struct device *, void *); - -const struct cfattach impact_xbow_ca = { - sizeof(struct impact_xbow_softc), impact_xbow_match, impact_xbow_attach -}; - -int impact_xbow_is_console(struct xbow_attach_args *); - -int -impact_xbow_match(struct device *parent, void *match, void *aux) -{ - struct xbow_attach_args *xaa = aux; - - if (xaa->xaa_vendor == XBOW_VENDOR_SGI5 && - xaa->xaa_product == XBOW_PRODUCT_SGI5_IMPACT) - return 1; - - return 0; -} - -void -impact_xbow_attach(struct device *parent, struct device *self, void *aux) -{ - struct xbow_attach_args *xaa = aux; - struct impact_xbow_softc *sc = (struct impact_xbow_softc *)self; - bus_space_tag_t iot; - bus_space_handle_t ioh; - int console; - - if (strncmp(bios_graphics, "alive", 5) != 0) { - printf(" device has not been setup by firmware!\n"); - return; - } - - printf(" revision %d\n", xaa->xaa_revision); - - console = impact_xbow_is_console(xaa); - - if (console != 0) { - iot = NULL; - ioh = 0; - } else { - /* - * Create a copy of the bus space tag. - */ - bcopy(xaa->xaa_iot, &sc->iot_store, - sizeof(struct mips_bus_space)); - iot = &sc->iot_store; - - /* Setup bus space mappings. */ - if (bus_space_map(iot, IMPACTSR_REG_OFFSET, - IMPACTSR_REG_SIZE, 0, &ioh)) { - printf("failed to map registers\n"); - return; - } - } - - if (impact_attach_common(&sc->sc_base, iot, ioh, console, 1) != 0) { - if (console == 0) - bus_space_unmap(iot, ioh, IMPACTSR_REG_SIZE); - } -} - -/* - * Console support. - */ - -int -impact_xbow_cnprobe() -{ - u_int32_t wid, vendor, product; - - if (xbow_widget_id(console_output.nasid, console_output.widget, - &wid) != 0) - return 0; - - vendor = WIDGET_ID_VENDOR(wid); - product = WIDGET_ID_PRODUCT(wid); - - if (vendor != XBOW_VENDOR_SGI5 || product != XBOW_PRODUCT_SGI5_IMPACT) - return 0; - - if (strncmp(bios_graphics, "alive", 5) != 0) - return 0; - - return 1; -} - -int -impact_xbow_cnattach() -{ - static struct mips_bus_space impact_iot_store; - bus_space_tag_t iot; - bus_space_handle_t ioh; - int rc; - - /* Build bus space accessor. */ - xbow_build_bus_space(&impact_iot_store, console_output.nasid, - console_output.widget); - iot = &impact_iot_store; - - rc = bus_space_map(iot, IMPACTSR_REG_OFFSET, IMPACTSR_REG_SIZE, - 0, &ioh); - if (rc != 0) - return rc; - - rc = impact_cnattach_common(iot, ioh, 1); - if (rc != 0) { - bus_space_unmap(iot, ioh, IMPACTSR_REG_SIZE); - return rc; - } - - return 0; -} - -int -impact_xbow_is_console(struct xbow_attach_args *xaa) -{ - return xaa->xaa_nasid == console_output.nasid && - xaa->xaa_widget == console_output.widget; -} diff --git a/sys/arch/sgi/xbow/odyssey.c b/sys/arch/sgi/xbow/odyssey.c deleted file mode 100644 index fa5595611c6..00000000000 --- a/sys/arch/sgi/xbow/odyssey.c +++ /dev/null @@ -1,1149 +0,0 @@ -/* $OpenBSD: odyssey.c,v 1.15 2021/03/11 11:17:00 jsg Exp $ */ -/* - * Copyright (c) 2009, 2010 Joel Sing <jsing@openbsd.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * Driver for the SGI VPro (aka Odyssey) Graphics Card. - */ - -/* - * The details regarding the design and operation of this hardware, along with - * the necessary magic numbers, are only available thanks to the reverse - * engineering work undertaken by Stanislaw Skowronek <skylark@linux-mips.org>. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/device.h> -#include <sys/malloc.h> - -#include <machine/autoconf.h> - -#include <mips64/arcbios.h> - -#include <sgi/dev/gl.h> -#include <sgi/xbow/odysseyreg.h> -#include <sgi/xbow/odysseyvar.h> -#include <sgi/xbow/widget.h> -#include <sgi/xbow/xbow.h> -#include <sgi/xbow/xbowdevs.h> - -#include <dev/wscons/wsconsio.h> -#include <dev/wscons/wsdisplayvar.h> -#include <dev/rasops/rasops.h> - -/* - * Colourmap data. - */ -struct odyssey_cmap { - u_int8_t cm_red[256]; - u_int8_t cm_green[256]; - u_int8_t cm_blue[256]; -}; - -/* - * Screen data. - */ -struct odyssey_screen { - struct device *sc; /* Back pointer. */ - - struct rasops_info ri; /* Screen raster display info. */ - struct odyssey_cmap cmap; /* Display colour map. */ - uint32_t attr; /* Rasops attributes. */ - - int width; /* Width in pixels. */ - int height; /* Height in pixels. */ - int depth; /* Colour depth in bits. */ - int linebytes; /* Bytes per line. */ -}; - -struct odyssey_softc { - struct device sc_dev; - - struct mips_bus_space iot_store; - bus_space_tag_t iot; - bus_space_handle_t ioh; - - int console; /* Is this the console? */ - int screens; /* No of screens allocated. */ - - struct odyssey_screen *curscr; /* Current screen. */ -}; - -int odyssey_match(struct device *, void *, void *); -void odyssey_attach(struct device *, struct device *, void *); - -int odyssey_is_console(struct xbow_attach_args *); - -void odyssey_cmd_wait(struct odyssey_softc *); -void odyssey_data_wait(struct odyssey_softc *); -void odyssey_cmd_flush(struct odyssey_softc *, int); - -void odyssey_setup(struct odyssey_softc *); -void odyssey_init_screen(struct odyssey_screen *); - -/* - * Colour map handling for indexed modes. - */ -int odyssey_getcmap(struct odyssey_cmap *, struct wsdisplay_cmap *); -int odyssey_putcmap(struct odyssey_cmap *, struct wsdisplay_cmap *); - -/* - * Hardware acceleration for rasops. - */ -void odyssey_rop(struct odyssey_softc *, int, int, int, int, int, int); -void odyssey_copyrect(struct odyssey_softc *, int, int, int, int, int, int); -void odyssey_fillrect(struct odyssey_softc *, int, int, int, int, u_int); -int odyssey_do_cursor(struct rasops_info *); -int odyssey_putchar(void *, int, int, u_int, uint32_t); -int odyssey_copycols(void *, int, int, int, int); -int odyssey_erasecols(void *, int, int, int, uint32_t); -int odyssey_copyrows(void *, int, int, int); -int odyssey_eraserows(void *, int, int, uint32_t); - -u_int32_t ieee754_sp(uint); - -/* - * Interfaces for wscons. - */ -int odyssey_ioctl(void *, u_long, caddr_t, int, struct proc *); -paddr_t odyssey_mmap(void *, off_t, int); -int odyssey_alloc_screen(void *, const struct wsscreen_descr *, void **, - int *, int *, uint32_t *); -void odyssey_free_screen(void *, void *); -int odyssey_show_screen(void *, void *, int, void (*)(void *, int, int), - void *); -int odyssey_load_font(void *, void *, struct wsdisplay_font *); -int odyssey_list_font(void *, struct wsdisplay_font *); - -static struct odyssey_screen odyssey_consdata; -static struct odyssey_softc odyssey_cons_sc; - -struct wsscreen_descr odyssey_stdscreen = { - "std", /* Screen name. */ -}; - -struct wsdisplay_accessops odyssey_accessops = { - .ioctl = odyssey_ioctl, - .mmap = odyssey_mmap, - .alloc_screen = odyssey_alloc_screen, - .free_screen = odyssey_free_screen, - .show_screen = odyssey_show_screen, - .load_font = odyssey_load_font, - .list_font = odyssey_list_font -}; - -const struct wsscreen_descr *odyssey_scrlist[] = { - &odyssey_stdscreen -}; - -struct wsscreen_list odyssey_screenlist = { - nitems(odyssey_scrlist), odyssey_scrlist -}; - -const struct cfattach odyssey_ca = { - sizeof(struct odyssey_softc), odyssey_match, odyssey_attach, -}; - -struct cfdriver odyssey_cd = { - NULL, "odyssey", DV_DULL, -}; - -int -odyssey_match(struct device *parent, void *match, void *aux) -{ - struct xbow_attach_args *xaa = aux; - - if (xaa->xaa_vendor == XBOW_VENDOR_SGI2 && - xaa->xaa_product == XBOW_PRODUCT_SGI2_ODYSSEY) - return 1; - - return 0; -} - -void -odyssey_attach(struct device *parent, struct device *self, void *aux) -{ - struct xbow_attach_args *xaa = aux; - struct wsemuldisplaydev_attach_args waa; - struct odyssey_softc *sc = (void *)self; - struct odyssey_screen *screen; - - if (strncmp(bios_graphics, "alive", 5) != 0) { - printf(" device has not been setup by firmware!\n"); - return; - } - - printf(" revision %d\n", xaa->xaa_revision); - - /* - * Create a copy of the bus space tag. - */ - bcopy(xaa->xaa_iot, &sc->iot_store, sizeof(struct mips_bus_space)); - sc->iot = &sc->iot_store; - - /* Setup bus space mappings. */ - if (bus_space_map(sc->iot, ODYSSEY_REG_OFFSET, ODYSSEY_REG_SIZE, - BUS_SPACE_MAP_LINEAR, &sc->ioh)) { - printf("failed to map bus space!\n"); - return; - } - - if (odyssey_is_console(xaa)) { - /* - * Setup has already been done via odyssey_cnattach(). - */ - screen = &odyssey_consdata; - sc->curscr = screen; - sc->curscr->sc = (void *)sc; - sc->console = 1; - } else { - /* - * Setup screen data. - */ - sc->curscr = malloc(sizeof(struct odyssey_screen), M_DEVBUF, - M_NOWAIT); - if (sc->curscr == NULL) { - printf("failed to allocate screen memory!\n"); - return; - } - sc->curscr->sc = (void *)sc; - screen = sc->curscr; - - /* Setup hardware and clear screen. */ - odyssey_setup(sc); - odyssey_fillrect(sc, 0, 0, 1280, 1024, 0x000000); - odyssey_cmd_flush(sc, 0); - - /* Set screen defaults. */ - screen->width = 1280; - screen->height = 1024; - screen->depth = 32; - screen->linebytes = screen->width * screen->depth / 8; - - odyssey_init_screen(screen); - } - - waa.console = sc->console; - waa.scrdata = &odyssey_screenlist; - waa.accessops = &odyssey_accessops; - waa.accesscookie = screen; - waa.defaultscreens = 0; - config_found(self, &waa, wsemuldisplaydevprint); -} - -void -odyssey_init_screen(struct odyssey_screen *screen) -{ - u_char *colour; - int i; - - /* - * Initialise screen. - */ - - /* Initialise rasops. */ - memset(&screen->ri, 0, sizeof(struct rasops_info)); - - screen->ri.ri_flg = RI_CENTER; - screen->ri.ri_depth = screen->depth; - screen->ri.ri_width = screen->width; - screen->ri.ri_height = screen->height; - screen->ri.ri_stride = screen->linebytes; - - if (screen->depth == 32) { - screen->ri.ri_bpos = 16; - screen->ri.ri_bnum = 8; - screen->ri.ri_gpos = 8; - screen->ri.ri_gnum = 8; - screen->ri.ri_rpos = 0; - screen->ri.ri_rnum = 8; - } else if (screen->depth == 16) { - screen->ri.ri_rpos = 10; - screen->ri.ri_rnum = 5; - screen->ri.ri_gpos = 5; - screen->ri.ri_gnum = 5; - screen->ri.ri_bpos = 0; - screen->ri.ri_bnum = 5; - } - - rasops_init(&screen->ri, screen->height / 8, screen->width / 8); - - /* - * Initialise colourmap, if required. - */ - if (screen->depth == 8) { - for (i = 0; i < 16; i++) { - colour = (u_char *)&rasops_cmap[i * 3]; - screen->cmap.cm_red[i] = colour[0]; - screen->cmap.cm_green[i] = colour[1]; - screen->cmap.cm_blue[i] = colour[2]; - } - for (i = 240; i < 256; i++) { - colour = (u_char *)&rasops_cmap[i * 3]; - screen->cmap.cm_red[i] = colour[0]; - screen->cmap.cm_green[i] = colour[1]; - screen->cmap.cm_blue[i] = colour[2]; - } - } - - screen->ri.ri_hw = screen->sc; - - screen->ri.ri_ops.putchar = odyssey_putchar; - screen->ri.ri_do_cursor = odyssey_do_cursor; - screen->ri.ri_ops.copyrows = odyssey_copyrows; - screen->ri.ri_ops.copycols = odyssey_copycols; - screen->ri.ri_ops.eraserows = odyssey_eraserows; - screen->ri.ri_ops.erasecols = odyssey_erasecols; - - odyssey_stdscreen.ncols = screen->ri.ri_cols; - odyssey_stdscreen.nrows = screen->ri.ri_rows; - odyssey_stdscreen.textops = &screen->ri.ri_ops; - odyssey_stdscreen.fontwidth = screen->ri.ri_font->fontwidth; - odyssey_stdscreen.fontheight = screen->ri.ri_font->fontheight; - odyssey_stdscreen.capabilities = screen->ri.ri_caps; -} - -/* - * Hardware initialisation. - */ -void -odyssey_setup(struct odyssey_softc *sc) -{ - u_int64_t val; - int i; - - /* Initialise Buzz Graphics Engine. */ - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x20008003); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x21008010); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x22008000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x23008002); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x2400800c); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x2500800e); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x27008000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x28008000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x290080d6); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x2a0080e0); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x2c0080ea); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x2e008380); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x2f008000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x30008000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x31008000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x32008000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x33008000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x34008000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x35008000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x310081e0); - odyssey_cmd_flush(sc, 0); - - /* Initialise Buzz X-Form. */ - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x9080bda2); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x3f800000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x3f000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0xbf800000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x4e000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x40400000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x4e000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x4d000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x34008000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x9080bdc8); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x3f800000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x3f000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x3f800000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x3f000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x3f800000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x3f800000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x34008010); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x908091df); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x3f800000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x34008000); - odyssey_cmd_flush(sc, 0); - - /* Initialise Buzz Raster. */ - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x0001203b); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00001000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00001000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00001000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00001000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x0001084a); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000080); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000080); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010845); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x000000ff); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x000076ff); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x0001141b); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000001); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00011c16); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x03000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010404); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00011023); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00ff0ff0); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00ff0ff0); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x000000ff); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00011017); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00002000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000050); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x20004950); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x0001204b); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x004ff3ff); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00ffffff); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00ffffff); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00ffffff); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - odyssey_cmd_flush(sc, 0); - - /* - * Initialise Pixel Blaster & Jammer. - */ - for (i = 0; i < 32; i++) { - if ((i & 0xf) == 0) - odyssey_data_wait(sc); - - bus_space_write_8(sc->iot, sc->ioh, ODYSSEY_DATA_FIFO, - ((0x30000001ULL | ((0x2900 + i) << 14)) << 32) | - 0x905215a6); - } - - odyssey_data_wait(sc); - bus_space_write_8(sc->iot, sc->ioh, ODYSSEY_DATA_FIFO, - ((0x30000001ULL | (0x2581 << 14)) << 32) | 0x0); - - /* Gamma ramp. */ - for (i = 0; i < 0x600; i++) { - if ((i & 0xf) == 0) - odyssey_data_wait(sc); - - if (i < 0x200) - val = i >> 2; - else if (i < 0x300) - val = ((i - 0x200) >> 1) + 0x80; - else - val = ((i - 0x300) >> 0) + 0x100; - - val = (val << 20) | (val << 10) | val; - - bus_space_write_8(sc->iot, sc->ioh, ODYSSEY_DATA_FIFO, - ((0x30000001ULL | ((0x1a00 + i) << 14)) << 32) | val); - } -} - -void -odyssey_cmd_wait(struct odyssey_softc *sc) -{ - u_int32_t val, timeout = 1000000; - - val = bus_space_read_4(sc->iot, sc->ioh, ODYSSEY_STATUS); - while ((val & ODYSSEY_STATUS_CMD_FIFO_LOW) == 0) { - delay(1); - if (--timeout == 0) { - printf("odyssey: timeout waiting for command fifo!\n"); - return; - } - val = bus_space_read_4(sc->iot, sc->ioh, ODYSSEY_STATUS); - } -} - -void -odyssey_data_wait(struct odyssey_softc *sc) -{ - u_int32_t val, timeout = 1000000; - - val = bus_space_read_4(sc->iot, sc->ioh, ODYSSEY_DBE_STATUS); - while ((val & 0x7f) > 0) { - delay(1); - if (--timeout == 0) { - printf("odyssey: timeout waiting for data fifo!\n"); - return; - } - val = bus_space_read_4(sc->iot, sc->ioh, ODYSSEY_DBE_STATUS); - } -} - -void -odyssey_cmd_flush(struct odyssey_softc *sc, int quick) -{ - - odyssey_cmd_wait(sc); - - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010443); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x000000fa); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010046); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010046); - - if (quick) - return; - - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010019); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010443); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000096); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010046); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010046); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010046); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010046); - - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010443); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x000000fa); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010046); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010046); -} - -/* - * Interfaces for wscons. - */ - -int -odyssey_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p) -{ - struct odyssey_screen *screen = (struct odyssey_screen *)v; - int rc; - - switch (cmd) { - case WSDISPLAYIO_GTYPE: - *(u_int *)data = WSDISPLAY_TYPE_ODYSSEY; - break; - - case WSDISPLAYIO_GINFO: - { - struct wsdisplay_fbinfo *fb = (struct wsdisplay_fbinfo *)data; - - fb->height = screen->height; - fb->width = screen->width; - fb->depth = screen->depth; - fb->cmsize = screen->depth == 8 ? 256 : 0; - } - break; - - case WSDISPLAYIO_LINEBYTES: - *(u_int *)data = screen->linebytes; - break; - - case WSDISPLAYIO_GETCMAP: - if (screen->depth == 8) { - struct wsdisplay_cmap *cm = - (struct wsdisplay_cmap *)data; - - rc = odyssey_getcmap(&screen->cmap, cm); - if (rc != 0) - return (rc); - } - break; - - case WSDISPLAYIO_PUTCMAP: - if (screen->depth == 8) { - struct wsdisplay_cmap *cm = - (struct wsdisplay_cmap *)data; - - rc = odyssey_putcmap(&screen->cmap, cm); - if (rc != 0) - return (rc); - } - break; - - case WSDISPLAYIO_GVIDEO: - case WSDISPLAYIO_SVIDEO: - /* Handled by the upper layer. */ - break; - - default: - return (-1); - } - - return (0); -} - -int -odyssey_getcmap(struct odyssey_cmap *cm, struct wsdisplay_cmap *rcm) -{ - u_int index = rcm->index, count = rcm->count; - int rc; - - if (index >= 256 || count > 256 - index) - return (EINVAL); - - if ((rc = copyout(&cm->cm_red[index], rcm->red, count)) != 0) - return (rc); - if ((rc = copyout(&cm->cm_green[index], rcm->green, count)) != 0) - return (rc); - if ((rc = copyout(&cm->cm_blue[index], rcm->blue, count)) != 0) - return (rc); - - return (0); -} - -int -odyssey_putcmap(struct odyssey_cmap *cm, struct wsdisplay_cmap *rcm) -{ - u_int index = rcm->index, count = rcm->count; - int rc; - - if (index >= 256 || count > 256 - index) - return (EINVAL); - - if ((rc = copyin(rcm->red, &cm->cm_red[index], count)) != 0) - return (rc); - if ((rc = copyin(rcm->green, &cm->cm_green[index], count)) != 0) - return (rc); - if ((rc = copyin(rcm->blue, &cm->cm_blue[index], count)) != 0) - return (rc); - - return (0); -} - -paddr_t -odyssey_mmap(void *v, off_t offset, int protection) -{ - return (-1); -} - -int -odyssey_alloc_screen(void *v, const struct wsscreen_descr *type, - void **cookiep, int *curxp, int *curyp, uint32_t *attrp) -{ - struct odyssey_screen *screen = (struct odyssey_screen *)v; - struct odyssey_softc *sc = (struct odyssey_softc *)screen->sc; - - /* We do not allow multiple consoles at the moment. */ - if (sc->screens > 0) - return (ENOMEM); - - sc->screens++; - - /* Return rasops_info via cookie. */ - *cookiep = &screen->ri; - - /* Move cursor to top left of screen. */ - *curxp = 0; - *curyp = 0; - - /* Correct screen attributes. */ - screen->ri.ri_ops.pack_attr(&screen->ri, 0, 0, 0, attrp); - screen->attr = *attrp; - - return (0); -} - -void -odyssey_free_screen(void *v, void *cookie) -{ - /* We do not allow multiple consoles at the moment. */ -} - -int -odyssey_show_screen(void *v, void *cookie, int waitok, - void (*cb)(void *, int, int), void *cbarg) -{ - /* We do not allow multiple consoles at the moment. */ - return (0); -} - -int -odyssey_load_font(void *v, void *emulcookie, struct wsdisplay_font *font) -{ - struct odyssey_screen *screen = (struct odyssey_screen *)v; - - return rasops_load_font(&screen->ri, emulcookie, font); -} - -int -odyssey_list_font(void *v, struct wsdisplay_font *font) -{ - struct odyssey_screen *screen = (struct odyssey_screen *)v; - - return rasops_list_font(&screen->ri, font); -} - -/* - * Hardware accelerated functions. - */ - -void -odyssey_rop(struct odyssey_softc *sc, int x, int y, int w, int h, int op, int c) -{ - /* Setup raster operation. */ - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010404); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00100000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, OPENGL_LOGIC_OP); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, op); - odyssey_cmd_flush(sc, 1); - - odyssey_fillrect(sc, x, y, w, h, c); - - /* Return to copy mode. */ - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010404); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00100000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, OPENGL_LOGIC_OP); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, - OPENGL_LOGIC_OP_COPY); - odyssey_cmd_flush(sc, 1); -} - -void -odyssey_copyrect(struct odyssey_softc *sc, int sx, int sy, int dx, int dy, - int w, int h) -{ - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010658); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00120000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00002031); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00002000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, sx | (sy << 16)); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x80502050); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, w | (h << 16)); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x82223042); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00002000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, dx | (dy << 16)); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x3222204b); - - odyssey_cmd_flush(sc, 1); -} - -void -odyssey_fillrect(struct odyssey_softc *sc, int x, int y, int w, int h, u_int c) -{ - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, OPENGL_BEGIN); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, OPENGL_QUADS); - - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, OPENGL_COLOR_3UB); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, c & 0xff); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, (c >> 8) & 0xff); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, (c >> 16) & 0xff); - - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, OPENGL_VERTEX_2I); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, x); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, y); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, OPENGL_VERTEX_2I); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, x + w); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, y); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, OPENGL_VERTEX_2I); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, x + w); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, y + h); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, OPENGL_VERTEX_2I); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, x); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, y + h); - - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, OPENGL_END); - - odyssey_cmd_flush(sc, 1); -} - -int -odyssey_do_cursor(struct rasops_info *ri) -{ - struct odyssey_softc *sc = ri->ri_hw; - struct odyssey_screen *screen = sc->curscr; - int y, x, w, h, fg, bg; - - w = ri->ri_font->fontwidth; - h = ri->ri_font->fontheight; - x = ri->ri_xorigin + ri->ri_ccol * w; - y = ri->ri_yorigin + ri->ri_crow * h; - - ri->ri_ops.unpack_attr(ri, screen->attr, &fg, &bg, NULL); - - odyssey_rop(sc, x, y, w, h, OPENGL_LOGIC_OP_XOR, ri->ri_devcmap[fg]); - odyssey_cmd_flush(sc, 0); - - return 0; -} - -int -odyssey_putchar(void *cookie, int row, int col, u_int uc, uint32_t attr) -{ - struct rasops_info *ri = cookie; - struct odyssey_softc *sc = ri->ri_hw; - struct wsdisplay_font *font = ri->ri_font; - int bg, fg, ul, i, j, ci, l; - uint x, y, w, h; - u_int8_t *fontbitmap; - u_int chunk; - - w = ri->ri_font->fontwidth; - h = ri->ri_font->fontheight; - x = ri->ri_xorigin + col * w; - y = ri->ri_yorigin + row * h; - - fontbitmap = (u_int8_t *)(font->data + (uc - font->firstchar) * - ri->ri_fontscale); - ri->ri_ops.unpack_attr(ri, attr, &fg, &bg, &ul); - - /* Handle spaces with a single fillrect. */ - if (uc == ' ') { - odyssey_fillrect(sc, x, y, w, h, ri->ri_devcmap[bg]); - odyssey_cmd_flush(sc, 0); - return 0; - } - - odyssey_fillrect(sc, x, y, w, h, 0xff0000); - - /* Setup pixel painting. */ - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010405); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00002400); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, OPENGL_COLOR_3UB); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00011453); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000002); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - odyssey_cmd_flush(sc, 0); - - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x2900812f); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, OPENGL_BEGIN); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x0000000a); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0xcf80a92f); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, ieee754_sp(x)); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, ieee754_sp(y)); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, - ieee754_sp(x + font->fontwidth)); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, - ieee754_sp(y + font->fontheight)); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, OPENGL_VERTEX_2I); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00004570); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x0f00104c); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000071); - - for (i = font->fontheight; i != 0; i--) { - - /* Get bitmap for current line. */ - if (font->fontwidth <= 8) - chunk = *fontbitmap; - else - chunk = *(u_int16_t *)fontbitmap; - fontbitmap += font->stride; - - /* Handle underline. */ - if (ul && i == 1) - chunk = 0xffff; - - /* Draw character. */ - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, - 0x00004570); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, - 0x0fd1104c); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, - 0x00000071); - - w = font->fontwidth; - l = 0; - - for (j = 0; j < font->fontwidth; j++) { - - if (l == 0) { - - l = (w > 14 ? 14 : w); - w -= 14; - - /* Number of pixels. */ - bus_space_write_4(sc->iot, sc->ioh, - ODYSSEY_CMD_FIFO, (0x00014011 | - (l << 10))); - - } - - if (font->fontwidth > 8) - ci = (chunk & (1 << (16 - j)) ? fg : bg); - else - ci = (chunk & (1 << (8 - j)) ? fg : bg); - - bus_space_write_4(sc->iot, sc->ioh, - ODYSSEY_CMD_FIFO, ri->ri_devcmap[ci]); - - l--; - } - } - - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, OPENGL_END); - odyssey_cmd_flush(sc, 1); - - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x290080d6); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00011453); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00000000); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00010405); - bus_space_write_4(sc->iot, sc->ioh, ODYSSEY_CMD_FIFO, 0x00002000); - odyssey_cmd_flush(sc, 0); - - return 0; -} - -int -odyssey_copycols(void *cookie, int row, int src, int dst, int num) -{ - struct rasops_info *ri = cookie; - struct odyssey_softc *sc = ri->ri_hw; - int i; - - if (src < dst) { - - /* We cannot control copy direction, so copy col by col. */ - for (i = num - 1; i >= 0; i--) - odyssey_copyrect(sc, - ri->ri_xorigin + (src + i) * ri->ri_font->fontwidth, - ri->ri_yorigin + row * ri->ri_font->fontheight, - ri->ri_xorigin + (dst + i) * ri->ri_font->fontwidth, - ri->ri_yorigin + row * ri->ri_font->fontheight, - ri->ri_font->fontwidth, ri->ri_font->fontheight); - - } else { - - odyssey_copyrect(sc, - ri->ri_xorigin + src * ri->ri_font->fontwidth, - ri->ri_yorigin + row * ri->ri_font->fontheight, - ri->ri_xorigin + dst * ri->ri_font->fontwidth, - ri->ri_yorigin + row * ri->ri_font->fontheight, - num * ri->ri_font->fontwidth, ri->ri_font->fontheight); - - } - - odyssey_cmd_flush(sc, 0); - - return 0; -} - -int -odyssey_erasecols(void *cookie, int row, int col, int num, uint32_t attr) -{ - struct rasops_info *ri = cookie; - struct odyssey_softc *sc = ri->ri_hw; - int bg, fg; - - ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL); - - row *= ri->ri_font->fontheight; - col *= ri->ri_font->fontwidth; - num *= ri->ri_font->fontwidth; - - odyssey_fillrect(sc, ri->ri_xorigin + col, ri->ri_yorigin + row, - num, ri->ri_font->fontheight, ri->ri_devcmap[bg]); - odyssey_cmd_flush(sc, 0); - - return 0; -} - -int -odyssey_copyrows(void *cookie, int src, int dst, int num) -{ - struct rasops_info *ri = cookie; - struct odyssey_softc *sc = ri->ri_hw; - int i; - - if (src < dst) { - - /* We cannot control copy direction, so copy row by row. */ - for (i = num - 1; i >= 0; i--) - odyssey_copyrect(sc, ri->ri_xorigin, ri->ri_yorigin + - (src + i) * ri->ri_font->fontheight, - ri->ri_xorigin, ri->ri_yorigin + - (dst + i) * ri->ri_font->fontheight, - ri->ri_emuwidth, ri->ri_font->fontheight); - - } else { - - odyssey_copyrect(sc, ri->ri_xorigin, - ri->ri_yorigin + src * ri->ri_font->fontheight, - ri->ri_xorigin, - ri->ri_yorigin + dst * ri->ri_font->fontheight, - ri->ri_emuwidth, num * ri->ri_font->fontheight); - - } - - odyssey_cmd_flush(sc, 0); - - return 0; -} - -int -odyssey_eraserows(void *cookie, int row, int num, uint32_t attr) -{ - struct rasops_info *ri = cookie; - struct odyssey_softc *sc = ri->ri_hw; - int x, y, w, bg, fg; - - ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL); - - if ((num == ri->ri_rows) && ISSET(ri->ri_flg, RI_FULLCLEAR)) { - num = ri->ri_height; - x = y = 0; - w = ri->ri_width; - } else { - num *= ri->ri_font->fontheight; - x = ri->ri_xorigin; - y = ri->ri_yorigin + row * ri->ri_font->fontheight; - w = ri->ri_emuwidth; - } - - odyssey_fillrect(sc, x, y, w, num, ri->ri_devcmap[bg]); - odyssey_cmd_flush(sc, 0); - - return 0; -} - -u_int32_t -ieee754_sp(uint v) -{ - u_int8_t exp = 0; - int i = 12; /* 0 <= v < 2048 */ - - /* - * Convert a small integer to IEEE754 single precision floating point: - * - * Sign - 1 bit - * Exponent - 8 bits (with 2^(8-1)-1 = 127 bias) - * Fraction - 23 bits - */ - - /* Determine shift for fraction. */ - while (i && (v & (1 << --i)) == 0); - - if (v != 0) - exp = 127 + i; - - return (exp << 23) | ((v << (23 - i)) & 0x7fffff); -} - -/* - * Console support. - */ - -int -odyssey_cnprobe() -{ - u_int32_t wid, vendor, product; - - /* Probe for Odyssey graphics card. */ - if (xbow_widget_id(console_output.nasid, console_output.widget, - &wid) != 0) - return 0; - - vendor = WIDGET_ID_VENDOR(wid); - product = WIDGET_ID_PRODUCT(wid); - - if (vendor != XBOW_VENDOR_SGI2 || product != XBOW_PRODUCT_SGI2_ODYSSEY) - return 0; - - if (strncmp(bios_graphics, "alive", 5) != 0) - return 0; - - return 1; -} - -int -odyssey_cnattach() -{ - struct odyssey_softc *sc; - struct odyssey_screen *screen; - int rc; - - sc = &odyssey_cons_sc; - screen = &odyssey_consdata; - sc->curscr = screen; - sc->curscr->sc = (void *)sc; - - /* Build bus space accessor. */ - xbow_build_bus_space(&sc->iot_store, console_output.nasid, - console_output.widget); - sc->iot = &sc->iot_store; - - /* Setup bus space mappings. */ - rc = bus_space_map(sc->iot, ODYSSEY_REG_OFFSET, ODYSSEY_REG_SIZE, - BUS_SPACE_MAP_LINEAR, &sc->ioh); - if (rc != 0) - return rc; - - /* Setup hardware and clear screen. */ - odyssey_setup(sc); - odyssey_fillrect(sc, 0, 0, 1280, 1024, 0x000000); - odyssey_cmd_flush(sc, 0); - - /* Set screen defaults. */ - screen->width = 1280; - screen->height = 1024; - screen->depth = 32; - screen->linebytes = screen->width * screen->depth / 8; - - odyssey_init_screen(screen); - - /* - * Attach wsdisplay. - */ - screen->ri.ri_ops.pack_attr(&screen->ri, 0, 0, 0, &screen->attr); - wsdisplay_cnattach(&odyssey_stdscreen, &screen->ri, 0, 0, screen->attr); - - return 0; -} - -int -odyssey_is_console(struct xbow_attach_args *xaa) -{ - return xaa->xaa_nasid == console_output.nasid && - xaa->xaa_widget == console_output.widget; -} diff --git a/sys/arch/sgi/xbow/odysseyreg.h b/sys/arch/sgi/xbow/odysseyreg.h deleted file mode 100644 index 9bc36378366..00000000000 --- a/sys/arch/sgi/xbow/odysseyreg.h +++ /dev/null @@ -1,43 +0,0 @@ -/* $OpenBSD: odysseyreg.h,v 1.2 2012/04/16 22:17:16 miod Exp $ */ -/* - * Copyright (c) 2009, 2010 Joel Sing <jsing@openbsd.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * Register details for the SGI VPro (aka Odyssey) Graphics Card. - */ - -#define ODYSSEY_REG_OFFSET 0x00000000 -#define ODYSSEY_REG_SIZE 0x00410000 - -#define ODYSSEY_STATUS 0x00001064 -#define ODYSSEY_STATUS_CMD_FIFO_HIGH 0x00008000 -#define ODYSSEY_STATUS_CMD_FIFO_LOW 0x00020000 -#define ODYSSEY_DBE_STATUS 0x0000106c - -#define ODYSSEY_CMD_FIFO 0x00110000 -#define ODYSSEY_DATA_FIFO 0x00400000 - -/* - * OpenGL Commands. - */ - -#define OPENGL_BEGIN 0x00014400 -#define OPENGL_END 0x00014001 -#define OPENGL_LOGIC_OP 0x00010422 -#define OPENGL_VERTEX_2I 0x8080c800 -#define OPENGL_COLOR_3UB 0xc580cc08 - -#define OPENGL_QUADS 0x00000007 diff --git a/sys/arch/sgi/xbow/odysseyvar.h b/sys/arch/sgi/xbow/odysseyvar.h deleted file mode 100644 index 7e331156442..00000000000 --- a/sys/arch/sgi/xbow/odysseyvar.h +++ /dev/null @@ -1,19 +0,0 @@ -/* $OpenBSD: odysseyvar.h,v 1.2 2010/04/06 19:12:34 miod Exp $ */ -/* - * Copyright (c) 2010 Joel Sing <jsing@openbsd.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -int odyssey_cnprobe(void); -int odyssey_cnattach(void); diff --git a/sys/arch/sgi/xbow/widget.h b/sys/arch/sgi/xbow/widget.h deleted file mode 100644 index c88666066e0..00000000000 --- a/sys/arch/sgi/xbow/widget.h +++ /dev/null @@ -1,79 +0,0 @@ -/* $OpenBSD: widget.h,v 1.2 2010/04/06 19:02:57 miod Exp $ */ - -/* - * Copyright (c) 2008 Miodrag Vallat. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _WIDGET_H_ -#define _WIDGET_H_ - -/* - * 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. - */ - -#define WIDGET_ID 0x0000 -#define WIDGET_ID_REV_MASK 0xf0000000 -#define WIDGET_ID_REV_SHIFT 28 -#define WIDGET_ID_REV(wid) \ - (((wid) & WIDGET_ID_REV_MASK) >> WIDGET_ID_REV_SHIFT) -#define WIDGET_ID_PRODUCT_MASK 0x0ffff000 -#define WIDGET_ID_PRODUCT_SHIFT 12 -#define WIDGET_ID_PRODUCT(wid) \ - (((wid) & WIDGET_ID_PRODUCT_MASK) >> WIDGET_ID_PRODUCT_SHIFT) -#define WIDGET_ID_VENDOR_MASK 0x00000ffe -#define WIDGET_ID_VENDOR_SHIFT 1 -#define WIDGET_ID_VENDOR(wid) \ - (((wid) & WIDGET_ID_VENDOR_MASK) >> WIDGET_ID_VENDOR_SHIFT) -#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 0x0058 -#define XBOW_PERFCNTR_A 0x0060 -#define XBOW_PERFCNTR_B 0x0068 -#define XBOW_NIC 0x0070 -#define XBOW_WIDGET_LINK(w) (0x0100 + ((w) & 7) * 0x0040) - -/* - * Crossbow Per-widget ``Link'' Register Set. - */ -#define WIDGET_LINK_IBF 0x0000 -#define WIDGET_LINK_CONTROL 0x0008 -#define WIDGET_CONTROL_ALIVE 0x80000000 -#define WIDGET_LINK_STATUS 0x0010 -#define WIDGET_STATUS_ALIVE 0x80000000 -#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 - -#endif /* _WIDGET_H_ */ diff --git a/sys/arch/sgi/xbow/xbow.c b/sys/arch/sgi/xbow/xbow.c deleted file mode 100644 index 8545c87c266..00000000000 --- a/sys/arch/sgi/xbow/xbow.c +++ /dev/null @@ -1,727 +0,0 @@ -/* $OpenBSD: xbow.c,v 1.36 2021/03/11 11:17:00 jsg Exp $ */ - -/* - * Copyright (c) 2008, 2009, 2011 Miodrag Vallat. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -/* - * Copyright (c) 2004 Opsycon AB (www.opsycon.se) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -/* - * XBOW is the mux between two nodes and XIO. - * - * A Crossbow (XBOW) connects two nodeboards via their respective - * HUB to up to six different I/O controllers in XIO slots. In a - * multiprocessor system all processors have access to the XIO - * slots but may need to pass traffic via the routers. - * - * To each XIO port on the XBOW a XIO interface is attached. Such - * interfaces can be for example PCI bridges which then add another - * level to the hierarchy. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/conf.h> -#include <sys/malloc.h> -#include <sys/device.h> -#include <sys/atomic.h> - -#include <mips64/archtype.h> - -#include <machine/autoconf.h> -#include <machine/intr.h> -#include <machine/mnode.h> - -#include <sgi/xbow/hub.h> -#include <sgi/xbow/widget.h> -#include <sgi/xbow/xbow.h> - -#include <sgi/xbow/xbowdevs.h> -#include <sgi/xbow/xbowdevs_data.h> - -int xbowmatch(struct device *, void *, void *); -void xbowattach(struct device *, struct device *, void *); -int xbowprint(void *, const char *); -int xbowsubmatch(struct device *, void *, void *); -int xbow_attach_widget(struct device *, int16_t, int, - int (*)(struct device *, void *, void *), cfprint_t); - -int xbow_kl_search_brd(lboard_t *, void *); -int xbow_kl_search_mplane(klinfo_t *, void *); - -uint32_t xbow_read_4(bus_space_tag_t, bus_space_handle_t, bus_size_t); -uint64_t xbow_read_8(bus_space_tag_t, bus_space_handle_t, bus_size_t); -void xbow_write_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, uint32_t); -void xbow_write_8(bus_space_tag_t, bus_space_handle_t, bus_size_t, uint64_t); -void xbow_read_raw_4(bus_space_tag_t, bus_space_handle_t, bus_addr_t, - uint8_t *, bus_size_t); -void xbow_write_raw_4(bus_space_tag_t, bus_space_handle_t, bus_addr_t, - const uint8_t *, bus_size_t); -void xbow_read_raw_8(bus_space_tag_t, bus_space_handle_t, bus_addr_t, - uint8_t *, bus_size_t); -void xbow_write_raw_8(bus_space_tag_t, bus_space_handle_t, bus_addr_t, - const uint8_t *, bus_size_t); - -void xbow_space_unmap(bus_space_tag_t, bus_space_handle_t, bus_size_t); -int xbow_space_region(bus_space_tag_t, bus_space_handle_t, bus_size_t, - bus_size_t, bus_space_handle_t *); -void *xbow_space_vaddr(bus_space_tag_t, bus_space_handle_t); -void xbow_space_barrier(bus_space_tag_t, bus_space_handle_t, bus_size_t, - bus_size_t, int); - -const struct xbow_product *xbow_identify(uint32_t, uint32_t); - -struct xbow_softc { - struct device sc_dev; - int16_t sc_nasid; -}; - -const struct cfattach xbow_ca = { - sizeof(struct xbow_softc), xbowmatch, xbowattach -}; - -struct cfdriver xbow_cd = { - NULL, "xbow", DV_DULL -}; - -static const bus_space_t xbowbus_tag = { - (bus_addr_t)0, /* will be modified in widgets bus_space_t */ - NULL, - xbow_read_1, - xbow_write_1, - xbow_read_2, - xbow_write_2, - xbow_read_4, - xbow_write_4, - xbow_read_8, - xbow_write_8, - xbow_read_raw_2, - xbow_write_raw_2, - xbow_read_raw_4, - xbow_write_raw_4, - xbow_read_raw_8, - xbow_write_raw_8, - xbow_space_map, - xbow_space_unmap, - xbow_space_region, - xbow_space_vaddr, - xbow_space_barrier -}; - -/* - * Function pointers to hide widget discovery and mapping differences across - * systems. - */ -paddr_t (*xbow_widget_base)(int16_t, u_int); -paddr_t (*xbow_widget_map)(int16_t, u_int, bus_addr_t *, bus_size_t *); - -int (*xbow_widget_id)(int16_t, u_int, uint32_t *); - -/* - * Attachment glue. - */ - -int -xbowmatch(struct device *parent, void *match, void *aux) -{ - struct mainbus_attach_args *maa = aux; - - if (strcmp(maa->maa_name, xbow_cd.cd_name) != 0) - return (0); - - switch (sys_config.system_type) { - case SGI_IP27: - case SGI_IP35: - case SGI_OCTANE: - return (1); - default: - return (0); - } -} - -const struct xbow_product * -xbow_identify(uint32_t vendor, uint32_t product) -{ - const struct xbow_product *p; - - for (p = xbow_products; p->productname != NULL; p++) - if (p->vendor == vendor && p->product == product) - return p; - - return NULL; -} - -int -xbowprint(void *aux, const char *pnp) -{ - struct xbow_attach_args *xaa = aux; - const struct xbow_product *p; - - p = xbow_identify(xaa->xaa_vendor, xaa->xaa_product); - - if (pnp != NULL) { - if (p != NULL) - printf("\"%s\"", p->productname); - else - printf("vendor %x product %x", - xaa->xaa_vendor, xaa->xaa_product); - printf(" revision %d at %s", - xaa->xaa_revision, pnp); - } - printf(" widget %d", xaa->xaa_widget); - if (pnp == NULL) { - if (p != NULL) - printf(": %s", p->productname); - } - - return (UNCONF); -} - -int -xbowsubmatch(struct device *parent, void *vcf, void *aux) -{ - struct xbow_attach_args *xaa = aux; - struct cfdata *cf = vcf; - - if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != xaa->xaa_widget) - return 0; - if (cf->cf_loc[1] != -1 && cf->cf_loc[1] != xaa->xaa_vendor) - return 0; - if (cf->cf_loc[2] != -1 && cf->cf_loc[2] != xaa->xaa_product) - return 0; - - return (*cf->cf_attach->ca_match)(parent, vcf, aux); -} - -/* - * Widget probe order for various components - */ - -#ifdef TGT_OCTANE -/* Octane: probe Heart first, then onboard devices, then other slots */ -const uint8_t xbow_probe_octane[] = - { 0x08, 0x0f, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0 }; -#endif -#ifdef TGT_ORIGIN -/* Origin 200: probe onboard devices, and there is nothing more */ -const uint8_t xbow_probe_singlebridge[] = - { 0x08, 0 }; -/* Base I/O board: probe onboard devices, then other slots in ascending order */ -const uint8_t xbow_probe_baseio[] = - { 0x0f, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0 }; -/* I-Brick: probe PCI buses first (starting with the onboard devices) */ -const uint8_t xbow_probe_ibrick[] = - { 0x0f, 0x0e, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0 }; -/* P-Brick: all widgets are PCI buses, probe in recommended order */ -const uint8_t xbow_probe_pbrick[] = - { 0x09, 0x08, 0x0f, 0x0e, 0x0c, 0x0d, 0x0a, 0x0b, 0 }; -/* X-Brick: all widgets are XIO devices, probe in recommended order */ -const uint8_t xbow_probe_xbrick[] = - { 0x08, 0x09, 0x0c, 0x0d, 0x0a, 0x0b, 0x0e, 0x0f, 0 }; -#endif - -/* - * Structures used to carry information between KL and attachment code. - */ - -struct xbow_config { - int valid; - int widgets[WIDGET_MAX + 1 - WIDGET_MIN]; -}; - -struct xbow_kl_config { - const uint8_t *probe_order; - struct xbow_config *cfg; -}; - -void -xbowattach(struct device *parent, struct device *self, void *aux) -{ - struct xbow_softc *sc = (struct xbow_softc *)self; - struct mainbus_attach_args *maa = aux; - int16_t nasid = maa->maa_nasid; - uint32_t wid, vendor, product; - const struct xbow_product *p; -#ifdef TGT_ORIGIN - struct xbow_config cfg; -#endif - struct xbow_kl_config klcfg; - uint widget; - - sc->sc_nasid = nasid; - - /* - * This assumes widget 0 is the XBow itself (or an XXBow). - * If it isn't - feel free to haunt my bedroom at night. - */ - if (xbow_widget_id(nasid, 0, &wid) != 0) - panic("no xbow"); - vendor = WIDGET_ID_VENDOR(wid); - product = WIDGET_ID_PRODUCT(wid); - p = xbow_identify(vendor, product); - if (p == NULL) - printf(": unknown xbow (vendor %x product %x)", - vendor, product); - else - printf(": %s", p->productname); - printf(" revision %d\n", WIDGET_ID_REV(wid)); - - switch (sys_config.system_type) { - default: -#ifdef TGT_ORIGIN - memset(&cfg, 0, sizeof cfg); - klcfg.cfg = &cfg; - - /* - * If widget 0 reports itself as a bridge, this is not a - * complete XBow, but only a limited topology. This is - * found on at least the Origin 200. - */ - if (vendor == XBOW_VENDOR_SGI4 && - product == XBOW_PRODUCT_SGI4_BRIDGE) { - klcfg.probe_order = xbow_probe_singlebridge; - } else { - /* - * Get crossbow information from the KL configuration. - */ - klcfg.probe_order = NULL; - kl_scan_node(nasid, KLBRD_ANY, xbow_kl_search_brd, - &klcfg); - if (klcfg.probe_order == NULL) - klcfg.probe_order = xbow_probe_baseio; - - /* should not happen, but I can't help being paranoid */ - if (cfg.valid == 0) { - printf("%s: no hub\n", self->dv_xname); - return; - } - } - break; -#endif -#ifdef TGT_OCTANE - case SGI_OCTANE: - klcfg.probe_order = xbow_probe_octane; - break; -#endif - } - - for (; *klcfg.probe_order != 0; klcfg.probe_order++) { - widget = *klcfg.probe_order; -#ifdef TGT_ORIGIN - if (cfg.valid != 0 && - !ISSET(cfg.widgets[widget - WIDGET_MIN], XBOW_PORT_ENABLE)) - continue; -#endif - (void)xbow_attach_widget(self, nasid, widget, xbowsubmatch, - xbowprint); - } -} - -int -xbow_attach_widget(struct device *self, int16_t nasid, int widget, - int (*sm)(struct device *, void *, void *), cfprint_t print) -{ - struct xbow_attach_args xaa; - uint32_t wid; - struct mips_bus_space bs; - int rc; - - if ((rc = xbow_widget_id(nasid, widget, &wid)) != 0) - return rc; - - /* - * Build a bus_space_t suitable for this widget. - */ - xbow_build_bus_space(&bs, nasid, widget); - - xaa.xaa_nasid = nasid; - xaa.xaa_widget = widget; - xaa.xaa_vendor = WIDGET_ID_VENDOR(wid); - xaa.xaa_product = WIDGET_ID_PRODUCT(wid); - xaa.xaa_revision = WIDGET_ID_REV(wid); - xaa.xaa_iot = &bs; - - if (config_found_sm(self, &xaa, print, sm) == NULL) - return ENOENT; - - return 0; -} - -#ifdef TGT_ORIGIN - -/* - * These two functions try to figure out the configuration of the XBow - * on this node. - * - * We are looking for two pieces of information: - * - the Hub widget, to which memory is attached and interrupts are routed. - * - what kind of Brick we are. - * - * The first information can be obtained easily by looking for a MPLANE type - * board. However there is no easy way to figure the second part, except for - * checking what kind of boards are reported. - * - * A BaseIO board will report itself once, as a single widget. Bricks, on the - * other hand, appear for each of the widgets they provide. - */ - -int -xbow_kl_search_brd(lboard_t *brd, void *arg) -{ - struct xbow_kl_config *cfg = arg; - - switch (brd->brd_type & IP27_BC_MASK) { - case IP27_BC_MPLANE: - if (cfg->cfg->valid == 0) - kl_scan_board(brd, KLSTRUCT_XBOW, xbow_kl_search_mplane, - cfg->cfg); - break; - case IP27_BC_IO: - if (cfg->probe_order == NULL) - cfg->probe_order = xbow_probe_baseio; - break; - case IP27_BC_BRICK: - if (cfg->probe_order == NULL) - switch (brd->brd_type) { - case IP27_BRD_IBRICK: - case IP27_BRD_IXBRICK: - cfg->probe_order = xbow_probe_ibrick; - break; - case IP27_BRD_PBRICK: - case IP27_BRD_PXBRICK: - cfg->probe_order = xbow_probe_pbrick; - break; - case IP27_BRD_XBRICK: - cfg->probe_order = xbow_probe_xbrick; - break; - default: - /* other brick */ - break; - } - break; - } - - if (cfg->cfg->valid != 0 && cfg->probe_order != NULL) - return 1; /* stop enumeration */ - - return 0; -} - -int -xbow_kl_search_mplane(klinfo_t *c, void *arg) -{ - klxbow_t *xbow = (klxbow_t *)c; - struct xbow_config *cfg = arg; - uint w; - - cfg->valid = 1; - for (w = WIDGET_MIN; w <= WIDGET_MAX; w++) - cfg->widgets[w - WIDGET_MIN] = - xbow->xbow_port_info[w - WIDGET_MIN].port_flag; - - return 1; -} - -#endif - -/* - * Bus access primitives. - */ - -void -xbow_build_bus_space(struct mips_bus_space *bs, int nasid, int widget) -{ - bcopy(&xbowbus_tag, bs, sizeof (*bs)); - bs->bus_base = (*xbow_widget_base)(nasid, widget); -} - -uint8_t -xbow_read_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) -{ - return *(volatile uint8_t *)(h + o); -} - -uint16_t -xbow_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) -{ - return *(volatile uint16_t *)(h + o); -} - -uint32_t -xbow_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) -{ - return *(volatile uint32_t *)(h + o); -} - -uint64_t -xbow_read_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) -{ - return *(volatile uint64_t *)(h + o); -} - -void -xbow_write_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint8_t v) -{ - *(volatile uint8_t *)(h + o) = v; -} - -void -xbow_write_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint16_t v) -{ - *(volatile uint16_t *)(h + o) = v; -} - -void -xbow_write_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint32_t v) -{ - *(volatile uint32_t *)(h + o) = v; -} - -void -xbow_write_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, uint64_t v) -{ - *(volatile uint64_t *)(h + o) = v; -} - -void -xbow_read_raw_2(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o, - uint8_t *buf, bus_size_t len) -{ - volatile uint16_t *addr = (volatile uint16_t *)(h + o); - len >>= 1; - while (len-- != 0) { - *(uint16_t *)buf = *addr; - buf += 2; - } -} - -void -xbow_write_raw_2(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o, - const uint8_t *buf, bus_size_t len) -{ - volatile uint16_t *addr = (volatile uint16_t *)(h + o); - len >>= 1; - while (len-- != 0) { - *addr = *(uint16_t *)buf; - buf += 2; - } -} - -void -xbow_read_raw_4(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o, - uint8_t *buf, bus_size_t len) -{ - volatile uint32_t *addr = (volatile uint32_t *)(h + o); - len >>= 2; - while (len-- != 0) { - *(uint32_t *)buf = *addr; - buf += 4; - } -} - -void -xbow_write_raw_4(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o, - const uint8_t *buf, bus_size_t len) -{ - volatile uint32_t *addr = (volatile uint32_t *)(h + o); - len >>= 2; - while (len-- != 0) { - *addr = *(uint32_t *)buf; - buf += 4; - } -} - -void -xbow_read_raw_8(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o, - uint8_t *buf, bus_size_t len) -{ - volatile uint64_t *addr = (volatile uint64_t *)(h + o); - len >>= 3; - while (len-- != 0) { - *(uint64_t *)buf = *addr; - buf += 8; - } -} - -void -xbow_write_raw_8(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o, - const uint8_t *buf, bus_size_t len) -{ - volatile uint64_t *addr = (volatile uint64_t *)(h + o); - len >>= 3; - while (len-- != 0) { - *addr = *(uint64_t *)buf; - buf += 8; - } -} - -int -xbow_space_map(bus_space_tag_t t, bus_addr_t offs, bus_size_t size, - int flags, bus_space_handle_t *bshp) -{ - bus_addr_t bpa; - - bpa = t->bus_base + offs; - -#ifdef DIAGNOSTIC - /* check that this does not overflow the window */ - if (((bpa + size - 1) >> 24) != (t->bus_base >> 24)) - return (EINVAL); -#endif - - *bshp = bpa; - return 0; -} - -void -xbow_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size) -{ -} - -int -xbow_space_region(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 - bus_addr_t bpa; - - bpa = (bus_addr_t)bsh - t->bus_base; - /* check that this does not overflow the window */ - if (((bpa + offset) >> 24) != (t->bus_base >> 24)) - return (EINVAL); -#endif - - *nbshp = bsh + offset; - return 0; -} - -void * -xbow_space_vaddr(bus_space_tag_t t, bus_space_handle_t h) -{ - return (void *)h; -} - -void -xbow_space_barrier(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offs, - bus_size_t len, int flags) -{ - mips_sync(); -} - -/* - * Interrupt handling code. - * - * Interrupt handling should be done at the Heart/Hub driver level, we only - * act as a proxy here. - * - * Note that, for the time being, interrupt handling is implicitly done at - * the master nasid; other nodes do not handle interrupts. - */ - -uint64_t xbow_intr_address; - -int (*xbow_intr_widget_intr_register)(int, int, int *) = NULL; -int (*xbow_intr_widget_intr_establish)(int (*)(void *), void *, int, int, - const char *, struct intrhand *) = NULL; -void (*xbow_intr_widget_intr_disestablish)(int) = NULL; -void (*xbow_intr_widget_intr_set)(int) = NULL; -void (*xbow_intr_widget_intr_clear)(int) = NULL; - -int -xbow_intr_register(int widget, int level, int *intrbit) -{ - if (xbow_intr_widget_intr_register == NULL) - return EINVAL; - - return (*xbow_intr_widget_intr_register)(widget, level, intrbit); -} - -int -xbow_intr_establish(int (*func)(void *), void *arg, int intrbit, int level, - const char *name, struct intrhand *ihstore) -{ - if (xbow_intr_widget_intr_establish == NULL) - return EINVAL; - - return (*xbow_intr_widget_intr_establish)(func, arg, intrbit, level, - name, ihstore); -} - -void -xbow_intr_disestablish(int intrbit) -{ - if (xbow_intr_widget_intr_disestablish == NULL) - return; - - (*xbow_intr_widget_intr_disestablish)(intrbit); -} - -void -xbow_intr_clear(int intrbit) -{ - if (xbow_intr_widget_intr_clear == NULL) - return; - - (*xbow_intr_widget_intr_clear)(intrbit); -} - -void -xbow_intr_set(int intrbit) -{ - if (xbow_intr_widget_intr_set == NULL) - return; - - (*xbow_intr_widget_intr_set)(intrbit); -} - -/* - * Widget mapping code. - */ - -paddr_t -xbow_widget_map_space(struct device *dev, u_int widget, bus_addr_t *offs, - bus_size_t *len) -{ - struct xbow_softc *sc = (struct xbow_softc *)dev; - - if (xbow_widget_map == NULL) - return 0UL; - - return (*xbow_widget_map)(sc->sc_nasid, widget, offs, len); -} diff --git a/sys/arch/sgi/xbow/xbow.h b/sys/arch/sgi/xbow/xbow.h deleted file mode 100644 index 6d921cb2d3b..00000000000 --- a/sys/arch/sgi/xbow/xbow.h +++ /dev/null @@ -1,132 +0,0 @@ -/* $OpenBSD: xbow.h,v 1.12 2011/04/17 17:44:24 miod Exp $ */ - -/* - * Copyright (c) 2008 Miodrag Vallat. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _XBOW_H_ -#define _XBOW_H_ - -/* - * Devices connected to the XBow are called ``widgets'' and are - * identified by a common widget memory area at the beginning of their - * memory space. - * - * Each widget has its own memory space. The lowest 16MB are always - * accessible as a so-called ``short window''. Other `views' of the - * widget are possible, depending on the system (the whole widget - * address space is always visible on Octane, while Origin family - * systems can only map a few ``large windows'', which are a scarce - * resource). - * - * Apart from the crossbow itself being widget #0, the widgets are divided - * in two groups: widgets #8 to #b are the ``upper'' widgets, while widgets - * #c to #f are the ``lower'' widgets. - * - * Widgets are uniquely identified with their widget number on the XBow - * bus. However, the way they are mapped and accessed will depend on the - * processor (well, the processor board node) requesting access. Hence the - * two parameters needed to map a widget. - */ - -extern paddr_t (*xbow_widget_base)(int16_t, u_int); -extern paddr_t (*xbow_widget_map)(int16_t, u_int, bus_addr_t *, bus_size_t *); - -extern int (*xbow_widget_id)(int16_t, u_int, uint32_t *); - -extern int (*xbow_intr_widget_intr_register)(int, int, int *); -extern int (*xbow_intr_widget_intr_establish)(int (*)(void *), void *, - int, int, const char *, struct intrhand *); -extern void (*xbow_intr_widget_intr_disestablish)(int); - -extern void (*xbow_intr_widget_intr_set)(int); -extern void (*xbow_intr_widget_intr_clear)(int); - -/* - * Valid widget values - */ - -#define WIDGET_MIN 8 -#define WIDGET_MAX 15 - -/* interrupt register address on the master hub */ -extern uint64_t xbow_intr_address; - -struct xbow_attach_args { - int16_t xaa_nasid; - int xaa_widget; - - uint32_t xaa_vendor; - uint32_t xaa_product; - uint32_t xaa_revision; - - bus_space_tag_t xaa_iot; - /* - * WARNING! xaa_iot points to memory allocated on the stack, - * drivers need to make a copy of it. - */ -}; - -void xbow_build_bus_space(struct mips_bus_space *, int, int); -int xbow_intr_register(int, int, int *); -int xbow_intr_establish(int (*)(void *), void *, int, int, const char *, - struct intrhand *); -void xbow_intr_disestablish(int); -void xbow_intr_clear(int); -void xbow_intr_set(int); - -paddr_t xbow_widget_map_space(struct device *, u_int, - bus_addr_t *, bus_size_t *); - -int xbow_space_map(bus_space_tag_t, bus_addr_t, bus_size_t, int, - bus_space_handle_t *); -uint8_t xbow_read_1(bus_space_tag_t, bus_space_handle_t, bus_size_t); -uint16_t xbow_read_2(bus_space_tag_t, bus_space_handle_t, bus_size_t); -void xbow_read_raw_2(bus_space_tag_t, bus_space_handle_t, bus_addr_t, - uint8_t *, bus_size_t); -void xbow_write_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, uint8_t); -void xbow_write_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, - uint16_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/xbowdevs b/sys/arch/sgi/xbow/xbowdevs deleted file mode 100644 index be568290122..00000000000 --- a/sys/arch/sgi/xbow/xbowdevs +++ /dev/null @@ -1,80 +0,0 @@ -$OpenBSD: xbowdevs,v 1.6 2009/10/15 23:42:43 miod Exp $ -/* - * Copyright (c) 2008 Miodrag Vallat. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -vendor SGI 0x0000 -vendor SGI2 0x0023 -vendor SGI3 0x0024 -vendor SGI4 0x0036 -vendor SGI5 0x02aa - -/* - * List of known products. Grouped by type. - */ - -/* - * Crossbows - */ - -product SGI XBOW 0x0000 XBow -product SGI XXBOW 0xd000 XXBow -product SGI PXBOW 0xd100 PXBow - -/* - * Frame buffers and graphics related devices - */ - -product SGI5 IMPACT 0xc003 ImpactSR -product SGI2 ODYSSEY 0xc013 Odyssey -product SGI5 KONA 0xc102 Kona -product SGI3 TPU 0xc202 TPU - -/* - * Non-XIO bus bridges - */ - -product SGI4 BRIDGE 0xc002 Bridge -product SGI3 XBRIDGE 0xd002 XBridge -/* - * PIC is really a single chip but with two widgets headers, and 4 PCI-X - * slots per widget. - * The second widget register set uses 0xd112 as the product id. - */ -product SGI3 PIC 0xd102 PIC -/* - * TIO apparently is a next-generation XIO framework; TIO:CP being a TIO - * variant of PIC with two PCI-X buses, and TIO:CA an AGP bridge. - * Unlike PIC, the two heads of TIO:CP would appear as two distinct TIO - * widgets. - * TIO widgets are supposedly only found on SN2 systems onwards (i.e. - * ia64-based Altix systems), but in case there is a way to connect TIO - * nodes to XIO nodes, better identify them properly. - */ -product SGI3 TIOCP0 0xe000 TIO:CP -product SGI3 TIOCP1 0xe010 TIO:CP -product SGI3 TIOCA 0xe020 TIO:CA - -/* - * Octane HEART memory and interrupt controller - */ -product SGI4 HEART 0xc001 Heart - -/* - * Miscellaneous widgets - */ - -product SGI4 HUB 0xc101 Hub -product SGI4 BEDROCK 0xc110 Bedrock diff --git a/sys/arch/sgi/xbow/xbowdevs.h b/sys/arch/sgi/xbow/xbowdevs.h deleted file mode 100644 index c2d6b3a4189..00000000000 --- a/sys/arch/sgi/xbow/xbowdevs.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT. - * - * generated from: - * OpenBSD: xbowdevs,v 1.6 2009/10/15 23:42:43 miod Exp - */ -/* - * Copyright (c) 2008 Miodrag Vallat. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#define XBOW_VENDOR_SGI 0x0000 -#define XBOW_VENDOR_SGI2 0x0023 -#define XBOW_VENDOR_SGI3 0x0024 -#define XBOW_VENDOR_SGI4 0x0036 -#define XBOW_VENDOR_SGI5 0x02aa - -/* - * List of known products. Grouped by type. - */ - -/* - * Crossbows - */ - -#define XBOW_PRODUCT_SGI_XBOW 0x0000 /* XBow */ -#define XBOW_PRODUCT_SGI_XXBOW 0xd000 /* XXBow */ -#define XBOW_PRODUCT_SGI_PXBOW 0xd100 /* PXBow */ - -/* - * Frame buffers and graphics related devices - */ - -#define XBOW_PRODUCT_SGI5_IMPACT 0xc003 /* ImpactSR */ -#define XBOW_PRODUCT_SGI2_ODYSSEY 0xc013 /* Odyssey */ -#define XBOW_PRODUCT_SGI5_KONA 0xc102 /* Kona */ -#define XBOW_PRODUCT_SGI3_TPU 0xc202 /* TPU */ - -/* - * Non-XIO bus bridges - */ - -#define XBOW_PRODUCT_SGI4_BRIDGE 0xc002 /* Bridge */ -#define XBOW_PRODUCT_SGI3_XBRIDGE 0xd002 /* XBridge */ -/* - * PIC is really a single chip but with two widgets headers, and 4 PCI-X - * slots per widget. - * The second widget register set uses 0xd112 as the product id. - */ -#define XBOW_PRODUCT_SGI3_PIC 0xd102 /* PIC */ -/* - * TIO apparently is a next-generation XIO framework; TIO:CP being a TIO - * variant of PIC with two PCI-X buses, and TIO:CA an AGP bridge. - * Unlike PIC, the two heads of TIO:CP would appear as two distinct TIO - * widgets. - * TIO widgets are supposedly only found on SN2 systems onwards (i.e. - * ia64-based Altix systems), but in case there is a way to connect TIO - * nodes to XIO nodes, better identify them properly. - */ -#define XBOW_PRODUCT_SGI3_TIOCP0 0xe000 /* TIO:CP */ -#define XBOW_PRODUCT_SGI3_TIOCP1 0xe010 /* TIO:CP */ -#define XBOW_PRODUCT_SGI3_TIOCA 0xe020 /* TIO:CA */ - -/* - * Octane HEART memory and interrupt controller - */ -#define XBOW_PRODUCT_SGI4_HEART 0xc001 /* Heart */ - -/* - * Miscellaneous widgets - */ - -#define XBOW_PRODUCT_SGI4_HUB 0xc101 /* Hub */ -#define XBOW_PRODUCT_SGI4_BEDROCK 0xc110 /* Bedrock */ diff --git a/sys/arch/sgi/xbow/xbowdevs_data.h b/sys/arch/sgi/xbow/xbowdevs_data.h deleted file mode 100644 index a6553a06856..00000000000 --- a/sys/arch/sgi/xbow/xbowdevs_data.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT. - * - * generated from: - * OpenBSD: xbowdevs,v 1.6 2009/10/15 23:42:43 miod Exp - */ - -/* - * Copyright (c) 2008 Miodrag Vallat. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - - -/* Descriptions of known devices. */ -struct xbow_product { - uint32_t vendor; - uint32_t product; - const char *productname; -}; - -static const struct xbow_product xbow_products[] = { - { - XBOW_VENDOR_SGI, XBOW_PRODUCT_SGI_XBOW, - "XBow", - }, - { - XBOW_VENDOR_SGI, XBOW_PRODUCT_SGI_XXBOW, - "XXBow", - }, - { - XBOW_VENDOR_SGI, XBOW_PRODUCT_SGI_PXBOW, - "PXBow", - }, - { - XBOW_VENDOR_SGI5, XBOW_PRODUCT_SGI5_IMPACT, - "ImpactSR", - }, - { - XBOW_VENDOR_SGI2, XBOW_PRODUCT_SGI2_ODYSSEY, - "Odyssey", - }, - { - XBOW_VENDOR_SGI5, XBOW_PRODUCT_SGI5_KONA, - "Kona", - }, - { - XBOW_VENDOR_SGI3, XBOW_PRODUCT_SGI3_TPU, - "TPU", - }, - { - XBOW_VENDOR_SGI4, XBOW_PRODUCT_SGI4_BRIDGE, - "Bridge", - }, - { - XBOW_VENDOR_SGI3, XBOW_PRODUCT_SGI3_XBRIDGE, - "XBridge", - }, - { - XBOW_VENDOR_SGI3, XBOW_PRODUCT_SGI3_PIC, - "PIC", - }, - { - XBOW_VENDOR_SGI3, XBOW_PRODUCT_SGI3_TIOCP0, - "TIO:CP", - }, - { - XBOW_VENDOR_SGI3, XBOW_PRODUCT_SGI3_TIOCP1, - "TIO:CP", - }, - { - XBOW_VENDOR_SGI3, XBOW_PRODUCT_SGI3_TIOCA, - "TIO:CA", - }, - { - XBOW_VENDOR_SGI4, XBOW_PRODUCT_SGI4_HEART, - "Heart", - }, - { - XBOW_VENDOR_SGI4, XBOW_PRODUCT_SGI4_HUB, - "Hub", - }, - { - XBOW_VENDOR_SGI4, XBOW_PRODUCT_SGI4_BEDROCK, - "Bedrock", - }, - { 0, 0, NULL, } -}; - diff --git a/sys/arch/sgi/xbow/xbridge.c b/sys/arch/sgi/xbow/xbridge.c deleted file mode 100644 index 3782fd740b7..00000000000 --- a/sys/arch/sgi/xbow/xbridge.c +++ /dev/null @@ -1,3596 +0,0 @@ -/* $OpenBSD: xbridge.c,v 1.104 2021/03/21 14:18:37 visa Exp $ */ - -/* - * Copyright (c) 2008, 2009, 2011 Miodrag Vallat. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * XBow Bridge (as well as XBridge and PIC) Widget driver. - */ - -/* - * IMPORTANT AUTHOR'S NOTE: I did not write any of this code under the - * influence of drugs. Looking back at that particular piece of hardware, - * I wonder if this hasn't been a terrible mistake. - */ - -/* - - xbridge 101 - =========== - - There are three ASIC using this model: - - - Bridge, used on Octane and maybe early Origin 200 and 2000 systems. - - XBridge, used on later Origin 200/2000 and Origin 300/3000 systems. - - PIC, used on Origin 350/3500 systems. - - (for the record, Fuel is Origin 300 like and Tezro is Origin 350 like). - - Bridge and XBridge each appear as a single widget, supporting 8 PCI devices, - while PIC appears as two contiguous widgets, each supporting 2 PCI-X devices. - -- - address space - - Each widget has a 36-bit address space. xbridge widgets only use 33 bits - though. - - On Octane systems, the whole 36 bit address space is fully available. On - all other systems, the low 16MB (24 bit) address space is always available, - and access to arbitrary areas of the address space can be achieved by - programming the Crossbow's IOTTE (I/O Translation Table Entries). - - IMPORTANT! there is a limited number of IOTTE per Crossbow: 7, of which the - seventh is used to workaround a hardware bug, leaving only 6 entries - available across all widgets. - - Each IOTTE opens a contiguous window of 28 or 29 bits, depending on the - particular system model and configuration. On Origin 300/3000 and 350/3500, - this will always be 29 bit (512MB), while on Origin 200/2000 systems, this - depends on the ``M mode vs N mode'' configuration. Most systems run in M - mode (which is the default) which also allows for 29 bit; systems in N mode - (allowing more than 64 nodes to be connected) can only provide 28 bit IOTTE - windows (256MB). - - The widget address space is as follows: - - offset size description - 0##0000##0000 0##0003##0000 registers - 0##4000##0000 0##4000##0000 PCI memory space - 1##0000##0000 1##0000##0000 PCI I/O space - - Note the PCI memory space is limited to 30 bit; this is supposedly hardware - enforced, i.e. one may set the top two bits of 32-bit memory BAR and they - would be ignored. The xbridge driver doesn't try this though (-: - - IMPORTANT! On Bridge (not XBridge) revision up to 3, the I/O space is not - available (apparently this would be because of a hardware issue in the - byteswap logic, causing it to return unpredictable values when accessing - this address range). - -- - PCI resource mapping - - Each BAR value is an offset within the memory or I/O space (with the memory - space being limited to 30 bits, or 1GB), *EXCEPT* when the value fits in one - of the ``devio'' slots. - - So now is a good time to introduce the devio. - - There are 8 devio registers, one per device; these registers contain various - device-global flags (such as byte swapping and coherency), as well as the - location of a ``devio window'' in one of the address spaces, selected on a - per-devio basis. - - The devio register only programs the upper 12 bits of the 32 window base - address, the low 20 bits being zero; the window size are fixed and depend on - the given device: devices 0 and 1 have ``large'' windows of 2MB (0020##0000), - while devices 2 to 7 have ``small'' windows of 1MB (0010##0000). - - Apparently there are some hidden rules about the upper 12 bits, though, and - the rules differ on Octane vs Origin systems. - - This is why the address space, from the pci driver point of view, is split - in three parts: there is the ``devio black hole'' where we must make sure - that no BAR allocation crosses a devio boundary, and the rest of the address - space (under the devio zone and above it). - - I am slowly moving away from the devio mappings the PROM leaves us in, and - eventually I expect to be able to have more flexibility in their position. - However there is the console uart mapping I don't want to change now, and - - of course - we inherit it from the prom as a devio register for the IOC3 or - IOC4 device. - - So currently, the extents I provide the MI code with span the 0->ffff##ffff - address space, with only the following areas available: - - each devio range, if configured for the given address space - - on Octane, the whole memory or I/O space minus the 16MB area in which all - devio mappings take place - - on Origin, if we have an IOTTE mapping a part of the memory or I/O address - space, the whole window minus the 16MB area in which all devio mappings - take place. - - Now I need to make sure that the MI code will never allocate mappings - crossing devio ranges. So during the Bridge setup, I am initializing - ALL BAR on a device-by-device basis, working with smaller extents: - - if the device can have all its resources of a given type (I/O or mem) - fitting in a devio area, I configure a devio, and make it allocate from - an extent spanning only the devio range. - - if there are not enough devio (because the device might need two devio - ranges, one for I/O resources and one for memory resources, and there are - only 8 devio, and if the bus is populated there might not be enough unused - devio slots to hijack), then allocation is done on the larger address space - (granted on Octane, or provided with an IOTTE window on Origin), using an - extent covering this area minus the 16MB area in which all devio mappings - take place. - So in either case, I am now sure that there are no resources crossing the - devio boundaries, which are invisible to the MI code. - - This also explains why I am making sure that the devio ranges are close to - each other - it makes the creation of the temporary resource extents simpler - (bear in mind that a device might need resources from the IOTTE window before - all devio ranges are set up). - - And of course to make things even less simple, the IOTTE allocation may fail - (e.g. on a P-Brick with 6 XBridge chips on the same Crossbow), and if we are - using an old revision Bridge, all I/O resources need to be allocated with - devio (so we can't decide to get rid of them anyway). - - So, when it's time to configure further devices (for ppb and pccbb), I need - the same trick to prevent resource allocation to cross devio boundaries. - - Actually, as far as pccbb is concerned, I give up entirely on resources if - all I have is a devio to map within - at least for now, because the devio do - not cover the 0000..ffff range in I/O space needed for pcmcia. So for the - I/O resources, I give rbus the low 16 bits of the I/O extent (if available); - as for the memory resources, I need to exclude the devio area, and since rbus - currently only supports a single contiguous area, I give it the area starting - after the devio range (which is, by far, the largest part of the - at-least-256MB region). - - Do you need aspirin yet? - -- - DMA - - Device DMA addresses can be constructed in three ways: - - direct 64 bit address - - 32 bit address within a programmable 31 bit ``direct DMA'' window - - 32 bit translated address using ATE (Address Translation Entries) - - direct 64 bit address: - These are easy to construct (pick your memory address, set bit 56, and - you're done), but these can only work with pci devices aware of 64 bit - addresses. - - direct DMA window: - There is a Bridge global register to define the base address of the window, - and then we have 2GB available. This is what I am currently using, and - convenient for PCI devices unable to use 64 bit DMA addresses. - - translated DMA: - There is another 2GB window in which accesses are indirected through ATE, - which can point anywhere in memory. - - ATE are IOMMU translation entries. PCI addresses in the translated window - transparently map to the address their ATE point to. - - Bridge chip have 128 so-called `internal' entries, and can use their - optional `external' SSRAM to provide more (up to 65536 entries with 512KB - SSRAM). However, due to chip bugs, those `external' entries can not be - updated while there is DMA in progress using external entries, even if the - updated entries are not related to those used by the DMA transfer. - - XBridge chip extend the internal entries to 1024, but do not provide - support for external entries. - - All ATE share the same page size, which is configurable as 4KB or 16KB. - - Due to the small number of ATE entries, and since you can not use part of - the system's RAM to add entries as you need them (unlike hppa or sparc64), - the driver no longer uses them, as there is nothing we can do when we run - out of ATE. - -- - interrupts - - This is easy, for a change. There are 8 interrupt sources, one per device; - pins A and C map of devices 0-7 map to interrupt sources 0-7, and pins B and - D of devices 0-7 map to interrupt sources 4-7 then 0-3 (i.e. device# ^ 4). - - All interrupts occurring on the Bridge cause an XIO interrupt packet to be - sent to the XIO interrupt address programmed at Bridge initialization time; - packets can be configured as self-clearing or not on an interrupt source - basis. - - Due to silicon bugs, interrupts can be lost if two interrupt sources - interrupt within a too short interval; there is a documented workaround for - this which consists of recognizing this situation and self-inflicting - ourselves the lost interrupt (see details in xbridge_intr_handler() ). - -- - endianness - - Endianness control is quite finegrained and quite complex at first glance: - - memory and I/O accesses not occurring within devio ranges have their - endianness controlled by the endianness flags in the (global) Bridge - configuration register... - - ... to which adds the per-device endianness flag in the device devio - register... - - and accesses occurring through devio register only use the - per-device devio register mentioned above, even if the devio - range is defined in a different register! - - i.e. - - devio 0 = endianness control C0, devio range R0 - devio 1 = endianness control C1, devio range R1 - global Bridge = endianness control C2 - - 1. access from device 0 to R0 uses C2^C0 - 2. access from device 0 to R1 uses C2^C0 - 3. access from device 0 outside R0 and R1 uses C2 - 4. access from device 1 to R0 uses C2^C1 - 5. access from device 1 to R1 uses C2^C1 - 6. access from device 1 outside R0 and R1 uses C1 - - (note that, the way I set up devio registers, cases 2 and 4 can never - occur if both device 0 and device 1 are present) - - Now for DMA: - - i don't remember what 64 bit DMA uses - - direct DMA (within the 2GB window) uses a per-device bit in devio - - translated DMA (using ATE) uses a per-device bit in devio if the - chip is a Bridge, while XBridge and PIC use different DMA addresses - (i.e. with a given ATE, there is one address pointing to it in - non-swapped mode, and another address pointing to it in swapped - mode). - - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/device.h> -#include <sys/evcount.h> -#include <sys/malloc.h> -#include <sys/proc.h> -#include <sys/extent.h> -#include <sys/mbuf.h> -#include <sys/mutex.h> -#include <sys/queue.h> -#include <sys/atomic.h> - -#include <machine/autoconf.h> -#include <machine/bus.h> -#include <machine/cpu.h> -#include <machine/intr.h> -#include <machine/mnode.h> - -#include <uvm/uvm_extern.h> - -#include <dev/pci/pcireg.h> -#include <dev/pci/pcivar.h> -#include <dev/pci/pcidevs.h> -#include <dev/pci/ppbreg.h> - -#include <dev/cardbus/rbus.h> - -#include <mips64/archtype.h> -#include <sgi/xbow/xbow.h> -#include <sgi/xbow/xbowdevs.h> - -#include <sgi/xbow/widget.h> -#include <sgi/xbow/xbridgereg.h> - -#ifdef TGT_OCTANE -#include <sgi/sgi/ip30.h> -#endif - -#include "cardbus.h" - -int xbridge_match(struct device *, void *, void *); -void xbridge_attach(struct device *, struct device *, void *); -int xbridge_print(void *, const char *); -int xbridge_submatch(struct device *, void *, void *); -int xbpci_match(struct device *, void *, void *); -void xbpci_attach(struct device *, struct device *, void *); -int xbpci_print(void *, const char *); - -struct xbridge_intr; - -struct xbpci_attach_args { - uint xaa_busno; - - int xaa_flags; - int16_t xaa_nasid; - int xaa_widget; - uint xaa_devio_skew; - int xaa_revision; - - bus_space_tag_t xaa_regt; - bus_addr_t xaa_offset; -}; - -struct xbpci_softc { - struct device xb_dev; - struct device *xb_bow; - - /* - * 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. - */ - uint64_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, uint64_t); - - uint xb_busno; - uint xb_nslots; - - int xb_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 */ -#define XF_PCIX 0x08 /* bus in PCIX mode */ - int16_t xb_nasid; - int xb_widget; - uint xb_devio_skew; /* upper bits of devio ARCS mappings */ - int xb_revision; - - struct mips_pci_chipset xb_pc; - - bus_space_tag_t xb_regt; - bus_space_handle_t xb_regh; - - struct mips_bus_space *xb_mem_bus_space; - struct mips_bus_space *xb_mem_bus_space_sw; - struct mips_bus_space *xb_io_bus_space; - struct mips_bus_space *xb_io_bus_space_sw; - struct machine_bus_dma_tag *xb_dmat; - - struct xbridge_intr *xb_intr[BRIDGE_NINTRS]; - char xb_intrstr[BRIDGE_NINTRS][sizeof("irq #, xbow irq ###")]; - - int xb_err_intrsrc; - int (*xb_pci_intr_handler)(void *); - - uint64_t xb_ier; /* copy of BRIDGE_IER value */ - - /* - * Device information. - */ - struct { - pcireg_t id; - uint32_t devio; - } xb_devices[MAX_SLOTS]; - uint xb_devio_usemask; - - /* - * Large resource view sizes - */ - 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 xb_ioexname[32]; - struct extent *xb_ioex; - char xb_memexname[32]; - struct extent *xb_memex; -}; - -struct xbridge_softc { - struct device sc_dev; - uint sc_nbuses; - - struct mips_bus_space sc_regt; -}; - -#define DEVNAME(xb) ((xb)->xb_dev.dv_xname) - -#define PCI_ID_EMPTY PCI_ID_CODE(PCI_VENDOR_INVALID, 0xffff); -#define SLOT_EMPTY(xb,dev) \ - (PCI_VENDOR((xb)->xb_devices[dev].id) == PCI_VENDOR_INVALID || \ - PCI_VENDOR((xb)->xb_devices[dev].id) == 0) - -const struct cfattach xbridge_ca = { - sizeof(struct xbridge_softc), xbridge_match, xbridge_attach -}; - -struct cfdriver xbridge_cd = { - NULL, "xbridge", DV_DULL -}; - -const struct cfattach xbpci_ca = { - sizeof(struct xbpci_softc), xbpci_match, xbpci_attach -}; - -struct cfdriver xbpci_cd = { - NULL, "xbpci", DV_DULL -}; - -void xbridge_attach_hook(struct device *, struct device *, - struct pcibus_attach_args *); -int xbridge_bus_maxdevs(void *, int); -pcitag_t xbridge_make_tag(void *, int, int, int); -void xbridge_decompose_tag(void *, pcitag_t, int *, int *, int *); -int xbridge_conf_size(void *, pcitag_t); -pcireg_t xbridge_conf_read(void *, pcitag_t, int); -void xbridge_conf_write(void *, pcitag_t, int, pcireg_t); -int xbridge_intr_map(struct pci_attach_args *, pci_intr_handle_t *); -const char *xbridge_intr_string(void *, pci_intr_handle_t); -void *xbridge_intr_establish(void *, pci_intr_handle_t, int, - int (*func)(void *), void *, const char *); -void xbridge_intr_disestablish(void *, void *); -int xbridge_intr_line(void *, pci_intr_handle_t); -int xbridge_ppb_setup(void *, pcitag_t, bus_addr_t *, bus_addr_t *, - bus_addr_t *, bus_addr_t *); -int xbridge_probe_device_hook(void *, struct pci_attach_args *); -void *xbridge_rbus_parent_io(struct pci_attach_args *); -void *xbridge_rbus_parent_mem(struct pci_attach_args *); -int xbridge_get_widget(void *); -int xbridge_get_dl(void *, pcitag_t, struct sgi_device_location *); - -int xbridge_pci_intr_handler(void *); -int xbridge_picv1_pci_intr_handler(void *); -int xbridge_err_intr_handler(void *); - -uint8_t xbridge_read_1(bus_space_tag_t, bus_space_handle_t, bus_size_t); -uint16_t xbridge_read_2(bus_space_tag_t, bus_space_handle_t, bus_size_t); -void xbridge_write_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, - uint8_t); -void xbridge_write_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, - uint16_t); -void xbridge_read_raw_2(bus_space_tag_t, bus_space_handle_t, bus_addr_t, - uint8_t *, bus_size_t); -void xbridge_write_raw_2(bus_space_tag_t, bus_space_handle_t, bus_addr_t, - const uint8_t *, bus_size_t); -void xbridge_read_raw_4(bus_space_tag_t, bus_space_handle_t, bus_addr_t, - uint8_t *, bus_size_t); -void xbridge_write_raw_4(bus_space_tag_t, bus_space_handle_t, bus_addr_t, - const uint8_t *, bus_size_t); -void xbridge_read_raw_8(bus_space_tag_t, bus_space_handle_t, bus_addr_t, - uint8_t *, bus_size_t); -void xbridge_write_raw_8(bus_space_tag_t, bus_space_handle_t, bus_addr_t, - const uint8_t *, bus_size_t); - -int xbridge_space_map_devio(bus_space_tag_t, bus_addr_t, bus_size_t, int, - bus_space_handle_t *); -int xbridge_space_map_io(bus_space_tag_t, bus_addr_t, bus_size_t, int, - bus_space_handle_t *); -int xbridge_space_map_mem(bus_space_tag_t, bus_addr_t, bus_size_t, int, - bus_space_handle_t *); -int xbridge_space_region_devio(bus_space_tag_t, bus_space_handle_t, - bus_size_t, bus_size_t, bus_space_handle_t *); -int xbridge_space_region_io(bus_space_tag_t, bus_space_handle_t, - bus_size_t, bus_size_t, bus_space_handle_t *); -int xbridge_space_region_mem(bus_space_tag_t, bus_space_handle_t, - bus_size_t, bus_size_t, bus_space_handle_t *); - -void xbridge_space_barrier(bus_space_tag_t, bus_space_handle_t, - bus_size_t, bus_size_t, int); - -bus_addr_t xbridge_pa_to_device(paddr_t, int); - -int xbridge_rbus_space_map(bus_space_tag_t, bus_addr_t, bus_size_t, - int, bus_space_handle_t *); -void xbridge_rbus_space_unmap(bus_space_tag_t, bus_space_handle_t, - bus_size_t, bus_addr_t *); - -void xbridge_err_clear(struct xbpci_softc *, uint64_t); -void xbridge_err_handle(struct xbpci_softc *, uint64_t); - -int xbridge_allocate_devio(struct xbpci_softc *, int, int); -void xbridge_set_devio(struct xbpci_softc *, int, uint32_t, int); - -int xbridge_resource_explore(struct xbpci_softc *, pcitag_t, - struct extent *, struct extent *); -void xbridge_resource_manage(struct xbpci_softc *, pcitag_t, - struct extent *, struct extent *); - -void xbridge_device_setup(struct xbpci_softc *, int, int, uint32_t); -int xbridge_extent_chomp(struct xbpci_softc *, struct extent *); -void xbridge_extent_setup(struct xbpci_softc *); -struct extent * - xbridge_mapping_setup(struct xbpci_softc *, int); -void xbridge_resource_setup(struct xbpci_softc *); -void xbridge_rrb_setup(struct xbpci_softc *, int); -const char * - xbridge_setup(struct xbpci_softc *); - -uint64_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, - uint64_t); -uint64_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, - uint64_t); - -static __inline__ uint64_t -xbridge_read_reg(struct xbpci_softc *xb, bus_addr_t a) -{ - return (*xb->xb_read_reg)(xb->xb_regt, xb->xb_regh, a); -} -static __inline__ void -xbridge_write_reg(struct xbpci_softc *xb, bus_addr_t a, uint64_t v) -{ - (*xb->xb_write_reg)(xb->xb_regt, xb->xb_regh, a, v); -} - -static __inline__ void -xbridge_wbflush(struct xbpci_softc *xb, uint d) -{ - while (xbridge_read_reg(xb, BRIDGE_DEVICE_WBFLUSH(d)) != 0) ; -} - -static const struct machine_bus_dma_tag xbridge_dma_tag = { - NULL, /* _cookie */ - _dmamap_create, - _dmamap_destroy, - _dmamap_load, - _dmamap_load_mbuf, - _dmamap_load_uio, - _dmamap_load_raw, - _dmamap_load_buffer, - _dmamap_unload, - _dmamap_sync, - _dmamem_alloc, - _dmamem_free, - _dmamem_map, - _dmamem_unmap, - _dmamem_mmap, - xbridge_pa_to_device, - BRIDGE_DMA_DIRECT_LENGTH - 1 -}; - -static const struct mips_pci_chipset xbridge_pci_chipset = { - .pc_attach_hook = xbridge_attach_hook, - .pc_bus_maxdevs = xbridge_bus_maxdevs, - .pc_make_tag = xbridge_make_tag, - .pc_decompose_tag = xbridge_decompose_tag, - .pc_conf_size = xbridge_conf_size, - .pc_conf_read = xbridge_conf_read, - .pc_conf_write = xbridge_conf_write, - .pc_probe_device_hook = xbridge_probe_device_hook, - .pc_get_widget = xbridge_get_widget, - .pc_get_dl = xbridge_get_dl, - .pc_intr_map = xbridge_intr_map, - .pc_intr_string = xbridge_intr_string, - .pc_intr_establish = xbridge_intr_establish, - .pc_intr_disestablish = xbridge_intr_disestablish, - .pc_intr_line = xbridge_intr_line, - .pc_ppb_setup = xbridge_ppb_setup, -#if NCARDBUS > 0 - .pc_rbus_parent_io = xbridge_rbus_parent_io, - .pc_rbus_parent_mem = xbridge_rbus_parent_mem -#endif -}; - -/* - ********************* 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 */ - { XBOW_VENDOR_SGI3, XBOW_PRODUCT_SGI3_PIC, XF_PIC } -}; - -int -xbridge_match(struct device *parent, void *match, void *aux) -{ - struct xbow_attach_args *xaa = aux; - uint i; - - 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; -} - -void -xbridge_attach(struct device *parent, struct device *self, void *aux) -{ - struct xbridge_softc *sc = (struct xbridge_softc *)self; - struct xbow_attach_args *xaa = aux; - struct xbpci_attach_args xbpa; - int flags; - uint devio_skew; - uint i; - - printf(" revision %d\n", xaa->xaa_revision); - - for (i = 0; i < nitems(xbridge_devices); i++) - if (xaa->xaa_vendor == xbridge_devices[i].vendor && - xaa->xaa_product == xbridge_devices[i].product) { - flags = xbridge_devices[i].flags; - break; - } - - /* PICs are XBridges without an I/O window */ - if (ISSET(flags, XF_PIC)) - SET(flags, XF_XBRIDGE | XF_NO_DIRECT_IO); - /* Bridge < D lacks an I/O window */ - if (!ISSET(flags, XF_XBRIDGE) && xaa->xaa_revision < 4) - SET(flags, XF_NO_DIRECT_IO); - - /* - * Figure out where the ARCS devio mappings will go. - * ARCS configures all the devio in a contiguous 16MB area - * (i.e. the upper 8 bits of the DEVIO_BASE field of the - * devio registers are the same). - * - * In order to make our life simpler, on widgets where we may - * want to keep some of the ARCS mappings (because that's where - * our console device lives), we will use the same 16MB area. - * - * Otherwise, we can use whatever values we want; to keep the - * code simpler, we will nevertheless use a 16MB area as well, - * making sure it does not start at zero so that pcmcia bridges - * can be used. - * - * On Octane, the upper bits of ARCS mappings are zero, and thus - * point to the start of the widget. On Origin, they match the - * widget number. - */ -#ifdef TGT_OCTANE - if (sys_config.system_type == SGI_OCTANE && - xaa->xaa_widget == IP30_BRIDGE_WIDGET) - devio_skew = 0; - else -#endif - devio_skew = xaa->xaa_widget; - - sc->sc_nbuses = ISSET(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++) { - xbpa.xaa_busno = i; - xbpa.xaa_flags = flags; - xbpa.xaa_nasid = xaa->xaa_nasid; - xbpa.xaa_widget = xaa->xaa_widget; - xbpa.xaa_devio_skew = devio_skew; - xbpa.xaa_revision = xaa->xaa_revision; - xbpa.xaa_regt = &sc->sc_regt; - xbpa.xaa_offset = i != 0 ? BRIDGE_BUS_OFFSET : 0; - - config_found_sm(&sc->sc_dev, &xbpa, xbridge_print, - xbridge_submatch); - } -} - -int -xbridge_submatch(struct device *parent, void *vcf, void *aux) -{ - struct cfdata *cf = vcf; - struct xbpci_attach_args *xaa = aux; - - if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != xaa->xaa_busno) - return 0; - - return (*cf->cf_attach->ca_match)(parent, vcf, aux); -} - -int -xbridge_print(void *aux, const char *pnp) -{ - struct xbpci_attach_args *xaa = aux; - - if (pnp) - printf("xbpci at %s", pnp); - printf(" bus %d", xaa->xaa_busno); - - return UNCONF; -} - -int -xbpci_match(struct device *parent, void *vcf, void *aux) -{ - return 1; -} - -void -xbpci_attach(struct device *parent, struct device *self, void *aux) -{ - struct xbpci_softc *xb = (struct xbpci_softc *)self; - struct xbpci_attach_args *xaa = (struct xbpci_attach_args *)aux; - struct pcibus_attach_args pba; - const char *errmsg = NULL; - - printf(": "); - - /* xbow -> xbridge -> xbpci: xbow device is our grandfather */ - xb->xb_bow = parent->dv_parent; - xb->xb_busno = xaa->xaa_busno; - xb->xb_flags = xaa->xaa_flags; - xb->xb_nasid = xaa->xaa_nasid; - xb->xb_widget = xaa->xaa_widget; - xb->xb_devio_skew = xaa->xaa_devio_skew; - xb->xb_revision = xaa->xaa_revision; - - if (ISSET(xb->xb_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; - } - - /* - * Revision 1 of PIC requires a wrapper around - * xbridge_pci_intr_handler(). - */ - if (ISSET(xb->xb_flags, XF_PIC) && xb->xb_revision <= 1) - xb->xb_pci_intr_handler = xbridge_picv1_pci_intr_handler; - else - xb->xb_pci_intr_handler = xbridge_pci_intr_handler; - - /* - * Map Bridge registers. - */ - - xb->xb_regt = xaa->xaa_regt; - if (bus_space_map(xaa->xaa_regt, xaa->xaa_offset, - BRIDGE_REGISTERS_SIZE, 0, &xb->xb_regh)) { - printf("unable to map control registers\n"); - return; - } - - /* - * Create bus_space accessors... we inherit them from xbow, but - * need to overwrite mapping routines, and set up byteswapping - * versions. - */ - - xb->xb_mem_bus_space = malloc(sizeof (*xb->xb_mem_bus_space), - M_DEVBUF, M_NOWAIT); - xb->xb_mem_bus_space_sw = malloc(sizeof (*xb->xb_mem_bus_space_sw), - M_DEVBUF, M_NOWAIT); - xb->xb_io_bus_space = malloc(sizeof (*xb->xb_io_bus_space), - M_DEVBUF, M_NOWAIT); - xb->xb_io_bus_space_sw = malloc(sizeof (*xb->xb_io_bus_space_sw), - M_DEVBUF, M_NOWAIT); - if (xb->xb_mem_bus_space == NULL || xb->xb_mem_bus_space_sw == NULL || - xb->xb_io_bus_space == NULL || xb->xb_io_bus_space_sw == NULL) - goto fail1; - - bcopy(xb->xb_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_barrier = xbridge_space_barrier; - - bcopy(xb->xb_mem_bus_space, xb->xb_mem_bus_space_sw, - sizeof(*xb->xb_mem_bus_space)); - xb->xb_mem_bus_space_sw->_space_read_1 = xbridge_read_1; - xb->xb_mem_bus_space_sw->_space_write_1 = xbridge_write_1; - xb->xb_mem_bus_space_sw->_space_read_2 = xbridge_read_2; - xb->xb_mem_bus_space_sw->_space_write_2 = xbridge_write_2; - xb->xb_mem_bus_space_sw->_space_read_raw_2 = xbridge_read_raw_2; - xb->xb_mem_bus_space_sw->_space_write_raw_2 = xbridge_write_raw_2; - xb->xb_mem_bus_space_sw->_space_read_raw_4 = xbridge_read_raw_4; - xb->xb_mem_bus_space_sw->_space_write_raw_4 = xbridge_write_raw_4; - xb->xb_mem_bus_space_sw->_space_read_raw_8 = xbridge_read_raw_8; - xb->xb_mem_bus_space_sw->_space_write_raw_8 = xbridge_write_raw_8; - - bcopy(xb->xb_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_barrier = xbridge_space_barrier; - - bcopy(xb->xb_io_bus_space, xb->xb_io_bus_space_sw, - sizeof(*xb->xb_io_bus_space)); - xb->xb_io_bus_space_sw->_space_read_1 = xbridge_read_1; - xb->xb_io_bus_space_sw->_space_write_1 = xbridge_write_1; - xb->xb_io_bus_space_sw->_space_read_2 = xbridge_read_2; - xb->xb_io_bus_space_sw->_space_write_2 = xbridge_write_2; - xb->xb_io_bus_space_sw->_space_read_raw_2 = xbridge_read_raw_2; - xb->xb_io_bus_space_sw->_space_write_raw_2 = xbridge_write_raw_2; - xb->xb_io_bus_space_sw->_space_read_raw_4 = xbridge_read_raw_4; - xb->xb_io_bus_space_sw->_space_write_raw_4 = xbridge_write_raw_4; - xb->xb_io_bus_space_sw->_space_read_raw_8 = xbridge_read_raw_8; - xb->xb_io_bus_space_sw->_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 fail1; - memcpy(xb->xb_dmat, &xbridge_dma_tag, sizeof(*xb->xb_dmat)); - xb->xb_dmat->_cookie = xb; - - /* - * Initialize PCI methods. - */ - - bcopy(&xbridge_pci_chipset, &xb->xb_pc, sizeof(xbridge_pci_chipset)); - xb->xb_pc.pc_conf_v = xb; - xb->xb_pc.pc_intr_v = xb; - - /* - * Configure Bridge for proper operation (DMA, I/O mappings, - * RRB allocation, etc). - */ - - if ((errmsg = xbridge_setup(xb)) != NULL) - goto fail2; - printf("\n"); - - /* - * Attach children. - */ - - xbridge_extent_setup(xb); - - bzero(&pba, sizeof(pba)); - pba.pba_busname = "pci"; - /* - * XXX pba_iot and pba_memt ought to be irrelevant, since we - * XXX return the tags a device needs in probe_device_hook(); - * XXX however the pci(4) device needs a valid pba_memt for the - * XXX PCIOCGETROM* ioctls. - * XXX - * XXX Since most devices will need the byteswap tags, and those - * XXX which don't do not have PCI roms, let's pass the byteswap - * XXX versions by default. - */ - pba.pba_iot = xb->xb_io_bus_space_sw; - pba.pba_memt = xb->xb_mem_bus_space_sw; - pba.pba_dmat = xb->xb_dmat; - pba.pba_ioex = xb->xb_ioex; - pba.pba_memex = xb->xb_memex; -#ifdef DEBUG - if (xb->xb_ioex != NULL) - extent_print(xb->xb_ioex); - if (xb->xb_memex != NULL) - extent_print(xb->xb_memex); -#endif - pba.pba_pc = &xb->xb_pc; - pba.pba_domain = pci_ndomains++; - pba.pba_bus = 0; - - config_found(self, &pba, xbpci_print); - return; - -fail2: - free(xb->xb_dmat, M_DEVBUF, 0); -fail1: - free(xb->xb_io_bus_space_sw, M_DEVBUF, - sizeof (*xb->xb_io_bus_space_sw)); - free(xb->xb_io_bus_space, M_DEVBUF, sizeof (*xb->xb_io_bus_space)); - free(xb->xb_mem_bus_space_sw, M_DEVBUF, - sizeof (*xb->xb_mem_bus_space_sw)); - free(xb->xb_mem_bus_space, M_DEVBUF, sizeof (*xb->xb_mem_bus_space)); - if (errmsg == NULL) - errmsg = "not enough memory to build bus access structures"; - printf("%s\n", errmsg); -} - -int -xbpci_print(void *aux, const char *pnp) -{ - struct pcibus_attach_args *pba = aux; - - if (pnp) - printf("%s at %s", pba->pba_busname, pnp); - printf(" bus %d", pba->pba_bus); - - return UNCONF; -} - -/* - ********************* PCI glue. - */ - -void -xbridge_attach_hook(struct device *parent, struct device *self, - struct pcibus_attach_args *pba) -{ -} - -pcitag_t -xbridge_make_tag(void *cookie, int bus, int dev, int func) -{ - return (bus << 16) | (dev << 11) | (func << 8); -} - -void -xbridge_decompose_tag(void *cookie, pcitag_t tag, int *busp, int *devp, - int *funcp) -{ - if (busp != NULL) - *busp = (tag >> 16) & 0xff; - if (devp != NULL) - *devp = (tag >> 11) & 0x1f; - if (funcp != NULL) - *funcp = (tag >> 8) & 0x7; -} - -int -xbridge_bus_maxdevs(void *cookie, int busno) -{ - struct xbpci_softc *xb = cookie; - - return busno == 0 ? xb->xb_nslots : 32; -} - -int -xbridge_conf_size(void *cookie, pcitag_t tag) -{ -#if 0 - struct xbpci_softc *xb = cookie; - int bus, dev, fn; - - xbridge_decompose_tag(cookie, tag, &bus, &dev, &fn); - - /* - * IOC3 devices only implement a subset of the PCI configuration - * registers. Although xbridge_conf_{read,write} correctly - * handle the unimplemented registers, better provide a limited - * configuration space to userland. - */ - - if (bus == 0 && xb->xb_devices[dev].id == - PCI_ID_CODE(PCI_VENDOR_SGI, PCI_PRODUCT_SGI_IOC3)) - return PCI_INTERRUPT_REG + 4; -#endif - - return PCI_CONFIG_SPACE_SIZE; -} - -pcireg_t -xbridge_conf_read(void *cookie, pcitag_t tag, int offset) -{ - struct xbpci_softc *xb = cookie; - pcireg_t data; - int bus, dev, fn; - paddr_t pa; - int skip; - int s; - - xbridge_decompose_tag(cookie, tag, &bus, &dev, &fn); - - /* - * IOC3 devices only implement a subset of the PCI configuration - * registers (supposedly only the first 0x20 bytes, however - * writing to the second BAR also writes to the first). - * - * Depending on which particular model we encounter, things may - * seem to work, or write access to nonexisting registers would - * completely freeze the machine. - * - * We thus check for the device type here, and handle the non - * existing registers ourselves. - */ - - skip = 0; - if (bus == 0 && xb->xb_devices[dev].id == - PCI_ID_CODE(PCI_VENDOR_SGI, PCI_PRODUCT_SGI_IOC3)) { - switch (offset) { - case PCI_ID_REG: - case PCI_COMMAND_STATUS_REG: - case PCI_CLASS_REG: - case PCI_BHLC_REG: - case PCI_MAPREG_START: - /* These registers are implemented. Go ahead. */ - break; - case PCI_INTERRUPT_REG: - /* This register is not implemented. Fake it. */ - data = (PCI_INTERRUPT_PIN_A << - PCI_INTERRUPT_PIN_SHIFT) | - (dev << PCI_INTERRUPT_LINE_SHIFT); - skip = 1; - break; - default: - /* These registers are not implemented. */ - data = 0; - skip = 1; - break; - } - } - - if (skip == 0) { - /* - * Disable interrupts on this bridge (especially error - * interrupts). - */ - s = splhigh(); - xbridge_write_reg(xb, BRIDGE_IER, 0); - (void)xbridge_read_reg(xb, WIDGET_TFLUSH); - - if (bus != 0) { - xbridge_write_reg(xb, BRIDGE_PCI_CFG, - (bus << 16) | (dev << 11)); - pa = xb->xb_regh + BRIDGE_PCI_CFG1_SPACE; - } else { - /* - * On PIC, device 0 in configuration space is the - * PIC itself, device slots are offset by one. - */ - if (ISSET(xb->xb_flags, XF_PIC)) - dev++; - pa = xb->xb_regh + BRIDGE_PCI_CFG_SPACE + (dev << 12); - } - - pa += (fn << 8) + offset; - if (guarded_read_4(pa, &data) != 0) - data = 0xffffffff; - - xbridge_write_reg(xb, BRIDGE_IER, xb->xb_ier); - (void)xbridge_read_reg(xb, WIDGET_TFLUSH); - splx(s); - } - - return data; -} - -void -xbridge_conf_write(void *cookie, pcitag_t tag, int offset, pcireg_t data) -{ - struct xbpci_softc *xb = cookie; - int bus, dev, fn; - paddr_t pa; - int skip; - int s; - - xbridge_decompose_tag(cookie, tag, &bus, &dev, &fn); - - /* - * IOC3 devices only implement a subset of the PCI configuration - * registers. - * Depending on which particular model we encounter, things may - * seem to work, or write access to nonexisting registers would - * completely freeze the machine. - * - * We thus check for the device type here, and handle the non - * existing registers ourselves. - */ - - skip = 0; - 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: - /* - * Some IOC3 models do not support having this bit - * cleared (which is what pci_mapreg_probe() will - * do), so we set it unconditionally. - */ - data |= PCI_COMMAND_MEM_ENABLE; - /* FALLTHROUGH */ - case PCI_ID_REG: - case PCI_CLASS_REG: - case PCI_BHLC_REG: - case PCI_MAPREG_START: - /* These registers are implemented. Go ahead. */ - break; - default: - /* These registers are not implemented. */ - skip = 1; - break; - } - } - - if (skip == 0) { - /* - * Disable interrupts on this bridge (especially error - * interrupts). - */ - s = splhigh(); - xbridge_write_reg(xb, BRIDGE_IER, 0); - (void)xbridge_read_reg(xb, WIDGET_TFLUSH); - - if (bus != 0) { - xbridge_write_reg(xb, BRIDGE_PCI_CFG, - (bus << 16) | (dev << 11)); - pa = xb->xb_regh + BRIDGE_PCI_CFG1_SPACE; - } else { - /* - * On PIC, device 0 in configuration space is the - * PIC itself, device slots are offset by one. - */ - if (ISSET(xb->xb_flags, XF_PIC)) - dev++; - pa = xb->xb_regh + BRIDGE_PCI_CFG_SPACE + (dev << 12); - } - - pa += (fn << 8) + offset; - guarded_write_4(pa, data); - - xbridge_write_reg(xb, BRIDGE_IER, xb->xb_ier); - (void)xbridge_read_reg(xb, WIDGET_TFLUSH); - splx(s); - } -} - -int -xbridge_probe_device_hook(void *cookie, struct pci_attach_args *pa) -{ - struct xbpci_softc *xb = cookie; - - /* - * Check for the hardware byteswap setting of the device we are - * interested in, and pick bus_space_tag accordingly. - * Note that the device list here must match xbridge_resource_setup(). - */ - if (pa->pa_id == PCI_ID_CODE(PCI_VENDOR_SGI, PCI_PRODUCT_SGI_IOC3) || - pa->pa_id == PCI_ID_CODE(PCI_VENDOR_SGI, PCI_PRODUCT_SGI_IOC4) || - pa->pa_id == PCI_ID_CODE(PCI_VENDOR_SGI, PCI_PRODUCT_SGI_RAD1)) { - pa->pa_iot = xb->xb_io_bus_space; - pa->pa_memt = xb->xb_mem_bus_space; - } else { - pa->pa_iot = xb->xb_io_bus_space_sw; - pa->pa_memt = xb->xb_mem_bus_space_sw; - } - - return 0; -} - -int -xbridge_get_widget(void *cookie) -{ - struct xbpci_softc *xb = cookie; - - return xb->xb_widget; -} - -int -xbridge_get_dl(void *cookie, pcitag_t tag, struct sgi_device_location *sdl) -{ - int bus, device, fn; - struct xbpci_softc *xb = cookie; - - xbridge_decompose_tag(cookie, tag, &bus, &device, &fn); - if (bus != 0) - return 0; - - sdl->nasid = xb->xb_nasid; - sdl->widget = xb->xb_widget; - - sdl->bus = xb->xb_busno; - sdl->device = device; - sdl->fn = fn; - - return 1; -} - -/* - ********************* Interrupt handling. - */ - -/* - * We map each slot to its own interrupt bit, which will in turn be routed to - * the Heart or Hub widget in charge of interrupt processing. - */ - -struct xbridge_intrhandler { - LIST_ENTRY(xbridge_intrhandler) xih_nxt; - struct xbridge_intr *xih_main; - int (*xih_func)(void *); - void *xih_arg; - struct evcount xih_count; - int xih_flags; -#define XIH_MPSAFE 0x01 - int xih_level; - int xih_device; /* device slot number */ -}; - -struct xbridge_intr { - struct xbpci_softc *xi_bus; - int xi_intrsrc; /* interrupt source on interrupt widget */ - int xi_intrbit; /* interrupt source on BRIDGE */ - LIST_HEAD(, xbridge_intrhandler) xi_handlers; -}; - -/* how our pci_intr_handle_t are constructed... */ -#define XBRIDGE_INTR_VALID 0x100 -#define XBRIDGE_INTR_HANDLE(d,b) (XBRIDGE_INTR_VALID | ((d) << 3) | (b)) -#define XBRIDGE_INTR_DEVICE(h) (((h) >> 3) & 07) -#define XBRIDGE_INTR_BIT(h) ((h) & 07) - -int -xbridge_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) -{ - struct xbpci_softc *xb = pa->pa_pc->pc_conf_v; - int bus, device, intr; - int pin; - - *ihp = 0; - - if (pa->pa_intrpin == 0) { - /* No IRQ used. */ - return 1; - } - -#ifdef DIAGNOSTIC - if (pa->pa_intrpin > 4) { - printf("%s: bad interrupt pin %d\n", __func__, pa->pa_intrpin); - return 1; - } -#endif - - pci_decompose_tag(pa->pa_pc, pa->pa_tag, &bus, &device, NULL); - - if (pa->pa_bridgetag) { - pin = PPB_INTERRUPT_SWIZZLE(pa->pa_rawintrpin, device); - if (!ISSET(pa->pa_bridgeih[pin - 1], XBRIDGE_INTR_VALID)) - return 0; - intr = XBRIDGE_INTR_BIT(pa->pa_bridgeih[pin - 1]); - } else { - /* - * For IOC3 devices, pin A is always the regular PCI interrupt, - * but wiring of interrupt pin B may vary. - * We rely upon ioc(4) being able to figure out whether it's - * an onboard chip or not, and to require interrupt pin D - * instead of B in the former case. - */ - intr = -1; - if (xb->xb_devices[device].id == - PCI_ID_CODE(PCI_VENDOR_SGI, PCI_PRODUCT_SGI_IOC3)) { - - switch (pa->pa_intrpin) { - case PCI_INTERRUPT_PIN_A: - case PCI_INTERRUPT_PIN_B: - break; - case PCI_INTERRUPT_PIN_D: - /* - * If this device is an onboard IOC3, - * interrupt pin B is wired as pin A of - * the first empty PCI slot... - */ - for (intr = 0; intr < MAX_SLOTS; intr++) - if (SLOT_EMPTY(xb, intr)) - break; - /* should not happen, but fallback anyway */ - if (intr >= MAX_SLOTS) - intr = -1; - break; - default: - return 1; - } - } - if (intr < 0) { - if (pa->pa_intrpin & 1) - intr = device; - else - intr = device ^ 4; - } - } - - *ihp = XBRIDGE_INTR_HANDLE(device, intr); - - return 0; -} - -const char * -xbridge_intr_string(void *cookie, pci_intr_handle_t ih) -{ - struct xbpci_softc *xb = (struct xbpci_softc *)cookie; - int intrbit = XBRIDGE_INTR_BIT(ih); - - if (xb->xb_intrstr[intrbit][0] == '\0') - snprintf(xb->xb_intrstr[intrbit], - sizeof xb->xb_intrstr[intrbit], "irq %ld", ih); - return xb->xb_intrstr[intrbit]; -} - -void * -xbridge_intr_establish(void *cookie, pci_intr_handle_t ih, int level, - int (*func)(void *), void *arg, const char *name) -{ - struct xbpci_softc *xb = (struct xbpci_softc *)cookie; - struct xbridge_intr *xi; - struct xbridge_intrhandler *xih; - uint64_t int_addr; - int device = XBRIDGE_INTR_DEVICE(ih); - int intrbit = XBRIDGE_INTR_BIT(ih); - int flags; - int intrsrc; - int new; - - flags = (level & IPL_MPSAFE) ? XIH_MPSAFE : 0; - level &= ~IPL_MPSAFE; - - /* - * Allocate bookkeeping structure if this is the - * first time we're using this interrupt source. - */ - 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_bus = xb; - xi->xi_intrbit = intrbit; - LIST_INIT(&xi->xi_handlers); - - if (xbow_intr_register(xb->xb_widget, level, &intrsrc) != 0) { - free(xi, M_DEVBUF, sizeof *xi); - return NULL; - } - - xi->xi_intrsrc = intrsrc; - xb->xb_intr[intrbit] = xi; - snprintf(xb->xb_intrstr[intrbit], - sizeof xb->xb_intrstr[intrbit], - "irq %d, xbow irq %d", intrbit, intrsrc); - } else - intrsrc = xi->xi_intrsrc; - - /* - * Register the interrupt at the Heart or Hub level if this is the - * first time we're using this interrupt source. - */ - new = LIST_EMPTY(&xi->xi_handlers); - if (new) { - /* - * XXX The interrupt dispatcher is always registered - * XXX at IPL_BIO, in case the interrupt will be shared - * XXX between devices of different levels. - */ - if (xbow_intr_establish(xb->xb_pci_intr_handler, xi, intrsrc, - IPL_BIO | IPL_MPSAFE, NULL, NULL)) { - printf("%s: unable to register interrupt handler\n", - DEVNAME(xb)); - return NULL; - } - } - - xih = (struct xbridge_intrhandler *) - malloc(sizeof(*xih), M_DEVBUF, M_NOWAIT); - if (xih == NULL) - return NULL; - - xih->xih_main = xi; - xih->xih_func = func; - xih->xih_arg = arg; - xih->xih_flags = flags; - xih->xih_level = level; - xih->xih_device = device; - evcount_attach(&xih->xih_count, name, &xi->xi_intrsrc); - LIST_INSERT_HEAD(&xi->xi_handlers, xih, xih_nxt); - - if (new) { - /* - * Note that, while PIC uses a complete XIO address, - * Bridge will only store the interrupt source and high - * bits of the address, and will reuse the widget interrupt - * address for the low 38 bits of the XIO address. - */ - if (ISSET(xb->xb_flags, XF_PIC)) - int_addr = ((uint64_t)intrsrc << 48) | - (xbow_intr_address & ((1UL << 48) - 1)); - else - int_addr = ((xbow_intr_address >> 30) & - 0x0003ff00) | intrsrc; - xb->xb_ier |= 1L << intrbit; - - xbridge_write_reg(xb, BRIDGE_INT_ADDR(intrbit), int_addr); - xbridge_write_reg(xb, BRIDGE_IER, xb->xb_ier); - /* - * INT_MODE register controls which interrupt pins cause - * ``interrupt clear'' packets to be sent for high->low - * transition. - * We enable such packets to be sent in order not to have to - * clear interrupts ourselves. - */ - 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)xbridge_read_reg(xb, WIDGET_TFLUSH); - } - - return (void *)xih; -} - -void -xbridge_intr_disestablish(void *cookie, void *vih) -{ - struct xbpci_softc *xb = cookie; - struct xbridge_intrhandler *xih = (struct xbridge_intrhandler *)vih; - struct xbridge_intr *xi = xih->xih_main; - int intrbit = xi->xi_intrbit; - - evcount_detach(&xih->xih_count); - LIST_REMOVE(xih, xih_nxt); - - if (LIST_EMPTY(&xi->xi_handlers)) { - xb->xb_ier &= ~(1 << intrbit); - xbridge_write_reg(xb, BRIDGE_INT_ADDR(intrbit), 0); - xbridge_write_reg(xb, BRIDGE_IER, xb->xb_ier); - 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)xbridge_read_reg(xb, WIDGET_TFLUSH); - - xbow_intr_disestablish(xi->xi_intrsrc); - /* - * Note we could free xb->xb_intr[intrbit] at this point, - * but it's not really worth doing. - */ - } - - free(xih, M_DEVBUF, sizeof *xih); -} - -int -xbridge_intr_line(void *cookie, pci_intr_handle_t ih) -{ - return XBRIDGE_INTR_BIT(ih); -} - -int -xbridge_err_intr_handler(void *v) -{ - struct xbpci_softc *xb = (struct xbpci_softc *)v; - uint64_t isr; - - isr = xbridge_read_reg(xb, BRIDGE_ISR) & ~BRIDGE_ISR_HWINTR_MASK; - xbridge_err_handle(xb, isr); - - xbow_intr_clear(xb->xb_err_intrsrc); - - return 1; -} - -int -xbridge_pci_intr_handler(void *v) -{ - struct xbridge_intr *xi = (struct xbridge_intr *)v; - struct xbpci_softc *xb = xi->xi_bus; - struct xbridge_intrhandler *xih; - uint64_t isr; - int rc; -#ifdef MULTIPROCESSOR - int need_lock; -#endif - - /* XXX shouldn't happen, and assumes interrupt is not shared */ - if (LIST_EMPTY(&xi->xi_handlers)) { - printf("%s: spurious irq %d\n", DEVNAME(xb), xi->xi_intrbit); - return 0; - } - - /* - * Flush PCI write buffers before servicing the interrupt. - */ - LIST_FOREACH(xih, &xi->xi_handlers, xih_nxt) - xbridge_wbflush(xb, xih->xih_device); - - isr = xbridge_read_reg(xb, BRIDGE_ISR); - if ((isr & ~BRIDGE_ISR_HWINTR_MASK) != 0) { - /* - * This is an error interrupt triggered by a particular - * device. - */ - xbridge_err_handle(xb, isr & ~BRIDGE_ISR_HWINTR_MASK); - if ((isr &= BRIDGE_ISR_HWINTR_MASK) == 0) - return 1; - } - - if ((isr & (1L << xi->xi_intrbit)) == 0) { - /* - * May be a result of the lost interrupt workaround (see - * near the end of this function); don't complain in that - * case. - */ - rc = -1; -#ifdef DEBUG - printf("%s: irq %d but not pending in ISR %08llx\n", - DEVNAME(xb), xi->xi_intrbit, isr); -#endif - } else { - rc = 0; - LIST_FOREACH(xih, &xi->xi_handlers, xih_nxt) { - splraise(xih->xih_level); -#ifdef MULTIPROCESSOR - if (ISSET(xih->xih_flags, XIH_MPSAFE)) - need_lock = 0; - else - need_lock = xih->xih_flags < IPL_CLOCK; - if (need_lock) - __mp_lock(&kernel_lock); -#endif - if ((*xih->xih_func)(xih->xih_arg) != 0) { - xih->xih_count.ec_count++; - rc = 1; - } -#ifdef MULTIPROCESSOR - if (need_lock) - __mp_unlock(&kernel_lock); -#endif - /* - * No need to lower spl here, as our caller will - * lower spl upon our return. - * However that splraise() is necessary so that - * interrupt handler code calling splx() will not - * cause our interrupt source to be unmasked. - */ - } - /* XXX assumes interrupt is not shared */ - if (rc == 0) - printf("%s: spurious irq %d\n", - DEVNAME(xb), xi->xi_intrbit); - } - - /* - * There is a known BRIDGE race in which, if two interrupts - * on two different pins occur within 60nS of each other, - * further interrupts on the first pin do not cause an - * interrupt to be sent. - * - * The workaround against this is to check if our interrupt - * source is still active (i.e. another interrupt is pending), - * in which case we force an interrupt anyway. - * - * The XBridge even has a nice facility to do this, where we - * do not even have to check if our interrupt is pending. - */ - - if (ISSET(xb->xb_flags, XF_XBRIDGE)) { - xbridge_write_reg(xb, BRIDGE_INT_FORCE_PIN(xi->xi_intrbit), 1); - (void)xbridge_read_reg(xb, WIDGET_TFLUSH); - } else { - if (xbridge_read_reg(xb, BRIDGE_ISR) & (1 << xi->xi_intrbit)) - xbow_intr_set(xi->xi_intrsrc); - } - - return rc; -} - -int -xbridge_picv1_pci_intr_handler(void *v) -{ - struct xbridge_intr *xi = (struct xbridge_intr *)v; - struct xbpci_softc *xb = xi->xi_bus; - - /* - * Revision 1 of PIC is supposed to need the interrupt enable bit - * to be toggled to prevent loss of interrupt. - */ - xbridge_write_reg(xb, BRIDGE_IER, xb->xb_ier & ~(1L << xi->xi_intrbit)); - (void)xbridge_read_reg(xb, WIDGET_TFLUSH); - xbridge_write_reg(xb, BRIDGE_IER, xb->xb_ier); - (void)xbridge_read_reg(xb, WIDGET_TFLUSH); - - return xbridge_pci_intr_handler(v); -} - -/* - ********************* chip register access. - */ - -uint64_t -bridge_read_reg(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t a) -{ - return (uint64_t)widget_read_4(t, h, a); -} -void -bridge_write_reg(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t a, - uint64_t v) -{ - widget_write_4(t, h, a, (uint32_t)v); -} - -uint64_t -pic_read_reg(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t a) -{ - return widget_read_8(t, h, a); -} - -void -pic_write_reg(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t a, - uint64_t v) -{ - widget_write_8(t, h, a, v); -} - -/* - ********************* bus_space glue. - */ - -uint8_t -xbridge_read_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) -{ - return *(volatile uint8_t *)((h + o) ^ 3); -} - -uint16_t -xbridge_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) -{ - return *(volatile uint16_t *)((h + o) ^ 2); -} - -void -xbridge_write_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, - uint8_t v) -{ - *(volatile uint8_t *)((h + o) ^ 3) = v; -} - -void -xbridge_write_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, - uint16_t v) -{ - *(volatile uint16_t *)((h + o) ^ 2) = v; -} - -void -xbridge_read_raw_2(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o, - uint8_t *buf, bus_size_t len) -{ - volatile uint16_t *addr = (volatile uint16_t *)((h + o) ^ 2); - len >>= 1; - while (len-- != 0) { - *(uint16_t *)buf = letoh16(*addr); - buf += 2; - } -} - -void -xbridge_write_raw_2(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o, - const uint8_t *buf, bus_size_t len) -{ - volatile uint16_t *addr = (volatile uint16_t *)((h + o) ^ 2); - len >>= 1; - while (len-- != 0) { - *addr = htole16(*(uint16_t *)buf); - buf += 2; - } -} - -void -xbridge_read_raw_4(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o, - uint8_t *buf, bus_size_t len) -{ - volatile uint32_t *addr = (volatile uint32_t *)(h + o); - len >>= 2; - while (len-- != 0) { - *(uint32_t *)buf = letoh32(*addr); - buf += 4; - } -} - -void -xbridge_write_raw_4(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o, - const uint8_t *buf, bus_size_t len) -{ - volatile uint32_t *addr = (volatile uint32_t *)(h + o); - len >>= 2; - while (len-- != 0) { - *addr = htole32(*(uint32_t *)buf); - buf += 4; - } -} - -void -xbridge_read_raw_8(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o, - uint8_t *buf, bus_size_t len) -{ - volatile uint64_t *addr = (volatile uint64_t *)(h + o); - len >>= 3; - while (len-- != 0) { - *(uint64_t *)buf = letoh64(*addr); - buf += 8; - } -} - -void -xbridge_write_raw_8(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o, - const uint8_t *buf, bus_size_t len) -{ - volatile uint64_t *addr = (volatile uint64_t *)(h + o); - len >>= 3; - while (len-- != 0) { - *addr = htole64(*(uint64_t *)buf); - buf += 8; - } -} - -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 xbpci_softc *xb = (struct xbpci_softc *)t->bus_private; - bus_addr_t bpa; -#ifdef DIAGNOSTIC - bus_addr_t start, end; - uint d; -#endif - - if ((offs >> 24) != xb->xb_devio_skew) - return EINVAL; /* not a devio mapping */ - - /* - * Figure out which devio `slot' we are using, and make sure - * we do not overrun it. - */ - bpa = offs & ((1UL << 24) - 1); -#ifdef DIAGNOSTIC - 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) - return EINVAL; - else - break; - } - } - if (d == xb->xb_nslots) - return EINVAL; -#endif - - /* - * Note we can not use our own bus_base because it might not point - * to our small window. Instead, use the one used by the xbridge - * driver itself, which _always_ points to the short window. - */ - *bshp = xb->xb_regt->bus_base + bpa; - return 0; -} - -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 xbpci_softc *xb = (struct xbpci_softc *)t->bus_private; - - /* - * Base address is either within the devio area, or our direct - * window. - */ - - 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 < xb->xb_iostart || offs + size - 1 > xb->xb_ioend) - return EINVAL; -#endif - - *bshp = (t->bus_base + offs); - return 0; -} - -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) -{ -#if defined(TGT_ORIGIN) || defined(DIAGNOSTIC) - struct xbpci_softc *xb = (struct xbpci_softc *)t->bus_private; -#endif - - /* - * Base address is either within the devio area, or our direct - * window. Except on Octane where we never setup devio memory - * mappings, because the large mapping is always available. - */ - -#ifdef TGT_ORIGIN - if (sys_config.system_type != SGI_OCTANE && - (offs >> 24) == xb->xb_devio_skew) - return xbridge_space_map_devio(t, offs, size, flags, bshp); -#endif - -#ifdef DIAGNOSTIC - /* check that this does not overflow the mapping */ - if (offs < xb->xb_memstart || offs + size - 1 > xb->xb_memend) - return EINVAL; -#endif - - *bshp = (t->bus_base + offs); - return 0; -} - -int -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 xbpci_softc *xb = (struct xbpci_softc *)t->bus_private; - bus_addr_t bpa; - bus_addr_t start, end; - uint d; -#endif - -#ifdef DIAGNOSTIC - /* - * Note we can not use our own bus_base because it might not point - * 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 - xb->xb_regt->bus_base; - - if ((bpa >> 24) != 0) - return EINVAL; /* not a devio mapping */ - - /* - * Figure out which devio `slot' we are using, and make sure - * we do not overrun it. - */ - 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) - return EINVAL; - else - break; - } - } - if (d == xb->xb_nslots) - return EINVAL; -#endif - - *nbshp = bsh + offset; - return 0; -} - -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 xbpci_softc *xb = (struct xbpci_softc *)t->bus_private; - bus_addr_t bpa; - - /* - * Note we can not use our own bus_base because it might not point - * 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 - xb->xb_regt->bus_base; - - if ((bpa >> 24) == 0) - return xbridge_space_region_devio(t, bsh, offset, size, nbshp); - -#ifdef DIAGNOSTIC - /* check that this does not overflow the mapping */ - bpa = (bus_addr_t)bsh - t->bus_base; - if (bpa + offset + size - 1 > xb->xb_ioend) - return EINVAL; -#endif - - *nbshp = bsh + offset; - return 0; -} - -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) -{ -#if defined(TGT_ORIGIN) || defined(DIAGNOSTIC) - struct xbpci_softc *xb = (struct xbpci_softc *)t->bus_private; - bus_addr_t bpa; -#endif - - /* - * Base address is either within the devio area, or our direct - * window. Except on Octane where we never setup devio memory - * mappings, because the large mapping is always available. - */ - -#ifdef TGT_ORIGIN - if (sys_config.system_type != SGI_OCTANE) { - /* - * Note we can not use our own bus_base because it might not - * point 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 - xb->xb_regt->bus_base; - - if ((bpa >> 24) == 0) - return xbridge_space_region_devio(t, bsh, offset, size, - nbshp); - } -#endif - -#ifdef DIAGNOSTIC - /* check that this does not overflow the mapping */ - bpa = (bus_addr_t)bsh - t->bus_base; - if (bpa + offset + size - 1 > xb->xb_memend) - return EINVAL; -#endif - - *nbshp = bsh + offset; - return 0; -} - -void -xbridge_space_barrier(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offs, - bus_size_t len, int flags) -{ - struct xbpci_softc *xb = (struct xbpci_softc *)t->bus_private; - bus_addr_t bpa, start, end; - uint d, devmin, devmax; - - mips_sync(); - - if (flags & BUS_SPACE_BARRIER_WRITE) { - /* - * Try to figure out which device we are working for, and - * flush its PCI write buffer. - * This is ugly; we really need to be able to provide a - * different bus_space_tag_t to each slot, to be able - * to tell them apart. - */ - if (t->_space_map == xbridge_space_map_devio) { - bpa = (bus_addr_t)h - xb->xb_regt->bus_base; - 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) - break; - } - devmin = d; - devmax = d + 1; - /* should not happen */ - if (d == xb->xb_nslots) { - devmin = 0; - devmax = xb->xb_nslots; - } - } else { - /* nothing better came up my sleeve... */ - devmin = 0; - devmax = xb->xb_nslots; - } - for (d = devmin; d < devmax; d++) - xbridge_wbflush(xb, d); - (void)xbridge_read_reg(xb, WIDGET_TFLUSH); - } -} - -/* - ********************* bus_dma helpers - */ - -/* - * Since the common bus_dma code makes sure DMA-able memory is allocated - * within the dma_constraint limits, which are set to the direct DMA - * window, we do not need to check for addresses outside this range here. - */ - -bus_addr_t -xbridge_pa_to_device(paddr_t pa, int flags) -{ - KASSERTMSG(pa - dma_constraint.ucr_low < BRIDGE_DMA_DIRECT_LENGTH, - "pa 0x%lx not in dma constraint range! (0x%lx-0x%lx)", - pa, dma_constraint.ucr_low, dma_constraint.ucr_high); - return (pa - dma_constraint.ucr_low) + BRIDGE_DMA_DIRECT_BASE; -} - -/* - ********************* Bridge configuration code. - */ - -const char * -xbridge_setup(struct xbpci_softc *xb) -{ - bus_addr_t ba; - paddr_t pa; - uint64_t status, ctrl, int_addr, dirmap; - int mode, speed, dev; - - status = xbridge_read_reg(xb, WIDGET_STATUS); - ctrl = xbridge_read_reg(xb, WIDGET_CONTROL); - - /* - * Print bus mode and speed. - */ - - mode = ISSET(xb->xb_flags, XF_PIC) && - ISSET(status, PIC_WIDGET_STATUS_PCIX_MODE); - if (mode != 0) { - SET(xb->xb_flags, XF_PCIX); - speed = (status & PIC_WIDGET_STATUS_PCIX_SPEED_MASK) >> - PIC_WIDGET_STATUS_PCIX_SPEED_SHIFT; - } else if (ISSET(xb->xb_flags, XF_XBRIDGE)) { - speed = (ctrl & BRIDGE_WIDGET_CONTROL_SPEED_MASK) >> - BRIDGE_WIDGET_CONTROL_SPEED_SHIFT; - } else - speed = 0; - /* 0 = 33 MHz, 1 = 66 MHz, 2 = 100 MHz, 3 = 133 MHz */ - speed = (speed & 2 ? 100 : 33) + (speed & 1 ? 33 : 0); - printf("%d MHz %s bus", speed, mode ? "PCIX" : "PCI"); - - /* - * Gather device identification for all slots. - * We need this to be able to allocate RRBs correctly, and also - * to be able to check quickly whether a given device is an IOC3. - */ - - for (dev = 0; dev < xb->xb_nslots; dev++) { - if (ISSET(xb->xb_flags, XF_PIC)) - pa = xb->xb_regh + BRIDGE_PCI_CFG_SPACE + - ((dev + 1) << 12) + PCI_ID_REG; - else - pa = xb->xb_regh + BRIDGE_PCI_CFG_SPACE + - (dev << 12) + PCI_ID_REG; - if (guarded_read_4(pa, &xb->xb_devices[dev].id) != 0) - xb->xb_devices[dev].id = PCI_ID_EMPTY; - } - - /* - * Configure the direct DMA window to access the 2GB memory - * window selected as our DMA memory range. - */ - dirmap = (dma_constraint.ucr_low >> BRIDGE_DIRMAP_BASE_SHIFT) & - BRIDGE_DIRMAP_BASE_MASK; - switch (sys_config.system_type) { - default: -#ifdef TGT_ORIGIN - dirmap |= kl_hub_widget[ - IP27_PHYS_TO_NODE(dma_constraint.ucr_low)] << - BRIDGE_DIRMAP_WIDGET_SHIFT; - break; -#endif -#ifdef TGT_OCTANE - case SGI_OCTANE: - dirmap |= IP30_HEART_WIDGET << BRIDGE_DIRMAP_WIDGET_SHIFT; - break; -#endif - } - xbridge_write_reg(xb, BRIDGE_DIR_MAP, dirmap); - - /* - * Allocate RRB for the existing devices. - */ - - xbridge_rrb_setup(xb, 0); - xbridge_rrb_setup(xb, 1); - - /* - * Enable(?) snooping and disable relaxed order on PIC. - */ - - if (ISSET(xb->xb_flags, XF_PIC)) { - ctrl &= ~PIC_WIDGET_CONTROL_NO_SNOOP; - ctrl &= ~PIC_WIDGET_CONTROL_RELAX_ORDER; - } - - /* - * Disable byteswapping on PIO accesses through the large window - * (we handle this at the bus_space level). It should not have - * been enabled by ARCS, since IOC serial console relies on this, - * but better enforce this anyway. - */ - - ctrl &= ~BRIDGE_WIDGET_CONTROL_IO_SWAP; - ctrl &= ~BRIDGE_WIDGET_CONTROL_MEM_SWAP; - 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(xb); - - /* - * Older Bridge chips needs to run with pci timeouts - * disabled. - */ - - if (!ISSET(xb->xb_flags, XF_XBRIDGE) && xb->xb_revision < 4) { - xbridge_write_reg(xb, BRIDGE_BUS_TIMEOUT, - xbridge_read_reg(xb, BRIDGE_BUS_TIMEOUT) & - ~BRIDGE_BUS_PCI_RETRY_CNT_MASK); - } - - /* - * AT&T/Lucent USS-302 and USS-312 USB controllers require - * a larger PCI retry hold interval for proper operation. - */ - - for (dev = 0; dev < xb->xb_nslots; dev++) { - if (xb->xb_devices[dev].id == - PCI_ID_CODE(PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_USBHC) || - xb->xb_devices[dev].id == - PCI_ID_CODE(PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_USBHC2)) { - ctrl = xbridge_read_reg(xb, BRIDGE_BUS_TIMEOUT); - ctrl &= ~BRIDGE_BUS_PCI_RETRY_HOLD_MASK; - ctrl |= (4 << BRIDGE_BUS_PCI_RETRY_HOLD_SHIFT); - xbridge_write_reg(xb, BRIDGE_BUS_TIMEOUT, ctrl); - - break; - } - } - - /* - * Clear the write request memory in PIC, to avoid risking - * spurious parity errors if it is not clean. - */ - if (ISSET(xb->xb_flags, XF_PIC)) { - for (ba = PIC_WR_REQ_LOWER(0); - ba != PIC_WR_REQ_LOWER(PIC_WR_REQ_ENTRIES); ba += 8) - xbridge_write_reg(xb, ba, 0ULL); - for (ba = PIC_WR_REQ_UPPER(0); - ba != PIC_WR_REQ_UPPER(PIC_WR_REQ_ENTRIES); ba += 8) - xbridge_write_reg(xb, ba, 0ULL); - for (ba = PIC_WR_REQ_PARITY(0); - ba != PIC_WR_REQ_PARITY(PIC_WR_REQ_ENTRIES); ba += 8) - xbridge_write_reg(xb, ba, 0ULL); - } - - /* - * Setup interrupt handling. - * - * Note that, on PIC, the `lower address' register is a 64 bit - * register and thus need to be initialized with the whole 64 bit - * address; the `upper address' register is hardwired to zero and - * ignores writes, so we can use the same logic on Bridge and PIC. - * - * Also, on Octane, we need to keep otherwise unused interrupt source - * #6 enabled on the obio widget, as it controls routing of the - * power button interrupt (and to make things more complicated than - * necessary, this pin is wired to a particular Heart interrupt - * register bit, so interrupts on this pin will never be seen at the - * Bridge level). - */ - -#ifdef TGT_OCTANE - if (sys_config.system_type == SGI_OCTANE && - xb->xb_widget == IP30_BRIDGE_WIDGET) - xb->xb_ier = 1L << 6; - else -#endif - xb->xb_ier = 0; - xbridge_write_reg(xb, BRIDGE_IER, 0); - xbridge_write_reg(xb, BRIDGE_INT_MODE, 0); - xbridge_write_reg(xb, BRIDGE_INT_DEV, 0); - int_addr = xbow_intr_address & ((1UL << 48) - 1); - switch (sys_config.system_type) { - default: -#ifdef TGT_ORIGIN - int_addr |= (uint64_t)kl_hub_widget[masternasid] << 48; - break; -#endif -#ifdef TGT_OCTANE - case SGI_OCTANE: - int_addr |= (uint64_t)IP30_HEART_WIDGET << 48; - break; -#endif - } - xbridge_write_reg(xb, WIDGET_INTDEST_ADDR_LOWER, int_addr); - xbridge_write_reg(xb, WIDGET_INTDEST_ADDR_UPPER, int_addr >> 32); - - (void)xbridge_read_reg(xb, WIDGET_TFLUSH); - - /* - * Register an error interrupt handler. - */ - - if (xbow_intr_register(xb->xb_widget, IPL_HIGH, - &xb->xb_err_intrsrc) != 0) - return "can't allocate error interrupt source"; - if (xbow_intr_establish(xbridge_err_intr_handler, xb, - xb->xb_err_intrsrc, IPL_HIGH, DEVNAME(xb), NULL)) - return "unable to register error interrupt handler"; - - xbridge_err_clear(xb, 0); - xbridge_write_reg(xb, BRIDGE_INT_HOST_ERR, xb->xb_err_intrsrc); - - /* - * Enable as many error interrupt sources as possible; older - * Bridge chips need to have a few of them kept masked to - * avoid hitting hardware issues. - */ - xb->xb_ier |= (ISSET(xb->xb_flags, XF_PIC) ? - PIC_ISR_ERRMASK : BRIDGE_ISR_ERRMASK) & - ~(BRIDGE_ISR_MULTIPLE_ERR | BRIDGE_ISR_SSRAM_PERR | - BRIDGE_ISR_GIO_BENABLE_ERR); - if (xb->xb_busno != 0) { - /* xtalk errors will only show up on bus #0 */ - xb->xb_ier &= ~(BRIDGE_ISR_UNSUPPORTED_XOP | - BRIDGE_ISR_LLP_REC_SNERR | BRIDGE_ISR_LLP_REC_CBERR | - BRIDGE_ISR_LLP_RCTY | BRIDGE_ISR_LLP_TX_RETRY | - BRIDGE_ISR_LLP_TCTY); - } - if (!ISSET(xb->xb_flags, XF_XBRIDGE)) { - if (xb->xb_revision < 2) - xb->xb_ier &= ~(BRIDGE_ISR_UNEXPECTED_RESP | - BRIDGE_ISR_PCI_MASTER_TMO | - BRIDGE_ISR_RESP_XTALK_ERR | - BRIDGE_ISR_LLP_TX_RETRY | BRIDGE_ISR_XREAD_REQ_TMO); - if (xb->xb_revision < 3) - xb->xb_ier &= ~BRIDGE_ISR_BAD_XRESP_PACKET; - } - - xbridge_write_reg(xb, BRIDGE_IER, xb->xb_ier); - - (void)xbridge_read_reg(xb, WIDGET_TFLUSH); - - return NULL; -} - -/* - * Handle PCI errors. - */ -void -xbridge_err_handle(struct xbpci_softc *xb, uint64_t isr) -{ - uint64_t pci_err, wid_err, resp_err; - - wid_err = xbridge_read_reg(xb, WIDGET_ERR_ADDR_LOWER); - if (!ISSET(xb->xb_flags, XF_PIC)) - wid_err |= xbridge_read_reg(xb, WIDGET_ERR_ADDR_UPPER) << 32; - pci_err = xbridge_read_reg(xb, BRIDGE_PCI_ERR_LOWER); - if (!ISSET(xb->xb_flags, XF_PIC)) - pci_err |= xbridge_read_reg(xb, BRIDGE_PCI_ERR_UPPER) << 32; - resp_err = xbridge_read_reg(xb, BRIDGE_WIDGET_RESP_LOWER); - if (!ISSET(xb->xb_flags, XF_PIC)) - resp_err |= - xbridge_read_reg(xb, BRIDGE_WIDGET_RESP_UPPER) << 32; - - /* XXX give more detailed information */ - printf("%s: error interrupt, isr %llx wid %llx pci %llx resp %llx\n", - DEVNAME(xb), isr, wid_err, pci_err, resp_err); - - xbridge_err_clear(xb, isr); -} - -/* - * Clear any error condition. - */ -void -xbridge_err_clear(struct xbpci_softc *xb, uint64_t isr) -{ - if (ISSET(xb->xb_flags, XF_PIC)) { - if (isr == 0) - isr = xbridge_read_reg(xb, BRIDGE_ISR) & - ~BRIDGE_ISR_HWINTR_MASK; - xbridge_write_reg(xb, BRIDGE_ICR, isr); - } else - xbridge_write_reg(xb, BRIDGE_ICR, BRIDGE_ICR_ALL); - - (void)xbridge_read_reg(xb, WIDGET_TFLUSH); -} - -/* - * Build a not-so-pessimistic RRB allocation register value. - */ -void -xbridge_rrb_setup(struct xbpci_softc *xb, int odd) -{ - uint rrb[MAX_SLOTS / 2]; /* tentative rrb assignment */ - uint total; /* rrb count */ - uint32_t proto; /* proto rrb value */ - int dev, i, j; - - /* - * First, try to allocate as many RRBs per device as possible. - */ - - total = 0; - for (i = 0; i < nitems(rrb); i++) { - dev = (i << 1) + !!odd; - if (dev >= xb->xb_nslots || SLOT_EMPTY(xb, dev)) - rrb[i] = 0; - else { - rrb[i] = 4; /* optimistic value */ - total += 4; - } - } - - /* - * Then, try to reduce greed until we do not claim more than - * the 8 RRBs we can afford. - */ - - if (total > 8) { - /* - * All devices should be able to live with 3 RRBs, so - * reduce their allocation from 4 to 3. - */ - for (i = 0; i < nitems(rrb); i++) { - if (rrb[i] == 4) { - rrb[i]--; - if (--total == 8) - break; - } - } - } - - if (total > 8) { - /* - * There are too many devices for 3 RRBs per device to - * be possible. Attempt to reduce from 3 to 2, except - * for isp(4) devices. - */ - for (i = 0; i < nitems(rrb); i++) { - if (rrb[i] == 3) { - dev = (i << 1) + !!odd; - if (PCI_VENDOR(xb->xb_devices[dev].id) != - PCI_VENDOR_QLOGIC) { - rrb[i]--; - if (--total == 8) - break; - } - } - } - } - - if (total > 8) { - /* - * Too bad, we need to shrink the RRB allocation for - * isp devices too. We'll try to favour the lowest - * slots, though, hence the reversed loop order. - */ - for (i = nitems(rrb) - 1; i >= 0; i--) { - if (rrb[i] == 3) { - rrb[i]--; - if (--total == 8) - break; - } - } - } - - /* - * Now build the RRB register value proper. - */ - - proto = 0; - for (i = 0; i < nitems(rrb); i++) { - for (j = 0; j < rrb[i]; j++) - proto = (proto << RRB_SHIFT) | (RRB_VALID | i); - } - - xbridge_write_reg(xb, odd ? BRIDGE_RRB_ODD : BRIDGE_RRB_EVEN, proto); -} - -/* - * Configure PCI resources for all devices. - */ -void -xbridge_resource_setup(struct xbpci_softc *xb) -{ - pci_chipset_tag_t pc = &xb->xb_pc; - int dev, nfuncs; - pcitag_t tag; - pcireg_t id, bhlcr; - uint32_t devio; - int need_setup; - uint secondary, nppb, npccbb, ppbstride; - const struct pci_quirkdata *qd; - - /* - * On Octane, we will want to map everything through the large - * windows, whenever possible. - * - * Set up these mappings now. - */ - - if (sys_config.system_type == SGI_OCTANE) { - xb->xb_ioex = xbridge_mapping_setup(xb, 1); - xb->xb_memex = xbridge_mapping_setup(xb, 0); - } - - /* - * Configure all regular PCI devices. - */ - -#ifdef DEBUG - for (dev = 0; dev < xb->xb_nslots; dev++) - printf("device %d: devio %08llx\n", - dev, xbridge_read_reg(xb, BRIDGE_DEVICE(dev))); -#endif - nppb = npccbb = 0; - for (dev = 0; dev < xb->xb_nslots; dev++) { - if (SLOT_EMPTY(xb, dev)) - continue; - - /* - * Count ppb and pccbb devices, we will need their number later. - */ - - tag = pci_make_tag(pc, 0, dev, 0); - bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG); - if (PCI_HDRTYPE_TYPE(bhlcr) == 1) - nppb++; - if (PCI_HDRTYPE_TYPE(bhlcr) == 2) - npccbb++; - - /* - * We want to avoid changing mapping configuration for - * devices which have been setup by ARCS. - * - * On Octane, the whole on-board I/O widget has been - * set up, with direct mappings into widget space. - * - * On Origin, since direct mappings are expensive, - * everything set up by ARCS has a valid devio - * mapping; those can be identified as they sport the - * widget number in the high address bits. - * - * We will only fix the device-global devio flags on - * devices which have been set up by ARCS. Otherwise, - * we'll need to perform proper PCI resource allocation. - */ - - id = xb->xb_devices[dev].id; - devio = xbridge_read_reg(xb, BRIDGE_DEVICE(dev)); - if (id != PCI_ID_CODE(PCI_VENDOR_SGI, PCI_PRODUCT_SGI_IOC3) && - id != PCI_ID_CODE(PCI_VENDOR_SGI, PCI_PRODUCT_SGI_IOC4)) - need_setup = 1; - else - need_setup = xb->xb_busno != 0 || xb->xb_devio_skew != - ((devio & BRIDGE_DEVICE_BASE_MASK) >> - (24 - BRIDGE_DEVICE_BASE_SHIFT)); - - /* - * Enable byte swapping for DMA, except on IOC3, IOC4 and - * RAD1 devices. - */ - if (id == PCI_ID_CODE(PCI_VENDOR_SGI, PCI_PRODUCT_SGI_IOC3) || - id == PCI_ID_CODE(PCI_VENDOR_SGI, PCI_PRODUCT_SGI_IOC4) || - id == PCI_ID_CODE(PCI_VENDOR_SGI, PCI_PRODUCT_SGI_RAD1)) - devio &= - ~(BRIDGE_DEVICE_SWAP_PMU | BRIDGE_DEVICE_SWAP_DIR); - else - devio |= - BRIDGE_DEVICE_SWAP_PMU | BRIDGE_DEVICE_SWAP_DIR; - - /* - * Disable write gathering. - */ - devio &= - ~(BRIDGE_DEVICE_WGATHER_PMU | BRIDGE_DEVICE_WGATHER_DIR); - - /* - * Disable prefetching - on-board isp(4) controllers on - * Octane are set up with this, but this confuses the - * driver. - */ - devio &= ~BRIDGE_DEVICE_PREFETCH; - - /* - * Force cache coherency. - */ - devio |= BRIDGE_DEVICE_COHERENT; - - if (need_setup == 0) { - xbridge_set_devio(xb, dev, devio, 1); - continue; - } - - /* - * Clear any residual devio mapping. - */ - devio &= ~BRIDGE_DEVICE_BASE_MASK; - devio &= ~BRIDGE_DEVICE_IO_MEM; - xbridge_set_devio(xb, dev, devio, 0); - - /* - * We now need to perform the resource allocation for this - * device, which has not been setup by ARCS. - */ - - qd = pci_lookup_quirkdata(PCI_VENDOR(id), PCI_PRODUCT(id)); - if (PCI_HDRTYPE_MULTIFN(bhlcr) || - (qd != NULL && (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0)) - nfuncs = 8; - else - nfuncs = 1; - - xbridge_device_setup(xb, dev, nfuncs, devio); - } - - /* - * Configure PCI-PCI and PCI-CardBus bridges, if any. - * - * We do this after all the other PCI devices have been configured - * in order to favour them during resource allocation. - */ - - if (npccbb != 0) { - /* - * If there are PCI-CardBus bridges, we really want to be - * able to have large resource spaces... - */ - 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 < xb->xb_nslots; dev++) { - if (SLOT_EMPTY(xb, dev)) - continue; - - tag = pci_make_tag(pc, 0, dev, 0); - bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG); - - switch (PCI_HDRTYPE_TYPE(bhlcr)) { - case 1: /* PCI-PCI bridge */ - ppb_initialize(pc, tag, 0, secondary, - secondary + ppbstride - 1); - secondary += ppbstride; - break; - case 2: /* PCI-CardBus bridge */ - /* - * We do not expect cardbus devices to sport - * PCI-PCI bridges themselves, so only one - * PCI bus will do. - */ - pccbb_initialize(pc, tag, 0, secondary, secondary); - secondary++; - break; - } - } - - if (xb->xb_ioex != NULL) { - extent_destroy(xb->xb_ioex); - xb->xb_ioex = NULL; - } - if (xb->xb_memex != NULL) { - extent_destroy(xb->xb_memex); - xb->xb_memex = NULL; - } -} - -/* - * Make the Octane flash area unavailable in the PCI space extents, so - * that we do not try to map devices in its area. - */ -int -xbridge_extent_chomp(struct xbpci_softc *xb, struct extent *ex) -{ -#ifdef TGT_OCTANE - /* - * On Octane, the boot PROM is part of the onboard IOC3 - * device, and is accessible through the PCI memory space - * (and maybe through the PCI I/O space as well). - * - * To avoid undebuggable surprises, make sure we never use - * this space. - */ - if (sys_config.system_type == SGI_OCTANE && - xb->xb_widget == IP30_BRIDGE_WIDGET) { - u_long fmin, fmax; - - /* - * This relies upon the knowledge that both flash bases - * are contiguous, to perform only one extent operation. - * I don't think we need to be pedantic to the point of - * doing this in two steps, really -- miod - */ - fmin = max(IP30_FLASH_BASE, ex->ex_start); - fmax = min(IP30_FLASH_ALT + IP30_FLASH_SIZE - 1, ex->ex_end); - if (fmax >= fmin) - return extent_alloc_region(ex, fmin, fmax + 1 - fmin, - EX_NOWAIT | EX_MALLOCOK); - } -#endif - - return 0; -} - -/* - * Build resource extents for the MI PCI code to play with. - * These extents cover the configured devio areas, and the large resource - * views, if applicable. - */ -void -xbridge_extent_setup(struct xbpci_softc *xb) -{ - int dev; - int errors; - bus_addr_t start, end; - uint32_t devio; - - 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 (xb->xb_ioex != NULL) { - errors = 0; - /* make all configured devio ranges available... */ - 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(xb->xb_ioex, start, - BRIDGE_DEVIO_SIZE(dev), EX_NOWAIT) != 0) { - errors++; - break; - } - } - /* ...as well as the large views, if any */ - if (xb->xb_ioend != 0) { - start = xb->xb_iostart; - if (start == 0) - start = 1; - end = xb->xb_devio_skew << 24; - if (start < end) - if (extent_free(xb->xb_ioex, start, - end, EX_NOWAIT) != 0) - errors++; - - 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 (xbridge_extent_chomp(xb, xb->xb_ioex) != 0) - errors++; - - if (errors != 0) { - extent_destroy(xb->xb_ioex); - xb->xb_ioex = NULL; - } - } - - 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 (xb->xb_memex != NULL) { - errors = 0; - /* make all configured devio ranges available... */ - 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(xb->xb_memex, start, - BRIDGE_DEVIO_SIZE(dev), EX_NOWAIT) != 0) { - errors++; - break; - } - } - /* ...as well as the large views, if any */ - if (xb->xb_memend != 0) { - start = xb->xb_memstart; - if (start == 0) - start = 1; - end = xb->xb_devio_skew << 24; - if (start < end) - if (extent_free(xb->xb_memex, start, - end, EX_NOWAIT) != 0) - errors++; - - 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 (xbridge_extent_chomp(xb, xb->xb_memex) != 0) - errors++; - - if (errors != 0) { - extent_destroy(xb->xb_memex); - xb->xb_memex = NULL; - } - } -} - -struct extent * -xbridge_mapping_setup(struct xbpci_softc *xb, int io) -{ - bus_addr_t membase, offs; - bus_size_t len; - paddr_t base; - u_long start, end; - struct extent *ex = NULL; - - if (io) { - /* - * I/O mappings are available in the widget at offset - * BRIDGE_PCI_IO_SPACE_BASE onwards, but weren't working - * correctly until Bridge revision 4 (apparently, what - * didn't work was the byteswap logic). - * - * Also, this direct I/O space is not supported on PIC - * widgets. - */ - - 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(xb->xb_bow, - xb->xb_widget, &offs, &len); - } else - base = 0; - - if (base != 0) { - if (offs + len > BRIDGE_PCI_IO_SPACE_BASE + - BRIDGE_PCI_IO_SPACE_LENGTH) - len = BRIDGE_PCI_IO_SPACE_BASE + - BRIDGE_PCI_IO_SPACE_LENGTH - offs; - -#ifdef DEBUG - printf("direct io %#lx-%#lx base %#lx\n", - offs, offs + len - 1, base); -#endif - offs -= BRIDGE_PCI_IO_SPACE_BASE; - - ex = extent_create("xbridge_direct_io", - offs == 0 ? 1 : offs, offs + len - 1, - M_DEVBUF, NULL, 0, EX_NOWAIT); - - /* - * Note that we do not need to invoke - * xbridge_extent_chomp() here since we will - * reserve the whole devio area. - */ - - if (ex != NULL) { - xb->xb_io_bus_space->bus_base = base - offs; - xb->xb_io_bus_space->_space_map = - xbridge_space_map_io; - xb->xb_io_bus_space->_space_subregion = - xbridge_space_region_io; - - xb->xb_io_bus_space_sw->bus_base = base - offs; - xb->xb_io_bus_space_sw->_space_map = - xbridge_space_map_io; - xb->xb_io_bus_space_sw->_space_subregion = - xbridge_space_region_io; - - 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. - */ - - 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(xb->xb_bow, - xb->xb_widget, &offs, &len); - - if (base != 0) { - /* - * Only the low 30 bits of memory BAR are honoured - * by the hardware, thus restricting memory mappings - * to 1GB. - */ - if (offs + len > membase + BRIDGE_PCI_MEM_SPACE_LENGTH) - len = membase + BRIDGE_PCI_MEM_SPACE_LENGTH - - offs; - -#ifdef DEBUG - printf("direct mem %#lx-%#lx base %#lx\n", - offs, offs + len - 1, base); -#endif - offs -= membase; - - ex = extent_create("xbridge_direct_mem", - offs == 0 ? 1 : offs, offs + len - 1, - M_DEVBUF, NULL, 0, EX_NOWAIT); - - /* - * Note that we do not need to invoke - * xbridge_extent_chomp() here since we will - * reserve the whole devio area. - */ - - if (ex != NULL) { - xb->xb_mem_bus_space->bus_base = base - offs; - xb->xb_mem_bus_space->_space_map = - xbridge_space_map_mem; - xb->xb_mem_bus_space->_space_subregion = - xbridge_space_region_mem; - - xb->xb_mem_bus_space_sw->bus_base = base - offs; - xb->xb_mem_bus_space_sw->_space_map = - xbridge_space_map_mem; - xb->xb_mem_bus_space_sw->_space_subregion = - xbridge_space_region_mem; - - xb->xb_memstart = offs; - xb->xb_memend = offs + len - 1; - } - } - } - - if (ex != NULL) { - /* - * Remove the devio mapping range from the extent - * to avoid ambiguous mappings. - * - * Note that xbow_widget_map_space() may have returned - * a range in which the devio area does not appear. - */ - 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) - start = ex->ex_start; - if (end > ex->ex_end + 1) - end = ex->ex_end + 1; - if (extent_alloc_region(ex, start, end - start, - EX_NOWAIT | EX_MALLOCOK) != 0) { - printf("%s: failed to expurge devio range" - " from %s large extent\n", - DEVNAME(xb), io ? "i/o" : "mem"); - extent_destroy(ex); - ex = NULL; - } - } - } - - return ex; -} - -/* - * Flags returned by xbridge_resource_explore() - */ -#define XR_IO 0x01 /* needs I/O mappings */ -#define XR_MEM 0x02 /* needs memory mappings */ -#define XR_IO_OFLOW_S 0x04 /* can't fit I/O in a short devio */ -#define XR_MEM_OFLOW_S 0x08 /* can't fit memory in a short devio */ -#define XR_IO_OFLOW 0x10 /* can't fit I/O in a large devio */ -#define XR_MEM_OFLOW 0x20 /* can't fit memory in a large devio */ - -int -xbridge_resource_explore(struct xbpci_softc *xb, pcitag_t tag, - struct extent *ioex, struct extent *memex) -{ - pci_chipset_tag_t pc = &xb->xb_pc; - pcireg_t bhlc, type, addr, mask; - bus_addr_t base; - bus_size_t size; - int reg, reg_start, reg_end, reg_rom; - int rc = 0; - - bhlc = pci_conf_read(pc, tag, PCI_BHLC_REG); - switch (PCI_HDRTYPE_TYPE(bhlc)) { - case 0: - reg_start = PCI_MAPREG_START; - reg_end = PCI_MAPREG_END; - reg_rom = PCI_ROM_REG; - break; - case 1: /* PCI-PCI bridge */ - reg_start = PCI_MAPREG_START; - reg_end = PCI_MAPREG_PPB_END; - reg_rom = 0; /* 0x38 */ - break; - case 2: /* PCI-CardBus bridge */ - reg_start = PCI_MAPREG_START; - reg_end = PCI_MAPREG_PCB_END; - reg_rom = 0; - break; - default: - return rc; - } - - for (reg = reg_start; reg < reg_end; reg += 4) { - if (pci_mapreg_probe(pc, tag, reg, &type) == 0) - continue; - - if (pci_mapreg_info(pc, tag, reg, type, NULL, &size, NULL)) - continue; - - switch (type) { - case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT: - reg += 4; - /* FALLTHROUGH */ - case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT: - rc |= XR_MEM; - if (memex != NULL) { - if (size > memex->ex_end - memex->ex_start) - rc |= XR_MEM_OFLOW | XR_MEM_OFLOW_S; - else if (extent_alloc(memex, size, size, - 0, 0, 0, &base) != 0) - rc |= XR_MEM_OFLOW | XR_MEM_OFLOW_S; - else if (base >= BRIDGE_DEVIO_SHORT) - rc |= XR_MEM_OFLOW_S; - } else - rc |= XR_MEM_OFLOW | XR_MEM_OFLOW_S; - break; - case PCI_MAPREG_TYPE_IO: - rc |= XR_IO; - if (ioex != NULL) { - if (size > ioex->ex_end - ioex->ex_start) - rc |= XR_IO_OFLOW | XR_IO_OFLOW_S; - else if (extent_alloc(ioex, size, size, - 0, 0, 0, &base) != 0) - rc |= XR_IO_OFLOW | XR_IO_OFLOW_S; - else if (base >= BRIDGE_DEVIO_SHORT) - rc |= XR_IO_OFLOW_S; - } else - rc |= XR_IO_OFLOW | XR_IO_OFLOW_S; - break; - } - } - - if (reg_rom != 0) { - addr = pci_conf_read(pc, tag, reg_rom); - pci_conf_write(pc, tag, reg_rom, ~PCI_ROM_ENABLE); - mask = pci_conf_read(pc, tag, reg_rom); - pci_conf_write(pc, tag, reg_rom, addr); - size = PCI_ROM_SIZE(mask); - - if (size != 0) { - rc |= XR_MEM; - if (memex != NULL) { - if (size > memex->ex_end - memex->ex_start) - rc |= XR_MEM_OFLOW | XR_MEM_OFLOW_S; - else if (extent_alloc(memex, size, size, - 0, 0, 0, &base) != 0) - rc |= XR_MEM_OFLOW | XR_MEM_OFLOW_S; - else if (base >= BRIDGE_DEVIO_SHORT) - rc |= XR_MEM_OFLOW_S; - } else - rc |= XR_MEM_OFLOW | XR_MEM_OFLOW_S; - } - } - - return rc; -} - -void -xbridge_resource_manage(struct xbpci_softc *xb, pcitag_t tag, - struct extent *ioex, struct extent *memex) -{ - pci_chipset_tag_t pc = &xb->xb_pc; - pcireg_t bhlc, type, mask; - bus_addr_t base; - bus_size_t size; - int reg, reg_start, reg_end, reg_rom; - - bhlc = pci_conf_read(pc, tag, PCI_BHLC_REG); - switch (PCI_HDRTYPE_TYPE(bhlc)) { - case 0: - reg_start = PCI_MAPREG_START; - reg_end = PCI_MAPREG_END; - reg_rom = PCI_ROM_REG; - break; - case 1: /* PCI-PCI bridge */ - reg_start = PCI_MAPREG_START; - reg_end = PCI_MAPREG_PPB_END; - reg_rom = 0; /* 0x38 */ - break; - case 2: /* PCI-CardBus bridge */ - reg_start = PCI_MAPREG_START; - reg_end = PCI_MAPREG_PCB_END; - reg_rom = 0; - break; - default: - return; - } - - for (reg = reg_start; reg < reg_end; reg += 4) { - if (pci_mapreg_probe(pc, tag, reg, &type) == 0) - continue; - - if (pci_mapreg_info(pc, tag, reg, type, &base, &size, NULL)) - continue; - - /* - * Note that we do not care about the existing BAR values, - * since these devices either have not been setup by ARCS - * or do not matter for early system setup (such as - * optional IOC3 PCI boards, which will get setup by - * ARCS but can be reinitialized as we see fit). - */ -#ifdef DEBUG - printf("tag %04lx bar %02x type %d base %#lx size %#lx", - tag, reg, type, base, size); -#endif - switch (type) { - case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT: - /* - * Since our mapping ranges are restricted to - * at most 30 bits, the upper part of the 64 bit - * BAR registers is always zero. - */ - pci_conf_write(pc, tag, reg + 4, 0); - /* FALLTHROUGH */ - case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT: - if (memex != NULL) { - if (extent_alloc(memex, size, size, 0, 0, 0, - &base) != 0) - base = 0; - } else - base = 0; - break; - case PCI_MAPREG_TYPE_IO: - if (ioex != NULL) { - if (extent_alloc(ioex, size, size, 0, 0, 0, - &base) != 0) - base = 0; - } else - base = 0; - break; - } - -#ifdef DEBUG - printf(" setup at %#lx\n", base); -#endif - pci_conf_write(pc, tag, reg, base); - - if (type == (PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT)) - reg += 4; - } - - if (reg_rom != 0) { - base = (bus_addr_t)pci_conf_read(pc, tag, reg_rom); - pci_conf_write(pc, tag, reg_rom, ~PCI_ROM_ENABLE); - mask = pci_conf_read(pc, tag, reg_rom); - size = PCI_ROM_SIZE(mask); - - if (size != 0) { -#ifdef DEBUG - printf("bar %02x type rom base %#lx size %#lx", - reg_rom, base, size); -#endif - if (memex != NULL) { - if (extent_alloc(memex, size, size, 0, 0, 0, - &base) != 0) - base = 0; - } else - base = 0; -#ifdef DEBUG - printf(" setup at %#lx\n", base); -#endif - } else - base = 0; - - /* ROM intentionally left disabled */ - pci_conf_write(pc, tag, reg_rom, base); - } -} - -void -xbridge_device_setup(struct xbpci_softc *xb, int dev, int nfuncs, - uint32_t devio) -{ - pci_chipset_tag_t pc = &xb->xb_pc; - int function; - pcitag_t tag; - pcireg_t id, csr; - uint32_t baseio; - int resources; - int io_devio, mem_devio; - struct extent *ioex, *memex; - - /* - * In a first step, we enumerate all the requested resources, - * and check if they could fit within devio mappings. - * - * If devio can't afford us the mappings we need, we'll - * try and allocate a large window. - */ - - /* - * Allocate extents to use for devio mappings if necessary. - * This can fail; in that case we'll try to use a large mapping - * whenever possible, or silently fail to configure the device. - */ - if (xb->xb_ioex != NULL) - ioex = NULL; - else { - ioex = extent_create("xbridge_io", - 0, BRIDGE_DEVIO_LARGE - 1, - M_DEVBUF, NULL, 0, EX_NOWAIT); -#ifdef DEBUG - if (ioex == NULL) - printf("%s: ioex extent_create failed\n", __func__); -#endif - } - if (xb->xb_memex != NULL) - memex = NULL; - else { - memex = extent_create("xbridge_mem", - 0, BRIDGE_DEVIO_LARGE - 1, - M_DEVBUF, NULL, 0, EX_NOWAIT); -#ifdef DEBUG - if (memex == NULL) - printf("%s: memex extent_create failed\n", __func__); -#endif - } - - resources = 0; - for (function = 0; function < nfuncs; function++) { - tag = pci_make_tag(pc, 0, dev, function); - id = pci_conf_read(pc, tag, PCI_ID_REG); - - if (PCI_VENDOR(id) == PCI_VENDOR_INVALID || - PCI_VENDOR(id) == 0) - continue; - - csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); - pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr & - ~(PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE)); - - resources |= xbridge_resource_explore(xb, tag, ioex, memex); - } -#ifdef DEBUG - printf("resources mask: %02x\n", resources); -#endif - - if (memex != NULL) { - extent_destroy(memex); - memex = NULL; - } - if (ioex != NULL) { - extent_destroy(ioex); - ioex = NULL; - } - - /* - * In a second step, if resources can be mapped using devio slots, - * allocate them. Otherwise, or if we can't get a devio slot - * big enough for the resources we need to map, we'll need - * to get a large window mapping. - * - * Note that, on Octane, we try to avoid using devio whenever - * possible. - */ - - io_devio = -1; - if (ISSET(resources, XR_IO)) { - if (!ISSET(resources, XR_IO_OFLOW) && - (sys_config.system_type != SGI_OCTANE || - xb->xb_ioex == NULL)) - io_devio = xbridge_allocate_devio(xb, dev, - ISSET(resources, XR_IO_OFLOW_S)); - if (io_devio >= 0) { - 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), 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 (xb->xb_ioex == NULL) - xb->xb_ioex = xbridge_mapping_setup(xb, 1); - } - } - - mem_devio = -1; - if (ISSET(resources, XR_MEM)) { - if (!ISSET(resources, XR_MEM_OFLOW) && - sys_config.system_type != SGI_OCTANE) - mem_devio = xbridge_allocate_devio(xb, dev, - ISSET(resources, XR_MEM_OFLOW_S)); - if (mem_devio >= 0) { - 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 | - (baseio >> BRIDGE_DEVICE_BASE_SHIFT), 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 (xb->xb_memex == NULL) - xb->xb_memex = xbridge_mapping_setup(xb, 0); - } - } - - /* - * Finally allocate the resources proper and update the - * device BARs accordingly. - */ - - for (function = 0; function < nfuncs; function++) { - tag = pci_make_tag(pc, 0, dev, function); - id = pci_conf_read(pc, tag, PCI_ID_REG); - - if (PCI_VENDOR(id) == PCI_VENDOR_INVALID || - PCI_VENDOR(id) == 0) - continue; - - xbridge_resource_manage(xb, tag, - ioex != NULL ? ioex : xb->xb_ioex, - memex != NULL ? memex : xb->xb_memex); - } - - if (memex != NULL) - extent_destroy(memex); - if (ioex != NULL) - extent_destroy(ioex); -} - -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 xbpci_softc *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 = xbridge_read_reg(xb, BRIDGE_DEVICE(dev)); - - /* - * Since our caller computes resource needs starting at zero, we - * can ignore the start values when computing the amount of - * resources we'll need. - */ - - /* - * Try and allocate I/O resources first, as we may not be able - * to use a large I/O mapping, in which case we want to use our - * reserved devio for this purpose. - */ - - exsize = *ioend; - *iostart = 0xffffffff; - *ioend = 0; - if (exsize++ != 0) { - /* try to allocate through a devio slot whenever possible... */ - if (exsize < BRIDGE_DEVIO_SHORT) - devio_idx = xbridge_allocate_devio(xb, dev, 0); - else if (exsize < BRIDGE_DEVIO_LARGE) - devio_idx = xbridge_allocate_devio(xb, dev, 1); - else - devio_idx = -1; - - /* ...if it fails, try the large view.... */ - 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 && xb->xb_ioex == NULL) { - if (exsize > BRIDGE_DEVIO_SHORT) - devio_idx = xbridge_allocate_devio(xb, dev, 1); - if (devio_idx < 0) - devio_idx = xbridge_allocate_devio(xb, dev, 0); - } - - if (devio_idx >= 0) { - 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), 1); - *iostart = base; - *ioend = base + BRIDGE_DEVIO_SIZE(devio_idx) - 1; - } 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, - * if successful, will work as a 32 bit i/o range. - */ - if (exsize < 1UL << 12) - exsize = 1UL << 12; - for (tries = 0; tries < 5; tries++) { - if (extent_alloc(xb->xb_ioex, exsize, - 1UL << 12, 0, 0, EX_NOWAIT | EX_MALLOCOK, - &exstart) == 0) { - *iostart = exstart; - *ioend = exstart + exsize - 1; - break; - } - exsize >>= 1; - if (exsize < 1UL << 12) - break; - } - } - } - - exsize = *memend; - *memstart = 0xffffffff; - *memend = 0; - if (exsize++ != 0) { - /* try to allocate through a devio slot whenever possible... */ - if (exsize < BRIDGE_DEVIO_SHORT) - devio_idx = xbridge_allocate_devio(xb, dev, 0); - else if (exsize < BRIDGE_DEVIO_LARGE) - devio_idx = xbridge_allocate_devio(xb, dev, 1); - else - devio_idx = -1; - - /* ...if it fails, try the large view.... */ - 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 && xb->xb_memex == NULL) { - if (exsize > BRIDGE_DEVIO_SHORT) - devio_idx = xbridge_allocate_devio(xb, dev, 1); - if (devio_idx < 0) - devio_idx = xbridge_allocate_devio(xb, dev, 0); - } - - if (devio_idx >= 0) { - 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), 1); - *memstart = base; - *memend = base + BRIDGE_DEVIO_SIZE(devio_idx) - 1; - } 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 - * 30 bits, so our allocation, if successful, will - * work as a 32 bit memory range. - */ - if (exsize < 1UL << 20) - exsize = 1UL << 20; - for (tries = 0; tries < 5; tries++) { - if (extent_alloc(xb->xb_memex, exsize, - 1UL << 20, 0, 0, EX_NOWAIT | EX_MALLOCOK, - &exstart) == 0) { - *memstart = exstart; - *memend = exstart + exsize - 1; - break; - } - exsize >>= 1; - if (exsize < 1UL << 20) - break; - } - } - } - - return 0; -} - -#if NCARDBUS > 0 - -static struct rb_md_fnptr xbridge_rb_md_fn = { - xbridge_rbus_space_map, - xbridge_rbus_space_unmap -}; - -int -xbridge_rbus_space_map(bus_space_tag_t t, bus_addr_t addr, bus_size_t size, - int flags, bus_space_handle_t *bshp) -{ - return bus_space_map(t, addr, size, flags, bshp); -} - -void -xbridge_rbus_space_unmap(bus_space_tag_t t, bus_space_handle_t h, - bus_size_t size, bus_addr_t *addrp) -{ - bus_space_unmap(t, h, size); - *addrp = h - t->bus_base; -} - -void * -xbridge_rbus_parent_io(struct pci_attach_args *pa) -{ - struct extent *ex = pa->pa_ioex; - bus_addr_t start, end; - rbus_tag_t rb = NULL; - - /* - * We want to force I/O mappings to lie in the low 16 bits - * area. This is mandatory for 16-bit pcmcia devices; and - * although 32-bit cardbus devices could use a larger range, - * the pccbb driver doesn't enable the large I/O windows. - */ - if (ex != NULL) { - start = 0; - end = 0x10000; - if (start < ex->ex_start) - start = ex->ex_start; - if (end > ex->ex_end) - end = ex->ex_end; - - if (start < end) { - rb = rbus_new_root_share(pa->pa_iot, ex, - start, end - start); - if (rb != NULL) - rb->rb_md = &xbridge_rb_md_fn; - } - } - - /* - * We are not allowed to return NULL. If we can't provide - * resources, return a valid body which will fail requests. - */ - if (rb == NULL) - rb = rbus_new_body(pa->pa_iot, NULL, 0, 0, RBUS_SPACE_INVALID); - - return rb; -} - -void * -xbridge_rbus_parent_mem(struct pci_attach_args *pa) -{ - struct xbpci_softc *xb = pa->pa_pc->pc_conf_v; - struct extent *ex = pa->pa_memex; - bus_addr_t start; - rbus_tag_t rb = NULL; - - /* - * There is no restriction for the memory mappings, - * however we need to make sure these won't hit the - * devio range (for md_space_unmap to work correctly). - */ - if (ex != NULL) { - start = (xb->xb_devio_skew + 1) << 24; - if (start < ex->ex_start) - start = ex->ex_start; - - if (start < ex->ex_end) { - rb = rbus_new_root_share(pa->pa_memt, ex, - start, ex->ex_end - start); - if (rb != NULL) - rb->rb_md = &xbridge_rb_md_fn; - } - } - - /* - * We are not allowed to return NULL. If we can't provide - * resources, return a valid body which will fail requests. - */ - if (rb == NULL) - rb = rbus_new_body(pa->pa_iot, NULL, 0, 0, RBUS_SPACE_INVALID); - - return rb; -} - -#endif /* NCARDBUS > 0 */ - -int -xbridge_allocate_devio(struct xbpci_softc *xb, int dev, int wantlarge) -{ -#ifdef DEBUG - int orig_dev = dev; -#endif - - /* - * If the preferred slot is available and matches the size requested, - * use it. - */ - - if (!ISSET(xb->xb_devio_usemask, 1 << dev)) { - if (BRIDGE_DEVIO_SIZE(dev) >= - (wantlarge ? BRIDGE_DEVIO_LARGE : BRIDGE_DEVIO_SHORT)) { -#ifdef DEBUG - printf("%s(%d,%d): using reserved entry\n", - __func__, dev, wantlarge); -#endif - return dev; - } - } - - /* - * Otherwise pick the smallest available devio matching our size - * request. - */ - - for (dev = 0; dev < xb->xb_nslots; dev++) { - if (ISSET(xb->xb_devio_usemask, 1 << dev)) - continue; /* devio in use */ - - if (!SLOT_EMPTY(xb, dev)) - continue; /* devio to be used soon */ - - if (BRIDGE_DEVIO_SIZE(dev) >= - (wantlarge ? BRIDGE_DEVIO_LARGE : BRIDGE_DEVIO_SHORT)) { -#ifdef DEBUG - printf("%s(%d,%d): using unused entry %d\n", - __func__, orig_dev, wantlarge, dev); -#endif - return dev; - } - } - -#ifdef DEBUG - printf("%s(%d,%d): no entry available\n", - __func__, orig_dev, wantlarge); -#endif - return -1; -} - -void -xbridge_set_devio(struct xbpci_softc *xb, int dev, uint32_t devio, int final) -{ - xbridge_write_reg(xb, BRIDGE_DEVICE(dev), devio); - (void)xbridge_read_reg(xb, WIDGET_TFLUSH); - xb->xb_devices[dev].devio = devio; - if (final) - SET(xb->xb_devio_usemask, 1 << dev); -#ifdef DEBUG - printf("device %d: new %sdevio %08x\n", - dev, final ? "final " : "", devio); -#endif -} - -#ifdef DDB -void xbridge_ddb(void); -void -xbridge_ddb() -{ - struct xbpci_softc *xb; - unsigned int n, intrbit; - - for (n = 0; n < xbpci_cd.cd_ndevs; n++) { - xb = xbpci_cd.cd_devs[n]; - if (xb == NULL) - continue; - - printf("%s: ISR %p IER %p xb_ier %p\n", - xb->xb_dev.dv_xname, - (void *)xbridge_read_reg(xb, BRIDGE_ISR), - (void *)xbridge_read_reg(xb, BRIDGE_IER), - (void *)xb->xb_ier); - - printf("mode %p dev %p\n", - (void *)xbridge_read_reg(xb, BRIDGE_INT_MODE), - (void *)xbridge_read_reg(xb, BRIDGE_INT_DEV)); - - for (intrbit = 0; intrbit < 8; intrbit++) - printf("IRQ%u to %p\n", intrbit, - (void *)xbridge_read_reg(xb, - BRIDGE_INT_ADDR(intrbit))); - - printf("%s: PCICFG %08llx ERR %08llx:%08llx\n", - xb->xb_dev.dv_xname, - xbridge_read_reg(xb, BRIDGE_PCI_CFG), - xbridge_read_reg(xb, BRIDGE_PCI_ERR_UPPER), - xbridge_read_reg(xb, BRIDGE_PCI_ERR_LOWER)); - } -} -#endif diff --git a/sys/arch/sgi/xbow/xbridgereg.h b/sys/arch/sgi/xbow/xbridgereg.h deleted file mode 100644 index c473f2b3cdb..00000000000 --- a/sys/arch/sgi/xbow/xbridgereg.h +++ /dev/null @@ -1,340 +0,0 @@ -/* $OpenBSD: xbridgereg.h,v 1.16 2021/03/11 11:17:00 jsg Exp $ */ - -/* - * Copyright (c) 2008, 2009 Miodrag Vallat. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * 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 BRIDGE_NSLOTS 8 -#define PIC_NSLOTS 4 -#define MAX_SLOTS BRIDGE_NSLOTS - -#define BRIDGE_NINTRS 8 - -#define PIC_WIDGET_STATUS_PCIX_SPEED_MASK 0x0000000c00000000UL -#define PIC_WIDGET_STATUS_PCIX_SPEED_SHIFT 34 -#define PIC_WIDGET_STATUS_PCIX_MODE 0x0000000200000000UL - -#define PIC_WIDGET_CONTROL_NO_SNOOP 0x4000000000000000UL -#define PIC_WIDGET_CONTROL_RELAX_ORDER 0x2000000000000000UL -#define BRIDGE_WIDGET_CONTROL_IO_SWAP 0x00800000 -#define BRIDGE_WIDGET_CONTROL_MEM_SWAP 0x00400000 -#define BRIDGE_WIDGET_CONTROL_LARGE_PAGES 0x00200000 -#define BRIDGE_WIDGET_CONTROL_SPEED_MASK 0x00000030 -#define BRIDGE_WIDGET_CONTROL_SPEED_SHIFT 4 - -/* Response Buffer Address */ -#define BRIDGE_WIDGET_RESP_UPPER 0x00000060 -#define BRIDGE_WIDGET_RESP_LOWER 0x00000068 - -/* - * DMA Direct Window - * - * The direct map register allows the 2GB direct window to map to - * a given widget address space. The upper bits of the XIO address, - * identifying the node to access, are provided in the low-order - * bits of the register. - */ - -#define BRIDGE_DIR_MAP 0x00000080 - -#define BRIDGE_DIRMAP_WIDGET_SHIFT 20 -#define BRIDGE_DIRMAP_ADD_512MB 0x00020000 /* add 512MB */ -#define BRIDGE_DIRMAP_BASE_MASK 0x0001ffff -#define BRIDGE_DIRMAP_BASE_SHIFT 31 - -#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 0x000000b0 - -#define BRIDGE_BUS_TIMEOUT 0x000000c0 -#define BRIDGE_BUS_PCI_RETRY_CNT_SHIFT 0 -#define BRIDGE_BUS_PCI_RETRY_CNT_MASK 0x000003ff -#define BRIDGE_BUS_GIO_TIMEOUT 0x00001000 -#define BRIDGE_BUS_PCI_RETRY_HOLD_SHIFT 16 -#define BRIDGE_BUS_PCI_RETRY_HOLD_MASK 0x001f0000 - -#define BRIDGE_PCI_CFG 0x000000c8 -#define BRIDGE_PCI_ERR_UPPER 0x000000d0 -#define BRIDGE_PCI_ERR_LOWER 0x000000d8 - -/* - * Interrupt handling - */ - -#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) (0x00000180 + 8 * (d)) -#define BRIDGE_INT_FORCE_PIN(d) (0x000001c0 + 8 * (d)) - -/* - * BRIDGE_ISR bits (bits 32 and beyond are PIC only) - */ - -/* PCI-X split completion message parity error */ -#define BRIDGE_ISR_PCIX_SPLIT_MSG_PARITY 0x0000200000000000ULL -/* PCI-X split completion error message */ -#define BRIDGE_ISR_PCIX_SPLIT_EMSG 0x0000100000000000ULL -/* PCI-X split completion timeout */ -#define BRIDGE_ISR_PCIX_SPLIT_TO 0x0000080000000000ULL -/* PCI-X unexpected completion cycle */ -#define BRIDGE_ISR_PCIX_UNEX_COMP 0x0000040000000000ULL -/* internal RAM parity error */ -#define BRIDGE_ISR_INT_RAM_PERR 0x0000020000000000ULL -/* PCI/PCI-X arbitration error */ -#define BRIDGE_ISR_PCIX_ARB_ERR 0x0000010000000000ULL -/* PCI-X read request timeout */ -#define BRIDGE_ISR_PCIX_REQ_TMO 0x0000008000000000ULL -/* PCI-X target abort */ -#define BRIDGE_ISR_PCIX_TABORT 0x0000004000000000ULL -/* PCI-X PERR */ -#define BRIDGE_ISR_PCIX_PERR 0x0000002000000000ULL -/* PCI-X SERR */ -#define BRIDGE_ISR_PCIX_SERR 0x0000001000000000ULL -/* PCI-X PIO retry counter exceeded */ -#define BRIDGE_ISR_PCIX_MRETRY 0x0000000800000000ULL -/* PCI-X master timeout */ -#define BRIDGE_ISR_PCIX_MTMO 0x0000000400000000ULL -/* PCI-X data cycle parity error */ -#define BRIDGE_ISR_PCIX_D_PARITY 0x0000000200000000ULL -/* PCI-X address or attribute cycle parity error */ -#define BRIDGE_ISR_PCIX_A_PARITY 0x0000000100000000ULL -/* multiple errors occurred - bridge only */ -#define BRIDGE_ISR_MULTIPLE_ERR 0x0000000080000000ULL -/* PMU access fault */ -#define BRIDGE_ISR_PMU_ESIZE_FAULT 0x0000000040000000ULL -/* unexpected xtalk incoming response */ -#define BRIDGE_ISR_UNEXPECTED_RESP 0x0000000020000000ULL -/* xtalk incoming response framing error */ -#define BRIDGE_ISR_BAD_XRESP_PACKET 0x0000000010000000ULL -/* xtalk incoming request framing error */ -#define BRIDGE_ISR_BAD_XREQ_PACKET 0x0000000008000000ULL -/* xtalk incoming response command word error bit set */ -#define BRIDGE_ISR_RESP_XTALK_ERR 0x0000000004000000ULL -/* xtalk incoming request command word error bit set */ -#define BRIDGE_ISR_REQ_XTALK_ERR 0x0000000002000000ULL -/* request packet has invalid address for this widget */ -#define BRIDGE_ISR_INVALID_ADDRESS 0x0000000001000000ULL -/* request operation not supported by the bridge */ -#define BRIDGE_ISR_UNSUPPORTED_XOP 0x0000000000800000ULL -/* request packet overflow */ -#define BRIDGE_ISR_XREQ_FIFO_OFLOW 0x0000000000400000ULL -/* LLP receiver sequence number error */ -#define BRIDGE_ISR_LLP_REC_SNERR 0x0000000000200000ULL -/* LLP receiver check bit error */ -#define BRIDGE_ISR_LLP_REC_CBERR 0x0000000000100000ULL -/* LLP receiver retry count exceeded */ -#define BRIDGE_ISR_LLP_RCTY 0x0000000000080000ULL -/* LLP transmitter side required retry */ -#define BRIDGE_ISR_LLP_TX_RETRY 0x0000000000040000ULL -/* LLP transmitter retry count exceeded */ -#define BRIDGE_ISR_LLP_TCTY 0x0000000000020000ULL -/* (ATE) SSRAM parity error - bridge only */ -#define BRIDGE_ISR_SSRAM_PERR 0x0000000000010000ULL -/* PCI abort condition */ -#define BRIDGE_ISR_PCI_ABORT 0x0000000000008000ULL -/* PCI bridge detected parity error */ -#define BRIDGE_ISR_PCI_PARITY 0x0000000000004000ULL -/* PCI address or command parity error */ -#define BRIDGE_ISR_PCI_SERR 0x0000000000002000ULL -/* PCI device parity error */ -#define BRIDGE_ISR_PCI_PERR 0x0000000000001000ULL -/* PCI device selection timeout */ -#define BRIDGE_ISR_PCI_MASTER_TMO 0x0000000000000800ULL -/* PCI retry count exceeded */ -#define BRIDGE_ISR_PCI_RETRY_CNT 0x0000000000000400ULL -/* PCI to xtalk read request timeout */ -#define BRIDGE_ISR_XREAD_REQ_TMO 0x0000000000000200ULL -/* GIO non-contiguous byte enable in xtalk packet - bridge only */ -#define BRIDGE_ISR_GIO_BENABLE_ERR 0x0000000000000100ULL -#define BRIDGE_ISR_HWINTR_MASK 0x00000000000000ffULL - -#define BRIDGE_ISR_ERRMASK 0x00000000fffffe00ULL -#define PIC_ISR_ERRMASK 0x00003fff7ffffe00ULL - -/* - * BRIDGE_ICR bits, for Bridge and XBridge chips only (error interrupts - * being cleared in groups) - */ - -#define BRIDGE_ICR_MULTIPLE 0x00000040 -#define BRIDGE_ICR_CRP 0x00000020 -#define BRIDGE_ICR_RESP_BUF 0x00000010 -#define BRIDGE_ICR_REQ_DSP 0x00000008 -#define BRIDGE_ICR_LLP 0x00000004 -#define BRIDGE_ICR_SSRAM 0x00000002 -#define BRIDGE_ICR_PCI 0x00000001 -#define BRIDGE_ICR_ALL 0x0000007f - -/* - * PCI Resource Mapping control - * - * There are three ways to map a given device: - * - memory mapping in the long window, at BRIDGE_PCI_MEM_SPACE_BASE, - * shared by all devices. - * - I/O mapping in the long window, at BRIDGE_PCI_IO_SPACE_BASE, - * shared by all devices, but only on widget revision 4 or later. - * - programmable memory or I/O mapping at a selectable place in the - * short window, with an 1MB granularity. The size of this - * window is 2MB for the windows at 2MB and 4MB, and 1MB onwards. - * - * ARCBios will setup mappings in the short window for us, and - * the selected address will match BAR0. - */ - -#define BRIDGE_DEVICE(d) (0x00000200 + 8 * (d)) -/* flags applying to the device itself */ -/* enable write gathering through ATE */ -#define BRIDGE_DEVICE_WGATHER_PMU 0x01000000 -/* enable write gathering through the direct window */ -#define BRIDGE_DEVICE_WGATHER_DIR 0x00800000 -/* byteswap DMA done through ATE */ -#define BRIDGE_DEVICE_SWAP_PMU 0x00100000 -/* byteswap DMA done through the direct window */ -#define BRIDGE_DEVICE_SWAP_DIR 0x00080000 -/* flags applying to the mapping in this devio register */ -#define BRIDGE_DEVICE_PREFETCH 0x00040000 -#define BRIDGE_DEVICE_PRECISE 0x00020000 -#define BRIDGE_DEVICE_COHERENT 0x00010000 -#define BRIDGE_DEVICE_BARRIER 0x00008000 -/* byteswap PIO */ -#define BRIDGE_DEVICE_SWAP 0x00002000 -/* set if memory space, clear if I/O space */ -#define BRIDGE_DEVICE_IO_MEM 0x00001000 -#define BRIDGE_DEVICE_BASE_MASK 0x00000fff -#define BRIDGE_DEVICE_BASE_SHIFT 20 - -#define BRIDGE_DEVIO_BASE 0x00200000 -#define BRIDGE_DEVIO_LARGE 0x00200000 -#define BRIDGE_DEVIO_SHORT 0x00100000 - -#define BRIDGE_DEVIO_OFFS(d) \ - (BRIDGE_DEVIO_BASE + \ - BRIDGE_DEVIO_LARGE * ((d) < 2 ? (d) : 2) + \ - 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) (0x00000240 + 8 * (d)) - -/* - * Read Response Buffer configuration registers - * - * There are 16 RRB, which are shared among the PCI devices. - * The following registers provide four bits per RRB, describing - * their RRB assignment. - * - * Since these four bits only assign two bits to map to a PCI slot, - * the low-order bit is implied by the RRB register: one controls the - * even-numbered PCI slots, while the other controls the odd-numbered - * PCI slots. - */ - -#define BRIDGE_RRB_EVEN 0x00000280 -#define BRIDGE_RRB_ODD 0x00000288 - -#define RRB_VALID 0x8 -#define RRB_VCHAN 0x4 -#define RRB_DEVICE_MASK 0x3 -#define RRB_SHIFT 4 - -/* - * Address Translation Entries - */ - -#define BRIDGE_INTERNAL_ATE 128 -#define XBRIDGE_INTERNAL_ATE 1024 - -#define BRIDGE_ATE_SSHIFT 12 /* 4KB */ -#define BRIDGE_ATE_LSHIFT 14 /* 16KB */ -#define BRIDGE_ATE_SSIZE (1ULL << BRIDGE_ATE_SSHIFT) -#define BRIDGE_ATE_LSIZE (1ULL << BRIDGE_ATE_LSHIFT) -#define BRIDGE_ATE_SMASK (BRIDGE_ATE_SSIZE - 1) -#define BRIDGE_ATE_LMASK (BRIDGE_ATE_LSIZE - 1) - -#define BRIDGE_ATE(a) (0x00010000 + (a) * 8) - -#define ATE_NV 0x0000000000000000ULL -#define ATE_V 0x0000000000000001ULL -#define ATE_COH 0x0000000000000002ULL -#define ATE_PRECISE 0x0000000000000004ULL -#define ATE_PREFETCH 0x0000000000000008ULL -#define ATE_BARRIER 0x0000000000000010ULL -#define ATE_BSWAP 0x0000000000000020ULL /* XB */ -#define ATE_WIDGET_MASK 0x0000000000000f00ULL -#define ATE_WIDGET_SHIFT 8 -#define ATE_ADDRESS_MASK 0x0000fffffffff000ULL -#define ATE_RMF_MASK 0x00ff000000000000ULL /* BR */ - -/* - * PIC Write Request memory - */ - -#define PIC_WR_REQ_LOWER(a) (0x00018000 + (a) * 8) -#define PIC_WR_REQ_UPPER(a) (0x00018800 + (a) * 8) -#define PIC_WR_REQ_PARITY(a) (0x00019000 + (a) * 8) - -#define PIC_WR_REQ_ENTRIES 0x100 - -/* - * Configuration space - * - * Access to the first bus is done in the first area, sorted by - * device number and function number. - * Access to other buses is done in the second area, after programming - * BRIDGE_PCI_CFG to the appropriate bus and slot number. - */ - -#define BRIDGE_PCI_CFG_SPACE 0x00020000 -#define BRIDGE_PCI_CFG1_SPACE 0x00028000 - -/* - * DMA addresses - * The Bridge can do DMA either through a direct 2GB window, or through - * a 1GB translated window, using its ATE memory. - */ - -#define BRIDGE_DMA_TRANSLATED_BASE 0x40000000ULL -#define XBRIDGE_DMA_TRANSLATED_SWAP 0x20000000ULL -#define ATE_ADDRESS(a,s) \ - (BRIDGE_DMA_TRANSLATED_BASE + ((a) << (s))) -#define ATE_INDEX(a,s) \ - (((a) - BRIDGE_DMA_TRANSLATED_BASE) >> (s)) - -#define BRIDGE_DMA_DIRECT_BASE 0x80000000ULL -#define BRIDGE_DMA_DIRECT_LENGTH 0x80000000ULL diff --git a/sys/arch/sgi/xbow/xheart.c b/sys/arch/sgi/xbow/xheart.c deleted file mode 100644 index be5a244a5ae..00000000000 --- a/sys/arch/sgi/xbow/xheart.c +++ /dev/null @@ -1,487 +0,0 @@ -/* $OpenBSD: xheart.c,v 1.33 2020/07/06 13:33:08 pirofti Exp $ */ - -/* - * Copyright (c) 2008 Miodrag Vallat. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * IP30 Heart Widget - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/device.h> -#include <sys/evcount.h> -#include <sys/malloc.h> -#include <sys/timetc.h> -#include <sys/atomic.h> - -#include <machine/autoconf.h> -#include <machine/cpu.h> -#include <mips64/mips_cpu.h> -#include <machine/intr.h> - -#include <sgi/xbow/xbow.h> -#include <sgi/xbow/xbowdevs.h> -#include <sgi/xbow/xheartreg.h> - -#include <dev/onewire/onewirereg.h> -#include <dev/onewire/onewirevar.h> - -struct xheart_softc { - struct device sc_dev; - struct onewire_bus sc_bus; -}; - -int xheart_match(struct device *, void *, void *); -void xheart_attach(struct device *, struct device *, void *); - -const struct cfattach xheart_ca = { - sizeof(struct xheart_softc), xheart_match, xheart_attach, -}; - -struct cfdriver xheart_cd = { - NULL, "xheart", DV_DULL, -}; - -int xheart_ow_reset(void *); -int xheart_ow_read_bit(struct xheart_softc *); -int xheart_ow_send_bit(void *, int); -int xheart_ow_read_byte(void *); -int xheart_ow_triplet(void *, int); -int xheart_ow_pulse(struct xheart_softc *, int, int); - -int xheart_intr_register(int, int, int *); -int xheart_intr_establish(int (*)(void *), void *, int, int, const char *, - struct intrhand *); -void xheart_intr_disestablish(int); -void xheart_intr_clear(int); -void xheart_intr_set(int); -uint32_t xheart_intr_handler(uint32_t, struct trapframe *); -void xheart_intr_makemasks(void); -void xheart_setintrmask(int); -void xheart_splx(int); - -u_int xheart_get_timecount(struct timecounter *); - -struct timecounter xheart_timecounter = { - .tc_get_timecount = xheart_get_timecount, - .tc_poll_pps = NULL, - .tc_counter_mask = 0xffffffff, /* truncate 52-bit counter to 32-bit */ - .tc_frequency = 12500000, - .tc_name = "heart", - .tc_quality = 100, - .tc_priv = NULL, - .tc_user = 0, -}; - -extern uint32_t ip30_lights_frob(uint32_t, struct trapframe *); - -/* - * HEART interrupt handling declarations: 64 sources; 5 levels. - */ - -struct intrhand *xheart_intrhand[HEART_NINTS]; - -#ifdef notyet -#define INTPRI_HEART_4 (INTPRI_CLOCK + 1) -#define INTPRI_HEART_3 (INTPRI_HEART_4 + 1) -#define INTPRI_HEART_2 (INTPRI_HEART_3 + 1) -#define INTPRI_HEART_1 (INTPRI_HEART_2 + 1) -#define INTPRI_HEART_0 (INTPRI_HEART_1 + 1) -#else -#define INTPRI_HEART_2 (INTPRI_IPI) -#define INTPRI_HEART_0 (INTPRI_CLOCK + 1) -#endif -#define INTPRI_HEART_LEDS (INTPRI_HEART_0 + 1) - -uint64_t xheart_intem[MAXCPUS]; -uint64_t xheart_imask[MAXCPUS][NIPLS]; - -int -xheart_match(struct device *parent, void *match, void *aux) -{ - struct xbow_attach_args *xaa = aux; - - if (xaa->xaa_vendor == XBOW_VENDOR_SGI4 && - xaa->xaa_product == XBOW_PRODUCT_SGI4_HEART) - return 1; - - return 0; -} - -void -xheart_attach(struct device *parent, struct device *self, void *aux) -{ - struct xbow_attach_args *xaa = aux; - struct xheart_softc *sc = (void *)self; - struct onewirebus_attach_args oba; - paddr_t heart; - - printf(" revision %d\n", xaa->xaa_revision); - - sc->sc_bus.bus_cookie = sc; - sc->sc_bus.bus_reset = xheart_ow_reset; - sc->sc_bus.bus_bit = xheart_ow_send_bit; - sc->sc_bus.bus_read_byte = xheart_ow_read_byte; - sc->sc_bus.bus_write_byte = NULL; /* use default routine */ - sc->sc_bus.bus_read_block = NULL; /* use default routine */ - sc->sc_bus.bus_write_block = NULL; /* use default routine */ - sc->sc_bus.bus_triplet = xheart_ow_triplet; - sc->sc_bus.bus_matchrom = NULL; /* use default routine */ - sc->sc_bus.bus_search = NULL; /* use default routine */ - - oba.oba_bus = &sc->sc_bus; - oba.oba_flags = ONEWIRE_SCAN_NOW | ONEWIRE_NO_PERIODIC_SCAN; - config_found(self, &oba, onewirebus_print); - - xbow_intr_address = 0x80; - xbow_intr_widget_intr_register = xheart_intr_register; - xbow_intr_widget_intr_establish = xheart_intr_establish; - xbow_intr_widget_intr_disestablish = xheart_intr_disestablish; - xbow_intr_widget_intr_clear = xheart_intr_clear; - xbow_intr_widget_intr_set = xheart_intr_set; - - /* - * Acknowledge and disable all interrupts. - */ - heart = PHYS_TO_XKPHYS(HEART_PIU_BASE, CCA_NC); - *(volatile uint64_t*)(heart + HEART_ISR_CLR) = 0xffffffffffffffffUL; - *(volatile uint64_t*)(heart + HEART_IMR(0)) = 0UL; - *(volatile uint64_t*)(heart + HEART_IMR(1)) = 0UL; - *(volatile uint64_t*)(heart + HEART_IMR(2)) = 0UL; - *(volatile uint64_t*)(heart + HEART_IMR(3)) = 0UL; - -#ifdef notyet - set_intr(INTPRI_HEART_4, CR_INT_4, xheart_intr_handler); - set_intr(INTPRI_HEART_3, CR_INT_3, xheart_intr_handler); -#endif - set_intr(INTPRI_HEART_2, CR_INT_2, xheart_intr_handler); -#ifdef notyet - set_intr(INTPRI_HEART_1, CR_INT_1, xheart_intr_handler); -#endif - set_intr(INTPRI_HEART_0, CR_INT_0, xheart_intr_handler); - - set_intr(INTPRI_HEART_LEDS, CR_INT_5, ip30_lights_frob); - - register_splx_handler(xheart_splx); - - tc_init(&xheart_timecounter); -} - -/* - * Number-In-a-Can (1-Wire) interface - */ - -int -xheart_ow_reset(void *v) -{ - struct xheart_softc *sc = v; - return xheart_ow_pulse(sc, 500, 65); -} - -int -xheart_ow_read_bit(struct xheart_softc *sc) -{ - return xheart_ow_pulse(sc, 6, 13); -} - -int -xheart_ow_send_bit(void *v, int bit) -{ - struct xheart_softc *sc = v; - int rc; - - if (bit != 0) - rc = xheart_ow_pulse(sc, 6, 110); - else - rc = xheart_ow_pulse(sc, 80, 30); - return rc; -} - -int -xheart_ow_read_byte(void *v) -{ - struct xheart_softc *sc = v; - unsigned int byte = 0; - int i; - - for (i = 0; i < 8; i++) - byte |= xheart_ow_read_bit(sc) << i; - - return byte; -} - -int -xheart_ow_triplet(void *v, int dir) -{ - struct xheart_softc *sc = v; - int rc; - - rc = xheart_ow_read_bit(sc); - rc <<= 1; - rc |= xheart_ow_read_bit(sc); - - switch (rc) { - case 0x0: - xheart_ow_send_bit(v, dir); - break; - case 0x1: - xheart_ow_send_bit(v, 0); - break; - default: - xheart_ow_send_bit(v, 1); - break; - } - - return (rc); -} - -int -xheart_ow_pulse(struct xheart_softc *sc, int pulse, int data) -{ - uint64_t mcr_value; - paddr_t heart; - - heart = PHYS_TO_XKPHYS(HEART_PIU_BASE + HEART_MICROLAN, CCA_NC); - mcr_value = (pulse << 10) | (data << 2); - *(volatile uint64_t *)heart = mcr_value; - do { - mcr_value = *(volatile uint64_t *)heart; - } while ((mcr_value & 0x00000002) == 0); - - delay(500); - - return (mcr_value & 1); -} - -/* - * HEART interrupt handling routines - */ - -/* - * Find a suitable interrupt bit for the given interrupt. - */ -int -xheart_intr_register(int widget, int level, int *intrbit) -{ - int bit; - u_long cpuid = cpu_number(); - - /* - * All interrupts will be serviced at hardware level 0, - * so the `level' argument can be ignored. - */ - for (bit = HEART_INTR_WIDGET_MAX; bit >= HEART_INTR_WIDGET_MIN; bit--) - if ((xheart_intem[cpuid] & (1UL << bit)) == 0) - goto found; - - return EINVAL; - -found: - *intrbit = bit; - return 0; -} - -/* - * Register an interrupt handler for a given source, and enable it. - */ -int -xheart_intr_establish(int (*func)(void *), void *arg, int intrbit, - int level, const char *name, struct intrhand *ihstore) -{ - struct intrhand *ih; - int flags; - int s; - u_long cpuid = cpu_number(); - -#ifdef DIAGNOSTIC - if (intrbit < 0 || intrbit >= HEART_NINTS) - return EINVAL; -#endif - - flags = (level & IPL_MPSAFE) ? IH_MPSAFE : 0; - level &= ~IPL_MPSAFE; - - /* - * HEART interrupts are not supposed to be shared - the interrupt - * mask is large enough for all widgets. - */ - if (xheart_intrhand[intrbit] != NULL) - return EEXIST; - - if (ihstore == NULL) { - ih = malloc(sizeof(*ih), M_DEVBUF, M_NOWAIT); - if (ih == NULL) - return ENOMEM; - flags |= IH_ALLOCATED; - } else - ih = ihstore; - - ih->ih_next = NULL; - ih->ih_fun = func; - ih->ih_arg = arg; - ih->ih_level = level; - ih->ih_irq = intrbit; - ih->ih_flags = flags; - if (name != NULL) - evcount_attach(&ih->ih_count, name, &ih->ih_level); - - s = splhigh(); - - xheart_intrhand[intrbit] = ih; - - xheart_intem[cpuid] |= 1UL << intrbit; - xheart_intr_makemasks(); - - splx(s); /* causes hw mask update */ - - return 0; -} - -void -xheart_intr_disestablish(int intrbit) -{ - struct intrhand *ih; - int s; - u_long cpuid = cpu_number(); - -#ifdef DIAGNOSTIC - if (intrbit < 0 || intrbit >= HEART_NINTS) - return; -#endif - - s = splhigh(); - - if ((ih = xheart_intrhand[intrbit]) == NULL) { - splx(s); - return; - } - - xheart_intrhand[intrbit] = NULL; - - xheart_intem[cpuid] &= ~(1UL << intrbit); - xheart_intr_makemasks(); - - splx(s); - - if (ISSET(ih->ih_flags, IH_ALLOCATED)) - free(ih, M_DEVBUF, sizeof *ih); -} - -void -xheart_intr_clear(int intrbit) -{ - *(volatile uint64_t *)PHYS_TO_XKPHYS(HEART_PIU_BASE + HEART_ISR_CLR, - CCA_NC) = 1UL << intrbit; -} - -void -xheart_intr_set(int intrbit) -{ - *(volatile uint64_t *)PHYS_TO_XKPHYS(HEART_PIU_BASE + HEART_ISR_SET, - CCA_NC) = 1UL << intrbit; -} - -void -xheart_splx(int newipl) -{ - struct cpu_info *ci = curcpu(); - - /* Update masks to new ipl. Order highly important! */ - ci->ci_ipl = newipl; - xheart_setintrmask(newipl); - - /* If we still have softints pending trigger processing. */ - if (ci->ci_softpending != 0 && newipl < IPL_SOFTINT) - setsoftintr0(); -} - -/* - * Heart interrupt handler. Can be registered at any hardware interrupt level. - */ - -#define INTR_FUNCTIONNAME xheart_intr_handler -#define MASK_FUNCTIONNAME xheart_intr_makemasks -#define INTR_LOCAL_DECLS \ - paddr_t heart = PHYS_TO_XKPHYS(HEART_PIU_BASE, CCA_NC); \ - u_long cpuid = cpu_number(); -#define MASK_LOCAL_DECLS \ - u_long cpuid = cpu_number(); -#define INTR_GETMASKS \ -do { \ - isr = *(volatile uint64_t *)(heart + HEART_ISR); \ - imr = *(volatile uint64_t *)(heart + HEART_IMR(cpuid)); \ - switch (hwpend) { \ - case CR_INT_0: \ - isr &= HEART_ISR_LVL0_MASK; \ - bit = HEART_ISR_LVL0_MAX; \ - break; \ - case CR_INT_1: \ - isr &= HEART_ISR_LVL1_MASK; \ - bit = HEART_ISR_LVL1_MAX; \ - break; \ - case CR_INT_2: \ - isr &= HEART_ISR_LVL2_MASK; \ - bit = HEART_ISR_LVL2_MAX; \ - break; \ - case CR_INT_3: \ - isr &= HEART_ISR_LVL3_MASK; \ - bit = HEART_ISR_LVL3_MAX; \ - break; \ - case CR_INT_4: \ - isr &= HEART_ISR_LVL4_MASK; \ - bit = HEART_ISR_LVL4_MAX; \ - break; \ - default: \ - return 0; /* can't happen */ \ - } \ -} while (0) -#define INTR_MASKPENDING \ - *(volatile uint64_t *)(heart + HEART_IMR(cpuid)) &= ~isr -#define INTR_IMASK(ipl) xheart_imask[cpuid][ipl] -#define INTR_HANDLER(bit) xheart_intrhand[bit] -#define INTR_SPURIOUS(bit) \ -do { \ - printf("spurious xheart interrupt %d\n", bit); \ -} while (0) -#define INTR_MASKRESTORE \ - *(volatile uint64_t *)(heart + HEART_IMR(cpuid)) = imr -#define INTR_MASKSIZE HEART_NINTS - -#include <sgi/sgi/intr_template.c> - -void -xheart_setintrmask(int level) -{ - paddr_t heart = PHYS_TO_XKPHYS(HEART_PIU_BASE, CCA_NC); - u_long cpuid = cpu_number(); - - *(volatile uint64_t *)(heart + HEART_IMR(cpuid)) = - xheart_intem[cpuid] & ~xheart_imask[cpuid][level]; -} - -/* - * Timecounter interface. - */ - -uint -xheart_get_timecount(struct timecounter *tc) -{ - paddr_t heart = PHYS_TO_XKPHYS(HEART_PIU_BASE, CCA_NC); - - return (u_int)*(volatile uint64_t *)(heart + HEART_CTR_VALUE); -} diff --git a/sys/arch/sgi/xbow/xheartreg.h b/sys/arch/sgi/xbow/xheartreg.h deleted file mode 100644 index 6d498465dbf..00000000000 --- a/sys/arch/sgi/xbow/xheartreg.h +++ /dev/null @@ -1,120 +0,0 @@ -/* $OpenBSD: xheartreg.h,v 1.5 2012/06/17 12:34:19 miod Exp $ */ - -/* - * Copyright (c) 2008, 2011 Miodrag Vallat. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * IP30 HEART registers - */ - -/* physical address in PIU mode */ -#define HEART_PIU_BASE 0x000000000ff00000 - -#define HEART_MODE 0x0000 -#define HEART_MEMORY_STATUS 0x0020 /* 8 32 bit registers */ -#define HEART_MEMORY_VALID 0x80000000 -#define HEART_MEMORY_SIZE_MASK 0x003f0000 -#define HEART_MEMORY_SIZE_SHIFT 16 -#define HEART_MEMORY_ADDR_MASK 0x000001ff -#define HEART_MEMORY_ADDR_SHIFT 0 -#define HEART_MEMORY_UNIT_SHIFT 25 /* 32MB */ - -#define HEART_MICROLAN 0x00b8 - -/* - * Interrupt handling registers. - * The Heart supports four different interrupt targets, although only - * the two cpus are used in practice. - */ - -#define HEART_IMR(s) (0x00010000 + (s) * 8) -#define HEART_ISR_SET 0x00010020 -#define HEART_ISR_CLR 0x00010028 -#define HEART_ISR 0x00010030 - -/* - * ISR bit assignments. - */ - -/** Level 4 interrupt: hardware error */ -#define HEART_ISR_LVL4_MASK 0xfff8000000000000UL -#define HEART_ISR_LVL4_MAX 63 -/* Heart (widget 8) error */ -#define HEART_ISR_WID08_ERROR 63 -/* CPU bus error */ -#define HEART_ISR_CPU_BUSERR(c) (59 + (c)) -/* Crossbow (widget 0) error */ -#define HEART_ISR_WID00_ERROR 58 -/* Widget error */ -#define HEART_ISR_WID0F_ERROR 57 -#define HEART_ISR_WID0E_ERROR 56 -#define HEART_ISR_WID0D_ERROR 55 -#define HEART_ISR_WID0C_ERROR 54 -#define HEART_ISR_WID0B_ERROR 53 -#define HEART_ISR_WID0A_ERROR 52 -#define HEART_ISR_WID09_ERROR 51 - -#define HEART_ISR_WID_ERROR(w) \ - ((w) == 0 ? HEART_ISR_WID00_ERROR : \ - (w) == 8 ? HEART_ISR_WID08_ERROR : HEART_ISR_WID09_ERROR + (w) - 9) - -/** Level 3 interrupt: heart counter/timer */ -#define HEART_ISR_LVL3_MASK 0x0004000000000000UL -#define HEART_ISR_LVL3_MAX 50 -/* Crossbow clock */ -#define HEART_ISR_HEARTCLOCK 50 - -/** Level 2 interrupt */ -#define HEART_ISR_LVL2_MASK 0x0003ffff00000000UL -#define HEART_ISR_LVL2_MAX 49 -/* IPI */ -#define HEART_ISR_IPI(c) (46 + (c)) -/* Debugger interrupts */ -#define HEART_ISR_DBG(c) (42 + (c)) -/* Power switch */ -#define HEART_ISR_POWER 41 -/* 40-32 freely available */ - -/** Level 1 interrupt */ -#define HEART_ISR_LVL1_MASK 0x00000000ffff0000UL -#define HEART_ISR_LVL1_MAX 31 -/* 31-16 freely available */ - -/** Level 0 interrupt */ -#define HEART_ISR_LVL0_MASK 0x000000000000ffffUL -#define HEART_ISR_LVL0_MAX 15 -/* 15-3 freely available */ - -#define HEART_INTR_WIDGET_MAX 15 -#define HEART_INTR_WIDGET_MIN 3 - -#define HEART_NINTS 64 - -/* - * Crossbow clock, as a free-running counter. - * The clock rate is 400 MHz, with the counter running at 1/32 of the clock, - * i.e. 12.5 MHz (80 nS period) - */ - -#define HEART_CTR_VALUE 0x00020000 /* 52-bit counter value, r/o */ -#define HEART_CTR_LIMIT 0x00030000 /* 24-bit limit value */ -#define HEART_CTR_TRIGGER 0x00040000 - -/* - * Per-processor ID register. - */ - -#define HEART_PRID 0x00050000 |