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... */
v4.17
 
  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... */