vserver 1.9.3
[linux-2.6.git] / include / asm-ia64 / sn / sn_sal.h
1 #ifndef _ASM_IA64_SN_SN_SAL_H
2 #define _ASM_IA64_SN_SN_SAL_H
3
4 /*
5  * System Abstraction Layer definitions for IA64
6  *
7  * This file is subject to the terms and conditions of the GNU General Public
8  * License.  See the file "COPYING" in the main directory of this archive
9  * for more details.
10  *
11  * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All rights reserved.
12  */
13
14
15 #include <linux/config.h>
16 #include <asm/sal.h>
17 #include <asm/sn/sn_cpuid.h>
18 #include <asm/sn/arch.h>
19 #include <asm/sn/nodepda.h>
20 #include <asm/sn/klconfig.h>
21         
22
23 // SGI Specific Calls
24 #define  SN_SAL_POD_MODE                           0x02000001
25 #define  SN_SAL_SYSTEM_RESET                       0x02000002
26 #define  SN_SAL_PROBE                              0x02000003
27 #define  SN_SAL_GET_MASTER_NASID                   0x02000004
28 #define  SN_SAL_GET_KLCONFIG_ADDR                  0x02000005
29 #define  SN_SAL_LOG_CE                             0x02000006
30 #define  SN_SAL_REGISTER_CE                        0x02000007
31 #define  SN_SAL_GET_PARTITION_ADDR                 0x02000009
32 #define  SN_SAL_XP_ADDR_REGION                     0x0200000f
33 #define  SN_SAL_NO_FAULT_ZONE_VIRTUAL              0x02000010
34 #define  SN_SAL_NO_FAULT_ZONE_PHYSICAL             0x02000011
35 #define  SN_SAL_PRINT_ERROR                        0x02000012
36 #define  SN_SAL_SET_ERROR_HANDLING_FEATURES        0x0200001a   // reentrant
37 #define  SN_SAL_GET_FIT_COMPT                      0x0200001b   // reentrant
38 #define  SN_SAL_CONSOLE_PUTC                       0x02000021
39 #define  SN_SAL_CONSOLE_GETC                       0x02000022
40 #define  SN_SAL_CONSOLE_PUTS                       0x02000023
41 #define  SN_SAL_CONSOLE_GETS                       0x02000024
42 #define  SN_SAL_CONSOLE_GETS_TIMEOUT               0x02000025
43 #define  SN_SAL_CONSOLE_POLL                       0x02000026
44 #define  SN_SAL_CONSOLE_INTR                       0x02000027
45 #define  SN_SAL_CONSOLE_PUTB                       0x02000028
46 #define  SN_SAL_CONSOLE_XMIT_CHARS                 0x0200002a
47 #define  SN_SAL_CONSOLE_READC                      0x0200002b
48 #define  SN_SAL_SYSCTL_MODID_GET                   0x02000031
49 #define  SN_SAL_SYSCTL_GET                         0x02000032
50 #define  SN_SAL_SYSCTL_IOBRICK_MODULE_GET          0x02000033
51 #define  SN_SAL_SYSCTL_IO_PORTSPEED_GET            0x02000035
52 #define  SN_SAL_SYSCTL_SLAB_GET                    0x02000036
53 #define  SN_SAL_BUS_CONFIG                         0x02000037
54 #define  SN_SAL_SYS_SERIAL_GET                     0x02000038
55 #define  SN_SAL_PARTITION_SERIAL_GET               0x02000039
56 #define  SN_SAL_SYSCTL_PARTITION_GET               0x0200003a
57 #define  SN_SAL_SYSTEM_POWER_DOWN                  0x0200003b
58 #define  SN_SAL_GET_MASTER_BASEIO_NASID            0x0200003c
59 #define  SN_SAL_COHERENCE                          0x0200003d
60 #define  SN_SAL_MEMPROTECT                         0x0200003e
61 #define  SN_SAL_SYSCTL_FRU_CAPTURE                 0x0200003f
62
63 #define  SN_SAL_SYSCTL_IOBRICK_PCI_OP              0x02000042   // reentrant
64 #define  SN_SAL_IROUTER_OP                         0x02000043
65 #define  SN_SAL_HWPERF_OP                          0x02000050   // lock
66
67 /*
68  * Service-specific constants
69  */
70
71 /* Console interrupt manipulation */
72         /* action codes */
73 #define SAL_CONSOLE_INTR_OFF    0       /* turn the interrupt off */
74 #define SAL_CONSOLE_INTR_ON     1       /* turn the interrupt on */
75 #define SAL_CONSOLE_INTR_STATUS 2       /* retrieve the interrupt status */
76         /* interrupt specification & status return codes */
77 #define SAL_CONSOLE_INTR_XMIT   1       /* output interrupt */
78 #define SAL_CONSOLE_INTR_RECV   2       /* input interrupt */
79
80 #ifdef CONFIG_HOTPLUG_PCI_SGI
81 /* power up / power down / reset a PCI slot or bus */
82 #define SAL_SYSCTL_PCI_POWER_UP         0
83 #define SAL_SYSCTL_PCI_POWER_DOWN       1
84 #define SAL_SYSCTL_PCI_RESET            2
85
86 /* what type of I/O brick? */
87 #define SAL_SYSCTL_IO_XTALK     0       /* connected via a compute node */
88
89 #endif  /* CONFIG_HOTPLUG_PCI_SGI */
90
91 /*
92  * IRouter (i.e. generalized system controller) operations
93  */
94 #define SAL_IROUTER_OPEN        0       /* open a subchannel */
95 #define SAL_IROUTER_CLOSE       1       /* close a subchannel */
96 #define SAL_IROUTER_SEND        2       /* send part of an IRouter packet */
97 #define SAL_IROUTER_RECV        3       /* receive part of an IRouter packet */
98 #define SAL_IROUTER_INTR_STATUS 4       /* check the interrupt status for
99                                          * an open subchannel
100                                          */
101 #define SAL_IROUTER_INTR_ON     5       /* enable an interrupt */
102 #define SAL_IROUTER_INTR_OFF    6       /* disable an interrupt */
103 #define SAL_IROUTER_INIT        7       /* initialize IRouter driver */
104
105 /* IRouter interrupt mask bits */
106 #define SAL_IROUTER_INTR_XMIT   SAL_CONSOLE_INTR_XMIT
107 #define SAL_IROUTER_INTR_RECV   SAL_CONSOLE_INTR_RECV
108
109
110 /*
111  * SAL Error Codes
112  */
113 #define SALRET_MORE_PASSES      1
114 #define SALRET_OK               0
115 #define SALRET_NOT_IMPLEMENTED  (-1)
116 #define SALRET_INVALID_ARG      (-2)
117 #define SALRET_ERROR            (-3)
118
119 /*
120  * SN_SAL_SET_ERROR_HANDLING_FEATURES bit settings
121  */
122 enum 
123 {
124         /* if "rz always" is set, have the mca slaves call os_init_slave */
125         SN_SAL_EHF_MCA_SLV_TO_OS_INIT_SLV=0,
126         /* do not rz on tlb checks, even if "rz always" is set */
127         SN_SAL_EHF_NO_RZ_TLBC,
128         /* do not rz on PIO reads to I/O space, even if "rz always" is set */
129         SN_SAL_EHF_NO_RZ_IO_READ,
130 };
131
132
133 /**
134  * sn_sal_rev_major - get the major SGI SAL revision number
135  *
136  * The SGI PROM stores its version in sal_[ab]_rev_(major|minor).
137  * This routine simply extracts the major value from the
138  * @ia64_sal_systab structure constructed by ia64_sal_init().
139  */
140 static inline int
141 sn_sal_rev_major(void)
142 {
143         struct ia64_sal_systab *systab = efi.sal_systab;
144
145         return (int)systab->sal_b_rev_major;
146 }
147
148 /**
149  * sn_sal_rev_minor - get the minor SGI SAL revision number
150  *
151  * The SGI PROM stores its version in sal_[ab]_rev_(major|minor).
152  * This routine simply extracts the minor value from the
153  * @ia64_sal_systab structure constructed by ia64_sal_init().
154  */
155 static inline int
156 sn_sal_rev_minor(void)
157 {
158         struct ia64_sal_systab *systab = efi.sal_systab;
159         
160         return (int)systab->sal_b_rev_minor;
161 }
162
163 /*
164  * Specify the minimum PROM revsion required for this kernel.
165  * Note that they're stored in hex format...
166  */
167 #define SN_SAL_MIN_MAJOR        0x3  /* SN2 kernels need at least PROM 3.40 */
168 #define SN_SAL_MIN_MINOR        0x40
169
170 u64 ia64_sn_probe_io_slot(long paddr, long size, void *data_ptr);
171
172 /*
173  * Returns the master console nasid, if the call fails, return an illegal
174  * value.
175  */
176 static inline u64
177 ia64_sn_get_console_nasid(void)
178 {
179         struct ia64_sal_retval ret_stuff;
180
181         ret_stuff.status = 0;
182         ret_stuff.v0 = 0;
183         ret_stuff.v1 = 0;
184         ret_stuff.v2 = 0;
185         SAL_CALL(ret_stuff, SN_SAL_GET_MASTER_NASID, 0, 0, 0, 0, 0, 0, 0);
186
187         if (ret_stuff.status < 0)
188                 return ret_stuff.status;
189
190         /* Master console nasid is in 'v0' */
191         return ret_stuff.v0;
192 }
193
194 /*
195  * Returns the master baseio nasid, if the call fails, return an illegal
196  * value.
197  */
198 static inline u64
199 ia64_sn_get_master_baseio_nasid(void)
200 {
201         struct ia64_sal_retval ret_stuff;
202
203         ret_stuff.status = 0;
204         ret_stuff.v0 = 0;
205         ret_stuff.v1 = 0;
206         ret_stuff.v2 = 0;
207         SAL_CALL(ret_stuff, SN_SAL_GET_MASTER_BASEIO_NASID, 0, 0, 0, 0, 0, 0, 0);
208
209         if (ret_stuff.status < 0)
210                 return ret_stuff.status;
211
212         /* Master baseio nasid is in 'v0' */
213         return ret_stuff.v0;
214 }
215
216 static inline u64
217 ia64_sn_get_klconfig_addr(nasid_t nasid)
218 {
219         struct ia64_sal_retval ret_stuff;
220         int cnodeid;
221
222         cnodeid = nasid_to_cnodeid(nasid);
223         ret_stuff.status = 0;
224         ret_stuff.v0 = 0;
225         ret_stuff.v1 = 0;
226         ret_stuff.v2 = 0;
227         SAL_CALL(ret_stuff, SN_SAL_GET_KLCONFIG_ADDR, (u64)nasid, 0, 0, 0, 0, 0, 0);
228
229         /*
230          * We should panic if a valid cnode nasid does not produce
231          * a klconfig address.
232          */
233         if (ret_stuff.status != 0) {
234                 panic("ia64_sn_get_klconfig_addr: Returned error %lx\n", ret_stuff.status);
235         }
236         return(ret_stuff.v0);
237 }
238
239 /*
240  * Returns the next console character.
241  */
242 static inline u64
243 ia64_sn_console_getc(int *ch)
244 {
245         struct ia64_sal_retval ret_stuff;
246
247         ret_stuff.status = 0;
248         ret_stuff.v0 = 0;
249         ret_stuff.v1 = 0;
250         ret_stuff.v2 = 0;
251         SAL_CALL_NOLOCK(ret_stuff, SN_SAL_CONSOLE_GETC, 0, 0, 0, 0, 0, 0, 0);
252
253         /* character is in 'v0' */
254         *ch = (int)ret_stuff.v0;
255
256         return ret_stuff.status;
257 }
258
259 /*
260  * Read a character from the SAL console device, after a previous interrupt
261  * or poll operation has given us to know that a character is available
262  * to be read.
263  */
264 static inline u64
265 ia64_sn_console_readc(void)
266 {
267         struct ia64_sal_retval ret_stuff;
268
269         ret_stuff.status = 0;
270         ret_stuff.v0 = 0;
271         ret_stuff.v1 = 0;
272         ret_stuff.v2 = 0;
273         SAL_CALL_NOLOCK(ret_stuff, SN_SAL_CONSOLE_READC, 0, 0, 0, 0, 0, 0, 0);
274
275         /* character is in 'v0' */
276         return ret_stuff.v0;
277 }
278
279 /*
280  * Sends the given character to the console.
281  */
282 static inline u64
283 ia64_sn_console_putc(char ch)
284 {
285         struct ia64_sal_retval ret_stuff;
286
287         ret_stuff.status = 0;
288         ret_stuff.v0 = 0;
289         ret_stuff.v1 = 0;
290         ret_stuff.v2 = 0;
291         SAL_CALL_NOLOCK(ret_stuff, SN_SAL_CONSOLE_PUTC, (uint64_t)ch, 0, 0, 0, 0, 0, 0);
292
293         return ret_stuff.status;
294 }
295
296 /*
297  * Sends the given buffer to the console.
298  */
299 static inline u64
300 ia64_sn_console_putb(const char *buf, int len)
301 {
302         struct ia64_sal_retval ret_stuff;
303
304         ret_stuff.status = 0;
305         ret_stuff.v0 = 0; 
306         ret_stuff.v1 = 0;
307         ret_stuff.v2 = 0;
308         SAL_CALL_NOLOCK(ret_stuff, SN_SAL_CONSOLE_PUTB, (uint64_t)buf, (uint64_t)len, 0, 0, 0, 0, 0);
309
310         if ( ret_stuff.status == 0 ) {
311                 return ret_stuff.v0;
312         }
313         return (u64)0;
314 }
315
316 /*
317  * Print a platform error record
318  */
319 static inline u64
320 ia64_sn_plat_specific_err_print(int (*hook)(const char*, ...), char *rec)
321 {
322         struct ia64_sal_retval ret_stuff;
323
324         ret_stuff.status = 0;
325         ret_stuff.v0 = 0;
326         ret_stuff.v1 = 0;
327         ret_stuff.v2 = 0;
328         SAL_CALL_REENTRANT(ret_stuff, SN_SAL_PRINT_ERROR, (uint64_t)hook, (uint64_t)rec, 0, 0, 0, 0, 0);
329
330         return ret_stuff.status;
331 }
332
333 /*
334  * Check for Platform errors
335  */
336 static inline u64
337 ia64_sn_plat_cpei_handler(void)
338 {
339         struct ia64_sal_retval ret_stuff;
340
341         ret_stuff.status = 0;
342         ret_stuff.v0 = 0;
343         ret_stuff.v1 = 0;
344         ret_stuff.v2 = 0;
345         SAL_CALL_NOLOCK(ret_stuff, SN_SAL_LOG_CE, 0, 0, 0, 0, 0, 0, 0);
346
347         return ret_stuff.status;
348 }
349
350 /*
351  * Checks for console input.
352  */
353 static inline u64
354 ia64_sn_console_check(int *result)
355 {
356         struct ia64_sal_retval ret_stuff;
357
358         ret_stuff.status = 0;
359         ret_stuff.v0 = 0;
360         ret_stuff.v1 = 0;
361         ret_stuff.v2 = 0;
362         SAL_CALL_NOLOCK(ret_stuff, SN_SAL_CONSOLE_POLL, 0, 0, 0, 0, 0, 0, 0);
363
364         /* result is in 'v0' */
365         *result = (int)ret_stuff.v0;
366
367         return ret_stuff.status;
368 }
369
370 /*
371  * Checks console interrupt status
372  */
373 static inline u64
374 ia64_sn_console_intr_status(void)
375 {
376         struct ia64_sal_retval ret_stuff;
377
378         ret_stuff.status = 0;
379         ret_stuff.v0 = 0;
380         ret_stuff.v1 = 0;
381         ret_stuff.v2 = 0;
382         SAL_CALL_NOLOCK(ret_stuff, SN_SAL_CONSOLE_INTR, 
383                  0, SAL_CONSOLE_INTR_STATUS,
384                  0, 0, 0, 0, 0);
385
386         if (ret_stuff.status == 0) {
387             return ret_stuff.v0;
388         }
389         
390         return 0;
391 }
392
393 /*
394  * Enable an interrupt on the SAL console device.
395  */
396 static inline void
397 ia64_sn_console_intr_enable(uint64_t intr)
398 {
399         struct ia64_sal_retval ret_stuff;
400
401         ret_stuff.status = 0;
402         ret_stuff.v0 = 0;
403         ret_stuff.v1 = 0;
404         ret_stuff.v2 = 0;
405         SAL_CALL_NOLOCK(ret_stuff, SN_SAL_CONSOLE_INTR, 
406                  intr, SAL_CONSOLE_INTR_ON,
407                  0, 0, 0, 0, 0);
408 }
409
410 /*
411  * Disable an interrupt on the SAL console device.
412  */
413 static inline void
414 ia64_sn_console_intr_disable(uint64_t intr)
415 {
416         struct ia64_sal_retval ret_stuff;
417
418         ret_stuff.status = 0;
419         ret_stuff.v0 = 0;
420         ret_stuff.v1 = 0;
421         ret_stuff.v2 = 0;
422         SAL_CALL_NOLOCK(ret_stuff, SN_SAL_CONSOLE_INTR, 
423                  intr, SAL_CONSOLE_INTR_OFF,
424                  0, 0, 0, 0, 0);
425 }
426
427 /*
428  * Sends a character buffer to the console asynchronously.
429  */
430 static inline u64
431 ia64_sn_console_xmit_chars(char *buf, int len)
432 {
433         struct ia64_sal_retval ret_stuff;
434
435         ret_stuff.status = 0;
436         ret_stuff.v0 = 0;
437         ret_stuff.v1 = 0;
438         ret_stuff.v2 = 0;
439         SAL_CALL_NOLOCK(ret_stuff, SN_SAL_CONSOLE_XMIT_CHARS,
440                  (uint64_t)buf, (uint64_t)len,
441                  0, 0, 0, 0, 0);
442
443         if (ret_stuff.status == 0) {
444             return ret_stuff.v0;
445         }
446
447         return 0;
448 }
449
450 /*
451  * Returns the iobrick module Id
452  */
453 static inline u64
454 ia64_sn_sysctl_iobrick_module_get(nasid_t nasid, int *result)
455 {
456         struct ia64_sal_retval ret_stuff;
457
458         ret_stuff.status = 0;
459         ret_stuff.v0 = 0;
460         ret_stuff.v1 = 0;
461         ret_stuff.v2 = 0;
462         SAL_CALL_NOLOCK(ret_stuff, SN_SAL_SYSCTL_IOBRICK_MODULE_GET, nasid, 0, 0, 0, 0, 0, 0);
463
464         /* result is in 'v0' */
465         *result = (int)ret_stuff.v0;
466
467         return ret_stuff.status;
468 }
469
470 /**
471  * ia64_sn_pod_mode - call the SN_SAL_POD_MODE function
472  *
473  * SN_SAL_POD_MODE actually takes an argument, but it's always
474  * 0 when we call it from the kernel, so we don't have to expose
475  * it to the caller.
476  */
477 static inline u64
478 ia64_sn_pod_mode(void)
479 {
480         struct ia64_sal_retval isrv;
481         SAL_CALL(isrv, SN_SAL_POD_MODE, 0, 0, 0, 0, 0, 0, 0);
482         if (isrv.status)
483                 return 0;
484         return isrv.v0;
485 }
486
487 /*
488  * Retrieve the system serial number as an ASCII string.
489  */
490 static inline u64
491 ia64_sn_sys_serial_get(char *buf)
492 {
493         struct ia64_sal_retval ret_stuff;
494         SAL_CALL_NOLOCK(ret_stuff, SN_SAL_SYS_SERIAL_GET, buf, 0, 0, 0, 0, 0, 0);
495         return ret_stuff.status;
496 }
497
498 extern char sn_system_serial_number_string[];
499 extern u64 sn_partition_serial_number;
500
501 static inline char *
502 sn_system_serial_number(void) {
503         if (sn_system_serial_number_string[0]) {
504                 return(sn_system_serial_number_string);
505         } else {
506                 ia64_sn_sys_serial_get(sn_system_serial_number_string);
507                 return(sn_system_serial_number_string);
508         }
509 }
510         
511
512 /*
513  * Returns a unique id number for this system and partition (suitable for
514  * use with license managers), based in part on the system serial number.
515  */
516 static inline u64
517 ia64_sn_partition_serial_get(void)
518 {
519         struct ia64_sal_retval ret_stuff;
520         SAL_CALL(ret_stuff, SN_SAL_PARTITION_SERIAL_GET, 0, 0, 0, 0, 0, 0, 0);
521         if (ret_stuff.status != 0)
522             return 0;
523         return ret_stuff.v0;
524 }
525
526 static inline u64
527 sn_partition_serial_number_val(void) {
528         if (sn_partition_serial_number) {
529                 return(sn_partition_serial_number);
530         } else {
531                 return(sn_partition_serial_number = ia64_sn_partition_serial_get());
532         }
533 }
534
535 /*
536  * Returns the partition id of the nasid passed in as an argument,
537  * or INVALID_PARTID if the partition id cannot be retrieved.
538  */
539 static inline partid_t
540 ia64_sn_sysctl_partition_get(nasid_t nasid)
541 {
542         struct ia64_sal_retval ret_stuff;
543         SAL_CALL(ret_stuff, SN_SAL_SYSCTL_PARTITION_GET, nasid,
544                  0, 0, 0, 0, 0, 0);
545         if (ret_stuff.status != 0)
546             return INVALID_PARTID;
547         return ((partid_t)ret_stuff.v0);
548 }
549
550 /*
551  * Returns the partition id of the current processor.
552  */
553
554 extern partid_t sn_partid;
555
556 static inline partid_t
557 sn_local_partid(void) {
558         if (sn_partid < 0) {
559                 return (sn_partid = ia64_sn_sysctl_partition_get(cpuid_to_nasid(smp_processor_id())));
560         } else {
561                 return sn_partid;
562         }
563 }
564
565 /*
566  * Register or unregister a physical address range being referenced across
567  * a partition boundary for which certain SAL errors should be scanned for,
568  * cleaned up and ignored.  This is of value for kernel partitioning code only.
569  * Values for the operation argument:
570  *      1 = register this address range with SAL
571  *      0 = unregister this address range with SAL
572  * 
573  * SAL maintains a reference count on an address range in case it is registered
574  * multiple times.
575  * 
576  * On success, returns the reference count of the address range after the SAL
577  * call has performed the current registration/unregistration.  Returns a
578  * negative value if an error occurred.
579  */
580 static inline int
581 sn_register_xp_addr_region(u64 paddr, u64 len, int operation)
582 {
583         struct ia64_sal_retval ret_stuff;
584         SAL_CALL(ret_stuff, SN_SAL_XP_ADDR_REGION, paddr, len, (u64)operation,
585                  0, 0, 0, 0);
586         return ret_stuff.status;
587 }
588
589 /*
590  * Register or unregister an instruction range for which SAL errors should
591  * be ignored.  If an error occurs while in the registered range, SAL jumps
592  * to return_addr after ignoring the error.  Values for the operation argument:
593  *      1 = register this instruction range with SAL
594  *      0 = unregister this instruction range with SAL
595  *
596  * Returns 0 on success, or a negative value if an error occurred.
597  */
598 static inline int
599 sn_register_nofault_code(u64 start_addr, u64 end_addr, u64 return_addr,
600                          int virtual, int operation)
601 {
602         struct ia64_sal_retval ret_stuff;
603         u64 call;
604         if (virtual) {
605                 call = SN_SAL_NO_FAULT_ZONE_VIRTUAL;
606         } else {
607                 call = SN_SAL_NO_FAULT_ZONE_PHYSICAL;
608         }
609         SAL_CALL(ret_stuff, call, start_addr, end_addr, return_addr, (u64)1,
610                  0, 0, 0);
611         return ret_stuff.status;
612 }
613
614 /*
615  * Change or query the coherence domain for this partition. Each cpu-based
616  * nasid is represented by a bit in an array of 64-bit words:
617  *      0 = not in this partition's coherency domain
618  *      1 = in this partition's coherency domain
619  *
620  * It is not possible for the local system's nasids to be removed from
621  * the coherency domain.  Purpose of the domain arguments:
622  *      new_domain = set the coherence domain to the given nasids
623  *      old_domain = return the current coherence domain
624  *
625  * Returns 0 on success, or a negative value if an error occurred.
626  */
627 static inline int
628 sn_change_coherence(u64 *new_domain, u64 *old_domain)
629 {
630         struct ia64_sal_retval ret_stuff;
631         SAL_CALL(ret_stuff, SN_SAL_COHERENCE, new_domain, old_domain, 0, 0,
632                  0, 0, 0);
633         return ret_stuff.status;
634 }
635
636 /*
637  * Change memory access protections for a physical address range.
638  * nasid_array is not used on Altix, but may be in future architectures.
639  * Available memory protection access classes are defined after the function.
640  */
641 static inline int
642 sn_change_memprotect(u64 paddr, u64 len, u64 perms, u64 *nasid_array)
643 {
644         struct ia64_sal_retval ret_stuff;
645         int cnodeid;
646         unsigned long irq_flags;
647
648         cnodeid = nasid_to_cnodeid(get_node_number(paddr));
649         spin_lock(&NODEPDA(cnodeid)->bist_lock);
650         local_irq_save(irq_flags);
651         SAL_CALL_NOLOCK(ret_stuff, SN_SAL_MEMPROTECT, paddr, len, nasid_array,
652                  perms, 0, 0, 0);
653         local_irq_restore(irq_flags);
654         spin_unlock(&NODEPDA(cnodeid)->bist_lock);
655         return ret_stuff.status;
656 }
657 #define SN_MEMPROT_ACCESS_CLASS_0               0x14a080
658 #define SN_MEMPROT_ACCESS_CLASS_1               0x2520c2
659 #define SN_MEMPROT_ACCESS_CLASS_2               0x14a1ca
660 #define SN_MEMPROT_ACCESS_CLASS_3               0x14a290
661 #define SN_MEMPROT_ACCESS_CLASS_6               0x084080
662 #define SN_MEMPROT_ACCESS_CLASS_7               0x021080
663
664 /*
665  * Turns off system power.
666  */
667 static inline void
668 ia64_sn_power_down(void)
669 {
670         struct ia64_sal_retval ret_stuff;
671         SAL_CALL(ret_stuff, SN_SAL_SYSTEM_POWER_DOWN, 0, 0, 0, 0, 0, 0, 0);
672         while(1);
673         /* never returns */
674 }
675
676 /**
677  * ia64_sn_fru_capture - tell the system controller to capture hw state
678  *
679  * This routine will call the SAL which will tell the system controller(s)
680  * to capture hw mmr information from each SHub in the system.
681  */
682 static inline u64
683 ia64_sn_fru_capture(void)
684 {
685         struct ia64_sal_retval isrv;
686         SAL_CALL(isrv, SN_SAL_SYSCTL_FRU_CAPTURE, 0, 0, 0, 0, 0, 0, 0);
687         if (isrv.status)
688                 return 0;
689         return isrv.v0;
690 }
691
692 /*
693  * Performs an operation on a PCI bus or slot -- power up, power down
694  * or reset.
695  */
696 static inline u64
697 ia64_sn_sysctl_iobrick_pci_op(nasid_t n, u64 connection_type, 
698                               u64 bus, slotid_t slot, 
699                               u64 action)
700 {
701         struct ia64_sal_retval rv = {0, 0, 0, 0};
702
703         SAL_CALL_NOLOCK(rv, SN_SAL_SYSCTL_IOBRICK_PCI_OP, connection_type, n, action,
704                  bus, (u64) slot, 0, 0);
705         if (rv.status)
706                 return rv.v0;
707         return 0;
708 }
709
710 /*
711  * Tell the prom how the OS wants to handle specific error features.
712  * It takes an array of 7 u64.
713  */
714 static inline u64
715 ia64_sn_set_error_handling_features(const u64 *feature_bits)
716 {
717         struct ia64_sal_retval rv = {0, 0, 0, 0};
718
719         SAL_CALL_REENTRANT(rv, SN_SAL_SET_ERROR_HANDLING_FEATURES,
720                         feature_bits[0],
721                         feature_bits[1],
722                         feature_bits[2],
723                         feature_bits[3],
724                         feature_bits[4],
725                         feature_bits[5],
726                         feature_bits[6]);
727         return rv.status;
728 }
729
730
731 /*
732  * Open a subchannel for sending arbitrary data to the system
733  * controller network via the system controller device associated with
734  * 'nasid'.  Return the subchannel number or a negative error code.
735  */
736 static inline int
737 ia64_sn_irtr_open(nasid_t nasid)
738 {
739         struct ia64_sal_retval rv;
740         SAL_CALL_REENTRANT(rv, SN_SAL_IROUTER_OP, SAL_IROUTER_OPEN, nasid,
741                            0, 0, 0, 0, 0);
742         return (int) rv.v0;
743 }
744
745 /*
746  * Close system controller subchannel 'subch' previously opened on 'nasid'.
747  */
748 static inline int
749 ia64_sn_irtr_close(nasid_t nasid, int subch)
750 {
751         struct ia64_sal_retval rv;
752         SAL_CALL_REENTRANT(rv, SN_SAL_IROUTER_OP, SAL_IROUTER_CLOSE,
753                            (u64) nasid, (u64) subch, 0, 0, 0, 0);
754         return (int) rv.status;
755 }
756
757 /*
758  * Read data from system controller associated with 'nasid' on
759  * subchannel 'subch'.  The buffer to be filled is pointed to by
760  * 'buf', and its capacity is in the integer pointed to by 'len'.  The
761  * referent of 'len' is set to the number of bytes read by the SAL
762  * call.  The return value is either SALRET_OK (for bytes read) or
763  * SALRET_ERROR (for error or "no data available").
764  */
765 static inline int
766 ia64_sn_irtr_recv(nasid_t nasid, int subch, char *buf, int *len)
767 {
768         struct ia64_sal_retval rv;
769         SAL_CALL_REENTRANT(rv, SN_SAL_IROUTER_OP, SAL_IROUTER_RECV,
770                            (u64) nasid, (u64) subch, (u64) buf, (u64) len,
771                            0, 0);
772         return (int) rv.status;
773 }
774
775 /*
776  * Write data to the system controller network via the system
777  * controller associated with 'nasid' on suchannel 'subch'.  The
778  * buffer to be written out is pointed to by 'buf', and 'len' is the
779  * number of bytes to be written.  The return value is either the
780  * number of bytes written (which could be zero) or a negative error
781  * code.
782  */
783 static inline int
784 ia64_sn_irtr_send(nasid_t nasid, int subch, char *buf, int len)
785 {
786         struct ia64_sal_retval rv;
787         SAL_CALL_REENTRANT(rv, SN_SAL_IROUTER_OP, SAL_IROUTER_SEND,
788                            (u64) nasid, (u64) subch, (u64) buf, (u64) len,
789                            0, 0);
790         return (int) rv.v0;
791 }
792
793 /*
794  * Check whether any interrupts are pending for the system controller
795  * associated with 'nasid' and its subchannel 'subch'.  The return
796  * value is a mask of pending interrupts (SAL_IROUTER_INTR_XMIT and/or
797  * SAL_IROUTER_INTR_RECV).
798  */
799 static inline int
800 ia64_sn_irtr_intr(nasid_t nasid, int subch)
801 {
802         struct ia64_sal_retval rv;
803         SAL_CALL_REENTRANT(rv, SN_SAL_IROUTER_OP, SAL_IROUTER_INTR_STATUS,
804                            (u64) nasid, (u64) subch, 0, 0, 0, 0);
805         return (int) rv.v0;
806 }
807
808 /*
809  * Enable the interrupt indicated by the intr parameter (either
810  * SAL_IROUTER_INTR_XMIT or SAL_IROUTER_INTR_RECV).
811  */
812 static inline int
813 ia64_sn_irtr_intr_enable(nasid_t nasid, int subch, u64 intr)
814 {
815         struct ia64_sal_retval rv;
816         SAL_CALL_REENTRANT(rv, SN_SAL_IROUTER_OP, SAL_IROUTER_INTR_ON,
817                            (u64) nasid, (u64) subch, intr, 0, 0, 0);
818         return (int) rv.v0;
819 }
820
821 /*
822  * Disable the interrupt indicated by the intr parameter (either
823  * SAL_IROUTER_INTR_XMIT or SAL_IROUTER_INTR_RECV).
824  */
825 static inline int
826 ia64_sn_irtr_intr_disable(nasid_t nasid, int subch, u64 intr)
827 {
828         struct ia64_sal_retval rv;
829         SAL_CALL_REENTRANT(rv, SN_SAL_IROUTER_OP, SAL_IROUTER_INTR_OFF,
830                            (u64) nasid, (u64) subch, intr, 0, 0, 0);
831         return (int) rv.v0;
832 }
833
834 /**
835  * ia64_sn_get_fit_compt - read a FIT entry from the PROM header
836  * @nasid: NASID of node to read
837  * @index: FIT entry index to be retrieved (0..n)
838  * @fitentry: 16 byte buffer where FIT entry will be stored.
839  * @banbuf: optional buffer for retrieving banner
840  * @banlen: length of banner buffer
841  *
842  * Access to the physical PROM chips needs to be serialized since reads and
843  * writes can't occur at the same time, so we need to call into the SAL when
844  * we want to look at the FIT entries on the chips.
845  *
846  * Returns:
847  *      %SALRET_OK if ok
848  *      %SALRET_INVALID_ARG if index too big
849  *      %SALRET_NOT_IMPLEMENTED if running on older PROM
850  *      ??? if nasid invalid OR banner buffer not large enough
851  */
852 static inline int
853 ia64_sn_get_fit_compt(u64 nasid, u64 index, void *fitentry, void *banbuf,
854                       u64 banlen)
855 {
856         struct ia64_sal_retval rv;
857         SAL_CALL_NOLOCK(rv, SN_SAL_GET_FIT_COMPT, nasid, index, fitentry,
858                         banbuf, banlen, 0, 0);
859         return (int) rv.status;
860 }
861
862 /*
863  * Initialize the SAL components of the system controller
864  * communication driver; specifically pass in a sizable buffer that
865  * can be used for allocation of subchannel queues as new subchannels
866  * are opened.  "buf" points to the buffer, and "len" specifies its
867  * length.
868  */
869 static inline int
870 ia64_sn_irtr_init(nasid_t nasid, void *buf, int len)
871 {
872         struct ia64_sal_retval rv;
873         SAL_CALL_REENTRANT(rv, SN_SAL_IROUTER_OP, SAL_IROUTER_INIT,
874                            (u64) nasid, (u64) buf, (u64) len, 0, 0, 0);
875         return (int) rv.status;
876 }
877
878 /*
879  * This is the access point to the Altix PROM hardware performance
880  * and status monitoring interface. For info on using this, see
881  * include/asm-ia64/sn/sn2/sn_hwperf.h
882  */
883 static inline int
884 ia64_sn_hwperf_op(nasid_t nasid, u64 opcode, u64 a0, u64 a1, u64 a2,
885                   u64 a3, u64 a4, int *v0)
886 {
887         struct ia64_sal_retval rv;
888         SAL_CALL_NOLOCK(rv, SN_SAL_HWPERF_OP, (u64)nasid,
889                 opcode, a0, a1, a2, a3, a4);
890         if (v0)
891                 *v0 = (int) rv.v0;
892         return (int) rv.status;
893 }
894
895 #endif /* _ASM_IA64_SN_SN_SAL_H */