patch-2.2.18 linux/arch/ppc/kernel/prom.c

Next file: linux/arch/ppc/kernel/setup.c
Previous file: linux/arch/ppc/kernel/process.c
Back to the patch index
Back to the overall index

diff -u --new-file --recursive --exclude-from /usr/src/exclude v2.2.17/arch/ppc/kernel/prom.c linux/arch/ppc/kernel/prom.c
@@ -16,6 +16,8 @@
 #include <linux/string.h>
 #include <linux/init.h>
 #include <linux/version.h>
+#include <linux/fs.h>
+#include <linux/console.h>
 #include <asm/spinlock.h>
 #include <asm/prom.h>
 #include <asm/page.h>
@@ -27,6 +29,10 @@
 #include <asm/system.h>
 #include <asm/gemini.h>
 #include <asm/linux_logo.h>
+#include <asm/mmu.h>
+#include <asm/pgtable.h>
+#include <asm/adb.h>
+#include <asm/pmu.h>
 
 /*
  * Properties whose value is longer than this get excluded from our
@@ -109,6 +115,12 @@
 
 #ifdef CONFIG_BOOTX_TEXT
 
+/*
+ * The VGA font is in the _pmac section. Can't this cause problems with CHRP
+ * using some of the prom_xxxx functions ?
+ * All this need to be moved in a separate source file anyway
+ */
+
 static void clearscreen(void);
 static void flushscreen(void);
 
@@ -116,6 +128,9 @@
 void drawstring(const char *c);
 void drawhex(unsigned long v);
 static void scrollscreen(void);
+static void prepare_disp_BAT(void);
+static void boot_console_write(struct console *co, const char *s,
+				 unsigned count);
 
 static void draw_byte(unsigned char c, long locX, long locY);
 static void draw_byte_32(unsigned char *bits, unsigned long *base, int rb);
@@ -128,10 +143,28 @@
 static long				g_max_loc_X = 0;
 static long				g_max_loc_Y = 0; 
 
+unsigned long disp_BATL = 0;
+unsigned long disp_BATU = 0;
+
 #define cmapsz	(16*256)
 
 static unsigned char vga_font[cmapsz];
 
+static struct console boot_cons = {
+	"boot",
+	boot_console_write,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	CON_PRINTBUFFER,
+	0,
+	0,
+	NULL
+};
+static int boot_cons_registered = 0;
+
 #endif /* CONFIG_BOOTX_TEXT */
 
 
@@ -243,7 +276,7 @@
 	return prom_args.args[nargs];
 }
 
-__init
+/*__init*/
 void
 prom_print(const char *msg)
 {
@@ -399,6 +432,7 @@
 		}
 		
 #ifdef CONFIG_BOOTX_TEXT
+		prepare_disp_BAT();
 		prom_print(RELOC("booting...\n"));
 		flushscreen();
 #endif
@@ -573,7 +607,11 @@
 	 * is in its holding pattern code.
 	 *
 	 * -- Cort
+	 * 
+	 * This code crashes on some pmacs since the memory at 8M is not
+	 * claim'ed and so can be unmapped. -- BenH
 	 */
+	if (chrp)
 	{
 		extern void __secondary_hold(void);
 		unsigned long i;
@@ -599,7 +637,7 @@
 	}
 
 	/* look for cpus */
-	for (node = 0; prom_next_node(&node);)
+	for (node = 0; chrp && prom_next_node(&node);)
 	{
 		type[0] = 0;
 		call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"),
@@ -642,6 +680,7 @@
 	if (!chrp && RELOC(disp_bi)) {
 		RELOC(prom_stdout) = 0;
 		clearscreen();
+		prepare_disp_BAT();
 		prom_welcome(PTRRELOC(RELOC(disp_bi)), phys);
 	}
 #endif
@@ -692,9 +731,50 @@
 	drawhex(val);
 	drawstring("\n");
 }
+
+/* Calc BAT values for mapping the display and store them
+ * in disp_BATH and disp_BATL. Those values are then used
+ * from head.S to map the display during identify_machine()
+ * and MMU_Init()
+ * 
+ * For now, the display is mapped in place (1:1). This should
+ * be changed if the display physical address overlaps
+ * KERNELBASE, which is fortunately not the case on any machine
+ * I know of. This mapping is temporary and will disappear as
+ * soon as the setup done by MMU_Init() is applied
+ * 
+ * For now, we align the BAT and then map 8Mb on 601 and 16Mb
+ * on other PPCs. This may cause trouble if the framebuffer
+ * is really badly aligned, but I didn't encounter this case
+ * yet.
+ */
+__init
+static void
+prepare_disp_BAT(void)
+{
+	unsigned long offset = reloc_offset();
+	boot_infos_t* bi = PTRRELOC(RELOC(disp_bi));
+	unsigned long addr = (unsigned long)bi->dispDeviceBase;
+	
+	if ((_get_PVR() >> 16) != 1) {
+		/* 603, 604, G3, G4, ... */
+		addr &= 0xFF000000UL;
+		RELOC(disp_BATU) = addr | (BL_16M<<2) | 2;
+		RELOC(disp_BATL) = addr | (_PAGE_NO_CACHE | _PAGE_GUARDED | BPP_RW);		
+	} else {
+		/* 601 */
+		addr &= 0xFF800000UL;
+		RELOC(disp_BATU) = addr | (_PAGE_NO_CACHE | PP_RWXX) | 4;
+		RELOC(disp_BATL) = addr | BL_8M | 0x40;
+	}
+	bi->logicalDisplayBase = bi->dispDeviceBase;
+}
+
 #endif
 
