summaryrefslogtreecommitdiff
path: root/sys/arch/sgi/hpc/hpc.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/sgi/hpc/hpc.c')
-rw-r--r--sys/arch/sgi/hpc/hpc.c1044
1 files changed, 0 insertions, 1044 deletions
diff --git a/sys/arch/sgi/hpc/hpc.c b/sys/arch/sgi/hpc/hpc.c
deleted file mode 100644
index c3a2b72ab17..00000000000
--- a/sys/arch/sgi/hpc/hpc.c
+++ /dev/null
@@ -1,1044 +0,0 @@
-/* $OpenBSD: hpc.c,v 1.18 2015/09/18 20:50:02 miod Exp $ */
-/* $NetBSD: hpc.c,v 1.66 2011/07/01 18:53:46 dyoung Exp $ */
-/* $NetBSD: ioc.c,v 1.9 2011/07/01 18:53:47 dyoung Exp $ */
-
-/*
- * Copyright (c) 2003 Christopher Sekiya
- * 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 for the
- * NetBSD Project. See http://www.NetBSD.org/ for
- * information about NetBSD.
- * 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.
- */
-/*
- * Copyright (c) 2000 Soren S. Jorvang
- * Copyright (c) 2001 Rafal K. Boni
- * Copyright (c) 2001 Jason R. Thorpe
- * 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 for the
- * NetBSD Project. See http://www.NetBSD.org/ for
- * information about NetBSD.
- * 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.
- */
-
-/*
- * Combined driver for the HPC (High performance Peripheral Controller)
- * and IOC2 (I/O Controller) chips.
- *
- * It would theoretically be better to attach an IOC driver to HPC on
- * IOC systems (IP22/24/26/28), and attach the few onboard devices
- * which attach directly to HPC on IP20, to IOC. But since IOC depends
- * too much on HPC, the complexity this would introduce is not worth
- * the hassle.
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/device.h>
-#include <sys/timeout.h>
-
-#include <mips64/archtype.h>
-
-#include <machine/autoconf.h>
-#include <machine/bus.h>
-#include <mips64/cache.h>
-#include <machine/cpu.h>
-
-#include <sgi/gio/gioreg.h>
-#include <sgi/gio/giovar.h>
-
-#include <sgi/hpc/hpcreg.h>
-#include <sgi/hpc/hpcvar.h>
-#include <sgi/localbus/imcvar.h>
-#include <sgi/localbus/intreg.h>
-#include <sgi/localbus/intvar.h>
-#include <sgi/hpc/iocreg.h>
-#include <sgi/sgi/ip22.h>
-
-#include <dev/ic/smc93cx6var.h>
-
-struct hpc_device {
- const char *hd_name;
- bus_addr_t hd_base;
- bus_addr_t hd_devoff;
- bus_addr_t hd_dmaoff;
- int hd_irq;
- int hd_sysmask;
-};
-
-#define HPCDEV_IP20 (1U << 1) /* Indigo R4k */
-#define HPCDEV_IP22 (1U << 2) /* Indigo2 */
-#define HPCDEV_IP24 (1U << 3) /* Indy, Challenge S */
-#define HPCDEV_IP24_INDY (1U << 4) /* Indy only */
-
-/*
- * On-board HPC1 devices (IP20 only)
- */
-static const struct hpc_device hpc1_onboard[] = {
- /* probe order is important for IP20 zs */
- { "zs", /* serial 0/1 duart 1 */
- HPC_BASE_ADDRESS_0,
- 0x0d10, 0,
- INT2_L0_INTR(INT2_L0_IP20_SERIAL),
- HPCDEV_IP20 },
- { "zs", /* kbd/ms duart 0 */
- HPC_BASE_ADDRESS_0,
- 0x0d00, 0,
- INT2_L0_INTR(INT2_L0_IP20_SERIAL),
- HPCDEV_IP20 },
- { "sq", /* onboard Ethernet */
- HPC_BASE_ADDRESS_0,
- HPC1_ENET_DEVREGS, HPC1_ENET_REGS,
- INT2_L0_INTR(INT2_L0_ENET),
- HPCDEV_IP20 },
- { "wdsc", /* onboard SCSI */
- HPC_BASE_ADDRESS_0,
- HPC1_SCSI0_DEVREGS, HPC1_SCSI0_REGS,
- INT2_L0_INTR(INT2_L0_SCSI1),
- HPCDEV_IP20 },
- { NULL }
-};
-
-/*
- * On-board HPC3 devices (IP22, IP24)
- */
-static const struct hpc_device hpc3_onboard[] = {
- { "zs", /* serial 0/1 duart 0 */
- HPC_BASE_ADDRESS_0,
- IOC_BASE + IOC_SERIAL_REGS, 0,
- INT2_MAP1_INTR(INT2_MAP_SERIAL),
- HPCDEV_IP22 | HPCDEV_IP24 },
- { "pckbc", /* PS/2 keyboard/mouse controller */
- HPC_BASE_ADDRESS_0,
- IOC_BASE + IOC_KB_REGS, 0,
- INT2_MAP1_INTR(INT2_MAP_PCKBC),
- HPCDEV_IP22 | HPCDEV_IP24_INDY },
- { "sq", /* onboard Ethernet */
- HPC_BASE_ADDRESS_0,
- HPC3_ENET_DEVREGS, HPC3_ENET_REGS,
- INT2_L0_INTR(INT2_L0_ENET),
- HPCDEV_IP22 | HPCDEV_IP24 },
- { "wdsc", /* onboard SCSI */
- HPC_BASE_ADDRESS_0,
- HPC3_SCSI0_DEVREGS, HPC3_SCSI0_REGS,
- INT2_L0_INTR(INT2_L0_IP22_SCSI0),
- HPCDEV_IP22 | HPCDEV_IP24 },
- { "wdsc", /* Indigo2/Challenge M secondary onboard SCSI */
- HPC_BASE_ADDRESS_0,
- HPC3_SCSI1_DEVREGS, HPC3_SCSI1_REGS,
- INT2_L0_INTR(INT2_L0_SCSI1),
- HPCDEV_IP22 },
- { "haltwo", /* onboard audio */
- HPC_BASE_ADDRESS_0,
- HPC3_PBUS_CH0_DEVREGS, HPC3_PBUS_DMAREGS,
- INT2_L1_INTR(INT2_L1_IP22_HPC_DMA),
- HPCDEV_IP22 | HPCDEV_IP24_INDY },
- { "pione", /* onboard parallel port */
- HPC_BASE_ADDRESS_0,
- IOC_BASE + IOC_PLP_REGS, 0,
- INT2_L0_INTR(INT2_L0_IP22_PARALLEL),
- HPCDEV_IP22 | HPCDEV_IP24 },
- { "panel", /* Indy front panel */
- HPC_BASE_ADDRESS_0,
- IOC_BASE + IOC_PANEL, 0,
- INT2_L1_INTR(INT2_L1_IP22_PANEL),
- HPCDEV_IP22 | HPCDEV_IP24 },
- { NULL }
-};
-
-/*
- * Expansion HPC1 devices
- */
-static const struct hpc_device hpc1_devices[] = {
- { "sq", /* E++ GIO adapter */
- 0,
- HPC1_ENET_DEVREGS, HPC1_ENET_REGS,
- -1,
- HPCDEV_IP20 | HPCDEV_IP24 },
- { "wdsc", /* GIO32 SCSI adapter */
- 0,
- HPC1_SCSI0_DEVREGS, HPC1_SCSI0_REGS,
- -1,
- HPCDEV_IP20 | HPCDEV_IP24 },
- { NULL }
-};
-
-/*
- * Expansion HPC3 devices
- */
-static const struct hpc_device hpc3_devices[] = {
- { "sq", /* Challenge S IO+ secondary ethernet */
- HPC_BASE_ADDRESS_1,
- HPC3_ENET_DEVREGS, HPC3_ENET_REGS,
- INT2_L0_INTR(INT2_L0_GIO_SLOT0),
- HPCDEV_IP24 },
-
- { NULL }
-};
-
-struct hpc_softc {
- struct device sc_dev;
-
- bus_addr_t sc_base;
-
- bus_space_tag_t sc_ct;
- bus_space_handle_t sc_ch;
- bus_dma_tag_t sc_dmat;
-
- struct timeout sc_blink_tmo;
-};
-
-static struct hpc_values hpc1_values = {
- .revision = 1,
- .scsi0_regs = HPC1_SCSI0_REGS,
- .scsi0_regs_size = HPC1_SCSI0_REGS_SIZE,
- .scsi0_cbp = HPC1_SCSI0_CBP,
- .scsi0_ndbp = HPC1_SCSI0_NDBP,
- .scsi0_bc = HPC1_SCSI0_BC,
- .scsi0_ctl = HPC1_SCSI0_CTL,
- .scsi0_gio = HPC1_SCSI0_GIO,
- .scsi0_dev = HPC1_SCSI0_DEV,
- .scsi0_dmacfg = HPC1_SCSI0_DMACFG,
- .scsi0_piocfg = HPC1_SCSI0_PIOCFG,
- .scsi1_regs = 0,
- .scsi1_regs_size = 0,
- .scsi1_cbp = 0,
- .scsi1_ndbp = 0,
- .scsi1_bc = 0,
- .scsi1_ctl = 0,
- .scsi1_gio = 0,
- .scsi1_dev = 0,
- .scsi1_dmacfg = 0,
- .scsi1_piocfg = 0,
- .enet_regs = HPC1_ENET_REGS,
- .enet_regs_size = HPC1_ENET_REGS_SIZE,
- .enet_intdelay = HPC1_ENET_INTDELAY,
- .enet_intdelayval = HPC1_ENET_INTDELAY_OFF,
- .enetr_cbp = HPC1_ENETR_CBP,
- .enetr_ndbp = HPC1_ENETR_NDBP,
- .enetr_bc = HPC1_ENETR_BC,
- .enetr_ctl = HPC1_ENETR_CTL,
- .enetr_ctl_active = HPC1_ENETR_CTL_ACTIVE,
- .enetr_reset = HPC1_ENETR_RESET,
- .enetr_dmacfg = 0,
- .enetr_piocfg = 0,
- .enetx_cbp = HPC1_ENETX_CBP,
- .enetx_ndbp = HPC1_ENETX_NDBP,
- .enetx_bc = HPC1_ENETX_BC,
- .enetx_ctl = HPC1_ENETX_CTL,
- .enetx_ctl_active = HPC1_ENETX_CTL_ACTIVE,
- .enetx_dev = 0,
- .enetr_fifo = HPC1_ENETR_FIFO,
- .enetr_fifo_size = HPC1_ENETR_FIFO_SIZE,
- .enetx_fifo = HPC1_ENETX_FIFO,
- .enetx_fifo_size = HPC1_ENETX_FIFO_SIZE,
- .enet_devregs = HPC1_ENET_DEVREGS,
- .enet_devregs_size = HPC1_ENET_DEVREGS_SIZE,
- .pbus_fifo = 0,
- .pbus_fifo_size = 0,
- .pbus_bbram = 0,
-#define MAX_SCSI_XFER (roundup(MAXPHYS, PAGE_SIZE))
- .scsi_dma_segs = (MAX_SCSI_XFER / 4096),
- .scsi_dma_segs_size = 4096,
- .scsi_dma_datain_cmd = (HPC1_SCSI_DMACTL_ACTIVE | HPC1_SCSI_DMACTL_DIR),
- .scsi_dma_dataout_cmd = HPC1_SCSI_DMACTL_ACTIVE,
- .scsi_dmactl_flush = HPC1_SCSI_DMACTL_FLUSH,
- .scsi_dmactl_active = HPC1_SCSI_DMACTL_ACTIVE,
- .scsi_dmactl_reset = HPC1_SCSI_DMACTL_RESET
-};
-
-static struct hpc_values hpc3_values = {
- .revision = 3,
- .scsi0_regs = HPC3_SCSI0_REGS,
- .scsi0_regs_size = HPC3_SCSI0_REGS_SIZE,
- .scsi0_cbp = HPC3_SCSI0_CBP,
- .scsi0_ndbp = HPC3_SCSI0_NDBP,
- .scsi0_bc = HPC3_SCSI0_BC,
- .scsi0_ctl = HPC3_SCSI0_CTL,
- .scsi0_gio = HPC3_SCSI0_GIO,
- .scsi0_dev = HPC3_SCSI0_DEV,
- .scsi0_dmacfg = HPC3_SCSI0_DMACFG,
- .scsi0_piocfg = HPC3_SCSI0_PIOCFG,
- .scsi1_regs = HPC3_SCSI1_REGS,
- .scsi1_regs_size = HPC3_SCSI1_REGS_SIZE,
- .scsi1_cbp = HPC3_SCSI1_CBP,
- .scsi1_ndbp = HPC3_SCSI1_NDBP,
- .scsi1_bc = HPC3_SCSI1_BC,
- .scsi1_ctl = HPC3_SCSI1_CTL,
- .scsi1_gio = HPC3_SCSI1_GIO,
- .scsi1_dev = HPC3_SCSI1_DEV,
- .scsi1_dmacfg = HPC3_SCSI1_DMACFG,
- .scsi1_piocfg = HPC3_SCSI1_PIOCFG,
- .enet_regs = HPC3_ENET_REGS,
- .enet_regs_size = HPC3_ENET_REGS_SIZE,
- .enet_intdelay = 0,
- .enet_intdelayval = 0,
- .enetr_cbp = HPC3_ENETR_CBP,
- .enetr_ndbp = HPC3_ENETR_NDBP,
- .enetr_bc = HPC3_ENETR_BC,
- .enetr_ctl = HPC3_ENETR_CTL,
- .enetr_ctl_active = HPC3_ENETR_CTL_ACTIVE,
- .enetr_reset = HPC3_ENETR_RESET,
- .enetr_dmacfg = HPC3_ENETR_DMACFG,
- .enetr_piocfg = HPC3_ENETR_PIOCFG,
- .enetx_cbp = HPC3_ENETX_CBP,
- .enetx_ndbp = HPC3_ENETX_NDBP,
- .enetx_bc = HPC3_ENETX_BC,
- .enetx_ctl = HPC3_ENETX_CTL,
- .enetx_ctl_active = HPC3_ENETX_CTL_ACTIVE,
- .enetx_dev = HPC3_ENETX_DEV,
- .enetr_fifo = HPC3_ENETR_FIFO,
- .enetr_fifo_size = HPC3_ENETR_FIFO_SIZE,
- .enetx_fifo = HPC3_ENETX_FIFO,
- .enetx_fifo_size = HPC3_ENETX_FIFO_SIZE,
- .enet_devregs = HPC3_ENET_DEVREGS,
- .enet_devregs_size = HPC3_ENET_DEVREGS_SIZE,
- .pbus_fifo = HPC3_PBUS_FIFO,
- .pbus_fifo_size = HPC3_PBUS_FIFO_SIZE,
- .pbus_bbram = HPC3_PBUS_BBRAM,
- .scsi_dma_segs = (MAX_SCSI_XFER / 8192),
- .scsi_dma_segs_size = 8192,
- .scsi_dma_datain_cmd = HPC3_SCSI_DMACTL_ACTIVE,
- .scsi_dma_dataout_cmd =(HPC3_SCSI_DMACTL_ACTIVE | HPC3_SCSI_DMACTL_DIR),
- .scsi_dmactl_flush = HPC3_SCSI_DMACTL_FLUSH,
- .scsi_dmactl_active = HPC3_SCSI_DMACTL_ACTIVE,
- .scsi_dmactl_reset = HPC3_SCSI_DMACTL_RESET
-};
-
-int hpc_match(struct device *, void *, void *);
-void hpc_attach(struct device *, struct device *, void *);
-int hpc_print(void *, const char *);
-
-int hpc_revision(struct hpc_softc *, struct gio_attach_args *);
-int hpc_submatch(struct device *, void *, void *);
-int hpc_power_intr(void *);
-void hpc_blink(void *);
-void hpc_blink_ioc(void *);
-int hpc_read_eeprom(int, bus_space_tag_t, bus_space_handle_t, uint8_t *,
- size_t);
-
-struct hpc_dma_desc *hpc_sync_dma_desc_par(struct hpc_dma_desc *,
- struct hpc_dma_desc *);
-struct hpc_dma_desc *hpc_sync_dma_desc_ecc(struct hpc_dma_desc *,
- struct hpc_dma_desc *);
-void hpc_update_dma_desc_par(struct hpc_dma_desc *, struct hpc_dma_desc *);
-void hpc_update_dma_desc_ecc(struct hpc_dma_desc *, struct hpc_dma_desc *);
-
-/* globals since they depend upon the system type, not the hpc version */
-struct hpc_dma_desc *(*hpc_sync_dma_desc_fn)(struct hpc_dma_desc *,
- struct hpc_dma_desc *);
-void (*hpc_update_dma_desc_fn)(struct hpc_dma_desc *, struct hpc_dma_desc *);
-
-const struct cfattach hpc_ca = {
- sizeof(struct hpc_softc), hpc_match, hpc_attach
-};
-
-struct cfdriver hpc_cd = {
- NULL, "hpc", DV_DULL
-};
-
-void hpc3_space_barrier(bus_space_tag_t, bus_space_handle_t, bus_size_t,
- bus_size_t, int);
-
-bus_space_t hpc3bus_tag = {
- PHYS_TO_XKPHYS(0, CCA_NC),
- NULL,
- imc_read_1, imc_write_1,
- imc_read_2, imc_write_2,
- imc_read_4, imc_write_4,
- imc_read_8, imc_write_8,
- imc_read_raw_2, imc_write_raw_2,
- imc_read_raw_4, imc_write_raw_4,
- imc_read_raw_8, imc_write_raw_8,
- imc_space_map, imc_space_unmap, imc_space_region,
- imc_space_vaddr, hpc3_space_barrier
-};
-
-int
-hpc_match(struct device *parent, void *vcf, void *aux)
-{
- struct gio_attach_args* ga = aux;
- uint32_t dummy;
-
- /* Make sure it's actually there and readable */
- if (guarded_read_4(PHYS_TO_XKPHYS(ga->ga_addr, CCA_NC), &dummy) == 0)
- return 1;
-
- return 0;
-}
-
-void
-hpc_attach(struct device *parent, struct device *self, void *aux)
-{
- struct hpc_softc *sc = (struct hpc_softc *)self;
- struct gio_attach_args* ga = aux;
- struct hpc_attach_args ha;
- const struct hpc_device *hd;
- struct hpc_values *hv;
- uint32_t probe32;
- uint8_t probe8;
- uint32_t hpctype;
- int isonboard;
- int isioplus;
- int giofast;
- int needprobe;
- int sysmask = 0;
-
- sc->sc_base = ga->ga_addr;
- sc->sc_ct = ga->ga_iot;
- sc->sc_ch = PHYS_TO_XKPHYS(sc->sc_base, CCA_NC);
- sc->sc_dmat = ga->ga_dmat;
-
- /* setup HPC DMA helpers if not done already */
- if (hpc_sync_dma_desc_fn == NULL) {
- if (ip22_ecc) {
- hpc_sync_dma_desc_fn = hpc_sync_dma_desc_ecc;
- hpc_update_dma_desc_fn = hpc_update_dma_desc_ecc;
- } else {
- hpc_sync_dma_desc_fn = hpc_sync_dma_desc_par;
- hpc_update_dma_desc_fn = hpc_update_dma_desc_par;
- }
- }
-
- switch (sys_config.system_type) {
- case SGI_IP20:
- sysmask = HPCDEV_IP20;
- break;
- case SGI_IP22:
- case SGI_IP26:
- case SGI_IP28:
- switch (sys_config.system_subtype) {
- default:
- case IP22_INDIGO2:
- sysmask = HPCDEV_IP22;
- break;
- case IP22_CHALLS:
- sysmask = HPCDEV_IP24;
- break;
- case IP22_INDY:
- sysmask = HPCDEV_IP24 | HPCDEV_IP24_INDY;
- break;
- }
- break;
- };
-
- if ((hpctype = hpc_revision(sc, ga)) == 0) {
- printf(": could not identify HPC revision\n");
- return;
- }
-
- if (hpctype != 3)
- hpc_old = 1;
-
- /* force big-endian mode */
- if (hpctype == 15)
- bus_space_write_4(sc->sc_ct, sc->sc_ch, HPC1_BIGENDIAN, 0);
-
- /*
- * Select the proper bus_space_tag for child devices. HPC3 need a
- * specific barrier function.
- */
- if (hpctype == 3)
- sc->sc_ct = &hpc3bus_tag;
-
- /*
- * All machines have only one HPC on the mainboard itself. ''Extra''
- * HPCs require bus arbiter and other magic to run happily.
- */
- isonboard = (sc->sc_base == HPC_BASE_ADDRESS_0);
- isioplus = (sc->sc_base == HPC_BASE_ADDRESS_1 && hpctype == 3 &&
- (sysmask & HPCDEV_IP24) != 0);
-
- printf(": SGI HPC%d%s (%s)\n", (hpctype == 3) ? 3 : 1,
- (hpctype == 15) ? ".5" : "", (isonboard) ? "onboard" :
- (isioplus) ? "IO+ mezzanine" : "GIO slot");
-
- /*
- * Configure the IOC.
- */
- if (isonboard && sys_config.system_type != SGI_IP20) {
- /* Reset IOC */
- bus_space_write_4(sc->sc_ct, sc->sc_ch, IOC_BASE + IOC_RESET,
- IOC_RESET_PARALLEL | IOC_RESET_PCKBC | IOC_RESET_EISA |
- IOC_RESET_ISDN | IOC_RESET_LED_GREEN );
-
- /*
- * Set the two serial ports to PC mode.
- */
- bus_space_write_4(sc->sc_ct, sc->sc_ch, IOC_BASE + IOC_WRITE,
- bus_space_read_4(sc->sc_ct, sc->sc_ch,
- IOC_BASE + IOC_WRITE) |
- IOC_WRITE_PC_UART2 | IOC_WRITE_PC_UART1);
-
- /* XXX: the firmware should have taken care of this already */
-#if 0
- if (sys_config.system_subtype != IP22_INDIGO2) {
- bus_space_write_4(sc->sc_ct, sc->sc_ch,
- IOC_BASE + IOC_GCSEL, 0xff);
- bus_space_write_4(sc->sc_ct, sc->sc_ch,
- IOC_BASE + IOC_GCREG, 0xff);
- }
-#endif
- }
-
- /*
- * Configure the bus arbiter appropriately.
- *
- * In the case of Challenge S, we must tell the IO+ board which
- * DMA channel to use (we steal it from one of the slots). SGI allows
- * an HPC1.5 in slot 1, in which case IO+ must use EXP0, or any
- * other DMA-capable board in slot 0, which leaves us to use EXP1. Of
- * course, this means that only one GIO board may use DMA.
- *
- * Note that this never happens on Indigo2.
- */
- if (isioplus) {
- int arb_slot;
-
- if (guarded_read_4(PHYS_TO_XKPHYS(HPC_BASE_ADDRESS_2, CCA_NC),
- &probe32) != 0)
- arb_slot = GIO_SLOT_EXP1;
- else
- arb_slot = GIO_SLOT_EXP0;
-
- if (gio_arb_config(arb_slot, GIO_ARB_LB | GIO_ARB_MST |
- GIO_ARB_64BIT | GIO_ARB_HPC2_64BIT)) {
- printf("%s: failed to configure GIO bus arbiter\n",
- sc->sc_dev.dv_xname);
- return;
- }
-
- printf("%s: using EXP%d's DMA channel\n",
- sc->sc_dev.dv_xname,
- (arb_slot == GIO_SLOT_EXP0) ? 0 : 1);
-
- bus_space_write_4(sc->sc_ct, sc->sc_ch,
- HPC3_PBUS_CFGPIO_REGS, 0x0003ffff);
-
- if (arb_slot == GIO_SLOT_EXP0)
- bus_space_write_4(sc->sc_ct, sc->sc_ch,
- HPC3_PBUS_CH0_DEVREGS, 0x20202020);
- else
- bus_space_write_4(sc->sc_ct, sc->sc_ch,
- HPC3_PBUS_CH0_DEVREGS, 0x30303030);
- } else if (!isonboard) {
- int arb_slot;
-
- arb_slot = (sc->sc_base == HPC_BASE_ADDRESS_1) ?
- GIO_SLOT_EXP0 : GIO_SLOT_EXP1;
-
- if (gio_arb_config(arb_slot, GIO_ARB_RT | GIO_ARB_MST)) {
- printf("%s: failed to configure GIO bus arbiter\n",
- sc->sc_dev.dv_xname);
- return;
- }
- }
-
- hpc_read_eeprom(hpctype, sc->sc_ct, sc->sc_ch,
- ha.hpc_eeprom, sizeof(ha.hpc_eeprom));
-
- if (hpctype == 3) {
- hv = &hpc3_values;
- if (isonboard) {
- hd = hpc3_onboard;
- if (sys_config.system_subtype == IP22_INDIGO2) {
- /* wild guess */
- giofast = 1;
- } else {
- /*
- * According to IRIX hpc3.h, the fast GIO bit
- * is active high, but the register value has
- * been found to be 0xf8 on slow GIO systems
- * and 0xf1 on fast ones, which tends to prove
- * the opposite...
- */
- if (bus_space_read_4(sc->sc_ct, sc->sc_ch,
- IOC_BASE + IOC_GCREG) & IOC_GCREG_GIO_33MHZ)
- giofast = 0;
- else
- giofast = 1;
- }
- } else {
- hd = hpc3_devices;
- /*
- * XXX should IO+ Mezzanine use the same settings as
- * XXX the onboard HPC3?
- */
- giofast = 0;
- }
- needprobe = 0;
- } else {
- hv = &hpc1_values;
- hv->revision = hpctype;
- giofast = 0;
- if (isonboard) {
- hd = hpc1_onboard;
- needprobe = 0;
- } else {
- hd = hpc1_devices;
- /*
- * Until a reliable way of telling E++ and GIO32 SCSI
- * boards apart is found, we will need to do basic
- * chip existence checks before attempting to attach.
- */
- needprobe = 1;
- }
- }
- for (; hd->hd_name != NULL; hd++) {
- if ((hd->hd_sysmask & sysmask) == 0 ||
- (hd->hd_base != 0 && hd->hd_base != sc->sc_base))
- continue;
-
- ha.ha_name = hd->hd_name;
- ha.ha_base = sc->sc_base;
- ha.ha_devoff = hd->hd_devoff;
- ha.ha_dmaoff = hd->hd_dmaoff;
- /*
- * Compute the interrupt line for HPC1 expansion boards.
- * This allows the hpc1_devices[] array to remain compact.
- */
- if (hd->hd_irq < 0) {
- if (sys_config.system_type == SGI_IP20)
- ha.ha_irq = INT2_L0_INTR(INT2_L0_GIO_LVL1);
- else {
- if (sc->sc_base == HPC_BASE_ADDRESS_1)
- ha.ha_irq =
- INT2_MAP0_INTR(INT2_MAP_GIO_SLOT0);
- else
- ha.ha_irq =
- INT2_MAP0_INTR(INT2_MAP_GIO_SLOT1);
- }
- } else
- ha.ha_irq = hd->hd_irq;
-
- ha.ha_st = sc->sc_ct;
- ha.ha_sh = sc->sc_ch;
- ha.ha_dmat = sc->sc_dmat;
- ha.hpc_regs = hv;
- ha.ha_giofast = giofast;
-
- /*
- * On hpc@gio boards such as the E++, we want to avoid
- * `wdsc not configured' messages (or sq on SCSI boards).
- * The following checks are borrowed from the sq(4) and
- * wdsc(4) respective probes.
- */
- if (needprobe) {
- paddr_t pa;
- volatile uint32_t *reg;
-
- if (strcmp(hd->hd_name, "sq") == 0) {
- /*
- * E++ registers aren't accessible until
- * the reset register is written to.
- */
- pa = sc->sc_ch + hd->hd_dmaoff +
- hv->enetr_reset;
- reg = (volatile uint32_t *)
- PHYS_TO_XKPHYS(pa, CCA_NC);
- if (guarded_read_4((vaddr_t)reg, &probe32) != 0)
- continue;
- *reg = 0x01;
- delay(20);
- *reg = 0x00;
-
- pa = sc->sc_ch + hd->hd_devoff +
- (7 << 2); /* SEEQ_TXSTAT */
- reg = (volatile uint32_t *)
- PHYS_TO_XKPHYS(pa, CCA_NC);
- if (guarded_read_4((vaddr_t)reg, &probe32) != 0)
- continue;
- if ((probe32 & 0xff) != 0x80) /*TXSTAT_OLDNEW*/
- continue;
- } else
- /* if (strcmp(hd->hd_name, "wdsc") == 0) */ {
- /*
- * wdsc registers may not be accessible
- * until the dma engine is reset.
- */
- pa = sc->sc_ch + hd->hd_dmaoff +
- hv->scsi0_ctl;
- reg = (volatile uint32_t *)
- PHYS_TO_XKPHYS(pa, CCA_NC);
- if (guarded_read_4((vaddr_t)reg, &probe32) != 0)
- continue;
- *reg = hv->scsi_dmactl_reset;
- delay(1000);
- *reg = 0;
- delay(1000);
-
- pa = sc->sc_ch + hd->hd_devoff + 3;
- if (guarded_read_1(PHYS_TO_XKPHYS(pa, CCA_NC),
- &probe8) != 0)
- continue;
- if (probe8 == 0xff)
- continue;
- }
- }
-
- config_found_sm(self, &ha, hpc_print, hpc_submatch);
- }
-
- /*
- * Attach the clock chip as well if on hpc0.
- */
- if (isonboard) {
- if (sys_config.system_type == SGI_IP20) {
- ha.ha_name = "dpclock";
- ha.ha_devoff = HPC1_PBUS_BBRAM;
- } else {
- ha.ha_name = "dsclock";
- ha.ha_devoff = HPC3_PBUS_BBRAM;
- }
- ha.ha_base = sc->sc_base;
- ha.ha_dmaoff = 0;
- ha.ha_irq = -1;
- ha.ha_st = sc->sc_ct;
- ha.ha_sh = sc->sc_ch;
- ha.ha_dmat = sc->sc_dmat;
- ha.hpc_regs = NULL;
- ha.ha_giofast = giofast;
-
- config_found_sm(self, &ha, hpc_print, hpc_submatch);
-
- if (sys_config.system_type == SGI_IP20) {
- timeout_set(&sc->sc_blink_tmo, hpc_blink, sc);
- hpc_blink(sc);
- } else {
- timeout_set(&sc->sc_blink_tmo, hpc_blink_ioc, sc);
- hpc_blink_ioc(sc);
- }
- }
-}
-
-/*
- * HPC revision detection isn't as simple as it should be. Devices probe
- * differently depending on their slots, but luckily there is only one
- * instance in which we have to decide the major revision (HPC1 vs HPC3).
- *
- * The HPC is found in the following configurations:
- * o Indigo R4k
- * One on-board HPC1 or HPC1.5.
- * Up to two additional HPC1.5's in GIO slots 0 and 1.
- * o Indy
- * One on-board HPC3.
- * Up to two additional HPC1.5's in GIO slots 0 and 1.
- * o Challenge S
- * One on-board HPC3.
- * Up to one additional HPC3 on the IO+ board (if installed).
- * Up to one additional HPC1.5 in slot 1 of the IO+ board.
- * o Indigo2, Challenge M
- * One on-board HPC3.
- *
- * All we really have to worry about is the IP24 case.
- */
-int
-hpc_revision(struct hpc_softc *sc, struct gio_attach_args *ga)
-{
- uint32_t reg;
-
- /* No hardware ever supported the last hpc base address. */
- if (ga->ga_addr == HPC_BASE_ADDRESS_3)
- return 0;
-
- switch (sys_config.system_type) {
- case SGI_IP20:
- if (guarded_read_4(PHYS_TO_XKPHYS(ga->ga_addr + HPC1_BIGENDIAN,
- CCA_NC), &reg) != 0) {
- if (((reg >> HPC1_REVSHIFT) & HPC1_REVMASK) ==
- HPC1_REV15)
- return 15;
- else
- return 1;
- }
- return 1;
-
- case SGI_IP22:
- case SGI_IP26:
- case SGI_IP28:
- if (ga->ga_addr == HPC_BASE_ADDRESS_0)
- return 3;
-
- if (sys_config.system_subtype == IP22_INDIGO2)
- return 0;
-
- /*
- * If IP24, probe slot 0 to determine if HPC1.5 or HPC3. Slot 1
- * must be HPC1.5.
- */
-
- if (ga->ga_addr == HPC_BASE_ADDRESS_2)
- return 15;
-
- /*
- * Probe for it. We use one of the PBUS registers. Note
- * that this probe succeeds with my E++ adapter in slot 1
- * (bad), but it appears to always do the right thing in
- * slot 0 (good!) and we're only worried about that one
- * anyhow.
- */
- if (guarded_read_4(PHYS_TO_XKPHYS(ga->ga_addr +
- HPC3_PBUS_CH7_BP, CCA_NC), &reg) != 0)
- return 15;
- else
- return 3;
- }
-
- return 0;
-}
-
-int
-hpc_submatch(struct device *parent, void *vcf, void *aux)
-{
- struct cfdata *cf = (struct cfdata *)vcf;
- struct hpc_attach_args *ha = (struct hpc_attach_args *)aux;
-
- if (cf->cf_loc[0 /*HPCCF_OFFSET*/] != -1 &&
- (bus_addr_t)cf->cf_loc[0 /*HPCCF_OFFSET*/] != ha->ha_devoff)
- return 0;
-
- return (*cf->cf_attach->ca_match)(parent, cf, aux);
-}
-
-int
-hpc_print(void *aux, const char *pnp)
-{
- struct hpc_attach_args *ha = aux;
-
- if (pnp)
- printf("%s at %s", ha->ha_name, pnp);
-
- printf(" offset 0x%08lx", ha->ha_devoff);
- if (ha->ha_irq >= 0)
- printf(" irq %d", ha->ha_irq);
-
- return UNCONF;
-}
-
-void *
-hpc_intr_establish(int irq, int level, int (*handler)(void *), void *arg,
- const char *what)
-{
- return int2_intr_establish(irq, level, handler, arg, what);
-}
-
-int
-hpc_is_intr_pending(int irq)
-{
- return int2_is_intr_pending(irq);
-}
-
-void
-hpc_intr_disable(void *v)
-{
- int2_intr_disable(v);
-}
-
-void
-hpc_intr_enable(void *v)
-{
- int2_intr_enable(v);
-}
-
-/*
- * bus_space_barrier() function for HPC3 (which have a write buffer)
- */
-void
-hpc3_space_barrier(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offs,
- bus_size_t sz, int how)
-{
- mips_sync();
- /* just read a side-effect free register */
- (void)*(volatile uint32_t *)
- PHYS_TO_XKPHYS(HPC_BASE_ADDRESS_0 + HPC3_INTRSTAT_40, CCA_NC);
-}
-
-void
-hpc_blink(void *arg)
-{
- struct hpc_softc *sc = arg;
-
- bus_space_write_1(sc->sc_ct, sc->sc_ch, HPC1_AUX_REGS,
- bus_space_read_1(sc->sc_ct, sc->sc_ch, HPC1_AUX_REGS) ^
- HPC1_AUX_CONSLED);
-
- timeout_add(&sc->sc_blink_tmo,
- (((averunnable.ldavg[0] + FSCALE) * hz) >> (FSHIFT + 1)));
-}
-
-void
-hpc_blink_ioc(void *arg)
-{
- struct hpc_softc *sc = arg;
- uint32_t value;
-
- /* This is a bit odd. To strobe the green LED, we have to toggle the
- red control bit. */
- value = bus_space_read_4(sc->sc_ct, sc->sc_ch, IOC_BASE + IOC_RESET) &
- 0xff;
- value ^= IOC_RESET_LED_RED;
- bus_space_write_4(sc->sc_ct, sc->sc_ch, IOC_BASE + IOC_RESET, value);
-
- timeout_add(&sc->sc_blink_tmo,
- (((averunnable.ldavg[0] + FSCALE) * hz) >> (FSHIFT + 1)));
-}
-
-/*
- * Read the eeprom associated with one of the HPC's.
- *
- * NB: An eeprom is not always present, but the HPC should be able to
- * handle this gracefully. Any consumers should validate the data to
- * ensure it's reasonable.
- */
-int
-hpc_read_eeprom(int hpctype, bus_space_tag_t t, bus_space_handle_t h,
- uint8_t *buf, size_t len)
-{
- struct seeprom_descriptor sd;
- bus_space_handle_t bsh;
- bus_size_t offset;
-
- if (!len || len & 0x1)
- return (1);
-
- offset = (hpctype == 3) ? HPC3_EEPROM_DATA : HPC1_AUX_REGS;
-
- if (bus_space_subregion(t, h, offset, 1, &bsh) != 0)
- return (1);
-
- sd.sd_chip = C56_66;
- sd.sd_tag = t;
- sd.sd_bsh = bsh;
- sd.sd_regsize = 1;
- sd.sd_control_offset = 0;
- sd.sd_status_offset = 0;
- sd.sd_dataout_offset = 0;
- sd.sd_DI = 0x10; /* EEPROM -> CPU */
- sd.sd_DO = 0x08; /* CPU -> EEPROM */
- sd.sd_CK = 0x04;
- sd.sd_CS = 0x02;
- sd.sd_MS = 0;
- sd.sd_RDY = 0;
-
- if (read_seeprom(&sd, (uint16_t *)buf, 0, len / 2) != 1)
- return (1);
-
- bus_space_unmap(t, bsh, 1);
-
- return 0;
-}
-
-/*
- * Routines to update HPC DMA descriptors.
- */
-
-struct hpc_dma_desc *
-hpc_sync_dma_desc(struct hpc_dma_desc *desc, struct hpc_dma_desc *store)
-{
- return (*hpc_sync_dma_desc_fn)(desc, store);
-}
-
-void
-hpc_update_dma_desc(struct hpc_dma_desc *desc, struct hpc_dma_desc *store)
-{
- (*hpc_update_dma_desc_fn)(desc, store);
-}
-
-/*
- * Parity MC flavour: descriptors are in non-cacheable memory, to which
- * accesses are allowed. No cache operation is needed.
- */
-
-struct hpc_dma_desc *
-hpc_sync_dma_desc_par(struct hpc_dma_desc *desc, struct hpc_dma_desc *store)
-{
- /* nothing to do */
- return desc;
-}
-
-void
-hpc_update_dma_desc_par(struct hpc_dma_desc *desc, struct hpc_dma_desc *store)
-{
- /* nothing to do */
- KDASSERT(desc == store);
-}
-
-/*
- * ECC MC flavour: descriptor are in cacheable memory, and need to be
- * evicted from cache before reading, and flushed from cache after updating.
- *
- * In addition, on R1000 systems, an actual copy of the descriptor needs
- * to be performed, to prevent speculative execution from writing to the
- * cached descriptor.
- */
-
-struct hpc_dma_desc *
-hpc_sync_dma_desc_ecc(struct hpc_dma_desc *desc, struct hpc_dma_desc *store)
-{
- Mips_IOSyncDCache(curcpu(),
- (vaddr_t)desc, sizeof(struct hpc_dma_desc), CACHE_SYNC_R);
-
- store->hdd_bufptr = desc->hdd_bufptr;
- store->hdd_ctl = desc->hdd_ctl;
- store->hdd_descptr = desc->hdd_descptr;
-
- return store;
-}
-
-void
-hpc_update_dma_desc_ecc(struct hpc_dma_desc *desc, struct hpc_dma_desc *store)
-{
- desc->hdd_bufptr = store->hdd_bufptr;
- desc->hdd_ctl = store->hdd_ctl;
- desc->hdd_descptr = store->hdd_descptr;
-
- Mips_IOSyncDCache(curcpu(),
- (vaddr_t)desc, sizeof(struct hpc_dma_desc), CACHE_SYNC_X);
-}