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 "Unknown 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... */