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

📄 dt.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *    Copyright (C) 2005-2006 Michael Ellerman, IBM Corporation *    Copyright (C) 2000-2004, IBM Corporation * *    Description: *      This file contains all the routines to build a flattened device *      tree for a legacy iSeries machine. * *      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. */#undef DEBUG#include <linux/types.h>#include <linux/init.h>#include <linux/pci.h>#include <linux/pci_regs.h>#include <linux/pci_ids.h>#include <linux/threads.h>#include <linux/bitops.h>#include <linux/string.h>#include <linux/kernel.h>#include <linux/if_ether.h>	/* ETH_ALEN */#include <asm/machdep.h>#include <asm/prom.h>#include <asm/lppaca.h>#include <asm/cputable.h>#include <asm/abs_addr.h>#include <asm/system.h>#include <asm/iseries/hv_types.h>#include <asm/iseries/hv_lp_config.h>#include <asm/iseries/hv_call_xm.h>#include <asm/udbg.h>#include "processor_vpd.h"#include "call_hpt.h"#include "call_pci.h"#include "pci.h"#include "it_exp_vpd_panel.h"#include "naca.h"#ifdef DEBUG#define DBG(fmt...) udbg_printf(fmt)#else#define DBG(fmt...)#endif/* * These are created by the linker script at the start and end * of the section containing all the strings from this file. */extern char __dt_strings_start[];extern char __dt_strings_end[];struct iseries_flat_dt {	struct boot_param_header header;	u64 reserve_map[2];};static void * __initdata dt_data;/* * Putting these strings here keeps them out of the section * that we rename to .dt_strings using objcopy and capture * for the strings blob of the flattened device tree. */static char __initdata device_type_cpu[] = "cpu";static char __initdata device_type_memory[] = "memory";static char __initdata device_type_serial[] = "serial";static char __initdata device_type_network[] = "network";static char __initdata device_type_pci[] = "pci";static char __initdata device_type_vdevice[] = "vdevice";static char __initdata device_type_vscsi[] = "vscsi";/* EBCDIC to ASCII conversion routines */static unsigned char __init e2a(unsigned char x){	switch (x) {	case 0x81 ... 0x89:		return x - 0x81 + 'a';	case 0x91 ... 0x99:		return x - 0x91 + 'j';	case 0xA2 ... 0xA9:		return x - 0xA2 + 's';	case 0xC1 ... 0xC9:		return x - 0xC1 + 'A';	case 0xD1 ... 0xD9:		return x - 0xD1 + 'J';	case 0xE2 ... 0xE9:		return x - 0xE2 + 'S';	case 0xF0 ... 0xF9:		return x - 0xF0 + '0';	}	return ' ';}static unsigned char * __init strne2a(unsigned char *dest,		const unsigned char *src, size_t n){	int i;	n = strnlen(src, n);	for (i = 0; i < n; i++)		dest[i] = e2a(src[i]);	return dest;}static struct iseries_flat_dt * __init dt_init(void){	struct iseries_flat_dt *dt;	unsigned long str_len;	str_len = __dt_strings_end - __dt_strings_start;	dt = (struct iseries_flat_dt *)ALIGN(klimit, 8);	dt->header.off_mem_rsvmap =		offsetof(struct iseries_flat_dt, reserve_map);	dt->header.off_dt_strings = ALIGN(sizeof(*dt), 8);	dt->header.off_dt_struct = dt->header.off_dt_strings		+ ALIGN(str_len, 8);	dt_data = (void *)((unsigned long)dt + dt->header.off_dt_struct);	dt->header.dt_strings_size = str_len;	/* There is no notion of hardware cpu id on iSeries */	dt->header.boot_cpuid_phys = smp_processor_id();	memcpy((char *)dt + dt->header.off_dt_strings, __dt_strings_start,			str_len);	dt->header.magic = OF_DT_HEADER;	dt->header.version = 0x10;	dt->header.last_comp_version = 0x10;	dt->reserve_map[0] = 0;	dt->reserve_map[1] = 0;	return dt;}static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value){	*((u32 *)dt_data) = value;	dt_data += sizeof(u32);}#ifdef notyetstatic void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value){	*((u64 *)dt_data) = value;	dt_data += sizeof(u64);}#endifstatic void __init dt_push_bytes(struct iseries_flat_dt *dt, const char *data,		int len){	memcpy(dt_data, data, len);	dt_data += ALIGN(len, 4);}static void __init dt_start_node(struct iseries_flat_dt *dt, const char *name){	dt_push_u32(dt, OF_DT_BEGIN_NODE);	dt_push_bytes(dt, name, strlen(name) + 1);}#define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE)static void __init dt_prop(struct iseries_flat_dt *dt, const char *name,		const void *data, int len){	unsigned long offset;	dt_push_u32(dt, OF_DT_PROP);	/* Length of the data */	dt_push_u32(dt, len);	offset = name - __dt_strings_start;	/* The offset of the properties name in the string blob. */	dt_push_u32(dt, (u32)offset);	/* The actual data. */	dt_push_bytes(dt, data, len);}static void __init dt_prop_str(struct iseries_flat_dt *dt, const char *name,		const char *data){	dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */}static void __init dt_prop_u32(struct iseries_flat_dt *dt, const char *name,		u32 data){	dt_prop(dt, name, &data, sizeof(u32));}static void __init dt_prop_u64(struct iseries_flat_dt *dt, const char *name,		u64 data){	dt_prop(dt, name, &data, sizeof(u64));}static void __init dt_prop_u64_list(struct iseries_flat_dt *dt,		const char *name, u64 *data, int n){	dt_prop(dt, name, data, sizeof(u64) * n);}static void __init dt_prop_u32_list(struct iseries_flat_dt *dt,		const char *name, u32 *data, int n){	dt_prop(dt, name, data, sizeof(u32) * n);}#ifdef notyetstatic void __init dt_prop_empty(struct iseries_flat_dt *dt, const char *name){	dt_prop(dt, name, NULL, 0);}#endifstatic void __init dt_cpus(struct iseries_flat_dt *dt){	unsigned char buf[32];	unsigned char *p;	unsigned int i, index;	struct IoHriProcessorVpd *d;	u32 pft_size[2];	/* yuck */	snprintf(buf, 32, "PowerPC,%s", cur_cpu_spec->cpu_name);	p = strchr(buf, ' ');	if (!p) p = buf + strlen(buf);	dt_start_node(dt, "cpus");	dt_prop_u32(dt, "#address-cells", 1);	dt_prop_u32(dt, "#size-cells", 0);	pft_size[0] = 0; /* NUMA CEC cookie, 0 for non NUMA  */	pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE);	for (i = 0; i < NR_CPUS; i++) {		if (lppaca[i].dyn_proc_status >= 2)			continue;		snprintf(p, 32 - (p - buf), "@%d", i);		dt_start_node(dt, buf);		dt_prop_str(dt, "device_type", device_type_cpu);		index = lppaca[i].dyn_hv_phys_proc_index;		d = &xIoHriProcessorVpd[index];		dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024);		dt_prop_u32(dt, "i-cache-line-size", d->xInstCacheOperandSize);		dt_prop_u32(dt, "d-cache-size", d->xDataL1CacheSizeKB * 1024);		dt_prop_u32(dt, "d-cache-line-size", d->xDataCacheOperandSize);		/* magic conversions to Hz copied from old code */		dt_prop_u32(dt, "clock-frequency",			((1UL << 34) * 1000000) / d->xProcFreq);		dt_prop_u32(dt, "timebase-frequency",			((1UL << 32) * 1000000) / d->xTimeBaseFreq);		dt_prop_u32(dt, "reg", i);		dt_prop_u32_list(dt, "ibm,pft-size", pft_size, 2);		dt_end_node(dt);	}	dt_end_node(dt);}static void __init dt_model(struct iseries_flat_dt *dt){	char buf[16] = "IBM,";	/* N.B. lparcfg.c knows about the "IBM," prefixes ... */	/* "IBM," + mfgId[2:3] + systemSerial[1:5] */	strne2a(buf + 4, xItExtVpdPanel.mfgID + 2, 2);	strne2a(buf + 6, xItExtVpdPanel.systemSerial + 1, 5);	buf[11] = '\0';	dt_prop_str(dt, "system-id", buf);	/* "IBM," + machineType[0:4] */	strne2a(buf + 4, xItExtVpdPanel.machineType, 4);	buf[8] = '\0';	dt_prop_str(dt, "model", buf);	dt_prop_str(dt, "compatible", "IBM,iSeries");	dt_prop_u32(dt, "ibm,partition-no", HvLpConfig_getLpIndex());}static void __init dt_initrd(struct iseries_flat_dt *dt){#ifdef CONFIG_BLK_DEV_INITRD	if (naca.xRamDisk) {		dt_prop_u64(dt, "linux,initrd-start", (u64)naca.xRamDisk);		dt_prop_u64(dt, "linux,initrd-end",			(u64)naca.xRamDisk + naca.xRamDiskSize * HW_PAGE_SIZE);	}#endif}static void __init dt_do_vdevice(struct iseries_flat_dt *dt,		const char *name, u32 reg, int unit,		const char *type, const char *compat, int end){	char buf[32];	snprintf(buf, 32, "%s@%08x", name, reg + ((unit >= 0) ? unit : 0));	dt_start_node(dt, buf);	dt_prop_str(dt, "device_type", type);	if (compat)

⌨️ 快捷键说明

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