2 * Extensible SAL Interface (ESI) support routines.
4 * Copyright (C) 2006 Hewlett-Packard Co
5 * Alex Williamson <alex.williamson@hp.com>
7 #include <linux/kernel.h>
8 #include <linux/init.h>
9 #include <linux/module.h>
10 #include <linux/string.h>
15 MODULE_AUTHOR("Alex Williamson <alex.williamson@hp.com>");
16 MODULE_DESCRIPTION("Extensible SAL Interface (ESI) support");
17 MODULE_LICENSE("GPL");
19 #define MODULE_NAME "esi"
21 #define ESI_TABLE_GUID \
22 EFI_GUID(0x43EA58DC, 0xCF28, 0x4b06, 0xB3, \
23 0x91, 0xB7, 0x50, 0x59, 0x34, 0x2B, 0xD4)
25 enum esi_systab_entry_type
{
26 ESI_DESC_ENTRY_POINT
= 0
33 #define ESI_DESC_SIZE(type) "\060"[(unsigned) (type)]
35 typedef struct ia64_esi_desc_entry_point
{
41 } ia64_esi_desc_entry_point_t
;
48 static struct ia64_sal_systab
*esi_systab
;
50 static int __init
esi_init (void)
52 efi_config_table_t
*config_tables
;
53 struct ia64_sal_systab
*systab
;
54 unsigned long esi
= 0;
58 config_tables
= __va(efi
.systab
->tables
);
60 for (i
= 0; i
< (int) efi
.systab
->nr_tables
; ++i
) {
61 if (efi_guidcmp(config_tables
[i
].guid
, ESI_TABLE_GUID
) == 0) {
62 esi
= config_tables
[i
].table
;
72 if (strncmp(systab
->signature
, "ESIT", 4) != 0) {
73 printk(KERN_ERR
"bad signature in ESI system table!");
77 p
= (char *) (systab
+ 1);
78 for (i
= 0; i
< systab
->entry_count
; i
++) {
80 * The first byte of each entry type contains the type
84 case ESI_DESC_ENTRY_POINT
:
87 printk(KERN_WARNING
"Unkown table type %d found in "
88 "ESI table, ignoring rest of table\n", *p
);
92 p
+= ESI_DESC_SIZE(*p
);
100 int ia64_esi_call (efi_guid_t guid
, struct ia64_sal_retval
*isrvp
,
101 enum esi_proc_type proc_type
, u64 func
,
102 u64 arg1
, u64 arg2
, u64 arg3
, u64 arg4
, u64 arg5
, u64 arg6
,
105 struct ia64_fpreg fr
[6];
106 unsigned long flags
= 0;
113 p
= (char *) (esi_systab
+ 1);
114 for (i
= 0; i
< esi_systab
->entry_count
; i
++) {
115 if (*p
== ESI_DESC_ENTRY_POINT
) {
116 ia64_esi_desc_entry_point_t
*esi
= (void *)p
;
117 if (!efi_guidcmp(guid
, esi
->guid
)) {
118 ia64_sal_handler esi_proc
;
121 pdesc
.addr
= __va(esi
->esi_proc
);
122 pdesc
.gp
= __va(esi
->gp
);
124 esi_proc
= (ia64_sal_handler
) &pdesc
;
126 ia64_save_scratch_fpregs(fr
);
127 if (proc_type
== ESI_PROC_SERIALIZED
)
128 spin_lock_irqsave(&sal_lock
, flags
);
129 else if (proc_type
== ESI_PROC_MP_SAFE
)
130 local_irq_save(flags
);
133 *isrvp
= (*esi_proc
)(func
, arg1
, arg2
, arg3
,
134 arg4
, arg5
, arg6
, arg7
);
135 if (proc_type
== ESI_PROC_SERIALIZED
)
136 spin_unlock_irqrestore(&sal_lock
,
138 else if (proc_type
== ESI_PROC_MP_SAFE
)
139 local_irq_restore(flags
);
142 ia64_load_scratch_fpregs(fr
);
146 p
+= ESI_DESC_SIZE(*p
);
150 EXPORT_SYMBOL_GPL(ia64_esi_call
);
152 int ia64_esi_call_phys (efi_guid_t guid
, struct ia64_sal_retval
*isrvp
,
153 u64 func
, u64 arg1
, u64 arg2
, u64 arg3
, u64 arg4
,
154 u64 arg5
, u64 arg6
, u64 arg7
)
156 struct ia64_fpreg fr
[6];
165 p
= (char *) (esi_systab
+ 1);
166 for (i
= 0; i
< esi_systab
->entry_count
; i
++) {
167 if (*p
== ESI_DESC_ENTRY_POINT
) {
168 ia64_esi_desc_entry_point_t
*esi
= (void *)p
;
169 if (!efi_guidcmp(guid
, esi
->guid
)) {
170 ia64_sal_handler esi_proc
;
173 pdesc
.addr
= (void *)esi
->esi_proc
;
174 pdesc
.gp
= (void *)esi
->gp
;
176 esi_proc
= (ia64_sal_handler
) &pdesc
;
178 esi_params
[0] = func
;
179 esi_params
[1] = arg1
;
180 esi_params
[2] = arg2
;
181 esi_params
[3] = arg3
;
182 esi_params
[4] = arg4
;
183 esi_params
[5] = arg5
;
184 esi_params
[6] = arg6
;
185 esi_params
[7] = arg7
;
186 ia64_save_scratch_fpregs(fr
);
187 spin_lock_irqsave(&sal_lock
, flags
);
188 *isrvp
= esi_call_phys(esi_proc
, esi_params
);
189 spin_unlock_irqrestore(&sal_lock
, flags
);
190 ia64_load_scratch_fpregs(fr
);
194 p
+= ESI_DESC_SIZE(*p
);
198 EXPORT_SYMBOL_GPL(ia64_esi_call_phys
);
200 static void __exit
esi_exit (void)
204 module_init(esi_init
);
205 module_exit(esi_exit
); /* makes module removable... */