1 // SPDX-License-Identifier: GPL-2.0-only
3 * Extensible SAL Interface (ESI) support routines.
5 * Copyright (C) 2006 Hewlett-Packard Co
6 * Alex Williamson <alex.williamson@hp.com>
8 #include <linux/kernel.h>
9 #include <linux/init.h>
10 #include <linux/module.h>
11 #include <linux/string.h>
16 MODULE_AUTHOR("Alex Williamson <alex.williamson@hp.com>");
17 MODULE_DESCRIPTION("Extensible SAL Interface (ESI) support");
18 MODULE_LICENSE("GPL");
20 #define MODULE_NAME "esi"
22 enum esi_systab_entry_type
{
23 ESI_DESC_ENTRY_POINT
= 0
30 #define ESI_DESC_SIZE(type) "\060"[(unsigned) (type)]
32 typedef struct ia64_esi_desc_entry_point
{
38 } ia64_esi_desc_entry_point_t
;
45 static struct ia64_sal_systab
*esi_systab
;
47 extern unsigned long esi_phys
;
49 static int __init
esi_init (void)
51 struct ia64_sal_systab
*systab
;
55 if (esi_phys
== EFI_INVALID_TABLE_ADDR
)
58 systab
= __va(esi_phys
);
60 if (strncmp(systab
->signature
, "ESIT", 4) != 0) {
61 printk(KERN_ERR
"bad signature in ESI system table!");
65 p
= (char *) (systab
+ 1);
66 for (i
= 0; i
< systab
->entry_count
; i
++) {
68 * The first byte of each entry type contains the type
72 case ESI_DESC_ENTRY_POINT
:
75 printk(KERN_WARNING
"Unknown table type %d found in "
76 "ESI table, ignoring rest of table\n", *p
);
80 p
+= ESI_DESC_SIZE(*p
);
88 int ia64_esi_call (efi_guid_t guid
, struct ia64_sal_retval
*isrvp
,
89 enum esi_proc_type proc_type
, u64 func
,
90 u64 arg1
, u64 arg2
, u64 arg3
, u64 arg4
, u64 arg5
, u64 arg6
,
93 struct ia64_fpreg fr
[6];
94 unsigned long flags
= 0;
101 p
= (char *) (esi_systab
+ 1);
102 for (i
= 0; i
< esi_systab
->entry_count
; i
++) {
103 if (*p
== ESI_DESC_ENTRY_POINT
) {
104 ia64_esi_desc_entry_point_t
*esi
= (void *)p
;
105 if (!efi_guidcmp(guid
, esi
->guid
)) {
106 ia64_sal_handler esi_proc
;
109 pdesc
.addr
= __va(esi
->esi_proc
);
110 pdesc
.gp
= __va(esi
->gp
);
112 esi_proc
= (ia64_sal_handler
) &pdesc
;
114 ia64_save_scratch_fpregs(fr
);
115 if (proc_type
== ESI_PROC_SERIALIZED
)
116 spin_lock_irqsave(&sal_lock
, flags
);
117 else if (proc_type
== ESI_PROC_MP_SAFE
)
118 local_irq_save(flags
);
121 *isrvp
= (*esi_proc
)(func
, arg1
, arg2
, arg3
,
122 arg4
, arg5
, arg6
, arg7
);
123 if (proc_type
== ESI_PROC_SERIALIZED
)
124 spin_unlock_irqrestore(&sal_lock
,
126 else if (proc_type
== ESI_PROC_MP_SAFE
)
127 local_irq_restore(flags
);
130 ia64_load_scratch_fpregs(fr
);
134 p
+= ESI_DESC_SIZE(*p
);
138 EXPORT_SYMBOL_GPL(ia64_esi_call
);
140 int ia64_esi_call_phys (efi_guid_t guid
, struct ia64_sal_retval
*isrvp
,
141 u64 func
, u64 arg1
, u64 arg2
, u64 arg3
, u64 arg4
,
142 u64 arg5
, u64 arg6
, u64 arg7
)
144 struct ia64_fpreg fr
[6];
153 p
= (char *) (esi_systab
+ 1);
154 for (i
= 0; i
< esi_systab
->entry_count
; i
++) {
155 if (*p
== ESI_DESC_ENTRY_POINT
) {
156 ia64_esi_desc_entry_point_t
*esi
= (void *)p
;
157 if (!efi_guidcmp(guid
, esi
->guid
)) {
158 ia64_sal_handler esi_proc
;
161 pdesc
.addr
= (void *)esi
->esi_proc
;
162 pdesc
.gp
= (void *)esi
->gp
;
164 esi_proc
= (ia64_sal_handler
) &pdesc
;
166 esi_params
[0] = func
;
167 esi_params
[1] = arg1
;
168 esi_params
[2] = arg2
;
169 esi_params
[3] = arg3
;
170 esi_params
[4] = arg4
;
171 esi_params
[5] = arg5
;
172 esi_params
[6] = arg6
;
173 esi_params
[7] = arg7
;
174 ia64_save_scratch_fpregs(fr
);
175 spin_lock_irqsave(&sal_lock
, flags
);
176 *isrvp
= esi_call_phys(esi_proc
, esi_params
);
177 spin_unlock_irqrestore(&sal_lock
, flags
);
178 ia64_load_scratch_fpregs(fr
);
182 p
+= ESI_DESC_SIZE(*p
);
186 EXPORT_SYMBOL_GPL(ia64_esi_call_phys
);
188 static void __exit
esi_exit (void)
192 module_init(esi_init
);
193 module_exit(esi_exit
); /* makes module removable... */