setup.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:9k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright (C) 2000, 2001 Broadcom Corporation
  3.  *
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU General Public License
  6.  * as published by the Free Software Foundation; either version 2
  7.  * of the License, or (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  17.  */
  18. #include <linux/config.h>
  19. #include <linux/init.h>
  20. #include <linux/kernel.h>
  21. #include <linux/mm.h>
  22. #include <linux/blk.h>
  23. #include <linux/bootmem.h>
  24. #include <linux/smp.h>
  25. #include <linux/console.h>
  26. #include <asm/bootinfo.h>
  27. #include <asm/reboot.h>
  28. #include <asm/sibyte/board.h>
  29. #include "cfe_xiocb.h"
  30. #include "cfe_api.h"
  31. #include "cfe_error.h"
  32. /* Max ram addressable in 32-bit segments */
  33. #ifdef CONFIG_MIPS64
  34. #define MAX_RAM_SIZE (~0ULL)
  35. #else
  36. #ifdef CONFIG_HIGHMEM
  37. #ifdef CONFIG_64BIT_PHYS_ADDR
  38. #define MAX_RAM_SIZE (~0ULL)
  39. #else
  40. #define MAX_RAM_SIZE (0xffffffffULL)
  41. #endif
  42. #else
  43. #define MAX_RAM_SIZE (0x1fffffffULL)
  44. #endif
  45. #endif
  46. #define SB1250_DUART_MINOR_BASE 192 /* XXXKW put this somewhere sane */
  47. #define SB1250_PROMICE_MINOR_BASE 191 /* XXXKW put this somewhere sane */
  48. kdev_t cfe_consdev;
  49. #define SIBYTE_MAX_MEM_REGIONS 8
  50. phys_t board_mem_region_addrs[SIBYTE_MAX_MEM_REGIONS];
  51. phys_t board_mem_region_sizes[SIBYTE_MAX_MEM_REGIONS];
  52. unsigned int board_mem_region_count;
  53. /* This is the kernel command line.  Actually, it's
  54.    copied, eventually, to command_line, and looks to be
  55.    quite redundant.  But not something to fix just now */
  56. extern char arcs_cmdline[];
  57. #ifdef CONFIG_EMBEDDED_RAMDISK
  58. /* These are symbols defined by the ramdisk linker script */
  59. extern unsigned char __rd_start;
  60. extern unsigned char __rd_end;
  61. #endif
  62. #ifdef CONFIG_SMP
  63. static int reboot_smp = 0;
  64. #endif
  65. static void cfe_linux_exit(void)
  66. {
  67. #ifdef CONFIG_SMP
  68. if (smp_processor_id()) {
  69. if (reboot_smp) {
  70. /* Don't repeat the process from another CPU */
  71. for (;;);
  72. } else {
  73. /* Get CPU 0 to do the cfe_exit */
  74. reboot_smp = 1;
  75. smp_call_function((void *)_machine_restart, NULL, 1, 0);
  76. for (;;);
  77. }
  78. }
  79. #endif
  80. printk("passing control back to CFEn");
  81. cfe_exit(1, 0);
  82. printk("cfe_exit returned??n");
  83. while(1);
  84. }
  85. static __init void prom_meminit(void)
  86. {
  87. u64 addr, size; /* regardless of 64BIT_PHYS_ADDR */
  88. long type;
  89. unsigned int idx;
  90. int rd_flag;
  91. #ifdef CONFIG_BLK_DEV_INITRD
  92. unsigned long initrd_pstart;
  93. unsigned long initrd_pend;
  94. #ifdef CONFIG_EMBEDDED_RAMDISK
  95. /* If we're using an embedded ramdisk, then __rd_start and __rd_end
  96.    are defined by the linker to be on either side of the ramdisk
  97.    area.  Otherwise, initrd_start should be defined by kernel command
  98.    line arguments */
  99. if (initrd_start == 0) {
  100. initrd_start = (unsigned long)&__rd_start;
  101. initrd_end = (unsigned long)&__rd_end;
  102. }
  103. #endif
  104. initrd_pstart = __pa(initrd_start);
  105. initrd_pend = __pa(initrd_end);
  106. if (initrd_start &&
  107.     ((initrd_pstart > MAX_RAM_SIZE)
  108.      || (initrd_pend > MAX_RAM_SIZE))) {
  109. panic("initrd out of addressable memory");
  110. }
  111. #endif /* INITRD */
  112. for (idx = 0; cfe_enummem(idx, &addr, &size, &type) != CFE_ERR_NOMORE;
  113.      idx++) {
  114. rd_flag = 0;
  115. if (type == CFE_MI_AVAILABLE) {
  116. /*
  117.  * See if this block contains (any portion of) the
  118.  * ramdisk
  119.  */
  120. #ifdef CONFIG_BLK_DEV_INITRD
  121. if (initrd_start) {
  122. if ((initrd_pstart > addr) &&
  123.     (initrd_pstart < (addr + size))) {
  124. add_memory_region(addr,
  125.                   initrd_pstart - addr,
  126.                   BOOT_MEM_RAM);
  127. rd_flag = 1;
  128. }
  129. if ((initrd_pend > addr) &&
  130.     (initrd_pend < (addr + size))) {
  131. add_memory_region(initrd_pend,
  132. (addr + size) - initrd_pend,
  133.  BOOT_MEM_RAM);
  134. rd_flag = 1;
  135. }
  136. }
  137. #endif
  138. if (!rd_flag) {
  139. if (addr > MAX_RAM_SIZE)
  140. continue;
  141. if (addr+size > MAX_RAM_SIZE)
  142. size = MAX_RAM_SIZE - (addr+size) + 1;
  143. /*
  144.  * memcpy/__copy_user prefetch, which
  145.  * will cause a bus error for
  146.  * KSEG/KUSEG addrs not backed by RAM.
  147.  * Hence, reserve some padding for the
  148.  * prefetch distance.
  149.  */
  150. if (size > 512)
  151. size -= 512;
  152. add_memory_region(addr, size, BOOT_MEM_RAM);
  153. }
  154. board_mem_region_addrs[board_mem_region_count] = addr;
  155. board_mem_region_sizes[board_mem_region_count] = size;
  156. board_mem_region_count++;
  157. if (board_mem_region_count ==
  158.     SIBYTE_MAX_MEM_REGIONS) {
  159. /*
  160.  * Too many regions.  Need to configure more
  161.  */
  162. while(1);
  163. }
  164. }
  165. }
  166. #ifdef CONFIG_BLK_DEV_INITRD
  167. if (initrd_start) {
  168. add_memory_region(initrd_pstart, initrd_pend - initrd_pstart,
  169.   BOOT_MEM_RESERVED);
  170. }
  171. #endif
  172. }
  173. #ifdef CONFIG_BLK_DEV_INITRD
  174. static int __init initrd_setup(char *str)
  175. {
  176. /*
  177.  *Initrd location comes in the form "<hex size of ramdisk in bytes>@<location in memory>"
  178.  *  e.g. initrd=3abfd@80010000.  This is set up by the loader.
  179.  */
  180. char *tmp, *endptr;
  181. unsigned long initrd_size;
  182. for (tmp = str; *tmp != '@'; tmp++) {
  183. if (!*tmp) {
  184. goto fail;
  185. }
  186. }
  187. *tmp = 0;
  188. tmp++;
  189. if (!*tmp) {
  190. goto fail;
  191. }
  192. initrd_size = simple_strtol(str, &endptr, 16);
  193. if (*endptr) {
  194. *(tmp-1) = '@';
  195. goto fail;
  196. }
  197. *(tmp-1) = '@';
  198. initrd_start = simple_strtol(tmp, &endptr, 16);
  199. if (*endptr) {
  200. goto fail;
  201. }
  202. initrd_end = initrd_start + initrd_size;
  203. printk("Found initrd of %lx@%lxn", initrd_size, initrd_start);
  204. return 1;
  205.  fail:
  206. printk("Bad initrd argument.  Disabling initrdn");
  207. initrd_start = 0;
  208. initrd_end = 0;
  209. return 1;
  210. }
  211. #endif
  212. /*
  213.  * prom_init is called just after the cpu type is determined, from init_arch()
  214.  */
  215. __init int prom_init(int argc, char **argv, char **envp, int *prom_vec)
  216. {
  217. _machine_restart   = (void (*)(char *))cfe_linux_exit;
  218. _machine_halt      = cfe_linux_exit;
  219. _machine_power_off = cfe_linux_exit;
  220. /*
  221.  * This should go away.  Detect if we're booting
  222.  * straight from cfe without a loader.  If we
  223.  * are, then we've got a prom vector in a0.  Otherwise,
  224.  * argc (and argv and envp, for that matter) will be 0)
  225.  */
  226. if (argc < 0) {
  227. prom_vec = (int *)argc;
  228. }
  229. cfe_init((long)prom_vec);
  230. cfe_open_console();
  231. if (cfe_getenv("LINUX_CMDLINE", arcs_cmdline, CL_SIZE) < 0) {
  232. if (argc < 0) {
  233. /*
  234.  * It's OK for direct boot to not provide a
  235.  *  command line
  236.  */
  237. strcpy(arcs_cmdline, "root=/dev/ram0 ");
  238. #ifdef CONFIG_SIBYTE_PTSWARM
  239. strcat(arcs_cmdline, "console=ttyS0,115200 ");
  240. #endif
  241. } else {
  242. /* The loader should have set the command line */
  243. panic("LINUX_CMDLINE not defined in cfe.");
  244. }
  245. }
  246. #ifdef CONFIG_BLK_DEV_INITRD
  247. {
  248. char *ptr;
  249. /* Need to find out early whether we've got an initrd.  So scan
  250.    the list looking now */
  251. for (ptr = arcs_cmdline; *ptr; ptr++) {
  252. while (*ptr == ' ') {
  253. ptr++;
  254. }
  255. if (!strncmp(ptr, "initrd=", 7)) {
  256. initrd_setup(ptr+7);
  257. break;
  258. } else {
  259. while (*ptr && (*ptr != ' ')) {
  260. ptr++;
  261. }
  262. }
  263. }
  264. }
  265. #endif /* CONFIG_BLK_DEV_INITRD */
  266. /* Not sure this is needed, but it's the safe way. */
  267. arcs_cmdline[CL_SIZE-1] = 0;
  268. mips_machgroup = MACH_GROUP_SIBYTE;
  269. prom_meminit();
  270. return 0;
  271. }
  272. void prom_free_prom_memory(void)
  273. {
  274. /* Not sure what I'm supposed to do here.  Nothing, I think */
  275. }
  276. int page_is_ram(unsigned long pagenr)
  277. {
  278. phys_t addr = pagenr << PAGE_SHIFT;
  279. int i;
  280. for (i = 0; i < board_mem_region_count; i++) {
  281. if ((addr >= board_mem_region_addrs[i])
  282.     && (addr < (board_mem_region_addrs[i] + board_mem_region_sizes[i]))) {
  283. return 1;
  284. }
  285. }
  286. return 0;
  287. }
  288. #ifdef CONFIG_SIBYTE_CFE_CONSOLE
  289. static void cfe_console_write(struct console *cons, const char *str,
  290.                               unsigned int count)
  291. {
  292. int i, last;
  293. for (i=0,last=0; i<count; i++) {
  294. if (!str[i])
  295. /* XXXKW can/should this ever happen? */
  296. panic("cfe_console_write with NULL");
  297. if (str[i] == 'n') {
  298. cfe_console_print(&str[last], i-last);
  299. cfe_console_print("r", 1);
  300. last = i;
  301. }
  302. }
  303. if (last != count)
  304. cfe_console_print(&str[last], count-last);
  305. }
  306. static kdev_t cfe_console_device(struct console *c)
  307. {
  308. return cfe_consdev;
  309. }
  310. static int cfe_console_setup(struct console *cons, char *str)
  311. {
  312. char consdev[32];
  313. cfe_open_console();
  314. /* XXXKW think about interaction with 'console=' cmdline arg */
  315. /* If none of the console options are configured, the build will break. */
  316. if (cfe_getenv("BOOT_CONSOLE", consdev, 32) >= 0) {
  317. #ifdef CONFIG_SIBYTE_SB1250_DUART
  318. if (!strcmp(consdev, "uart0")) {
  319. setleds("u0cn");
  320. cfe_consdev = MKDEV(TTY_MAJOR, SB1250_DUART_MINOR_BASE + 0);
  321. #ifndef CONFIG_SIBYTE_SB1250_DUART_NO_PORT_1
  322. } else if (!strcmp(consdev, "uart1")) {
  323. setleds("u1cn");
  324. cfe_consdev = MKDEV(TTY_MAJOR, SB1250_DUART_MINOR_BASE + 1);
  325. #endif
  326. #endif
  327. #ifdef CONFIG_VGA_CONSOLE
  328. } else if (!strcmp(consdev, "pcconsole0")) {
  329. setleds("pccn");
  330. cfe_consdev = MKDEV(TTY_MAJOR, 0);
  331. #endif
  332. #ifdef CONFIG_PROMICE
  333. } else if (!strcmp(consdev, "promice0")) {
  334. setleds("picn");
  335. cfe_consdev = MKDEV(TTY_MAJOR, SB1250_PROMICE_MINOR_BASE);
  336. #endif
  337. } else
  338. return -ENODEV;
  339. }
  340. return 0;
  341. }
  342. static struct console sb1250_cfe_cons = {
  343. name: "cfe",
  344. write: cfe_console_write,
  345. device: cfe_console_device,
  346. setup: cfe_console_setup,
  347. flags: CON_PRINTBUFFER,
  348. index: -1,
  349. };
  350. void __init sb1250_cfe_console_init(void)
  351. {
  352. register_console(&sb1250_cfe_cons);
  353. }
  354. #endif /* CONFIG_SIBYTE_CFE_CONSOLE */