diff options
author | Per Fogelstrom <pefo@cvs.openbsd.org> | 2004-08-06 21:12:20 +0000 |
---|---|---|
committer | Per Fogelstrom <pefo@cvs.openbsd.org> | 2004-08-06 21:12:20 +0000 |
commit | 925b1250f6b872a48c9a2aa6bc2f6177da057b1a (patch) | |
tree | e6e77d6b0c34da676f47a343a20fd219381b233c /sys/arch/sgi/localbus | |
parent | c15733015711563a770a7a71ad99d8158fc36663 (diff) |
initial sgi import
Diffstat (limited to 'sys/arch/sgi/localbus')
-rw-r--r-- | sys/arch/sgi/localbus/com_lbus.c | 135 | ||||
-rw-r--r-- | sys/arch/sgi/localbus/crimebus.h | 77 | ||||
-rw-r--r-- | sys/arch/sgi/localbus/macebus.c | 782 | ||||
-rw-r--r-- | sys/arch/sgi/localbus/macebus.h | 120 | ||||
-rw-r--r-- | sys/arch/sgi/localbus/macectrl.S | 55 |
5 files changed, 1169 insertions, 0 deletions
diff --git a/sys/arch/sgi/localbus/com_lbus.c b/sys/arch/sgi/localbus/com_lbus.c new file mode 100644 index 00000000000..3e45d1f8ec2 --- /dev/null +++ b/sys/arch/sgi/localbus/com_lbus.c @@ -0,0 +1,135 @@ +/* $OpenBSD: com_lbus.c,v 1.1 2004/08/06 21:12:19 pefo Exp $ */ + +/* + * Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * 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. + * + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/tty.h> + +#include <machine/autoconf.h> +#include <mips64/archtype.h> +#include <machine/bus.h> +#include <machine/intr.h> + +#include <dev/ic/comreg.h> +#include <dev/ic/comvar.h> +#include <dev/ic/ns16550reg.h> + +int com_localbus_probe(struct device *, void *, void *); +void com_localbus_attach(struct device *, struct device *, void *); + + +struct cfattach com_localbus_ca = { + sizeof(struct com_softc), com_localbus_probe, com_localbus_attach +}; + +extern void com_raisedtr(void *); +extern struct timeout compoll_to; + +int +com_localbus_probe(parent, match, aux) + struct device *parent; + void *match, *aux; +{ + bus_space_tag_t iot; + bus_space_handle_t ioh; + int iobase; + int rv; + struct cfdata *cf = match; + struct confargs *ca = aux; + + /* + * Check if this is our com. If low nibble is 0 match + * against system CLASS. Else a perfect match is checked. + */ + if ((ca->ca_sys & 0x000f) == 0) { + if (ca->ca_sys != (sys_config.system_type & 0xfff0)) + return 0; + } else if (ca->ca_sys != sys_config.system_type) { + return 0; + } + + iobase = (bus_addr_t)sys_config.cons_ioaddr[cf->cf_unit]; + if(iobase == 0) { + rv = 0; /* Not present */ + } + else { + iot = sys_config.cons_iot; + /* if it's in use as console, it's there. */ + if (!(iobase == comconsaddr && !comconsattached)) { + bus_space_map(iot, iobase, COM_NPORTS, 0, &ioh); + rv = comprobe1(iot, ioh); + } + else { + rv = 1; + } + } + return (rv); +} + +void +com_localbus_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct com_softc *sc = (void *)self; + int iobase, intr; + bus_space_handle_t ioh; + struct confargs *ca = aux; + + sc->sc_hwflags = 0; + sc->sc_swflags = 0; + iobase = (bus_addr_t)sys_config.cons_ioaddr[sc->sc_dev.dv_unit]; + intr = ca->ca_intr; + sc->sc_iobase = iobase; + sc->sc_frequency = sys_config.cons_baudclk; + + sc->sc_iot = sys_config.cons_iot; + + /* if it's in use as console, it's there. */ + if (!(iobase == comconsaddr && !comconsattached)) { + if (bus_space_map(sc->sc_iot, iobase, COM_NPORTS, 0, &ioh)) { + panic("unexpected bus_space_map failure"); + } + } + else { + ioh = comconsioh; + } + + sc->sc_ioh = ioh; + + com_attach_subr(sc); + + /* Enable IE pin. Some boards are not edge sensitive */ + SET(sc->sc_mcr, MCR_IENABLE); + bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_mcr, sc->sc_mcr); + + BUS_INTR_ESTABLISH(ca, NULL, intr, IST_EDGE, IPL_TTY, + comintr, (void *)sc, sc->sc_dev.dv_xname); + +} diff --git a/sys/arch/sgi/localbus/crimebus.h b/sys/arch/sgi/localbus/crimebus.h new file mode 100644 index 00000000000..ca4fabd0167 --- /dev/null +++ b/sys/arch/sgi/localbus/crimebus.h @@ -0,0 +1,77 @@ +/* $OpenBSD*/ + +/* + * Copyright (c) 2003-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. + * + */ + +#ifndef _CRIMEBUS_H_ +#define _CRIMEBUS_H_ + +#include <machine/bus.h> + +#define CRIMEBUS_BASE 0x14000000 + +#define CRIME_REVISION 0x0000 + +#define CRIME_CONTROL 0x0008 +#define CRIME_CTRL_TRITON_SYSADC 0x2000 +#define CRIME_CTRL_CRIME_SYSADC 0x1000 +#define CRIME_CTRL_HARD_RESET 0x0800 +#define CRIME_CTRL_SOFT_RESET 0x0400 +#define CRIME_CTRL_DOG_ENABLE 0x0200 +#define CRIME_CTRL_ENDIAN_BIG 0x0100 + +#define CRIME_INT_STAT 0x0010 +#define CRIME_INT_MASK 0x0018 +#define CRIME_INT_SOFT 0x0020 +#define CRIME_INT_HARD 0x0028 + +#define CRIME_KICK_DOG 0x0030 +#define CRIME_TIMER 0x0038 + +#define CRIME_CPU_ERROR_ADDR 0x0040 +#define CRIME_CPU_ERROR_STAT 0x0048 +#define CRIME_CPU_ERROR_ENAB 0x0050 + +#define CRIME_MEM_ERROR_STAT 0x0250 +#define CRIME_MEM_ERROR_ADDR 0x0258 + +extern bus_space_t crimebus_tag; + +u_int8_t crime_read_1(bus_space_tag_t, bus_space_handle_t, bus_size_t); +u_int16_t crime_read_2(bus_space_tag_t, bus_space_handle_t, bus_size_t); +u_int32_t crime_read_4(bus_space_tag_t, bus_space_handle_t, bus_size_t); +u_int64_t crime_read_8(bus_space_tag_t, bus_space_handle_t, bus_size_t); + +void crime_write_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int8_t); +void crime_write_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int16_t); +void crime_write_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t); +void crime_write_8(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int64_t); + +int crime_space_map(bus_space_tag_t, bus_addr_t, bus_size_t, int, bus_space_handle_t *); +void crime_space_unmap(bus_space_tag_t, bus_space_handle_t, bus_size_t); +int crime_space_region(bus_space_tag_t, bus_space_handle_t, bus_size_t, bus_size_t, bus_space_handle_t *); + +#endif /* _CRIMEBUS_H_ */ diff --git a/sys/arch/sgi/localbus/macebus.c b/sys/arch/sgi/localbus/macebus.c new file mode 100644 index 00000000000..e2e6897c195 --- /dev/null +++ b/sys/arch/sgi/localbus/macebus.c @@ -0,0 +1,782 @@ +/* $OpenBSD: macebus.c,v 1.1 2004/08/06 21:12:19 pefo Exp $ */ + +/* + * Copyright (c) 2000-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. + * + */ + +/* + * This is a combined macebus/crimebus driver. It handles + * configuration of all devices on the processor bus. + */ + +#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/tty.h> +#include <sys/extent.h> +#include <net/netisr.h> +#include <uvm/uvm_extern.h> + +#include <dev/pci/pcidevs.h> +#include <dev/pci/pcivar.h> + +#include <dev/ic/comvar.h> + +#include <mips64/archtype.h> + +#include <machine/autoconf.h> +#include <machine/intr.h> + +#include <sgi/localbus/macebus.h> +#include <sgi/localbus/crimebus.h> + +int macebusmatch(struct device *, void *, void *); +void macebusattach(struct device *, struct device *, void *); +int macebusprint(void *, const char *); +int macebusscan(struct device *, void *, void *); + +void *macebus_intr_establish(void *, u_long, int, int, + int (*)(void *), void *, char *); +void macebus_intr_disestablish(void *, void *); +void macebus_intr_makemasks(void); +void macebus_do_pending_int(void); +intrmask_t macebus_iointr(intrmask_t, struct trap_frame *); +intrmask_t macebus_aux(intrmask_t, struct trap_frame *); + +long mace_ext_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof (long)]; +long crime_ext_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof (long)]; + +int maceticks; /* Time tracker for special events */ + +struct cfattach macebus_ca = { + sizeof(struct device), macebusmatch, macebusattach +}; + +struct cfdriver macebus_cd = { + NULL, "macebus", DV_DULL, 1 +}; + +bus_space_t macebus_tag = { + NULL, + (bus_addr_t)MACEBUS_BASE, + NULL, + 0, + mace_read_1, mace_write_1, + mace_read_2, mace_write_2, + mace_read_4, mace_write_4, + mace_read_8, mace_write_8, + mace_space_map, mace_space_unmap, mace_space_region, +}; + +bus_space_t crimebus_tag = { + NULL, + (bus_addr_t)CRIMEBUS_BASE, + NULL, + 0, + mace_read_1, mace_write_1, + mace_read_2, mace_write_2, + mace_read_4, mace_write_4, + mace_read_8, mace_write_8, + mace_space_map, mace_space_unmap, mace_space_region, +}; + +bus_space_handle_t crime_h; +bus_space_handle_t mace_h; + + +/* + * Match bus only to targets which have this bus. + */ +int +macebusmatch(parent, match, aux) + struct device *parent; + void *match; + void *aux; +{ + if (sys_config.system_type == SGI_O2) { + return (1); + } + return(0); +} + +int +macebusprint(aux, macebus) + void *aux; + const char *macebus; +{ +/* XXXX print flags */ + return (QUIET); +} + + +int +macebusscan(struct device *parent, void *child, void *args) +{ + struct device *dev = child; + struct cfdata *cf = dev->dv_cfdata; + struct confargs lba; + struct abus lbus; + + if (cf->cf_fstate == FSTATE_STAR) { + printf("macebus '*' devs not allowed!\n"); + return 0; + } + + lba.ca_sys = cf->cf_loc[0]; + if (cf->cf_loc[1] == -1) { + lba.ca_baseaddr = 0; + } else { + lba.ca_baseaddr = cf->cf_loc[1]; + } + if (cf->cf_loc[2] == -1) { + lba.ca_intr = 0; + lba.ca_nintr = 0; + } else { + lba.ca_intr= cf->cf_loc[2]; + lba.ca_nintr = 1; + } + + lba.ca_bus = &lbus; + + /* Fill in what is needed for probing */ + lba.ca_bus->ab_type = BUS_LOCAL; + lba.ca_bus->ab_matchname = NULL; + lba.ca_name = cf->cf_driver->cd_name; + lba.ca_num = dev->dv_unit; + lba.ca_iot = &macebus_tag; + lba.ca_memt = &macebus_tag; + + return (*cf->cf_attach->ca_match)(parent, cf, &lba); +} + +void +macebusattach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + struct device *dev; + struct confargs lba; + struct abus lbus; + u_int32_t creg; + u_int64_t mask; + + /* + * Create an extent for the localbus control registers. + */ + macebus_tag.bus_extent = extent_create("mace_space", + macebus_tag.bus_base, macebus_tag.bus_base + 0x00400000, + M_DEVBUF, (caddr_t)mace_ext_storage, + sizeof(mace_ext_storage), EX_NOCOALESCE|EX_NOWAIT); + + crimebus_tag.bus_extent = extent_create("crime_space", + crimebus_tag.bus_base, crimebus_tag.bus_base + 0x00400000, + M_DEVBUF, (caddr_t)crime_ext_storage, + sizeof(crime_ext_storage), EX_NOCOALESCE|EX_NOWAIT); + + /* + * Map and set up CRIME control registers. + */ + if (bus_space_map(&crimebus_tag, 0x00000000, 0x400, 0, &crime_h)) { + printf("UH-OH! Can't map CRIME control registers!\n"); + return; + } + hwmask_addr = (void *)(PHYS_TO_KSEG1(CRIMEBUS_BASE)+CRIME_INT_MASK); + + creg = bus_space_read_8(&crimebus_tag, crime_h, CRIME_REVISION); + printf(" Crime revision %d.%d\n", (creg & 0xf0) >> 4, creg & 0xf); + + bus_space_write_8(&crimebus_tag, crime_h, CRIME_CPU_ERROR_STAT, 0); + bus_space_write_8(&crimebus_tag, crime_h, CRIME_MEM_ERROR_STAT, 0); + + mask = 0; + bus_space_write_8(&crimebus_tag, crime_h, CRIME_INT_MASK, mask); + bus_space_write_8(&crimebus_tag, crime_h, CRIME_INT_SOFT, 0); + bus_space_write_8(&crimebus_tag, crime_h, CRIME_INT_HARD, 0); + bus_space_write_8(&crimebus_tag, crime_h, CRIME_INT_STAT, 0); + + + /* + * Map and set up MACE ISA control registers. + */ + if (bus_space_map(&macebus_tag, MACE_ISA_OFFS, 0x400, 0, &mace_h)) { + printf("UH-OH! Can't map MACE ISA control registers!\n"); + return; + } + + bus_space_write_8(&macebus_tag, mace_h, MACE_ISA_INT_MASK, 0xffffffff); + bus_space_write_8(&macebus_tag, mace_h, MACE_ISA_INT_STAT, 0); + + /* + * Now attach all devices to macebus in proper order. + */ + memset(&lba, 0, sizeof(lba)); + memset(&lbus, 0, sizeof(lbus)); + lba.ca_bus = &lbus; + lba.ca_bus->ab_type = BUS_LOCAL; + lba.ca_bus->ab_matchname = NULL; + lba.ca_iot = &macebus_tag; + lba.ca_memt = &macebus_tag; + + /* + * On O2 systems all interrupts are handled by the + * macebus interrupt handler. Register all except clock. + */ + switch(sys_config.system_type) { + + case SGI_O2: + set_intr(INTPRI_MACEIO, CR_INT_0, macebus_iointr); + lba.ca_bus->ab_intr_establish = macebus_intr_establish; + lba.ca_bus->ab_intr_disestablish = macebus_intr_disestablish; + register_pending_int_handler(macebus_do_pending_int); + break; + + default: + panic("macebusscan: unknown macebus type!"); + } + + /* DEBUG: Set up a handler called when clock interrupts go off. */ + set_intr(INTPRI_MACEAUX, CR_INT_5, macebus_aux); + + + while ((dev = config_search(macebusscan, self, aux)) != NULL) { + struct cfdata *cf; + + cf = dev->dv_cfdata; + lba.ca_sys = cf->cf_loc[0]; + if (cf->cf_loc[1] == -1) { + lba.ca_baseaddr = 0; + } else { + lba.ca_baseaddr = cf->cf_loc[1]; + } + if (cf->cf_loc[2] == -1) { + lba.ca_intr = 0; + lba.ca_nintr = 0; + } else { + lba.ca_intr= cf->cf_loc[2]; + lba.ca_nintr = 1; + } + lba.ca_name = cf->cf_driver->cd_name; + lba.ca_num = dev->dv_unit; + + config_attach(self, dev, &lba, macebusprint); + } +} + + +/* + * Bus access primitives. These are really ugly... + */ + +u_int8_t +mace_read_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) +{ + return *(volatile u_int8_t *)(h + (o << 8) + 7); +} + +u_int16_t +mace_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) +{ + panic("mace_read_2"); +} + +u_int32_t +mace_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) +{ + return *(volatile u_int32_t *)(h + o); +} + +u_int64_t +mace_read_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) +{ + return lp32_read8((u_int64_t *)(h + o)); +} + +void +mace_write_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, u_int8_t v) +{ + *(volatile u_int8_t *)(h + (o << 8) + 7) = v; +} + +void +mace_write_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, u_int16_t v) +{ + panic("mace_write_2"); +} + +void +mace_write_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, u_int32_t v) +{ + *(volatile u_int32_t *)(h + o) = v; +} + +void +mace_write_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, u_int64_t v) +{ + lp32_write8((u_int64_t *)(h + o), v); +} + +int +mace_space_map(bus_space_tag_t t, bus_addr_t offs, bus_size_t size, + int cacheable, bus_space_handle_t *bshp) +{ + bus_addr_t bpa; + int error; + + bpa = t->bus_base + offs; + + /* Handle special mapping separately */ + if ((bpa >= 0x1f380000 && (bpa+size) <= 0x1f3a0000) ) { + *bshp = PHYS_TO_KSEG1(bpa); + return 0; + } + + if ((error = extent_alloc_region(t->bus_extent, bpa, size, + EX_NOWAIT | EX_MALLOCOK))) { + return error; + } + + if ((error = bus_mem_add_mapping(bpa, size, cacheable, bshp))) { + if (extent_free(t->bus_extent, bpa, size, EX_NOWAIT | + ((phys_map != NULL) ? EX_MALLOCOK : 0))) { + printf("bus_space_map: pa %p, size %p\n", bpa, size); + printf("bus_space_map: can't free region\n"); + } + } + return 0; +} + +void +mace_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size) +{ + bus_addr_t sva; + bus_size_t off, len; + bus_addr_t paddr; + + /* should this verify that the proper size is freed? */ + sva = trunc_page(bsh); + off = bsh - sva; + len = size+off; + + paddr = KSEG1_TO_PHYS(bsh); + if (paddr >= 0x1f380000 && (paddr+size) <= 0x1f3a0000) + return; + + if (pmap_extract(pmap_kernel(), bsh, (void *)&paddr) == 0) { + printf("bus_space_unmap: no pa for va %p\n", bsh); + return; + } + + if (phys_map != NULL && + ((sva >= VM_MIN_KERNEL_ADDRESS) && (sva < VM_MAX_KERNEL_ADDRESS))) { + /* do not free memory which was stolen from the vm system */ + uvm_km_free(kernel_map, sva, len); + } + + if (extent_free(t->bus_extent, paddr, size, EX_NOWAIT | + ((phys_map != NULL) ? EX_MALLOCOK : 0))) { + printf("bus_space_map: pa %p, size %p\n", paddr, size); + printf("bus_space_map: can't free region\n"); + } +} + +int +mace_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) +{ + *nbshp = bsh + offset; + return (0); +} + +/* + * Macebus interrupt handler driver. + */ + + +intrmask_t mace_intem = 0x0; +static intrmask_t intrtype[INTMASKSIZE]; +static intrmask_t intrmask[INTMASKSIZE]; +static intrmask_t intrlevel[INTMASKSIZE]; +struct intrhand *intrhand[INTMASKSIZE]; + +static int fakeintr __P((void *)); +static int fakeintr(void *a) {return 0;} + +/* + * Establish an interrupt handler called from the dispatcher. + * The interrupt function established should return zero if + * there was nothing to serve (no int) and non zero when an + * interrupt was serviced. + * Interrupts are numbered from 1 and up where 1 maps to HW int 0. + */ +void * +macebus_intr_establish(icp, irq, type, level, ih_fun, ih_arg, ih_what) + void *icp; + u_long irq; /* XXX pci_intr_handle_t compatible XXX */ + int type; + int level; + int (*ih_fun) __P((void *)); + void *ih_arg; + char *ih_what; +{ + struct intrhand **p, *q, *ih; + static struct intrhand fakehand = {NULL, fakeintr}; + int edge; +extern int cold; + +static int initialized = 0; + + if(!initialized) { +/*INIT CODE HERE*/ + initialized = 1; + } + + if(irq > 62 || irq < 1) { + panic("intr_establish: illegal irq %d\n", irq); + } + irq -= 1; /* Adjust for 1 being first (0 is no int) */ + + /* no point in sleeping unless someone can free memory. */ + ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK); + if (ih == NULL) + panic("intr_establish: can't malloc handler info"); + + if(type == IST_NONE || type == IST_PULSE) + panic("intr_establish: bogus type"); + + switch (intrtype[irq]) { + case IST_EDGE: + case IST_LEVEL: + if (type == intrtype[irq]) + break; + } + + switch (type) { + case IST_EDGE: + edge |= 1 << irq; + break; + case IST_LEVEL: + edge &= ~(1 << irq); + break; + } + + /* + * Figure out where to put the handler. + * This is O(N^2), but we want to preserve the order, and N is + * generally small. + */ + for (p = &intrhand[irq]; (q = *p) != NULL; p = &q->ih_next) + ; + + /* + * Actually install a fake handler momentarily, since we might be doing + * this with interrupts enabled and don't want the real routine called + * until masking is set up. + */ + fakehand.ih_level = level; + *p = &fakehand; + + macebus_intr_makemasks(); + + /* + * Poke the real handler in now. + */ + ih->ih_fun = ih_fun; + ih->ih_arg = ih_arg; + ih->ih_count = 0; + ih->ih_next = NULL; + ih->ih_level = level; + ih->ih_irq = irq; + ih->ih_what = ih_what; + *p = ih; + + return (ih); +} + +void +macebus_intr_disestablish(void *p1, void *p2) +{ +} + +/* + * Regenerate interrupt masks to reflect reality. + */ +void +macebus_intr_makemasks() +{ + int irq, level; + struct intrhand *q; + + /* First, figure out which levels each IRQ uses. */ + for (irq = 0; irq < INTMASKSIZE; irq++) { + int levels = 0; + for (q = intrhand[irq]; q; q = q->ih_next) + levels |= 1 << q->ih_level; + intrlevel[irq] = levels; + } + + /* Then figure out which IRQs use each level. */ + for (level = 0; level < 5; level++) { + int irqs = 0; + for (irq = 0; irq < INTMASKSIZE; irq++) + if (intrlevel[irq] & (1 << level)) + irqs |= 1 << irq; + imask[level] = irqs | SINT_ALLMASK; + } + + /* + * There are tty, network and disk drivers that use free() at interrupt + * time, so imp > (tty | net | bio). + */ + imask[IPL_VM] |= imask[IPL_TTY] | imask[IPL_NET] | imask[IPL_BIO]; + + /* + * Enforce a hierarchy that gives slow devices a better chance at not + * dropping data. + */ + imask[IPL_TTY] |= imask[IPL_NET] | imask[IPL_BIO]; + imask[IPL_NET] |= imask[IPL_BIO]; + + /* + * These are pseudo-levels. + */ + imask[IPL_NONE] = 0; + imask[IPL_HIGH] = -1; + + /* And eventually calculate the complete masks. */ + for (irq = 0; irq < INTMASKSIZE; irq++) { + int irqs = 1 << irq; + for (q = intrhand[irq]; q; q = q->ih_next) + irqs |= imask[q->ih_level]; + intrmask[irq] = irqs | SINT_ALLMASK; + } + + /* Lastly, determine which IRQs are actually in use. */ + irq = 0; + for (level = 0; level < INTMASKSIZE; level++) { + if (intrhand[level]) { + irq |= 1 << level; + } + } + mace_intem = irq & 0x0000ffff; + hw_setintrmask(0); +} + +void +macebus_do_pending_int() +{ + struct intrhand *ih; + int vector; + intrmask_t pcpl; + intrmask_t hwpend; + struct trap_frame cf; +static volatile int processing; + + /* Don't recurse... */ + if (processing) + return; + processing = 1; + +/* XXX interrupt vulnerable when changing ipending */ + pcpl = splhigh(); /* Turn off all */ + + /* XXX Fake a trapframe for clock pendings... */ + cf.pc = (int)&macebus_do_pending_int; + cf.sr = 0; + cf.cpl = pcpl; + + hwpend = ipending & ~pcpl; /* Do now unmasked pendings */ + hwpend &= ~(SINT_ALLMASK); + ipending &= ~hwpend; + while (hwpend) { + vector = ffs(hwpend) - 1; + hwpend &= ~(1L << vector); + ih = intrhand[vector]; + while (ih) { + ih->frame = &cf; + if((*ih->ih_fun)(ih->ih_arg)) { + ih->ih_count++; + } + ih = ih->ih_next; + } + } + if ((ipending & SINT_CLOCKMASK) & ~pcpl) { + ipending &= ~SINT_CLOCKMASK; + softclock(); + } + if ((ipending & SINT_NETMASK) & ~pcpl) { + extern int netisr; + int isr = netisr; + netisr = 0; + ipending &= ~SINT_NETMASK; +#ifdef INET +#include "ether.h" + if (NETHER > 0 && isr & (1 << NETISR_ARP)) { + arpintr(); + } + + if (isr & (1 << NETISR_IP)) { + ipintr(); + } +#endif +#ifdef INET6 + if(isr & (1 << NETISR_IPV6)) { + ip6intr(); + } +#endif +#ifdef NETATALK + if (isr & (1 << NETISR_ATALK)) { + atintr(); + } +#endif +#ifdef IMP + if (isr & (1 << NETISR_IMP)) { + impintr(); + } +#endif +#ifdef NS + if (isr & (1 << NETISR_NS)) { + nsintr(); + } +#endif +#ifdef ISO + if (isr & (1 << NETISR_ISO)) { + clnlintr(); + } +#endif +#ifdef CCITT + if (isr & (1 << NETISR_CCITT)) { + ccittintr(); + } +#endif +#include "ppp.h" + if (NPPP > 0 && isr & (1 << NETISR_PPP)) { + pppintr(); + } + +#include "bridge.h" + if (NBRIDGE > 0 && isr & (1 << NETISR_BRIDGE)) { + bridgeintr(); + } + } + +#ifdef NOTYET + if ((ipending & SINT_TTYMASK) & ~pcpl) { + ipending &= ~SINT_TTYMASK; + compoll(NULL); + } +#endif + + cpl = pcpl; /* Don't use splx... we are here already! */ + hw_setintrmask(pcpl); + + processing = 0; +} + +/* + * Process interrupts. The parameter pending has non-masked interrupts. + */ +intrmask_t +macebus_iointr(intrmask_t hwpend, struct trap_frame *cf) +{ + struct intrhand *ih; + intrmask_t catched, vm; + int v; + intrmask_t pending; + u_int64_t intstat, isastat, mask; + + intstat = bus_space_read_8(&crimebus_tag, crime_h, CRIME_INT_STAT); + intstat &= 0x0000ffff; + isastat = bus_space_read_8(&macebus_tag, mace_h, MACE_ISA_INT_STAT); + catched = 0; + + /* Mask off masked interrupts and save them as pending */ + if (intstat & cf->cpl) { + ipending |= intstat & cf->cpl; + mask = bus_space_read_8(&crimebus_tag, crime_h, CRIME_INT_MASK); + mask &= ~ipending; + bus_space_write_8(&crimebus_tag, crime_h, CRIME_INT_MASK, mask); + catched++; + } + + /* Scan the first 16 for now */ + pending = intstat & ~cf->cpl; + + for (v = 0, vm = 1; pending != 0 && v < 16 ; v++, vm <<= 1) { + if (pending & vm) { + ih = intrhand[v]; + + while (ih) { + ih->frame = cf; + if ((*ih->ih_fun)(ih->ih_arg)) { + catched |= vm; + ih->ih_count++; + } + ih = ih->ih_next; + } + } + } + if (catched) { + return CR_INT_0; + } + + return 0; /* Non found here */ +} + + +/* + * Macebus auxilary functions run each clock interrupt. + */ +intrmask_t +macebus_aux(intrmask_t hwpend, struct trap_frame *cf) +{ + u_int64_t mask; +extern char idle[]; +extern char e_idle[]; + + mask = bus_space_read_8(&macebus_tag, mace_h, MACE_ISA_MISC_REG); + mask |= MACE_ISA_MISC_RLED_OFF | MACE_ISA_MISC_GLED_OFF; + + /* GREEN - User mode */ + /* AMBER - System mode */ + /* RED - IDLE */ + if (cf->sr & SR_KSU_USER) { + mask &= ~MACE_ISA_MISC_GLED_OFF; + } else if (cf->pc >= (long)idle && cf->pc < (long)e_idle) { + mask &= ~MACE_ISA_MISC_RLED_OFF; + } else { + mask &= ~(MACE_ISA_MISC_RLED_OFF | MACE_ISA_MISC_GLED_OFF); + } + bus_space_write_8(&macebus_tag, mace_h, MACE_ISA_MISC_REG, mask); + + if (maceticks++ > 100*15) { + maceticks = 0; + } + + return 0; /* Real clock int handler registers */ +} diff --git a/sys/arch/sgi/localbus/macebus.h b/sys/arch/sgi/localbus/macebus.h new file mode 100644 index 00000000000..d5a3438ebc3 --- /dev/null +++ b/sys/arch/sgi/localbus/macebus.h @@ -0,0 +1,120 @@ +/* $OpenBSD*/ + +/* + * Copyright (c) 2003-2004 Opsycon AB (www.opsycon.com). + * + * 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. + * + */ + +#ifndef _MACEBUS_H_ +#define _MACEBUS_H_ 1 + +#include <machine/bus.h> + +/* + * Physical address of MACEBUS. + */ +#define MACEBUS_BASE 0x1f000000 + +/* + * Offsets for various I/O sections on MACEBUS + */ +#define MACE_PCI_OFFS 0x00080000 +#define MACE_VIN1_OFFS 0x00100000 +#define MACE_VIN2_OFFS 0x00180000 +#define MACE_VOUT_OFFS 0x00200000 +#define MACE_IO_OFFS 0x00300000 +#define MACE_ISAX_OFFS 0x00380000 + +/* + * PCI control registers (relative MACE_PCI_OFFS) + */ +#define MACE_PCI_ERROR_ADDRESS 0x0000 +#define MACE_PCI_ERROR_FLAGS 0x0004 +#define MACE_PCI_CONTROL 0x0008 +#define MACE_PCI_REVISION 0x000c +#define MACE_PCI_FLUSH 0x000c +#define MACE_PCI_CFGADDR 0x0cf8 +#define MACE_PCI_CFGDATA 0x0cfc + +#define MACE_PCI_INTCTRL 0x000000ff /* Interrupt control mask */ + +/* PCI_ERROR_FLAGS Bits */ +#define PERR_MASTER_ABORT 0x80000000 +#define PERR_TARGET_ABORT 0x40000000 +#define PERR_DATA_PARITY_ERR 0x20000000 +#define PERR_RETRY_ERR 0x10000000 +#define PERR_ILLEGAL_CMD 0x08000000 +#define PERR_SYSTEM_ERR 0x04000000 +#define PERR_INTERRUPT_TEST 0x02000000 +#define PERR_PARITY_ERR 0x01000000 +#define PERR_OVERRUN 0x00800000 +#define PERR_RSVD 0x00400000 +#define PERR_MEMORY_ADDR 0x00200000 +#define PERR_CONFIG_ADDR 0x00100000 +#define PERR_MASTER_ABORT_ADDR_VALID 0x00080000 +#define PERR_TARGET_ABORT_ADDR_VALID 0x00040000 +#define PERR_DATA_PARITY_ADDR_VALID 0x00020000 +#define PERR_RETRY_ADDR_VALID 0x00010000 + + +/* + * MACE ISA definitions. + */ +#define MACE_ISA_OFFS (MACE_IO_OFFS+0x00010000) + +#define MACE_ISA_MISC_REG 0x0008 /* Various status and controls */ +#define MACE_ISA_INT_STAT 0x0010 +#define MACE_ISA_INT_MASK 0x0018 + +/* MACE_ISA_MISC_REG definitions */ +#define MACE_ISA_MISC_RLED_OFF 0x0010 /* Turns off RED LED */ +#define MACE_ISA_MISC_GLED_OFF 0x0020 /* Turns off GREEN LED */ + + +/* ISA Periferials */ +#define MACE_ISA_EPP_OFFS (MACE_ISAX_OFFS+0x00000000) +#define MACE_ISA_ECP_OFFS (MACE_ISAX_OFFS+0x00008000) +#define MACE_ISA_SER1_OFFS (MACE_ISAX_OFFS+0x00010000) +#define MACE_ISA_SER2_OFFS (MACE_ISAX_OFFS+0x00018000) +#define MACE_ISA_RTC_OFFS (MACE_ISAX_OFFS+0x00020000) +#define MACE_ISA_GAME_OFFS (MACE_ISAX_OFFS+0x00030000) + + +extern bus_space_t macebus_tag; + +u_int8_t mace_read_1(bus_space_tag_t, bus_space_handle_t, bus_size_t); +u_int16_t mace_read_2(bus_space_tag_t, bus_space_handle_t, bus_size_t); +u_int32_t mace_read_4(bus_space_tag_t, bus_space_handle_t, bus_size_t); +u_int64_t mace_read_8(bus_space_tag_t, bus_space_handle_t, bus_size_t); + +void mace_write_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int8_t); +void mace_write_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int16_t); +void mace_write_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t); +void mace_write_8(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int64_t); + +int mace_space_map(bus_space_tag_t, bus_addr_t, bus_size_t, int, bus_space_handle_t *); +void mace_space_unmap(bus_space_tag_t, bus_space_handle_t, bus_size_t); +int mace_space_region(bus_space_tag_t, bus_space_handle_t, bus_size_t, bus_size_t, bus_space_handle_t *); + +#endif /* _MACEBUS_H_ */ diff --git a/sys/arch/sgi/localbus/macectrl.S b/sys/arch/sgi/localbus/macectrl.S new file mode 100644 index 00000000000..879032928aa --- /dev/null +++ b/sys/arch/sgi/localbus/macectrl.S @@ -0,0 +1,55 @@ +/* $OpenBSD: macectrl.S,v 1.1 2004/08/06 21:12:19 pefo Exp $ */ + +/* + * Copyright (c) 2004 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * 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. + * + */ +#include <machine/param.h> +#include <machine/psl.h> +#include <machine/asm.h> +#include <machine/cpu.h> +#include <machine/regnum.h> + +#include "assym.h" + + .set mips3 + .set noreorder # Noreorder is default style! + + .globl hw_setintrmask +LEAF(hw_setintrmask) + lw v0, mace_intem + PTR_L v1, hwmask_addr + nor a0, zero, a0 + beqz v1, 1f # addr not set, skip. + and v0, a0 + jr ra + sd v0, 0(v1) +1: + jr ra + nop +END(hw_setintrmask) + + .data + .globl hwmask_addr +hwmask_addr: .long 0 |