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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* $Id: setup.c,v 1.31 2001/08/23 16:36:40 dwmw2 Exp $
  2.  *
  3.  *  linux/arch/sh/kernel/setup.c
  4.  *
  5.  *  Copyright (C) 1999  Niibe Yutaka
  6.  *
  7.  */
  8. /*
  9.  * This file handles the architecture-dependent parts of initialization
  10.  */
  11. #include <linux/errno.h>
  12. #include <linux/sched.h>
  13. #include <linux/kernel.h>
  14. #include <linux/mm.h>
  15. #include <linux/stddef.h>
  16. #include <linux/unistd.h>
  17. #include <linux/ptrace.h>
  18. #include <linux/slab.h>
  19. #include <linux/user.h>
  20. #include <linux/a.out.h>
  21. #include <linux/tty.h>
  22. #include <linux/ioport.h>
  23. #include <linux/delay.h>
  24. #include <linux/config.h>
  25. #include <linux/init.h>
  26. #ifdef CONFIG_BLK_DEV_RAM
  27. #include <linux/blk.h>
  28. #endif
  29. #include <linux/bootmem.h>
  30. #include <linux/console.h>
  31. #include <linux/ctype.h>
  32. #include <linux/seq_file.h>
  33. #include <asm/processor.h>
  34. #include <asm/page.h>
  35. #include <asm/pgtable.h>
  36. #include <asm/uaccess.h>
  37. #include <asm/system.h>
  38. #include <asm/io.h>
  39. #include <asm/io_generic.h>
  40. #include <asm/machvec.h>
  41. #ifdef CONFIG_SH_EARLY_PRINTK
  42. #include <asm/sh_bios.h>
  43. #endif
  44. /*
  45.  * Machine setup..
  46.  */
  47. /*
  48.  * Initialize loops_per_jiffy as 10000000 (1000MIPS).
  49.  * This value will be used at the very early stage of serial setup.
  50.  * The bigger value means no problem.
  51.  */
  52. struct sh_cpuinfo boot_cpu_data = { CPU_SH_NONE, 0, 10000000, };
  53. struct screen_info screen_info;
  54. unsigned char aux_device_present = 0xaa;
  55. #if defined(CONFIG_SH_GENERIC) || defined(CONFIG_SH_UNKNOWN)
  56. struct sh_machine_vector sh_mv;
  57. #endif
  58. /* We need this to satisfy some external references. */
  59. struct screen_info screen_info = {
  60.         0, 25,                  /* orig-x, orig-y */
  61.         0,                      /* unused */
  62.         0,                      /* orig-video-page */
  63.         0,                      /* orig-video-mode */
  64.         80,                     /* orig-video-cols */
  65.         0,0,0,                  /* ega_ax, ega_bx, ega_cx */
  66.         25,                     /* orig-video-lines */
  67.         0,                      /* orig-video-isVGA */
  68.         16                      /* orig-video-points */
  69. };
  70. extern void fpu_init(void);
  71. extern int root_mountflags;
  72. extern int _text, _etext, _edata, _end;
  73. #define MV_NAME_SIZE 32
  74. static struct sh_machine_vector* __init get_mv_byname(const char* name);
  75. /*
  76.  * This is set up by the setup-routine at boot-time
  77.  */
  78. #define PARAM ((unsigned char *)empty_zero_page)
  79. #define MOUNT_ROOT_RDONLY (*(unsigned long *) (PARAM+0x000))
  80. #define RAMDISK_FLAGS (*(unsigned long *) (PARAM+0x004))
  81. #define ORIG_ROOT_DEV (*(unsigned long *) (PARAM+0x008))
  82. #define LOADER_TYPE (*(unsigned long *) (PARAM+0x00c))
  83. #define INITRD_START (*(unsigned long *) (PARAM+0x010))
  84. #define INITRD_SIZE (*(unsigned long *) (PARAM+0x014))
  85. /* ... */
  86. #define COMMAND_LINE ((char *) (PARAM+0x100))
  87. #define COMMAND_LINE_SIZE 256
  88. #define RAMDISK_IMAGE_START_MASK   0x07FF
  89. #define RAMDISK_PROMPT_FLAG 0x8000
  90. #define RAMDISK_LOAD_FLAG 0x4000
  91. static char command_line[COMMAND_LINE_SIZE] = { 0, };
  92.        char saved_command_line[COMMAND_LINE_SIZE];
  93. struct resource standard_io_resources[] = {
  94. { "dma1", 0x00, 0x1f },
  95. { "pic1", 0x20, 0x3f },
  96. { "timer", 0x40, 0x5f },
  97. { "keyboard", 0x60, 0x6f },
  98. { "dma page reg", 0x80, 0x8f },
  99. { "pic2", 0xa0, 0xbf },
  100. { "dma2", 0xc0, 0xdf },
  101. { "fpu", 0xf0, 0xff }
  102. };
  103. #define STANDARD_IO_RESOURCES (sizeof(standard_io_resources)/sizeof(struct resource))
  104. /* System RAM - interrupted by the 640kB-1M hole */
  105. #define code_resource (ram_resources[3])
  106. #define data_resource (ram_resources[4])
  107. static struct resource ram_resources[] = {
  108. { "System RAM", 0x000000, 0x09ffff, IORESOURCE_BUSY },
  109. { "System RAM", 0x100000, 0x100000, IORESOURCE_BUSY },
  110. { "Video RAM area", 0x0a0000, 0x0bffff },
  111. { "Kernel code", 0x100000, 0 },
  112. { "Kernel data", 0, 0 }
  113. };
  114. unsigned long memory_start, memory_end;
  115. #ifdef CONFIG_SH_EARLY_PRINTK
  116. /*
  117.  * Print a string through the BIOS
  118.  */
  119. static void sh_console_write(struct console *co, const char *s,
  120.  unsigned count)
  121. {
  122.      sh_bios_console_write(s, count);
  123. }
  124. static kdev_t sh_console_device(struct console *c)
  125. {
  126.      /* TODO: this is totally bogus */
  127. /* return MKDEV(SCI_MAJOR, SCI_MINOR_START + c->index); */
  128. return 0;
  129. }
  130. /*
  131.  * Setup initial baud/bits/parity. We do two things here:
  132.  * - construct a cflag setting for the first rs_open()
  133.  * - initialize the serial port
  134.  * Return non-zero if we didn't find a serial port.
  135.  */
  136. static int __init sh_console_setup(struct console *co, char *options)
  137. {
  138. int cflag = CREAD | HUPCL | CLOCAL;
  139. /*
  140.  * Now construct a cflag setting.
  141.  *   TODO: this is a totally bogus cflag, as we have
  142.  *   no idea what serial settings the BIOS is using, or
  143.  *   even if its using the serial port at all.
  144.  */
  145.      cflag |= B115200 | CS8 | /*no parity*/0;
  146. co->cflag = cflag;
  147. return 0;
  148. }
  149. static struct console sh_console = {
  150. name: "bios",
  151. write: sh_console_write,
  152. device: sh_console_device,
  153. setup: sh_console_setup,
  154. flags: CON_PRINTBUFFER,
  155. index: -1,
  156. };
  157. void sh_console_init(void)
  158. {
  159. register_console(&sh_console);
  160. }
  161. void sh_console_unregister(void)
  162. {
  163. unregister_console(&sh_console);
  164. }
  165. #endif
  166. static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE],
  167.   struct sh_machine_vector** mvp,
  168.   unsigned long *mv_io_base,
  169.   int *mv_mmio_enable)
  170. {
  171. char c = ' ', *to = command_line, *from = COMMAND_LINE;
  172. int len = 0;
  173. /* Save unparsed command line copy for /proc/cmdline */
  174. memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
  175. saved_command_line[COMMAND_LINE_SIZE-1] = '';
  176. memory_start = (unsigned long)PAGE_OFFSET+__MEMORY_START;
  177. memory_end = memory_start + __MEMORY_SIZE;
  178. for (;;) {
  179. /*
  180.  * "mem=XXX[kKmM]" defines a size of memory.
  181.  */
  182. if (c == ' ' && !memcmp(from, "mem=", 4)) {
  183. if (to != command_line)
  184. to--;
  185. {
  186. unsigned long mem_size;
  187. mem_size = memparse(from+4, &from);
  188. memory_end = memory_start + mem_size;
  189. }
  190. }
  191. if (c == ' ' && !memcmp(from, "sh_mv=", 6)) {
  192. char* mv_end;
  193. char* mv_comma;
  194. int mv_len;
  195. if (to != command_line)
  196. to--;
  197. from += 6;
  198. mv_end = strchr(from, ' ');
  199. if (mv_end == NULL)
  200. mv_end = from + strlen(from);
  201. mv_comma = strchr(from, ',');
  202. if ((mv_comma != NULL) && (mv_comma < mv_end)) {
  203. int ints[3];
  204. get_options(mv_comma+1, ARRAY_SIZE(ints), ints);
  205. *mv_io_base = ints[1];
  206. *mv_mmio_enable = ints[2];
  207. mv_len = mv_comma - from;
  208. } else {
  209. mv_len = mv_end - from;
  210. }
  211. if (mv_len > (MV_NAME_SIZE-1))
  212. mv_len = MV_NAME_SIZE-1;
  213. memcpy(mv_name, from, mv_len);
  214. mv_name[mv_len] = '';
  215. from = mv_end;
  216. *mvp = get_mv_byname(mv_name);
  217. }
  218. c = *(from++);
  219. if (!c)
  220. break;
  221. if (COMMAND_LINE_SIZE <= ++len)
  222. break;
  223. *(to++) = c;
  224. }
  225. *to = '';
  226. *cmdline_p = command_line;
  227. }
  228. void __init setup_arch(char **cmdline_p)
  229. {
  230. #if defined(CONFIG_SH_GENERIC) || defined(CONFIG_SH_UNKNOWN)
  231. extern struct sh_machine_vector mv_unknown;
  232. #endif
  233. struct sh_machine_vector *mv = NULL;
  234. char mv_name[MV_NAME_SIZE] = "";
  235. unsigned long mv_io_base = 0;
  236. int mv_mmio_enable = 0;
  237. unsigned long bootmap_size;
  238. unsigned long start_pfn, max_pfn, max_low_pfn;
  239. #ifdef CONFIG_SH_EARLY_PRINTK
  240. sh_console_init();
  241. #endif
  242. ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV);
  243. #ifdef CONFIG_BLK_DEV_RAM
  244. rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
  245. rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
  246. rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
  247. #endif
  248. if (!MOUNT_ROOT_RDONLY)
  249. root_mountflags &= ~MS_RDONLY;
  250. init_mm.start_code = (unsigned long)&_text;
  251. init_mm.end_code = (unsigned long) &_etext;
  252. init_mm.end_data = (unsigned long) &_edata;
  253. init_mm.brk = (unsigned long) &_end;
  254. code_resource.start = virt_to_bus(&_text);
  255. code_resource.end = virt_to_bus(&_etext)-1;
  256. data_resource.start = virt_to_bus(&_etext);
  257. data_resource.end = virt_to_bus(&_edata)-1;
  258. parse_cmdline(cmdline_p, mv_name, &mv, &mv_io_base, &mv_mmio_enable);
  259. #ifdef CONFIG_SH_GENERIC
  260. if (mv == NULL) {
  261. mv = &mv_unknown;
  262. if (*mv_name != '') {
  263. printk("Warning: Unsupported machine %s, using unknownn",
  264.        mv_name);
  265. }
  266. }
  267. sh_mv = *mv;
  268. #endif
  269. #ifdef CONFIG_SH_UNKNOWN
  270. sh_mv = mv_unknown;
  271. #endif
  272. #if defined(CONFIG_SH_GENERIC) || defined(CONFIG_SH_UNKNOWN)
  273. if (mv_io_base != 0) {
  274. sh_mv.mv_inb = generic_inb;
  275. sh_mv.mv_inw = generic_inw;
  276. sh_mv.mv_inl = generic_inl;
  277. sh_mv.mv_outb = generic_outb;
  278. sh_mv.mv_outw = generic_outw;
  279. sh_mv.mv_outl = generic_outl;
  280. sh_mv.mv_inb_p = generic_inb_p;
  281. sh_mv.mv_inw_p = generic_inw_p;
  282. sh_mv.mv_inl_p = generic_inl_p;
  283. sh_mv.mv_outb_p = generic_outb_p;
  284. sh_mv.mv_outw_p = generic_outw_p;
  285. sh_mv.mv_outl_p = generic_outl_p;
  286. sh_mv.mv_insb = generic_insb;
  287. sh_mv.mv_insw = generic_insw;
  288. sh_mv.mv_insl = generic_insl;
  289. sh_mv.mv_outsb = generic_outsb;
  290. sh_mv.mv_outsw = generic_outsw;
  291. sh_mv.mv_outsl = generic_outsl;
  292. sh_mv.mv_isa_port2addr = generic_isa_port2addr;
  293. generic_io_base = mv_io_base;
  294. }
  295. if (mv_mmio_enable != 0) {
  296. sh_mv.mv_readb = generic_readb;
  297. sh_mv.mv_readw = generic_readw;
  298. sh_mv.mv_readl = generic_readl;
  299. sh_mv.mv_writeb = generic_writeb;
  300. sh_mv.mv_writew = generic_writew;
  301. sh_mv.mv_writel = generic_writel;
  302. }
  303. #endif
  304. #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
  305. #define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
  306. #define PFN_PHYS(x) ((x) << PAGE_SHIFT)
  307. #ifdef CONFIG_DISCONTIGMEM
  308. NODE_DATA(0)->bdata = &discontig_node_bdata[0];
  309. NODE_DATA(1)->bdata = &discontig_node_bdata[1];
  310. bootmap_size = init_bootmem_node(NODE_DATA(1), 
  311.  PFN_UP(__MEMORY_START_2ND),
  312.  PFN_UP(__MEMORY_START_2ND),
  313.  PFN_DOWN(__MEMORY_START_2ND+__MEMORY_SIZE_2ND));
  314. free_bootmem_node(NODE_DATA(1), __MEMORY_START_2ND, __MEMORY_SIZE_2ND);
  315. reserve_bootmem_node(NODE_DATA(1), __MEMORY_START_2ND, bootmap_size);
  316. #endif
  317. /*
  318.  * Find the highest page frame number we have available
  319.  */
  320. max_pfn = PFN_DOWN(__pa(memory_end));
  321. /*
  322.  * Determine low and high memory ranges:
  323.  */
  324. max_low_pfn = max_pfn;
  325.   /*
  326.  * Partially used pages are not usable - thus
  327.  * we are rounding upwards:
  328.    */
  329. start_pfn = PFN_UP(__pa(&_end));
  330. /*
  331.  * Find a proper area for the bootmem bitmap. After this
  332.  * bootstrap step all allocations (until the page allocator
  333.  * is intact) must be done via bootmem_alloc().
  334.  */
  335. bootmap_size = init_bootmem_node(NODE_DATA(0), start_pfn,
  336.  __MEMORY_START>>PAGE_SHIFT,
  337.  max_low_pfn);
  338. /*
  339.  * Register fully available low RAM pages with the bootmem allocator.
  340.  */
  341. {
  342. unsigned long curr_pfn, last_pfn, pages;
  343. /*
  344.  * We are rounding up the start address of usable memory:
  345.  */
  346. curr_pfn = PFN_UP(__MEMORY_START);
  347. /*
  348.  * ... and at the end of the usable range downwards:
  349.  */
  350. last_pfn = PFN_DOWN(__pa(memory_end));
  351. if (last_pfn > max_low_pfn)
  352. last_pfn = max_low_pfn;
  353. pages = last_pfn - curr_pfn;
  354. free_bootmem_node(NODE_DATA(0), PFN_PHYS(curr_pfn),
  355.   PFN_PHYS(pages));
  356. }
  357. /*
  358.  * Reserve the kernel text and
  359.  * Reserve the bootmem bitmap. We do this in two steps (first step
  360.  * was init_bootmem()), because this catches the (definitely buggy)
  361.  * case of us accidentally initializing the bootmem allocator with
  362.  * an invalid RAM area.
  363.  */
  364. reserve_bootmem_node(NODE_DATA(0), __MEMORY_START+PAGE_SIZE,
  365. (PFN_PHYS(start_pfn)+bootmap_size+PAGE_SIZE-1)-__MEMORY_START);
  366. /*
  367.  * reserve physical page 0 - it's a special BIOS page on many boxes,
  368.  * enabling clean reboots, SMP operation, laptop functions.
  369.  */
  370. reserve_bootmem_node(NODE_DATA(0), __MEMORY_START, PAGE_SIZE);
  371. #ifdef CONFIG_BLK_DEV_INITRD
  372. if (LOADER_TYPE && INITRD_START) {
  373. if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
  374. reserve_bootmem_node(NODE_DATA(0), INITRD_START+__MEMORY_START, INITRD_SIZE);
  375. initrd_start =
  376. INITRD_START ? INITRD_START + PAGE_OFFSET + __MEMORY_START : 0;
  377. initrd_end = initrd_start + INITRD_SIZE;
  378. } else {
  379. printk("initrd extends beyond end of memory "
  380.     "(0x%08lx > 0x%08lx)ndisabling initrdn",
  381.     INITRD_START + INITRD_SIZE,
  382.     max_low_pfn << PAGE_SHIFT);
  383. initrd_start = 0;
  384. }
  385. }
  386. #endif
  387. #if 0
  388. /*
  389.  * Request the standard RAM and ROM resources -
  390.  * they eat up PCI memory space
  391.  */
  392. request_resource(&iomem_resource, ram_resources+0);
  393. request_resource(&iomem_resource, ram_resources+1);
  394. request_resource(&iomem_resource, ram_resources+2);
  395. request_resource(ram_resources+1, &code_resource);
  396. request_resource(ram_resources+1, &data_resource);
  397. probe_roms();
  398. /* request I/O space for devices used on all i[345]86 PCs */
  399. for (i = 0; i < STANDARD_IO_RESOURCES; i++)
  400. request_resource(&ioport_resource, standard_io_resources+i);
  401. #endif
  402. #ifdef CONFIG_VT
  403. #if defined(CONFIG_VGA_CONSOLE)
  404. conswitchp = &vga_con;
  405. #elif defined(CONFIG_DUMMY_CONSOLE)
  406. conswitchp = &dummy_con;
  407. #endif
  408. #endif
  409. /* Perform the machine specific initialisation */
  410. if (sh_mv.mv_init_arch != NULL) {
  411. sh_mv.mv_init_arch();
  412. }
  413. #if defined(__SH4__)
  414. /* We already grab/initialized FPU in head.S.  Make it consisitent. */
  415. init_task.used_math = 1;
  416. init_task.flags |= PF_USEDFPU;
  417. #endif
  418. paging_init();
  419. }
  420. struct sh_machine_vector* __init get_mv_byname(const char* name)
  421. {
  422. extern int strcasecmp(const char *, const char *);
  423. extern long __machvec_start, __machvec_end;
  424. struct sh_machine_vector *all_vecs =
  425. (struct sh_machine_vector *)&__machvec_start;
  426. int i, n = ((unsigned long)&__machvec_end
  427.     - (unsigned long)&__machvec_start)/
  428. sizeof(struct sh_machine_vector);
  429. for (i = 0; i < n; ++i) {
  430. struct sh_machine_vector *mv = &all_vecs[i];
  431. if (mv == NULL)
  432. continue;
  433. if (strcasecmp(name, mv->mv_name) == 0) {
  434. return mv;
  435. }
  436. }
  437. return NULL;
  438. }
  439. /*
  440.  * Get CPU information for use by the procfs.
  441.  */
  442. #ifdef CONFIG_PROC_FS
  443. static int show_cpuinfo(struct seq_file *m, void *v)
  444. {
  445. #if defined(__sh3__)
  446. seq_printf(m, "cpu familyt: SH-3n"
  447.       "cache sizet: 8K-byten");
  448. #elif defined(__SH4__)
  449. seq_printf(m, "cpu familyt: SH-4n"
  450.       "cache sizet: 8K-byte/16K-byten");
  451. #endif
  452. seq_printf(m, "bogomipst: %lu.%02lunn",
  453.      loops_per_jiffy/(500000/HZ),
  454.      (loops_per_jiffy/(5000/HZ)) % 100);
  455. seq_printf(m, "Machine: %sn", sh_mv.mv_name);
  456. #define PRINT_CLOCK(name, value) 
  457. seq_printf(m, name " clock: %d.%02dMHzn", 
  458.      ((value) / 1000000), ((value) % 1000000)/10000)
  459. PRINT_CLOCK("CPU", boot_cpu_data.cpu_clock);
  460. PRINT_CLOCK("Bus", boot_cpu_data.bus_clock);
  461. #ifdef CONFIG_CPU_SUBTYPE_ST40STB1
  462. PRINT_CLOCK("Memory", boot_cpu_data.memory_clock);
  463. #endif
  464. PRINT_CLOCK("Peripheral module", boot_cpu_data.module_clock);
  465. return 0;
  466. }
  467. static void *c_start(struct seq_file *m, loff_t *pos)
  468. {
  469. return (void*)(*pos == 0);
  470. }
  471. static void *c_next(struct seq_file *m, void *v, loff_t *pos)
  472. {
  473. return NULL;
  474. }
  475. static void c_stop(struct seq_file *m, void *v)
  476. {
  477. }
  478. struct seq_operations cpuinfo_op = {
  479. start: c_start,
  480. next: c_next,
  481. stop: c_stop,
  482. show: show_cpuinfo,
  483. };
  484. #endif