patch-2.1.79 linux/arch/ppc/kernel/setup.c

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

diff -u --recursive --new-file v2.1.78/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c
@@ -1,6 +1,6 @@
 /*
- * $Id: setup.c,v 1.16 1997/08/27 22:06:54 cort Exp $
- * Common prep/pmac boot and setup code.
+ * $Id: setup.c,v 1.48 1998/01/01 10:04:44 paulus Exp $
+ * Common prep/pmac/chrp boot and setup code.
  */
 
 #include <linux/config.h>
@@ -8,19 +8,31 @@
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/reboot.h>
-#include <linux/openpic.h>
+#include <linux/delay.h>
+#include <linux/blk.h>
 
+#include <asm/adb.h>
 #include <asm/cuda.h>
 #include <asm/residual.h>
 #include <asm/io.h>
 #include <asm/ide.h>
+#include <asm/prom.h>
 
+extern char cmd_line[512];
 char saved_command_line[256];
 unsigned char aux_device_present;
 
+#if !defined(CONFIG_MACH_SPECIFIC)
+unsigned long ISA_DMA_THRESHOLD;
+unsigned long DMA_MODE_READ, DMA_MODE_WRITE;
+int _machine;
+#endif /* ! CONFIG_MACH_SPECIFIC */
+
 /* copy of the residual data */
 RESIDUAL res;
-int _machine;
+int _prep_type;
+/* if we have openfirmware */
+unsigned long have_of;
 
 /*
  * Perhaps we can put the pmac screen_info[] here
@@ -28,7 +40,7 @@
  * Until we get multiple-console support in here
  * that is.  -- Cort
  */ 
-#if defined(CONFIG_CHRP) || defined(CONFIG_PREP )
+#if !defined(CONFIG_PMAC_CONSOLE)
 struct screen_info screen_info = {
 	0, 25,			/* orig-x, orig-y */
 	{ 0, 0 },		/* unused */
@@ -48,94 +60,20 @@
 {
 	return 0;
 }
-int sd_find_target(void *a, int b)
-{
-	return 0;
-}
 void pmac_find_display(void)
 {
 }
-
 #endif
 
-/*
- * Find out what kind of machine we're on and save any data we need
- * from the early boot process (devtree is copied on pmac by prom_init() )
- */
-unsigned long identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
-			       unsigned long r6, unsigned long r7)
-{
-	extern unsigned long initrd_start, initrd_end;
-	extern char cmd_line[256];
-#ifdef CONFIG_PMAC /* cheat for now - perhaps a check for OF could tell us */
-	_machine = _MACH_Pmac;
-#endif /* CONFIG_PMAC */
-#ifdef CONFIG_PREP
-	/* make a copy of residual data */
-	if ( r3 )
-		memcpy( (void *)&res,(void *)(r3+KERNELBASE), sizeof(RESIDUAL) );
-	if (!strncmp(res.VitalProductData.PrintableModel,"IBM",3))
-		_machine = _MACH_IBM;
-	else
-		_machine = _MACH_Motorola;
-#endif /* CONFIG_PREP */
-#ifdef CONFIG_CHRP 
-	_machine = _MACH_chrp;
-#endif /* CONFIG_CHRP */
-
-	switch (_machine)
-	{
-	case _MACH_Pmac:
-		io_base = 0;
-		pci_dram_offset = 0;
-		break;
-	case _MACH_IBM:
-	case _MACH_Motorola:
-		io_base = 0x80000000;
-		pci_dram_offset = 0x80000000;
-#ifdef CONFIG_BLK_DEV_RAM
-		/* take care of initrd if we have one */
-		if ( r4 )
-		{
-			initrd_start = r4 + KERNELBASE;
-			initrd_end = r5 + KERNELBASE;
-		}
-#endif /* CONFIG_BLK_DEV_RAM */
-		/* take care of cmd line */
-		if ( r6 )
-		{
-			
-			*(char *)(r7+KERNELBASE) = 0;
-			strcpy(cmd_line, (char *)(r6+KERNELBASE));
-		}
-		break;
-	case _MACH_chrp:
-		/* LongTrail */
-		io_base = 0xf8000000;
-		pci_dram_offset = 0;
-		/* take care of initrd if we have one */
-		if ( r4 ) {
-			initrd_start = r4 + KERNELBASE;
-			initrd_end = r5 + KERNELBASE;
-		}
-		/* take care of cmd line */
-		if ( r6 ) {
-			*(char *)(r7+KERNELBASE) = 0;
-			strcpy(cmd_line, (char *)(r6+KERNELBASE));
-		}
-		break;
-	default:
-		printk("Unknown machine type in identify_machine!\n");
-	}
-	return 0;
-}
-
 /* cmd is ignored for now... */
 void machine_restart(char *cmd)
 {
-	struct cuda_request req;
+	struct adb_request req;
 	unsigned long flags;
 	unsigned long i = 10000;
+#if 0	
+	int err;
+#endif	
 
 	switch(_machine)
 	{
@@ -144,8 +82,14 @@
 		for (;;)
 			cuda_poll();
 		break;
-	case _MACH_IBM:
-	case _MACH_Motorola:
+	case _MACH_chrp:
+#if 0		/* RTAS doesn't seem to work on Longtrail.
+		   For now, do it the same way as the PReP. */
+		err = call_rtas("system-reboot", 0, 1, NULL);
+		printk("RTAS system-reboot returned %d\n", err);
+		for (;;);
+#endif
+	case _MACH_prep:
 		_disable_interrupts();
 		
 		/* set exception prefix high - to the prom */
@@ -160,25 +104,29 @@
 		while ( i != 0 ) i++;
 		panic("restart failed\n");
 		break;
-
-	case _MACH_chrp:
-		openpic_init_processor(1<<0);
-		break;
 	}
 }
 
 void machine_power_off(void)
 {
-	struct cuda_request req;
+	struct adb_request req;
+#if 0	
+	int err;
+#endif	
 
-	if ( _machine == _MACH_Pmac )
-	{
+	switch (_machine) {
+	case _MACH_Pmac:
 		cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_POWERDOWN);
 		for (;;)
 			cuda_poll();
-	}
-	else /* prep or chrp */
-	{
+	case _MACH_chrp:
+#if 0		/* RTAS doesn't seem to work on Longtrail.
+		   For now, do it the same way as the PReP. */
+		err = call_rtas("power-off", 2, 1, NULL, 0, 0);
+		printk("RTAS system-reboot returned %d\n", err);
+		for (;;);
+#endif
+	case _MACH_prep:
 		machine_restart(NULL);
 	}
 }
