Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 14 Jun 2004 02:34:03 GMT
From:      Juli Mallett <jmallett@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 54886 for review
Message-ID:  <200406140234.i5E2Y3b5039697@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 <sys/cdefs.h>
+#ifdef	__KERNEL_RCSID
+__KERNEL_RCSID(0, "$NetBSD: int.c,v 1.7 2004/04/11 12:05:37 pooka Exp $");
+#endif
+__FBSDID("$FreeBSD$");
+
 #include <sys/param.h>
 #include <sys/proc.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
 
-#include <machine/locore.h>
-#include <machine/cache.h>
-#include <machine/cpu.h>
+#include <machine/bus.h>
 #include <machine/cpuinfo.h>
-
+#include <platform/int2reg.h>
+#include <platform/int2var.h>
 #include <platform/intr.h>
 #include <platform/models.h>
 #include <platform/sysconf.h>
+#include <platform/timerreg.h>
 
-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_ */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200406140234.i5E2Y3b5039697>