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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*  $Id: setup.c,v 1.126 2001/11/13 00:49:27 davem Exp $
  2.  *  linux/arch/sparc/kernel/setup.c
  3.  *
  4.  *  Copyright (C) 1995  David S. Miller (davem@caip.rutgers.edu)
  5.  *  Copyright (C) 2000  Anton Blanchard (anton@samba.org)
  6.  */
  7. #include <linux/errno.h>
  8. #include <linux/sched.h>
  9. #include <linux/kernel.h>
  10. #include <linux/mm.h>
  11. #include <linux/stddef.h>
  12. #include <linux/unistd.h>
  13. #include <linux/ptrace.h>
  14. #include <linux/slab.h>
  15. #include <asm/smp.h>
  16. #include <linux/user.h>
  17. #include <linux/a.out.h>
  18. #include <linux/tty.h>
  19. #include <linux/delay.h>
  20. #include <linux/config.h>
  21. #include <linux/fs.h>
  22. #include <linux/seq_file.h>
  23. #include <linux/kdev_t.h>
  24. #include <linux/major.h>
  25. #include <linux/string.h>
  26. #include <linux/blk.h>
  27. #include <linux/init.h>
  28. #include <linux/interrupt.h>
  29. #include <linux/console.h>
  30. #include <linux/spinlock.h>
  31. #include <asm/segment.h>
  32. #include <asm/system.h>
  33. #include <asm/io.h>
  34. #include <asm/kgdb.h>
  35. #include <asm/processor.h>
  36. #include <asm/oplib.h>
  37. #include <asm/page.h>
  38. #include <asm/pgtable.h>
  39. #include <asm/traps.h>
  40. #include <asm/vaddrs.h>
  41. #include <asm/kdebug.h>
  42. #include <asm/mbus.h>
  43. #include <asm/idprom.h>
  44. #include <asm/softirq.h>
  45. #include <asm/hardirq.h>
  46. #include <asm/machines.h>
  47. struct screen_info screen_info = {
  48. 0, 0, /* orig-x, orig-y */
  49. 0, /* unused */
  50. 0, /* orig-video-page */
  51. 0, /* orig-video-mode */
  52. 128, /* orig-video-cols */
  53. 0,0,0, /* ega_ax, ega_bx, ega_cx */
  54. 54, /* orig-video-lines */
  55. 0,                      /* orig-video-isVGA */
  56. 16                      /* orig-video-points */
  57. };
  58. /* Typing sync at the prom prompt calls the function pointed to by
  59.  * romvec->pv_synchook which I set to the following function.
  60.  * This should sync all filesystems and return, for now it just
  61.  * prints out pretty messages and returns.
  62.  */
  63. extern unsigned long trapbase;
  64. extern int serial_console;
  65. extern void breakpoint(void);
  66. #if CONFIG_SUN_CONSOLE
  67. void (*prom_palette)(int);
  68. #endif
  69. asmlinkage void sys_sync(void); /* it's really int */
  70. /* Pretty sick eh? */
  71. void prom_sync_me(void)
  72. {
  73. unsigned long prom_tbr, flags;
  74. /* XXX Badly broken. FIX! - Anton */
  75. save_and_cli(flags);
  76. __asm__ __volatile__("rd %%tbr, %0nt" : "=r" (prom_tbr));
  77. __asm__ __volatile__("wr %0, 0x0, %%tbrnt"
  78.      "nopnt"
  79.      "nopnt"
  80.      "nopnt" : : "r" (&trapbase));
  81. #ifdef CONFIG_SUN_CONSOLE
  82. if (prom_palette)
  83. prom_palette(1);
  84. #endif
  85. prom_printf("PROM SYNC COMMAND...n");
  86. show_free_areas();
  87. if(current->pid != 0) {
  88. sti();
  89. sys_sync();
  90. cli();
  91. }
  92. prom_printf("Returning to promn");
  93. __asm__ __volatile__("wr %0, 0x0, %%tbrnt"
  94.      "nopnt"
  95.      "nopnt"
  96.      "nopnt" : : "r" (prom_tbr));
  97. restore_flags(flags);
  98. return;
  99. }
  100. extern void rs_kgdb_hook(int tty_num); /* sparc/serial.c */
  101. unsigned int boot_flags __initdata = 0;
  102. #define BOOTME_DEBUG  0x1
  103. #define BOOTME_SINGLE 0x2
  104. #define BOOTME_KGDBA  0x4
  105. #define BOOTME_KGDBB  0x8
  106. #define BOOTME_KGDB   0xc
  107. #ifdef CONFIG_SUN_CONSOLE
  108. static int console_fb __initdata = 0;
  109. #endif
  110. /* Exported for mm/init.c:paging_init. */
  111. unsigned long cmdline_memory_size __initdata = 0;
  112. void kernel_enter_debugger(void)
  113. {
  114. if (boot_flags & BOOTME_KGDB) {
  115. printk("KGDB: Enteredn");
  116. breakpoint();
  117. }
  118. }
  119. static void
  120. prom_console_write(struct console *con, const char *s, unsigned n)
  121. {
  122. prom_printf("%s", s);
  123. }
  124. static struct console prom_debug_console = {
  125. name: "debug",
  126. write: prom_console_write,
  127. flags: CON_PRINTBUFFER,
  128. index: -1,
  129. };
  130. int obp_system_intr(void)
  131. {
  132. if (boot_flags & BOOTME_KGDB) {
  133. printk("KGDB: system interruptedn");
  134. breakpoint();
  135. return 1;
  136. }
  137. if (boot_flags & BOOTME_DEBUG) {
  138. printk("OBP: system interruptedn");
  139. prom_halt();
  140. return 1;
  141. }
  142. return 0;
  143. }
  144. /* 
  145.  * Process kernel command line switches that are specific to the
  146.  * SPARC or that require special low-level processing.
  147.  */
  148. static void __init process_switch(char c)
  149. {
  150. switch (c) {
  151. case 'd':
  152. boot_flags |= BOOTME_DEBUG;
  153. break;
  154. case 's':
  155. boot_flags |= BOOTME_SINGLE;
  156. break;
  157. case 'h':
  158. prom_printf("boot_flags_init: Halt!n");
  159. prom_halt();
  160. break;
  161. case 'p':
  162. /* Use PROM debug console. */
  163. register_console(&prom_debug_console);
  164. break;
  165. default:
  166. printk("Unknown boot switch (-%c)n", c);
  167. break;
  168. }
  169. }
  170. static void __init boot_flags_init(char *commands)
  171. {
  172. while (*commands) {
  173. /* Move to the start of the next "argument". */
  174. while (*commands && *commands == ' ')
  175. commands++;
  176. /* Process any command switches, otherwise skip it. */
  177. if (*commands == '')
  178. break;
  179. else if (*commands == '-') {
  180. commands++;
  181. while (*commands && *commands != ' ')
  182. process_switch(*commands++);
  183. } else if (strlen(commands) >= 9
  184.    && !strncmp(commands, "kgdb=tty", 8)) {
  185. switch (commands[8]) {
  186. #ifdef CONFIG_SUN_SERIAL
  187. case 'a':
  188. boot_flags |= BOOTME_KGDBA;
  189. prom_printf("KGDB: Using serial line /dev/ttya.n");
  190. break;
  191. case 'b':
  192. boot_flags |= BOOTME_KGDBB;
  193. prom_printf("KGDB: Using serial line /dev/ttyb.n");
  194. break;
  195. #endif
  196. default:
  197. printk("KGDB: Unknown tty line.n");
  198. break;
  199. }
  200. commands += 9;
  201. } else {
  202. #if CONFIG_SUN_CONSOLE
  203. if (!strncmp(commands, "console=", 8)) {
  204. commands += 8;
  205. if (!strncmp (commands, "ttya", 4)) {
  206. console_fb = 2;
  207. prom_printf ("Using /dev/ttya as console.n");
  208. } else if (!strncmp (commands, "ttyb", 4)) {
  209. console_fb = 3;
  210. prom_printf ("Using /dev/ttyb as console.n");
  211. #if defined(CONFIG_PROM_CONSOLE)
  212. } else if (!strncmp (commands, "prom", 4)) {
  213. char *p;
  214. for (p = commands - 8; *p && *p != ' '; p++)
  215. *p = ' ';
  216. conswitchp = &prom_con;
  217. console_fb = 1;
  218. #endif
  219. } else {
  220. console_fb = 1;
  221. }
  222. } else
  223. #endif
  224. if (!strncmp(commands, "mem=", 4)) {
  225. /*
  226.  * "mem=XXX[kKmM] overrides the PROM-reported
  227.  * memory size.
  228.  */
  229. cmdline_memory_size = simple_strtoul(commands + 4,
  230.      &commands, 0);
  231. if (*commands == 'K' || *commands == 'k') {
  232. cmdline_memory_size <<= 10;
  233. commands++;
  234. } else if (*commands=='M' || *commands=='m') {
  235. cmdline_memory_size <<= 20;
  236. commands++;
  237. }
  238. }
  239. while (*commands && *commands != ' ')
  240. commands++;
  241. }
  242. }
  243. }
  244. /* This routine will in the future do all the nasty prom stuff
  245.  * to probe for the mmu type and its parameters, etc. This will
  246.  * also be where SMP things happen plus the Sparc specific memory
  247.  * physical memory probe as on the alpha.
  248.  */
  249. extern int prom_probe_memory(void);
  250. extern void sun4c_probe_vac(void);
  251. extern char cputypval;
  252. extern unsigned long start, end;
  253. extern void panic_setup(char *, int *);
  254. extern void srmmu_end_memory(unsigned long, unsigned long *);
  255. extern void sun_serial_setup(void);
  256. extern unsigned short root_flags;
  257. extern unsigned short root_dev;
  258. extern unsigned short ram_flags;
  259. #define RAMDISK_IMAGE_START_MASK 0x07FF
  260. #define RAMDISK_PROMPT_FLAG 0x8000
  261. #define RAMDISK_LOAD_FLAG 0x4000
  262. extern int root_mountflags;
  263. char saved_command_line[256];
  264. char reboot_command[256];
  265. enum sparc_cpu sparc_cpu_model;
  266. struct tt_entry *sparc_ttable;
  267. struct pt_regs fake_swapper_regs;
  268. extern void paging_init(void);
  269. void __init setup_arch(char **cmdline_p)
  270. {
  271. int i;
  272. unsigned long highest_paddr;
  273. sparc_ttable = (struct tt_entry *) &start;
  274. /* Initialize PROM console and command line. */
  275. *cmdline_p = prom_getbootargs();
  276. strcpy(saved_command_line, *cmdline_p);
  277. /* Set sparc_cpu_model */
  278. sparc_cpu_model = sun_unknown;
  279. if(!strcmp(&cputypval,"sun4 ")) { sparc_cpu_model=sun4; }
  280. if(!strcmp(&cputypval,"sun4c")) { sparc_cpu_model=sun4c; }
  281. if(!strcmp(&cputypval,"sun4m")) { sparc_cpu_model=sun4m; }
  282. if(!strcmp(&cputypval,"sun4s")) { sparc_cpu_model=sun4m; }  /* CP-1200 with PROM 2.30 -E */
  283. if(!strcmp(&cputypval,"sun4d")) { sparc_cpu_model=sun4d; }
  284. if(!strcmp(&cputypval,"sun4e")) { sparc_cpu_model=sun4e; }
  285. if(!strcmp(&cputypval,"sun4u")) { sparc_cpu_model=sun4u; }
  286. #ifdef CONFIG_SUN4
  287. if (sparc_cpu_model != sun4) {
  288. prom_printf("This kernel is for Sun4 architecture only.n");
  289. prom_halt();
  290. }
  291. #endif
  292. printk("ARCH: ");
  293. switch(sparc_cpu_model) {
  294. case sun4:
  295. printk("SUN4n");
  296. break;
  297. case sun4c:
  298. printk("SUN4Cn");
  299. break;
  300. case sun4m:
  301. printk("SUN4Mn");
  302. break;
  303. case sun4d:
  304. printk("SUN4Dn");
  305. break;
  306. case sun4e:
  307. printk("SUN4En");
  308. break;
  309. case sun4u:
  310. printk("SUN4Un");
  311. break;
  312. default:
  313. printk("UNKNOWN!n");
  314. break;
  315. };
  316. #ifdef CONFIG_DUMMY_CONSOLE
  317. conswitchp = &dummy_con;
  318. #elif defined(CONFIG_PROM_CONSOLE)
  319. conswitchp = &prom_con;
  320. #endif
  321. boot_flags_init(*cmdline_p);
  322. idprom_init();
  323. if (ARCH_SUN4C_SUN4)
  324. sun4c_probe_vac();
  325. load_mmu();
  326. (void) prom_probe_memory();
  327. phys_base = 0xffffffffUL;
  328. highest_paddr = 0UL;
  329. for (i = 0; sp_banks[i].num_bytes != 0; i++) {
  330. unsigned long top;
  331. if (sp_banks[i].base_addr < phys_base)
  332. phys_base = sp_banks[i].base_addr;
  333. top = sp_banks[i].base_addr +
  334. sp_banks[i].num_bytes;
  335. if (highest_paddr < top)
  336. highest_paddr = top;
  337. }
  338. if (!root_flags)
  339. root_mountflags &= ~MS_RDONLY;
  340. ROOT_DEV = to_kdev_t(root_dev);
  341. #ifdef CONFIG_BLK_DEV_INITRD
  342. rd_image_start = ram_flags & RAMDISK_IMAGE_START_MASK;
  343. rd_prompt = ((ram_flags & RAMDISK_PROMPT_FLAG) != 0);
  344. rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0);
  345. #endif
  346. prom_setsync(prom_sync_me);
  347. {
  348. #if !CONFIG_SUN_SERIAL
  349. serial_console = 0;
  350. #else
  351. switch (console_fb) {
  352. case 0: /* Let get our io devices from prom */
  353. {
  354. int idev = prom_query_input_device();
  355. int odev = prom_query_output_device();
  356. if (idev == PROMDEV_IKBD && odev == PROMDEV_OSCREEN) {
  357. serial_console = 0;
  358. } else if (idev == PROMDEV_ITTYA && odev == PROMDEV_OTTYA) {
  359. serial_console = 1;
  360. } else if (idev == PROMDEV_ITTYB && odev == PROMDEV_OTTYB) {
  361. serial_console = 2;
  362. } else if (idev == PROMDEV_I_UNK && odev == PROMDEV_OTTYA) {
  363. prom_printf("MrCoffee ttyan");
  364. serial_console = 1;
  365. } else if (idev == PROMDEV_I_UNK && odev == PROMDEV_OSCREEN) {
  366. serial_console = 0;
  367. prom_printf("MrCoffee keyboardn");
  368. } else {
  369. prom_printf("Inconsistent or unknown consolen");
  370. prom_printf("You cannot mix serial and non serial input/output devicesn");
  371. prom_halt();
  372. }
  373. }
  374. break;
  375. case 1: serial_console = 0; break; /* Force one of the framebuffers as console */
  376. case 2: serial_console = 1; break; /* Force ttya as console */
  377. case 3: serial_console = 2; break; /* Force ttyb as console */
  378. }
  379. #endif
  380. }
  381. if ((boot_flags & BOOTME_KGDBA)) {
  382. rs_kgdb_hook(0);
  383. }
  384. if ((boot_flags & BOOTME_KGDBB)) {
  385. rs_kgdb_hook(1);
  386. }
  387. if((boot_flags&BOOTME_DEBUG) && (linux_dbvec!=0) && 
  388.    ((*(short *)linux_dbvec) != -1)) {
  389. printk("Booted under KADB. Syncing trap table.n");
  390. (*(linux_dbvec->teach_debugger))();
  391. }
  392. if((boot_flags & BOOTME_KGDB)) {
  393. set_debug_traps();
  394. prom_printf ("Breakpoint!n");
  395. breakpoint();
  396. }
  397. init_mm.context = (unsigned long) NO_CONTEXT;
  398. init_task.thread.kregs = &fake_swapper_regs;
  399. if (serial_console)
  400. conswitchp = NULL;
  401. paging_init();
  402. }
  403. asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on)
  404. {
  405. return -EIO;
  406. }
  407. extern char *sparc_cpu_type[];
  408. extern char *sparc_fpu_type[];
  409. static int show_cpuinfo(struct seq_file *m, void *__unused)
  410. {
  411. int cpuid = hard_smp_processor_id();
  412. seq_printf(m,
  413.    "cputt: %sn"
  414.    "fputt: %sn"
  415.    "promlibtt: Version %d Revision %dn"
  416.    "promtt: %d.%dn"
  417.    "typett: %sn"
  418.    "ncpus probedt: %dn"
  419.    "ncpus activet: %dn"
  420. #ifndef CONFIG_SMP
  421.    "BogoMipst: %lu.%02lun"
  422. #endif
  423.    ,
  424.    sparc_cpu_type[cpuid] ? : "undetermined",
  425.    sparc_fpu_type[cpuid] ? : "undetermined",
  426.    romvec->pv_romvers,
  427.    prom_rev,
  428.    romvec->pv_printrev >> 16,
  429.    (short) romvec->pv_printrev,
  430.    &cputypval,
  431.    linux_num_cpus,
  432.    smp_num_cpus
  433. #ifndef CONFIG_SMP
  434.    , loops_per_jiffy/(500000/HZ),
  435.    (loops_per_jiffy/(5000/HZ)) % 100
  436. #endif
  437. );
  438. #ifdef CONFIG_SMP
  439. smp_bogo_info(m);
  440. #endif
  441. mmu_info(m);
  442. #ifdef CONFIG_SMP
  443. smp_info(m);
  444. #endif
  445. return 0;
  446. }
  447. static void *c_start(struct seq_file *m, loff_t *pos)
  448. {
  449. /* The pointer we are returning is arbitrary,
  450.  * it just has to be non-NULL and not IS_ERR
  451.  * in the success case.
  452.  */
  453. return *pos == 0 ? &c_start : NULL;
  454. }
  455. static void *c_next(struct seq_file *m, void *v, loff_t *pos)
  456. {
  457. ++*pos;
  458. return c_start(m, pos);
  459. }
  460. static void c_stop(struct seq_file *m, void *v)
  461. {
  462. }
  463. struct seq_operations cpuinfo_op = {
  464. start: c_start,
  465. next: c_next,
  466. stop: c_stop,
  467. show: show_cpuinfo,
  468. };