2 * Copyright (C) 2000, 2001, 2002 Broadcom Corporation
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.
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.
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.
21 * Broadcom Common Firmware Environment (CFE)
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.
27 * Authors: Mitch Lichtenberg, Chris Demetriou
30 #include <asm/fw/cfe/cfe_api.h>
31 #include "cfe_api_int.h"
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))
37 int cfe_iocb_dispatch(struct cfe_xiocb
*xiocb
);
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.
48 static int (*cfe_dispfunc
) (intptr_t handle
, intptr_t xiocb
);
49 static u64 cfe_handle
;
51 int cfe_init(u64 handle
, u64 ept
)
53 cfe_dispfunc
= NATIVE_FROM_XPTR(ept
);
58 int cfe_iocb_dispatch(struct cfe_xiocb
* xiocb
)
62 return (*cfe_dispfunc
) ((intptr_t) cfe_handle
, (intptr_t) xiocb
);
65 int cfe_close(int handle
)
67 struct cfe_xiocb xiocb
;
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;
75 cfe_iocb_dispatch(&xiocb
);
77 return xiocb
.xiocb_status
;
81 int cfe_cpu_start(int cpu
, void (*fn
) (void), long sp
, long gp
, long a1
)
83 struct cfe_xiocb xiocb
;
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
;
97 cfe_iocb_dispatch(&xiocb
);
99 return xiocb
.xiocb_status
;
102 int cfe_cpu_stop(int cpu
)
104 struct cfe_xiocb xiocb
;
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
;
114 cfe_iocb_dispatch(&xiocb
);
116 return xiocb
.xiocb_status
;
119 int cfe_enumenv(int idx
, char *name
, int namelen
, char *val
, int vallen
)
121 struct cfe_xiocb xiocb
;
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
;
134 cfe_iocb_dispatch(&xiocb
);
136 return xiocb
.xiocb_status
;
140 cfe_enummem(int idx
, int flags
, u64
*start
, u64
*length
, u64
*type
)
142 struct cfe_xiocb xiocb
;
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
;
151 cfe_iocb_dispatch(&xiocb
);
153 if (xiocb
.xiocb_status
< 0)
154 return xiocb
.xiocb_status
;
156 *start
= xiocb
.plist
.xiocb_meminfo
.mi_addr
;
157 *length
= xiocb
.plist
.xiocb_meminfo
.mi_size
;
158 *type
= xiocb
.plist
.xiocb_meminfo
.mi_type
;
163 int cfe_exit(int warm
, int status
)
165 struct cfe_xiocb xiocb
;
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
;
174 cfe_iocb_dispatch(&xiocb
);
176 return xiocb
.xiocb_status
;
179 int cfe_flushcache(int flg
)
181 struct cfe_xiocb xiocb
;
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;
189 cfe_iocb_dispatch(&xiocb
);
191 return xiocb
.xiocb_status
;
194 int cfe_getdevinfo(char *name
)
196 struct cfe_xiocb xiocb
;
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
);
207 cfe_iocb_dispatch(&xiocb
);
209 if (xiocb
.xiocb_status
< 0)
210 return xiocb
.xiocb_status
;
211 return xiocb
.plist
.xiocb_buffer
.buf_ioctlcmd
;
214 int cfe_getenv(char *name
, char *dest
, int destlen
)
216 struct cfe_xiocb xiocb
;
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
;
231 cfe_iocb_dispatch(&xiocb
);
233 return xiocb
.xiocb_status
;
236 int cfe_getfwinfo(cfe_fwinfo_t
* info
)
238 struct cfe_xiocb xiocb
;
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
);
246 cfe_iocb_dispatch(&xiocb
);
248 if (xiocb
.xiocb_status
< 0)
249 return xiocb
.xiocb_status
;
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
;
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
;
268 int cfe_getstdhandle(int flg
)
270 struct cfe_xiocb xiocb
;
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;
278 cfe_iocb_dispatch(&xiocb
);
280 if (xiocb
.xiocb_status
< 0)
281 return xiocb
.xiocb_status
;
282 return xiocb
.xiocb_handle
;
288 struct cfe_xiocb xiocb
;
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;
297 cfe_iocb_dispatch(&xiocb
);
299 return xiocb
.plist
.xiocb_time
.ticks
;
303 int cfe_inpstat(int handle
)
305 struct cfe_xiocb xiocb
;
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;
314 cfe_iocb_dispatch(&xiocb
);
316 if (xiocb
.xiocb_status
< 0)
317 return xiocb
.xiocb_status
;
318 return xiocb
.plist
.xiocb_inpstat
.inp_status
;
322 cfe_ioctl(int handle
, unsigned int ioctlnum
, unsigned char *buffer
,
323 int length
, int *retlen
, u64 offset
)
325 struct cfe_xiocb xiocb
;
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
;
337 cfe_iocb_dispatch(&xiocb
);
340 *retlen
= xiocb
.plist
.xiocb_buffer
.buf_retlen
;
341 return xiocb
.xiocb_status
;
344 int cfe_open(char *name
)
346 struct cfe_xiocb xiocb
;
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
);
357 cfe_iocb_dispatch(&xiocb
);
359 if (xiocb
.xiocb_status
< 0)
360 return xiocb
.xiocb_status
;
361 return xiocb
.xiocb_handle
;
364 int cfe_read(int handle
, unsigned char *buffer
, int length
)
366 return cfe_readblk(handle
, 0, buffer
, length
);
369 int cfe_readblk(int handle
, s64 offset
, unsigned char *buffer
, int length
)
371 struct cfe_xiocb xiocb
;
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
;
382 cfe_iocb_dispatch(&xiocb
);
384 if (xiocb
.xiocb_status
< 0)
385 return xiocb
.xiocb_status
;
386 return xiocb
.plist
.xiocb_buffer
.buf_retlen
;
389 int cfe_setenv(char *name
, char *val
)
391 struct cfe_xiocb xiocb
;
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
);
404 cfe_iocb_dispatch(&xiocb
);
406 return xiocb
.xiocb_status
;
409 int cfe_write(int handle
, unsigned char *buffer
, int length
)
411 return cfe_writeblk(handle
, 0, buffer
, length
);
414 int cfe_writeblk(int handle
, s64 offset
, unsigned char *buffer
, int length
)
416 struct cfe_xiocb xiocb
;
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
;
427 cfe_iocb_dispatch(&xiocb
);
429 if (xiocb
.xiocb_status
< 0)
430 return xiocb
.xiocb_status
;
431 return xiocb
.plist
.xiocb_buffer
.buf_retlen
;