FreeBSD/mips booting on Sibyte 1250

Neelkanth Natu neelnatu at yahoo.com
Wed Jun 17 04:52:29 UTC 2009


Hi Warner,

I have attached the diffs against -current at revision 194280.

There are some changes in the diff that are unrelated to the sibyte
work and probably should be committed separately.

I can provide more information about changes to specific files if necessary.

best
Neel

--- On Fri, 6/12/09, M. Warner Losh <imp at bsdimp.com> wrote:

> From: M. Warner Losh <imp at bsdimp.com>
> Subject: Re: FreeBSD/mips booting on Sibyte 1250
> To: neelnatu at yahoo.com
> Cc: freebsd-mips at freebsd.org
> Date: Friday, June 12, 2009, 8:33 PM
> In message: <856232.92278.qm at web34401.mail.mud.yahoo.com>
>             Neelkanth Natu
> <neelnatu at yahoo.com>
> writes:
> : I don't want to keep holding diffs against -current for
> this, so I was
> : hoping to get this checked in. How do I go about doing
> that?
> 
> diffs would be a good start :)
> 
> Usually, we pass them through /projects/mips/* to make sure
> that we
> have a good integration branch before we collapse/merge the
> changes
> into -current.
> 
> Warner
>


      
-------------- next part --------------
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/conf/files.mips ./sys/conf/files.mips
--- /u/neelnatu/p4/freebsd_current/src/sys/conf/files.mips	2009-06-15 23:27:26.208231000 -0700
+++ ./sys/conf/files.mips	2009-06-16 17:31:21.727409000 -0700
@@ -94,5 +94,6 @@
 
 dev/cfe/cfe_api.c		optional	cfe
 dev/cfe/cfe_console.c		optional	cfe_console
+dev/cfe/cfe_env.c		optional	cfe_env
 #dev/cfe/cfe_resource.c		optional	cfe	# not yet needed
 
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/conf/options.mips ./sys/conf/options.mips
--- /u/neelnatu/p4/freebsd_current/src/sys/conf/options.mips	2009-06-15 23:27:26.286232000 -0700
+++ ./sys/conf/options.mips	2009-06-16 17:31:21.732415000 -0700
@@ -33,6 +33,7 @@
 CPU_MIPS64	opt_global.h
 CPU_NOFPU	opt_global.h
 CPU_SENTRY5	opt_global.h
+CPU_SB1		opt_global.h
 
 ISA_MIPS1	opt_cputype.h
 ISA_MIPS3	opt_cputype.h
@@ -44,6 +45,8 @@
 YAMON		opt_global.h
 CFE		opt_global.h
 CFE_CONSOLE	opt_global.h
+CFE_ENV		opt_global.h
+CFE_ENV_SIZE	opt_global.h
 
 KERNPHYSADDR	opt_global.h
 KERNVIRTADDR	opt_global.h
@@ -55,3 +58,8 @@
 
 TICK_USE_YAMON_FREQ	opt_global.h
 TICK_USE_MALTA_RTC	opt_global.h
+
+PCI_IOSPACE_SIZE	opt_global.h
+PCI_IOSPACE_ADDR	opt_global.h
+
+MAXMEM			opt_global.h
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/dev/cfe/cfe_api.c ./sys/dev/cfe/cfe_api.c
--- /u/neelnatu/p4/freebsd_current/src/sys/dev/cfe/cfe_api.c	2009-06-15 23:27:31.799448000 -0700
+++ ./sys/dev/cfe/cfe_api.c	2009-06-16 17:31:21.738412000 -0700
@@ -160,7 +160,7 @@
 {
     cfe_xiocb_t xiocb;
 
-    xiocb.xiocb_fcode = CFE_CMD_ENV_SET;
+    xiocb.xiocb_fcode = CFE_CMD_ENV_ENUM;
     xiocb.xiocb_status = 0;
     xiocb.xiocb_handle = 0;
     xiocb.xiocb_flags = 0;
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/dev/cfe/cfe_console.c ./sys/dev/cfe/cfe_console.c
--- /u/neelnatu/p4/freebsd_current/src/sys/dev/cfe/cfe_console.c	2009-06-15 23:27:31.825449000 -0700
+++ ./sys/dev/cfe/cfe_console.c	2009-06-16 17:31:21.747410000 -0700
@@ -84,14 +84,12 @@
 static void
 cn_drvinit(void *unused)
 {
-	char output[32];
 	struct tty *tp;
 
 	if (cfe_consdev.cn_pri != CN_DEAD &&
 	    cfe_consdev.cn_name[0] != '\0') {
 		tp = tty_alloc(&cfe_ttydevsw, NULL);
-		tty_makedev(tp, NULL, "%s", output);
-		tty_makealias(tp, "cfecons");
+		tty_makedev(tp, NULL, "cfecons");
 	}
 }
 
@@ -117,15 +115,21 @@
 static void
 cfe_tty_outwakeup(struct tty *tp)
 {
-	int len;
+	int len, written, rc;
 	u_char buf[CFEBURSTLEN];
 
 	for (;;) {
 		len = ttydisc_getc(tp, buf, sizeof buf);
 		if (len == 0)
 			break;
-		while (cfe_write(conhandle, buf, len) == 0)
-			continue;
+
+		written = 0;
+		while (written < len) {
+			rc = cfe_write(conhandle, &buf[written], len - written);
+			if (rc < 0)
+				break;
+			written += rc;
+		}
 	}
 }
 
@@ -184,13 +188,9 @@
 static int
 cfe_cngetc(struct consdev *cp)
 {
-	int result;
 	unsigned char ch;
 
-	while ((result = cfe_read(conhandle, &ch, 1)) == 0)
-		continue;
-
-	if (result > 0) {
+	if (cfe_read(conhandle, &ch, 1) == 1) {
 #if defined(KDB) && defined(ALT_BREAK_TO_DEBUGGER)
 		int kdb_brk;
 
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/dev/cfe/cfe_env.c ./sys/dev/cfe/cfe_env.c
--- /u/neelnatu/p4/freebsd_current/src/sys/dev/cfe/cfe_env.c	1969-12-31 16:00:00.000000000 -0800
+++ ./sys/dev/cfe/cfe_env.c	2009-05-12 01:12:44.728865000 -0700
@@ -0,0 +1,74 @@
+/*-
+ * Copyright (c) 2009 Neelkanth Natu
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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/kernel.h>
+#include <sys/systm.h>
+
+#include <dev/cfe/cfe_api.h>
+
+__FBSDID("$FreeBSD$");
+
+#ifndef	CFE_ENV_SIZE
+#define	CFE_ENV_SIZE	PAGE_SIZE	/* default is one page */
+#endif
+
+extern void cfe_env_init(void);
+
+static char cfe_env_buf[CFE_ENV_SIZE];
+
+void
+cfe_env_init(void)
+{
+	int idx, len;
+	char name[64], val[128], *cp, *cplim;
+
+	cp = cfe_env_buf;
+	cplim = cp + CFE_ENV_SIZE;
+
+	idx = 0;
+	while (1) {
+		if (cfe_enumenv(idx, name, sizeof(name), val, sizeof(val)) != 0)
+			break;
+
+		if (bootverbose)
+			printf("Importing CFE env: \"%s=%s\"\n", name, val);
+
+		/*
+		 * name=val\0\0
+		 */
+		len = strlen(name) + 1 + strlen(val) + 1 + 1;
+		if (cplim - cp < len)
+			printf("No space to store CFE env: \"%s=%s\"\n",
+				name, val);
+		else
+			cp += sprintf(cp, "%s=%s", name, val) + 1;
+		++idx;
+	}
+	*cp++ = '\0';
+
+	kern_envp = cfe_env_buf;
+}
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/mips/conf/SWARM ./sys/mips/conf/SWARM
--- /u/neelnatu/p4/freebsd_current/src/sys/mips/conf/SWARM	1969-12-31 16:00:00.000000000 -0800
+++ ./sys/mips/conf/SWARM	2009-06-13 12:17:44.499588000 -0700
@@ -0,0 +1,82 @@
+#
+# $Id: //depot/user/neelnatu/freebsd_sibyte/src/sys/mips/conf/SWARM#7 $
+#
+
+ident		SWARM
+options		CPU_NOFPU
+options		CPU_SB1
+
+files		"../sibyte/files.sibyte"
+hints		"SWARM.hints"
+
+options		PCI_IOSPACE_ADDR=0xFC000000
+options		PCI_IOSPACE_SIZE=0x02000000
+
+#
+# 32-bit kernel cannot deal with physical memory beyond 4GB
+#
+options		MAXMEM=4096*1024
+
+options		CFE
+options		CFE_CONSOLE
+options		CFE_ENV
+options		ALT_BREAK_TO_DEBUGGER
+
+# cfe loader expects kernel at 0x80001000 for mips32 w/o backwards
+# offsets in the linked elf image (see ldscript hack)
+# XXX can we conditionalize the linker stuff on options CFE?
+options		KERNVIRTADDR=0x80001000
+
+makeoptions	LDSCRIPT_NAME=	ldscript.mips.cfe
+
+#cpu		CPU_MIPS64
+#options 	ISA_MIPS64
+#makeoptions	ARCH_FLAGS="-march=mips64 -mgp64 -mabi=o64"
+cpu		CPU_MIPS32
+options 	ISA_MIPS32
+makeoptions	ARCH_FLAGS="-march=mips32"
+
+makeoptions	DEBUG=-g		#Build kernel with gdb(1) debug symbols
+makeoptions	MODULES_OVERRIDE=""
+
+options		DDB
+options		KDB
+
+options		SCHED_4BSD		#4BSD scheduler
+options		INET			#InterNETworking
+options		NFSCLIENT		#Network Filesystem Client
+options		NFS_ROOT		#NFS usable as /, requires NFSCLIENT
+options		PSEUDOFS		#Pseudo-filesystem framework
+options		_KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions
+
+# Debugging for use in -current
+options		INVARIANTS
+options		INVARIANT_SUPPORT
+options		WITNESS
+
+options		MD_ROOT
+options		MD_ROOT_SIZE=4096
+options 	FFS			#Fast filesystem
+
+device		pci
+device		miibus
+device		bge
+device		loop
+device		ether
+device		md
+
+options		USB_DEBUG
+device usb
+device ohci
+device uhci
+device ehci
+
+device umass
+
+device scbus
+device da
+
+device		ata
+device		atadisk
+device		atapicd
+options		ATA_STATIC_ID
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/mips/conf/SWARM.hints ./sys/mips/conf/SWARM.hints
--- /u/neelnatu/p4/freebsd_current/src/sys/mips/conf/SWARM.hints	1969-12-31 16:00:00.000000000 -0800
+++ ./sys/mips/conf/SWARM.hints	2009-05-30 19:35:45.581258000 -0700
@@ -0,0 +1,17 @@
+# $FreeBSD$
+hint.zbbus.0.at="nexus0"
+hint.zbpci.0.at="zbbus0"
+hint.scd.0.at="zbbus0"
+
+#
+# SWARM IDE interface is on the generic bus at chip select 4.
+# The CS4 region is 64KB in size and starts at 0x100B0000.
+# The IDE interrupt is wired to GPIO4 (intsrc 36 to the interrupt mapper)
+#
+hint.ata.0.at="zbbus0"
+hint.ata.0.maddr=0x100B0000
+hint.ata.0.msize=0x10000
+hint.ata.0.irq=36
+#hint.ata.0.disabled=0
+#hint.ata.0.regoffset=0x1F0
+#hint.ata.0.regshift=5
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/mips/include/cpu.h ./sys/mips/include/cpu.h
--- /u/neelnatu/p4/freebsd_current/src/sys/mips/include/cpu.h	2009-06-15 23:27:51.494233000 -0700
+++ ./sys/mips/include/cpu.h	2009-06-16 17:31:21.752415000 -0700
@@ -154,7 +154,11 @@
  * The bits in the CONFIG register
  */
 #define CFG_K0_UNCACHED	2
