Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
esi.c
Go to the documentation of this file.
1 /*
2  * Extensible SAL Interface (ESI) support routines.
3  *
4  * Copyright (C) 2006 Hewlett-Packard Co
5  * Alex Williamson <[email protected]>
6  */
7 #include <linux/kernel.h>
8 #include <linux/init.h>
9 #include <linux/module.h>
10 #include <linux/string.h>
11 
12 #include <asm/esi.h>
13 #include <asm/sal.h>
14 
15 MODULE_AUTHOR("Alex Williamson <[email protected]>");
16 MODULE_DESCRIPTION("Extensible SAL Interface (ESI) support");
17 MODULE_LICENSE("GPL");
18 
19 #define MODULE_NAME "esi"
20 
21 #define ESI_TABLE_GUID \
22  EFI_GUID(0x43EA58DC, 0xCF28, 0x4b06, 0xB3, \
23  0x91, 0xB7, 0x50, 0x59, 0x34, 0x2B, 0xD4)
24 
27 };
28 
29 /*
30  * Entry type: Size:
31  * 0 48
32  */
33 #define ESI_DESC_SIZE(type) "\060"[(unsigned) (type)]
34 
35 typedef struct ia64_esi_desc_entry_point {
42 
43 struct pdesc {
44  void *addr;
45  void *gp;
46 };
47 
48 static struct ia64_sal_systab *esi_systab;
49 
50 static int __init esi_init (void)
51 {
52  efi_config_table_t *config_tables;
53  struct ia64_sal_systab *systab;
54  unsigned long esi = 0;
55  char *p;
56  int i;
57 
58  config_tables = __va(efi.systab->tables);
59 
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;
63  break;
64  }
65  }
66 
67  if (!esi)
68  return -ENODEV;
69 
70  systab = __va(esi);
71 
72  if (strncmp(systab->signature, "ESIT", 4) != 0) {
73  printk(KERN_ERR "bad signature in ESI system table!");
74  return -ENODEV;
75  }
76 
77  p = (char *) (systab + 1);
78  for (i = 0; i < systab->entry_count; i++) {
79  /*
80  * The first byte of each entry type contains the type
81  * descriptor.
82  */
83  switch (*p) {
85  break;
86  default:
87  printk(KERN_WARNING "Unknown table type %d found in "
88  "ESI table, ignoring rest of table\n", *p);
89  return -ENODEV;
90  }
91 
92  p += ESI_DESC_SIZE(*p);
93  }
94 
95  esi_systab = systab;
96  return 0;
97 }
98 
99 
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,
103  u64 arg7)
104 {
105  struct ia64_fpreg fr[6];
106  unsigned long flags = 0;
107  int i;
108  char *p;
109 
110  if (!esi_systab)
111  return -1;
112 
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;
119  struct pdesc pdesc;
120 
121  pdesc.addr = __va(esi->esi_proc);
122  pdesc.gp = __va(esi->gp);
123 
124  esi_proc = (ia64_sal_handler) &pdesc;
125 
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);
131  else
132  preempt_disable();
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,
137  flags);
138  else if (proc_type == ESI_PROC_MP_SAFE)
139  local_irq_restore(flags);
140  else
141  preempt_enable();
143  return 0;
144  }
145  }
146  p += ESI_DESC_SIZE(*p);
147  }
148  return -1;
149 }
151 
154  u64 arg5, u64 arg6, u64 arg7)
155 {
156  struct ia64_fpreg fr[6];
157  unsigned long flags;
158  u64 esi_params[8];
159  char *p;
160  int i;
161 
162  if (!esi_systab)
163  return -1;
164 
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;
171  struct pdesc pdesc;
172 
173  pdesc.addr = (void *)esi->esi_proc;
174  pdesc.gp = (void *)esi->gp;
175 
176  esi_proc = (ia64_sal_handler) &pdesc;
177 
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;
187  spin_lock_irqsave(&sal_lock, flags);
188  *isrvp = esi_call_phys(esi_proc, esi_params);
189  spin_unlock_irqrestore(&sal_lock, flags);
191  return 0;
192  }
193  }
194  p += ESI_DESC_SIZE(*p);
195  }
196  return -1;
197 }
199 
200 static void __exit esi_exit (void)
201 {
202 }
203 
204 module_init(esi_init);
205 module_exit(esi_exit); /* makes module removable... */