⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 setup.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* *  linux/arch/i386/kernel/setup.c * *  Copyright (C) 1995  Linus Torvalds * *  Enhanced CPU type detection by Mike Jagdis, Patrick St. Jean *  and Martin Mares, November 1997. * *  Force Cyrix 6x86(MX) and M II processors to report MTRR capability *  and Cyrix "coma bug" recognition by *      Zolt醤 B鰏z鰎m閚yi <zboszor@mail.externet.hu> February 1999. *  *  Force Centaur C6 processors to report MTRR capability. *      Bart Hartgers <bart@etpmod.phys.tue.nl>, May 1999. * *  Intel Mobile Pentium II detection fix. Sean Gilley, June 1999. * *  IDT Winchip tweaks, misc clean ups. *	Dave Jones <davej@suse.de>, August 1999 * *  Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999 * *  Better detection of Centaur/IDT WinChip models. *      Bart Hartgers <bart@etpmod.phys.tue.nl>, August 1999. * *  Memory region support *	David Parsons <orc@pell.chi.il.us>, July-August 1999 * *  Cleaned up cache-detection code *	Dave Jones <davej@suse.de>, October 1999 * *	Added proper L2 cache detection for Coppermine *	Dragan Stancevic <visitor@valinux.com>, October 1999 * *  Added the original array for capability flags but forgot to credit  *  myself :) (~1998) Fixed/cleaned up some cpu_model_info and other stuff *  	Jauder Ho <jauderho@carumba.com>, January 2000 * *  Detection for Celeron coppermine, identify_cpu() overhauled, *  and a few other clean ups. *  Dave Jones <davej@suse.de>, April 2000 * *  Pentium III FXSR, SSE support *  General FPU state handling cleanups *	Gareth Hughes <gareth@valinux.com>, May 2000 * *  Added proper Cascades CPU and L2 cache detection for Cascades *  and 8-way type cache happy bunch from Intel:^) *  Dragan Stancevic <visitor@valinux.com>, May 2000  * *  Forward port AMD Duron errata T13 from 2.2.17pre *  Dave Jones <davej@suse.de>, August 2000 * *  Forward port lots of fixes/improvements from 2.2.18pre *  Cyrix III, Pentium IV support. *  Dave Jones <davej@suse.de>, October 2000 * *  Massive cleanup of CPU detection and bug handling; *  Transmeta CPU detection, *  H. Peter Anvin <hpa@zytor.com>, November 2000 *//* * This file handles the architecture-dependent parts of initialization */#include <linux/errno.h>#include <linux/sched.h>#include <linux/kernel.h>#include <linux/mm.h>#include <linux/stddef.h>#include <linux/unistd.h>#include <linux/ptrace.h>#include <linux/malloc.h>#include <linux/user.h>#include <linux/a.out.h>#include <linux/tty.h>#include <linux/ioport.h>#include <linux/delay.h>#include <linux/config.h>#include <linux/init.h>#include <linux/apm_bios.h>#ifdef CONFIG_BLK_DEV_RAM#include <linux/blk.h>#endif#include <linux/highmem.h>#include <linux/bootmem.h>#include <asm/processor.h>#include <linux/console.h>#include <asm/uaccess.h>#include <asm/system.h>#include <asm/io.h>#include <asm/smp.h>#include <asm/cobalt.h>#include <asm/msr.h>#include <asm/desc.h>#include <asm/e820.h>#include <asm/dma.h>#include <asm/mpspec.h>#include <asm/mmu_context.h>/* * Machine setup.. */char ignore_irq13;		/* set if exception 16 works */struct cpuinfo_x86 boot_cpu_data = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };unsigned long mmu_cr4_features;/* * Bus types .. */#ifdef CONFIG_EISAint EISA_bus;#endifint MCA_bus;/* for MCA, but anyone else can use it if they want */unsigned int machine_id;unsigned int machine_submodel_id;unsigned int BIOS_revision;unsigned int mca_pentium_flag;/* * Setup options */struct drive_info_struct { char dummy[32]; } drive_info;struct screen_info screen_info;struct apm_info apm_info;struct sys_desc_table_struct {	unsigned short length;	unsigned char table[0];};struct e820map e820;unsigned char aux_device_present;#ifdef CONFIG_BLK_DEV_RAMextern int rd_doload;		/* 1 = load ramdisk, 0 = don't load */extern int rd_prompt;		/* 1 = prompt for ramdisk, 0 = don't prompt */extern int rd_image_start;	/* starting block # of image */#endifextern int root_mountflags;extern char _text, _etext, _edata, _end;extern unsigned long cpu_khz;static int disable_x86_serial_nr __initdata = 1;/* * This is set up by the setup-routine at boot-time */#define PARAM	((unsigned char *)empty_zero_page)#define SCREEN_INFO (*(struct screen_info *) (PARAM+0))#define EXT_MEM_K (*(unsigned short *) (PARAM+2))#define ALT_MEM_K (*(unsigned long *) (PARAM+0x1e0))#define E820_MAP_NR (*(char*) (PARAM+E820NR))#define E820_MAP    ((struct e820entry *) (PARAM+E820MAP))#define APM_BIOS_INFO (*(struct apm_bios_info *) (PARAM+0x40))#define DRIVE_INFO (*(struct drive_info_struct *) (PARAM+0x80))#define SYS_DESC_TABLE (*(struct sys_desc_table_struct*)(PARAM+0xa0))#define MOUNT_ROOT_RDONLY (*(unsigned short *) (PARAM+0x1F2))#define RAMDISK_FLAGS (*(unsigned short *) (PARAM+0x1F8))#define ORIG_ROOT_DEV (*(unsigned short *) (PARAM+0x1FC))#define AUX_DEVICE_INFO (*(unsigned char *) (PARAM+0x1FF))#define LOADER_TYPE (*(unsigned char *) (PARAM+0x210))#define KERNEL_START (*(unsigned long *) (PARAM+0x214))#define INITRD_START (*(unsigned long *) (PARAM+0x218))#define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c))#define COMMAND_LINE ((char *) (PARAM+2048))#define COMMAND_LINE_SIZE 256#define RAMDISK_IMAGE_START_MASK  	0x07FF#define RAMDISK_PROMPT_FLAG		0x8000#define RAMDISK_LOAD_FLAG		0x4000	#ifdef	CONFIG_VISWSchar visws_board_type = -1;char visws_board_rev = -1;#define	PIIX_PM_START		0x0F80#define	SIO_GPIO_START		0x0FC0#define	SIO_PM_START		0x0FC8#define	PMBASE			PIIX_PM_START#define	GPIREG0			(PMBASE+0x30)#define	GPIREG(x)		(GPIREG0+((x)/8))#define	PIIX_GPI_BD_ID1		18#define	PIIX_GPI_BD_REG		GPIREG(PIIX_GPI_BD_ID1)#define	PIIX_GPI_BD_SHIFT	(PIIX_GPI_BD_ID1 % 8)#define	SIO_INDEX	0x2e#define	SIO_DATA	0x2f#define	SIO_DEV_SEL	0x7#define	SIO_DEV_ENB	0x30#define	SIO_DEV_MSB	0x60#define	SIO_DEV_LSB	0x61#define	SIO_GP_DEV	0x7#define	SIO_GP_BASE	SIO_GPIO_START#define	SIO_GP_MSB	(SIO_GP_BASE>>8)#define	SIO_GP_LSB	(SIO_GP_BASE&0xff)#define	SIO_GP_DATA1	(SIO_GP_BASE+0)#define	SIO_PM_DEV	0x8#define	SIO_PM_BASE	SIO_PM_START#define	SIO_PM_MSB	(SIO_PM_BASE>>8)#define	SIO_PM_LSB	(SIO_PM_BASE&0xff)#define	SIO_PM_INDEX	(SIO_PM_BASE+0)#define	SIO_PM_DATA	(SIO_PM_BASE+1)#define	SIO_PM_FER2	0x1#define	SIO_PM_GP_EN	0x80static voidvisws_get_board_type_and_rev(void){	int raw;	visws_board_type = (char)(inb_p(PIIX_GPI_BD_REG) & PIIX_GPI_BD_REG)							 >> PIIX_GPI_BD_SHIFT;/* * Get Board rev. * First, we have to initialize the 307 part to allow us access * to the GPIO registers.  Let's map them at 0x0fc0 which is right * after the PIIX4 PM section. */	outb_p(SIO_DEV_SEL, SIO_INDEX);	outb_p(SIO_GP_DEV, SIO_DATA);	/* Talk to GPIO regs. */    	outb_p(SIO_DEV_MSB, SIO_INDEX);	outb_p(SIO_GP_MSB, SIO_DATA);	/* MSB of GPIO base address */	outb_p(SIO_DEV_LSB, SIO_INDEX);	outb_p(SIO_GP_LSB, SIO_DATA);	/* LSB of GPIO base address */	outb_p(SIO_DEV_ENB, SIO_INDEX);	outb_p(1, SIO_DATA);		/* Enable GPIO registers. */    /* * Now, we have to map the power management section to write * a bit which enables access to the GPIO registers. * What lunatic came up with this shit? */	outb_p(SIO_DEV_SEL, SIO_INDEX);	outb_p(SIO_PM_DEV, SIO_DATA);	/* Talk to GPIO regs. */	outb_p(SIO_DEV_MSB, SIO_INDEX);	outb_p(SIO_PM_MSB, SIO_DATA);	/* MSB of PM base address */    	outb_p(SIO_DEV_LSB, SIO_INDEX);	outb_p(SIO_PM_LSB, SIO_DATA);	/* LSB of PM base address */	outb_p(SIO_DEV_ENB, SIO_INDEX);	outb_p(1, SIO_DATA);		/* Enable PM registers. */    /* * Now, write the PM register which enables the GPIO registers. */	outb_p(SIO_PM_FER2, SIO_PM_INDEX);	outb_p(SIO_PM_GP_EN, SIO_PM_DATA);    /* * Now, initialize the GPIO registers. * We want them all to be inputs which is the * power on default, so let's leave them alone. * So, let's just read the board rev! */	raw = inb_p(SIO_GP_DATA1);	raw &= 0x7f;	/* 7 bits of valid board revision ID. */	if (visws_board_type == VISWS_320) {		if (raw < 0x6) {			visws_board_rev = 4;		} else if (raw < 0xc) {			visws_board_rev = 5;		} else {			visws_board_rev = 6;			}	} else if (visws_board_type == VISWS_540) {			visws_board_rev = 2;		} else {			visws_board_rev = raw;		}		printk("Silicon Graphics %s (rev %d)\n",			visws_board_type == VISWS_320 ? "320" :			(visws_board_type == VISWS_540 ? "540" :					"unknown"),					visws_board_rev);	}#endifstatic char command_line[COMMAND_LINE_SIZE];       char saved_command_line[COMMAND_LINE_SIZE];struct resource standard_io_resources[] = {	{ "dma1", 0x00, 0x1f, IORESOURCE_BUSY },	{ "pic1", 0x20, 0x3f, IORESOURCE_BUSY },	{ "timer", 0x40, 0x5f, IORESOURCE_BUSY },	{ "keyboard", 0x60, 0x6f, IORESOURCE_BUSY },	{ "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY },	{ "pic2", 0xa0, 0xbf, IORESOURCE_BUSY },	{ "dma2", 0xc0, 0xdf, IORESOURCE_BUSY },	{ "fpu", 0xf0, 0xff, IORESOURCE_BUSY }};#define STANDARD_IO_RESOURCES (sizeof(standard_io_resources)/sizeof(struct resource))static struct resource code_resource = { "Kernel code", 0x100000, 0 };static struct resource data_resource = { "Kernel data", 0, 0 };static struct resource vram_resource = { "Video RAM area", 0xa0000, 0xbffff, IORESOURCE_BUSY };/* System ROM resources */#define MAXROMS 6static struct resource rom_resources[MAXROMS] = {	{ "System ROM", 0xF0000, 0xFFFFF, IORESOURCE_BUSY },	{ "Video ROM", 0xc0000, 0xc7fff, IORESOURCE_BUSY }};#define romsignature(x) (*(unsigned short *)(x) == 0xaa55)static void __init probe_roms(void){	int roms = 1;	unsigned long base;	unsigned char *romstart;	request_resource(&iomem_resource, rom_resources+0);	/* Video ROM is standard at C000:0000 - C7FF:0000, check signature */	for (base = 0xC0000; base < 0xE0000; base += 2048) {		romstart = bus_to_virt(base);		if (!romsignature(romstart))			continue;		request_resource(&iomem_resource, rom_resources + roms);		roms++;		break;	}	/* Extension roms at C800:0000 - DFFF:0000 */	for (base = 0xC8000; base < 0xE0000; base += 2048) {		unsigned long length;		romstart = bus_to_virt(base);		if (!romsignature(romstart))			continue;		length = romstart[2] * 512;		if (length) {			unsigned int i;			unsigned char chksum;			chksum = 0;			for (i = 0; i < length; i++)				chksum += romstart[i];			/* Good checksum? */			if (!chksum) {				rom_resources[roms].start = base;				rom_resources[roms].end = base + length - 1;				rom_resources[roms].name = "Extension ROM";				rom_resources[roms].flags = IORESOURCE_BUSY;				request_resource(&iomem_resource, rom_resources + roms);				roms++;				if (roms >= MAXROMS)					return;			}		}	}	/* Final check for motherboard extension rom at E000:0000 */	base = 0xE0000;	romstart = bus_to_virt(base);	if (romsignature(romstart)) {		rom_resources[roms].start = base;		rom_resources[roms].end = base + 65535;		rom_resources[roms].name = "Extension ROM";		rom_resources[roms].flags = IORESOURCE_BUSY;		request_resource(&iomem_resource, rom_resources + roms);	}}void __init add_memory_region(unsigned long long start,                                  unsigned long long size, int type){	int x = e820.nr_map;	if (x == E820MAX) {	    printk("Ooops! Too many entries in the memory map!\n");	    return;	}	e820.map[x].addr = start;	e820.map[x].size = size;	e820.map[x].type = type;	e820.nr_map++;} /* add_memory_region */#define E820_DEBUG	1static void __init print_memory_map(char *who){	int i;	for (i = 0; i < e820.nr_map; i++) {		printk(" %s: %016Lx @ %016Lx ", who,			e820.map[i].size, e820.map[i].addr);		switch (e820.map[i].type) {		case E820_RAM:	printk("(usable)\n");				break;		case E820_RESERVED:				printk("(reserved)\n");				break;		case E820_ACPI:				printk("(ACPI data)\n");				break;		case E820_NVS:				printk("(ACPI NVS)\n");				break;		default:	printk("type %lu\n", e820.map[i].type);				break;		}	}}/* * Copy the BIOS e820 map into a safe place. * * Sanity-check it while we're at it.. * * If we're lucky and live on a modern system, the setup code * will have given us a memory map that we can use to properly * set up memory.  If we aren't, we'll fake a memory map. * * We check to see that the memory map contains at least 2 elements * before we'll use it, because the detection code in setup.S may * not be perfect and most every PC known to man has two memory * regions: one from 0 to 640k, and one from 1mb up.  (The IBM * thinkpad 560x, for example, does not cooperate with the memory * detection code.) */static int __init copy_e820_map(struct e820entry * biosmap, int nr_map){	/* Only one memory region (or negative)? Ignore it */	if (nr_map < 2)		return -1;	do {		unsigned long long start = biosmap->addr;		unsigned long long size = biosmap->size;		unsigned long long end = start + size;		unsigned long type = biosmap->type;		/* Overflow in 64 bits? Ignore the memory map. */		if (start > end)			return -1;		/*		 * Some BIOSes claim RAM in the 640k - 1M region.		 * Not right. Fix it up.		 */		if (type == E820_RAM) {			if (start < 0x100000ULL && end > 0xA0000ULL) {				if (start < 0xA0000ULL)					add_memory_region(start, 0xA0000ULL-start, type);				if (end <= 0x100000ULL)					continue;				start = 0x100000ULL;				size = end - start;			}		}		add_memory_region(start, size, type);	} while (biosmap++,--nr_map);	return 0;}/* * Do NOT EVER look at the BIOS memory size location. * It does not work on many machines. */#define LOWMEMSIZE()	(0x9f000)void __init setup_memory_region(void){	char *who = "BIOS-e820";	/*	 * Try to copy the BIOS-supplied E820-map.	 *	 * Otherwise fake a memory map; one section from 0k->640k,	 * the next section from 1mb->appropriate_mem_k	 */	if (copy_e820_map(E820_MAP, E820_MAP_NR) < 0) {		unsigned long mem_size;		/* compare results from other methods and take the greater */		if (ALT_MEM_K < EXT_MEM_K) {			mem_size = EXT_MEM_K;			who = "BIOS-88";		} else {			mem_size = ALT_MEM_K;			who = "BIOS-e801";		}		e820.nr_map = 0;		add_memory_region(0, LOWMEMSIZE(), E820_RAM);		add_memory_region(HIGH_MEMORY, (mem_size << 10) - HIGH_MEMORY, E820_RAM);  	}	printk("BIOS-provided physical RAM map:\n");	print_memory_map(who);} /* setup_memory_region */static inline void parse_mem_cmdline (char ** cmdline_p){	char c = ' ', *to = command_line, *from = COMMAND_LINE;	int len = 0;	int usermem = 0;	/* Save unparsed command line copy for /proc/cmdline */	memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';	for (;;) {		/*		 * "mem=nopentium" disables the 4MB page tables.		 * "mem=XXX[kKmM]" defines a memory region from HIGH_MEM		 * to <mem>, overriding the bios size.		 * "mem=XXX[KkmM]@XXX[KkmM]" defines a memory region from		 * <start> to <start>+<mem>, overriding the bios size.		 */		if (c == ' ' && !memcmp(from, "mem=", 4)) {			if (to != command_line)				to--;			if (!memcmp(from+4, "nopentium", 9)) {				from += 9+4;				clear_bit(X86_FEATURE_PSE, &boot_cpu_data.x86_capability);			} else if (!memcmp(from+4, "exactmap", 8)) {				from += 8+4;				e820.nr_map = 0;				usermem = 1;			} else {				/* If the user specifies memory size, we				 * blow away any automatically generated				 * size				 */				unsigned long start_at, mem_size; 				if (usermem == 0) {					/* first time in: zap the whitelist					 * and reinitialize it with the					 * standard low-memory region.					 */					e820.nr_map = 0;					usermem = 1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -