xref: /freebsd/sys/dev/cfe/cfe_api.c (revision 3274f529)
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
63 int 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 
75 static int (*cfe_dispfunc)(intptr_t handle, intptr_t xiocb) = 0;
76 static cfe_xuint_t cfe_handle = 0;
77 
78 int
79 cfe_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 
86 int
87 cfe_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)
95 int
96 cfe_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)
114 int
115 cfe_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)
138 int
139 cfe_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)
158 int
159 cfe_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)
181 int
182 cfe_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)
208 int
209 cfe_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)
227 int
228 cfe_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)
245 int
246 cfe_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)
268 int
269 cfe_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)
293 int
294 cfe_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)
327 int
328 cfe_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)
348 int64_t
349 #ifdef CFE_API_IMPL_NAMESPACE
350 __cfe_getticks(void)
351 #else
352 cfe_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)
372 int
373 cfe_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)
394 int
395 cfe_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)
419 int
420 cfe_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)
442 int
443 cfe_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)
450 int
451 cfe_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)
473 int
474 cfe_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)
497 int
498 cfe_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)
510 int
511 cfe_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)
518 int
519 cfe_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