-static int prom_set_color(ihandle ih, int i, int r, int g, int b)
+__init
+static int
+prom_set_color(ihandle ih, int i, int r, int g, int b)
 {
 	struct prom_args prom_args;
 	unsigned long offset = reloc_offset();
@@ -729,7 +809,7 @@
 	ihandle ih;
 	int i;
 	unsigned long offset = reloc_offset();
-	char type[16], *path;
+	char type[16], *path, name[32];
 	static unsigned char default_colors[] = {
 		0x00, 0x00, 0x00,
 		0x00, 0x00, 0xaa,
@@ -757,6 +837,12 @@
 			  type, sizeof(type));
 		if (strcmp(type, RELOC("display")) != 0)
 			continue;
+		name[0] = 0;
+		call_prom(RELOC("getprop"), 4, 1, node, RELOC("name"),
+			  name, sizeof(name));
+		if (!strcmp(name, RELOC("offscreen-display")))
+	    		continue;
+
 		/* It seems OF doesn't null-terminate the path :-( */
 		path = (char *) mem;
 		memset(path, 0, 256);
@@ -1189,7 +1275,7 @@
 		    ((node->name && !strcmp(node->name, "open-pic")) ||
 		     !node->name)) {
 		    for (i = 0; i < np->n_intrs; ++i)
-			np->intrs[i].line = openpic_to_irq(np->intrs[i].line);
+			np->intrs[i].line = np->intrs[i].line + NUM_8259_INTERRUPTS;
 		}
 		return mem_start;
 	    }
@@ -1492,7 +1578,7 @@
 			/* CHRP machines */
 			np->n_intrs = l / (2 * sizeof(int));
 			for (i = 0; i < np->n_intrs; ++i) {
-				np->intrs[i].line = openpic_to_irq(*ip++);
+				np->intrs[i].line = (*ip++) + NUM_8259_INTERRUPTS;
 				np->intrs[i].sense = *ip++;
 			}
 		}
@@ -1637,9 +1723,17 @@
 	int l;
 	
 	for (np = allnodes; np != 0; np = np->allnext) {
-		char *pname = np->parent ?
-			(char *)get_property(np->parent, "name", &l) : 0;
-		if (pname && strcmp(pname, "mac-io") == 0)
+		int in_macio = 0;
+		struct device_node* parent = np->parent;
+		while(parent) {
+			char *pname = (char *)get_property(parent, "name", &l);
+			if (pname && strcmp(pname, "mac-io") == 0) {
+				in_macio = 1;
+				break;
+			}
+			parent = parent->parent;
+		}
+		if (in_macio)
 			continue;
 		reg = (unsigned int *) get_property(np, "reg", &l);
 		if (reg == 0 || l < sizeof(struct reg_property))
@@ -1757,7 +1851,7 @@
 	struct property *pp;
 
 	for (pp = np->properties; pp != 0; pp = pp->next)
-		if (strcmp(pp->name, name) == 0) {
+		if (pp->name && strcmp(pp->name, name) == 0) {
 			if (lenp != 0)
 				*lenp = pp->length;
 			return pp->value;
@@ -1901,11 +1995,30 @@
 void
 map_bootx_text(void)
 {
+	unsigned long base, offset, size;
 	if (disp_bi == 0)
 		return;
-	disp_bi->logicalDisplayBase =
-		ioremap((unsigned long) disp_bi->dispDeviceBase,
-			disp_bi->dispDeviceRowBytes * disp_bi->dispDeviceRect[3]);
+	base = ((unsigned long) disp_bi->dispDeviceBase) & 0xFFFFF000UL;
+	offset = ((unsigned long) disp_bi->dispDeviceBase) - base;
+	size = disp_bi->dispDeviceRowBytes * disp_bi->dispDeviceRect[3] + offset
+		+ disp_bi->dispDeviceRect[0];
+	disp_bi->logicalDisplayBase = ioremap(base, size) + offset;
+}
+
+__init
+void
+install_boot_console(void)
+{
+	register_console(&boot_cons);
+	boot_cons_registered = 1;
+}
+
+void
+remove_boot_console(void)
+{
+	if (boot_cons_registered)
+		unregister_console(&boot_cons);
+	boot_cons_registered = 0;
 }
 
 /* Calc the base address of a given point (x,y) */
@@ -1981,7 +2094,11 @@
 	unsigned long width		= ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) *
 						(bi->dispDeviceDepth >> 3)) >> 2;
 	int i,j;
-	
+
+#ifdef CONFIG_POWERMAC
+	pmu_suspend();
+#endif
+
 	for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1] - 16); i++)
 	{
 		unsigned long *src_ptr = src;
@@ -1998,6 +2115,10 @@
 			*(dst_ptr++) = 0;
 		dst += (bi->dispDeviceRowBytes >> 2);
 	}
+
+#ifdef CONFIG_POWERMAC
+	pmu_resume();
+#endif
 }
 
 __pmac
@@ -2041,6 +2162,16 @@
 	while (*c)
 		drawchar(*c++);
 }
+
+#ifdef CONFIG_BOOTX_TEXT
+__pmac
+static void boot_console_write(struct console *co, const char *s,
+				 unsigned count)
+{
+	while(count--)
+		drawchar(*s++);
+}
+#endif
 
 __pmac
 void

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