setup.c revision 8df32c636e785069ba7d223ceb9b72c182902295
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This file is subject to the terms and conditions of the GNU General Public
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * License.  See the file "COPYING" in the main directory of this archive
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for more details.
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1995 Linus Torvalds
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1995 Waldorf Electronics
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1994, 95, 96, 97, 98, 99, 2000, 01, 02, 03  Ralf Baechle
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1996 Stoned Elipot
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1999 Silicon Graphics, Inc.
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2000 2001, 2002  Maciej W. Rozycki
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h>
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
16894673ee6122a3ce1958e1fe096901ba5356a96bJon Smirl#include <linux/screen_info.h>
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/bootmem.h>
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/initrd.h>
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/root_dev.h>
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/highmem.h>
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/console.h>
2222a9835c350782a5c3257343713932af3ac92ee0Dave Hansen#include <linux/pfn.h>
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/addrspace.h>
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/bootinfo.h>
26ec74e361f1e71a2498e48b62abdc4bd8d2423354Ralf Baechle#include <asm/cache.h>
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/cpu.h>
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/sections.h>
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/setup.h>
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/system.h>
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32ec74e361f1e71a2498e48b62abdc4bd8d2423354Ralf Baechlestruct cpuinfo_mips cpu_data[NR_CPUS] __read_mostly;
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(cpu_data);
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_VT
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct screen_info screen_info;
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Despite it's name this variable is even if we don't have PCI
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunsigned int PCI_DMA_BUS_IS_PHYS;
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(PCI_DMA_BUS_IS_PHYS);
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Setup information
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * These are initialized so they are in the .data section
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
52ec74e361f1e71a2498e48b62abdc4bd8d2423354Ralf Baechleunsigned long mips_machtype __read_mostly = MACH_UNKNOWN;
53ec74e361f1e71a2498e48b62abdc4bd8d2423354Ralf Baechleunsigned long mips_machgroup __read_mostly = MACH_GROUP_UNKNOWN;
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(mips_machtype);
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(mips_machgroup);
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct boot_mem_map boot_mem_map;
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char command_line[CL_SIZE];
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds       char arcs_cmdline[CL_SIZE]=CONFIG_CMDLINE;
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * mips_io_port_base is the begin of the address space to which x86 style
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * I/O ports are mapped.
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
67ec74e361f1e71a2498e48b62abdc4bd8d2423354Ralf Baechleconst unsigned long mips_io_port_base __read_mostly = -1;
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(mips_io_port_base);
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * isa_slot_offset is the address where E(ISA) busaddress 0 is mapped
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for the processor.
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunsigned long isa_slot_offset;
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(isa_slot_offset);
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct resource code_resource = { .name = "Kernel code", };
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct resource data_resource = { .name = "Kernel data", };
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __init add_memory_region(phys_t start, phys_t size, long type)
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int x = boot_mem_map.nr_map;
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct boot_mem_map_entry *prev = boot_mem_map.map + x - 1;
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
85b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu	/* Sanity check */
86b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu	if (start + size < start) {
87b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu		printk("Trying to add an invalid memory region, skipped\n");
88b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu		return;
89b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu	}
90b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Try to merge with previous entry if any.  This is far less than
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * perfect but is sufficient for most real world cases.
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (x && prev->addr + prev->size == start && prev->type == type) {
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		prev->size += size;
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (x == BOOT_MEM_MAP_MAX) {
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("Ooops! Too many entries in the memory map!\n");
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	boot_mem_map.map[x].addr = start;
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	boot_mem_map.map[x].size = size;
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	boot_mem_map.map[x].type = type;
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	boot_mem_map.nr_map++;
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __init print_memory_map(void)
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const int field = 2 * sizeof(unsigned long);
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < boot_mem_map.nr_map; i++) {
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(" memory: %0*Lx @ %0*Lx ",
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       field, (unsigned long long) boot_mem_map.map[i].size,
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       field, (unsigned long long) boot_mem_map.map[i].addr);
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch (boot_mem_map.map[i].type) {
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case BOOT_MEM_RAM:
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk("(usable)\n");
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case BOOT_MEM_ROM_DATA:
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk("(ROM data)\n");
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case BOOT_MEM_RESERVED:
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk("(reserved)\n");
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk("type %lu\n", boot_mem_map.map[i].type);
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1388df32c636e785069ba7d223ceb9b72c182902295Franck Bui-Huustatic void __init parse_cmdline_early(void)
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char c = ' ', *to = command_line, *from = saved_command_line;
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long start_at, mem_size;
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int len = 0;
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int usermem = 0;
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("Determined physical RAM map:\n");
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	print_memory_map();
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (;;) {
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * "mem=XXX[kKmM]" defines a memory region from
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * 0 to <XXX>, overriding the determined size.
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * "mem=XXX[KkmM]@YYY[KkmM]" defines a memory region from
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * <YYY> to <YYY>+<XXX>, overriding the determined size.
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (c == ' ' && !memcmp(from, "mem=", 4)) {
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (to != command_line)
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				to--;
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * If a user specifies memory size, we
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * blow away any automatically generated
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * size.
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (usermem == 0) {
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				boot_mem_map.nr_map = 0;
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				usermem = 1;
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mem_size = memparse(from + 4, &from);
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (*from == '@')
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				start_at = memparse(from + 1, &from);
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				start_at = 0;
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			add_memory_region(start_at, mem_size, BOOT_MEM_RAM);
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		c = *(from++);
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!c)
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (CL_SIZE <= ++len)
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*(to++) = c;
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*to = '\0';
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (usermem) {
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("User-defined physical RAM map:\n");
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		print_memory_map();
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
189d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu/*
190d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu * Manage initrd
191d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu */
192d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu#ifdef CONFIG_BLK_DEV_INITRD
193d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu
194d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huustatic int __init parse_rd_cmdline(unsigned long *rd_start, unsigned long *rd_end)
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * "rd_start=0xNNNNNNNN" defines the memory address of an initrd
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * "rd_size=0xNN" it's size
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long start = 0;
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long size = 0;
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long end;
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char cmd_line[CL_SIZE];
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char *start_str;
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char *size_str;
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char *tmp;
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	strcpy(cmd_line, command_line);
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*command_line = 0;
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tmp = cmd_line;
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Ignore "rd_start=" strings in other parameters. */
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	start_str = strstr(cmd_line, "rd_start=");
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (start_str && start_str != cmd_line && *(start_str - 1) != ' ')
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		start_str = strstr(start_str, " rd_start=");
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (start_str) {
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (start_str != cmd_line)
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			strncat(command_line, tmp, start_str - tmp);
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		start = memparse(start_str + 9, &start_str);
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tmp = start_str + 1;
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		start_str = strstr(start_str, " rd_start=");
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (*tmp)
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		strcat(command_line, tmp);
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	strcpy(cmd_line, command_line);
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*command_line = 0;
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tmp = cmd_line;
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Ignore "rd_size" strings in other parameters. */
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	size_str = strstr(cmd_line, "rd_size=");
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (size_str && size_str != cmd_line && *(size_str - 1) != ' ')
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		size_str = strstr(size_str, " rd_size=");
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (size_str) {
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (size_str != cmd_line)
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			strncat(command_line, tmp, size_str - tmp);
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		size = memparse(size_str + 8, &size_str);
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tmp = size_str + 1;
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		size_str = strstr(size_str, " rd_size=");
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (*tmp)
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		strcat(command_line, tmp);
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
242875d43e72b5bf22161a81de7554f88eccf8a51aeRalf Baechle#ifdef CONFIG_64BIT
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* HACK: Guess if the sign extension was forgotten */
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (start > 0x0000000080000000 && start < 0x00000000ffffffff)
245460c0422c3861ab63a14c2be600a96a9e68b89f2Atsushi Nemoto		start |= 0xffffffff00000000UL;
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	end = start + size;
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (start && end) {
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*rd_start = start;
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*rd_end = end;
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 1;
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
257d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huustatic unsigned long __init init_initrd(void)
258d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu{
259d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	unsigned long tmp, end;
260d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	u32 *initrd_header;
261d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu
262d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	ROOT_DEV = Root_RAM0;
263d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu
264d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	if (parse_rd_cmdline(&initrd_start, &initrd_end))
265d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu		return initrd_end;
266d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	/*
267d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	 * Board specific code should have set up initrd_start
268d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	 * and initrd_end...
269d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	 */
270d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	end = (unsigned long)&_end;
271d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	tmp = PAGE_ALIGN(end) - sizeof(u32) * 2;
272d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	if (tmp < end)
273d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu		tmp += PAGE_SIZE;
274d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu
275d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	initrd_header = (u32 *)tmp;
276d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	if (initrd_header[0] == 0x494E5244) {
277d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu		initrd_start = (unsigned long)&initrd_header[2];
278d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu		initrd_end = initrd_start + initrd_header[1];
279d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	}
280d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	return initrd_end;
281d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu}
282d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu
283d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huustatic void __init finalize_initrd(void)
284d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu{
285d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	unsigned long size = initrd_end - initrd_start;
286d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu
287d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	if (size == 0) {
288d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu		printk(KERN_INFO "Initrd not found or empty");
289d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu		goto disable;
290d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	}
291d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	if (CPHYSADDR(initrd_end) > PFN_PHYS(max_low_pfn)) {
292d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu		printk("Initrd extends beyond end of memory");
293d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu		goto disable;
294d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	}
295d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu
296d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	reserve_bootmem(CPHYSADDR(initrd_start), size);
297d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	initrd_below_start_ok = 1;
298d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu
299d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	printk(KERN_INFO "Initial ramdisk at: 0x%lx (%lu bytes)\n",
300d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	       initrd_start, size);
301d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	return;
302d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huudisable:
303d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	printk(" - disabling initrd\n");
304d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	initrd_start = 0;
305d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	initrd_end = 0;
306d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu}
307d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu
308d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu#else  /* !CONFIG_BLK_DEV_INITRD */
309d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu
310d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu#define init_initrd()		0
311d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu#define finalize_initrd()	do {} while (0)
312d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu
313d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu#endif
314d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu
315b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu/*
316b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu * Initialize the bootmem allocator. It also setup initrd related data
317b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu * if needed.
318b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu */
319d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu#ifdef CONFIG_SGI_IP27
320d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu
321b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huustatic void __init bootmem_init(void)
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
323d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	init_initrd();
324d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	finalize_initrd();
325d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu}
326d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu
327d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu#else  /* !CONFIG_SGI_IP27 */
328d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu
329d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huustatic void __init bootmem_init(void)
330d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu{
331d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	unsigned long reserved_end;
332b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu	unsigned long highest = 0;
333b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu	unsigned long mapstart = -1UL;
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long bootmap_size;
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
338d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	 * Init any data related to initrd. It's a nop if INITRD is
339d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	 * not selected. Once that done we can determine the low bound
340d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	 * of usable memory.
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
342d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	reserved_end = init_initrd();
343d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	reserved_end = PFN_UP(CPHYSADDR(max(reserved_end, (unsigned long)&_end)));
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
345b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu	/*
346b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu	 * Find the highest page frame number we have available.
347b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu	 */
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < boot_mem_map.nr_map; i++) {
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned long start, end;
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (boot_mem_map.map[i].type != BOOT_MEM_RAM)
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		start = PFN_UP(boot_mem_map.map[i].addr);
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		end = PFN_DOWN(boot_mem_map.map[i].addr
356b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu				+ boot_mem_map.map[i].size);
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
358b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu		if (end > highest)
359b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu			highest = end;
360b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu		if (end <= reserved_end)
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
362b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu		if (start >= mapstart)
363b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu			continue;
364b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu		mapstart = max(reserved_end, start);
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Determine low and high memory ranges
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
370b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu	if (highest > PFN_DOWN(HIGHMEM_START)) {
371b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu#ifdef CONFIG_HIGHMEM
372b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu		highstart_pfn = PFN_DOWN(HIGHMEM_START);
373b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu		highend_pfn = highest;
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
375b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu		highest = PFN_DOWN(HIGHMEM_START);
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
379b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu	 * Initialize the boot-time allocator with low memory only.
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
381b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu	bootmap_size = init_bootmem(mapstart, highest);
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Register fully available low RAM pages with the bootmem allocator.
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < boot_mem_map.nr_map; i++) {
387b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu		unsigned long start, end, size;
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Reserve usable memory.
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (boot_mem_map.map[i].type != BOOT_MEM_RAM)
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
395b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu		start = PFN_UP(boot_mem_map.map[i].addr);
396b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu		end   = PFN_DOWN(boot_mem_map.map[i].addr
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    + boot_mem_map.map[i].size);
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
399b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu		 * We are rounding up the start address of usable memory
400b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu		 * and at the end of the usable range downwards.
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
402b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu		if (start >= max_low_pfn)
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
404b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu		if (start < reserved_end)
405b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu			start = reserved_end;
406b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu		if (end > max_low_pfn)
407b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu			end = max_low_pfn;
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
410b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu		 * ... finally, is the area going away?
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
412b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu		if (end <= start)
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
414b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu		size = end - start;
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Register lowmem ranges */
417b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu		free_bootmem(PFN_PHYS(start), size << PAGE_SHIFT);
418b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu		memory_present(0, start, end);
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
421b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu	/*
422b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu	 * Reserve the bootmap memory.
423b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu	 */
424b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu	reserve_bootmem(PFN_PHYS(mapstart), bootmap_size);
425b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu
426d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	/*
427d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	 * Reserve initrd memory if needed.
428d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	 */
429d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu	finalize_initrd();
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
432d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu#endif	/* CONFIG_SGI_IP27 */
433d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu
4342925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle/*
4352925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * arch_mem_init - initialize memory managment subsystem
4362925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle *
4372925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle *  o plat_mem_setup() detects the memory configuration and will record detected
4382925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle *    memory areas using add_memory_region.
4392925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle *  o parse_cmdline_early() parses the command line for mem= options which,
4402925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle *    iff detected, will override the results of the automatic detection.
4412925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle *
4422925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * At this stage the memory configuration of the system is known to the
4432925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * kernel but generic memory managment system is still entirely uninitialized.
4442925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle *
4452925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle *  o bootmem_init()
4462925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle *  o sparse_init()
4472925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle *  o paging_init()
4482925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle *
4492925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * At this stage the bootmem allocator is ready to use.
4502925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle *
4512925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * NOTE: historically plat_mem_setup did the entire platform initialization.
4522925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle *       This was rather impractical because it meant plat_mem_setup had to
4532925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * get away without any kind of memory allocator.  To keep old code from
4542925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * breaking plat_setup was just renamed to plat_setup and a second platform
4552925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * initialization hook for anything else was introduced.
4562925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle */
4572925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle
4582925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechleextern void plat_mem_setup(void);
4592925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle
4602925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechlestatic void __init arch_mem_init(char **cmdline_p)
4612925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle{
4622925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle	/* call board setup routine */
4632925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle	plat_mem_setup();
4642925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle
4652925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle	strlcpy(command_line, arcs_cmdline, sizeof(command_line));
4662925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle	strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
4672925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle
4682925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle	*cmdline_p = command_line;
4692925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle
4702925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle	parse_cmdline_early();
4712925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle	bootmem_init();
4722925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle	sparse_init();
4732925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle	paging_init();
4742925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle}
4752925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle
476b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu#define MAXMEM		HIGHMEM_START
477b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu#define MAXMEM_PFN	PFN_DOWN(MAXMEM)
478b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu
4798df32c636e785069ba7d223ceb9b72c182902295Franck Bui-Huustatic void __init resource_init(void)
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4836adb5fe7020e8f99d27da932157ea27325df9263Ralf Baechle	if (UNCAC_BASE != IO_BASE)
4846adb5fe7020e8f99d27da932157ea27325df9263Ralf Baechle		return;
4856adb5fe7020e8f99d27da932157ea27325df9263Ralf Baechle
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	code_resource.start = virt_to_phys(&_text);
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	code_resource.end = virt_to_phys(&_etext) - 1;
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data_resource.start = virt_to_phys(&_etext);
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data_resource.end = virt_to_phys(&_edata) - 1;
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Request address space for all standard RAM.
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < boot_mem_map.nr_map; i++) {
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct resource *res;
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned long start, end;
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		start = boot_mem_map.map[i].addr;
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		end = boot_mem_map.map[i].addr + boot_mem_map.map[i].size - 1;
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (start >= MAXMEM)
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (end >= MAXMEM)
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			end = MAXMEM - 1;
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		res = alloc_bootmem(sizeof(struct resource));
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch (boot_mem_map.map[i].type) {
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case BOOT_MEM_RAM:
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case BOOT_MEM_ROM_DATA:
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			res->name = "System RAM";
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case BOOT_MEM_RESERVED:
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			res->name = "reserved";
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		res->start = start;
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		res->end = end;
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		request_resource(&iomem_resource, res);
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 *  We don't know which RAM region contains kernel data,
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 *  so we try it repeatedly and let the resource manager
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 *  test it.
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		request_resource(res, &code_resource);
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		request_resource(res, &data_resource);
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef MAXMEM
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef MAXMEM_PFN
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __init setup_arch(char **cmdline_p)
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cpu_probe();
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	prom_init();
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cpu_report();
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if defined(CONFIG_VT)
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if defined(CONFIG_VGA_CONSOLE)
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        conswitchp = &vga_con;
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#elif defined(CONFIG_DUMMY_CONSOLE)
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        conswitchp = &dummy_con;
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5492925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle	arch_mem_init(cmdline_p);
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	resource_init();
5529b6695a8adfe0916e81ddd810a5b9db3eb8b0e46Ralf Baechle#ifdef CONFIG_SMP
5539b6695a8adfe0916e81ddd810a5b9db3eb8b0e46Ralf Baechle	plat_smp_setup();
5549b6695a8adfe0916e81ddd810a5b9db3eb8b0e46Ralf Baechle#endif
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint __init fpu_disable(char *s)
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
559f088fc84f94c1a36943e28ad704a9a740a35f877Ralf Baechle	int i;
560f088fc84f94c1a36943e28ad704a9a740a35f877Ralf Baechle
561f088fc84f94c1a36943e28ad704a9a740a35f877Ralf Baechle	for (i = 0; i < NR_CPUS; i++)
562f088fc84f94c1a36943e28ad704a9a740a35f877Ralf Baechle		cpu_data[i].options &= ~MIPS_CPU_FPU;
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 1;
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds__setup("nofpu", fpu_disable);
568e50c0a8fa60da9ac0e0a70caa8a3a803815c1f2fRalf Baechle
569e50c0a8fa60da9ac0e0a70caa8a3a803815c1f2fRalf Baechleint __init dsp_disable(char *s)
570e50c0a8fa60da9ac0e0a70caa8a3a803815c1f2fRalf Baechle{
571e50c0a8fa60da9ac0e0a70caa8a3a803815c1f2fRalf Baechle	cpu_data[0].ases &= ~MIPS_ASE_DSP;
572e50c0a8fa60da9ac0e0a70caa8a3a803815c1f2fRalf Baechle
573e50c0a8fa60da9ac0e0a70caa8a3a803815c1f2fRalf Baechle	return 1;
574e50c0a8fa60da9ac0e0a70caa8a3a803815c1f2fRalf Baechle}
575e50c0a8fa60da9ac0e0a70caa8a3a803815c1f2fRalf Baechle
576e50c0a8fa60da9ac0e0a70caa8a3a803815c1f2fRalf Baechle__setup("nodsp", dsp_disable);
577