@@ -202,38 +150,328 @@
 {
 	if ( _machine == _MACH_Pmac )
 		pmac_ide_init_hwif_ports(p,base,irq);
-	else /* prep */
+	else /* prep or chrp */
 		prep_ide_init_hwif_ports(p,base,irq);
 	
 }
 
-/*
- * Will merge more into here later  -- Cort
- */
 int get_cpuinfo(char *buffer)
 {
 	extern int pmac_get_cpuinfo(char *);
 	extern int chrp_get_cpuinfo(char *);	
 	extern int prep_get_cpuinfo(char *);
+	unsigned long len = 0;
+	unsigned long bogosum = 0;
+	unsigned long i;
+#ifdef __SMP__
+	extern unsigned long cpu_present_map;	
+	extern struct cpuinfo_PPC cpu_data[NR_CPUS];
+#define GET_PVR ((long int)(cpu_data[i].pvr))
+#define CD(x) (cpu_data[i].x)
+#else
+#define cpu_present_map 1L
+#define smp_num_cpus 1
+#define GET_PVR ((long int)_get_PVR())
+#define CD(x) (x)
+#endif	
+
+	for ( i = 0; i < smp_num_cpus ; i++ )
+	{
+		if ( ! ( cpu_present_map & (1<<i) ) )
+			continue;
+		if ( i )
+			len += sprintf(len+buffer,"\n");
+		len += sprintf(len+buffer,"processor\t: %lu\n",i);
+		len += sprintf(len+buffer,"cpu\t\t: ");
 	
+		switch (GET_PVR >> 16)
+		{
+		case 1:
+			len += sprintf(len+buffer, "601\n");
+			break;
+		case 3:
+			len += sprintf(len+buffer, "603\n");
+			break;
+		case 4:
+			len += sprintf(len+buffer, "604\n");
+			break;
+		case 6:
+			len += sprintf(len+buffer, "603e\n");
+			break;
+		case 7:
+			len += sprintf(len+buffer, "603ev\n");
+			break;
+		case 8:
+			len += sprintf(len+buffer, "750 (Arthur)\n");
+			break;
+		case 9:
+			len += sprintf(len+buffer, "604e\n");
+			break;
+		case 10:
+			len += sprintf(len+buffer, "604ev5 (MachV)\n");
+			break;
+		default:
+			len += sprintf(len+buffer, "unknown (%lu)\n",
+				       GET_PVR>>16);
+			break;
+		}
+
+		/*
+		 * Assume here that all clock rates are the same in a
+		 * smp system.  -- Cort
+		 */
+		if ( have_of )
+		{
+			struct device_node *cpu_node;
+			int *fp;
+			
+			cpu_node = find_type_devices("cpu");
+			if ( !cpu_node ) break;
+			fp = (int *) get_property(cpu_node, "clock-frequency", NULL);
+			if ( !fp ) break;
+			len += sprintf(len+buffer, "clock\t\t: %dMHz\n",
+				       *fp / 1000000);
+		}
+		
+		/* PREP's without residual data for some reason will give
+		   incorrect values here */
+		if ( is_prep )
+		{
+			len += sprintf(len+buffer, "clock\t\t: ");
+			if ( res.ResidualLength )
+				len += sprintf(len+buffer, "%ldMHz\n",
+				       (res.VitalProductData.ProcessorHz > 1024) ?
+				       res.VitalProductData.ProcessorHz>>20 :
+				       res.VitalProductData.ProcessorHz);
+			else
+				len += sprintf(len+buffer, "???\n");
+		}				
+		
+		len += sprintf(len+buffer, "revision\t: %ld.%ld\n",
+			       (GET_PVR & 0xff00) >> 8, GET_PVR & 0xff);
+
+		len += sprintf(buffer+len, "bogomips\t: %lu.%02lu\n",
+			       (CD(loops_per_sec)+2500)/500000,
+			       (CD(loops_per_sec)+2500)/5000 % 100);
+		bogosum += CD(loops_per_sec);
+	}
+
+#ifdef __SMP__
+	if ( i )
+		len += sprintf(buffer+len, "\n");
+	len += sprintf(buffer+len,"total bogomips\t: %lu.%02lu\n",
+	       (bogosum+2500)/500000,
+	       (bogosum+2500)/5000 % 100);
+#endif /* __SMP__ */
+
+	/*
+	 * Ooh's and aah's info about zero'd pages in idle task
+	 */ 
+	{
+		extern unsigned int zerocount, zerototal, zeropage_hits,zeropage_calls;
+		len += sprintf(buffer+len,"zero pages\t: total %u (%luKb) "
+			       "current: %u (%luKb) hits: %u/%u (%u%%)\n",
+			       zerototal, (zerototal*PAGE_SIZE)>>10,
+			       zerocount, (zerocount*PAGE_SIZE)>>10,
+			       zeropage_hits,zeropage_calls,
+			       /* : 1 below is so we don't div by zero */
+			       (zeropage_hits*100) /
+			            ((zeropage_calls)?zeropage_calls:1));
+	}
 
 	switch (_machine)
 	{
 	case _MACH_Pmac:
-		return pmac_get_cpuinfo(buffer);
+		len += pmac_get_cpuinfo(buffer+len);
 		break;
-	case _MACH_Motorola:
-	case _MACH_IBM:
-		return prep_get_cpuinfo(buffer);
+	case _MACH_prep:
+		len += prep_get_cpuinfo(buffer+len);
 		break;
 	case _MACH_chrp:
-		return chrp_get_cpuinfo(buffer);
+		len += chrp_get_cpuinfo(buffer+len);
 		break;
 	}
-	printk("Unknown machine %d in get_cpuinfo()\n",_machine);
-	return 0;
+	return len;
 }
 
