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    *  Device Function stubs			File: cfe_api.c
24    *
25    *  This module contains device function stubs (small routines to
26    *  call the standard "iocb" interface entry point to CFE).
27    *  There should be one routine here per iocb function call.
28    *
29    *  Authors:  Mitch Lichtenberg, Chris Demetriou
30    *
31    ********************************************************************* */
32
33#include "cfe_api.h"
34#include "cfe_api_int.h"
35
36/* Cast from a native pointer to a cfe_xptr_t and back.	 */
37#define XPTR_FROM_NATIVE(n)	((cfe_xptr_t) (intptr_t) (n))
38#define NATIVE_FROM_XPTR(x)	((void *) (intptr_t) (x))
39
40#ifdef CFE_API_IMPL_NAMESPACE
41#define cfe_iocb_dispatch(a)		__cfe_iocb_dispatch(a)
42#endif
43int cfe_iocb_dispatch(cfe_xiocb_t * xiocb);
44
45#if defined(CFE_API_common) || defined(CFE_API_ALL)
46/*
47 * Declare the dispatch function with args of "intptr_t".
48 * This makes sure whatever model we're compiling in
49 * puts the pointers in a single register.  For example,
50 * combining -mlong64 and -mips1 or -mips2 would lead to
51 * trouble, since the handle and IOCB pointer will be
52 * passed in two registers each, and CFE expects one.
53 */
54
55static int (*cfe_dispfunc) (intptr_t handle, intptr_t xiocb) = 0;
56static cfe_xuint_t cfe_handle = 0;
57
58int cfe_init(cfe_xuint_t handle, cfe_xuint_t ept)
59{
60	cfe_dispfunc = NATIVE_FROM_XPTR(ept);
61	cfe_handle = handle;
62	return 0;
63}
64
65int cfe_iocb_dispatch(cfe_xiocb_t * xiocb)
66{
67	if (!cfe_dispfunc)
68		return -1;
69	return (*cfe_dispfunc) ((intptr_t) cfe_handle, (intptr_t) xiocb);
70}
71#endif				/* CFE_API_common || CFE_API_ALL */
72
73#if defined(CFE_API_close) || defined(CFE_API_ALL)
74int cfe_close(int handle)
75{
76	cfe_xiocb_t xiocb;
77
78	xiocb.xiocb_fcode = CFE_CMD_DEV_CLOSE;
79	xiocb.xiocb_status = 0;
80	xiocb.xiocb_handle = handle;
81	xiocb.xiocb_flags = 0;
82	xiocb.xiocb_psize = 0;
83
84	cfe_iocb_dispatch(&xiocb);
85
86	return xiocb.xiocb_status;
87
88}
89#endif				/* CFE_API_close || CFE_API_ALL */
90
91#if defined(CFE_API_cpu_start) || defined(CFE_API_ALL)
92int cfe_cpu_start(int cpu, void (*fn) (void), long sp, long gp, long a1)
93{
94	cfe_xiocb_t xiocb;
95
96	xiocb.xiocb_fcode = CFE_CMD_FW_CPUCTL;
97	xiocb.xiocb_status = 0;
98	xiocb.xiocb_handle = 0;
99	xiocb.xiocb_flags = 0;
100	xiocb.xiocb_psize = sizeof(xiocb_cpuctl_t);
101	xiocb.plist.xiocb_cpuctl.cpu_number = cpu;
102	xiocb.plist.xiocb_cpuctl.cpu_command = CFE_CPU_CMD_START;
103	xiocb.plist.xiocb_cpuctl.gp_val = gp;
104	xiocb.plist.xiocb_cpuctl.sp_val = sp;
105	xiocb.plist.xiocb_cpuctl.a1_val = a1;
106	xiocb.plist.xiocb_cpuctl.start_addr = (long) fn;
107
108	cfe_iocb_dispatch(&xiocb);
109
110	return xiocb.xiocb_status;
111}
112#endif				/* CFE_API_cpu_start || CFE_API_ALL */
113
114#if defined(CFE_API_cpu_stop) || defined(CFE_API_ALL)
115int cfe_cpu_stop(int cpu)
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_STOP;
126
127	cfe_iocb_dispatch(&xiocb);
128
129	return xiocb.xiocb_status;
130}
131#endif				/* CFE_API_cpu_stop || CFE_API_ALL */
132
133#if defined(CFE_API_enumenv) || defined(CFE_API_ALL)
134int cfe_enumenv(int idx, char *name, int namelen, char *val, int vallen)
135{
136	cfe_xiocb_t xiocb;
137
138	xiocb.xiocb_fcode = CFE_CMD_ENV_SET;
139	xiocb.xiocb_status = 0;
140	xiocb.xiocb_handle = 0;
141	xiocb.xiocb_flags = 0;
142	xiocb.xiocb_psize = sizeof(xiocb_envbuf_t);
143	xiocb.plist.xiocb_envbuf.enum_idx = idx;
144	xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
145	xiocb.plist.xiocb_envbuf.name_length = namelen;
146	xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(val);
147	xiocb.plist.xiocb_envbuf.val_length = vallen;
148
149	cfe_iocb_dispatch(&xiocb);
150
151	return xiocb.xiocb_status;
152}
153#endif				/* CFE_API_enumenv || CFE_API_ALL */
154
155#if defined(CFE_API_enummem) || defined(CFE_API_ALL)
156int
157cfe_enummem(int idx, int flags, cfe_xuint_t * start, cfe_xuint_t * length,
158	    cfe_xuint_t * type)
159{
160	cfe_xiocb_t xiocb;
161
162	xiocb.xiocb_fcode = CFE_CMD_FW_MEMENUM;
163	xiocb.xiocb_status = 0;
164	xiocb.xiocb_handle = 0;
165	xiocb.xiocb_flags = flags;
166	xiocb.xiocb_psize = sizeof(xiocb_meminfo_t);
167	xiocb.plist.xiocb_meminfo.mi_idx = idx;
168
169	cfe_iocb_dispatch(&xiocb);
170
171	if (xiocb.xiocb_status < 0)
172		return xiocb.xiocb_status;
173
174	*start = xiocb.plist.xiocb_meminfo.mi_addr;
175	*length = xiocb.plist.xiocb_meminfo.mi_size;
176	*type = xiocb.plist.xiocb_meminfo.mi_type;
177
178	return 0;
179}
180#endif				/* CFE_API_enummem || CFE_API_ALL */
181
182#if defined(CFE_API_exit) || defined(CFE_API_ALL)
183int cfe_exit(int warm, int status)
184{
185	cfe_xiocb_t xiocb;
186
187	xiocb.xiocb_fcode = CFE_CMD_FW_RESTART;
188	xiocb.xiocb_status = 0;
189	xiocb.xiocb_handle = 0;
190	xiocb.xiocb_flags = warm ? CFE_FLG_WARMSTART : 0;
191	xiocb.xiocb_psize = sizeof(xiocb_exitstat_t);
192	xiocb.plist.xiocb_exitstat.status = status;
193
194	cfe_iocb_dispatch(&xiocb);
195
196	return xiocb.xiocb_status;
197}
198#endif				/* CFE_API_exit || CFE_API_ALL */
199
200#if defined(CFE_API_flushcache) || defined(CFE_API_ALL)
201int cfe_flushcache(int flg)
202{
203	cfe_xiocb_t xiocb;
204
205	xiocb.xiocb_fcode = CFE_CMD_FW_FLUSHCACHE;
206	xiocb.xiocb_status = 0;
207	xiocb.xiocb_handle = 0;
208	xiocb.xiocb_flags = flg;
209	xiocb.xiocb_psize = 0;
210
211	cfe_iocb_dispatch(&xiocb);
212
213	return xiocb.xiocb_status;
214}
215#endif				/* CFE_API_flushcache || CFE_API_ALL */
216
217#if defined(CFE_API_getdevinfo) || defined(CFE_API_ALL)
218int cfe_getdevinfo(char *name)
219{
220	cfe_xiocb_t xiocb;
221
222	xiocb.xiocb_fcode = CFE_CMD_DEV_GETINFO;
223	xiocb.xiocb_status = 0;
224	xiocb.xiocb_handle = 0;
225	xiocb.xiocb_flags = 0;
226	xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
227	xiocb.plist.xiocb_buffer.buf_offset = 0;
228	xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name);
229	xiocb.plist.xiocb_buffer.buf_length = cfe_strlen(name);
230
231	cfe_iocb_dispatch(&xiocb);
232
233	if (xiocb.xiocb_status < 0)
234		return xiocb.xiocb_status;
235	return xiocb.plist.xiocb_buffer.buf_devflags;
236}
237#endif				/* CFE_API_getdevinfo || CFE_API_ALL */
238
239#if defined(CFE_API_getenv) || defined(CFE_API_ALL)
240int cfe_getenv(char *name, char *dest, int destlen)
241{
242	cfe_xiocb_t xiocb;
243
244	*dest = 0;
245
246	xiocb.xiocb_fcode = CFE_CMD_ENV_GET;
247	xiocb.xiocb_status = 0;
248	xiocb.xiocb_handle = 0;
249	xiocb.xiocb_flags = 0;
250	xiocb.xiocb_psize = sizeof(xiocb_envbuf_t);
251	xiocb.plist.xiocb_envbuf.enum_idx = 0;
252	xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
253	xiocb.plist.xiocb_envbuf.name_length = cfe_strlen(name);
254	xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(dest);
255	xiocb.plist.xiocb_envbuf.val_length = destlen;
256
257	cfe_iocb_dispatch(&xiocb);
258
259	return xiocb.xiocb_status;
260}
261#endif				/* CFE_API_getenv || CFE_API_ALL */
262
263#if defined(CFE_API_getfwinfo) || defined(CFE_API_ALL)
264int cfe_getfwinfo(cfe_fwinfo_t * info)
265{
266	cfe_xiocb_t xiocb;
267
268	xiocb.xiocb_fcode = CFE_CMD_FW_GETINFO;
269	xiocb.xiocb_status = 0;
270	xiocb.xiocb_handle = 0;
271	xiocb.xiocb_flags = 0;
272	xiocb.xiocb_psize = sizeof(xiocb_fwinfo_t);
273
274	cfe_iocb_dispatch(&xiocb);
275
276	if (xiocb.xiocb_status < 0)
277		return xiocb.xiocb_status;
278
279	info->fwi_version = xiocb.plist.xiocb_fwinfo.fwi_version;
280	info->fwi_totalmem = xiocb.plist.xiocb_fwinfo.fwi_totalmem;
281	info->fwi_flags = xiocb.plist.xiocb_fwinfo.fwi_flags;
282	info->fwi_boardid = xiocb.plist.xiocb_fwinfo.fwi_boardid;
283	info->fwi_bootarea_va = xiocb.plist.xiocb_fwinfo.fwi_bootarea_va;
284	info->fwi_bootarea_pa = xiocb.plist.xiocb_fwinfo.fwi_bootarea_pa;
285	info->fwi_bootarea_size =
286	    xiocb.plist.xiocb_fwinfo.fwi_bootarea_size;
287
288	return 0;
289}
290#endif				/* CFE_API_getfwinfo || CFE_API_ALL */
291
292#if defined(CFE_API_getstdhandle) || defined(CFE_API_ALL)
293int cfe_getstdhandle(int flg)
294{
295	cfe_xiocb_t xiocb;
296
297	xiocb.xiocb_fcode = CFE_CMD_DEV_GETHANDLE;
298	xiocb.xiocb_status = 0;
299	xiocb.xiocb_handle = 0;
300	xiocb.xiocb_flags = flg;
301	xiocb.xiocb_psize = 0;
302
303	cfe_iocb_dispatch(&xiocb);
304
305	if (xiocb.xiocb_status < 0)
306		return xiocb.xiocb_status;
307	return xiocb.xiocb_handle;
308}
309#endif				/* CFE_API_getstdhandle || CFE_API_ALL */
310
311#if defined(CFE_API_getticks) || defined(CFE_API_ALL)
312int64_t
313#ifdef CFE_API_IMPL_NAMESPACE
314__cfe_getticks(void)
315#else
316cfe_getticks(void)
317#endif
318{
319	cfe_xiocb_t xiocb;
320
321	xiocb.xiocb_fcode = CFE_CMD_FW_GETTIME;
322	xiocb.xiocb_status = 0;
323	xiocb.xiocb_handle = 0;
324	xiocb.xiocb_flags = 0;
325	xiocb.xiocb_psize = sizeof(xiocb_time_t);
326	xiocb.plist.xiocb_time.ticks = 0;
327
328	cfe_iocb_dispatch(&xiocb);
329
330	return xiocb.plist.xiocb_time.ticks;
331
332}
333#endif				/* CFE_API_getticks || CFE_API_ALL */
334
335#if defined(CFE_API_inpstat) || defined(CFE_API_ALL)
336int cfe_inpstat(int handle)
337{
338	cfe_xiocb_t xiocb;
339
340	xiocb.xiocb_fcode = CFE_CMD_DEV_INPSTAT;
341	xiocb.xiocb_status = 0;
342	xiocb.xiocb_handle = handle;
343	xiocb.xiocb_flags = 0;
344	xiocb.xiocb_psize = sizeof(xiocb_inpstat_t);
345	xiocb.plist.xiocb_inpstat.inp_status = 0;
346
347	cfe_iocb_dispatch(&xiocb);
348
349	if (xiocb.xiocb_status < 0)
350		return xiocb.xiocb_status;
351	return xiocb.plist.xiocb_inpstat.inp_status;
352}
353#endif				/* CFE_API_inpstat || CFE_API_ALL */
354
355#if defined(CFE_API_ioctl) || defined(CFE_API_ALL)
356int
357cfe_ioctl(int handle, unsigned int ioctlnum, unsigned char *buffer,
358	  int length, int *retlen, cfe_xuint_t offset)
359{
360	cfe_xiocb_t xiocb;
361
362	xiocb.xiocb_fcode = CFE_CMD_DEV_IOCTL;
363	xiocb.xiocb_status = 0;
364	xiocb.xiocb_handle = handle;
365	xiocb.xiocb_flags = 0;
366	xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
367	xiocb.plist.xiocb_buffer.buf_offset = offset;
368	xiocb.plist.xiocb_buffer.buf_ioctlcmd = ioctlnum;
369	xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
370	xiocb.plist.xiocb_buffer.buf_length = length;
371
372	cfe_iocb_dispatch(&xiocb);
373
374	if (retlen)
375		*retlen = xiocb.plist.xiocb_buffer.buf_retlen;
376	return xiocb.xiocb_status;
377}
378#endif				/* CFE_API_ioctl || CFE_API_ALL */
379
380#if defined(CFE_API_open) || defined(CFE_API_ALL)
381int cfe_open(char *name)
382{
383	cfe_xiocb_t xiocb;
384
385	xiocb.xiocb_fcode = CFE_CMD_DEV_OPEN;
386	xiocb.xiocb_status = 0;
387	xiocb.xiocb_handle = 0;
388	xiocb.xiocb_flags = 0;
389	xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
390	xiocb.plist.xiocb_buffer.buf_offset = 0;
391	xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name);
392	xiocb.plist.xiocb_buffer.buf_length = cfe_strlen(name);
393
394	cfe_iocb_dispatch(&xiocb);
395
396	if (xiocb.xiocb_status < 0)
397		return xiocb.xiocb_status;
398	return xiocb.xiocb_handle;
399}
400#endif				/* CFE_API_open || CFE_API_ALL */
401
402#if defined(CFE_API_read) || defined(CFE_API_ALL)
403int cfe_read(int handle, unsigned char *buffer, int length)
404{
405	return cfe_readblk(handle, 0, buffer, length);
406}
407#endif				/* CFE_API_read || CFE_API_ALL */
408
409#if defined(CFE_API_readblk) || defined(CFE_API_ALL)
410int
411cfe_readblk(int handle, cfe_xint_t offset, unsigned char *buffer,
412	    int length)
413{
414	cfe_xiocb_t xiocb;
415
416	xiocb.xiocb_fcode = CFE_CMD_DEV_READ;
417	xiocb.xiocb_status = 0;
418	xiocb.xiocb_handle = handle;
419	xiocb.xiocb_flags = 0;
420	xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
421	xiocb.plist.xiocb_buffer.buf_offset = offset;
422	xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
423	xiocb.plist.xiocb_buffer.buf_length = length;
424
425	cfe_iocb_dispatch(&xiocb);
426
427	if (xiocb.xiocb_status < 0)
428		return xiocb.xiocb_status;
429	return xiocb.plist.xiocb_buffer.buf_retlen;
430}
431#endif				/* CFE_API_readblk || CFE_API_ALL */
432
433#if defined(CFE_API_setenv) || defined(CFE_API_ALL)
434int cfe_setenv(char *name, char *val)
435{
436	cfe_xiocb_t xiocb;
437
438	xiocb.xiocb_fcode = CFE_CMD_ENV_SET;
439	xiocb.xiocb_status = 0;
440	xiocb.xiocb_handle = 0;
441	xiocb.xiocb_flags = 0;
442	xiocb.xiocb_psize = sizeof(xiocb_envbuf_t);
443	xiocb.plist.xiocb_envbuf.enum_idx = 0;
444	xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
445	xiocb.plist.xiocb_envbuf.name_length = cfe_strlen(name);
446	xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(val);
447	xiocb.plist.xiocb_envbuf.val_length = cfe_strlen(val);
448
449	cfe_iocb_dispatch(&xiocb);
450
451	return xiocb.xiocb_status;
452}
453#endif				/* CFE_API_setenv || CFE_API_ALL */
454
455#if (defined(CFE_API_strlen) || defined(CFE_API_ALL)) && \
456	!defined(CFE_API_STRLEN_CUSTOM)
457int cfe_strlen(char *name)
458{
459	int count = 0;
460
461	while (*name++)
462		count++;
463
464	return count;
465}
466#endif				/* CFE_API_strlen || CFE_API_ALL */
467
468#if defined(CFE_API_write) || defined(CFE_API_ALL)
469int cfe_write(int handle, unsigned char *buffer, int length)
470{
471	return cfe_writeblk(handle, 0, buffer, length);
472}
473#endif				/* CFE_API_write || CFE_API_ALL */
474
475#if defined(CFE_API_writeblk) || defined(CFE_API_ALL)
476int
477cfe_writeblk(int handle, cfe_xint_t offset, unsigned char *buffer,
478	     int length)
479{
480	cfe_xiocb_t xiocb;
481
482	xiocb.xiocb_fcode = CFE_CMD_DEV_WRITE;
483	xiocb.xiocb_status = 0;
484	xiocb.xiocb_handle = handle;
485	xiocb.xiocb_flags = 0;
486	xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
487	xiocb.plist.xiocb_buffer.buf_offset = offset;
488	xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
489	xiocb.plist.xiocb_buffer.buf_length = length;
490
491	cfe_iocb_dispatch(&xiocb);
492
493	if (xiocb.xiocb_status < 0)
494		return xiocb.xiocb_status;
495	return xiocb.plist.xiocb_buffer.buf_retlen;
496}
497#endif				/* CFE_API_writeblk || CFE_API_ALL */
498