prep_setup.c

来自「是关于linux2.5.1的完全源码」· C语言 代码 · 共 941 行 · 第 1/2 页

C
941
字号
/* * BK Id: %F% %I% %G% %U% %#% *//* *  arch/ppc/platforms/setup.c * *  Copyright (C) 1995  Linus Torvalds *  Adapted from 'alpha' version by Gary Thomas *  Modified by Cort Dougan (cort@cs.nmt.edu) * * Support for PReP (Motorola MTX/MVME) * by Troy Benjegerdes (hozer@drgw.net) *//* * bootup setup stuff.. */#include <linux/config.h>#include <linux/delay.h>#include <linux/module.h>#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/slab.h>#include <linux/user.h>#include <linux/a.out.h>#include <linux/tty.h>#include <linux/major.h>#include <linux/interrupt.h>#include <linux/reboot.h>#include <linux/init.h>#include <linux/blk.h>#include <linux/ioport.h>#include <linux/console.h>#include <linux/timex.h>#include <linux/pci.h>#include <linux/ide.h>#include <linux/seq_file.h>#include <asm/sections.h>#include <asm/mmu.h>#include <asm/processor.h>#include <asm/residual.h>#include <asm/io.h>#include <asm/pgtable.h>#include <asm/cache.h>#include <asm/dma.h>#include <asm/machdep.h>#include <asm/mk48t59.h>#include <asm/prep_nvram.h>#include <asm/raven.h>#include <asm/keyboard.h>#include <asm/vga.h>#include <asm/time.h>#include <asm/i8259.h>#include <asm/open_pic.h>unsigned char ucSystemType;unsigned char ucBoardRev;unsigned char ucBoardRevMaj, ucBoardRevMin;extern unsigned long mc146818_get_rtc_time(void);extern int mc146818_set_rtc_time(unsigned long nowtime);extern unsigned long mk48t59_get_rtc_time(void);extern int mk48t59_set_rtc_time(unsigned long nowtime);extern unsigned char prep_nvram_read_val(int addr);extern void prep_nvram_write_val(int addr,				 unsigned char val);extern unsigned char rs_nvram_read_val(int addr);extern void rs_nvram_write_val(int addr,				 unsigned char val);extern void ibm_prep_init(void);extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);extern int pckbd_getkeycode(unsigned int scancode);extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,		char raw_mode);extern char pckbd_unexpected_up(unsigned char keycode);extern void pckbd_leds(unsigned char leds);extern void pckbd_init_hw(void);extern unsigned char pckbd_sysrq_xlate[];extern void prep_find_bridges(void);extern char saved_command_line[];int _prep_type;#define cached_21	(((char *)(ppc_cached_irq_mask))[3])#define cached_A1	(((char *)(ppc_cached_irq_mask))[2])/* for the mac fs */kdev_t boot_dev;#ifdef CONFIG_SOUND_CS4232 long ppc_cs4232_dma, ppc_cs4232_dma2;#endifextern PTE *Hash, *Hash_end;extern unsigned long Hash_size, Hash_mask;extern int probingmem;extern unsigned long loops_per_jiffy;#ifdef CONFIG_SOUND_CS4232 EXPORT_SYMBOL(ppc_cs4232_dma);EXPORT_SYMBOL(ppc_cs4232_dma2);#endifstatic int __prepprep_show_cpuinfo(struct seq_file *m){	extern char *Motherboard_map_name;	int cachew;#ifdef CONFIG_PREP_RESIDUAL	int i;#endif	seq_printf(m, "machine\t\t: PReP %s\n", Motherboard_map_name);	switch ( _prep_type ) {	case _PREP_IBM:		cachew = inw(0x80c);		if (cachew & (1<<6))			seq_printf(m, "Upgrade CPU\n");		seq_printf(m, "L2\t\t: ");		if (cachew & (1<<7)) {			seq_printf(m, "not present\n");			goto no_l2;		}		seq_printf(m, "%sKb,", (cachew & (1 << 10))? "512" : "256");		seq_printf(m, "%ssync\n", (cachew & (1 << 15))? "" : "a");		break;	case _PREP_Motorola:		cachew = *((unsigned char *)CACHECRBA);		seq_printf(m, "L2\t\t: ");		switch (cachew & L2CACHE_MASK) {		case L2CACHE_512KB:			seq_printf(m, "512Kb");			break;		case L2CACHE_256KB:			seq_printf(m, "256Kb");			break;		case L2CACHE_1MB:			seq_printf(m, "1MB");			break;		case L2CACHE_NONE:			seq_printf(m, "none\n");			goto no_l2;			break;		default:			seq_printf(m, "%x\n", cachew);		}				seq_printf(m, ", parity %s",			   (cachew & L2CACHE_PARITY)? "enabled" : "disabled");		seq_printf(m, " SRAM:");				switch ( ((cachew & 0xf0) >> 4) & ~(0x3) ) {		case 1: seq_printf(m, "synchronous,parity,flow-through\n");			break;		case 2: seq_printf(m, "asynchronous,no parity\n");			break;		case 3: seq_printf(m, "asynchronous,parity\n");			break;		default:seq_printf(m, "synchronous,pipelined,no parity\n");			break;		}		break;	default:		break;	}no_l2:#ifdef CONFIG_PREP_RESIDUAL	if (res->ResidualLength != 0) {		/* print info about SIMMs */		seq_printf(m, "simms\t\t: ");		for (i = 0; (res->ActualNumMemories) && (i < MAX_MEMS); i++) {			if (res->Memories[i].SIMMSize != 0)				seq_printf(m, "%d:%ldM ", i,					(res->Memories[i].SIMMSize > 1024) ? 					res->Memories[i].SIMMSize>>20 : 					res->Memories[i].SIMMSize);		}		seq_printf(m, "\n");	}#endif	return 0;}static int __prepprep_show_percpuinfo(struct seq_file *m, int i){	/* PREP's without residual data will give incorrect values here */	seq_printf(m, "clock\t\t: ");#ifdef CONFIG_PREP_RESIDUAL		if (res->ResidualLength)		seq_printf(m, "%ldMHz\n",			   (res->VitalProductData.ProcessorHz > 1024) ?			   res->VitalProductData.ProcessorHz / 1000000 :			   res->VitalProductData.ProcessorHz);	else#endif /* CONFIG_PREP_RESIDUAL */		seq_printf(m, "???\n");	return 0;}#ifdef CONFIG_SOUND_CS4232 static long __init masktoint(unsigned int i){	int t = -1;	while (i >> ++t)		;	return (t-1);}/* * ppc_cs4232_dma and ppc_cs4232_dma2 are used in include/asm/dma.h * to distinguish sound dma-channels from others. This is because  * blocksize on 16 bit dma-channels 5,6,7 is 128k, but * the cs4232.c uses 64k like on 8 bit dma-channels 0,1,2,3 */static void __init prep_init_sound(void){	PPC_DEVICE *audiodevice = NULL;	/*	 * Get the needed resource informations from residual data.	 * 	 */#ifdef CONFIG_PREP_RESIDUAL	audiodevice = residual_find_device(~0, NULL, MultimediaController,			AudioController, -1, 0);	if (audiodevice != NULL) {		PnP_TAG_PACKET *pkt;		pkt = PnP_find_packet((unsigned char *)&res->DevicePnPHeap[audiodevice->AllocatedOffset],				S5_Packet, 0);		if (pkt != NULL)			ppc_cs4232_dma = masktoint(pkt->S5_Pack.DMAMask);		pkt = PnP_find_packet((unsigned char*)&res->DevicePnPHeap[audiodevice->AllocatedOffset],				S5_Packet, 1);		if (pkt != NULL)			ppc_cs4232_dma2 = masktoint(pkt->S5_Pack.DMAMask);	}#endif	/*	 * These are the PReP specs' defaults for the cs4231.  We use these	 * as fallback incase we don't have residual data.	 * At least the IBM Thinkpad 850 with IDE DMA Channels at 6 and 7 	 * will use the other values.	 */	if (audiodevice == NULL) {		switch (_prep_type) {		case _PREP_IBM:			ppc_cs4232_dma = 1;			ppc_cs4232_dma2 = -1;			break;		default: 			ppc_cs4232_dma = 6;			ppc_cs4232_dma2 = 7;		}	}	/*	 * Find a way to push these informations to the cs4232 driver	 * Give it out with printk, when not in cmd_line?	 * Append it to  cmd_line and saved_command_line?	 * Format is cs4232=io,irq,dma,dma2	 */}#endif /* CONFIG_SOUND_CS4232 *//* * Fill out screen_info according to the residual data. This allows us to use * at least vesafb. */static void __initprep_init_vesa(void){#if defined(CONFIG_PREP_RESIDUAL) && \	(defined(CONFIG_FB_VGA16) || defined(CONFIG_FB_VGA_16_MODULE) || \	 defined(CONFIG_FB_VESA))	PPC_DEVICE *vgadev;	vgadev = residual_find_device(~0, NULL, DisplayController, SVGAController,									-1, 0);	if (vgadev != NULL) {		PnP_TAG_PACKET *pkt;		pkt = PnP_find_large_vendor_packet(				(unsigned char *)&res->DevicePnPHeap[vgadev->AllocatedOffset],				0x04, 0); /* 0x04 = Display Tag */		if (pkt != NULL) {			unsigned char *ptr = (unsigned char *)pkt;			if (ptr[4]) {				/* graphics mode */				screen_info.orig_video_isVGA = VIDEO_TYPE_VLFB;				screen_info.lfb_depth = ptr[4] * 8;				screen_info.lfb_width = swab16(*(short *)(ptr+6));				screen_info.lfb_height = swab16(*(short *)(ptr+8));				screen_info.lfb_linelength = swab16(*(short *)(ptr+10));				screen_info.lfb_base = swab32(*(long *)(ptr+12));				screen_info.lfb_size = swab32(*(long *)(ptr+20)) / 65536;			}		}	}#endif /* CONFIG_PREP_RESIDUAL */}static void __initprep_setup_arch(void){	unsigned char reg;	/* init to some ~sane value until calibrate_delay() runs */	loops_per_jiffy = 50000000;		/* Lookup PCI host bridges */	prep_find_bridges();		/* Set up floppy in PS/2 mode */	outb(0x09, SIO_CONFIG_RA);	reg = inb(SIO_CONFIG_RD);	reg = (reg & 0x3F) | 0x40;	outb(reg, SIO_CONFIG_RD);	outb(reg, SIO_CONFIG_RD);	/* Have to write twice to change! */	/* we should determine this according to what we find! -- Cort */	switch ( _prep_type )	{	case _PREP_IBM:		/* Enable L2.  Assume we don't need to flush -- Cort*/		*(unsigned char *)(0x8000081c) |= 3;		ROOT_DEV = to_kdev_t(0x0301); /* hda1 */		break;	case _PREP_Motorola:		/* Enable L2.  Assume we don't need to flush -- Cort*/		*(unsigned char *)(0x8000081c) |= 3;#ifdef CONFIG_BLK_DEV_INITRD		if (initrd_start)			ROOT_DEV = mk_kdev(RAMDISK_MAJOR, 0); /* /dev/ram */		else#endif#ifdef CONFIG_ROOT_NFS			ROOT_DEV = to_kdev_t(0x00ff); /* /dev/nfs */#else			ROOT_DEV = to_kdev_t(0x0802); /* /dev/sda2 */#endif		break;	}	/* Read in NVRAM data */ 	init_prep_nvram();	/* if no bootargs, look in NVRAM */	if ( cmd_line[0] == '\0' ) {		char *bootargs;		 bootargs = prep_nvram_get_var("bootargs");		 if (bootargs != NULL) {			 strcpy(cmd_line, bootargs);			 /* again.. */			 strcpy(saved_command_line, cmd_line);		}	}#ifdef CONFIG_SOUND_CS4232 	prep_init_sound();#endif /* CONFIG_SOUND_CS4232 */	prep_init_vesa();	switch (_prep_type) {	case _PREP_Motorola:		raven_init();		break;	case _PREP_IBM:		ibm_prep_init();		break;	}#ifdef CONFIG_VGA_CONSOLE	/* vgacon.c needs to know where we mapped IO memory in io_block_mapping() */	vgacon_remap_base = 0xf0000000;	conswitchp = &vga_con;#elif defined(CONFIG_DUMMY_CONSOLE)	conswitchp = &dummy_con;#endif}/* * Determine the decrementer frequency from the residual data * This allows for a faster boot as we do not need to calibrate the * decrementer against another clock. This is important for embedded systems. */static int __initprep_res_calibrate_decr(void){#ifdef CONFIG_PREP_RESIDUAL	unsigned long freq, divisor = 4;	if ( res->VitalProductData.ProcessorBusHz ) {		freq = res->VitalProductData.ProcessorBusHz;		printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",				(freq/divisor)/1000000,				(freq/divisor)%1000000);		tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000);		tb_ticks_per_jiffy = freq / HZ / divisor;		return 0;	} else#endif			return 1;}/* * Uses the on-board timer to calibrate the on-chip decrementer register * for prep systems.  On the pmac the OF tells us what the frequency is * but on prep we have to figure it out. * -- Cort *//* Done with 3 interrupts: the first one primes the cache and the * 2 following ones measure the interval. The precision of the method * is still doubtful due to the short interval sampled. */static volatile int calibrate_steps __initdata = 3;static unsigned tbstamp __initdata = 0;static void __initprep_calibrate_decr_handler(int irq, void *dev, struct pt_regs *regs){	unsigned long t, freq;	int step=--calibrate_steps;	t = get_tbl();	if (step > 0) {		tbstamp = t;	} else {		freq = (t - tbstamp)*HZ;		printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",			 freq/1000000, freq%1000000);		tb_ticks_per_jiffy = freq / HZ;		tb_to_us = mulhwu_scale_factor(freq, 1000000);	}}static void __initprep_calibrate_decr(void){	int res;	/* Try and get this from the residual data. */	res = prep_res_calibrate_decr();	/* If we didn't get it from the residual data, try this. */	if ( res ) {		unsigned long flags;

⌨️ 快捷键说明

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