patch-2.4.0-test3 linux/arch/mips64/sgi-ip27/ip27-setup.c

Next file: linux/arch/mips64/sgi-ip27/ip27-timer.c
Previous file: linux/arch/mips64/sgi-ip27/ip27-reset.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/sgi-ip27/ip27-setup.c linux/arch/mips64/sgi-ip27/ip27-setup.c
@@ -1,17 +1,19 @@
-/* $Id: ip27-setup.c,v 1.7 2000/03/07 15:45:29 ralf Exp $
- *
+/*
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
  * SGI IP27 specific setup.
  *
- * Copyright (C) 1999 Ralf Baechle (ralf@gnu.org)
- * Copyright (C) 1999 Silcon Graphics, Inc.
+ * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org)
+ * Copyright (C) 1999, 2000 Silcon Graphics, Inc.
  */
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
 #include <asm/sn/types.h>
 #include <asm/sn/sn0/addrs.h>
 #include <asm/sn/sn0/hubni.h>
@@ -24,6 +26,7 @@
 #include <asm/pci/bridge.h>
 #include <asm/paccess.h>
 #include <asm/sn/sn0/ip27.h>
+#include <asm/sn/sn0/hubio.h>
 
 /* Check against user dumbness.  */
 #ifdef CONFIG_VT
@@ -101,27 +104,32 @@
 #define XXBOW_WIDGET_PART_NUM   0xd000          /* Xbridge */
 #define BASE_XBOW_PORT  	8     /* Lowest external port */
 
-static void __init pcibr_setup(void)
+unsigned int bus_to_cpu[256];
+
+void __init pcibr_setup(cnodeid_t nid)
 {
-	int 			i;
+	int 			i, start, num, masterwid;
 	bridge_t 		*bridge; 
 	volatile u64 		hubreg;
-	nasid_t	 		nasid;
+	nasid_t	 		nasid, masternasid;
 	xwidget_part_num_t	partnum;
 	widgetreg_t 		widget_id;
+	static spinlock_t	pcibr_setup_lock = SPIN_LOCK_UNLOCKED;
 
-	num_bridges = 0;
 	/*
 	 * find what's on our local node
 	 */
-	nasid = 0;
-	hubreg = LOCAL_HUB_L(IIO_LLP_CSR);
+	spin_lock(&pcibr_setup_lock);
+	start = num_bridges;		/* Remember where we start from */
+	nasid = COMPACT_TO_NASID_NODEID(nid);
+	hubreg = REMOTE_HUB_L(nasid, IIO_LLP_CSR);
 	if (hubreg & IIO_LLP_CSR_IS_UP) {
 		/* link is up */
 		widget_id = *(volatile widgetreg_t *)
                         (RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID);
 		partnum = XWIDGET_PART_NUM(widget_id);
-		printk("pcibr_setup(): found partnum= 0x%x ", partnum);
+		printk("Cpu %d, Nasid 0x%x, pcibr_setup(): found partnum= 0x%x",
+					smp_processor_id(), nasid, partnum);
 		if (partnum == BRIDGE_WIDGET_PART_NUM) {
 			/*
 			 * found direct connected bridge so must be Origin200
@@ -130,8 +138,7 @@
 			num_bridges = 1;
         		bus_to_wid[0] = 0x8;
 			bus_to_nid[0] = 0;
-		}
-		if (partnum == XBOW_WIDGET_PART_NUM) {
+		} else if (partnum == XBOW_WIDGET_PART_NUM) {
 			lboard_t *brd;
 			klxbow_t *xbow_p;
 			/*
@@ -144,11 +151,32 @@
                                    KLTYPE_MIDPLANE8)) == NULL)
 				printk("argh\n");
 			else
-				printk("brd= 0x%x\n", brd);
+				printk("brd = 0x%lx\n", (unsigned long) brd);
 			if ((xbow_p = (klxbow_t *)
 			     find_component(brd, NULL, KLSTRUCT_XBOW)) == NULL)
 				printk("argh\n");
 			else {
+			   /*
+			    * Okay, here's a xbow. Lets arbitrate and find
+			    * out if we should initialize it. Set hub connected
+			    * at highest or lowest widget as master.
+			    * This algo needs to change a little for headless
+			    * nodes.
+			    */
+#ifdef WIDGET_A
+			   i = HUB_WIDGET_ID_MAX + 1;
+			   do {
+				i--;
+			   } while (!XBOW_PORT_TYPE_HUB(xbow_p, i));
+#else
+			   i = HUB_WIDGET_ID_MIN - 1;
+			   do {
+				i++;
+			   } while (!XBOW_PORT_TYPE_HUB(xbow_p, i));
+#endif
+			   masterwid = i;
+			   masternasid = XBOW_PORT_NASID(xbow_p, i);
+			   if (nasid == masternasid)
 			   for (i=HUB_WIDGET_ID_MIN; i<=HUB_WIDGET_ID_MAX; i++) {
 				if (!XBOW_PORT_IS_ENABLED(xbow_p, i))
 					continue;
@@ -165,8 +193,7 @@
 				}
 			   }
 			}
-		}
-		if (partnum == XXBOW_WIDGET_PART_NUM) {
+		} else if (partnum == XXBOW_WIDGET_PART_NUM) {
 			/*
 			 * found xbridge, assume ibrick for now 
 			 */
@@ -182,13 +209,17 @@
 			num_bridges = 3;
 		}
 	}
