From owner-p4-projects@FreeBSD.ORG Mon Jun 14 02:34:07 2004 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id AD2A016A4D1; Mon, 14 Jun 2004 02:34:06 +0000 (GMT) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 8379916A4CE for ; Mon, 14 Jun 2004 02:34:06 +0000 (GMT) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 7C68B43D5A for ; Mon, 14 Jun 2004 02:34:06 +0000 (GMT) (envelope-from jmallett@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.12.11/8.12.11) with ESMTP id i5E2Y4EU039700 for ; Mon, 14 Jun 2004 02:34:04 GMT (envelope-from jmallett@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.12.11/8.12.11/Submit) id i5E2Y3b5039697 for perforce@freebsd.org; Mon, 14 Jun 2004 02:34:03 GMT (envelope-from jmallett@freebsd.org) Date: Mon, 14 Jun 2004 02:34:03 GMT Message-Id: <200406140234.i5E2Y3b5039697@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to jmallett@freebsd.org using -f From: Juli Mallett To: Perforce Change Reviews Subject: PERFORCE change 54886 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 14 Jun 2004 02:34:07 -0000 http://perforce.freebsd.org/chv.cgi?CH=54886 Change 54886 by jmallett@jmallett_oingo on 2004/06/14 02:33:06 Synch ip22 int code from NetBSD, including timecounter code, which is all I want in a NetBSD-derived ip22.c for now. Lose the cache stuff, I'm avoiding the hell out of caches right now anyway. This also means we have actual interrupt code here! Now to go make some busses consume it. Affected files ... .. //depot/projects/mips/sys/mips/sgimips/int2reg.h#1 add .. //depot/projects/mips/sys/mips/sgimips/int2var.h#1 add .. //depot/projects/mips/sys/mips/sgimips/intr.h#6 edit .. //depot/projects/mips/sys/mips/sgimips/ip22.c#8 edit .. //depot/projects/mips/sys/mips/sgimips/models.h#2 edit .. //depot/projects/mips/sys/mips/sgimips/timerreg.h#1 add Differences ... ==== //depot/projects/mips/sys/mips/sgimips/intr.h#6 (text+ko) ==== @@ -23,12 +23,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $P4: //depot/projects/mips/sys/mips/sgimips/intr.h#5 $ + * $P4: //depot/projects/mips/sys/mips/sgimips/intr.h#6 $ */ #ifndef _SGIMIPS_INTR_H_ #define _SGIMIPS_INTR_H_ +#define NINTR 32 + void platform_establish_hardintr(int, void (*)(void *), void *); void platform_establish_softintr(int, void (*)(void *), void *); ==== //depot/projects/mips/sys/mips/sgimips/ip22.c#8 (text+ko) ==== @@ -1,7 +1,7 @@ -/* $NetBSD: ip22.c,v 1.14 2002/11/09 19:21:12 thorpej Exp $ */ +/* $NetBSD: int.c,v 1.7 2004/04/11 12:05:37 pooka Exp $ */ /* - * Copyright (c) 2001, 2002 Rafal K. Boni + * Copyright (c) 2004 Christopher SEKIYA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,128 +27,255 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* + * INT/INT2/INT3 interrupt controller (used in Indy's, Indigo's, etc..) + */ + +#include +#ifdef __KERNEL_RCSID +__KERNEL_RCSID(0, "$NetBSD: int.c,v 1.7 2004/04/11 12:05:37 pooka Exp $"); +#endif +__FBSDID("$FreeBSD$"); + #include #include #include #include -#include -#include -#include +#include #include - +#include +#include #include #include #include +#include -static u_int32_t iocwrite; /* IOC write register: read-only */ -static u_int32_t iocreset; /* IOC reset register: read-only */ +static bus_space_handle_t ioh; +static bus_space_tag_t iot; -void ip22_watchdog(int); -unsigned long ip22_cal_timer(u_int32_t, u_int32_t); +static void int_local0_intr(void *); +static void int_local1_intr(void *); +static void int_mappable_intr(void *); +static unsigned long int_cal_timer(void); +static void ip22_watchdog(int); -/* ip22_cache.S */ -extern void ip22_sdcache_enable(void); -extern void ip22_sdcache_disable(void); +static struct intrhand { + void (*ih_fun)(void *); + void *ih_arg; +} intrtab[NINTR]; void ip22_init(void) { - u_int i; - u_int32_t sysid; - u_int32_t int23addr; - unsigned long cps; - unsigned long ctrdiff[3]; + u_int32_t address; + + if (mach_type == MACH_SGI_IP22) { + printf("int: "); + if (mach_subtype == MACH_SGI_IP22_FULLHOUSE) { + printf("IP22"); + address = INT_IP22; + } else { + printf("IP24"); + address = INT_IP24; + } + } else + panic("int0: passed match, but failed attach?"); + + printf(" addr 0x%x", address); + +#if notyet + bus_space_map(iot, address, 0, 0, &ioh); +#else + ioh = address; +#endif + iot = device_space_tag; + + /* Clean out interrupt masks */ + bus_space_write_4(iot, ioh, INT2_LOCAL0_MASK, 0); + bus_space_write_4(iot, ioh, INT2_LOCAL1_MASK, 0); + bus_space_write_4(iot, ioh, INT2_MAP_MASK0, 0); + bus_space_write_4(iot, ioh, INT2_MAP_MASK1, 0); + + /* Reset timer interrupts */ + bus_space_write_4(iot, ioh, INT2_TIMER_CLEAR, 0x03); + + switch (mach_type) { + case MACH_SGI_IP22: + { + int i; + unsigned long cps; + unsigned long ctrdiff[3]; + + platform_establish_hardintr(0, int_local0_intr, NULL); + platform_establish_hardintr(1, int_local1_intr, NULL); + + /* calibrate timer */ + int_cal_timer(); + + cps = 0; + for (i = 0; + i < sizeof(ctrdiff) / sizeof(ctrdiff[0]); i++) { + do { + ctrdiff[i] = int_cal_timer(); + } while (ctrdiff[i] == 0); + + cps += ctrdiff[i]; + } + + cps = cps / (sizeof(ctrdiff) / sizeof(ctrdiff[0])); + + printf(": bus %luMHz, CPU %luMHz", cps / 10000, cps / 5000); + + /* R4k/R4400/R4600/R5k count at half CPU frequency */ + curcpu()->ci_cpu_freq = 2 * cps * hz; + break; + } + default: + panic("int0: unsupported machine type %i\n", mach_type); + break; + } + + printf("\n"); + + 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()); + + if (mach_type == MACH_SGI_IP22) { + /* Wire interrupts 7, 11 to mappable interrupt 0,1 handlers */ + intrtab[7].ih_fun = int_mappable_intr; + intrtab[7].ih_arg = (void*) 0; + + intrtab[11].ih_fun = int_mappable_intr; + intrtab[11].ih_arg = (void*) 1; + } /* enable watchdog timer, clear it */ - *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(0x1fa00004) |= 0x100; + platform.watchdog = ip22_watchdog; + (*platform.watchdog)(1); *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(0x1fa00014) = 0; +} - sysid = *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(0x1fbd9858); +static void +int_mappable_intr(void *arg) +{ + int i; + int intnum; + u_int32_t mstat; + u_int32_t mmask; + long which = (long)arg; - if (sysid & 1) - mach_subtype = MACH_SGI_IP22_FULLHOUSE; - else - mach_subtype = MACH_SGI_IP22_GUINESS; + mstat = bus_space_read_4(iot, ioh, INT2_MAP_STATUS); + mmask = bus_space_read_4(iot, ioh, INT2_MAP_MASK0 + (which << 2)); - mach_boardrev = (sysid >> 1) & 0x0f; + mstat &= mmask; - printf("IOC rev %d, machine %s, board rev %d\n", (sysid >> 5) & 0x07, - (sysid & 1) ? "Indigo2 (Fullhouse)" : "Indy (Guiness)", - (sysid >> 1) & 0x0f); + for (i = 0; i < 8; i++) { + intnum = i + 16 + (which << 3); + if (mstat & (1 << i)) { + if (intrtab[intnum].ih_fun != NULL) + (intrtab[intnum].ih_fun)(intrtab[intnum].ih_arg); + else + printf("int0: unexpected mapped interrupt %d\n", + intnum); + } + } +} - if (mach_subtype == MACH_SGI_IP22_FULLHOUSE) - int23addr = 0x1fbd9000; - else - int23addr = 0x1fbd9880; +static void +int_local0_intr(void *arg) +{ + int i; + u_int32_t l0stat; + u_int32_t l0mask; - /* Reset timer interrupts */ - *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(int23addr + 0x20) = 3; + l0stat = bus_space_read_4(iot, ioh, INT2_LOCAL0_STATUS); + l0mask = bus_space_read_4(iot, ioh, INT2_LOCAL0_MASK); - /* - * Reset Parallel port, Keyboard/mouse and EISA. Turn LED off. - * For Fullhouse, toggle magic GIO reset bit. - */ - iocreset = 0x17; - if (mach_subtype == MACH_SGI_IP22_FULLHOUSE) - iocreset |= 0x08; + l0stat &= l0mask; - *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(0x1fbd9870) = iocreset; + for (i = 0; i < 8; i++) { + if (l0stat & (1 << i)) { + if (intrtab[i].ih_fun != NULL) + (intrtab[i].ih_fun)(intrtab[i].ih_arg); + else + printf("int0: unexpected local0 interrupt %d\n", + i); + } + } +} - /* - * Set the 10BaseT port to use UTP cable, set autoselect mode for - * the ethernet interface (AUI vs. TP), set the two serial ports - * to PC mode. - */ - iocwrite = 0x3a; - *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(0x1fbd9878) = iocwrite; +static void +int_local1_intr(void *arg) +{ + int i; + u_int32_t l1stat; + u_int32_t l1mask; - /* Clean out interrupt masks */ - *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(int23addr + 0x04) = 0x00; - *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(int23addr + 0x0c) = 0x00; + l1stat = bus_space_read_4(iot, ioh, INT2_LOCAL1_STATUS); + l1mask = bus_space_read_4(iot, ioh, INT2_LOCAL1_MASK); - *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(int23addr + 0x14) = 0x00; - *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(int23addr + 0x18) = 0x00; + l1stat &= l1mask; - /* Set the general control registers for Guiness */ - if (mach_subtype == MACH_SGI_IP22_GUINESS) { - *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(0x1fbd9848) = 0xff; - *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(0x1fbd984c) = 0xff; + for (i = 0; i < 8; i++) { + if (l1stat & (1 << i)) { + if (intrtab[8 + i].ih_fun != NULL) + (intrtab[8 + i].ih_fun)(intrtab[8 + i].ih_arg); + else + printf("int0: unexpected local1 interrupt %x\n", + 8 + i); + } } +} - platform.watchdog = ip22_watchdog; +void +ip22_intr_establish(int level, void (*handler)(void *), void *arg) +{ + u_int32_t mask; - /* Prime cache */ - ip22_cal_timer(int23addr + 0x3c, int23addr + 0x38); + if (level < 0 || level >= NINTR) + panic("invalid interrupt level"); - cps = 0; - for(i = 0; i < sizeof(ctrdiff) / sizeof(ctrdiff[0]); i++) { - do { - ctrdiff[i] = ip22_cal_timer(int23addr + 0x3c, - int23addr + 0x38); - } while (ctrdiff[i] == 0); - - cps += ctrdiff[i]; + if (intrtab[level].ih_fun != NULL) { + printf("int0: cannot share interrupts yet.\n"); + return; } - cps = cps / (sizeof(ctrdiff) / sizeof(ctrdiff[0])); + intrtab[level].ih_fun = handler; + intrtab[level].ih_arg = arg; - printf("Timer calibration, got %lu cycles (%lu, %lu, %lu)\n", cps, - ctrdiff[0], ctrdiff[1], ctrdiff[2]); + if (level < 8) { + mask = bus_space_read_4(iot, ioh, INT2_LOCAL0_MASK); + mask |= (1 << level); + bus_space_write_4(iot, ioh, INT2_LOCAL0_MASK, mask); + } else if (level < 16) { + mask = bus_space_read_4(iot, ioh, INT2_LOCAL1_MASK); + mask |= (1 << (level - 8)); + bus_space_write_4(iot, ioh, INT2_LOCAL1_MASK, mask); + } else if (level < 24) { + /* Map0 interrupt maps to l0 bit 7, so turn that on too */ + mask = bus_space_read_4(iot, ioh, INT2_LOCAL0_MASK); + mask |= (1 << 7); + bus_space_write_4(iot, ioh, INT2_LOCAL0_MASK, mask); - /* Counter on R4k/R4400/R4600/R5k counts at half the CPU frequency */ - curcpu()->ci_cpu_freq = 2 * cps * 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()); + mask = bus_space_read_4(iot, ioh, INT2_MAP_MASK0); + mask |= (1 << (level - 16)); + bus_space_write_4(iot, ioh, INT2_MAP_MASK0, mask); + } else { + /* Map1 interrupt maps to l1 bit 3, so turn that on too */ + mask = bus_space_read_4(iot, ioh, INT2_LOCAL1_MASK); + mask |= (1 << 3); + bus_space_write_4(iot, ioh, INT2_LOCAL1_MASK, mask); - printf("CPU clock speed = %lu.%02luMhz\n", - curcpu()->ci_cpu_freq / 1000000, - (curcpu()->ci_cpu_freq / 10000) % 100); + mask = bus_space_read_4(iot, ioh, INT2_MAP_MASK1); + mask |= (1 << (level - 24)); + bus_space_write_4(iot, ioh, INT2_MAP_MASK1, mask); + } } -unsigned long -ip22_cal_timer(u_int32_t tctrl, u_int32_t tcount) +static unsigned long +int_cal_timer(void) { int s; int roundtime; @@ -167,58 +294,32 @@ s = splhigh(); - *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(tctrl) = 0x80 | 0x30 | 0x04; - *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(tcount) = sampletime & 0xff; - *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(tcount) = sampletime >> 8; + bus_space_write_4(iot, ioh, INT2_TIMER_CONTROL, + ( TIMER_SEL2 | TIMER_16BIT | TIMER_RATEGEN) ); + bus_space_write_4(iot, ioh, INT2_TIMER_2, (sampletime & 0xff)); + bus_space_write_4(iot, ioh, INT2_TIMER_2, (sampletime >> 8)); startctr = mips_rd_count(); /* Wait for the MSB to count down to zero */ do { - *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(tctrl) = 0x80 | 0x00; - lsb = *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(tcount) & 0xff; - msb = *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(tcount) & 0xff; + bus_space_write_4(iot, ioh, INT2_TIMER_CONTROL, TIMER_SEL2 ); + lsb = bus_space_read_4(iot, ioh, INT2_TIMER_2) & 0xff; + msb = bus_space_read_4(iot, ioh, INT2_TIMER_2) & 0xff; endctr = mips_rd_count(); } while (msb); /* Turn off timer */ - *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(tctrl) = 0x80 | 0x30 | 0x08; + bus_space_write_4(iot, ioh, INT2_TIMER_CONTROL, + ( TIMER_SEL2 | TIMER_16BIT | TIMER_SWSTROBE) ); splx(s); return (endctr - startctr) / roundtime * roundtime; } -void ip22_cache_init(void); - -void -ip22_cache_init(void) -{ - - /* - * If we don't have an R4000-style cache, then initialize the - * IP22 SysAD L2 cache. - * - * XXX: For now we disable the SysAD cache on R4600/R5k systems, - * as there's no code to drive it; also make sure to clear the - * flags used by the generic MIPS code so it doesn't attempt to - * use the L2. - */ - switch (MIPS_PRID_IMPL(cpu_id)) { - case MIPS_R4600: -#ifndef ENABLE_MIPS_R3NKK - case MIPS_R5000: -#endif - mips_sdcache_size = 0; - mips_sdcache_line_size = 0; - printf("disabling IP22 SysAD L2 cache\n"); - ip22_sdcache_disable(); - break; - } -} - -void +static void ip22_watchdog(int enable) { if (enable) ==== //depot/projects/mips/sys/mips/sgimips/models.h#2 (text+ko) ==== @@ -38,5 +38,6 @@ extern int mach_boardrev; /* machine board revision, in case it matters */ void ip22_init(void); +void ip22_intr_establish(int, void (*)(void *), void *); #endif /* _SGIMIPS_MODELS_H_ */