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

📄 prom_init.c

📁 是关于linux2.5.1的完全源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Note that prom_init() and anything called from prom_init() * may be running at an address that is different from the address * that it was linked at.  References to static data items are * handled by compiling this file with -mrelocatable-lib. */#include <linux/config.h>#include <linux/kernel.h>#include <linux/string.h>#include <linux/init.h>#include <linux/version.h>#include <linux/threads.h>#include <linux/spinlock.h>#include <linux/ioport.h>#include <linux/pci.h>#include <linux/slab.h>#include <asm/sections.h>#include <asm/prom.h>#include <asm/page.h>#include <asm/processor.h>#include <asm/irq.h>#include <asm/io.h>#include <asm/smp.h>#include <asm/bootx.h>#include <asm/system.h>#include <asm/mmu.h>#include <asm/pgtable.h>#include <asm/bitops.h>#include <asm/bootinfo.h>#include <asm/btext.h>#include <asm/pci-bridge.h>#include <asm/open_pic.h>#include <asm/cacheflush.h>#ifdef CONFIG_FB#include <asm/linux_logo.h>#endif/* * Properties whose value is longer than this get excluded from our * copy of the device tree.  This way we don't waste space storing * things like "driver,AAPL,MacOS,PowerPC" properties.  But this value * does need to be big enough to ensure that we don't lose things * like the interrupt-map property on a PCI-PCI bridge. */#define MAX_PROPERTY_LENGTH	4096#ifndef FB_MAX			/* avoid pulling in all of the fb stuff */#define FB_MAX	8#endif#define ALIGNUL(x) (((x) + sizeof(unsigned long)-1) & -sizeof(unsigned long))struct prom_args {	const char *service;	int nargs;	int nret;	void *args[10];};struct pci_address {	unsigned a_hi;	unsigned a_mid;	unsigned a_lo;};struct pci_reg_property {	struct pci_address addr;	unsigned size_hi;	unsigned size_lo;};struct pci_range {	struct pci_address addr;	unsigned phys;	unsigned size_hi;	unsigned size_lo;};struct isa_reg_property {	unsigned space;	unsigned address;	unsigned size;};struct pci_intr_map {	struct pci_address addr;	unsigned dunno;	phandle int_ctrler;	unsigned intr;};static void prom_exit(void);static void *call_prom(const char *service, int nargs, int nret, ...);static void *call_prom_ret(const char *service, int nargs, int nret,			   void **rets, ...);static void prom_print_hex(unsigned int v);static int  prom_set_color(ihandle ih, int i, int r, int g, int b);static int  prom_next_node(phandle *nodep);static unsigned long check_display(unsigned long mem);static void setup_disp_fake_bi(ihandle dp);static unsigned long copy_device_tree(unsigned long mem_start,				unsigned long mem_end);static unsigned long inspect_node(phandle node, struct device_node *dad,				unsigned long mem_start, unsigned long mem_end,				struct device_node ***allnextpp);static void prom_hold_cpus(unsigned long mem);static void prom_instantiate_rtas(void);static void * early_get_property(unsigned long base, unsigned long node,				char *prop);prom_entry prom __initdata = 0;ihandle prom_chosen __initdata = 0;ihandle prom_stdout __initdata = 0;char *prom_display_paths[FB_MAX] __initdata = { 0, };phandle prom_display_nodes[FB_MAX] __initdata;unsigned int prom_num_displays __initdata = 0;static char *of_stdout_device __initdata = 0;static ihandle prom_disp_node __initdata = 0;unsigned int rtas_data;   /* physical pointer */unsigned int rtas_entry;  /* physical pointer */unsigned int rtas_size;unsigned int old_rtas;boot_infos_t *boot_infos;char *bootpath;char *bootdevice;struct device_node *allnodes;extern char *klimit;extern char _stext;static void __initprom_exit(void){	struct prom_args args;	args.service = "exit";	args.nargs = 0;	args.nret = 0;	prom(&args);	for (;;)			/* should never get here */		;}static void * __initcall_prom(const char *service, int nargs, int nret, ...){	va_list list;	int i;	struct prom_args prom_args;	prom_args.service = service;	prom_args.nargs = nargs;	prom_args.nret = nret;	va_start(list, nret);	for (i = 0; i < nargs; ++i)		prom_args.args[i] = va_arg(list, void *);	va_end(list);	for (i = 0; i < nret; ++i)		prom_args.args[i + nargs] = 0;	prom(&prom_args);	return prom_args.args[nargs];}static void * __initcall_prom_ret(const char *service, int nargs, int nret, void **rets, ...){	va_list list;	int i;	struct prom_args prom_args;	prom_args.service = service;	prom_args.nargs = nargs;	prom_args.nret = nret;	va_start(list, rets);	for (i = 0; i < nargs; ++i)		prom_args.args[i] = va_arg(list, void *);	va_end(list);	for (i = 0; i < nret; ++i)		prom_args.args[i + nargs] = 0;	prom(&prom_args);	for (i = 1; i < nret; ++i)		rets[i-1] = prom_args.args[nargs + i];	return prom_args.args[nargs];}void __initprom_print(const char *msg){	const char *p, *q;	if (prom_stdout == 0)		return;	for (p = msg; *p != 0; p = q) {		for (q = p; *q != 0 && *q != '\n'; ++q)			;		if (q > p)			call_prom("write", 3, 1, prom_stdout, p, q - p);		if (*q != 0) {			++q;			call_prom("write", 3, 1, prom_stdout, "\r\n", 2);		}	}}static void __initprom_print_hex(unsigned int v){	char buf[16];	int i, c;	for (i = 0; i < 8; ++i) {		c = (v >> ((7-i)*4)) & 0xf;		c += (c >= 10)? ('a' - 10): '0';		buf[i] = c;	}	buf[i] = ' ';	buf[i+1] = 0;	prom_print(buf);}static int __initprom_set_color(ihandle ih, int i, int r, int g, int b){	struct prom_args prom_args;	prom_args.service = "call-method";	prom_args.nargs = 6;	prom_args.nret = 1;	prom_args.args[0] = "color!";	prom_args.args[1] = ih;	prom_args.args[2] = (void *) i;	prom_args.args[3] = (void *) b;	prom_args.args[4] = (void *) g;	prom_args.args[5] = (void *) r;	prom(&prom_args);	return (int) prom_args.args[6];}static int __initprom_next_node(phandle *nodep){	phandle node;	if ((node = *nodep) != 0	    && (*nodep = call_prom("child", 1, 1, node)) != 0)		return 1;	if ((*nodep = call_prom("peer", 1, 1, node)) != 0)		return 1;	for (;;) {		if ((node = call_prom("parent", 1, 1, node)) == 0)			return 0;		if ((*nodep = call_prom("peer", 1, 1, node)) != 0)			return 1;	}}/* * If we have a display that we don't know how to drive, * we will want to try to execute OF's open method for it * later.  However, OF will probably fall over if we do that * we've taken over the MMU. * So we check whether we will need to open the display, * and if so, open it now. */static unsigned long __initcheck_display(unsigned long mem){	phandle node;	ihandle ih;	int i;	char type[16], *path;	static unsigned char default_colors[] = {		0x00, 0x00, 0x00,		0x00, 0x00, 0xaa,		0x00, 0xaa, 0x00,		0x00, 0xaa, 0xaa,		0xaa, 0x00, 0x00,		0xaa, 0x00, 0xaa,		0xaa, 0xaa, 0x00,		0xaa, 0xaa, 0xaa,		0x55, 0x55, 0x55,		0x55, 0x55, 0xff,		0x55, 0xff, 0x55,		0x55, 0xff, 0xff,		0xff, 0x55, 0x55,		0xff, 0x55, 0xff,		0xff, 0xff, 0x55,		0xff, 0xff, 0xff	};	prom_disp_node = 0;	for (node = 0; prom_next_node(&node); ) {		type[0] = 0;		call_prom("getprop", 4, 1, node, "device_type",			  type, sizeof(type));		if (strcmp(type, "display") != 0)			continue;		/* It seems OF doesn't null-terminate the path :-( */		path = (char *) mem;		memset(path, 0, 256);		if ((int) call_prom("package-to-path", 3, 1,				    node, path, 255) < 0)			continue;		/*		 * If this display is the device that OF is using for stdout,		 * move it to the front of the list.		 */		mem += strlen(path) + 1;		i = prom_num_displays++;		if (of_stdout_device != 0 && i > 0		    && strcmp(of_stdout_device, path) == 0) {			for (; i > 0; --i) {				prom_display_paths[i]					= prom_display_paths[i-1];				prom_display_nodes[i]					= prom_display_nodes[i-1];			}		}		prom_display_paths[i] = path;		prom_display_nodes[i] = node;		if (i == 0)			prom_disp_node = node;		if (prom_num_displays >= FB_MAX)			break;	}try_again:	/*	 * Open the first display and set its colormap.	 */	if (prom_num_displays > 0) {		path = prom_display_paths[0];		prom_print("opening display ");		prom_print(path);		ih = call_prom("open", 1, 1, path);		if (ih == 0 || ih == (ihandle) -1) {			prom_print("... failed\n");			for (i=1; i<prom_num_displays; i++) {				prom_display_paths[i-1] = prom_display_paths[i];				prom_display_nodes[i-1] = prom_display_nodes[i];			}			if (--prom_num_displays > 0)				prom_disp_node = prom_display_nodes[0];			else				prom_disp_node = NULL;			goto try_again;		} else {			prom_print("... ok\n");			/*			 * Setup a usable color table when the appropriate			 * method is available.			 * Should update this to use set-colors.			 */			for (i = 0; i < 32; i++)				if (prom_set_color(ih, i, default_colors[i*3],						   default_colors[i*3+1],						   default_colors[i*3+2]) != 0)					break;#ifdef CONFIG_FB			for (i = 0; i < LINUX_LOGO_COLORS; i++)				if (prom_set_color(ih, i + 32,						   linux_logo_red[i],						   linux_logo_green[i],						   linux_logo_blue[i]) != 0)					break;#endif /* CONFIG_FB */		}	}	return ALIGNUL(mem);}/* This function will enable the early boot text when doing OF booting. This * way, xmon output should work too */static void __initsetup_disp_fake_bi(ihandle dp){#ifdef CONFIG_BOOTX_TEXT	int width = 640, height = 480, depth = 8, pitch;	unsigned address;	struct pci_reg_property addrs[8];	int i, naddrs;	char name[32];	char *getprop = "getprop";	prom_print("Initializing fake screen: ");	memset(name, 0, sizeof(name));	call_prom(getprop, 4, 1, dp, "name", name, sizeof(name));	name[sizeof(name)-1] = 0;	prom_print(name);	prom_print("\n");	call_prom(getprop, 4, 1, dp, "width", &width, sizeof(width));	call_prom(getprop, 4, 1, dp, "height", &height, sizeof(height));	call_prom(getprop, 4, 1, dp, "depth", &depth, sizeof(depth));	pitch = width * ((depth + 7) / 8);	call_prom(getprop, 4, 1, dp, "linebytes",		  &pitch, sizeof(pitch));	if (pitch == 1)		pitch = 0x1000;		/* for strange IBM display */	address = 0;	call_prom(getprop, 4, 1, dp, "address",		  &address, sizeof(address));	if (address == 0) {		/* look for an assigned address with a size of >= 1MB */		naddrs = (int) call_prom(getprop, 4, 1, dp,				"assigned-addresses",				addrs, sizeof(addrs));		naddrs /= sizeof(struct pci_reg_property);		for (i = 0; i < naddrs; ++i) {			if (addrs[i].size_lo >= (1 << 20)) {				address = addrs[i].addr.a_lo;				/* use the BE aperture if possible */				if (addrs[i].size_lo >= (16 << 20))					address += (8 << 20);				break;			}		}		if (address == 0) {			prom_print("Failed to get address\n");			return;		}	}	/* kludge for valkyrie */	if (strcmp(name, "valkyrie") == 0)		address += 0x1000;	btext_setup_display(width, height, depth, pitch, address);	btext_prepare_BAT();#endif /* CONFIG_BOOTX_TEXT */}/* * Make a copy of the device tree from the PROM. */static unsigned long __initcopy_device_tree(unsigned long mem_start, unsigned long mem_end){	phandle root;

⌨️ 快捷键说明

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