+	num = num_bridges - start;
+	spin_unlock(&pcibr_setup_lock);
 	/*
          * set bridge registers
          */
-	for (i=0; i<num_bridges; i++) {
+	for (i = start; i < (start + num); i++) {
+
 		DBG("pcibr_setup: bus= %d  bus_to_wid[%2d]= %d  bus_to_nid[%2d]= %d\n",
                         i, i, bus_to_wid[i], i, bus_to_nid[i]);
 
+		bus_to_cpu[i] = smp_processor_id();
 		/*
 		 * point to this bridge
 		 */
@@ -207,6 +238,19 @@
 		bridge->b_wid_control |= BRIDGE_CTRL_IO_SWAP;
 		bridge->b_wid_control |= BRIDGE_CTRL_MEM_SWAP;
 
+		/*
+		 * Hmm...  IRIX sets additional bits in the address which 
+		 * are documented as reserved in the bridge docs.
+		 * We waste time programming b_wid_int_upper/b_wid_int_lower,
+		 * since bridge_startup will set up the widget->nasid intr
+		 * path anyway.
+		 */
+		bridge->b_int_mode = 0x0;		/* Don't clear ints */
+		bridge->b_wid_int_upper = 0x000a8000;	/* Ints to widget A */
+		bridge->b_wid_int_lower = 0x01800090;
+		bridge->b_dir_map = 0xa00000;		/* DMA */
+		bridge->b_int_enable = 0;
+
 		bridge->b_wid_tflush;     /* wait until Bridge PIO complete */
 	}
 }
@@ -216,11 +260,11 @@
 	nasid_t nid;
 	hubreg_t p, e;
 
+	num_bridges = 0;
 	/*
 	 * hub_rtc init and cpu clock intr enabled for later calibrate_delay.
 	 */
 	DBG("ip27_setup(): Entered.\n");
-	per_cpu_init();
 	nid = get_nasid();
 	printk("IP27: Running on node %d.\n", nid);
 
@@ -239,9 +283,5 @@
 	verify_mode();
 	ioc3_sio_init();
 	ioc3_eth_init();
-
-	DBG("ip27_setup(): calling pcibr_setup\n");
-	/* set some bridge registers */
-	pcibr_setup();
-	DBG("ip27_setup(): Exit.\n");
+	per_cpu_init();
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)