📄 setup.c
字号:
/* * Powermac setup and early boot code plus other random bits. * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * * Adapted for Power Macintosh by Paul Mackerras * Copyright (C) 1996 Paul Mackerras (paulus@samba.org) * * Derived from "arch/alpha/kernel/setup.c" * Copyright (C) 1995 Linus Torvalds * * Maintained by Benjamin Herrenschmidt (benh@kernel.crashing.org) * * 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. * *//* * bootup setup stuff.. */#include <linux/config.h>#include <linux/init.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/string.h>#include <linux/delay.h>#include <linux/ioport.h>#include <linux/major.h>#include <linux/initrd.h>#include <linux/vt_kern.h>#include <linux/console.h>#include <linux/ide.h>#include <linux/pci.h>#include <linux/adb.h>#include <linux/cuda.h>#include <linux/pmu.h>#include <linux/irq.h>#include <linux/seq_file.h>#include <linux/root_dev.h>#include <linux/bitops.h>#include <linux/suspend.h>#include <asm/reg.h>#include <asm/sections.h>#include <asm/prom.h>#include <asm/system.h>#include <asm/pgtable.h>#include <asm/io.h>#include <asm/pci-bridge.h>#include <asm/ohare.h>#include <asm/mediabay.h>#include <asm/machdep.h>#include <asm/dma.h>#include <asm/cputable.h>#include <asm/btext.h>#include <asm/pmac_feature.h>#include <asm/time.h>#include <asm/of_device.h>#include <asm/mmu_context.h>#include <asm/iommu.h>#include <asm/smu.h>#include <asm/pmc.h>#include <asm/mpic.h>#include <asm/lmb.h>#include "pmac.h"#undef SHOW_GATWICK_IRQSunsigned char drive_info;int ppc_override_l2cr = 0;int ppc_override_l2cr_value;int has_l2cache = 0;int pmac_newworld = 1;static int current_root_goodness = -1;extern int pmac_newworld;extern struct machdep_calls pmac_md;#define DEFAULT_ROOT_DEVICE Root_SDA1 /* sda1 - slightly silly choice */#ifdef CONFIG_PPC64#include <asm/udbg.h>int sccdbg;#endifextern void zs_kgdb_hook(int tty_num);sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN;EXPORT_SYMBOL(sys_ctrler);#ifdef CONFIG_PMAC_SMUunsigned long smu_cmdbuf_abs;EXPORT_SYMBOL(smu_cmdbuf_abs);#endif#ifdef CONFIG_SMPextern struct smp_ops_t psurge_smp_ops;extern struct smp_ops_t core99_smp_ops;#endif /* CONFIG_SMP */static void pmac_show_cpuinfo(struct seq_file *m){ struct device_node *np; char *pp; int plen; int mbmodel; unsigned int mbflags; char* mbname; mbmodel = pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, PMAC_MB_INFO_MODEL, 0); mbflags = pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, PMAC_MB_INFO_FLAGS, 0); if (pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, PMAC_MB_INFO_NAME, (long) &mbname) != 0) mbname = "Unknown"; /* find motherboard type */ seq_printf(m, "machine\t\t: "); np = of_find_node_by_path("/"); if (np != NULL) { pp = (char *) get_property(np, "model", NULL); if (pp != NULL) seq_printf(m, "%s\n", pp); else seq_printf(m, "PowerMac\n"); pp = (char *) get_property(np, "compatible", &plen); if (pp != NULL) { seq_printf(m, "motherboard\t:"); while (plen > 0) { int l = strlen(pp) + 1; seq_printf(m, " %s", pp); plen -= l; pp += l; } seq_printf(m, "\n"); } of_node_put(np); } else seq_printf(m, "PowerMac\n"); /* print parsed model */ seq_printf(m, "detected as\t: %d (%s)\n", mbmodel, mbname); seq_printf(m, "pmac flags\t: %08x\n", mbflags); /* find l2 cache info */ np = of_find_node_by_name(NULL, "l2-cache"); if (np == NULL) np = of_find_node_by_type(NULL, "cache"); if (np != NULL) { unsigned int *ic = (unsigned int *) get_property(np, "i-cache-size", NULL); unsigned int *dc = (unsigned int *) get_property(np, "d-cache-size", NULL); seq_printf(m, "L2 cache\t:"); has_l2cache = 1; if (get_property(np, "cache-unified", NULL) != 0 && dc) { seq_printf(m, " %dK unified", *dc / 1024); } else { if (ic) seq_printf(m, " %dK instruction", *ic / 1024); if (dc) seq_printf(m, "%s %dK data", (ic? " +": ""), *dc / 1024); } pp = get_property(np, "ram-type", NULL); if (pp) seq_printf(m, " %s", pp); seq_printf(m, "\n"); of_node_put(np); } /* Indicate newworld/oldworld */ seq_printf(m, "pmac-generation\t: %s\n", pmac_newworld ? "NewWorld" : "OldWorld");}#ifndef CONFIG_ADB_CUDAint find_via_cuda(void){ if (!find_devices("via-cuda")) return 0; printk("WARNING ! Your machine is CUDA-based but your kernel\n"); printk(" wasn't compiled with CONFIG_ADB_CUDA option !\n"); return 0;}#endif#ifndef CONFIG_ADB_PMUint find_via_pmu(void){ if (!find_devices("via-pmu")) return 0; printk("WARNING ! Your machine is PMU-based but your kernel\n"); printk(" wasn't compiled with CONFIG_ADB_PMU option !\n"); return 0;}#endif#ifndef CONFIG_PMAC_SMUint smu_init(void){ /* should check and warn if SMU is present */ return 0;}#endif#ifdef CONFIG_PPC32static volatile u32 *sysctrl_regs;static void __init ohare_init(void){ /* this area has the CPU identification register and some registers used by smp boards */ sysctrl_regs = (volatile u32 *) ioremap(0xf8000000, 0x1000); /* * Turn on the L2 cache. * We assume that we have a PSX memory controller iff * we have an ohare I/O controller. */ if (find_devices("ohare") != NULL) { if (((sysctrl_regs[2] >> 24) & 0xf) >= 3) { if (sysctrl_regs[4] & 0x10) sysctrl_regs[4] |= 0x04000020; else sysctrl_regs[4] |= 0x04000000; if(has_l2cache) printk(KERN_INFO "Level 2 cache enabled\n"); } }}static void __init l2cr_init(void){ /* Checks "l2cr-value" property in the registry */ if (cpu_has_feature(CPU_FTR_L2CR)) { struct device_node *np = find_devices("cpus"); if (np == 0) np = find_type_devices("cpu"); if (np != 0) { unsigned int *l2cr = (unsigned int *) get_property(np, "l2cr-value", NULL); if (l2cr != 0) { ppc_override_l2cr = 1; ppc_override_l2cr_value = *l2cr; _set_L2CR(0); _set_L2CR(ppc_override_l2cr_value); } } } if (ppc_override_l2cr) printk(KERN_INFO "L2CR overridden (0x%x), " "backside cache is %s\n", ppc_override_l2cr_value, (ppc_override_l2cr_value & 0x80000000) ? "enabled" : "disabled");}#endifvoid __init pmac_setup_arch(void){ struct device_node *cpu, *ic; int *fp; unsigned long pvr; pvr = PVR_VER(mfspr(SPRN_PVR)); /* Set loops_per_jiffy to a half-way reasonable value, for use until calibrate_delay gets called. */ loops_per_jiffy = 50000000 / HZ; cpu = of_find_node_by_type(NULL, "cpu"); if (cpu != NULL) { fp = (int *) get_property(cpu, "clock-frequency", NULL); if (fp != NULL) { if (pvr >= 0x30 && pvr < 0x80) /* PPC970 etc. */ loops_per_jiffy = *fp / (3 * HZ); else if (pvr == 4 || pvr >= 8) /* 604, G3, G4 etc. */ loops_per_jiffy = *fp / HZ; else /* 601, 603, etc. */ loops_per_jiffy = *fp / (2 * HZ); } of_node_put(cpu); } /* See if newworld or oldworld */ for (ic = NULL; (ic = of_find_all_nodes(ic)) != NULL; ) if (get_property(ic, "interrupt-controller", NULL)) break; pmac_newworld = (ic != NULL); if (ic) of_node_put(ic); /* Lookup PCI hosts */ pmac_pci_init();#ifdef CONFIG_PPC32 ohare_init(); l2cr_init();#endif /* CONFIG_PPC32 */#ifdef CONFIG_PPC64 /* Probe motherboard chipset */ /* this is done earlier in setup_arch for 32-bit */ pmac_feature_init(); /* We can NAP */ powersave_nap = 1; printk(KERN_INFO "Using native/NAP idle loop\n");#endif#ifdef CONFIG_KGDB zs_kgdb_hook(0);#endif find_via_cuda(); find_via_pmu(); smu_init();#if defined(CONFIG_NVRAM) || defined(CONFIG_PPC64) pmac_nvram_init();#endif#ifdef CONFIG_PPC32#ifdef CONFIG_BLK_DEV_INITRD if (initrd_start) ROOT_DEV = Root_RAM0; else#endif ROOT_DEV = DEFAULT_ROOT_DEVICE;#endif#ifdef CONFIG_SMP /* Check for Core99 */ if (find_devices("uni-n") || find_devices("u3")) smp_ops = &core99_smp_ops;#ifdef CONFIG_PPC32 else smp_ops = &psurge_smp_ops;#endif#endif /* CONFIG_SMP */}char *bootpath;char *bootdevice;void *boot_host;int boot_target;int boot_part;extern dev_t boot_dev;#ifdef CONFIG_SCSIvoid __init note_scsi_host(struct device_node *node, void *host){ int l; char *p; l = strlen(node->full_name); if (bootpath != NULL && bootdevice != NULL && strncmp(node->full_name, bootdevice, l) == 0 && (bootdevice[l] == '/' || bootdevice[l] == 0)) { boot_host = host; /* * There's a bug in OF 1.0.5. (Why am I not surprised.) * If you pass a path like scsi/sd@1:0 to canon, it returns * something like /bandit@F2000000/gc@10/53c94@10000/sd@0,0 * That is, the scsi target number doesn't get preserved. * So we pick the target number out of bootpath and use that. */ p = strstr(bootpath, "/sd@"); if (p != NULL) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -