diff --git a/sys/arch/sgimips/dev/crime.c b/sys/arch/sgimips/dev/crime.c index 121a96930517..dad617b39b93 100644 --- a/sys/arch/sgimips/dev/crime.c +++ b/sys/arch/sgimips/dev/crime.c @@ -1,6 +1,7 @@ -/* $NetBSD: crime.c,v 1.16 2004/01/13 14:31:37 sekiya Exp $ */ +/* $NetBSD: crime.c,v 1.17 2004/01/18 00:54:55 sekiya Exp $ */ /* + * Copyright (c) 2004 Christopher SEKIYA * Copyright (c) 2000 Soren S. Jorvang * All rights reserved. * @@ -37,11 +38,12 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: crime.c,v 1.16 2004/01/13 14:31:37 sekiya Exp $"); +__KERNEL_RCSID(0, "$NetBSD: crime.c,v 1.17 2004/01/18 00:54:55 sekiya Exp $"); #include #include #include +#include #include #include @@ -58,9 +60,15 @@ __KERNEL_RCSID(0, "$NetBSD: crime.c,v 1.16 2004/01/13 14:31:37 sekiya Exp $"); static int crime_match(struct device *, struct cfdata *, void *); static void crime_attach(struct device *, struct device *, void *); -void crime_watchdog_tickle(void); +void crime_bus_reset(void); +void crime_watchdog_reset(void); +void crime_watchdog_disable(void); +void crime_intr(u_int32_t, u_int32_t, u_int32_t, u_int32_t); +void *crime_intr_establish(int, int, int (*)(void *), void *); +extern void mace_intr(int); /* XXX */ -struct crime_softc *crime_sc; /* only one per machine, okay to be global */ +static bus_space_tag_t crm_iot; +static bus_space_handle_t crm_ioh; CFATTACH_DECL(crime, sizeof(struct crime_softc), crime_match, crime_attach, NULL, NULL); @@ -73,10 +81,7 @@ struct { } crime[CRIME_NINTR]; static int -crime_match(parent, match, aux) - struct device *parent; - struct cfdata *match; - void *aux; +crime_match(struct device *parent, struct cfdata *match, void *aux) { /* @@ -89,24 +94,20 @@ crime_match(parent, match, aux) } static void -crime_attach(parent, self, aux) - struct device *parent; - struct device *self; - void *aux; +crime_attach(struct device *parent, struct device *self, void *aux) { - struct crime_softc *sc = (struct crime_softc *)self; struct mainbus_attach_args *ma = aux; u_int64_t crm_id; + u_int64_t baseline; + u_int32_t cps; - crime_sc = sc; + crm_iot = SGIMIPS_BUS_SPACE_CRIME; - sc->iot = SGIMIPS_BUS_SPACE_CRIME; - - if (bus_space_map(sc->iot, ma->ma_addr, 0 /* XXX */, - BUS_SPACE_MAP_LINEAR, &sc->ioh)) + if (bus_space_map(crm_iot, ma->ma_addr, 0 /* XXX */, + BUS_SPACE_MAP_LINEAR, &crm_ioh)) panic("crime_attach: can't map I/O space"); - crm_id = bus_space_read_8(sc->iot, sc->ioh, CRIME_REV); + crm_id = bus_space_read_8(crm_iot, crm_ioh, CRIME_REV); aprint_naive(": system ASIC"); @@ -135,20 +136,43 @@ crime_attach(parent, self, aux) aprint_normal(" (CRIME_ID: %llx)\n", crm_id); + /* reset CRIME CPU & memory error registers */ + crime_bus_reset(); + + baseline = bus_space_read_8(crm_iot, crm_ioh, CRIME_TIME) & CRIME_TIME_MASK; + cps = mips3_cp0_count_read(); + + while (((bus_space_read_8(crm_iot, crm_ioh, CRIME_TIME) & CRIME_TIME_MASK) + - baseline) < 50 * 1000000 / 15) + continue; + cps = mips3_cp0_count_read() - cps; + cps = cps / 5; + + /* Counter on R4k/R4400/R4600/R5k counts at half the CPU frequency */ + curcpu()->ci_cpu_freq = cps * 2 * hz; + curcpu()->ci_cycles_per_hz = curcpu()->ci_cpu_freq / (2 * hz); + curcpu()->ci_divisor_delay = curcpu()->ci_cpu_freq / (2 * 1000000); + MIPS_SET_CI_RECIPRICAL(curcpu()); + /* Turn on memory error and crime error interrupts. All others turned on as devices are registered. */ - bus_space_write_8(sc->iot, sc->ioh, CRIME_INTMASK, + bus_space_write_8(crm_iot, crm_ioh, CRIME_INTMASK, CRIME_INT_MEMERR | CRIME_INT_CRMERR | CRIME_INT_VICE | CRIME_INT_VID_OUT | CRIME_INT_VID_IN2 | CRIME_INT_VID_IN1); - bus_space_write_8(sc->iot, sc->ioh, CRIME_INTSTAT, 0); - bus_space_write_8(sc->iot, sc->ioh, CRIME_SOFTINT, 0); - bus_space_write_8(sc->iot, sc->ioh, CRIME_HARDINT, 0); + bus_space_write_8(crm_iot, crm_ioh, CRIME_INTSTAT, 0); + bus_space_write_8(crm_iot, crm_ioh, CRIME_SOFTINT, 0); + bus_space_write_8(crm_iot, crm_ioh, CRIME_HARDINT, 0); - platform.watchdog_reset = crime_watchdog_tickle; + platform.bus_reset = crime_bus_reset; + platform.watchdog_reset = crime_watchdog_reset; + platform.watchdog_disable = crime_watchdog_disable; + platform.watchdog_enable = crime_watchdog_reset; + platform.intr_establish = crime_intr_establish; + platform.intr0 = crime_intr; } /* @@ -156,12 +180,7 @@ crime_attach(parent, self, aux) */ void * -crime_intr_establish(irq, type, level, func, arg) - int irq; - int type; - int level; - int (*func)(void *); - void *arg; +crime_intr_establish(int irq, int level, int (*func)(void *), void *arg) { if (crime[irq].func != NULL) return NULL; /* panic("Cannot share CRIME interrupts!"); */ @@ -175,15 +194,51 @@ crime_intr_establish(irq, type, level, func, arg) } void -crime_intr(pendmask) - u_int pendmask; +crime_intr(u_int32_t status, u_int32_t cause, u_int32_t pc, u_int32_t ipending) { + u_int64_t crime_intmask; + u_int64_t crime_intstat; + u_int64_t crime_ipending; int i; - for (i = 0; i < CRIME_NINTR; i++) { - if ((pendmask & (1 << i)) && crime[i].func != NULL) - (*crime[i].func)(crime[i].arg); + crime_intmask = bus_space_read_8(crm_iot, crm_ioh, CRIME_INTMASK); + crime_intstat = bus_space_read_8(crm_iot, crm_ioh, CRIME_INTSTAT); + crime_ipending = (crime_intstat & crime_intmask); + + if (crime_ipending & 0xff) + mace_intr(crime_ipending & 0xff); + + if (crime_ipending & 0xffff0000) { + /* + * CRIME interrupts for CPU and memory errors + */ + if (crime_ipending & CRIME_INT_MEMERR) { + u_int64_t address = + bus_space_read_8(crm_iot, crm_ioh, CRIME_MEM_ERROR_ADDR); + u_int64_t status = + bus_space_read_8(crm_iot, crm_ioh, CRIME_MEM_ERROR_STAT); + printf("crime: memory error address %llx" + " status %llx\n", address << 2, status); + crime_bus_reset(); + } + + if (crime_ipending & CRIME_INT_CRMERR) { + u_int64_t stat = + bus_space_read_8(crm_iot, crm_ioh, CRIME_CPU_ERROR_STAT); + printf("crime: cpu error %llx at" + " address %llx\n", stat, + bus_space_read_8(crm_iot, crm_ioh, CRIME_CPU_ERROR_ADDR)); + crime_bus_reset(); + } } + + crime_ipending &= 0xff00; + + if (crime_ipending) + for (i = 0; i < CRIME_NINTR; i++) { + if ((crime_ipending & (1 << i)) && crime[i].func != NULL) + (*crime[i].func)(crime[i].arg); + } } void @@ -191,17 +246,34 @@ crime_intr_mask(unsigned int intr) { u_int64_t mask; - mask = bus_space_read_8(crime_sc->iot, crime_sc->ioh, CRIME_INTMASK); + mask = bus_space_read_8(crm_iot, crm_ioh, CRIME_INTMASK); mask |= (1 << intr); - bus_space_write_8(crime_sc->iot, crime_sc->ioh, CRIME_INTMASK, mask); + bus_space_write_8(crm_iot, crm_ioh, CRIME_INTMASK, mask); } void -crime_watchdog_tickle(void) +crime_bus_reset(void) { - /* enable watchdog timer, clear it */ - bus_space_write_8(crime_sc->iot, crime_sc->ioh, - CRIME_CONTROL, CRIME_CONTROL_DOG_ENABLE); - bus_space_write_8(crime_sc->iot, crime_sc->ioh, CRIME_WATCHDOG, 0); + bus_space_write_8(crm_iot, crm_ioh, CRIME_CPU_ERROR_STAT, 0); + bus_space_write_8(crm_iot, crm_ioh, CRIME_MEM_ERROR_STAT, 0); } +void +crime_watchdog_reset(void) +{ + /* enable watchdog timer, clear it */ + bus_space_write_8(crm_iot, crm_ioh, + CRIME_CONTROL, CRIME_CONTROL_DOG_ENABLE); + bus_space_write_8(crm_iot, crm_ioh, CRIME_WATCHDOG, 0); +} + +void +crime_watchdog_disable(void) +{ + u_int64_t reg; + + bus_space_write_8(crm_iot, crm_ioh, CRIME_WATCHDOG, 0); + reg = bus_space_read_8(crm_iot, crm_ioh, CRIME_CONTROL) + & ~CRIME_CONTROL_DOG_ENABLE; + bus_space_write_8(crm_iot, crm_ioh, CRIME_CONTROL, reg); +} diff --git a/sys/arch/sgimips/dev/crimevar.h b/sys/arch/sgimips/dev/crimevar.h index 2661ca55e353..a85bc1f73966 100644 --- a/sys/arch/sgimips/dev/crimevar.h +++ b/sys/arch/sgimips/dev/crimevar.h @@ -1,4 +1,4 @@ -/* $NetBSD: crimevar.h,v 1.2 2003/11/17 10:07:58 keihan Exp $ */ +/* $NetBSD: crimevar.h,v 1.3 2004/01/18 00:54:55 sekiya Exp $ */ /* * Copyright (c) 2003 Christopher SEKIYA @@ -36,13 +36,6 @@ struct crime_softc { struct device sc_dev; - - bus_space_tag_t iot; - bus_space_handle_t ioh; }; -extern struct crime_softc *crime_sc; - -void *crime_intr_establish(int, int, int, int (*)(void *), void *); -void crime_intr(u_int); void crime_intr_mask(unsigned int); diff --git a/sys/arch/sgimips/dev/imc.c b/sys/arch/sgimips/dev/imc.c index d46909c93fbd..31a8573fe0d6 100644 --- a/sys/arch/sgimips/dev/imc.c +++ b/sys/arch/sgimips/dev/imc.c @@ -1,4 +1,4 @@ -/* $NetBSD: imc.c,v 1.13 2004/01/13 14:31:37 sekiya Exp $ */ +/* $NetBSD: imc.c,v 1.14 2004/01/18 00:54:55 sekiya Exp $ */ /* * Copyright (c) 2001 Rafal K. Boni @@ -28,7 +28,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: imc.c,v 1.13 2004/01/13 14:31:37 sekiya Exp $"); +__KERNEL_RCSID(0, "$NetBSD: imc.c,v 1.14 2004/01/18 00:54:55 sekiya Exp $"); #include #include @@ -59,7 +59,9 @@ static void imc_attach(struct device *, struct device *, void *); static int imc_print(void *, const char *); void imc_bus_reset(void); void imc_bus_error(void); -void imc_watchdog_tickle(void); +void imc_watchdog_reset(void); +void imc_watchdog_disable(void); +void imc_watchdog_enable(void); CFATTACH_DECL(imc, sizeof(struct imc_softc), imc_match, imc_attach, NULL, NULL); @@ -110,7 +112,9 @@ imc_attach(parent, self, aux) panic("imc_attach: could not allocate memory\n"); platform.bus_reset = imc_bus_reset; - platform.watchdog_reset = imc_watchdog_tickle; + platform.watchdog_reset = imc_watchdog_reset; + platform.watchdog_disable = imc_watchdog_disable; + platform.watchdog_enable = imc_watchdog_enable; sysid = bus_space_read_4(isc.iot, isc.ioh, IMC_SYSID); @@ -220,11 +224,7 @@ imc_attach(parent, self, aux) iaa.iaa_name = "gio"; (void)config_found(self, (void*)&iaa, imc_print); - /* enable watchdog and clear it */ - reg = bus_space_read_4(isc.iot, isc.ioh, IMC_CPUCTRL0); - reg |= IMC_CPUCTRL0_WDOG; - bus_space_write_4(isc.iot, isc.ioh, IMC_CPUCTRL0, reg); - imc_watchdog_tickle(); + imc_watchdog_enable(); } @@ -260,7 +260,29 @@ imc_bus_error(void) } void -imc_watchdog_tickle(void) +imc_watchdog_reset(void) { bus_space_write_4(isc.iot, isc.ioh, IMC_WDOG, 0); } +void +imc_watchdog_disable(void) +{ + u_int32_t reg; + + bus_space_write_4(isc.iot, isc.ioh, IMC_WDOG, 0); + reg = bus_space_read_4(isc.iot, isc.ioh, IMC_CPUCTRL0); + reg &= IMC_CPUCTRL0_WDOG; + bus_space_write_4(isc.iot, isc.ioh, IMC_CPUCTRL0, reg); +} + +void +imc_watchdog_enable(void) +{ + u_int32_t reg; + + /* enable watchdog and clear it */ + reg = bus_space_read_4(isc.iot, isc.ioh, IMC_CPUCTRL0); + reg |= IMC_CPUCTRL0_WDOG; + bus_space_write_4(isc.iot, isc.ioh, IMC_CPUCTRL0, reg); + imc_watchdog_reset(); +} diff --git a/sys/arch/sgimips/dev/int2reg.h b/sys/arch/sgimips/dev/int2reg.h index df7df402b34e..25d10391db28 100644 --- a/sys/arch/sgimips/dev/int2reg.h +++ b/sys/arch/sgimips/dev/int2reg.h @@ -1,4 +1,4 @@ -/* $NetBSD: int2reg.h,v 1.1 2004/01/10 05:16:57 sekiya Exp $ */ +/* $NetBSD: int2reg.h,v 1.2 2004/01/18 00:54:55 sekiya Exp $ */ /* * Copyright (c) 2004 Christopher SEKIYA @@ -30,6 +30,12 @@ #if !defined(_ARCH_SGIMIPS_DEV_INT2_H_) #define _ARCH_SGIMIPS_DEV_INT2_H_ +/* The INT has known locations on all SGI machines */ +#define INT_IP12 0x1fb801c0 +#define INT_IP20 0x1fb801c0 +#define INT_IP22 0x1fbd9000 +#define INT_IP24 0x1fbd9880 + #define INT2_LOCAL0_STATUS 0x00 #define INT2_LOCAL0_MASK 0x04 #define INT2_LOCAL1_STATUS 0x08