+/*
+ * Find out what kind of machine we're on and save any data we need
+ * from the early boot process (devtree is copied on pmac by prom_init() )
+ */
+__initfunc(unsigned long
+identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
+		 unsigned long r6, unsigned long r7))
+{
+	extern unsigned long initrd_start, initrd_end;
+	extern setup_pci_ptrs(void);
+	unsigned long boot_sdr1;
+	ihandle prom_root;
+	unsigned char type[16], model[16];
+
+	asm("mfspr %0,25\n\t" :"=r" (boot_sdr1));
+
+	/* 
+	 * if we have a sdr1 then we have openfirmware 
+	 * and can ask it what machine we are (chrp/pmac/prep).
+	 * otherwise we're definitely prep. -- Cort
+	 */
+	if ( !boot_sdr1 )
+	{
+		/* we know for certain we're prep if no OF */
+		have_of = 0;
+		/* make a copy of residual data */
+		if ( r3 )
+			memcpy((void *)&res,(void *)(r3+KERNELBASE),
+			       sizeof(RESIDUAL));
+#ifndef CONFIG_MACH_SPECIFIC
+		_machine = _MACH_prep;
+#endif /* CONFIG_MACH_SPECIFIC */
+	}
+	else
+	{
+		/*
+		 * init prom here, then ask the openfirmware
+		 * what machine we are (prep/chrp/pmac).  We don't use
+		 * OF on prep just yet.  -- Cort
+		 */
+#ifndef CONFIG_PREP		/* don't use OF on prep yet */
+		have_of = 1;
+		/* prom_init has already been called from __start */
+		finish_device_tree();
+
+		/*
+		 * If we were booted via quik, r3 points to the physical
+		 * address of the command-line parameters.
+		 * If we were booted from an xcoff image (i.e. netbooted or
+		 * booted from floppy), we get the command line from the
+		 * bootargs property of the /chosen node.
+		 * If an initial ramdisk is present, r3 and r4
+		 * are used for initrd_start and initrd_size,
+		 * otherwise they contain 0xdeadbeef.  
+		 */
+		cmd_line[0] = 0;
+		if (r3 >= 0x4000 && r3 < 0x800000 && r4 == 0) {
+			strncpy(cmd_line, (char *)r3 + KERNELBASE,
+				sizeof(cmd_line));
+		} else {
+			struct device_node *chosen;
+			char *p;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+			if (r3 - KERNELBASE < 0x800000
+			    && r4 != 0 && r4 != 0xdeadbeef) {
+				initrd_start = r3;
+				initrd_end = r3 + r4;
+				ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
+			}
+#endif
+			chosen = find_path_device("/chosen");
+			if (chosen != NULL) {
+				p = get_property(chosen, "bootargs", NULL);
+				if (p != NULL)
+					strncpy(cmd_line, p, sizeof(cmd_line));
+			}
+		}
+		cmd_line[sizeof(cmd_line) - 1] = 0;
+#endif /* CONFIG_PREP */
+
+#ifndef CONFIG_MACH_SPECIFIC
+#if 0
+		prom_root = call_prom("finddevice", 1, 1, "/");		
+		call_prom("getprop", 4, 1, prom_root, "device_type", &type,
+			  (void *) sizeof(type));
+		call_prom("getprop", 4, 1, prom_root, "model", &type,
+			  (void *) sizeof(model));
+		if ( !strncmp("chrp", type,4) )
+		{
+			_machine = _MACH_chrp;
+		}
+		else 
+		{
+		        /*if ( !strncmp("Power Macintosh", type,15) )*/
+			_machine = _MACH_Pmac;
+                }
+#else
+
+#ifdef CONFIG_CHRP		
+		_machine = _MACH_chrp;
+#endif /* CONFIG_CHRP */
+#ifdef CONFIG_PMAC		
+		_machine = _MACH_Pmac;
+#endif /* CONFIG_PMAC */
+#ifdef CONFIG_PREP
+		_machine = _MACH_Prep;
+#endif /* CONFIG_PREP */
+#endif /* #if */		
+#endif /* CONFIG_MACH_SPECIFIC */
+	}
+
+	/* so that pmac/chrp can use pci to find its console -- Cort */
+	setup_pci_ptrs();
+	
+	switch (_machine)
+	{
+	case _MACH_Pmac:
+#if !defined(CONFIG_MACH_SPECIFIC)
+		isa_io_base = PMAC_ISA_IO_BASE;
+		isa_mem_base = PMAC_ISA_MEM_BASE;
+		pci_dram_offset = PMAC_PCI_DRAM_OFFSET;
+		ISA_DMA_THRESHOLD = ~0L;
+		DMA_MODE_READ = 1;
+		DMA_MODE_WRITE = 2;
+#endif /* ! CONFIG_MACH_SPECIFIC */
+		break;
+	case _MACH_prep:
+#if !defined(CONFIG_MACH_SPECIFIC)
+		isa_io_base = PREP_ISA_IO_BASE;
+		isa_mem_base = PREP_ISA_MEM_BASE;
+		pci_dram_offset = PREP_PCI_DRAM_OFFSET;
+		ISA_DMA_THRESHOLD = 0x00ffffff;
+		DMA_MODE_READ = 0x44;
+		DMA_MODE_WRITE = 0x48;
+#endif /* ! CONFIG_MACH_SPECIFIC */
+		/* figure out what kind of prep workstation we are */
+		if ( res.ResidualLength != 0 )
+		{
+			if ( !strncmp(res.VitalProductData.PrintableModel,"IBM",3) )
+				_prep_type = 0x00;
+			else
+				_prep_type = 0x01;
+		}
+		else /* assume motorola if no residual (netboot?) */
+			_prep_type = _PREP_Motorola;
+
+#ifdef CONFIG_BLK_DEV_RAM
+		/* take care of initrd if we have one */
+		if ( r4 )
+		{
+			initrd_start = r4 + KERNELBASE;
+			initrd_end = r5 + KERNELBASE;
+		}
+#endif /* CONFIG_BLK_DEV_RAM */
+		/* take care of cmd line */
+		if ( r6 )
+		{
+			*(char *)(r7+KERNELBASE) = 0;
+			strcpy(cmd_line, (char *)(r6+KERNELBASE));
+		}
+		break;
+	case _MACH_chrp:
+		/* LongTrail */
+#if !defined(CONFIG_MACH_SPECIFIC)
+		isa_io_base = CHRP_ISA_IO_BASE;
+		isa_mem_base = CHRP_ISA_MEM_BASE;
+		pci_dram_offset = CHRP_PCI_DRAM_OFFSET;
+		ISA_DMA_THRESHOLD = ~0L;
+		DMA_MODE_READ = 0x44;
+		DMA_MODE_WRITE = 0x48;
+#endif /* ! CONFIG_MACH_SPECIFIC */
+		break;
+	default:
+		printk("Unknown machine type in identify_machine!\n");
+	}
+	return 0;
+}
 
 __initfunc(unsigned long
 bios32_init(unsigned long memory_start, unsigned long memory_end))
@@ -244,25 +482,41 @@
 __initfunc(void setup_arch(char **cmdline_p,
 	unsigned long * memory_start_p, unsigned long * memory_end_p))
 {
-	extern void pmac_setup_arch(char **, unsigned long *, unsigned long *);
-	extern void chrp_setup_arch(char **, unsigned long *, unsigned long *);
-	extern void prep_setup_arch(char **, unsigned long *, unsigned long *);
+	extern void pmac_setup_arch(unsigned long *, unsigned long *);
+	extern void chrp_setup_arch(unsigned long *, unsigned long *);
+	extern void prep_setup_arch(unsigned long *, unsigned long *);
+	extern int panic_timeout;
+	extern char _etext[], _edata[];
+	extern char *klimit;
+	extern unsigned long find_available_memory(void);
+	extern unsigned long *end_of_DRAM;
+
+	/* reboot on panic */	
+	panic_timeout = 180;
 	
-	switch (_machine)
-	{
+	init_task.mm->start_code = PAGE_OFFSET;
+	init_task.mm->end_code = (unsigned long) _etext;
+	init_task.mm->end_data = (unsigned long) _edata;
+	init_task.mm->brk = (unsigned long) klimit;	
+
+	/* Save unparsed command line copy for /proc/cmdline */
+	strcpy(saved_command_line, cmd_line);
+	*cmdline_p = cmd_line;
+
+	*memory_start_p = find_available_memory();
+	*memory_end_p = (unsigned long) end_of_DRAM;
+
+	switch (_machine) {
 	case _MACH_Pmac:
-		pmac_setup_arch(cmdline_p,memory_start_p,memory_end_p);
+		pmac_setup_arch(memory_start_p, memory_end_p);
 		break;
-	case _MACH_Motorola:
-	case _MACH_IBM:
-		prep_setup_arch(cmdline_p,memory_start_p,memory_end_p);
+	case _MACH_prep:
+		prep_setup_arch(memory_start_p, memory_end_p);
 		break;
 	case _MACH_chrp:
-		return chrp_setup_arch(cmdline_p,memory_start_p,memory_end_p);
+		chrp_setup_arch(memory_start_p, memory_end_p);
 		break;
+	default:
+		printk("Unknown machine %d in setup_arch()\n", _machine);
 	}
-	printk("Unknown machine %d in setup_arch()\n",_machine);
 }
-
-
-

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov