Linux Audio

Check our new training course

Loading...
v5.4
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Extensible SAL Interface (ESI) support routines.
  4 *
  5 * Copyright (C) 2006 Hewlett-Packard Co
  6 * 	Alex Williamson <alex.williamson@hp.com>
  7 */
  8#include <linux/kernel.h>
  9#include <linux/init.h>
 10#include <linux/module.h>
 11#include <linux/string.h>
 12
 13#include <asm/esi.h>
 14#include <asm/sal.h>
 15
 16MODULE_AUTHOR("Alex Williamson <alex.williamson@hp.com>");
 17MODULE_DESCRIPTION("Extensible SAL Interface (ESI) support");
 18MODULE_LICENSE("GPL");
 19
 20#define MODULE_NAME	"esi"
 21
 22#define ESI_TABLE_GUID					\
 23    EFI_GUID(0x43EA58DC, 0xCF28, 0x4b06, 0xB3,		\
 24	     0x91, 0xB7, 0x50, 0x59, 0x34, 0x2B, 0xD4)
 25
 26enum esi_systab_entry_type {
 27	ESI_DESC_ENTRY_POINT = 0
 28};
 29
 30/*
 31 * Entry type:	Size:
 32 *	0	48
 33 */
 34#define ESI_DESC_SIZE(type)	"\060"[(unsigned) (type)]
 35
 36typedef struct ia64_esi_desc_entry_point {
 37	u8 type;
 38	u8 reserved1[15];
 39	u64 esi_proc;
 40	u64 gp;
 41	efi_guid_t guid;
 42} ia64_esi_desc_entry_point_t;
 43
 44struct pdesc {
 45	void *addr;
 46	void *gp;
 47};
 48
 49static struct ia64_sal_systab *esi_systab;
 50
 51static int __init esi_init (void)
 52{
 53	efi_config_table_t *config_tables;
 54	struct ia64_sal_systab *systab;
 55	unsigned long esi = 0;
 56	char *p;
 57	int i;
 58
 59	config_tables = __va(efi.systab->tables);
 60
 61	for (i = 0; i < (int) efi.systab->nr_tables; ++i) {
 62		if (efi_guidcmp(config_tables[i].guid, ESI_TABLE_GUID) == 0) {
 63			esi = config_tables[i].table;
 64			break;
 65		}
 66	}
 67
 68	if (!esi)
 69		return -ENODEV;
 70
 71	systab = __va(esi);
 72
 73	if (strncmp(systab->signature, "ESIT", 4) != 0) {
 74		printk(KERN_ERR "bad signature in ESI system table!");
 75		return -ENODEV;
 76	}
 77
 78	p = (char *) (systab + 1);
 79	for (i = 0; i < systab->entry_count; i++) {
 80		/*
 81		 * The first byte of each entry type contains the type
 82		 * descriptor.
 83		 */
 84		switch (*p) {
 85		      case ESI_DESC_ENTRY_POINT:
 86			break;
 87		      default:
 88			printk(KERN_WARNING "Unknown table type %d found in "
 89			       "ESI table, ignoring rest of table\n", *p);
 90			return -ENODEV;
 91		}
 92
 93		p += ESI_DESC_SIZE(*p);
 94	}
 95
 96	esi_systab = systab;
 97	return 0;
 98}
 99
