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

📄 prom.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
}/* This function will enable the early boot text when doing OF booting. This * way, xmon output should work too */#ifdef CONFIG_BOOTX_TEXT__initstatic voidsetup_disp_fake_bi(ihandle dp){	int width = 640, height = 480, depth = 8, pitch;	unsigned address;	boot_infos_t* bi;	unsigned long offset = reloc_offset();	struct pci_reg_property addrs[8];	int i, naddrs;	char name[32];	char *getprop = RELOC("getprop");	prom_print(RELOC("Initializing fake screen: "));	memset(name, 0, sizeof(name));	call_prom(getprop, 4, 1, dp, RELOC("name"), name, sizeof(name));	name[sizeof(name)-1] = 0;	prom_print(name);	prom_print(RELOC("\n"));	call_prom(getprop, 4, 1, dp, RELOC("width"), &width, sizeof(width));	call_prom(getprop, 4, 1, dp, RELOC("height"), &height, sizeof(height));	call_prom(getprop, 4, 1, dp, RELOC("depth"), &depth, sizeof(depth));	pitch = width * ((depth + 7) / 8);	call_prom(getprop, 4, 1, dp, RELOC("linebytes"),		  &pitch, sizeof(pitch));	if (pitch == 1)		pitch = 0x1000;		/* for strange IBM display */	address = 0;	call_prom(getprop, 4, 1, dp, RELOC("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,				RELOC("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(RELOC("Failed to get address\n"));			return;		}	}	/* kludge for valkyrie */	if (strcmp(name, RELOC("valkyrie")) == 0) 		address += 0x1000; 	RELOC(disp_bi) = &fake_bi;	bi = PTRRELOC((&fake_bi));	RELOC(g_loc_X) = 0;	RELOC(g_loc_Y) = 0;	RELOC(g_max_loc_X) = width / 8;	RELOC(g_max_loc_Y) = height / 16;	bi->logicalDisplayBase = (unsigned char *)address;	bi->dispDeviceBase = (unsigned char *)address;	bi->dispDeviceRowBytes = pitch;	bi->dispDeviceDepth = depth;	bi->dispDeviceRect[0] = bi->dispDeviceRect[1] = 0;	bi->dispDeviceRect[2] = width;	bi->dispDeviceRect[3] = height;}#endif__initstatic intprom_next_node(phandle *nodep){	phandle node;	unsigned long offset = reloc_offset();	if ((node = *nodep) != 0	    && (*nodep = call_prom(RELOC("child"), 1, 1, node)) != 0)		return 1;	if ((*nodep = call_prom(RELOC("peer"), 1, 1, node)) != 0)		return 1;	for (;;) {		if ((node = call_prom(RELOC("parent"), 1, 1, node)) == 0)			return 0;		if ((*nodep = call_prom(RELOC("peer"), 1, 1, node)) != 0)			return 1;	}}/* * Make a copy of the device tree from the PROM. */__initstatic unsigned longcopy_device_tree(unsigned long mem_start, unsigned long mem_end){	phandle root;	unsigned long new_start;	struct device_node **allnextp;	unsigned long offset = reloc_offset();	root = call_prom(RELOC("peer"), 1, 1, (phandle)0);	if (root == (phandle)0) {		prom_print(RELOC("couldn't get device tree root\n"));		prom_exit();	}	allnextp = &RELOC(allnodes);	mem_start = ALIGN(mem_start);	new_start = inspect_node(root, 0, mem_start, mem_end, &allnextp);	*allnextp = 0;	return new_start;}__initstatic unsigned longinspect_node(phandle node, struct device_node *dad,	     unsigned long mem_start, unsigned long mem_end,	     struct device_node ***allnextpp){	int l;	phandle child;	struct device_node *np;	struct property *pp, **prev_propp;	char *prev_name, *namep;	unsigned char *valp;	unsigned long offset = reloc_offset();	np = (struct device_node *) mem_start;	mem_start += sizeof(struct device_node);	memset(np, 0, sizeof(*np));	np->node = node;	**allnextpp = PTRUNRELOC(np);	*allnextpp = &np->allnext;	if (dad != 0) {		np->parent = PTRUNRELOC(dad);		/* we temporarily use the `next' field as `last_child'. */		if (dad->next == 0)			dad->child = PTRUNRELOC(np);		else			dad->next->sibling = PTRUNRELOC(np);		dad->next = np;	}	/* get and store all properties */	prev_propp = &np->properties;	prev_name = RELOC("");	for (;;) {		pp = (struct property *) mem_start;		namep = (char *) (pp + 1);		pp->name = PTRUNRELOC(namep);		if ((int) call_prom(RELOC("nextprop"), 3, 1, node, prev_name,				    namep) <= 0)			break;		mem_start = ALIGN((unsigned long)namep + strlen(namep) + 1);		prev_name = namep;		valp = (unsigned char *) mem_start;		pp->value = PTRUNRELOC(valp);		pp->length = (int)			call_prom(RELOC("getprop"), 4, 1, node, namep,				  valp, mem_end - mem_start);		if (pp->length < 0)			continue;#ifdef MAX_PROPERTY_LENGTH		if (pp->length > MAX_PROPERTY_LENGTH)			continue; /* ignore this property */#endif		mem_start = ALIGN(mem_start + pp->length);		*prev_propp = PTRUNRELOC(pp);		prev_propp = &pp->next;	}	*prev_propp = 0;	/* get the node's full name */	l = (int) call_prom(RELOC("package-to-path"), 3, 1, node,			    (char *) mem_start, mem_end - mem_start);	if (l >= 0) {		np->full_name = PTRUNRELOC((char *) mem_start);		*(char *)(mem_start + l) = 0;		mem_start = ALIGN(mem_start + l + 1);	}	/* do all our children */	child = call_prom(RELOC("child"), 1, 1, node);	while (child != (void *)0) {		mem_start = inspect_node(child, np, mem_start, mem_end,					 allnextpp);		child = call_prom(RELOC("peer"), 1, 1, child);	}	return mem_start;}/* * finish_device_tree is called once things are running normally * (i.e. with text and data mapped to the address they were linked at). * It traverses the device tree and fills in the name, type, * {n_}addrs and {n_}intrs fields of each node. */__initvoidfinish_device_tree(void){	unsigned long mem = (unsigned long) klimit;	/* All newworld machines now use the interrupt tree */	struct device_node *np = allnodes;	while(np && (_machine == _MACH_Pmac)) {		if (get_property(np, "interrupt-parent", 0)) {			pmac_newworld = 1;			break;		}		np = np->allnext;	}	if ((_machine == _MACH_chrp) || (boot_infos == 0 && pmac_newworld))		use_of_interrupt_tree = 1;	mem = finish_node(allnodes, mem, NULL, 0, 0);	dev_tree_size = mem - (unsigned long) allnodes;	klimit = (char *) mem;}/* * early_get_property is used to access the device tree image prepared * by BootX very early on, before the pointers in it have been relocated. */__init void *early_get_property(unsigned long base, unsigned long node, char *prop){	struct device_node *np = (struct device_node *)(base + node);	struct property *pp;	for (pp = np->properties; pp != 0; pp = pp->next) {		pp = (struct property *) (base + (unsigned long)pp);		if (strcmp((char *)((unsigned long)pp->name + base),			   prop) == 0) {			return (void *)((unsigned long)pp->value + base);		}	}	return 0;}__initstatic unsigned longfinish_node(struct device_node *np, unsigned long mem_start,	    interpret_func *ifunc, int naddrc, int nsizec){	struct device_node *child;	int *ip;	np->name = get_property(np, "name", 0);	np->type = get_property(np, "device_type", 0);	/* get the device addresses and interrupts */	if (ifunc != NULL) {		mem_start = ifunc(np, mem_start, naddrc, nsizec);	}	if (use_of_interrupt_tree) {		mem_start = finish_node_interrupts(np, mem_start);	}	/* Look for #address-cells and #size-cells properties. */	ip = (int *) get_property(np, "#address-cells", 0);	if (ip != NULL)		naddrc = *ip;	ip = (int *) get_property(np, "#size-cells", 0);	if (ip != NULL)		nsizec = *ip;	/* the f50 sets the name to 'display' and 'compatible' to what we	 * expect for the name -- Cort	 */	if (!strcmp(np->name, "display"))		np->name = get_property(np, "compatible", 0);	if (!strcmp(np->name, "device-tree"))		ifunc = interpret_root_props;	else if (np->type == 0)		ifunc = NULL;	else if (!strcmp(np->type, "pci") || !strcmp(np->type, "vci"))		ifunc = interpret_pci_props;	else if (!strcmp(np->type, "dbdma"))		ifunc = interpret_dbdma_props;	else if (!strcmp(np->type, "mac-io")		 || ifunc == interpret_macio_props)		ifunc = interpret_macio_props;	else if (!strcmp(np->type, "isa"))		ifunc = interpret_isa_props;	else if (!((ifunc == interpret_dbdma_props		    || ifunc == interpret_macio_props)		   && (!strcmp(np->type, "escc")		       || !strcmp(np->type, "media-bay"))))		ifunc = NULL;	/* if we were booted from BootX, convert the full name */	if (boot_infos	    && strncmp(np->full_name, "Devices:device-tree", 19) == 0) {		if (np->full_name[19] == 0) {			strcpy(np->full_name, "/");		} else if (np->full_name[19] == ':') {			char *p = np->full_name + 19;			np->full_name = p;			for (; *p; ++p)				if (*p == ':')					*p = '/';		}	}	for (child = np->child; child != NULL; child = child->sibling)		mem_start = finish_node(child, mem_start, ifunc,					naddrc, nsizec);	return mem_start;}/* This routine walks the interrupt tree for a given device node and gather  * all necessary informations according to the draft interrupt mapping * for CHRP. The current version was only tested on Apple "Core99" machines * and may not handle cascaded controllers correctly. */__initstatic unsigned longfinish_node_interrupts(struct device_node *np, unsigned long mem_start){	/* Finish this node */	unsigned int *isizep, *asizep, *interrupts, *map, *map_mask, *reg;	phandle *parent;	struct device_node *node, *parent_node;	int l, isize, ipsize, asize, map_size, regpsize;	/* Currently, we don't look at all nodes with no "interrupts" property */	interrupts = (unsigned int *)get_property(np, "interrupts", &l);	if (interrupts == NULL)		return mem_start;	ipsize = l>>2;	reg = (unsigned int *)get_property(np, "reg", &l);	regpsize = l>>2;	/* We assume default interrupt cell size is 1 (bugus ?) */	isize = 1;	node = np;		do {	    /* We adjust the cell size if the current parent contains an #interrupt-cells	     * property */	    isizep = (unsigned int *)get_property(node, "#interrupt-cells", &l);	    if (isizep)	    	isize = *isizep;	    /* We don't do interrupt cascade (ISA) for now, we stop on the first 	     * controller found	     */	    if (get_property(node, "interrupt-controller", &l)) {	    	int i,j;		int cvt_irq;		/* XXX on chrp, offset interrupt numbers for the		   8259 by 0, those for the openpic by 16 */		cvt_irq = _machine == _MACH_chrp			&& get_property(node, "interrupt-parent", NULL) == 0;	    	np->intrs = (struct interrupt_info *) mem_start;		np->n_intrs = ipsize / isize;		mem_start += np->n_intrs * sizeof(struct interrupt_info);		for (i = 0; i < np->n_intrs; ++i) {		    np->intrs[i].line = *interrupts++;		    if (cvt_irq)			np->intrs[i].line = openpic_to_irq(np->intrs[i].line);		    np->intrs[i].sense = 0;		    if (isize > 1)		        np->intrs[i].sense = *interrupts++;		    for (j=2; j<isize; j++)		    	interrupts++;		}		return mem_start;	    }	    /* We lookup for an interrupt-map. This code can only handle one interrupt	     * per device in the map. We also don't handle #address-cells in the parent	     * I skip the pci node itself here, may not be necessary but I don't like it's	     * reg property.	     */	    if (np != node)	        map = (unsigned int *)get_property(node, "interrupt-map", &l);	     else	     	map = NULL;	    if (map && l) {	    	int i, found, temp_isize;	        map_size = l>>2;	        map_mask = (unsigned int *)get_property(node, "interrupt-map-mask", &l);	        asizep = (unsigned int *)get_property(node, "#address-cells", &l);	        if (asizep && l == sizeof(unsigned int))	            asize = *asizep;	        else	            asize = 0;	        found = 0;	        while(map_size>0 && !found) {	            found = 1;	            for (i=0; i<asize; i++) {	            	unsigned int mask = map_mask ? map_mask[i] : 0xffffffff;	            	if (!reg || (i>=regpsize) || ((mask & *map) != (mask & reg[i])))	           	    found = 0;	           	map++;	           	map_size--;	            }	            for (i=0; i<isize; i++) {	            	unsigned int mask = map_mask ? map_mask[i+asize] : 0xffffffff;	            	if ((mask & *map) != (mask & interrupts[i]))	            	    found = 0;	            	map++;	            	map_size--;	            }	            parent = *((phandle *)(map));	            map+=1; map_size-=1;	            parent_node = find_phandle(parent);	            temp_isize = isize;	            if (parent_node) {			isizep = (unsigned int *)get_property(parent_node, "#interrupt-cells", &l);	    		if (isizep)	    		    temp_isize = *isizep;	            }	            if (!found) {	            	map += temp_isize;	            	map_size-=temp_isize;	            }	        }	        if (found) {	            node = parent_node;	            reg = NULL;	            regpsize = 0;	            interrupts = (unsigned int *)map;	            ipsize = temp_isize*1;		    continue;	        }	    }	    /* We look for an explicit interrupt-parent.	     */	    parent = (phandle *)get_property(node, "interrupt-parent", &l);	    if (parent && (l == sizeof(phandle)) &&	    	(parent_node = find_phandle(*parent))) {	    	node = parent_node;	    	continue;	    }	    /* Default, get real parent */	    node = node->parent;	} while(node);	return mem_start;}/* * When BootX makes a copy of the device tree from the MacOS * Name Registry, it is in the format we use but all of the pointers * are offsets from the start of the tree. * This procedure updates the pointers. */__initvoid relocate_nodes(void){	unsigned long base;	struct device_node *np;	struct property *pp;#define ADDBASE(x)	(x = (x)? ((typeof (x))((unsigned long)(x) + base)): 0)	base = (unsigned long) boot_infos + boot_infos->deviceTreeOffset;	allnodes = (struct device_node *)(base + 4);	for (np = allnodes; np != 0; np = np->allnext) {		ADDBASE(np->full_name);		ADDBASE(np->properties);		ADDBASE(np->parent);		ADDBASE(np->child);		ADDBASE(np->sibling);		ADDBASE(np->allnext);		for (pp = np->properties; pp != 0; pp = pp->next) {			ADDBASE(pp->name);			ADDBASE(pp->value);			ADDBASE(pp->next);		}	}}__initstatic unsigned longinterpret_pci_props(struct device_node *np, unsigned long mem_start,		    int naddrc, int nsizec){	struct address_range *adr;	struct pci_reg_property *pci_addrs;	int i, l, *ip, ml;

⌨️ 快捷键说明

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