+#if defined(CPU_SB1)
+#define CFG_K0_COHERENT	5	/* cacheable coherent */
+#else
 #define	CFG_K0_CACHED	3
+#endif
 
 /*
  * The bits in the context register.
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/mips/include/cpuregs.h ./sys/mips/include/cpuregs.h
--- /u/neelnatu/p4/freebsd_current/src/sys/mips/include/cpuregs.h	2009-06-15 23:27:51.500230000 -0700
+++ ./sys/mips/include/cpuregs.h	2009-06-16 17:31:21.758417000 -0700
@@ -103,6 +103,8 @@
 /* CPU dependent mtc0 hazard hook */
 #ifdef TARGET_OCTEON
 #define	COP0_SYNC  nop; nop; nop; nop; nop;
+#elif defined(CPU_SB1)
+#define COP0_SYNC  ssnop; ssnop; ssnop; ssnop; ssnop; ssnop; ssnop; ssnop; ssnop
 #else
 #define	COP0_SYNC		/* nothing */
 #endif
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/mips/include/intr.h ./sys/mips/include/intr.h
--- /u/neelnatu/p4/freebsd_current/src/sys/mips/include/intr.h	2009-06-15 23:27:51.535235000 -0700
+++ ./sys/mips/include/intr.h	2009-06-16 17:31:21.766414000 -0700
@@ -75,8 +75,8 @@
 
 typedef void (*mask_fn)(void *);
 
