1/* from: Broadcom Id: cfe_api.c,v 1.18 2006/08/24 02:13:56 binh Exp $ */
2
3/*-
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 * Copyright 2000, 2001, 2002
7 * Broadcom Corporation. All rights reserved.
8 *
9 * This software is furnished under license and may be used and copied only
10 * in accordance with the following terms and conditions.  Subject to these
11 * conditions, you may download, copy, install, use, modify and distribute
12 * modified or unmodified copies of this software in source and/or binary
13 * form. No title or ownership is transferred hereby.
14 *
15 * 1) Any source code used, modified or distributed must reproduce and
16 *    retain this copyright notice and list of conditions as they appear in
17 *    the source file.
18 *
19 * 2) No right is granted to use any trade name, trademark, or logo of
20 *    Broadcom Corporation.  The "Broadcom Corporation" name may not be
21 *    used to endorse or promote products derived from this software
22 *    without the prior written permission of Broadcom Corporation.
23 *
24 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR IMPLIED
25 *    WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF
26 *    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
27 *    NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM BE LIABLE
28 *    FOR ANY DAMAGES WHATSOEVER, AND IN PARTICULAR, BROADCOM SHALL NOT BE
29 *    LIABLE FOR DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 *    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 *    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
32 *    BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
33 *    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
34 *    OR OTHERWISE), EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 */
36
37/*  *********************************************************************
38    *
39    *  Broadcom Common Firmware Environment (CFE)
40    *
41    *  Device Function stubs			File: cfe_api.c
42    *
43    *  This module contains device function stubs (small routines to
44    *  call the standard "iocb" interface entry point to CFE).
45    *  There should be one routine here per iocb function call.
46    *
47    *  Authors:  Mitch Lichtenberg, Chris Demetriou
48    *
49    ********************************************************************* */
50
51#include <sys/cdefs.h>
52#include <dev/cfe/cfe_api.h>
53#include <dev/cfe/cfe_api_int.h>
54
55/* Cast from a native pointer to a cfe_xptr_t and back.  */
56#define XPTR_FROM_NATIVE(n)	((cfe_xptr_t) (intptr_t) (n))
57#define NATIVE_FROM_XPTR(x)	((void *) (intptr_t) (x))
58
59#ifdef CFE_API_IMPL_NAMESPACE
60#define cfe_iocb_dispatch(a)		__cfe_iocb_dispatch(a)
61#endif
62int cfe_iocb_dispatch(cfe_xiocb_t *xiocb);
63
64#if defined(CFE_API_common) || defined(CFE_API_ALL)
65/*
66 * Declare the dispatch function with args of "intptr_t".
67 * This makes sure whatever model we're compiling in
68 * puts the pointers in a single register.  For example,
69 * combining -mlong64 and -mips1 or -mips2 would lead to
70 * trouble, since the handle and IOCB pointer will be
71 * passed in two registers each, and CFE expects one.
72 */
73
74static int (*cfe_dispfunc)(intptr_t handle, intptr_t xiocb) = 0;
75static cfe_xuint_t cfe_handle = 0;
76
77int
78cfe_init(cfe_xuint_t handle, cfe_xuint_t ept)
79{
80    cfe_dispfunc = NATIVE_FROM_XPTR(ept);
81    cfe_handle = handle;
82    return 0;
83}
84
85int
86cfe_iocb_dispatch(cfe_xiocb_t *xiocb)
87{
88    if (!cfe_dispfunc) return -1;
89    return (*cfe_dispfunc)((intptr_t)cfe_handle, (intptr_t)xiocb);
90}
91#endif /* CFE_API_common || CFE_API_ALL */
92
93#if defined(CFE_API_close) || defined(CFE_API_ALL)
94int
95cfe_close(int handle)
96{
97    cfe_xiocb_t xiocb;
98
99    xiocb.xiocb_fcode = CFE_CMD_DEV_CLOSE;
100    xiocb.xiocb_status = 0;
101    xiocb.xiocb_handle = handle;
102    xiocb.xiocb_flags = 0;
103    xiocb.xiocb_psize = 0;
104
105    cfe_iocb_dispatch(&xiocb);
106
107    return xiocb.xiocb_status;
108
109}
110#endif /* CFE_API_close || CFE_API_ALL */
111
112#if defined(CFE_API_cpu_start) || defined(CFE_API_ALL)
113int
114cfe_cpu_start(int cpu, void (*fn)(void), long sp, long gp, long a1)
115{
116    cfe_xiocb_t xiocb;
117
118    xiocb.xiocb_fcode = CFE_CMD_FW_CPUCTL;
119    xiocb.xiocb_status = 0;
120    xiocb.xiocb_handle = 0;
121    xiocb.xiocb_flags  = 0;
122    xiocb.xiocb_psize = sizeof(xiocb_cpuctl_t);
123    xiocb.plist.xiocb_cpuctl.cpu_number = cpu;
124    xiocb.plist.xiocb_cpuctl.cpu_command = CFE_CPU_CMD_START;
125    xiocb.plist.xiocb_cpuctl.gp_val = gp;
126    xiocb.plist.xiocb_cpuctl.sp_val = sp;
127    xiocb.plist.xiocb_cpuctl.a1_val = a1;
128    xiocb.plist.xiocb_cpuctl.start_addr = (long)fn;
129
130    cfe_iocb_dispatch(&xiocb);
131
132    return xiocb.xiocb_status;
133}
134#endif /* CFE_API_cpu_start || CFE_API_ALL */
135
136#if defined(CFE_API_cpu_stop) || defined(CFE_API_ALL)
137int
138cfe_cpu_stop(int cpu)
139{
140    cfe_xiocb_t xiocb;
141
142    xiocb.xiocb_fcode = CFE_CMD_FW_CPUCTL;
143    xiocb.xiocb_status = 0;
144    xiocb.xiocb_handle = 0;
145    xiocb.xiocb_flags  = 0;
146    xiocb.xiocb_psize = sizeof(xiocb_cpuctl_t);
147    xiocb.plist.xiocb_cpuctl.cpu_number = cpu;
148    xiocb.plist.xiocb_cpuctl.cpu_command = CFE_CPU_CMD_STOP;
149
150    cfe_iocb_dispatch(&xiocb);
151
152    return xiocb.xiocb_status;
153}
154#endif /* CFE_API_cpu_stop || CFE_API_ALL */
155
156#if defined(CFE_API_enumenv) || defined(CFE_API_ALL)
157int
158cfe_enumenv(int idx, char *name, int namelen, char *val, int vallen)
159{
160    cfe_xiocb_t xiocb;
161
162    xiocb.xiocb_fcode = CFE_CMD_ENV_ENUM;
163    xiocb.xiocb_status = 0;
164    xiocb.xiocb_handle = 0;
165    xiocb.xiocb_flags = 0;
166    xiocb.xiocb_psize = sizeof(xiocb_envbuf_t);
167    xiocb.plist.xiocb_envbuf.enum_idx = idx;
168    xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
169    xiocb.plist.xiocb_envbuf.name_length = namelen;
170    xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(val);
171    xiocb.plist.xiocb_envbuf.val_length = vallen;
172
173    cfe_iocb_dispatch(&xiocb);
174
175    return xiocb.xiocb_status;
176}
177#endif /* CFE_API_enumenv || CFE_API_ALL */
178
179#if defined(CFE_API_enumdev) || defined(CFE_API_ALL)
180int
181cfe_enumdev(int idx, char *name, int namelen)
182{
183    cfe_xiocb_t xiocb;
184
185    xiocb.xiocb_fcode = CFE_CMD_DEV_ENUM;
186    xiocb.xiocb_status = 0;
187    xiocb.xiocb_handle = 0;
188    xiocb.xiocb_flags = 0;
189    xiocb.xiocb_psize = sizeof(xiocb_envbuf_t);
190    xiocb.plist.xiocb_envbuf.enum_idx = idx;
191    xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
192    xiocb.plist.xiocb_envbuf.name_length = namelen;
193
194    cfe_iocb_dispatch(&xiocb);
195
196    return xiocb.xiocb_status;
197}
198#endif /* CFE_API_enumdev || CFE_API_ALL */
199
200#if defined(CFE_API_enummem) || defined(CFE_API_ALL)
201int
202cfe_enummem(int idx, int flags, cfe_xuint_t *start, cfe_xuint_t *length,
203	    cfe_xuint_t *type)
204{
205    cfe_xiocb_t xiocb;
206
207    xiocb.xiocb_fcode = CFE_CMD_FW_MEMENUM;
208    xiocb.xiocb_status = 0;
209    xiocb.xiocb_handle = 0;
210    xiocb.xiocb_flags = flags;
211    xiocb.xiocb_psize = sizeof(xiocb_meminfo_t);
212    xiocb.plist.xiocb_meminfo.mi_idx = idx;
213
214    cfe_iocb_dispatch(&xiocb);
215
216    if (xiocb.xiocb_status < 0)
217	return xiocb.xiocb_status;
218
219    *start = xiocb.plist.xiocb_meminfo.mi_addr;
220    *length = xiocb.plist.xiocb_meminfo.mi_size;
221    *type = xiocb.plist.xiocb_meminfo.mi_type;
222
223    return 0;
224}
225#endif /* CFE_API_enummem || CFE_API_ALL */
226
227#if defined(CFE_API_exit) || defined(CFE_API_ALL)
228int
229cfe_exit(int warm, int status)
230{
231    cfe_xiocb_t xiocb;
232
233    xiocb.xiocb_fcode = CFE_CMD_FW_RESTART;
234    xiocb.xiocb_status = 0;
235    xiocb.xiocb_handle = 0;
236    xiocb.xiocb_flags = warm ? CFE_FLG_WARMSTART : 0;
237    xiocb.xiocb_psize = sizeof(xiocb_exitstat_t);
238    xiocb.plist.xiocb_exitstat.status = status;
239
240    cfe_iocb_dispatch(&xiocb);
241
242    return xiocb.xiocb_status;
243}
244#endif /* CFE_API_exit || CFE_API_ALL */
245
246#if defined(CFE_API_flushcache) || defined(CFE_API_ALL)
247int
248cfe_flushcache(int flg)
249{
250    cfe_xiocb_t xiocb;
251
252    xiocb.xiocb_fcode = CFE_CMD_FW_FLUSHCACHE;
253    xiocb.xiocb_status = 0;
254    xiocb.xiocb_handle = 0;
255    xiocb.xiocb_flags = flg;
256    xiocb.xiocb_psize = 0;
257
258    cfe_iocb_dispatch(&xiocb);
259
260    return xiocb.xiocb_status;
261}
262#endif /* CFE_API_flushcache || CFE_API_ALL */
263
264#if defined(CFE_API_getdevinfo) || defined(CFE_API_ALL)
265int
266cfe_getdevinfo(char *name)
267{
268    cfe_xiocb_t xiocb;
269
270    xiocb.xiocb_fcode = CFE_CMD_DEV_GETINFO;
271    xiocb.xiocb_status = 0;
272    xiocb.xiocb_handle = 0;
273    xiocb.xiocb_flags = 0;
274    xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
275    xiocb.plist.xiocb_buffer.buf_offset = 0;
276    xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name);
277    xiocb.plist.xiocb_buffer.buf_length = cfe_strlen(name);
278
279    cfe_iocb_dispatch(&xiocb);
280
281    if (xiocb.xiocb_status < 0)
282	return xiocb.xiocb_status;
283    return xiocb.plist.xiocb_buffer.buf_devflags;
284}
285#endif /* CFE_API_getdevinfo || CFE_API_ALL */
286
287#if defined(CFE_API_getenv) || defined(CFE_API_ALL)
288int
289cfe_getenv(char *name, char *dest, int destlen)
290{
291    cfe_xiocb_t xiocb;
292
293    *dest = 0;
294
295    xiocb.xiocb_fcode = CFE_CMD_ENV_GET;
296    xiocb.xiocb_status = 0;
297    xiocb.xiocb_handle = 0;
298    xiocb.xiocb_flags = 0;
299    xiocb.xiocb_psize = sizeof(xiocb_envbuf_t);
300    xiocb.plist.xiocb_envbuf.enum_idx = 0;
301    xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
302    xiocb.plist.xiocb_envbuf.name_length = cfe_strlen(name);
303    xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(dest);
304    xiocb.plist.xiocb_envbuf.val_length = destlen;
305
306    cfe_iocb_dispatch(&xiocb);
307
308    return xiocb.xiocb_status;
309}
310#endif /* CFE_API_getenv || CFE_API_ALL */
311
312#if defined(CFE_API_getfwinfo) || defined(CFE_API_ALL)
313int
314cfe_getfwinfo(cfe_fwinfo_t *info)
315{
316    cfe_xiocb_t xiocb;
317
318    xiocb.xiocb_fcode = CFE_CMD_FW_GETINFO;
319    xiocb.xiocb_status = 0;
320    xiocb.xiocb_handle = 0;
321    xiocb.xiocb_flags = 0;
322    xiocb.xiocb_psize = sizeof(xiocb_fwinfo_t);
323
324    cfe_iocb_dispatch(&xiocb);
325
326    if (xiocb.xiocb_status < 0)
327	return xiocb.xiocb_status;
328
329    info->fwi_version = xiocb.plist.xiocb_fwinfo.fwi_version;
330    info->fwi_totalmem = xiocb.plist.xiocb_fwinfo.fwi_totalmem;
331    info->fwi_flags = xiocb.plist.xiocb_fwinfo.fwi_flags;
332    info->fwi_boardid = xiocb.plist.xiocb_fwinfo.fwi_boardid;
333    info->fwi_bootarea_va = xiocb.plist.xiocb_fwinfo.fwi_bootarea_va;
334    info->fwi_bootarea_pa = xiocb.plist.xiocb_fwinfo.fwi_bootarea_pa;
335    info->fwi_bootarea_size = xiocb.plist.xiocb_fwinfo.fwi_bootarea_size;
336#if 0
337    info->fwi_reserved1 = xiocb.plist.xiocb_fwinfo.fwi_reserved1;
338    info->fwi_reserved2 = xiocb.plist.xiocb_fwinfo.fwi_reserved2;
339    info->fwi_reserved3 = xiocb.plist.xiocb_fwinfo.fwi_reserved3;
340#endif
341
342    return 0;
343}
344#endif /* CFE_API_getfwinfo || CFE_API_ALL */
345
346#if defined(CFE_API_getstdhandle) || defined(CFE_API_ALL)
347int
348cfe_getstdhandle(int flg)
349{
350    cfe_xiocb_t xiocb;
351
352    xiocb.xiocb_fcode = CFE_CMD_DEV_GETHANDLE;
353    xiocb.xiocb_status = 0;
354    xiocb.xiocb_handle = 0;
355    xiocb.xiocb_flags = flg;
356    xiocb.xiocb_psize = 0;
357
358    cfe_iocb_dispatch(&xiocb);
359
360    if (xiocb.xiocb_status < 0)
361	return xiocb.xiocb_status;
362    return xiocb.xiocb_handle;
363
364}
365#endif /* CFE_API_getstdhandle || CFE_API_ALL */
366
367#if defined(CFE_API_getticks) || defined(CFE_API_ALL)
368int64_t
369#ifdef CFE_API_IMPL_NAMESPACE
370__cfe_getticks(void)
371#else
372cfe_getticks(void)
373#endif
374{
375    cfe_xiocb_t xiocb;
376
377    xiocb.xiocb_fcode = CFE_CMD_FW_GETTIME;
378    xiocb.xiocb_status = 0;
379    xiocb.xiocb_handle = 0;
380    xiocb.xiocb_flags = 0;
381    xiocb.xiocb_psize = sizeof(xiocb_time_t);
382    xiocb.plist.xiocb_time.ticks = 0;
383
384    cfe_iocb_dispatch(&xiocb);
385
386    return xiocb.plist.xiocb_time.ticks;
387
388}
389#endif /* CFE_API_getticks || CFE_API_ALL */
390
391#if defined(CFE_API_inpstat) || defined(CFE_API_ALL)
392int
393cfe_inpstat(int handle)
394{
395    cfe_xiocb_t xiocb;
396
397    xiocb.xiocb_fcode = CFE_CMD_DEV_INPSTAT;
398    xiocb.xiocb_status = 0;
399    xiocb.xiocb_handle = handle;
400    xiocb.xiocb_flags = 0;
401    xiocb.xiocb_psize = sizeof(xiocb_inpstat_t);
402    xiocb.plist.xiocb_inpstat.inp_status = 0;
403
404    cfe_iocb_dispatch(&xiocb);
405
406    if (xiocb.xiocb_status < 0)
407	return xiocb.xiocb_status;
408    return xiocb.plist.xiocb_inpstat.inp_status;
409
410}
411#endif /* CFE_API_inpstat || CFE_API_ALL */
412
413#if defined(CFE_API_ioctl) || defined(CFE_API_ALL)
414int
415cfe_ioctl(int handle, unsigned int ioctlnum, unsigned char *buffer, int length,
416	  int *retlen, cfe_xuint_t offset)
417{
418    cfe_xiocb_t xiocb;
419
420    xiocb.xiocb_fcode = CFE_CMD_DEV_IOCTL;
421    xiocb.xiocb_status = 0;
422    xiocb.xiocb_handle = handle;
423    xiocb.xiocb_flags = 0;
424    xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
425    xiocb.plist.xiocb_buffer.buf_offset = offset;
426    xiocb.plist.xiocb_buffer.buf_ioctlcmd = ioctlnum;
427    xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
428    xiocb.plist.xiocb_buffer.buf_length = length;
429
430    cfe_iocb_dispatch(&xiocb);
431
432    if (retlen)
433	*retlen = xiocb.plist.xiocb_buffer.buf_retlen;
434    return xiocb.xiocb_status;
435}
436#endif /* CFE_API_ioctl || CFE_API_ALL */
437
438#if defined(CFE_API_open) || defined(CFE_API_ALL)
439int
440cfe_open(char *name)
441{
442    cfe_xiocb_t xiocb;
443
444    xiocb.xiocb_fcode = CFE_CMD_DEV_OPEN;
445    xiocb.xiocb_status = 0;
446    xiocb.xiocb_handle = 0;
447    xiocb.xiocb_flags = 0;
448    xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
449    xiocb.plist.xiocb_buffer.buf_offset = 0;
450    xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name);
451    xiocb.plist.xiocb_buffer.buf_length = cfe_strlen(name);
452
453    cfe_iocb_dispatch(&xiocb);
454
455    if (xiocb.xiocb_status < 0)
456	return xiocb.xiocb_status;
457    return xiocb.xiocb_handle;
458}
459#endif /* CFE_API_open || CFE_API_ALL */
460
461#if defined(CFE_API_read) || defined(CFE_API_ALL)
462int
463cfe_read(int handle, unsigned char *buffer, int length)
464{
465    return cfe_readblk(handle, 0, buffer, length);
466}
467#endif /* CFE_API_read || CFE_API_ALL */
468
469#if defined(CFE_API_readblk) || defined(CFE_API_ALL)
470int
471cfe_readblk(int handle, cfe_xint_t offset, unsigned char *buffer, int length)
472{
473    cfe_xiocb_t xiocb;
474
475    xiocb.xiocb_fcode = CFE_CMD_DEV_READ;
476    xiocb.xiocb_status = 0;
477    xiocb.xiocb_handle = handle;
478    xiocb.xiocb_flags = 0;
479    xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
480    xiocb.plist.xiocb_buffer.buf_offset = offset;
481    xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
482    xiocb.plist.xiocb_buffer.buf_length = length;
483
484    cfe_iocb_dispatch(&xiocb);
485
486    if (xiocb.xiocb_status < 0)
487	return xiocb.xiocb_status;
488    return xiocb.plist.xiocb_buffer.buf_retlen;
489}
490#endif /* CFE_API_readblk || CFE_API_ALL */
491
492#if defined(CFE_API_setenv) || defined(CFE_API_ALL)
493int
494cfe_setenv(char *name, char *val)
495{
496    cfe_xiocb_t xiocb;
497
498    xiocb.xiocb_fcode = CFE_CMD_ENV_SET;
499    xiocb.xiocb_status = 0;
500    xiocb.xiocb_handle = 0;
501    xiocb.xiocb_flags = 0;
502    xiocb.xiocb_psize = sizeof(xiocb_envbuf_t);
503    xiocb.plist.xiocb_envbuf.enum_idx = 0;
504    xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
505    xiocb.plist.xiocb_envbuf.name_length = cfe_strlen(name);
506    xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(val);
507    xiocb.plist.xiocb_envbuf.val_length = cfe_strlen(val);
508
509    cfe_iocb_dispatch(&xiocb);
510
511    return xiocb.xiocb_status;
512}
513#endif /* CFE_API_setenv || CFE_API_ALL */
514
515#if (defined(CFE_API_strlen) || defined(CFE_API_ALL)) \
516    && !defined(CFE_API_STRLEN_CUSTOM)
517int
518cfe_strlen(char *name)
519{
520    int count = 0;
521
522    while (*name++)
523	count++;
524
525    return count;
526}
527#endif /* CFE_API_strlen || CFE_API_ALL */
528
529#if defined(CFE_API_write) || defined(CFE_API_ALL)
530int
531cfe_write(int handle, unsigned char *buffer, int length)
532{
533    return cfe_writeblk(handle, 0, buffer, length);
534}
535#endif /* CFE_API_write || CFE_API_ALL */
536
537#if defined(CFE_API_writeblk) || defined(CFE_API_ALL)
538int
539cfe_writeblk(int handle, cfe_xint_t offset, unsigned char *buffer, int length)
540{
541    cfe_xiocb_t xiocb;
542
543    xiocb.xiocb_fcode = CFE_CMD_DEV_WRITE;
544    xiocb.xiocb_status = 0;
545    xiocb.xiocb_handle = handle;
546    xiocb.xiocb_flags = 0;
547    xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
548    xiocb.plist.xiocb_buffer.buf_offset = offset;
549    xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
550    xiocb.plist.xiocb_buffer.buf_length = length;
551
552    cfe_iocb_dispatch(&xiocb);
553
554    if (xiocb.xiocb_status < 0)
555	return xiocb.xiocb_status;
556    return xiocb.plist.xiocb_buffer.buf_retlen;
557}
558#endif /* CFE_API_writeblk || CFE_API_ALL */
559