ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / ia64 / sn / fakeprom / fw-emu.c
1 /*
2  * PAL & SAL emulation.
3  *
4  * Copyright (C) 1998-2000 Hewlett-Packard Co
5  * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
6  *
7  *
8  * Copyright (C) 2000-2003 Silicon Graphics, Inc.  All rights reserved.
9  * 
10  * This program is free software; you can redistribute it and/or modify it 
11  * under the terms of version 2 of the GNU General Public License 
12  * as published by the Free Software Foundation.
13  * 
14  * This program is distributed in the hope that it would be useful, but 
15  * WITHOUT ANY WARRANTY; without even the implied warranty of 
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
17  * 
18  * Further, this software is distributed without any warranty that it is 
19  * free of the rightful claim of any third person regarding infringement 
20  * or the like.  Any license provided herein, whether implied or 
21  * otherwise, applies only to this software file.  Patent licenses, if 
22  * any, provided herein do not apply to combinations of this program with 
23  * other software, or any other product whatsoever.
24  * 
25  * You should have received a copy of the GNU General Public 
26  * License along with this program; if not, write the Free Software 
27  * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
28  * 
29  * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, 
30  * Mountain View, CA  94043, or:
31  * 
32  * http://www.sgi.com 
33  * 
34  * For further information regarding this notice, see: 
35  * 
36  * http://oss.sgi.com/projects/GenInfo/NoticeExplan
37  */
38 #include <linux/config.h>
39 #include <linux/efi.h>
40 #include <asm/pal.h>
41 #include <asm/sal.h>
42 #include <asm/sn/sn_sal.h>
43 #include <asm/processor.h>
44 #include <asm/sn/sn_cpuid.h>
45 #ifdef SGI_SN2
46 #include <asm/sn/sn2/addrs.h>
47 #include <asm/sn/sn2/shub_mmr.h>
48 #endif
49 #include <linux/acpi.h>
50 #include "fpmem.h"
51
52 #define RSDP_NAME               "RSDP"
53 #define RSDP_SIG                "RSD PTR "  /* RSDT Pointer signature */
54 #define APIC_SIG                "APIC"      /* Multiple APIC Description Table */
55 #define DSDT_SIG                "DSDT"      /* Differentiated System Description Table */
56 #define FADT_SIG                "FACP"      /* Fixed ACPI Description Table */
57 #define FACS_SIG                "FACS"      /* Firmware ACPI Control Structure */
58 #define PSDT_SIG                "PSDT"      /* Persistent System Description Table */
59 #define RSDT_SIG                "RSDT"      /* Root System Description Table */
60 #define XSDT_SIG                "XSDT"      /* Extended  System Description Table */
61 #define SSDT_SIG                "SSDT"      /* Secondary System Description Table */
62 #define SBST_SIG                "SBST"      /* Smart Battery Specification Table */
63 #define SPIC_SIG                "SPIC"      /* IOSAPIC table */
64 #define SRAT_SIG                "SRAT"      /* SRAT table */
65 #define SLIT_SIG                "SLIT"      /* SLIT table */
66 #define BOOT_SIG                "BOOT"      /* Boot table */
67 #define ACPI_SRAT_REVISION 1
68 #define ACPI_SLIT_REVISION 1
69
70 #define OEMID                   "SGI"
71 #ifdef SGI_SN2
72 #define PRODUCT                 "SN2"
73 #define PROXIMITY_DOMAIN(nasid) (((nasid)>>1) & 255)
74 #endif
75
76 #define MB      (1024*1024UL)
77 #define GB      (MB*1024UL)
78 #define BOOT_PARAM_ADDR 0x40000
79 #define MAX(i,j)                ((i) > (j) ? (i) : (j))
80 #define MIN(i,j)                ((i) < (j) ? (i) : (j))
81 #define ABS(i)                  ((i) > 0   ? (i) : -(i))
82 #define ALIGN8(p)               (((long)(p) +7) & ~7)
83
84 #define FPROM_BUG()             do {while (1);} while (0)
85 #define MAX_SN_NODES            128
86 #define MAX_LSAPICS             512
87 #define MAX_CPUS                512
88 #define MAX_CPUS_NODE           4
89 #define CPUS_PER_NODE           4
90 #define CPUS_PER_FSB            2
91 #define CPUS_PER_FSB_MASK       (CPUS_PER_FSB-1)
92
93 #define NUM_EFI_DESCS           2
94
95 #define RSDP_CHECKSUM_LENGTH    20
96
97 typedef union ia64_nasid_va {
98         struct {
99 #if defined(SGI_SN2)
100                 unsigned long off   : 36;       /* intra-region offset */
101                 unsigned long attr  :  2;
102                 unsigned long nasid : 11;       /* NASID */
103                 unsigned long off2  : 12;       /* fill */
104                 unsigned long reg   :  3;       /* region number */
105 #endif
106         } f;
107         unsigned long l;
108         void *p;
109 } ia64_nasid_va;
110
111 typedef struct {
112         unsigned long   pc;
113         unsigned long   gp;
114 } func_ptr_t;
115  
116 #define IS_VIRTUAL_MODE()        ({struct ia64_psr psr; asm("mov %0=psr" : "=r"(psr)); psr.dt;})
117 #define ADDR_OF(p)              (IS_VIRTUAL_MODE() ? ((void*)((long)(p)+PAGE_OFFSET)) : ((void*) (p)))
118
119 #if defined(SGI_SN2)
120 #define __fwtab_pa(n,x)         ({ia64_nasid_va _v; _v.l = (long) (x); _v.f.nasid = (x) ? (n) : 0; _v.f.reg = 0; _v.f.attr = 3; _v.l;})
121 #endif
122
123 /*
124  * The following variables are passed thru registersfrom the configuration file and
125  * are set via the _start function.
126  */
127 long            base_nasid;
128 long            num_cpus;
129 long            bsp_entry_pc=0;
130 long            num_nodes;
131 long            app_entry_pc;
132 int             bsp_lid;
133 func_ptr_t      ap_entry;
134
135
136 extern void pal_emulator(void);
137 static efi_runtime_services_t    *efi_runtime_p;
138 static char fw_mem[(  sizeof(efi_system_table_t)
139                     + sizeof(efi_runtime_services_t)
140                     + NUM_EFI_DESCS*sizeof(efi_config_table_t)
141                     + sizeof(struct ia64_sal_systab)
142                     + sizeof(struct ia64_sal_desc_entry_point)
143                     + sizeof(struct ia64_sal_desc_ap_wakeup)
144                     + sizeof(struct acpi20_table_rsdp)
145                     + sizeof(struct acpi_table_xsdt)
146                     + sizeof(struct acpi_table_slit)
147                     +   MAX_SN_NODES*MAX_SN_NODES+8
148                     + sizeof(struct acpi_table_madt)
149                     +   16*MAX_CPUS
150                     + (1+8*MAX_SN_NODES)*(sizeof(efi_memory_desc_t))
151                     + sizeof(struct acpi_table_srat)
152                     +   MAX_CPUS*sizeof(struct acpi_table_processor_affinity)
153                     +   MAX_SN_NODES*sizeof(struct acpi_table_memory_affinity)
154                     + sizeof(ia64_sal_desc_ptc_t) +
155                     + MAX_SN_NODES*sizeof(ia64_sal_ptc_domain_info_t) +
156                     + MAX_CPUS*sizeof(ia64_sal_ptc_domain_proc_entry_t) +
157                     + 1024)] __attribute__ ((aligned (8)));
158
159
160 static efi_status_t
161 efi_get_time (efi_time_t *tm, efi_time_cap_t *tc)
162 {
163         if (tm) {
164                 memset(tm, 0, sizeof(*tm));
165                 tm->year = 2000;
166                 tm->month = 2;
167                 tm->day = 13;
168                 tm->hour = 10;
169                 tm->minute = 11;
170                 tm->second = 12;
171         }
172
173         if (tc) {
174                 tc->resolution = 10;
175                 tc->accuracy = 12;
176                 tc->sets_to_zero = 1;
177         }
178
179         return EFI_SUCCESS;
180 }
181
182 static void
183 efi_reset_system (int reset_type, efi_status_t status, unsigned long data_size, efi_char16_t *data)
184 {
185         while(1);       /* Is there a pseudo-op to stop medusa */
186 }
187
188 static efi_status_t
189 efi_success (void)
190 {
191         return EFI_SUCCESS;
192 }
193
194 static efi_status_t
195 efi_unimplemented (void)
196 {
197         return EFI_UNSUPPORTED;
198 }
199
200 #ifdef SGI_SN2
201
202 #undef cpu_physical_id
203 #define cpu_physical_id(cpuid)                  ((ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff)
204
205 void
206 fprom_send_cpei(void) {
207         long            *p, val;
208         long            physid;
209         long            nasid, slice;
210
211         physid = cpu_physical_id(0);
212         nasid = cpu_physical_id_to_nasid(physid);
213         slice = cpu_physical_id_to_slice(physid);
214
215         p = (long*)GLOBAL_MMR_ADDR(nasid, SH_IPI_INT);
216         val =   (1UL<<SH_IPI_INT_SEND_SHFT) |
217                 (physid<<SH_IPI_INT_PID_SHFT) |
218                 ((long)0<<SH_IPI_INT_TYPE_SHFT) |
219                 ((long)0x1e<<SH_IPI_INT_IDX_SHFT) |
220                 (0x000feeUL<<SH_IPI_INT_BASE_SHFT);
221         *p = val;
222
223 }
224 #endif
225
226
227 static struct sal_ret_values
228 sal_emulator (long index, unsigned long in1, unsigned long in2,
229               unsigned long in3, unsigned long in4, unsigned long in5,
230               unsigned long in6, unsigned long in7)
231 {
232         long r9  = 0;
233         long r10 = 0;
234         long r11 = 0;
235         long status;
236
237         /*
238          * Don't do a "switch" here since that gives us code that
239          * isn't self-relocatable.
240          */
241         status = 0;
242         if (index == SAL_FREQ_BASE) {
243                 switch (in1) {
244                       case SAL_FREQ_BASE_PLATFORM:
245                         r9 = 500000000;
246                         break;
247
248                       case SAL_FREQ_BASE_INTERVAL_TIMER:
249                         /*
250                          * Is this supposed to be the cr.itc frequency
251                          * or something platform specific?  The SAL
252                          * doc ain't exactly clear on this...
253                          */
254                         r9 = 700000000;
255                         break;
256
257                       case SAL_FREQ_BASE_REALTIME_CLOCK:
258                         r9 = 50000000;
259                         break;
260
261                       default:
262                         status = -1;
263                         break;
264                 }
265         } else if (index == SAL_SET_VECTORS) {
266                 if (in1 == SAL_VECTOR_OS_BOOT_RENDEZ) {
267                         func_ptr_t      *fp;
268                         fp = ADDR_OF(&ap_entry);
269                         fp->pc = in2;
270                         fp->gp = in3;
271                 } else if (in1 == SAL_VECTOR_OS_MCA || in1 == SAL_VECTOR_OS_INIT) {
272                 } else {
273                         status = -1;
274                 }
275                 ;
276         } else if (index == SAL_GET_STATE_INFO) {
277                 ;
278         } else if (index == SAL_GET_STATE_INFO_SIZE) {
279                 r9 = 10000;
280                 ;
281         } else if (index == SAL_CLEAR_STATE_INFO) {
282                 ;
283         } else if (index == SAL_MC_RENDEZ) {
284                 ;
285         } else if (index == SAL_MC_SET_PARAMS) {
286                 ;
287         } else if (index == SAL_CACHE_FLUSH) {
288                 ;
289         } else if (index == SAL_CACHE_INIT) {
290                 ;
291         } else if (index == SAL_UPDATE_PAL) {
292                 ;
293 #ifdef SGI_SN2
294         } else if (index == SN_SAL_LOG_CE) {
295 #ifdef ajmtestcpei
296                 fprom_send_cpei();
297 #else /* ajmtestcpei */
298                 ;
299 #endif /* ajmtestcpei */
300 #endif
301         } else if (index == SN_SAL_PROBE) {
302                 r9 = 0UL;
303                 if (in2 == 4) {
304                         r9 = *(unsigned *)in1;
305                         if (r9 == -1) {
306                                 status = 1;
307                         }
308                 } else if (in2 == 2) {
309                         r9 = *(unsigned short *)in1;
310                         if (r9 == -1) {
311                                 status = 1;
312                         }
313                 } else if (in2 == 1) {
314                         r9 = *(unsigned char *)in1;
315                         if (r9 == -1) {
316                                 status = 1;
317                         }
318                 } else if (in2 == 8) {
319                         r9 = *(unsigned long *)in1;
320                         if (r9 == -1) {
321                                 status = 1;
322                         }
323                 } else {
324                         status = 2;
325                 }
326         } else if (index == SN_SAL_GET_KLCONFIG_ADDR) {
327                 r9 = 0x30000;
328         } else if (index == SN_SAL_CONSOLE_PUTC) {
329                 status = -1;
330         } else if (index == SN_SAL_CONSOLE_GETC) {
331                 status = -1;
332         } else if (index == SN_SAL_CONSOLE_POLL) {
333                 status = -1;
334         } else if (index == SN_SAL_SYSCTL_IOBRICK_MODULE_GET) {
335                 status = -1;
336         } else {
337                 status = -1;
338         }
339
340         asm volatile ("" :: "r"(r9), "r"(r10), "r"(r11));
341         return ((struct sal_ret_values) {status, r9, r10, r11});
342 }
343
344
345 /*
346  * This is here to work around a bug in egcs-1.1.1b that causes the
347  * compiler to crash (seems like a bug in the new alias analysis code.
348  */
349 void *
350 id (long addr)
351 {
352         return (void *) addr;
353 }
354
355
356 /*
357  * Fix the addresses in a function pointer by adding base node address
358  * to pc & gp.
359  */
360 void
361 fix_function_pointer(void *fp)
362 {
363         func_ptr_t      *_fp;
364
365         _fp = fp;
366         _fp->pc = __fwtab_pa(base_nasid, _fp->pc);
367         _fp->gp = __fwtab_pa(base_nasid, _fp->gp);
368 }
369
370 void
371 fix_virt_function_pointer(void **fptr)
372 {
373         func_ptr_t      *fp;
374         long            *p;
375
376         p = (long*)fptr;
377         fp = *fptr;
378         fp->pc = fp->pc | PAGE_OFFSET;
379         fp->gp = fp->gp | PAGE_OFFSET;
380         *p |= PAGE_OFFSET;
381 }
382
383
384 int
385 efi_set_virtual_address_map(void)
386 {
387         efi_runtime_services_t            *runtime;
388
389         runtime = efi_runtime_p;
390         fix_virt_function_pointer((void**)&runtime->get_time);
391         fix_virt_function_pointer((void**)&runtime->set_time);
392         fix_virt_function_pointer((void**)&runtime->get_wakeup_time);
393         fix_virt_function_pointer((void**)&runtime->set_wakeup_time);
394         fix_virt_function_pointer((void**)&runtime->set_virtual_address_map);
395         fix_virt_function_pointer((void**)&runtime->get_variable);
396         fix_virt_function_pointer((void**)&runtime->get_next_variable);
397         fix_virt_function_pointer((void**)&runtime->set_variable);
398         fix_virt_function_pointer((void**)&runtime->get_next_high_mono_count);
399         fix_virt_function_pointer((void**)&runtime->reset_system);
400         return EFI_SUCCESS;
401 }
402
403 void
404 acpi_table_initx(struct acpi_table_header *p, char *sig, int siglen, int revision, int oem_revision)
405 {
406         memcpy(p->signature, sig, siglen);
407         memcpy(p->oem_id, OEMID, 6);
408         memcpy(p->oem_table_id, sig, 4);
409         memcpy(p->oem_table_id+4, PRODUCT, 4);
410         p->revision = revision;
411         p->oem_revision = (revision<<16) + oem_revision;
412         memcpy(p->asl_compiler_id, "FPRM", 4);
413         p->asl_compiler_revision = 1;
414 }
415
416 void
417 acpi_checksum(struct acpi_table_header *p, int length)
418 {
419         u8      *cp, *cpe, checksum;
420
421         p->checksum = 0;
422         p->length = length;
423         checksum = 0;
424         for (cp=(u8*)p, cpe=cp+p->length; cp<cpe; cp++)
425                 checksum += *cp;
426         p->checksum = -checksum;
427 }
428
429 void
430 acpi_checksum_rsdp20(struct acpi20_table_rsdp *p, int length)
431 {
432         u8      *cp, *cpe, checksum;
433
434         p->checksum = 0;
435         p->ext_checksum = 0;
436         p->length = length;
437         checksum = 0;
438         for (cp=(u8*)p, cpe=cp+20; cp<cpe; cp++)
439                 checksum += *cp;
440         p->checksum = -checksum;
441
442         checksum = 0;
443         for (cp=(u8*)p, cpe=cp+length; cp<cpe; cp++)
444                 checksum += *cp;
445         p->ext_checksum = -checksum;
446 }
447
448 int
449 nasid_present(int nasid)
450 {
451         int     cnode;
452         for (cnode=0; cnode<num_nodes; cnode++)
453                 if (GetNasid(cnode) == nasid)
454                         return 1;
455         return 0;
456 }
457
458 void
459 sys_fw_init (const char *args, int arglen, int bsp)
460 {
461         /*
462          * Use static variables to keep from overflowing the RSE stack
463          */
464         static efi_system_table_t *efi_systab;
465         static efi_runtime_services_t *efi_runtime;
466         static efi_config_table_t *efi_tables;
467         static ia64_sal_desc_ptc_t *sal_ptc;
468         static ia64_sal_ptc_domain_info_t *sal_ptcdi;
469         static ia64_sal_ptc_domain_proc_entry_t *sal_ptclid;
470         static struct acpi20_table_rsdp *acpi20_rsdp;
471         static struct acpi_table_xsdt *acpi_xsdt;
472         static struct acpi_table_slit *acpi_slit;
473         static struct acpi_table_madt *acpi_madt;
474         static struct acpi_table_lsapic *lsapic20;
475         static struct ia64_sal_systab *sal_systab;
476         static struct acpi_table_srat *acpi_srat;
477         static struct acpi_table_processor_affinity *srat_cpu_affinity;
478         static struct acpi_table_memory_affinity *srat_memory_affinity;
479         static efi_memory_desc_t *efi_memmap, *md;
480         static unsigned long *pal_desc, *sal_desc;
481         static struct ia64_sal_desc_entry_point *sal_ed;
482         static struct ia64_boot_param *bp;
483         static struct ia64_sal_desc_ap_wakeup *sal_apwake;
484         static unsigned char checksum;
485         static char *cp, *cmd_line, *vendor;
486         static void *ptr;
487         static int mdsize, domain, last_domain ;
488         static int i, j, cnode, max_nasid, nasid, cpu, num_memmd, cpus_found;
489
490         /*
491          * Pass the parameter base address to the build_efi_xxx routines.
492          */
493 #if defined(SGI_SN2)
494         build_init(0x3000000000UL | ((long)base_nasid<<38));
495 #endif
496
497         num_nodes = GetNumNodes();
498         num_cpus = GetNumCpus();
499         for (max_nasid=0, cnode=0; cnode<num_nodes; cnode++)
500                 max_nasid = MAX(max_nasid, GetNasid(cnode));
501
502
503         memset(fw_mem, 0, sizeof(fw_mem));
504
505         pal_desc = (unsigned long *) &pal_emulator;
506         sal_desc = (unsigned long *) &sal_emulator;
507         fix_function_pointer(&pal_emulator);
508         fix_function_pointer(&sal_emulator);
509
510         /* Align this to 16 bytes, probably EFI does this  */
511         mdsize = (sizeof(efi_memory_desc_t) + 15) & ~15 ;
512
513         cp = fw_mem;
514         efi_systab  = (void *) cp; cp += ALIGN8(sizeof(*efi_systab));
515         efi_runtime_p = efi_runtime = (void *) cp; cp += ALIGN8(sizeof(*efi_runtime));
516         efi_tables  = (void *) cp; cp += ALIGN8(NUM_EFI_DESCS*sizeof(*efi_tables));
517         sal_systab  = (void *) cp; cp += ALIGN8(sizeof(*sal_systab));
518         sal_ed      = (void *) cp; cp += ALIGN8(sizeof(*sal_ed));
519         sal_ptc     = (void *) cp; cp += ALIGN8(sizeof(*sal_ptc));
520         sal_apwake  = (void *) cp; cp += ALIGN8(sizeof(*sal_apwake));
521         acpi20_rsdp = (void *) cp; cp += ALIGN8(sizeof(*acpi20_rsdp));
522         acpi_xsdt   = (void *) cp; cp += ALIGN8(sizeof(*acpi_xsdt) + 64); 
523                         /* save space for more OS defined table pointers. */
524
525         acpi_slit   = (void *) cp; cp += ALIGN8(sizeof(*acpi_slit) + 8 + (max_nasid+1)*(max_nasid+1));
526         acpi_madt   = (void *) cp; cp += ALIGN8(sizeof(*acpi_madt) + sizeof(struct acpi_table_lsapic) * (num_cpus+1));
527         acpi_srat   = (void *) cp; cp += ALIGN8(sizeof(struct acpi_table_srat));
528         cp         += sizeof(struct acpi_table_processor_affinity)*num_cpus + sizeof(struct acpi_table_memory_affinity)*num_nodes;
529         vendor      = (char *) cp; cp += ALIGN8(40);
530         efi_memmap  = (void *) cp; cp += ALIGN8(8*32*sizeof(*efi_memmap));
531         sal_ptcdi   = (void *) cp; cp += ALIGN8(CPUS_PER_FSB*(1+num_nodes)*sizeof(*sal_ptcdi));
532         sal_ptclid  = (void *) cp; cp += ALIGN8(((3+num_cpus)*sizeof(*sal_ptclid)+7)/8*8);
533         cmd_line    = (void *) cp;
534
535         if (args) {
536                 if (arglen >= 1024)
537                         arglen = 1023;
538                 memcpy(cmd_line, args, arglen);
539         } else {
540                 arglen = 0;
541         }
542         cmd_line[arglen] = '\0';
543         /* 
544          * For now, just bring up bash.
545          * If you want to execute all the startup scripts, delete the "init=..".
546          * You can also edit this line to pass other arguments to the kernel.
547          *    Note: disable kernel text replication.
548          */
549         strcpy(cmd_line, "init=/bin/bash console=ttyS0");
550
551         memset(efi_systab, 0, sizeof(efi_systab));
552         efi_systab->hdr.signature = EFI_SYSTEM_TABLE_SIGNATURE;
553         efi_systab->hdr.revision  = EFI_SYSTEM_TABLE_REVISION;
554         efi_systab->hdr.headersize = sizeof(efi_systab->hdr);
555         efi_systab->fw_vendor = __fwtab_pa(base_nasid, vendor);
556         efi_systab->fw_revision = 1;
557         efi_systab->runtime = __fwtab_pa(base_nasid, efi_runtime);
558         efi_systab->nr_tables = 2;
559         efi_systab->tables = __fwtab_pa(base_nasid, efi_tables);
560         memcpy(vendor, "S\0i\0l\0i\0c\0o\0n\0-\0G\0r\0a\0p\0h\0i\0c\0s\0\0", 40);
561
562         efi_runtime->hdr.signature = EFI_RUNTIME_SERVICES_SIGNATURE;
563         efi_runtime->hdr.revision = EFI_RUNTIME_SERVICES_REVISION;
564         efi_runtime->hdr.headersize = sizeof(efi_runtime->hdr);
565         efi_runtime->get_time = __fwtab_pa(base_nasid, &efi_get_time);
566         efi_runtime->set_time = __fwtab_pa(base_nasid, &efi_unimplemented);
567         efi_runtime->get_wakeup_time = __fwtab_pa(base_nasid, &efi_unimplemented);
568         efi_runtime->set_wakeup_time = __fwtab_pa(base_nasid, &efi_unimplemented);
569         efi_runtime->set_virtual_address_map = __fwtab_pa(base_nasid, &efi_set_virtual_address_map);
570         efi_runtime->get_variable = __fwtab_pa(base_nasid, &efi_unimplemented);
571         efi_runtime->get_next_variable = __fwtab_pa(base_nasid, &efi_unimplemented);
572         efi_runtime->set_variable = __fwtab_pa(base_nasid, &efi_unimplemented);
573         efi_runtime->get_next_high_mono_count = __fwtab_pa(base_nasid, &efi_unimplemented);
574         efi_runtime->reset_system = __fwtab_pa(base_nasid, &efi_reset_system);
575
576         efi_tables->guid = SAL_SYSTEM_TABLE_GUID;
577         efi_tables->table = __fwtab_pa(base_nasid, sal_systab);
578         efi_tables++;
579         efi_tables->guid = ACPI_20_TABLE_GUID;
580         efi_tables->table = __fwtab_pa(base_nasid, acpi20_rsdp);
581         efi_tables++;
582
583         fix_function_pointer(&efi_unimplemented);
584         fix_function_pointer(&efi_get_time);
585         fix_function_pointer(&efi_success);
586         fix_function_pointer(&efi_reset_system);
587         fix_function_pointer(&efi_set_virtual_address_map);
588
589
590         /* fill in the ACPI20 system table - has a pointer to the ACPI table header */
591         memcpy(acpi20_rsdp->signature, "RSD PTR ", 8);
592         acpi20_rsdp->xsdt_address = (u64)__fwtab_pa(base_nasid, acpi_xsdt);
593         acpi20_rsdp->revision = 2;
594         acpi_checksum_rsdp20(acpi20_rsdp, sizeof(struct acpi20_table_rsdp));
595
596         /* Set up the XSDT table  - contains pointers to the other ACPI tables */
597         acpi_table_initx(&acpi_xsdt->header, XSDT_SIG, 4, 1, 1);
598         acpi_xsdt->entry[0] = __fwtab_pa(base_nasid, acpi_madt);
599         acpi_xsdt->entry[1] = __fwtab_pa(base_nasid, acpi_slit);
600         acpi_xsdt->entry[2] = __fwtab_pa(base_nasid, acpi_srat);
601         acpi_checksum(&acpi_xsdt->header, sizeof(struct acpi_table_xsdt) + 16);
602
603         /* Set up the APIC table */
604         acpi_table_initx(&acpi_madt->header, APIC_SIG, 4, 1, 1);
605         lsapic20 = (struct acpi_table_lsapic*) (acpi_madt + 1);
606         for (cnode=0; cnode<num_nodes; cnode++) {
607                 nasid = GetNasid(cnode);
608                 for(cpu=0; cpu<CPUS_PER_NODE; cpu++) {
609                         if (!IsCpuPresent(cnode, cpu))
610                                 continue;
611                         lsapic20->header.type = ACPI_MADT_LSAPIC;
612                         lsapic20->header.length = sizeof(struct acpi_table_lsapic);
613                         lsapic20->acpi_id = cnode*4+cpu;
614                         lsapic20->flags.enabled = 1;
615 #if defined(SGI_SN2)
616                         lsapic20->eid = nasid&0xffff;
617                         lsapic20->id = (cpu<<4) | (nasid>>16);
618 #endif
619                         lsapic20 = (struct acpi_table_lsapic*) ((long)lsapic20+sizeof(struct acpi_table_lsapic));
620                 }
621         }
622         acpi_checksum(&acpi_madt->header, (char*)lsapic20 - (char*)acpi_madt);
623
624         /* Set up the SRAT table */
625         acpi_table_initx(&acpi_srat->header, SRAT_SIG, 4, ACPI_SRAT_REVISION, 1);
626         ptr = acpi_srat+1;
627         for (cnode=0; cnode<num_nodes; cnode++) {
628                 nasid = GetNasid(cnode);
629                 srat_memory_affinity = ptr;
630                 ptr = srat_memory_affinity+1;
631                 srat_memory_affinity->header.type = ACPI_SRAT_MEMORY_AFFINITY;
632                 srat_memory_affinity->header.length = sizeof(struct acpi_table_memory_affinity);
633                 srat_memory_affinity->proximity_domain = PROXIMITY_DOMAIN(nasid);
634                 srat_memory_affinity->base_addr_lo = 0;
635                 srat_memory_affinity->length_lo = 0;
636 #if defined(SGI_SN2)
637                 srat_memory_affinity->base_addr_hi = (nasid<<6) | (3<<4);
638                 srat_memory_affinity->length_hi = (MD_BANKSIZE*MD_BANKS_PER_NODE)>>32;
639 #endif
640                 srat_memory_affinity->memory_type = ACPI_ADDRESS_RANGE_MEMORY;
641                 srat_memory_affinity->flags.enabled = 1;
642         }
643
644         for (cnode=0; cnode<num_nodes; cnode++) {
645                 nasid = GetNasid(cnode);
646                 for(cpu=0; cpu<CPUS_PER_NODE; cpu++) {
647                         if (!IsCpuPresent(cnode, cpu))
648                                 continue;
649                         srat_cpu_affinity = ptr;
650                         ptr = srat_cpu_affinity + 1;
651                         srat_cpu_affinity->header.type = ACPI_SRAT_PROCESSOR_AFFINITY;
652                         srat_cpu_affinity->header.length = sizeof(struct acpi_table_processor_affinity);
653                         srat_cpu_affinity->proximity_domain = PROXIMITY_DOMAIN(nasid);
654                         srat_cpu_affinity->flags.enabled = 1;
655 #if defined(SGI_SN2)
656                         srat_cpu_affinity->lsapic_eid = nasid&0xffff;
657                         srat_cpu_affinity->apic_id = (cpu<<4) | (nasid>>16);
658 #endif
659                 }
660         }
661         acpi_checksum(&acpi_srat->header, (char*)ptr - (char*)acpi_srat);
662
663
664         /* Set up the SLIT table */
665         acpi_table_initx(&acpi_slit->header, SLIT_SIG, 4, ACPI_SLIT_REVISION, 1);
666         acpi_slit->localities = PROXIMITY_DOMAIN(max_nasid)+1;
667         cp=acpi_slit->entry;
668         memset(cp, 255, acpi_slit->localities*acpi_slit->localities);
669
670         for (i=0; i<=max_nasid; i++)
671                 for (j=0; j<=max_nasid; j++)
672                         if (nasid_present(i) && nasid_present(j))
673                                 *(cp+PROXIMITY_DOMAIN(i)*acpi_slit->localities+PROXIMITY_DOMAIN(j)) = 10 + MIN(254, 5*ABS(i-j));
674
675         cp = acpi_slit->entry + acpi_slit->localities*acpi_slit->localities;
676         acpi_checksum(&acpi_slit->header, cp - (char*)acpi_slit);
677
678
679         /* fill in the SAL system table: */
680         memcpy(sal_systab->signature, "SST_", 4);
681         sal_systab->size = sizeof(*sal_systab);
682         sal_systab->sal_rev_minor = 1;
683         sal_systab->sal_rev_major = 0;
684         sal_systab->entry_count = 3;
685         sal_systab->sal_b_rev_major = 0x1; /* set the SN SAL rev to */
686         sal_systab->sal_b_rev_minor = 0x0; /* 1.00 */
687
688         strcpy(sal_systab->oem_id, "SGI");
689         strcpy(sal_systab->product_id, "SN2");
690
691         /* fill in an entry point: */   
692         sal_ed->type = SAL_DESC_ENTRY_POINT;
693         sal_ed->pal_proc = __fwtab_pa(base_nasid, pal_desc[0]);
694         sal_ed->sal_proc = __fwtab_pa(base_nasid, sal_desc[0]);
695         sal_ed->gp = __fwtab_pa(base_nasid, sal_desc[1]);
696
697         /* kludge the PTC domain info */
698         sal_ptc->type = SAL_DESC_PTC;
699         sal_ptc->num_domains = 0;
700         sal_ptc->domain_info = __fwtab_pa(base_nasid, sal_ptcdi);
701         cpus_found = 0;
702         last_domain = -1;
703         sal_ptcdi--;
704         for (cnode=0; cnode<num_nodes; cnode++) {
705                 nasid = GetNasid(cnode);
706                 for(cpu=0; cpu<CPUS_PER_NODE; cpu++) {
707                         if (IsCpuPresent(cnode, cpu)) {
708                                 domain = cnode*CPUS_PER_NODE + cpu/CPUS_PER_FSB;
709                                 if (domain != last_domain) {
710                                         sal_ptc->num_domains++;
711                                         sal_ptcdi++;
712                                         sal_ptcdi->proc_count = 0;
713                                         sal_ptcdi->proc_list = __fwtab_pa(base_nasid, sal_ptclid);
714                                         last_domain = domain;
715                                 }
716                                 sal_ptcdi->proc_count++;
717                                 sal_ptclid->id = nasid;
718                                 sal_ptclid->eid = cpu;
719                                 sal_ptclid++;
720                                 cpus_found++;
721                         }
722                 }
723         }
724
725         if (cpus_found != num_cpus)
726                 FPROM_BUG();
727
728         /* Make the AP WAKEUP entry */
729         sal_apwake->type = SAL_DESC_AP_WAKEUP;
730         sal_apwake->mechanism = IA64_SAL_AP_EXTERNAL_INT;
731         sal_apwake->vector = 18;
732
733         for (checksum=0, cp=(char*)sal_systab; cp < (char *)efi_memmap; ++cp)
734                 checksum += *cp;
735         sal_systab->checksum = -checksum;
736
737         /* If the checksum is correct, the kernel tries to use the
738          * table. We dont build enough table & the kernel aborts.
739          * Note that the PROM hasd thhhe same problem!!
740          */
741
742         md = &efi_memmap[0];
743         num_memmd = build_efi_memmap((void *)md, mdsize) ;
744
745         bp = (struct ia64_boot_param*) __fwtab_pa(base_nasid, BOOT_PARAM_ADDR);
746         bp->efi_systab = __fwtab_pa(base_nasid, &fw_mem);
747         bp->efi_memmap = __fwtab_pa(base_nasid, efi_memmap);
748         bp->efi_memmap_size = num_memmd*mdsize;
749         bp->efi_memdesc_size = mdsize;
750         bp->efi_memdesc_version = 0x101;
751         bp->command_line = __fwtab_pa(base_nasid, cmd_line);
752         bp->console_info.num_cols = 80;
753         bp->console_info.num_rows = 25;
754         bp->console_info.orig_x = 0;
755         bp->console_info.orig_y = 24;
756         bp->fpswa = 0;
757
758         /*
759          * Now pick the BSP & store it LID value in
760          * a global variable. Note if BSP is greater than last cpu,
761          * pick the last cpu.
762          */
763         for (cnode=0; cnode<num_nodes; cnode++) {
764                 for(cpu=0; cpu<CPUS_PER_NODE; cpu++) {
765                         if (!IsCpuPresent(cnode, cpu))
766                                 continue;
767 #ifdef SGI_SN2
768                         bsp_lid = (GetNasid(cnode)<<16) | (cpu<<28);
769 #endif
770                         if (bsp-- > 0)
771                                 continue;
772                         return;
773                 }
774         }
775 }