-void mips_mask_irq(void);
-void mips_unmask_irq(void);
+void mips_mask_irq(void *);
+void mips_unmask_irq(void *);
 
 struct trapframe;
 void	mips_set_intr(int pri, uint32_t mask,
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/mips/include/intr_machdep.h ./sys/mips/include/intr_machdep.h
--- /u/neelnatu/p4/freebsd_current/src/sys/mips/include/intr_machdep.h	2009-06-15 23:27:51.537233000 -0700
+++ ./sys/mips/include/intr_machdep.h	2009-06-16 17:31:21.774409000 -0700
@@ -34,6 +34,27 @@
 
 struct trapframe;
 
+/*
+ * An interrupt source is defined by its interrupt number and handlers to
+ * mask and unmask the sources that trigger it.
+ *
+ * Once an interrupt handler is established for a particular interrupt number
+ * we always keep it enabled from the mips core point of view. However we may
+ * choose to mask the interrupt source feeding into it until the ithread has
+ * had a chance to run.
+ *
+ * XXX how does this work with platforms that have no interrupt mapper feeding
+ * interrupts to the cpu core?
+ */
+struct intsrc {
+	int	intrnum;
+	void 	(*mask_func)(struct intsrc *isrc);
+	void 	(*unmask_func)(struct intsrc *isrc);
+};
+
+int cpu_register_hard_intsrc(struct intsrc *isrc);
+int cpu_register_soft_intsrc(struct intsrc *isrc);
+
 void cpu_establish_hardintr(const char *, int (*)(void*), void (*)(void*), 
     void *, int, int, void **);
 void cpu_establish_softintr(const char *, int (*)(void*), void (*)(void*), 
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/mips/include/md_var.h ./sys/mips/include/md_var.h
--- /u/neelnatu/p4/freebsd_current/src/sys/mips/include/md_var.h	2009-06-15 23:27:51.545233000 -0700
+++ ./sys/mips/include/md_var.h	2009-06-16 17:31:21.793420000 -0700
@@ -39,7 +39,7 @@
 /*
  * Miscellaneous machine-dependent declarations.
  */
-extern	int	Maxmem;
+extern	long	Maxmem;
 extern	char	sigcode[];
 extern	int	szsigcode, szosigcode;
 
@@ -52,6 +52,7 @@
 u_long	kvtop(void *addr);
 int	is_physical_memory(vm_offset_t addr);
 int	is_cacheable_mem(vm_offset_t pa);
+int	is_coherent_mem(vm_offset_t pa);
 
 #define	MIPS_DEBUG   0
 
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/mips/include/pltfm.h ./sys/mips/include/pltfm.h
--- /u/neelnatu/p4/freebsd_current/src/sys/mips/include/pltfm.h	2009-06-15 23:27:51.569235000 -0700
+++ ./sys/mips/include/pltfm.h	2009-06-16 17:31:21.801415000 -0700
@@ -6,6 +6,12 @@
 #ifndef _MACHINE_PLTFM_H_
 #define	_MACHINE_PLTFM_H_
 
+#ifdef CPU_SB1
+/*
+ * XXX Make sure that these macros are not defined for the SB-1 cpu
+ * since they don't make any sense for it.
+ */
+#else
 /*
  * This files contains platform-specific definitions.
  */
@@ -25,5 +31,6 @@
 #endif
 #define	ADDR_NS16550_UART1	0x1ef14000	/* UART */
 #define	VADDR_NS16550_UART1	0xbef14000	/* UART */
+#endif
 
 #endif /* !_MACHINE_PLTFM_H_ */
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/mips/include/pte.h ./sys/mips/include/pte.h
--- /u/neelnatu/p4/freebsd_current/src/sys/mips/include/pte.h	2009-06-15 23:27:51.594236000 -0700
+++ ./sys/mips/include/pte.h	2009-06-16 17:31:21.808412000 -0700
@@ -105,7 +105,11 @@
 #define PTE_ODDPG       0x00001000 
 /*#define	PG_ATTR		0x0000003f  Not Used */
 #define	PTE_UNCACHED	0x00000010
+#ifdef CPU_SB1
+#define	PTE_CACHE	0x00000028	/* cacheable coherent */
+#else
 #define	PTE_CACHE	0x00000018
+#endif
 /*#define	PG_CACHEMODE	0x00000038 Not Used*/
 #define	PTE_ROPAGE	(PTE_V | PTE_RO | PTE_CACHE) /* Write protected */
 #define	PTE_RWPAGE	(PTE_V | PTE_M | PTE_CACHE)  /* Not wr-prot not clean */
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/mips/mips/autoconf.c ./sys/mips/mips/autoconf.c
--- /u/neelnatu/p4/freebsd_current/src/sys/mips/mips/autoconf.c	2009-06-15 23:27:51.705239000 -0700
+++ ./sys/mips/mips/autoconf.c	2009-06-16 17:31:21.813412000 -0700
@@ -93,6 +93,17 @@
 configure(dummy)
 	void *dummy;
 {
+	register_t sr;
+
+	/*
+	 * Enable interrupts on the processor. The interrupts are still
+	 * disabled by the interrupt mask bits until interrupt handlers
+	 * are registered.
+	 */
+	sr = mips_rd_status();
+	sr &= ~MIPS_INT_MASK;
+	sr |= MIPS_SR_INT_IE;
+	mips_wr_status(sr);
 
 	/* initialize new bus architecture */
 	root_bus_configure();
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/mips/mips/busdma_machdep.c ./sys/mips/mips/busdma_machdep.c
--- /u/neelnatu/p4/freebsd_current/src/sys/mips/mips/busdma_machdep.c	2009-06-15 23:27:51.707240000 -0700
+++ ./sys/mips/mips/busdma_machdep.c	2009-06-16 17:31:21.818418000 -0700
@@ -88,6 +88,7 @@
 #include <machine/bus.h>
 #include <machine/cache.h>
 #include <machine/cpufunc.h>
+#include <machine/md_var.h>
 
 struct bus_dma_tag {
 	bus_dma_tag_t		parent;
@@ -270,8 +271,7 @@
 	newtag->map_count = 0;
 	newtag->_wbase = 0;
 	newtag->_physbase = 0;
-	/* XXXMIPS: Should we limit window size to amount of physical memory */
-	newtag->_wsize = MIPS_KSEG1_START - MIPS_KSEG0_START;
+	newtag->_wsize = ptoa(Maxmem);
 	if (lockfunc != NULL) {
 		newtag->lockfunc = lockfunc;
 		newtag->lockfuncarg = lockfuncarg;
@@ -397,6 +397,7 @@
                  bus_dmamap_t *mapp)
 {
 	bus_dmamap_t newmap = NULL;
+	void *tmpaddr;
 
 	int mflags;
 
@@ -417,7 +418,9 @@
 	*mapp = newmap;
 	newmap->dmat = dmat;
 	
-        if (dmat->maxsize <= PAGE_SIZE) {
+        if (dmat->maxsize <= PAGE_SIZE &&
+	    dmat->alignment < dmat->maxsize &&
+	    dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem)) {
                 *vaddr = malloc(dmat->maxsize, M_DEVBUF, mflags);
         } else {
                 /*
@@ -450,19 +453,20 @@
 		}
 		*mapp = NULL;
                 return (ENOMEM);
+	} else if ((uintptr_t)*vaddr & (dmat->alignment - 1)) {
+		printf("bus_dmamem_alloc failed to align memory properly.\n");
 	}
-	if (flags & BUS_DMA_COHERENT) {
-		void *tmpaddr = (void *)*vaddr;
 
-		if (tmpaddr) {
-			tmpaddr = (void *)MIPS_PHYS_TO_KSEG1(vtophys(tmpaddr));
-			newmap->origbuffer = *vaddr;
-			newmap->allocbuffer = tmpaddr;
-			mips_dcache_wbinv_range((vm_offset_t)*vaddr,
-			    dmat->maxsize);
-			*vaddr = tmpaddr;
-		} else
-			newmap->origbuffer = newmap->allocbuffer = NULL;
+	tmpaddr = (void *)*vaddr;
+	if ((flags & BUS_DMA_COHERENT) && !is_coherent_mem(vtophys(tmpaddr))) {
+		KASSERT(vtophys(tmpaddr) < MIPS_KSEG0_LARGEST_PHYS,
+			("bus_dmamem_alloc: physaddr 0x%0x cannot "
+			 "be mapped in KSEG1", vtophys(tmpaddr)));
+		tmpaddr = (void *)MIPS_PHYS_TO_KSEG1(vtophys(tmpaddr));
+		newmap->origbuffer = *vaddr;
+		newmap->allocbuffer = tmpaddr;
+		mips_dcache_wbinv_range((vm_offset_t)*vaddr, dmat->maxsize);
+		*vaddr = tmpaddr;
 	} else 
 		newmap->origbuffer = newmap->allocbuffer = NULL;
         return (0);
@@ -481,7 +485,9 @@
 		    ("Trying to freeing the wrong DMA buffer"));
 		vaddr = map->origbuffer;
 	}
-        if (dmat->maxsize <= PAGE_SIZE)
+        if (dmat->maxsize <= PAGE_SIZE &&
+	    dmat->alignment < dmat->maxsize &&
+	    dmat->lowaddr >= ptoa(Maxmem))
 		free(vaddr, M_DEVBUF);
         else {
 		contigfree(vaddr, dmat->maxsize, M_DEVBUF);
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/mips/mips/cpu.c ./sys/mips/mips/cpu.c
--- /u/neelnatu/p4/freebsd_current/src/sys/mips/mips/cpu.c	2009-06-15 23:27:51.715239000 -0700
+++ ./sys/mips/mips/cpu.c	2009-06-16 17:31:21.824411000 -0700
@@ -92,9 +92,9 @@
     cpuinfo->tlb_nentries = ((cfg1 & MIPS_CONFIG1_TLBSZ_MASK) >> MIPS_CONFIG1_TLBSZ_SHIFT) + 1;
 
     /* L1 instruction cache. */
-    tmp = 1 << (((cfg1 & MIPS_CONFIG1_IL_MASK) >> MIPS_CONFIG1_IL_SHIFT) + 1);
+    tmp = (cfg1 & MIPS_CONFIG1_IL_MASK) >> MIPS_CONFIG1_IL_SHIFT;
     if (tmp != 0) {
-	cpuinfo->l1.ic_linesize = tmp;
+	cpuinfo->l1.ic_linesize = 1 << (tmp + 1);
 	cpuinfo->l1.ic_nways = (((cfg1 & MIPS_CONFIG1_IA_MASK) >> MIPS_CONFIG1_IA_SHIFT)) + 1;
 	cpuinfo->l1.ic_nsets = 1 << (((cfg1 & MIPS_CONFIG1_IS_MASK) >> MIPS_CONFIG1_IS_SHIFT) + 6);
 	cpuinfo->l1.ic_size = cpuinfo->l1.ic_linesize * cpuinfo->l1.ic_nsets 
@@ -102,9 +102,9 @@
     }
 
     /* L1 data cache. */
-    tmp = 1 << (((cfg1 & MIPS_CONFIG1_DL_MASK) >> MIPS_CONFIG1_DL_SHIFT) + 1);
+    tmp = (cfg1 & MIPS_CONFIG1_DL_MASK) >> MIPS_CONFIG1_DL_SHIFT;
     if (tmp != 0) {
-	cpuinfo->l1.dc_linesize = tmp;
+	cpuinfo->l1.dc_linesize = 1 << (tmp + 1);
 	cpuinfo->l1.dc_nways = (((cfg1 & MIPS_CONFIG1_DA_MASK) >> MIPS_CONFIG1_DA_SHIFT)) + 1;
 	cpuinfo->l1.dc_nsets = 1 << (((cfg1 & MIPS_CONFIG1_DS_MASK) >> MIPS_CONFIG1_DS_SHIFT) + 6);
 #ifdef TARGET_OCTEON
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/mips/mips/intr_machdep.c ./sys/mips/mips/intr_machdep.c
--- /u/neelnatu/p4/freebsd_current/src/sys/mips/mips/intr_machdep.c	2009-06-15 23:27:51.737242000 -0700
+++ ./sys/mips/mips/intr_machdep.c	2009-06-16 17:31:21.829412000 -0700
@@ -53,16 +53,97 @@
 static int last_printed = 0;
 #endif
 
+static struct intsrc *hardintr_srcs[NHARD_IRQS];
+static struct intsrc *softintr_srcs[NSOFT_IRQS];
+
+static int
+cpu_register_intsrc(struct intsrc *intsrcs[], int limit, struct intsrc *isrc)
+{
+	int intrnum;
+	
+	intrnum = isrc->intrnum;
+	if (intrnum < 0 || intrnum >= limit)
+		return (EINVAL);
+
+	/*
+	 * XXX locking?
+	 */
+	if (intsrcs[intrnum] != NULL)
+		return (EEXIST);
+	else
+		intsrcs[intrnum] = isrc;
+	return (0);
+}
+
+int
+cpu_register_hard_intsrc(struct intsrc *isrc)
+{
+
+	return (cpu_register_intsrc(hardintr_srcs, NHARD_IRQS, isrc));
+}
+
+int
+cpu_register_soft_intsrc(struct intsrc *isrc)
+{
+
+	return (cpu_register_intsrc(softintr_srcs, NSOFT_IRQS, isrc));
+}
+
 void
-mips_mask_irq(void)
+mips_mask_irq(void *arg)
 {
+	struct intsrc *isrc = arg;
 
+	if (isrc != NULL)
+		(*isrc->mask_func)(isrc);
 }
 
 void
-mips_unmask_irq(void)
+mips_unmask_irq(void *arg)
+{
+	struct intsrc *isrc = arg;
+
+	if (isrc != NULL)
+		(*isrc->unmask_func)(isrc);
+}
+
+#define	SR_HARD_IRQ_MASK(irq) ((1 << ((irq) + 2)) << 8)
+#define	SR_SOFT_IRQ_MASK(irq) ((1 << ((irq) + 0)) << 8)
+
+static void
+cpu_disable_hard_irq(int irq)
+{
+	KASSERT(irq >= 0 && irq < NHARD_IRQS,
+		("cpu_disable_hard_irq: invalid irq %d", irq));
+
+	mips_wr_status(mips_rd_status() & ~SR_HARD_IRQ_MASK(irq));
+}
+
+static void
+cpu_enable_hard_irq(int irq)
 {
+	KASSERT(irq >= 0 && irq < NHARD_IRQS,
+		("cpu_enable_hard_irq: invalid irq %d", irq));
 
+	mips_wr_status(mips_rd_status() | SR_HARD_IRQ_MASK(irq));
+}
+
+static void
+cpu_disable_soft_irq(int irq)
+{
+	KASSERT(irq >= 0 && irq < NSOFT_IRQS,
+		("cpu_disable_soft_irq: invalid irq %d", irq));
+
+	mips_wr_status(mips_rd_status() & ~SR_SOFT_IRQ_MASK(irq));
+}
+
+static void
+cpu_enable_soft_irq(int irq)
+{
+	KASSERT(irq >= 0 && irq < NSOFT_IRQS,
+		("cpu_enable_soft_irq: invalid irq %d", irq));
+
+	mips_wr_status(mips_rd_status() | SR_SOFT_IRQ_MASK(irq));
 }
 
 void
@@ -80,9 +161,20 @@
 	if (irq < 0 || irq >= NHARD_IRQS)
 		panic("%s called for unknown hard intr %d", __func__, irq);
 
+	/*
+	 * XXX Disable the hard irq
+	 *
+	 * It appears that there is a race between intr_event_add_handler()
+	 * and intr_event_handle() that can be triggered if we receive an
+	 * interrupt while we are adding the handler.
+	 *
+	 * Work around that by disabling the hard irq temporarily.
+	 */
+	cpu_disable_hard_irq(irq);
+
 	event = hardintr_events[irq];
 	if (event == NULL) {
-		error = intr_event_create(&event, (void *)irq, 0, irq,
+		error = intr_event_create(&event, hardintr_srcs[irq], 0, irq,
 		    (mask_fn)mips_mask_irq, (mask_fn)mips_unmask_irq,
 		    NULL, NULL, "hard intr%d:", irq);
 		if (error)
@@ -101,7 +193,7 @@
 	intr_event_add_handler(event, name, filt, handler, arg,
 	    intr_priority(flags), flags, cookiep);
 
-	mips_wr_status(mips_rd_status() | (((1 << irq) << 8) << 2));
+	cpu_enable_hard_irq(irq);
 }
 
 void
@@ -117,9 +209,11 @@
 	if (irq < 0 || irq > NSOFT_IRQS)
 		panic("%s called for unknown hard intr %d", __func__, irq);
 
+	cpu_disable_soft_irq(irq);
+
 	event = softintr_events[irq];
 	if (event == NULL) {
-		error = intr_event_create(&event, (void *)irq, 0, irq,
+		error = intr_event_create(&event, softintr_srcs[irq], 0, irq,
 		    (mask_fn)mips_mask_irq, (mask_fn)mips_unmask_irq,
 		    NULL, NULL, "intr%d:", irq);
 		if (error)
@@ -130,7 +224,7 @@
 	intr_event_add_handler(event, name, filt, handler, arg,
 	    intr_priority(flags), flags, cookiep);
 
-	mips_wr_status(mips_rd_status() | (((1<< irq) << 8)));
+	cpu_enable_soft_irq(irq);
 }
 
 void
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/mips/mips/locore.S ./sys/mips/mips/locore.S
--- /u/neelnatu/p4/freebsd_current/src/sys/mips/mips/locore.S	2009-06-15 23:27:51.739241000 -0700
+++ ./sys/mips/mips/locore.S	2009-06-16 17:31:21.834416000 -0700
@@ -138,7 +138,11 @@
 	mtc0	t2, COP_0_STATUS_REG
 	COP0_SYNC
 	/* Make sure KSEG0 is cached */
+#ifdef CPU_SB1
+	li	t0, CFG_K0_COHERENT
+#else
 	li	t0, CFG_K0_CACHED
+#endif
 	mtc0	t0, MIPS_COP_0_CONFIG
 	COP0_SYNC
 
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/mips/mips/machdep.c ./sys/mips/mips/machdep.c
--- /u/neelnatu/p4/freebsd_current/src/sys/mips/mips/machdep.c	2009-06-15 23:27:51.748240000 -0700
+++ ./sys/mips/mips/machdep.c	2009-06-16 17:31:21.848415000 -0700
@@ -104,6 +104,7 @@
 
 int cold = 1;
 long realmem = 0;
+long Maxmem = 0;
 int cpu_clock = MIPS_DEFAULT_HZ;
 SYSCTL_INT(_hw, OID_AUTO, clockrate, CTLFLAG_RD, 
     &cpu_clock, 0, "CPU instruction clock rate");
@@ -255,10 +256,7 @@
 	proc_linkup(&proc0, &thread0);
 	thread0.td_kstack = kstack0;
 	thread0.td_kstack_pages = KSTACK_PAGES - 1;
-	if (thread0.td_kstack & (1 << PAGE_SHIFT))
-		thread0.td_md.md_realstack = thread0.td_kstack + PAGE_SIZE;
-	else
-		thread0.td_md.md_realstack = thread0.td_kstack;
+	thread0.td_md.md_realstack = roundup2(thread0.td_kstack, PAGE_SIZE * 2);
 	/* Initialize pcpu info of cpu-zero */
 #ifdef SMP
 	pcpu_init(&__pcpu[0], 0, sizeof(struct pcpu));
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/mips/mips/mem.c ./sys/mips/mips/mem.c
--- /u/neelnatu/p4/freebsd_current/src/sys/mips/mips/mem.c	2009-06-15 23:27:51.752241000 -0700
+++ ./sys/mips/mips/mem.c	2009-06-16 17:31:21.853419000 -0700
@@ -101,8 +101,15 @@
 			vm_paddr_t pa;
 			register int o;
 
+#ifdef CPU_SB1
+			if (!is_physical_memory(v) ||
+			    !is_physical_memory(roundup2(v, PAGE_SIZE) - 1)) {
+				return (EFAULT);
+			}
+#else
 			if (v + c > (SDRAM_ADDR_START + ctob(physmem)))
 				return (EFAULT);
+#endif
 
 			if (is_cacheable_mem(v) && is_cacheable_mem(v + c)) {
 				struct fpage *fp;
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/mips/mips/nexus.c ./sys/mips/mips/nexus.c
--- /u/neelnatu/p4/freebsd_current/src/sys/mips/mips/nexus.c	2009-06-15 23:27:51.762242000 -0700
+++ ./sys/mips/mips/nexus.c	2009-06-16 17:31:21.866418000 -0700
@@ -76,6 +76,7 @@
 
 static struct rman irq_rman;
 static struct rman mem_rman;
+static struct rman port_rman;
 
 #ifdef notyet
 /*
@@ -173,6 +174,21 @@
 		panic("%s: mem_rman", __func__);
 	}
 
+	/*
+	 * MIPS has no concept of the x86 I/O address space but some cpus
+	 * provide a memory mapped window to access the PCI I/O BARs.
+	 */
+	port_rman.rm_start = 0;
+#ifdef PCI_IOSPACE_SIZE
+	port_rman.rm_end = PCI_IOSPACE_SIZE - 1;
+#endif
+	port_rman.rm_type = RMAN_ARRAY;
+	port_rman.rm_descr = "I/O ports";
+	if (rman_init(&port_rman) != 0 ||
+	    rman_manage_region(&port_rman, 0, port_rman.rm_end) != 0)
+		panic("%s: port_rman", __func__);
+
+
 	return (0);
 }
 
@@ -180,16 +196,21 @@
 nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags,
     driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep)
 {
-	int irq;
+	int irq, error;
 
-	register_t sr = intr_disable();
 	irq = rman_get_start(res);
 	if (irq >= NUM_MIPS_IRQS)
 		return (0);
 
+	if ((rman_get_flags(res) & RF_SHAREABLE) == 0)
+		flags |= INTR_EXCL;
+
+	error = rman_activate_resource(res);
+	if (error)
+		return (error);
+
 	cpu_establish_hardintr(device_get_nameunit(child), filt, intr, arg,
 	    irq, flags, cookiep);
-	intr_restore(sr);
 	return (0);
 }
 
@@ -238,6 +259,7 @@
 
 	retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
 	retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
+	retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#lx");
 
 	return (retval);
 }
@@ -338,6 +360,9 @@
 	case SYS_RES_MEMORY:
 		rm = &mem_rman;
 		break;
+	case SYS_RES_IOPORT:
+		rm = &port_rman;
+		break;
 	default:
 		printf("%s: unknown resource type %d\n", __func__, type);
 		return (0);
@@ -380,6 +405,11 @@
                 u_int32_t poffs;
                 
                 paddr = rman_get_start(r);
+#ifdef PCI_IOSPACE_ADDR
+		if (type == SYS_RES_IOPORT) {
+			paddr += PCI_IOSPACE_ADDR;
+		}
+#endif
                 psize = rman_get_size(r);
                 poffs = paddr - trunc_page(paddr);
                 vaddr = (caddr_t) pmap_mapdev(paddr-poffs, psize+poffs) + poffs;
@@ -473,6 +503,12 @@
 nexus_deactivate_resource(device_t bus, device_t child, int type, int rid,
 			  struct resource *r)
 {
+	vm_offset_t va;
+	
+	if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
+		va = (vm_offset_t)rman_get_virtual(r);
+		pmap_unmapdev(va, rman_get_size(r));
+	}
 
 	return (rman_deactivate_resource(r));
 }
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/mips/mips/pmap.c ./sys/mips/mips/pmap.c
--- /u/neelnatu/p4/freebsd_current/src/sys/mips/mips/pmap.c	2009-06-15 23:27:51.769243000 -0700
+++ ./sys/mips/mips/pmap.c	2009-06-16 17:31:21.873419000 -0700
@@ -313,6 +313,8 @@
 		}
 	}
 
+	Maxmem = atop(phys_avail[i - 1]);
+
 	if (bootverbose) {
 		printf("Physical memory chunk(s):\n");
 		for (i = 0; phys_avail[i + 1] != 0; i += 2) {
@@ -324,6 +326,7 @@
 			    (uintmax_t) phys_avail[i + 1] - 1,
 			    (uintmax_t) size, (uintmax_t) size / PAGE_SIZE);
 		}
+		printf("Maxmem is 0x%0lx\n", ptoa(Maxmem));
 	}
 	/*
 	 * Steal the message buffer from the beginning of memory.
@@ -2226,7 +2229,7 @@
 #endif
 	if (phys < MIPS_KSEG0_LARGEST_PHYS) {
 
-		va = MIPS_PHYS_TO_UNCACHED(phys);
+		va = MIPS_PHYS_TO_CACHED(phys);
 
 		bzero((caddr_t)va, PAGE_SIZE);
 		mips_dcache_wbinv_range(va, PAGE_SIZE);
@@ -2282,7 +2285,7 @@
 	} else
 #endif
 	if (phys < MIPS_KSEG0_LARGEST_PHYS) {
-		va = MIPS_PHYS_TO_UNCACHED(phys);
+		va = MIPS_PHYS_TO_CACHED(phys);
 		bzero((char *)(caddr_t)va + off, size);
 		mips_dcache_wbinv_range(va + off, size);
 	} else {
@@ -2321,7 +2324,7 @@
 	} else
 #endif
 	if (phys < MIPS_KSEG0_LARGEST_PHYS) {
-		va = MIPS_PHYS_TO_UNCACHED(phys);
+		va = MIPS_PHYS_TO_CACHED(phys);
 		bzero((caddr_t)va, PAGE_SIZE);
 		mips_dcache_wbinv_range(va, PAGE_SIZE);
 	} else {
@@ -2803,11 +2806,12 @@
 		return (void *)MIPS_PHYS_TO_KSEG1(pa);
 	else {
 		offset = pa & PAGE_MASK;
-		size = roundup(size, PAGE_SIZE);
+		size = roundup(size + offset, PAGE_SIZE);
         
 		va = kmem_alloc_nofault(kernel_map, size);
 		if (!va)
 			panic("pmap_mapdev: Couldn't alloc kernel virtual memory");
+		pa = trunc_page(pa);
 		for (tmpva = va; size > 0;) {
 			pmap_kenter(tmpva, pa);
 			size -= PAGE_SIZE;
@@ -2822,6 +2826,18 @@
 void
 pmap_unmapdev(vm_offset_t va, vm_size_t size)
 {
+	vm_offset_t base, offset, tmpva;
+
+	/* If the address is within KSEG1 then there is nothing to do */
+	if (va >= MIPS_KSEG1_START && va <= MIPS_KSEG1_END)
+		return;
+
+	base = trunc_page(va);
+	offset = va & PAGE_MASK;
+	size = roundup(size + offset, PAGE_SIZE);
+	for (tmpva = base; tmpva < base + size; tmpva += PAGE_SIZE)
+		pmap_kremove(tmpva);
+	kmem_free(kernel_map, base, size);
 }
 
 /*
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/mips/mips/swtch.S ./sys/mips/mips/swtch.S
--- /u/neelnatu/p4/freebsd_current/src/sys/mips/mips/swtch.S	2009-06-15 23:27:51.778242000 -0700
+++ ./sys/mips/mips/swtch.S	2009-06-16 17:31:21.878416000 -0700
@@ -81,14 +81,14 @@
 #define	_MFC0	dmfc0
 #define	_MTC0	dmtc0
 #define WIRED_SHIFT 34
-#define PAGE_SHIFT 34
+#define PAGE_SHIFT 12
 #else
 #define _SLL	sll
 #define	_SRL	srl
 #define	_MFC0	mfc0
 #define	_MTC0	mtc0
 #define WIRED_SHIFT 2
-#define PAGE_SHIFT 2
+#define PAGE_SHIFT 12
 #endif
 	.set	noreorder			# Noreorder is default style!
 #if defined(ISA_MIPS32)
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/mips/mips/tick.c ./sys/mips/mips/tick.c
--- /u/neelnatu/p4/freebsd_current/src/sys/mips/mips/tick.c	2009-06-15 23:27:51.779247000 -0700
+++ ./sys/mips/mips/tick.c	2009-06-16 17:31:21.884415000 -0700
@@ -229,7 +229,7 @@
 
 		/* Check to see if the timer has wrapped around. */
 		if (cur < last)
-			delta += (cur + (cycles_per_hz - last));
+			delta += (cur + (0xffffffff - last) + 1);
 		else
 			delta += (cur - last);
 
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/mips/mips/tlb.S ./sys/mips/mips/tlb.S
--- /u/neelnatu/p4/freebsd_current/src/sys/mips/mips/tlb.S	2009-06-15 23:27:51.781242000 -0700
+++ ./sys/mips/mips/tlb.S	2009-06-16 17:31:21.889422000 -0700
@@ -81,14 +81,14 @@
 #define	_MFC0	dmfc0
 #define	_MTC0	dmtc0
 #define WIRED_SHIFT 34
-#define PAGE_SHIFT 34
+#define PAGE_SHIFT 12
 #else
 #define _SLL	sll
 #define	_SRL	srl
 #define	_MFC0	mfc0
 #define	_MTC0	mtc0
 #define WIRED_SHIFT 2
-#define PAGE_SHIFT 2
+#define PAGE_SHIFT 12
 #endif
 	.set	noreorder			# Noreorder is default style!
 #if defined(ISA_MIPS32)
@@ -473,7 +473,17 @@
 	_MFC0	t4, COP_0_TLB_HI		# Get current PID
 	move	t2, a0
 	mfc0	t1, COP_0_TLB_WIRED
+
+	#
+	# Load invalid entry, each TLB entry should have it's own bogus 
+	# address calculated by following expression:
+	# MIPS_KSEG0_START + 0x0fff0000 + 2 * i * PAGE_SIZE;
+	# One bogus value for every TLB entry might cause MCHECK exception
+	#
+	sll	t3, t1, PAGE_SHIFT + 1
 	li	v0, MIPS_KSEG0_START + 0x0fff0000	# invalid address
+	addu	v0, t3
+
 	mfc0	t3, COP_0_TLB_PG_MASK		# save current pgMask
 
 	# do {} while (t1 < t2)
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/mips/mips/trap.c ./sys/mips/mips/trap.c
--- /u/neelnatu/p4/freebsd_current/src/sys/mips/mips/trap.c	2009-06-15 23:27:51.783244000 -0700
+++ ./sys/mips/mips/trap.c	2009-06-16 17:31:21.895420000 -0700
@@ -365,7 +365,7 @@
 		printf("cpuid = %d\n", PCPU_GET(cpuid));
 #endif
 		MachTLBGetPID(pid);
-		printf("badaddr = %p, pc = %p, ra = %p, sp = %p, sr = 0x%x, pid = %d, ASID = 0x%x\n",
+		printf("badaddr = 0x%0x, pc = 0x%0x, ra = 0x%0x, sp = 0x%0x, sr = 0x%x, pid = %d, ASID = 0x%x\n",
 		    trapframe->badvaddr, trapframe->pc, trapframe->ra,
 		    trapframe->sp, trapframe->sr,
 		    (curproc ? curproc->p_pid : -1), pid);
@@ -389,7 +389,7 @@
 		    ((type & ~T_USER) != T_SYSCALL)) {
 			if (++count == 3) {
 				trap_frame_dump(trapframe);
-				panic("too many faults at %p\n", last_badvaddr);
+				panic("too many faults at %x\n", last_badvaddr);
 			}
 		} else {
 			last_badvaddr = this_badvaddr;
@@ -570,7 +570,7 @@
 			--p->p_lock;
 			PROC_UNLOCK(p);
 #ifdef VMFAULT_TRACE
-			printf("vm_fault(%x (pmap %x), %x (%x), %x, %d) -> %x at pc %x\n",
+			printf("vm_fault(%p (pmap %p), %x (%x), %x, %d) -> %x at pc %x\n",
 			    map, &vm->vm_pmap, va, trapframe->badvaddr, ftype, flag,
 			    rv, trapframe->pc);
 #endif
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/mips/mips/vm_machdep.c ./sys/mips/mips/vm_machdep.c
--- /u/neelnatu/p4/freebsd_current/src/sys/mips/mips/vm_machdep.c	2009-06-15 23:27:51.787242000 -0700
+++ ./sys/mips/mips/vm_machdep.c	2009-06-16 17:31:21.901417000 -0700
@@ -395,6 +395,24 @@
  * Currently used by the kernel coredump code in order to avoid
  * dumping non-memory physical address space.
  */
+#ifdef CPU_SB1
+int
+is_physical_memory(vm_offset_t addr)
+{
+
+	if ((addr >= 0x00000000UL && addr < 0x10000000UL) ||
+	    (addr >= 0x80000000UL && addr < 0xa0000000UL) ||
+	    (addr >= 0xc0000000UL && addr < 0xd0000000UL)) {
+		return (1);
+	}
+#ifdef ISA_MIPS64
+	if (addr >= 0x0100000000ULL && addr < 0x8000000000ULL) {
+		return (1);
+	}
+#endif
+	return (0);
+}
+#else
 int
 is_physical_memory(vm_offset_t addr)
 {
@@ -403,7 +421,26 @@
 	else
 		return 0;
 }
+#endif	/* CPU_SB1 */
 
+#ifdef CPU_SB1
+int
+is_cacheable_mem(vm_offset_t pa)
+{
+
+	return (is_physical_memory(pa));
+}
+
+int
+is_coherent_mem(vm_offset_t pa)
+{
+	
+	/*
+	 * All physical memory is marked cacheable-coherent on the sibyte.
+	 */
+	return (is_physical_memory(pa));
+}
+#else
 int
 is_cacheable_mem(vm_offset_t pa)
 {
@@ -418,6 +455,14 @@
 		return 0;
 }
 
+int
+is_coherent_mem(vm_offset_t pa)
+{
+
+	return (0);
+}
+#endif	/* CPU_SB1 */
+
 /*
  * Allocate a pool of sf_bufs (sendfile(2) or "super-fast" if you prefer. :-))
  */
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/mips/sibyte/ata_zbbus.c ./sys/mips/sibyte/ata_zbbus.c
--- /u/neelnatu/p4/freebsd_current/src/sys/mips/sibyte/ata_zbbus.c	1969-12-31 16:00:00.000000000 -0800
+++ ./sys/mips/sibyte/ata_zbbus.c	2009-05-21 23:42:26.999969000 -0700
@@ -0,0 +1,170 @@
+/*-
+ * Copyright (c) 2009 Neelkanth Natu
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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/kernel.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/sema.h>
+#include <sys/taskqueue.h>
+
+#include <machine/bus.h>
+
+#include <vm/uma.h>
+
+#include <sys/ata.h>
+#include <dev/ata/ata-all.h>
+
+#include <machine/resource.h>
+
+__FBSDID("$FreeBSD$");
+
+static int
+ata_zbbus_probe(device_t dev)
+{
+
+	return (ata_probe(dev));
+}
+
+static int
+ata_zbbus_attach(device_t dev)
+{
+	int i, rid, regshift, regoffset;
+	struct ata_channel *ch;
+	struct resource *io;
+	
+	ch = device_get_softc(dev);
+
+	if (ch->attached)
+		return (0);
+	ch->attached = 1;
+
+	rid = 0;
+	io = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, ~0, 1, RF_ACTIVE);
+	if (io == NULL)
+		return (ENXIO);
+
+	/*
+	 * SWARM needs an address shift of 5 when accessing ATA registers.
+	 *
+	 * For e.g. an access to register 4 actually needs an address
+	 * of (4 << 5) to be output on the generic bus.
+	 */
+	regshift = 5;
+	resource_int_value(device_get_name(dev), device_get_unit(dev),
+			   "regshift", &regshift);
+	if (regshift && bootverbose)
+		device_printf(dev, "using a register shift of %d\n", regshift);
+
+	regoffset = 0x1F0;
+	resource_int_value(device_get_name(dev), device_get_unit(dev),
+			   "regoffset", &regoffset);
+	if (regoffset && bootverbose) {
+		device_printf(dev, "using a register offset of 0x%0x\n",
+			      regoffset);
+	}
+
+	/* setup the ata register addresses */
+	for (i = ATA_DATA; i <= ATA_COMMAND; ++i) {
+		ch->r_io[i].res = io;
+		ch->r_io[i].offset = (regoffset + i) << regshift;
+	}
+
+	ch->r_io[ATA_CONTROL].res = io;
+	ch->r_io[ATA_CONTROL].offset = (regoffset + ATA_CTLOFFSET) << regshift;
+	ch->r_io[ATA_IDX_ADDR].res = io;	/* XXX what is this used for */
+	ata_default_registers(dev);
+
+	/* initialize softc for this channel */
+	ch->unit = 0;
+	ch->flags |= ATA_USE_16BIT;
+	ata_generic_hw(dev);
+
+	return (ata_attach(dev));
+}
+
+static int
+ata_zbbus_detach(device_t dev)
+{
+	int error;
+	struct ata_channel *ch = device_get_softc(dev);
+
+	if (!ch->attached)
+		return (0);
+	ch->attached = 0;
+
+	error = ata_detach(dev);
+
+	bus_release_resource(dev, SYS_RES_MEMORY, 0,
+			     ch->r_io[ATA_IDX_ADDR].res);
+
+	return (error);
+}
+
+static int
+ata_zbbus_suspend(device_t dev)
+{
+	struct ata_channel *ch = device_get_softc(dev);
+
+	if (!ch->attached)
+		return (0);
+
+	return (ata_suspend(dev));
+}
+
+static int
+ata_zbbus_resume(device_t dev)
+{
+	struct ata_channel *ch = device_get_softc(dev);
+
+	if (!ch->attached)
+		return (0);
+
+	return (ata_resume(dev));
+}
+
+static device_method_t ata_zbbus_methods[] = {
+	/* device interface */
+	DEVMETHOD(device_probe,		ata_zbbus_probe),
+	DEVMETHOD(device_attach,	ata_zbbus_attach),
+	DEVMETHOD(device_detach,	ata_zbbus_detach),
+	DEVMETHOD(device_suspend,	ata_zbbus_suspend),
+	DEVMETHOD(device_resume,	ata_zbbus_resume),
+
+	{ 0, 0 }
+};
+
+static driver_t ata_zbbus_driver = {
+	"ata",
+	ata_zbbus_methods,
+	sizeof(struct ata_channel)
+};
+
+DRIVER_MODULE(ata, zbbus, ata_zbbus_driver, ata_devclass, 0, 0);
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/mips/sibyte/files.sibyte ./sys/mips/sibyte/files.sibyte
--- /u/neelnatu/p4/freebsd_current/src/sys/mips/sibyte/files.sibyte	1969-12-31 16:00:00.000000000 -0800
+++ ./sys/mips/sibyte/files.sibyte	2009-05-21 23:34:27.313938000 -0700
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+mips/sibyte/sb_machdep.c			standard
+mips/sibyte/sb_zbbus.c				standard
+mips/sibyte/sb_zbpci.c				standard
+mips/sibyte/sb_scd.c				standard
+mips/sibyte/ata_zbbus.c				standard
+
+mips/sibyte/sb_asm.S				standard
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/mips/sibyte/sb_asm.S ./sys/mips/sibyte/sb_asm.S
--- /u/neelnatu/p4/freebsd_current/src/sys/mips/sibyte/sb_asm.S	1969-12-31 16:00:00.000000000 -0800
+++ ./sys/mips/sibyte/sb_asm.S	2009-05-18 20:25:17.798702000 -0700
@@ -0,0 +1,155 @@
+/*-
+ * Copyright (c) 2009 Neelkanth Natu
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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/asm.h>
+
+/*
+ * We compile a 32-bit kernel to run on the SB-1 processor which is a 64-bit
+ * processor. It has some registers that must be accessed using 64-bit load
+ * and store instructions.
+ *
+ * So we have to resort to assembly because the compiler does not emit the
+ * 'ld' and 'sd' instructions since it thinks that it is compiling for a
+ * 32-bit mips processor.
+ */
+
+.set	mips64
+.set	noat
+.set	noreorder
+
+/*
+ * return (MIPS_PHYS_TO_KSEG1(0x10020008))
+ * Parameters: none
+ */
+LEAF(sb_read_syscfg)
+	lui     v0, 0xb002
+	ori     v0, v0, 0x8
+	ld      v1, 0(v0)	/* syscfg = MIPS_PHYS_TO_KSEG1(0x10020008) */
+	move	v0, v1
+	dsll32	v0, v0, 0
+	dsrl32	v0, v0, 0	/* v0 = lower_uint32(mask) */
+	jr	ra
+	dsrl32	v1, v1, 0	/* v1 = upper_uint32(mask) */
+END(sb_read_syscfg)
+
+/*
+ * MIPS_PHYS_TO_KSEG1(0x10020008) = (uint64_t)val
+ * Parameters:
+ * - lower_uint32(val): a0
+ * - upper_uint32(val): a1
+ */
+LEAF(sb_write_syscfg)
+	lui     v0, 0xb002
+	ori     v0, v0, 0x8
+	dsll32	a1, a1, 0	/* clear lower 32 bits of a1 */
+	dsll32	a0, a0, 0
+	dsrl32	a0, a0, 0	/* clear upper 32 bits of a0 */
+	or	a1, a1, a0
+	sd	a1, 0(v0)	/* MIPS_PHYS_TO_KSEG1(0x10020008) = val */
+	jr	ra
+	nop
+	nop
+END(sb_write_syscfg)
+
+/*
+ * MIPS_PHYS_TO_KSEG1(0x10020028) |= (1 << intsrc)
+ *
+ * Parameters:
+ * - intsrc (a0)
+ */
+LEAF(sb_disable_intsrc)
+	lui     v0, 0xb002
+	ori     v0, v0, 0x28
+	ld      v1, 0(v0)	/* mask = MIPS_PHYS_TO_KSEG1(0x10020028) */
+	li      a1, 1
+	dsllv   a1, a1, a0
+	or      a1, a1, v1	/* mask |= (1 << intsrc) */
+	jr	ra
+	sd      a1, 0(v0)	/* MIPS_PHYS_TO_KSEG1(0x10020028) = mask */
+END(sb_disable_intsrc)
+
+/*
+ * MIPS_PHYS_TO_KSEG1(0x10020028) &= ~(1 << intsrc)
+ *
+ * Parameters:
+ * - intsrc (a0)
+ */
+LEAF(sb_enable_intsrc)
+	lui     v0, 0xb002
+	ori     v0, v0, 0x28
+	ld      v1, 0(v0)	/* mask = MIPS_PHYS_TO_KSEG1(0x10020028) */
+	li      a2, 1
+	dsllv   a2, a2, a0
+	nor     a2, zero, a2
+	and     a2, a2, v1	/* mask &= ~(1 << intsrc) */
+	sd      a2, 0(v0)	/* MIPS_PHYS_TO_KSEG1(0x10020028) = mask */
+	jr      ra
+	nop
+END(sb_enable_intsrc)
+
+/*
+ * return ((uint64_t)MIPS_PHYS_TO_KSEG1(0x10020028))
+ * Parameters: none
+ */
+LEAF(sb_read_intsrc_mask)
+	lui     v0, 0xb002
+	ori     v0, v0, 0x28
+	ld      v1, 0(v0)	/* mask = MIPS_PHYS_TO_KSEG1(0x10020028) */
+	move	v0, v1
+	dsll32	v0, v0, 0
+	dsrl32	v0, v0, 0	/* v0 = lower_uint32(mask) */
+	jr	ra
+	dsrl32	v1, v1, 0	/* v1 = upper_uint32(mask) */
+END(sb_read_intsrc_mask)
+
+/*
+ * return ((uint64_t *)MIPS_PHYS_TO_KSEG1(0x10020200) + intsrc)
+ * Parameters:
+ * - intsrc (a0)
+ */
+LEAF(sb_read_intmap)
+	sll	a0, a0, 3	/* compute the offset of the intmap register */
+	lui     v0, 0xb002
+	addu    a0, a0, v0
+	ld      v0, 512(a0)	/* v0 = MIPS_PHYS_TO_KSEG1(0x10020200) + off */
+	jr      ra
+	nop
+END(sb_read_intmap)
+
+/*
+ * (uint64_t *)MIPS_PHYS_TO_KSEG1(0x10020200) + intsrc = irq
+ * Parameters:
+ * - intsrc (a0)
+ * - irq    (a1)
+ */
+LEAF(sb_write_intmap)
+	sll     a0, a0, 0x3 /* compute the offset of the intmap register */
+	lui     v0, 0xb002
+	addu    a0, a0, v0
+	sd      a1, 512(a0) /* MIPS_PHYS_TO_KSEG1(0x10020200) + off = irq */
+	jr      ra
+	nop
+END(sb_write_intmap)
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/mips/sibyte/sb_machdep.c ./sys/mips/sibyte/sb_machdep.c
--- /u/neelnatu/p4/freebsd_current/src/sys/mips/sibyte/sb_machdep.c	1969-12-31 16:00:00.000000000 -0800
+++ ./sys/mips/sibyte/sb_machdep.c	2009-06-10 13:53:30.333084000 -0700
@@ -0,0 +1,259 @@
+/*-
+ * Copyright (c) 2007 Bruce M. Simpson.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <machine/cpuregs.h>
+
+#include "opt_ddb.h"
+#include "opt_kdb.h"
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/imgact.h>
+#include <sys/bio.h>
+#include <sys/buf.h>
+#include <sys/bus.h>
+#include <sys/cpu.h>
+#include <sys/cons.h>
+#include <sys/exec.h>
+#include <sys/ucontext.h>
+#include <sys/proc.h>
+#include <sys/kdb.h>
+#include <sys/ptrace.h>
+#include <sys/reboot.h>
+#include <sys/signalvar.h>
+#include <sys/sysent.h>
+#include <sys/sysproto.h>
+#include <sys/user.h>
+
+#include <vm/vm.h>
+#include <vm/vm_object.h>
+#include <vm/vm_page.h>
+#include <vm/vm_pager.h>
+
+#include <machine/cache.h>
+#include <machine/clock.h>
+#include <machine/cpu.h>
+#include <machine/cpuinfo.h>
+#include <machine/cpufunc.h>
+#include <machine/cpuregs.h>
+#include <machine/hwfunc.h>
+#include <machine/intr_machdep.h>
+#include <machine/locore.h>
+#include <machine/md_var.h>
+#include <machine/pte.h>
+#include <machine/sigframe.h>
+#include <machine/trap.h>
+#include <machine/vmparam.h>
+
+#ifdef CFE
+#include <dev/cfe/cfe_api.h>
+#endif
+
+#include "sb_scd.h"
+
+#ifdef DDB
+#ifndef KDB
+#error KDB must be enabled in order for DDB to work!
+#endif
+#endif
+
+#ifdef CFE
+extern uint32_t cfe_handle;
+extern uint32_t cfe_vector;
+#endif
+
+#ifdef CFE_ENV
+extern void cfe_env_init(void);
+#endif
+
+extern int *edata;
+extern int *end;
+
+static void
+mips_init(void)
+{
+	int i, cfe_mem_idx, tmp;
+	uint64_t maxmem;
+
+#ifdef CFE_ENV
+	cfe_env_init();
+#endif
+
+	TUNABLE_INT_FETCH("boothowto", &boothowto);
+
+	if (boothowto & RB_VERBOSE)
+		bootverbose++;
+
+#ifdef MAXMEM
+	tmp = MAXMEM;
+#else
+	tmp = 0;
+#endif
+	TUNABLE_INT_FETCH("hw.physmem", &tmp);
+	maxmem = (uint64_t)tmp * 1024;
+
+#ifdef CFE
+	/*
+	 * Query DRAM memory map from CFE.
+	 */
+	physmem = 0;
+	cfe_mem_idx = 0;
+	for (i = 0; i < 10; i += 2) {
+		int result;
+		uint64_t addr, len, type;
+
+		result = cfe_enummem(cfe_mem_idx++, 0, &addr, &len, &type);
+		if (result < 0) {
+			phys_avail[i] = phys_avail[i + 1] = 0;
+			break;
+		}
+
+		KASSERT(type == CFE_MI_AVAILABLE,
+			("CFE DRAM region is not available?"));
+
+		if (bootverbose)
+			printf("cfe_enummem: 0x%016jx/%llu.\n", addr, len);
+
+		if (maxmem != 0) {
+			if (addr >= maxmem) {
+				printf("Ignoring %llu bytes of memory at 0x%jx "
+				       "that is above maxmem %dMB\n",
+				       len, addr,
+				       (int)(maxmem / (1024 * 1024)));
+				continue;
+			}
+
+			if (addr + len > maxmem) {
+				printf("Ignoring %llu bytes of memory "
+				       "that is above maxmem %dMB\n",
+				       (addr + len) - maxmem,
+				       (int)(maxmem / (1024 * 1024)));
+				len = maxmem - addr;
+			}
+		}
+
+		phys_avail[i] = addr;
+		if (i == 0 && addr == 0) {
+			/*
+			 * If this is the first physical memory segment probed
+			 * from CFE, omit the region at the start of physical
+			 * memory where the kernel has been loaded.
+			 */
+			phys_avail[i] += MIPS_KSEG0_TO_PHYS((vm_offset_t)&end);
+		}
+		phys_avail[i + 1] = addr + len;
+		physmem += len;
+	}
+
+	realmem = btoc(physmem);
+#endif
+
+	physmem = realmem;
+
+	init_param1();
+	init_param2(physmem);
+	mips_cpu_init();
+	pmap_bootstrap();
+	mips_proc0_init();
+	mutex_init();
+
+	kdb_init();
+#ifdef KDB
+	if (boothowto & RB_KDB)
+		kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger");
+#endif
+}
+
+void
+platform_halt(void)
+{
+
+}
+
+
+void
+platform_identify(void)
+{
+
+}
+
+void
+platform_reset(void)
+{
+	
+	/*
+	 * XXX SMP
+	 * XXX flush data caches
+	 */
+	sb_system_reset();
+}
+
+void
+platform_trap_enter(void)
+{
+
+}
+
+void
+platform_trap_exit(void)
+{
+
+}
+
+void
+platform_start(__register_t a0 __unused, __register_t a1 __unused, 
+    __register_t a2 __unused, __register_t a3 __unused)
+{
+	vm_offset_t kernend;
+
+	/* clear the BSS and SBSS segments */
+	memset(&edata, 0, (vm_offset_t)&end - (vm_offset_t)&edata);
+	kernend = round_page((vm_offset_t)&end);
+
+#ifdef CFE
+	/*
+	 * Initialize CFE firmware trampolines before
+	 * we initialize the low-level console.
+	 */
+	if (cfe_handle != 0)
+		cfe_init(cfe_handle, cfe_vector);
+#endif
+	cninit();
+
+#ifdef CFE
+	if (cfe_handle == 0)
+		panic("CFE was not detected by locore.\n");
+#endif
+	mips_init();
+
+	mips_timer_init_params(sb_cpu_speed(), 0);
+}
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/mips/sibyte/sb_scd.c ./sys/mips/sibyte/sb_scd.c
--- /u/neelnatu/p4/freebsd_current/src/sys/mips/sibyte/sb_scd.c	1969-12-31 16:00:00.000000000 -0800
+++ ./sys/mips/sibyte/sb_scd.c	2009-05-15 16:51:56.362688000 -0700
@@ -0,0 +1,152 @@
+/*-
+ * Copyright (c) 2009 Neelkanth Natu
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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/kernel.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+
+#include <machine/resource.h>
+
+#include "sb_scd.h"
+
+__FBSDID("$FreeBSD$");
+
+/*
+ * System Control and Debug (SCD) unit on the Sibyte ZBbus.
+ */
+
+/*
+ * Extract the value starting at bit position 'b' for 'n' bits from 'x'.
+ */
+#define	GET_VAL_64(x, b, n)	(((x) >> (b)) & ((1ULL << (n)) - 1))
+
+#define SYSCFG_PLLDIV(x)	GET_VAL_64((x), 7, 5)
+
+uint64_t
+sb_cpu_speed(void)
+{
+	int plldiv;
+	const uint64_t MHZ = 1000000;
+	
+	plldiv = SYSCFG_PLLDIV(sb_read_syscfg());
+	if (plldiv == 0) {
+		printf("PLL_DIV is 0 - assuming 6 (300MHz).\n");
+		plldiv = 6;
+	}
+
+	return (plldiv * 50 * MHZ);
+}
+
+void
+sb_system_reset(void)
+{
+	uint64_t syscfg;
+
+	const uint64_t SYSTEM_RESET = 1ULL << 60;
+	const uint64_t EXT_RESET = 1ULL << 59;
+	const uint64_t SOFT_RESET = 1ULL << 58;
+
+	syscfg = sb_read_syscfg();
+	syscfg &= ~SOFT_RESET;
+	syscfg |= SYSTEM_RESET | EXT_RESET;
+	sb_write_syscfg(syscfg);
+}
+
+int
+sb_route_intsrc(int intsrc)
+{
+	int intrnum;
+
+	KASSERT(intsrc >= 0 && intsrc < NUM_INTSRC,
+		("Invalid interrupt source number (%d)", intsrc));
+
+	/*
+	 * Interrupt 5 is used by sources internal to the CPU (e.g. timer).
+	 * Use a deterministic mapping for the remaining sources to map to
+	 * interrupt numbers 0 through 4.
+	 */
+	intrnum = intsrc % 5;
+
+	/*
+	 * Program the interrupt mapper while we are here.
+	 */
+	sb_write_intmap(intsrc, intrnum);
+
+	return (intrnum);
+}
+
+#define	SCD_PHYSADDR	0x10000000
+#define	SCD_SIZE	0x00060000
+
+static int
+scd_probe(device_t dev)
+{
+
+	device_set_desc(dev, "Broadcom/Sibyte System Control and Debug");
+	return (0);
+}
+
+static int
+scd_attach(device_t dev)
+{
+	int rid;
+	struct resource *res;
+
+	if (bootverbose) {
+		device_printf(dev, "attached.\n");
+	}
+
+	rid = 0;
+	res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, SCD_PHYSADDR,
+				 SCD_PHYSADDR + SCD_SIZE - 1, SCD_SIZE, 0);
+	if (res == NULL) {
+		panic("Cannot allocate resource for system control and debug.");
+	}
+	
+	return (0);
+}
+
+static device_method_t scd_methods[] ={
+	/* Device interface */
+	DEVMETHOD(device_probe,		scd_probe),
+	DEVMETHOD(device_attach,	scd_attach),
+	DEVMETHOD(device_detach,	bus_generic_detach),
+	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
+	DEVMETHOD(device_suspend,	bus_generic_suspend),
+	DEVMETHOD(device_resume,	bus_generic_resume),
+
+	{ 0, 0 }
+};
+
+static driver_t scd_driver = {
+	"scd",
+	scd_methods
+};
+
+static devclass_t scd_devclass;
+
+DRIVER_MODULE(scd, zbbus, scd_driver, scd_devclass, 0, 0);
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/mips/sibyte/sb_scd.h ./sys/mips/sibyte/sb_scd.h
--- /u/neelnatu/p4/freebsd_current/src/sys/mips/sibyte/sb_scd.h	1969-12-31 16:00:00.000000000 -0800
+++ ./sys/mips/sibyte/sb_scd.h	2009-05-15 01:58:12.318422000 -0700
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2009 Neelkanth Natu
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 _SB_SCD_H_
+#define	_SB_SCD_H_
+
+#define	NUM_INTSRC		64	/* total number of interrupt sources */
+
+uint64_t	sb_cpu_speed(void);
+void		sb_system_reset(void);
+
+int		sb_route_intsrc(int src);
+void		sb_enable_intsrc(int src);
+void		sb_disable_intsrc(int src);
+uint64_t	sb_read_intsrc_mask(void);
+
+int		sb_read_intmap(int intsrc);
+void		sb_write_intmap(int intsrc, int intrnum);
+
+uint64_t	sb_read_syscfg(void);
+void		sb_write_syscfg(uint64_t val);
+
+#endif	/* _SB_SCD_H_ */
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/mips/sibyte/sb_zbbus.c ./sys/mips/sibyte/sb_zbbus.c
--- /u/neelnatu/p4/freebsd_current/src/sys/mips/sibyte/sb_zbbus.c	1969-12-31 16:00:00.000000000 -0800
+++ ./sys/mips/sibyte/sb_zbbus.c	2009-06-13 12:29:39.515055000 -0700
@@ -0,0 +1,501 @@
+/*-
+ * Copyright (c) 2009 Neelkanth Natu
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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/kernel.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+
+#include <machine/resource.h>
+#include <machine/intr_machdep.h>
+
+#include "sb_scd.h"
+
+__FBSDID("$FreeBSD$");
+
+static MALLOC_DEFINE(M_INTMAP, "sb1250 intmap", "Sibyte 1250 Interrupt Mapper");
+
+#define	NUM_HARD_IRQS	6
+
+struct sb_intmap {
+	int intsrc;		/* interrupt mapper register number (0 - 63) */
+	int active;		/* Does this source generate interrupts? */
+
+	/*
+	 * The device that the interrupt belongs to. Note that multiple
+	 * devices may share an interrupt. For e.g. PCI_INT_x lines.
+	 *
+	 * The device 'dev' in combination with the 'rid' uniquely
+	 * identify this interrupt source.
+	 */
+	device_t dev;
+	int rid;
+
+	SLIST_ENTRY(sb_intmap) next;
+};
+
+/*
+ * We register 'sb_intsrc.isrc' using cpu_register_hard_intsrc() for each
+ * hard interrupt source [0-5].
+ *
+ * The mask/unmask callbacks use the information in 'sb_intmap' to figure
+ * out the corresponding interrupt sources to mask/unmask.
+ */
+struct sb_intsrc {
+	struct intsrc isrc;
+	SLIST_HEAD(, sb_intmap) sb_intmap_head;
+};
+
+static struct sb_intsrc sb_intsrc[NUM_HARD_IRQS];
+
+static struct sb_intmap *
+sb_intmap_lookup(int intrnum, device_t dev, int rid)
+{
+	struct sb_intsrc *isrc;
+	struct sb_intmap *map;
+
+	isrc = &sb_intsrc[intrnum];
+	SLIST_FOREACH(map, &isrc->sb_intmap_head, next) {
+		if (dev == map->dev && rid == map->rid)
+			break;
+	}
+	return (map);
+}
+
+/*
+ * Keep track of which (dev,rid) tuple is using the interrupt source.
+ *
+ * We don't actually unmask the interrupt source until the device calls
+ * a bus_setup_intr() on the resource.
+ */
+static void
+sb_intmap_add(int intrnum, device_t dev, int rid, int intsrc)
+{
+	struct sb_intsrc *isrc;
+	struct sb_intmap *map;
+	register_t sr;
+	
+	KASSERT(intrnum >= 0 && intrnum < NUM_HARD_IRQS,
+		("intrnum is out of range: %d", intrnum));
+
+	isrc = &sb_intsrc[intrnum];
+	map = sb_intmap_lookup(intrnum, dev, rid);
+	if (map) {
+		KASSERT(intsrc == map->intsrc,
+			("%s%d allocating SYS_RES_IRQ resource with rid %d "
+			 "with a different intsrc (%d versus %d)",
+			device_get_name(dev), device_get_unit(dev), rid,
+			intsrc, map->intsrc));
+		return;
+	}
+
+	map = malloc(sizeof(*map), M_INTMAP, M_WAITOK | M_ZERO);
+	map->intsrc = intsrc;
+	map->dev = dev;
+	map->rid = rid;
+
+	sr = intr_disable();
+	SLIST_INSERT_HEAD(&isrc->sb_intmap_head, map, next);
+	intr_restore(sr);
+}
+
+static void
+sb_intmap_activate(int intrnum, device_t dev, int rid)
+{
+	struct sb_intmap *map;
+	register_t sr;
+	
+	KASSERT(intrnum >= 0 && intrnum < NUM_HARD_IRQS,
+		("intrnum is out of range: %d", intrnum));
+
+	map = sb_intmap_lookup(intrnum, dev, rid);
+	if (map) {
+		/*
+		 * See comments in sb_unmask_func() about disabling cpu intr
+		 */
+		sr = intr_disable();
+		map->active = 1;
+		sb_enable_intsrc(map->intsrc);
+		intr_restore(sr);
+	} else {
+		/*
+		 * In zbbus_setup_intr() we blindly call sb_intmap_activate()
+		 * for every interrupt activation that comes our way.
+		 *
+		 * We might end up here if we did not "hijack" the SYS_RES_IRQ
+		 * resource in zbbus_alloc_resource().
+		 */
+		printf("sb_intmap_activate: unable to activate interrupt %d "
+		       "for device %s%d rid %d.\n", intrnum,
+		       device_get_name(dev), device_get_unit(dev), rid);
+	}
+}
+
+static void
+sb_mask_func(struct intsrc *arg)
+{
+	struct sb_intmap *map;
+	struct sb_intsrc *isrc;
+	uint64_t isrc_bitmap;
+
+	isrc_bitmap = 0;
+	isrc = (struct sb_intsrc *)arg;
+	SLIST_FOREACH(map, &isrc->sb_intmap_head, next) {
+		if (map->active == 0)
+			continue;
+		/*
+		 * If we have already disabled this interrupt source then don't
+		 * do it again. This can happen when multiple devices share
+		 * an interrupt source (e.g. PCI_INT_x).
+		 */
+		if (isrc_bitmap & (1ULL << map->intsrc))
+			continue;
+		sb_disable_intsrc(map->intsrc);
+		isrc_bitmap |= 1ULL << map->intsrc;
+	}
+}
+
+static void
+sb_unmask_func(struct intsrc *arg)
+{
+	struct sb_intmap *map;
+	struct sb_intsrc *sb_isrc;
+	uint64_t isrc_bitmap;
+	register_t sr;
+	
+	isrc_bitmap = 0;
+	sb_isrc = (struct sb_intsrc *)arg;
+
+	/*
+	 * Make sure we disable the cpu interrupts when enabling the
+	 * interrupt sources.
+	 *
+	 * This is to prevent a condition where some interrupt sources have
+	 * been enabled (but not all) and one of those interrupt sources
+	 * triggers an interrupt.
+	 *
+	 * If any of the interrupt handlers executes in an ithread then
+	 * cpu_intr() will return with all interrupt sources feeding into
+	 * that cpu irq masked. But when the loop below picks up where it
+	 * left off it will enable the remaining interrupt sources!!!
+	 *
+	 * If the disable the cpu interrupts then this race does not happen.
+	 */
+	sr = intr_disable();
+
+	SLIST_FOREACH(map, &sb_isrc->sb_intmap_head, next) {
+		if (map->active == 0)
+			continue;
+		/*
+		 * If we have already enabled this interrupt source then don't
+		 * do it again. This can happen when multiple devices share
+		 * an interrupt source (e.g. PCI_INT_x).
+		 */
+		if (isrc_bitmap & (1ULL << map->intsrc))
+			continue;
+		sb_enable_intsrc(map->intsrc);
+		isrc_bitmap |= 1ULL << map->intsrc;
+	}
+
+	intr_restore(sr);
+}
+
+struct zbbus_devinfo {
+	struct resource_list resources;
+};
+
+static MALLOC_DEFINE(M_ZBBUSDEV, "zbbusdev", "zbbusdev");
+
+static int
+zbbus_probe(device_t dev)
+{
+
+	device_set_desc(dev, "Broadcom/Sibyte ZBbus");
+	return (0);
+}
+
+static int
+zbbus_attach(device_t dev)
+{
+	int i, error;
+	struct intsrc *isrc;
+
+	if (bootverbose) {
+		device_printf(dev, "attached.\n");
+	}
+
+	for (i = 0; i < NUM_HARD_IRQS; ++i) {
+		isrc = &sb_intsrc[i].isrc;
+		isrc->intrnum = i;
+		isrc->mask_func = sb_mask_func;
+		isrc->unmask_func = sb_unmask_func;
+		error = cpu_register_hard_intsrc(isrc);
+		if (error)
+			panic("Error %d registering intsrc %d", error, i);
+	}
+	
+	bus_generic_probe(dev);
+	bus_enumerate_hinted_children(dev);
+	bus_generic_attach(dev);
+
+	return (0);
+}
+
+static void
+zbbus_hinted_child(device_t bus, const char *dname, int dunit)
+{
+	device_t child;
+	long maddr, msize;
+	int err, irq;
+
+	if (resource_disabled(dname, dunit))
+		return;
+
+	child = BUS_ADD_CHILD(bus, 0, dname, dunit);
+	if (child == NULL) {
+		panic("zbbus: could not add child %s unit %d\n", dname, dunit);
+	}
+
+	if (bootverbose)
+		device_printf(bus, "Adding hinted child %s%d\n", dname, dunit);
+
+	/*
+	 * Assign any pre-defined resources to the child.
+	 */
+	if (resource_long_value(dname, dunit, "msize", &msize) == 0 &&
+	    resource_long_value(dname, dunit, "maddr", &maddr) == 0) {
+		if (bootverbose) {
+			device_printf(bus, "Assigning memory resource "
+					   "0x%0lx/%ld to child %s%d\n",
+					   maddr, msize, dname, dunit);
+		}
+		err = bus_set_resource(child, SYS_RES_MEMORY, 0, maddr, msize);
+		if (err) {
+			device_printf(bus, "Unable to set memory resource "
+					   "0x%0lx/%ld for child %s%d: %d\n",
+					   maddr, msize, dname, dunit, err);
+		}
+	}
+
+	if (resource_int_value(dname, dunit, "irq", &irq) == 0) {
+		if (bootverbose) {
+			device_printf(bus, "Assigning irq resource %d to "
+					   "child %s%d\n", irq, dname, dunit);
+		}
+		err = bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1);
+		if (err) {
+			device_printf(bus, "Unable to set irq resource %d"
+					   "for child %s%d: %d\n",
+					   irq, dname, dunit, err);
+		}
+	}
+}
+
+static struct resource *
+zbbus_alloc_resource(device_t bus, device_t child, int type, int *rid,
+		     u_long start, u_long end, u_long count, u_int flags)
+{
+	struct resource *res;
+	int intrnum, intsrc, isdefault;
+	struct resource_list *rl;
+	struct resource_list_entry *rle;
+	struct zbbus_devinfo *dinfo;
+
+	isdefault = (start == 0UL && end == ~0UL && count == 1);
+
+	/*
+	 * Our direct child is asking for a default resource allocation.
+	 */
+	if (device_get_parent(child) == bus) {
+		dinfo = device_get_ivars(child);
+		rl = &dinfo->resources;
+		rle = resource_list_find(rl, type, *rid);
+		if (rle) {
+			if (rle->res)
+				panic("zbbus_alloc_resource: resource is busy");
+			if (isdefault) {
+				start = rle->start;
+				count = ulmax(count, rle->count);
+				end = ulmax(rle->end, start + count - 1);
+			}
+		} else {
+			if (isdefault) {
+				/*
+				 * Our child is requesting a default
+				 * resource allocation but we don't have the
+				 * 'type/rid' tuple in the resource list.
+				 *
+				 * We have to fail the resource allocation.
+				 */
+				return (NULL);
+			} else {
+				/*
+				 * The child is requesting a non-default
+				 * resource. We just pass the request up
+				 * to our parent. If the resource allocation
+				 * succeeds we will create a resource list
+				 * entry corresponding to that resource.
+				 */
+			}
+		}
+	} else {
+		rl = NULL;
+		rle = NULL;
+	}
+
+	/*
+	 * nexus doesn't know about the interrupt mapper and only wants to
+	 * see the hard irq numbers [0-6]. We translate from the interrupt
+	 * source presented to the mapper to the interrupt number presented
+	 * to the cpu.
+	 */
+	if ((count == 1) && (type == SYS_RES_IRQ)) {
+		intsrc = start;
+		intrnum = sb_route_intsrc(intsrc);
+		start = end = intrnum;
+	} else {
+		intsrc = -1;		/* satisfy gcc */
+		intrnum = -1;
+	}
+
+	res = bus_generic_alloc_resource(bus, child, type, rid,
+ 					 start, end, count, flags);
+
+	/*
+	 * Keep track of the input into the interrupt mapper that maps
+	 * to the resource allocated by 'child' with resource id 'rid'.
+	 *
+	 * If we don't record the mapping here then we won't be able to
+	 * locate the interrupt source when bus_setup_intr(child,rid) is
+	 * called.
+	 */
+	if (res != NULL && intrnum != -1)
+		sb_intmap_add(intrnum, child, rman_get_rid(res), intsrc);
+
+	/*
+	 * If a non-default resource allocation by our child was successful
+	 * then keep track of the resource in the resource list associated
+	 * with the child.
+	 */
+	if (res != NULL && rle == NULL && device_get_parent(child) == bus) {
+		resource_list_add(rl, type, *rid, start, end, count);
+		rle = resource_list_find(rl, type, *rid);
+		if (rle == NULL)
+			panic("zbbus_alloc_resource: cannot find resource");
+	}
+
+	if (rle != NULL) {
+		KASSERT(device_get_parent(child) == bus,
+			("rle should be NULL for passthru device"));
+		rle->res = res;
+		if (rle->res) {
+			rle->start = rman_get_start(rle->res);
+			rle->end = rman_get_end(rle->res);
+			rle->count = count;
+		}
+	}
+
+	return (res);
+}
+
+static int
+zbbus_setup_intr(device_t dev, device_t child, struct resource *irq, int flags,
+		 driver_filter_t *filter, driver_intr_t *intr, void *arg, 
+		 void **cookiep)
+{
+	int error;
+
+	error = bus_generic_setup_intr(dev, child, irq, flags,
+				       filter, intr, arg, cookiep);
+	if (error == 0)
+		sb_intmap_activate(rman_get_start(irq), child,
+				   rman_get_rid(irq));
+
+	return (error);
+}
+
+static device_t
+zbbus_add_child(device_t bus, int order, const char *name, int unit)
+{
+	device_t child;
+	struct zbbus_devinfo *dinfo;
+
+	child = device_add_child_ordered(bus, order, name, unit);
+	if (child != NULL) {
+		dinfo = malloc(sizeof(struct zbbus_devinfo), M_ZBBUSDEV,
+			       M_WAITOK | M_ZERO);
+		resource_list_init(&dinfo->resources);
+		device_set_ivars(child, dinfo);
+	}
+
+	return (child);
+}
+
+static struct resource_list *
+zbbus_get_resource_list(device_t dev, device_t child)
+{
+	struct zbbus_devinfo *dinfo = device_get_ivars(child);
+
+	return (&dinfo->resources);
+}
+
+static device_method_t zbbus_methods[] ={
+	/* Device interface */
+	DEVMETHOD(device_probe,		zbbus_probe),
+	DEVMETHOD(device_attach,	zbbus_attach),
+	DEVMETHOD(device_detach,	bus_generic_detach),
+	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
+	DEVMETHOD(device_suspend,	bus_generic_suspend),
+	DEVMETHOD(device_resume,	bus_generic_resume),
+
+	/* Bus interface */
+	DEVMETHOD(bus_alloc_resource,	zbbus_alloc_resource),
+	DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+	DEVMETHOD(bus_release_resource,	bus_generic_release_resource),
+	DEVMETHOD(bus_get_resource_list,zbbus_get_resource_list),
+	DEVMETHOD(bus_set_resource,	bus_generic_rl_set_resource),
+	DEVMETHOD(bus_get_resource,	bus_generic_rl_get_resource),
+	DEVMETHOD(bus_delete_resource,	bus_generic_rl_delete_resource),
+	DEVMETHOD(bus_setup_intr,	zbbus_setup_intr),
+	DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
+	DEVMETHOD(bus_add_child,	zbbus_add_child),
+	DEVMETHOD(bus_hinted_child,	zbbus_hinted_child),
+	
+	{ 0, 0 }
+};
+
+static driver_t zbbus_driver = {
+	"zbbus",
+	zbbus_methods
+};
+
+static devclass_t zbbus_devclass;
+
+DRIVER_MODULE(zbbus, nexus, zbbus_driver, zbbus_devclass, 0, 0);
diff -Nurd /u/neelnatu/p4/freebsd_current/src/sys/mips/sibyte/sb_zbpci.c ./sys/mips/sibyte/sb_zbpci.c
--- /u/neelnatu/p4/freebsd_current/src/sys/mips/sibyte/sb_zbpci.c	1969-12-31 16:00:00.000000000 -0800
+++ ./sys/mips/sibyte/sb_zbpci.c	2009-06-13 12:31:52.042328000 -0700
@@ -0,0 +1,283 @@
+/*-
+ * Copyright (c) 2009 Neelkanth Natu
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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/types.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/pcpu.h>
+#include <sys/smp.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_extern.h>
+#include <vm/pmap.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcib_private.h>
+
+#include <machine/pmap.h>
+#include <machine/resource.h>
+
+#include "pcib_if.h"
+
+#include "sb_scd.h"
+
+__FBSDID("$FreeBSD$");
+
+static struct {
+	vm_offset_t vaddr;
+	vm_paddr_t  paddr;
+} zbpci_config_space[MAXCPU];
+
+static const vm_paddr_t CFG_PADDR_BASE = 0xFE000000;
+	
+static int
+zbpci_probe(device_t dev)
+{
+	
+	device_set_desc(dev, "Broadcom/Sibyte PCI I/O Bridge");
+	return (0);
+}
+
+static int
+zbpci_attach(device_t dev)
+{
+	int n, rid, size;
+	vm_offset_t va;
+	struct resource *res;
+
+	/*
+	 * Reserve the the physical memory that is used to read/write to the
+	 * pci config space but don't activate it. We are using a page worth
+	 * of KVA as a window over this region.
+	 */
+	rid = 0;
+	size = (PCI_BUSMAX + 1) * (PCI_SLOTMAX + 1) * (PCI_FUNCMAX + 1) * 256;
+	res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, CFG_PADDR_BASE,
+				 CFG_PADDR_BASE + size - 1, size, 0);
+	if (res == NULL) {
+		panic("Cannot allocate resource for config space accesses.");
+	}
+
+	/*
+	 * Allocate KVA for accessing PCI config space.
+	 */
+	va = kmem_alloc_nofault(kernel_map, PAGE_SIZE * mp_ncpus);
+	if (va == 0) {
+		device_printf(dev, "Cannot allocate virtual addresses for "
+				   "config space access.\n");
+		return (ENOMEM);
+	}
+
+	for (n = 0; n < mp_ncpus; ++n) {
+		zbpci_config_space[n].vaddr = va + n * PAGE_SIZE;
+	}
+
+	/*
+	 * Sibyte has the PCI bus hierarchy rooted at bus 0 and HT-PCI
+	 * hierarchy rooted at bus 1.
+	 */
+	if (device_add_child(dev, "pci", 0) == NULL) {
+		panic("zbpci_attach: could not add pci bus 0.\n");
+	}
+
+	if (device_add_child(dev, "pci", 1) == NULL) {
+		panic("zbpci_attach: could not add pci bus 1.\n");
+	}
+
+	if (bootverbose) {
+		device_printf(dev, "attached.\n");
+	}
+
+	return (bus_generic_attach(dev));
+}
+
+static int
+zbpci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+	
+	switch (which) {
+	case PCIB_IVAR_DOMAIN:
+		*result = 0;				/* single PCI domain */
+		return (0);
+	case PCIB_IVAR_BUS:
+		*result = device_get_unit(child);	/* PCI bus 0 or 1 */
+		return (0);
+	default:
+		return (ENOENT);
+	}
+}
+
+/*
+ * We rely on the CFE to have configured the intline correctly to point to
+ * one of PCI-A/PCI-B/PCI-C/PCI-D in the interupt mapper.
+ */
+static int
+zbpci_route_interrupt(device_t pcib, device_t dev, int pin)
+{
+
+	return (PCI_INVALID_IRQ);
+}
+
+/*
+ * This function is expected to be called in a critical section since it
+ * changes the per-cpu pci config space va-to-pa mappings.
+ */
+static vm_offset_t
+zbpci_config_space_va(int bus, int slot, int func, int reg, int bytes)
+{
+	int cpu;
+	vm_offset_t va_page;
+	vm_paddr_t pa, pa_page;
+
+	if (bus <= PCI_BUSMAX && slot <= PCI_SLOTMAX && func <= PCI_FUNCMAX &&
+	    reg <= PCI_REGMAX && (bytes == 1 || bytes == 2 || bytes == 4) &&
+	    ((reg & (bytes - 1)) == 0)) {
+		cpu = PCPU_GET(cpuid);
+		va_page = zbpci_config_space[cpu].vaddr;
+		pa = CFG_PADDR_BASE |
+		     (bus << 16) | (slot << 11) | (func << 8) | reg;
+		pa_page = pa & ~(PAGE_SIZE - 1);
+		if (zbpci_config_space[cpu].paddr != pa_page) {
+			pmap_kremove(va_page);
+			pmap_kenter(va_page, pa_page);
+			zbpci_config_space[cpu].paddr = pa_page;
+		}
+		return (va_page + (pa - pa_page));
+	} else {
+		return (0);
+	}
+}
+
+static uint32_t
+zbpci_read_config(device_t dev, u_int b, u_int s, u_int f, u_int r, int w)
+{
+	uint32_t data;
+	vm_offset_t va;
+
+	critical_enter();
+
+	va = zbpci_config_space_va(b, s, f, r, w);
+	if (va == 0) {
+		panic("zbpci_read_config: invalid %d/%d/%d[%d] %d\n",
+		      b, s, f, r, w);
+	}
+
+	switch (w) {
+	case 4:
+		data = *(uint32_t *)va;
+		break;
+	case 2:
+		data = *(uint16_t *)va;
+		break;
+	case 1:
+		data = *(uint8_t *)va;
+		break;
+	default:
+		panic("zbpci_read_config: invalid width %d\n", w);
+	}
+
+	critical_exit();
+
+	return (data);
+}
+
+static void
+zbpci_write_config(device_t d, u_int b, u_int s, u_int f, u_int r,
+		   uint32_t data, int w)
+{
+	vm_offset_t va;
+
+	critical_enter();
+
+	va = zbpci_config_space_va(b, s, f, r, w);
+	if (va == 0) {
+		panic("zbpci_write_config: invalid %d/%d/%d[%d] %d/%d\n",
+		      b, s, f, r, data, w);
+	}
+
+	switch (w) {
+	case 4:
+		*(uint32_t *)va = data;
+		break;
+	case 2:
+		*(uint16_t *)va = data;
+		break;
+	case 1:
+		*(uint8_t *)va = data;
+		break;
+	default:
+		panic("zbpci_write_config: invalid width %d\n", w);
+	}
+
+	critical_exit();
+}
+
+static device_method_t zbpci_methods[] ={
+	/* Device interface */
+	DEVMETHOD(device_probe,		zbpci_probe),
+	DEVMETHOD(device_attach,	zbpci_attach),
+	DEVMETHOD(device_detach,	bus_generic_detach),
+	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
+	DEVMETHOD(device_suspend,	bus_generic_suspend),
+	DEVMETHOD(device_resume,	bus_generic_resume),
+
+	/* Bus interface */
+	DEVMETHOD(bus_read_ivar,	zbpci_read_ivar),
+	DEVMETHOD(bus_write_ivar,	bus_generic_write_ivar),
+	DEVMETHOD(bus_alloc_resource,	bus_generic_alloc_resource),
+	DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+	DEVMETHOD(bus_release_resource,	bus_generic_release_resource),
+	DEVMETHOD(bus_setup_intr,	bus_generic_setup_intr),
+	DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
+	DEVMETHOD(bus_add_child,	bus_generic_add_child),
+
+	/* pcib interface */
+	DEVMETHOD(pcib_maxslots,	pcib_maxslots),
+	DEVMETHOD(pcib_read_config,	zbpci_read_config),
+	DEVMETHOD(pcib_write_config,	zbpci_write_config),
+	DEVMETHOD(pcib_route_interrupt,	zbpci_route_interrupt),
+	
+	{ 0, 0 }
+};
+
+/*
+ * The "zbpci" class inherits from the "pcib" base class. Therefore in
+ * addition to drivers that belong to the "zbpci" class we will also
+ * consider drivers belonging to the "pcib" when probing children of
+ * "zbpci".
+ */
+DECLARE_CLASS(pcib_driver);
+DEFINE_CLASS_1(zbpci, zbpci_driver, zbpci_methods, 0, pcib_driver);
+
+static devclass_t zbpci_devclass;
+
+DRIVER_MODULE(zbpci, zbbus, zbpci_driver, zbpci_devclass, 0, 0);


More information about the freebsd-mips mailing list