Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/mips/fw/cfe/cfe_api.c
10820 views
1
/*
2
* Copyright (C) 2000, 2001, 2002 Broadcom Corporation
3
*
4
* This program is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU General Public License
6
* as published by the Free Software Foundation; either version 2
7
* of the License, or (at your option) any later version.
8
*
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
13
*
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
*/
18
19
/*
20
*
21
* Broadcom Common Firmware Environment (CFE)
22
*
23
* This module contains device function stubs (small routines to
24
* call the standard "iocb" interface entry point to CFE).
25
* There should be one routine here per iocb function call.
26
*
27
* Authors: Mitch Lichtenberg, Chris Demetriou
28
*/
29
30
#include <asm/fw/cfe/cfe_api.h>
31
#include "cfe_api_int.h"
32
33
/* Cast from a native pointer to a cfe_xptr_t and back. */
34
#define XPTR_FROM_NATIVE(n) ((cfe_xptr_t) (intptr_t) (n))
35
#define NATIVE_FROM_XPTR(x) ((void *) (intptr_t) (x))
36
37
int cfe_iocb_dispatch(struct cfe_xiocb *xiocb);
38
39
/*
40
* Declare the dispatch function with args of "intptr_t".
41
* This makes sure whatever model we're compiling in
42
* puts the pointers in a single register. For example,
43
* combining -mlong64 and -mips1 or -mips2 would lead to
44
* trouble, since the handle and IOCB pointer will be
45
* passed in two registers each, and CFE expects one.
46
*/
47
48
static int (*cfe_dispfunc) (intptr_t handle, intptr_t xiocb);
49
static u64 cfe_handle;
50
51
int cfe_init(u64 handle, u64 ept)
52
{
53
cfe_dispfunc = NATIVE_FROM_XPTR(ept);
54
cfe_handle = handle;
55
return 0;
56
}
57
58
int cfe_iocb_dispatch(struct cfe_xiocb * xiocb)
59
{
60
if (!cfe_dispfunc)
61
return -1;
62
return (*cfe_dispfunc) ((intptr_t) cfe_handle, (intptr_t) xiocb);
63
}
64
65
int cfe_close(int handle)
66
{
67
struct cfe_xiocb xiocb;
68
69
xiocb.xiocb_fcode = CFE_CMD_DEV_CLOSE;
70
xiocb.xiocb_status = 0;
71
xiocb.xiocb_handle = handle;
72
xiocb.xiocb_flags = 0;
73
xiocb.xiocb_psize = 0;
74
75
cfe_iocb_dispatch(&xiocb);
76
77
return xiocb.xiocb_status;
78
79
}
80
81
int cfe_cpu_start(int cpu, void (*fn) (void), long sp, long gp, long a1)
82
{
83
struct cfe_xiocb xiocb;
84
85
xiocb.xiocb_fcode = CFE_CMD_FW_CPUCTL;
86
xiocb.xiocb_status = 0;
87
xiocb.xiocb_handle = 0;
88
xiocb.xiocb_flags = 0;
89
xiocb.xiocb_psize = sizeof(struct xiocb_cpuctl);
90
xiocb.plist.xiocb_cpuctl.cpu_number = cpu;
91
xiocb.plist.xiocb_cpuctl.cpu_command = CFE_CPU_CMD_START;
92
xiocb.plist.xiocb_cpuctl.gp_val = gp;
93
xiocb.plist.xiocb_cpuctl.sp_val = sp;
94
xiocb.plist.xiocb_cpuctl.a1_val = a1;
95
xiocb.plist.xiocb_cpuctl.start_addr = (long) fn;
96
97
cfe_iocb_dispatch(&xiocb);
98
99
return xiocb.xiocb_status;
100
}
101
102
int cfe_cpu_stop(int cpu)
103
{
104
struct cfe_xiocb xiocb;
105
106
xiocb.xiocb_fcode = CFE_CMD_FW_CPUCTL;
107
xiocb.xiocb_status = 0;
108
xiocb.xiocb_handle = 0;
109
xiocb.xiocb_flags = 0;
110
xiocb.xiocb_psize = sizeof(struct xiocb_cpuctl);
111
xiocb.plist.xiocb_cpuctl.cpu_number = cpu;
112
xiocb.plist.xiocb_cpuctl.cpu_command = CFE_CPU_CMD_STOP;
113
114
cfe_iocb_dispatch(&xiocb);
115
116
return xiocb.xiocb_status;
117
}
118
119
int cfe_enumenv(int idx, char *name, int namelen, char *val, int vallen)
120
{
121
struct cfe_xiocb xiocb;
122
123
xiocb.xiocb_fcode = CFE_CMD_ENV_SET;
124
xiocb.xiocb_status = 0;
125
xiocb.xiocb_handle = 0;
126
xiocb.xiocb_flags = 0;
127
xiocb.xiocb_psize = sizeof(struct xiocb_envbuf);
128
xiocb.plist.xiocb_envbuf.enum_idx = idx;
129
xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
130
xiocb.plist.xiocb_envbuf.name_length = namelen;
131
xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(val);
132
xiocb.plist.xiocb_envbuf.val_length = vallen;
133
134
cfe_iocb_dispatch(&xiocb);
135
136
return xiocb.xiocb_status;
137
}
138
139
int
140
cfe_enummem(int idx, int flags, u64 *start, u64 *length, u64 *type)
141
{
142
struct cfe_xiocb xiocb;
143
144
xiocb.xiocb_fcode = CFE_CMD_FW_MEMENUM;
145
xiocb.xiocb_status = 0;
146
xiocb.xiocb_handle = 0;
147
xiocb.xiocb_flags = flags;
148
xiocb.xiocb_psize = sizeof(struct xiocb_meminfo);
149
xiocb.plist.xiocb_meminfo.mi_idx = idx;
150
151
cfe_iocb_dispatch(&xiocb);
152
153
if (xiocb.xiocb_status < 0)
154
return xiocb.xiocb_status;
155
156
*start = xiocb.plist.xiocb_meminfo.mi_addr;
157
*length = xiocb.plist.xiocb_meminfo.mi_size;
158
*type = xiocb.plist.xiocb_meminfo.mi_type;
159
160
return 0;
161
}
162
163
int cfe_exit(int warm, int status)
164
{
165
struct cfe_xiocb xiocb;
166
167
xiocb.xiocb_fcode = CFE_CMD_FW_RESTART;
168
xiocb.xiocb_status = 0;
169
xiocb.xiocb_handle = 0;
170
xiocb.xiocb_flags = warm ? CFE_FLG_WARMSTART : 0;
171
xiocb.xiocb_psize = sizeof(struct xiocb_exitstat);
172
xiocb.plist.xiocb_exitstat.status = status;
173
174
cfe_iocb_dispatch(&xiocb);
175
176
return xiocb.xiocb_status;
177
}
178
179
int cfe_flushcache(int flg)
180
{
181
struct cfe_xiocb xiocb;
182
183
xiocb.xiocb_fcode = CFE_CMD_FW_FLUSHCACHE;
184
xiocb.xiocb_status = 0;
185
xiocb.xiocb_handle = 0;
186
xiocb.xiocb_flags = flg;
187
xiocb.xiocb_psize = 0;
188
189
cfe_iocb_dispatch(&xiocb);
190
191
return xiocb.xiocb_status;
192
}
193
194
int cfe_getdevinfo(char *name)
195
{
196
struct cfe_xiocb xiocb;
197
198
xiocb.xiocb_fcode = CFE_CMD_DEV_GETINFO;
199
xiocb.xiocb_status = 0;
200
xiocb.xiocb_handle = 0;
201
xiocb.xiocb_flags = 0;
202
xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
203
xiocb.plist.xiocb_buffer.buf_offset = 0;
204
xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name);
205
xiocb.plist.xiocb_buffer.buf_length = strlen(name);
206
207
cfe_iocb_dispatch(&xiocb);
208
209
if (xiocb.xiocb_status < 0)
210
return xiocb.xiocb_status;
211
return xiocb.plist.xiocb_buffer.buf_ioctlcmd;
212
}
213
214
int cfe_getenv(char *name, char *dest, int destlen)
215
{
216
struct cfe_xiocb xiocb;
217
218
*dest = 0;
219
220
xiocb.xiocb_fcode = CFE_CMD_ENV_GET;
221
xiocb.xiocb_status = 0;
222
xiocb.xiocb_handle = 0;
223
xiocb.xiocb_flags = 0;
224
xiocb.xiocb_psize = sizeof(struct xiocb_envbuf);
225
xiocb.plist.xiocb_envbuf.enum_idx = 0;
226
xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
227
xiocb.plist.xiocb_envbuf.name_length = strlen(name);
228
xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(dest);
229
xiocb.plist.xiocb_envbuf.val_length = destlen;
230
231
cfe_iocb_dispatch(&xiocb);
232
233
return xiocb.xiocb_status;
234
}
235
236
int cfe_getfwinfo(cfe_fwinfo_t * info)
237
{
238
struct cfe_xiocb xiocb;
239
240
xiocb.xiocb_fcode = CFE_CMD_FW_GETINFO;
241
xiocb.xiocb_status = 0;
242
xiocb.xiocb_handle = 0;
243
xiocb.xiocb_flags = 0;
244
xiocb.xiocb_psize = sizeof(struct xiocb_fwinfo);
245
246
cfe_iocb_dispatch(&xiocb);
247
248
if (xiocb.xiocb_status < 0)
249
return xiocb.xiocb_status;
250
251
info->fwi_version = xiocb.plist.xiocb_fwinfo.fwi_version;
252
info->fwi_totalmem = xiocb.plist.xiocb_fwinfo.fwi_totalmem;
253
info->fwi_flags = xiocb.plist.xiocb_fwinfo.fwi_flags;
254
info->fwi_boardid = xiocb.plist.xiocb_fwinfo.fwi_boardid;
255
info->fwi_bootarea_va = xiocb.plist.xiocb_fwinfo.fwi_bootarea_va;
256
info->fwi_bootarea_pa = xiocb.plist.xiocb_fwinfo.fwi_bootarea_pa;
257
info->fwi_bootarea_size =
258
xiocb.plist.xiocb_fwinfo.fwi_bootarea_size;
259
#if 0
260
info->fwi_reserved1 = xiocb.plist.xiocb_fwinfo.fwi_reserved1;
261
info->fwi_reserved2 = xiocb.plist.xiocb_fwinfo.fwi_reserved2;
262
info->fwi_reserved3 = xiocb.plist.xiocb_fwinfo.fwi_reserved3;
263
#endif
264
265
return 0;
266
}
267
268
int cfe_getstdhandle(int flg)
269
{
270
struct cfe_xiocb xiocb;
271
272
xiocb.xiocb_fcode = CFE_CMD_DEV_GETHANDLE;
273
xiocb.xiocb_status = 0;
274
xiocb.xiocb_handle = 0;
275
xiocb.xiocb_flags = flg;
276
xiocb.xiocb_psize = 0;
277
278
cfe_iocb_dispatch(&xiocb);
279
280
if (xiocb.xiocb_status < 0)
281
return xiocb.xiocb_status;
282
return xiocb.xiocb_handle;
283
}
284
285
int64_t
286
cfe_getticks(void)
287
{
288
struct cfe_xiocb xiocb;
289
290
xiocb.xiocb_fcode = CFE_CMD_FW_GETTIME;
291
xiocb.xiocb_status = 0;
292
xiocb.xiocb_handle = 0;
293
xiocb.xiocb_flags = 0;
294
xiocb.xiocb_psize = sizeof(struct xiocb_time);
295
xiocb.plist.xiocb_time.ticks = 0;
296
297
cfe_iocb_dispatch(&xiocb);
298
299
return xiocb.plist.xiocb_time.ticks;
300
301
}
302
303
int cfe_inpstat(int handle)
304
{
305
struct cfe_xiocb xiocb;
306
307
xiocb.xiocb_fcode = CFE_CMD_DEV_INPSTAT;
308
xiocb.xiocb_status = 0;
309
xiocb.xiocb_handle = handle;
310
xiocb.xiocb_flags = 0;
311
xiocb.xiocb_psize = sizeof(struct xiocb_inpstat);
312
xiocb.plist.xiocb_inpstat.inp_status = 0;
313
314
cfe_iocb_dispatch(&xiocb);
315
316
if (xiocb.xiocb_status < 0)
317
return xiocb.xiocb_status;
318
return xiocb.plist.xiocb_inpstat.inp_status;
319
}
320
321
int
322
cfe_ioctl(int handle, unsigned int ioctlnum, unsigned char *buffer,
323
int length, int *retlen, u64 offset)
324
{
325
struct cfe_xiocb xiocb;
326
327
xiocb.xiocb_fcode = CFE_CMD_DEV_IOCTL;
328
xiocb.xiocb_status = 0;
329
xiocb.xiocb_handle = handle;
330
xiocb.xiocb_flags = 0;
331
xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
332
xiocb.plist.xiocb_buffer.buf_offset = offset;
333
xiocb.plist.xiocb_buffer.buf_ioctlcmd = ioctlnum;
334
xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
335
xiocb.plist.xiocb_buffer.buf_length = length;
336
337
cfe_iocb_dispatch(&xiocb);
338
339
if (retlen)
340
*retlen = xiocb.plist.xiocb_buffer.buf_retlen;
341
return xiocb.xiocb_status;
342
}
343
344
int cfe_open(char *name)
345
{
346
struct cfe_xiocb xiocb;
347
348
xiocb.xiocb_fcode = CFE_CMD_DEV_OPEN;
349
xiocb.xiocb_status = 0;
350
xiocb.xiocb_handle = 0;
351
xiocb.xiocb_flags = 0;
352
xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
353
xiocb.plist.xiocb_buffer.buf_offset = 0;
354
xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name);
355
xiocb.plist.xiocb_buffer.buf_length = strlen(name);
356
357
cfe_iocb_dispatch(&xiocb);
358
359
if (xiocb.xiocb_status < 0)
360
return xiocb.xiocb_status;
361
return xiocb.xiocb_handle;
362
}
363
364
int cfe_read(int handle, unsigned char *buffer, int length)
365
{
366
return cfe_readblk(handle, 0, buffer, length);
367
}
368
369
int cfe_readblk(int handle, s64 offset, unsigned char *buffer, int length)
370
{
371
struct cfe_xiocb xiocb;
372
373
xiocb.xiocb_fcode = CFE_CMD_DEV_READ;
374
xiocb.xiocb_status = 0;
375
xiocb.xiocb_handle = handle;
376
xiocb.xiocb_flags = 0;
377
xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
378
xiocb.plist.xiocb_buffer.buf_offset = offset;
379
xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
380
xiocb.plist.xiocb_buffer.buf_length = length;
381
382
cfe_iocb_dispatch(&xiocb);
383
384
if (xiocb.xiocb_status < 0)
385
return xiocb.xiocb_status;
386
return xiocb.plist.xiocb_buffer.buf_retlen;
387
}
388
389
int cfe_setenv(char *name, char *val)
390
{
391
struct cfe_xiocb xiocb;
392
393
xiocb.xiocb_fcode = CFE_CMD_ENV_SET;
394
xiocb.xiocb_status = 0;
395
xiocb.xiocb_handle = 0;
396
xiocb.xiocb_flags = 0;
397
xiocb.xiocb_psize = sizeof(struct xiocb_envbuf);
398
xiocb.plist.xiocb_envbuf.enum_idx = 0;
399
xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
400
xiocb.plist.xiocb_envbuf.name_length = strlen(name);
401
xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(val);
402
xiocb.plist.xiocb_envbuf.val_length = strlen(val);
403
404
cfe_iocb_dispatch(&xiocb);
405
406
return xiocb.xiocb_status;
407
}
408
409
int cfe_write(int handle, unsigned char *buffer, int length)
410
{
411
return cfe_writeblk(handle, 0, buffer, length);
412
}
413
414
int cfe_writeblk(int handle, s64 offset, unsigned char *buffer, int length)
415
{
416
struct cfe_xiocb xiocb;
417
418
xiocb.xiocb_fcode = CFE_CMD_DEV_WRITE;
419
xiocb.xiocb_status = 0;
420
xiocb.xiocb_handle = handle;
421
xiocb.xiocb_flags = 0;
422
xiocb.xiocb_psize = sizeof(struct xiocb_buffer);
423
xiocb.plist.xiocb_buffer.buf_offset = offset;
424
xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
425
xiocb.plist.xiocb_buffer.buf_length = length;
426
427
cfe_iocb_dispatch(&xiocb);
428
429
if (xiocb.xiocb_status < 0)
430
return xiocb.xiocb_status;
431
return xiocb.plist.xiocb_buffer.buf_retlen;
432
}
433
434