Linux Audio

Check our new training course

Loading...
v6.2
  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
 
 
 
 
 22enum esi_systab_entry_type {
 23	ESI_DESC_ENTRY_POINT = 0
 24};
 25
 26/*
 27 * Entry type:	Size:
 28 *	0	48
 29 */
 30#define ESI_DESC_SIZE(type)	"\060"[(unsigned) (type)]
 31
 32typedef struct ia64_esi_desc_entry_point {
 33	u8 type;
 34	u8 reserved1[15];
 35	u64 esi_proc;
 36	u64 gp;
 37	efi_guid_t guid;
 38} ia64_esi_desc_entry_point_t;
 39
 40struct pdesc {
 41	void *addr;
 42	void *gp;
 43};
 44
 45static struct ia64_sal_systab *esi_systab;
 46
 47extern unsigned long esi_phys;
 48
 49static int __init esi_init (void)
 50{
 
 51	struct ia64_sal_systab *systab;
 
 52	char *p;
 53	int i;
 54
 55	if (esi_phys == EFI_INVALID_TABLE_ADDR)
 
 
 
 
 
 
 
 
 
 56		return -ENODEV;
 57
 58	systab = __va(esi_phys);
 59
 60	if (strncmp(systab->signature, "ESIT", 4) != 0) {
 61		printk(KERN_ERR "bad signature in ESI system table!");
 62		return -ENODEV;
 63	}
 64
 65	p = (char *) (systab + 1);
 66	for (i = 0; i < systab->entry_count; i++) {
 67		/*
 68		 * The first byte of each entry type contains the type
 69		 * descriptor.
 70		 */
 71		switch (*p) {
 72		      case ESI_DESC_ENTRY_POINT:
 73			break;
 74		      default:
 75			printk(KERN_WARNING "Unknown table type %d found in "
 76			       "ESI table, ignoring rest of table\n", *p);
 77			return -ENODEV;
 78		}
 79
 80		p += ESI_DESC_SIZE(*p);
 81	}
 82
 83	esi_systab = systab;
 84	return 0;
 85}
 86
 87
 88int 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,
 91		   u64 arg7)
 92{
 93	struct ia64_fpreg fr[6];
 94	unsigned long flags = 0;
 95	int i;
 96	char *p;
 97
 98	if (!esi_systab)
 99		return -1;
100
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;
107				struct pdesc pdesc;
108
109				pdesc.addr = __va(esi->esi_proc);
110				pdesc.gp = __va(esi->gp);
111
112				esi_proc = (ia64_sal_handler) &pdesc;
113
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);
119				else
120					preempt_disable();
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,
125							       flags);
126				else if (proc_type == ESI_PROC_MP_SAFE)
127					local_irq_restore(flags);
128				else
129					preempt_enable();
130				ia64_load_scratch_fpregs(fr);
131				return 0;
132			}
133		}
134		p += ESI_DESC_SIZE(*p);
135	}
136	return -1;
137}
138EXPORT_SYMBOL_GPL(ia64_esi_call);
139
140int 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)
143{
144	struct ia64_fpreg fr[6];
145	unsigned long flags;
146	u64 esi_params[8];
147	char *p;
148	int i;
149
150	if (!esi_systab)
151		return -1;
152
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;
159				struct pdesc pdesc;
160
161				pdesc.addr = (void *)esi->esi_proc;
162				pdesc.gp = (void *)esi->gp;
163
164				esi_proc = (ia64_sal_handler) &pdesc;
165
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);
179				return 0;
180			}
181		}
182		p += ESI_DESC_SIZE(*p);
183	}
184	return -1;
185}
186EXPORT_SYMBOL_GPL(ia64_esi_call_phys);
187
188static void __exit esi_exit (void)
189{
190}
191
192module_init(esi_init);
193module_exit(esi_exit);	/* makes module removable... */
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... */