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

📄 inventory.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * inventory.c * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * * Copyright (c) 1999 The Puffin Group (David Kennedy and Alex deVries) * Copyright (c) 2001 Matthew Wilcox for Hewlett-Packard * * These are the routines to discover what hardware exists in this box. * This task is complicated by there being 3 different ways of * performing an inventory, depending largely on the age of the box. * The recommended way to do this is to check to see whether the machine * is a `Snake' first, then try System Map, then try PAT.  We try System * Map before checking for a Snake -- this probably doesn't cause any * problems, but... */#include <linux/types.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/slab.h>#include <linux/mm.h>#include <asm/hardware.h>#include <asm/io.h>#include <asm/pdc.h>#include <asm/processor.h>#include <asm/page.h>/*** Debug options** DEBUG_PAT Dump details which PDC PAT provides about ranges/devices.*/#undef DEBUG_PATint pdc_type = PDC_TYPE_ILLEGAL;void __init setup_pdc(void){	long status;	unsigned int bus_id;	struct pdc_system_map_mod_info module_result;	struct pdc_module_path module_path;	struct pdc_model model;#ifdef __LP64__	struct pdc_pat_cell_num cell_info;#endif	/* Determine the pdc "type" used on this machine */	printk(KERN_INFO "Determining PDC firmware type: ");	status = pdc_system_map_find_mods(&module_result, &module_path, 0);	if (status == PDC_OK) {		pdc_type = PDC_TYPE_SYSTEM_MAP;		printk("System Map.\n");		return;	}	/*	 * If the machine doesn't support PDC_SYSTEM_MAP then either it	 * is a pdc pat box, or it is an older box. All 64 bit capable	 * machines are either pdc pat boxes or they support PDC_SYSTEM_MAP.	 */	/*	 * TODO: We should test for 64 bit capability and give a	 * clearer message.	 */#ifdef __LP64__	status = pdc_pat_cell_get_number(&cell_info);	if (status == PDC_OK) {		pdc_type = PDC_TYPE_PAT;		printk("64 bit PAT.\n");		return;	}#endif	/* Check the CPU's bus ID.  There's probably a better test.  */	status = pdc_model_info(&model);	bus_id = (model.hversion >> (4 + 7)) & 0x1f;	switch (bus_id) {	case 0x4:		/* 720, 730, 750, 735, 755 */	case 0x6:		/* 705, 710 */	case 0x7:		/* 715, 725 */	case 0x8:		/* 745, 747, 742 */	case 0xA:		/* 712 and similiar */	case 0xC:		/* 715/64, at least */		pdc_type = PDC_TYPE_SNAKE;		printk("Snake.\n");		return;	default:		/* Everything else */		printk("Unsupported.\n");		panic("If this is a 64-bit machine, please try a 64-bit kernel.\n");	}}#define PDC_PAGE_ADJ_SHIFT (PAGE_SHIFT - 12) /* pdc pages are always 4k */static void __initset_pmem_entry(physmem_range_t *pmem_ptr, unsigned long start,	       unsigned long pages4k){	/* Rather than aligning and potentially throwing away	 * memory, we'll assume that any ranges are already	 * nicely aligned with any reasonable page size, and	 * panic if they are not (it's more likely that the	 * pdc info is bad in this case).	 */	if (   ((start & (PAGE_SIZE - 1)) != 0)	    || ((pages4k & ((1UL << PDC_PAGE_ADJ_SHIFT) - 1)) != 0) ) {		panic("Memory range doesn't align with page size!\n");	}	pmem_ptr->start_pfn = (start >> PAGE_SHIFT);	pmem_ptr->pages = (pages4k >> PDC_PAGE_ADJ_SHIFT);}static void __init pagezero_memconfig(void){	unsigned long npages;	/* Use the 32 bit information from page zero to create a single	 * entry in the pmem_ranges[] table.	 *	 * We currently don't support machines with contiguous memory	 * >= 4 Gb, who report that memory using 64 bit only fields	 * on page zero. It's not worth doing until it can be tested,	 * and it is not clear we can support those machines for other	 * reasons.	 *	 * If that support is done in the future, this is where it	 * should be done.	 */	npages = (PAGE_ALIGN(PAGE0->imm_max_mem) >> PAGE_SHIFT);	set_pmem_entry(pmem_ranges,0UL,npages);	npmem_ranges = 1;}#ifdef __LP64__/* All of the PDC PAT specific code is 64-bit only *//***  The module object is filled via PDC_PAT_CELL[Return Cell Module].**  If a module is found, register module will get the IODC bytes via**  pdc_iodc_read() using the PA view of conf_base_addr for the hpa parameter.****  The IO view can be used by PDC_PAT_CELL[Return Cell Module]**  only for SBAs and LBAs.  This view will cause an invalid**  argument error for all other cell module types.***/static int __init pat_query_module(ulong pcell_loc, ulong mod_index){	pdc_pat_cell_mod_maddr_block_t pa_pdc_cell;	pdc_pat_cell_mod_maddr_block_t io_pdc_cell;	unsigned long bytecnt;	unsigned long temp;	/* 64-bit scratch value */	long status;		/* PDC return value status */	struct parisc_device *dev;	/* return cell module (PA or Processor view) */	status = pdc_pat_cell_module(&bytecnt, pcell_loc, mod_index,				     PA_VIEW, &pa_pdc_cell);	if (status != PDC_OK) {		/* no more cell modules or error */		return status;	}	temp = pa_pdc_cell.cba;	dev = alloc_pa_dev(PAT_GET_CBA(temp), &pa_pdc_cell.mod_path);	if (!dev) {		return PDC_NE_MOD;	}	/* alloc_pa_dev sets dev->hpa */	/*	** save parameters in the parisc_device	** (The idea being the device driver will call pdc_pat_cell_module()	** and store the results in its own data structure.)	*/	dev->pcell_loc = pcell_loc;	dev->mod_index = mod_index;	/* save generic info returned from the call */	/* REVISIT: who is the consumer of this? not sure yet... */	dev->mod_info = pa_pdc_cell.mod_info;	/* pass to PAT_GET_ENTITY() */	dev->pmod_loc = pa_pdc_cell.mod_location;	register_parisc_device(dev);	/* advertise device */#ifdef DEBUG_PAT	/* dump what we see so far... */	switch (PAT_GET_ENTITY(dev->mod_info)) {		unsigned long i;	case PAT_ENTITY_PROC:		printk(KERN_DEBUG "PAT_ENTITY_PROC: id_eid 0x%lx\n",			pa_pdc_cell.mod[0]);		break;	case PAT_ENTITY_MEM:		printk(KERN_DEBUG 			"PAT_ENTITY_MEM: amount 0x%lx min_gni_base 0x%lx min_gni_len 0x%lx\n",			pa_pdc_cell.mod[0], pa_pdc_cell.mod[1], 			pa_pdc_cell.mod[2]);		break;	case PAT_ENTITY_CA:		printk(KERN_DEBUG "PAT_ENTITY_CA: %ld\n", pcell_loc);		break;	case PAT_ENTITY_PBC:		printk(KERN_DEBUG "PAT_ENTITY_PBC: ");		goto print_ranges;	case PAT_ENTITY_SBA:		printk(KERN_DEBUG "PAT_ENTITY_SBA: ");		goto print_ranges;	case PAT_ENTITY_LBA:		printk(KERN_DEBUG "PAT_ENTITY_LBA: "); print_ranges:		pdc_pat_cell_module(&bytecnt, pcell_loc, mod_index,				    IO_VIEW, &io_pdc_cell);		printk(KERN_DEBUG "ranges %ld\n", pa_pdc_cell.mod[1]);		for (i = 0; i < pa_pdc_cell.mod[1]; i++) {			printk(KERN_DEBUG 				"  PA_VIEW %ld: 0x%016lx 0x%016lx 0x%016lx\n", 				i, pa_pdc_cell.mod[2 + i * 3],	/* type */				pa_pdc_cell.mod[3 + i * 3],	/* start */				pa_pdc_cell.mod[4 + i * 3]);	/* finish (ie end) */			printk(KERN_DEBUG 				"  IO_VIEW %ld: 0x%016lx 0x%016lx 0x%016lx\n", 				i, io_pdc_cell.mod[2 + i * 3],	/* type */				io_pdc_cell.mod[3 + i * 3],	/* start */				io_pdc_cell.mod[4 + i * 3]);	/* finish (ie end) */		}		printk(KERN_DEBUG "\n");		break;	}#endif /* DEBUG_PAT */	return PDC_OK;}/* pat pdc can return information about a variety of different * types of memory (e.g. firmware,i/o, etc) but we only care about * the usable physical ram right now. Since the firmware specific * information is allocated on the stack, we'll be generous, in * case there is a lot of other information we don't care about. */#define PAT_MAX_RANGES (4 * MAX_PHYSMEM_RANGES)static void __init pat_memconfig(void){	unsigned long actual_len;	struct pdc_pat_pd_addr_map_entry mem_table[PAT_MAX_RANGES+1];	struct pdc_pat_pd_addr_map_entry *mtbl_ptr;	physmem_range_t *pmem_ptr;	long status;	int entries;	unsigned long length;	int i;	length = (PAT_MAX_RANGES + 1) * sizeof(struct pdc_pat_pd_addr_map_entry);	status = pdc_pat_pd_get_addr_map(&actual_len, mem_table, length, 0L);	if ((status != PDC_OK)	    || ((actual_len % sizeof(struct pdc_pat_pd_addr_map_entry)) != 0)) {		/* The above pdc call shouldn't fail, but, just in		 * case, just use the PAGE0 info.		 */		printk("\n\n\n");		printk(KERN_WARNING "WARNING! Could not get full memory configuration. "			"All memory may not be used!\n\n\n");		pagezero_memconfig();		return;	}	entries = actual_len / sizeof(struct pdc_pat_pd_addr_map_entry);	if (entries > PAT_MAX_RANGES) {		printk(KERN_WARNING "This Machine has more memory ranges than we support!\n");		printk(KERN_WARNING "Some memory may not be used!\n");	}

⌨️ 快捷键说明

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