100
101int ia64_esi_call (efi_guid_t guid, struct ia64_sal_retval *isrvp,
102		   enum esi_proc_type proc_type, u64 func,
103		   u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6,
104		   u64 arg7)
105{
106	struct ia64_fpreg fr[6];
107	unsigned long flags = 0;
108	int i;
109	char *p;
110
111	if (!esi_systab)
112		return -1;
113
114	p = (char *) (esi_systab + 1);
115	for (i = 0; i < esi_systab->entry_count; i++) {
116		if (*p == ESI_DESC_ENTRY_POINT) {
117			ia64_esi_desc_entry_point_t *esi = (void *)p;
118			if (!efi_guidcmp(guid, esi->guid)) {
119				ia64_sal_handler esi_proc;
120				struct pdesc pdesc;
121
122				pdesc.addr = __va(esi->esi_proc);
123				pdesc.gp = __va(esi->gp);
124
125				esi_proc = (ia64_sal_handler) &pdesc;
126
127				ia64_save_scratch_fpregs(fr);
128				if (proc_type == ESI_PROC_SERIALIZED)
129					spin_lock_irqsave(&sal_lock, flags);
130				else if (proc_type == ESI_PROC_MP_SAFE)
131					local_irq_save(flags);
132				else
133					preempt_disable();
134				*isrvp = (*esi_proc)(func, arg1, arg2, arg3,
135						     arg4, arg5, arg6, arg7);
136				if (proc_type == ESI_PROC_SERIALIZED)
137					spin_unlock_irqrestore(&sal_lock,
138							       flags);
139				else if (proc_type == ESI_PROC_MP_SAFE)
140					local_irq_restore(flags);
141				else
142					preempt_enable();
143				ia64_load_scratch_fpregs(fr);
144				return 0;
145			}
146		}
147		p += ESI_DESC_SIZE(*p);
148	}
149	return -1;
150}
151EXPORT_SYMBOL_GPL(ia64_esi_call);
152
153int ia64_esi_call_phys (efi_guid_t guid, struct ia64_sal_retval *isrvp,
154			u64 func, u64 arg1, u64 arg2, u64 arg3, u64 arg4,
155			u64 arg5, u64 arg6, u64 arg7)
156{
157	struct ia64_fpreg fr[6];
158	unsigned long flags;
159	u64 esi_params[8];
160	char *p;
161	int i;
162
163	if (!esi_systab)
164		return -1;
165
166	p = (char *) (esi_systab + 1);
167	for (i = 0; i < esi_systab->entry_count; i++) {
168		if (*p == ESI_DESC_ENTRY_POINT) {
169			ia64_esi_desc_entry_point_t *esi = (void *)p;
170			if (!efi_guidcmp(guid, esi->guid)) {
171				ia64_sal_handler esi_proc;
172				struct pdesc pdesc;
173
174				pdesc.addr = (void *)esi->esi_proc;
175				pdesc.gp = (void *)esi->gp;
176
177				esi_proc = (ia64_sal_handler) &pdesc;
178
179				esi_params[0] = func;
180				esi_params[1] = arg1;
181				esi_params[2] = arg2;
182				esi_params[3] = arg3;
183				esi_params[4] = arg4;
184				esi_params[5] = arg5;
185				esi_params[6] = arg6;
186				esi_params[7] = arg7;
187				ia64_save_scratch_fpregs(fr);
188				spin_lock_irqsave(&sal_lock, flags);
189				*isrvp = esi_call_phys(esi_proc, esi_params);
190				spin_unlock_irqrestore(&sal_lock, flags);
191				ia64_load_scratch_fpregs(fr);
192				return 0;
193			}
194		}
195		p += ESI_DESC_SIZE(*p);
196	}
197	return -1;
198}
199EXPORT_SYMBOL_GPL(ia64_esi_call_phys);
200
201static void __exit esi_exit (void)
202{
203}
204
205module_init(esi_init);
206module_exit(esi_exit);	/* makes module removable... */
v3.1
 
  1/*
  2 * Extensible SAL Interface (ESI) support routines.
  3 *
  4 * Copyright (C) 2006 Hewlett-Packard Co
  5 * 	Alex Williamson <alex.williamson@hp.com>
  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
 15MODULE_AUTHOR("Alex Williamson <alex.williamson@hp.com>");
 16MODULE_DESCRIPTION("Extensible SAL Interface (ESI) support");
 17MODULE_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
 25enum esi_systab_entry_type {
 26	ESI_DESC_ENTRY_POINT = 0
 27};
 28
 29/*
 30 * Entry type:	Size:
 31 *	0	48
 32 */
 33#define ESI_DESC_SIZE(type)	"\060"[(unsigned) (type)]
 34
 35typedef struct ia64_esi_desc_entry_point {
 36	u8 type;
 37	u8 reserved1[15];
 38	u64 esi_proc;
 39	u64 gp;
 40	efi_guid_t guid;
 41} ia64_esi_desc_entry_point_t;
 42
 43struct pdesc {
 44	void *addr;
 45	void *gp;
 46};
 47
 48static struct ia64_sal_systab *esi_systab;
 49
 50static 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) {
 84		      case ESI_DESC_ENTRY_POINT:
 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
100int 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
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);
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();
142				ia64_load_scratch_fpregs(fr);
143				return 0;
144			}
145		}
146		p += ESI_DESC_SIZE(*p);
147	}
148	return -1;
149}
150EXPORT_SYMBOL_GPL(ia64_esi_call);
151
152int 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)
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;
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);
191				return 0;
192			}
193		}
194		p += ESI_DESC_SIZE(*p);
195	}
196	return -1;
197}
198EXPORT_SYMBOL_GPL(ia64_esi_call_phys);
199
200static void __exit esi_exit (void)
201{
202}
203
204module_init(esi_init);
205module_exit(esi_exit);	/* makes module removable... */