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