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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright (C) 1999,2001-2002 Silicon Graphics, Inc. All rights reserved.
  3.  * 
  4.  * This program is free software; you can redistribute it and/or modify it 
  5.  * under the terms of version 2 of the GNU General Public License 
  6.  * as published by the Free Software Foundation.
  7.  * 
  8.  * This program is distributed in the hope that it would be useful, but 
  9.  * WITHOUT ANY WARRANTY; without even the implied warranty of 
  10.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
  11.  * 
  12.  * Further, this software is distributed without any warranty that it is 
  13.  * free of the rightful claim of any third person regarding infringement 
  14.  * or the like.  Any license provided herein, whether implied or 
  15.  * otherwise, applies only to this software file.  Patent licenses, if 
  16.  * any, provided herein do not apply to combinations of this program with 
  17.  * other software, or any other product whatsoever.
  18.  * 
  19.  * You should have received a copy of the GNU General Public 
  20.  * License along with this program; if not, write the Free Software 
  21.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  22.  * 
  23.  * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, 
  24.  * Mountain View, CA  94043, or:
  25.  * 
  26.  * http://www.sgi.com 
  27.  * 
  28.  * For further information regarding this notice, see: 
  29.  * 
  30.  * http://oss.sgi.com/projects/GenInfo/NoticeExplan
  31.  */
  32. #include <linux/config.h>
  33. #include <linux/init.h>
  34. #include <linux/delay.h>
  35. #include <linux/kernel.h>
  36. #include <linux/kdev_t.h>
  37. #include <linux/string.h>
  38. #include <linux/tty.h>
  39. #include <linux/console.h>
  40. #include <linux/timex.h>
  41. #include <linux/sched.h>
  42. #include <linux/ioport.h>
  43. #include <linux/mm.h>
  44. #include <linux/serial.h>
  45. #include <linux/irq.h>
  46. #include <linux/bootmem.h>
  47. #include <linux/mmzone.h>
  48. #include <linux/interrupt.h>
  49. #include <asm/io.h>
  50. #include <asm/sal.h>
  51. #include <asm/machvec.h>
  52. #include <asm/system.h>
  53. #ifdef CONFIG_IA64_MCA
  54. #include <asm/acpi-ext.h>
  55. #endif
  56. #include <asm/processor.h>
  57. #include <asm/sn/sgi.h>
  58. #include <asm/sn/io.h>
  59. #include <asm/sn/arch.h>
  60. #include <asm/sn/addrs.h>
  61. #include <asm/sn/pda.h>
  62. #include <asm/sn/nodepda.h>
  63. #include <asm/sn/sn_cpuid.h>
  64. #include <asm/sn/sn_private.h>
  65. #include <asm/sn/simulator.h>
  66. #include <asm/sn/leds.h>
  67. #include <asm/sn/bte.h>
  68. #include <asm/sn/clksupport.h>
  69. #ifdef CONFIG_IA64_SGI_SN2
  70. #include <asm/sn/sn2/shub.h>
  71. #endif
  72. extern void bte_init_node (nodepda_t *, cnodeid_t, char **);
  73. extern void bte_init_cpu (void);
  74. long sn_rtc_cycles_per_second;   
  75. /*
  76.  * This is the address of the RRegs in the HSpace of the global
  77.  * master.  It is used by a hack in serial.c (serial_[in|out],
  78.  * printk.c (early_printk), and kdb_io.c to put console output on that
  79.  * node's Bedrock UART.  It is initialized here to 0, so that
  80.  * early_printk won't try to access the UART before
  81.  * master_node_bedrock_address is properly calculated.
  82.  */
  83. u64 master_node_bedrock_address = 0UL;
  84. static void sn_init_pdas(char **);
  85. extern struct irq_desc *_sn_irq_desc[];
  86. #if defined(CONFIG_IA64_SGI_SN1)
  87. extern synergy_da_t *Synergy_da_indr[];
  88. #endif
  89. static nodepda_t *nodepdaindr[MAX_COMPACT_NODES];
  90. #ifdef CONFIG_IA64_SGI_SN2
  91. irqpda_t *irqpdaindr[NR_CPUS];
  92. #endif /* CONFIG_IA64_SGI_SN2 */
  93. /*
  94.  * The format of "screen_info" is strange, and due to early i386-setup
  95.  * code. This is just enough to make the console code think we're on a
  96.  * VGA color display.
  97.  */
  98. struct screen_info sn_screen_info = {
  99. orig_x:  0,
  100. orig_y:  0,
  101. orig_video_mode:  3,
  102. orig_video_cols: 80,
  103. orig_video_ega_bx:  3,
  104. orig_video_lines: 25,
  105. orig_video_isVGA:  1,
  106. orig_video_points: 16
  107. };
  108. /*
  109.  * This is here so we can use the CMOS detection in ide-probe.c to
  110.  * determine what drives are present.  In theory, we don't need this
  111.  * as the auto-detection could be done via ide-probe.c:do_probe() but
  112.  * in practice that would be much slower, which is painful when
  113.  * running in the simulator.  Note that passing zeroes in DRIVE_INFO
  114.  * is sufficient (the IDE driver will autodetect the drive geometry).
  115.  */
  116. char drive_info[4*16];
  117. /**
  118.  * sn_map_nr - return the mem_map entry for a given kernel address
  119.  * @addr: kernel address to query
  120.  *
  121.  * Finds the mem_map entry for the kernel address given.  Used by
  122.  * virt_to_page() (asm-ia64/page.h), among other things.
  123.  */
  124. unsigned long
  125. sn_map_nr (unsigned long addr)
  126. {
  127. return MAP_NR_DISCONTIG(addr);
  128. }
  129. /**
  130.  * early_sn_setup - early setup routine for SN platforms
  131.  *
  132.  * Sets up an intial console to aid debugging.  Intended primarily
  133.  * for bringup, it's only called if %BRINGUP and %CONFIG_IA64_EARLY_PRINTK
  134.  * are turned on.  See start_kernel() in init/main.c.
  135.  */
  136. #if defined(CONFIG_IA64_EARLY_PRINTK) && defined(CONFIG_IA64_SGI_SN)
  137. void __init
  138. early_sn_setup(void)
  139. {
  140. if ( IS_RUNNING_ON_SIMULATOR() ) {
  141. #if defined(CONFIG_IA64_SGI_SN1)
  142. master_node_bedrock_address = (u64)REMOTE_HSPEC_ADDR(get_nasid(), 0);
  143. #else
  144. master_node_bedrock_address = (u64)REMOTE_HUB(get_nasid(), SH_JUNK_BUS_UART0);
  145. #endif
  146. printk(KERN_DEBUG "early_sn_setup: setting master_node_bedrock_address to 0x%lxn", master_node_bedrock_address);
  147. }
  148. }
  149. #endif /* CONFIG_IA64_EARLY_PRINTK && CONFIG_IA64_SGI_SN */
  150. #ifdef NOT_YET_CONFIG_IA64_MCA
  151. extern void ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs);
  152. static struct irqaction mca_cpe_irqaction = { 
  153. handler:    ia64_mca_cpe_int_handler,
  154. flags:      SA_INTERRUPT,
  155. name:       "cpe_hndlr"
  156. };
  157. #endif
  158. #ifdef CONFIG_IA64_MCA
  159. extern int platform_irq_list[];
  160. #endif
  161. extern nasid_t master_nasid;
  162. /**
  163.  * sn_setup - SN platform setup routine
  164.  * @cmdline_p: kernel command line
  165.  *
  166.  * Handles platform setup for SN machines.  This includes determining
  167.  * the RTC frequency (via a SAL call), initializing secondary CPUs, and
  168.  * setting up per-node data areas.  The console is also initialized here.
  169.  */
  170. void __init
  171. sn_setup(char **cmdline_p)
  172. {
  173. long status, ticks_per_sec, drift;
  174. int i;
  175. master_nasid = get_nasid();
  176. (void)get_console_nasid();
  177. status = ia64_sal_freq_base(SAL_FREQ_BASE_REALTIME_CLOCK, &ticks_per_sec, &drift);
  178. if (status != 0 || ticks_per_sec < 100000)
  179. printk(KERN_WARNING "unable to determine platform RTC clock frequencyn");
  180. else
  181. sn_rtc_cycles_per_second = ticks_per_sec;
  182. for (i=0;i<NR_CPUS;i++)
  183. _sn_irq_desc[i] = _irq_desc;
  184. #ifdef CONFIG_IA64_MCA
  185. platform_irq_list[ACPI20_ENTRY_PIS_CPEI] = IA64_PCE_VECTOR;
  186. #endif
  187. if ( IS_RUNNING_ON_SIMULATOR() )
  188. {
  189. #ifdef CONFIG_IA64_SGI_SN2
  190. master_node_bedrock_address = (u64)REMOTE_HUB(get_nasid(), SH_JUNK_BUS_UART0);
  191. #else
  192. master_node_bedrock_address = (u64)REMOTE_HSPEC_ADDR(get_nasid(), 0);
  193. #endif
  194. printk(KERN_DEBUG "sn_setup: setting master_node_bedrock_address to 0x%lxn",
  195.        master_node_bedrock_address);
  196. }
  197. /*
  198.  * we set the default root device to /dev/hda
  199.  * to make simulation easy
  200.  */
  201. ROOT_DEV = to_kdev_t(0x0301);
  202. /*
  203.  * Create the PDAs and NODEPDAs for all the cpus.
  204.  */
  205. sn_init_pdas(cmdline_p);
  206. /* 
  207.  * For the bootcpu, we do this here. All other cpus will make the
  208.  * call as part of cpu_init in slave cpu initialization.
  209.  */
  210. sn_cpu_init();
  211. #ifdef CONFIG_SMP
  212. init_smp_config();
  213. #endif
  214. screen_info = sn_screen_info;
  215. /*
  216.  * Turn off "floating-point assist fault" warnings by default.
  217.  */
  218. current->thread.flags |= IA64_THREAD_FPEMU_NOPRINT;
  219. }
  220. /**
  221.  * sn_init_pdas - setup node data areas
  222.  *
  223.  * One time setup for Node Data Area.  Called by sn_setup().
  224.  */
  225. void
  226. sn_init_pdas(char **cmdline_p)
  227. {
  228. cnodeid_t cnode;
  229. /*
  230.  * Make sure that the PDA fits entirely in the same page as the 
  231.  * cpu_data area.
  232.  */
  233. if ((PDAADDR&~PAGE_MASK)+sizeof(pda_t) > PAGE_SIZE)
  234. panic("overflow of cpu_data page");
  235.         /*
  236.          * Allocate & initalize the nodepda for each node.
  237.          */
  238.         for (cnode=0; cnode < numnodes; cnode++) {
  239. nodepdaindr[cnode] = alloc_bootmem_node(NODE_DATA(cnode), sizeof(nodepda_t));
  240. memset(nodepdaindr[cnode], 0, sizeof(nodepda_t));
  241. #if defined(CONFIG_IA64_SGI_SN1)
  242. Synergy_da_indr[cnode * 2] = (synergy_da_t *) alloc_bootmem_node(NODE_DATA(cnode), sizeof(synergy_da_t));
  243. Synergy_da_indr[cnode * 2 + 1] = (synergy_da_t *) alloc_bootmem_node(NODE_DATA(cnode), sizeof(synergy_da_t));
  244. memset(Synergy_da_indr[cnode * 2], 0, sizeof(synergy_da_t));
  245. memset(Synergy_da_indr[cnode * 2 + 1], 0, sizeof(synergy_da_t));
  246. #endif
  247.         }
  248. /*
  249.  * Now copy the array of nodepda pointers to each nodepda.
  250.  */
  251.         for (cnode=0; cnode < numnodes; cnode++)
  252. memcpy(nodepdaindr[cnode]->pernode_pdaindr, nodepdaindr, sizeof(nodepdaindr));
  253. /*
  254.  * Set up IO related platform-dependent nodepda fields.
  255.  * The following routine actually sets up the hubinfo struct
  256.  * in nodepda.
  257.  */
  258. for (cnode = 0; cnode < numnodes; cnode++) {
  259. init_platform_nodepda(nodepdaindr[cnode], cnode);
  260. bte_init_node (nodepdaindr[cnode], cnode, cmdline_p);
  261. }
  262. }
  263. /**
  264.  * sn_cpu_init - initialize per-cpu data areas
  265.  * @cpuid: cpuid of the caller
  266.  *
  267.  * Called during cpu initialization on each cpu as it starts.
  268.  * Currently, initializes the per-cpu data area for SNIA.
  269.  * Also sets up a few fields in the nodepda.  Also known as
  270.  * platform_cpu_init() by the ia64 machvec code.
  271.  */
  272. void __init
  273. sn_cpu_init(void)
  274. {
  275. int cpuid;
  276. int cpuphyid;
  277. int nasid;
  278. int slice;
  279. int cnode;
  280. /*
  281.  * The boot cpu makes this call again after platform initialization is
  282.  * complete.
  283.  */
  284. if (nodepdaindr[0] == NULL)
  285. return;
  286. cpuid = smp_processor_id();
  287. cpuphyid = ((ia64_get_lid() >> 16) & 0xffff);
  288. nasid = cpu_physical_id_to_nasid(cpuphyid);
  289. cnode = nasid_to_cnodeid(nasid);
  290. slice = cpu_physical_id_to_slice(cpuphyid);
  291. pda.p_nodepda = nodepdaindr[cnode];
  292. pda.led_address = (long*) (LED0 + (slice<<LED_CPU_SHIFT));
  293. pda.led_state = 0;
  294. pda.hb_count = HZ/2;
  295. pda.hb_state = 0;
  296. pda.idle_flag = 0;
  297. if (local_node_data->active_cpu_count == 1)
  298. nodepda->node_first_cpu = cpuid;
  299. #ifdef CONFIG_IA64_SGI_SN1
  300. {
  301. int synergy;
  302. synergy = cpu_physical_id_to_synergy(cpuphyid);
  303. pda.p_subnodepda = &nodepdaindr[cnode]->snpda[synergy];
  304. }
  305. #endif
  306. #ifdef CONFIG_IA64_SGI_SN2
  307. /*
  308.  * We must use different memory allocators for first cpu (bootmem 
  309.  * allocator) than for the other cpus (regular allocator).
  310.  */
  311. if (cpuid == 0)
  312. irqpdaindr[cpuid] = alloc_bootmem_node(NODE_DATA(cpuid_to_cnodeid(cpuid)),sizeof(irqpda_t));
  313. else
  314. irqpdaindr[cpuid] = page_address(alloc_pages_node(local_cnodeid(), GFP_KERNEL, get_order(sizeof(irqpda_t))));
  315. memset(irqpdaindr[cpuid], 0, sizeof(irqpda_t));
  316. pda.p_irqpda = irqpdaindr[cpuid];
  317. pda.pio_write_status_addr = (volatile unsigned long *)LOCAL_MMR_ADDR((slice < 2 ? SH_PIO_WRITE_STATUS_0 : SH_PIO_WRITE_STATUS_1 ) );
  318. #endif
  319. #ifdef CONFIG_IA64_SGI_SN1
  320. pda.bedrock_rev_id = (volatile unsigned long *) LOCAL_HUB(LB_REV_ID);
  321. if (cpuid_to_synergy(cpuid))
  322. /* CPU B */
  323. pda.pio_write_status_addr = (volatile unsigned long *) GBL_PERF_B_ADDR;
  324. else
  325. /* CPU A */
  326. pda.pio_write_status_addr = (volatile unsigned long *) GBL_PERF_A_ADDR;
  327. #endif
  328. bte_init_cpu();
  329. }
  330. /**
  331.  * cnodeid_to_cpuid - convert a cnode to a cpuid of a cpu on the node.
  332.  * @cnode: node to get a cpuid from
  333.  *
  334.  * Returns -1 if no cpus exist on the node.
  335.  * NOTE:BRINGUP ZZZ This is NOT a good way to find cpus on the node.
  336.  * Need a better way!!
  337.  */
  338. int
  339. cnodeid_to_cpuid(int cnode) {
  340. int cpu;
  341. for (cpu = 0; cpu < smp_num_cpus; cpu++)
  342. if (cpuid_to_cnodeid(cpu) == cnode)
  343. break;
  344. if (cpu == smp_num_cpus) 
  345. cpu = -1;
  346. return cpu;
  347. }
  348. #if 0 /* ##jh */
  349. /**
  350.  * get_cycles - return a non-decreasing timestamp
  351.  *
  352.  * On SN, we use an RTC read for this function
  353.  */
  354. cycles_t
  355. get_cycles (void)
  356. {
  357. return GET_RTC_COUNTER();
  358. }
  359. #endif