RT-AC56 3.0.0.4.374.37 core
[tomato.git] / release / src-rt-6.x.4708 / cfe / cfe / main / cfe_iocb_dispatch.c
bloba71857ecd96b4b26c64c17706ee246c92c402221
1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
3 *
4 * IOCB dispatcher File: cfe_iocb_dispatch.c
5 *
6 * This routine is the main API dispatch for CFE. User API
7 * calls, via the ROM entry point, get dispatched to routines
8 * in this module.
9 *
10 * Author: Mitch Lichtenberg (mpl@broadcom.com)
12 *********************************************************************
14 * Copyright 2000,2001,2002,2003
15 * Broadcom Corporation. All rights reserved.
17 * This software is furnished under license and may be used and
18 * copied only in accordance with the following terms and
19 * conditions. Subject to these conditions, you may download,
20 * copy, install, use, modify and distribute modified or unmodified
21 * copies of this software in source and/or binary form. No title
22 * or ownership is transferred hereby.
24 * 1) Any source code used, modified or distributed must reproduce
25 * and retain this copyright notice and list of conditions
26 * as they appear in the source file.
28 * 2) No right is granted to use any trade name, trademark, or
29 * logo of Broadcom Corporation. The "Broadcom Corporation"
30 * name may not be used to endorse or promote products derived
31 * from this software without the prior written permission of
32 * Broadcom Corporation.
34 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
35 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
36 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
37 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
38 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
39 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
40 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
41 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
42 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
44 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
45 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
46 * THE POSSIBILITY OF SUCH DAMAGE.
47 ********************************************************************* */
50 #include "lib_types.h"
51 #include "lib_malloc.h"
52 #include "lib_queue.h"
53 #include "lib_printf.h"
54 #include "lib_string.h"
55 #include "cfe_iocb.h"
56 #include "cfe_error.h"
57 #include "cfe_device.h"
58 #include "cfe_timer.h"
59 #include "cfe_mem.h"
60 #include "cfe_fileops.h"
61 #include "cfe_boot.h"
62 #include "env_subr.h"
63 #include "cfe.h"
64 #include "cfe_console.h"
65 #include "bsp_config.h"
66 #include "initdata.h"
68 /* *********************************************************************
69 * Constants
70 ********************************************************************* */
72 #define HV 1 /* handle valid */
74 #ifndef CFG_BOARD_ID
75 #define CFG_BOARD_ID 0
76 #endif
78 /* *********************************************************************
79 * Globals
80 ********************************************************************* */
82 cfe_devctx_t *cfe_handle_table[CFE_MAX_HANDLE];
84 extern void _cfe_flushcache(int);
86 /* *********************************************************************
87 * Prototypes
88 ********************************************************************* */
90 int cfe_iocb_dispatch(cfe_iocb_t *iocb);
91 void cfe_device_poll(void *);
93 #if CFG_MULTI_CPUS
94 extern int altcpu_cmd_start(uint64_t,uint64_t *);
95 extern int altcpu_cmd_stop(uint64_t);
96 #endif
98 /* *********************************************************************
99 * Dispatch table
100 ********************************************************************* */
102 struct cfe_cmd_dispatch_s {
103 int plistsize;
104 int flags;
105 int (*func)(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
109 static int cfe_cmd_fw_getinfo(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
110 static int cfe_cmd_fw_restart(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
111 static int cfe_cmd_fw_boot(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
112 static int cfe_cmd_fw_cpuctl(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
113 static int cfe_cmd_fw_gettime(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
114 static int cfe_cmd_fw_memenum(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
115 static int cfe_cmd_fw_flushcache(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
117 static int cfe_cmd_dev_gethandle(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
118 static int cfe_cmd_dev_enum(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
119 static int cfe_cmd_dev_open(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
120 static int cfe_cmd_dev_inpstat(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
121 static int cfe_cmd_dev_read(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
122 static int cfe_cmd_dev_write(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
123 static int cfe_cmd_dev_ioctl(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
124 static int cfe_cmd_dev_close(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
125 static int cfe_cmd_dev_getinfo(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
127 static int cfe_cmd_env_enum(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
128 static int cfe_cmd_env_get(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
129 static int cfe_cmd_env_set(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
130 static int cfe_cmd_env_del(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
132 const static struct cfe_cmd_dispatch_s cfe_cmd_dispatch_table[CFE_CMD_MAX] = {
133 {sizeof(iocb_fwinfo_t), 0, cfe_cmd_fw_getinfo}, /* 0 : CFE_CMD_FW_GETINFO */
134 {sizeof(iocb_exitstat_t),0, cfe_cmd_fw_restart}, /* 1 : CFE_CMD_FW_RESTART */
135 {sizeof(iocb_buffer_t), 0, cfe_cmd_fw_boot}, /* 2 : CFE_CMD_FW_BOOT */
136 {sizeof(iocb_cpuctl_t), 0, cfe_cmd_fw_cpuctl}, /* 3 : CFE_CMD_FW_CPUCTL */
137 {sizeof(iocb_time_t), 0, cfe_cmd_fw_gettime}, /* 4 : CFE_CMD_FW_GETTIME */
138 {sizeof(iocb_meminfo_t),0, cfe_cmd_fw_memenum}, /* 5 : CFE_CMD_FW_MEMENUM */
139 {0, 0, cfe_cmd_fw_flushcache}, /* 6 : CFE_CMD_FW_FLUSHCACHE */
140 {-1, 0, NULL}, /* 7 : */
141 {-1, 0, NULL}, /* 8 : */
142 {0, 0, cfe_cmd_dev_gethandle}, /* 9 : CFE_CMD_DEV_GETHANDLE */
143 {sizeof(iocb_envbuf_t), 0, cfe_cmd_dev_enum}, /* 10 : CFE_CMD_DEV_ENUM */
144 {sizeof(iocb_buffer_t), 0, cfe_cmd_dev_open}, /* 11 : CFE_CMD_DEV_OPEN */
145 {sizeof(iocb_inpstat_t),HV, cfe_cmd_dev_inpstat}, /* 12 : CFE_CMD_DEV_INPSTAT */
146 {sizeof(iocb_buffer_t), HV, cfe_cmd_dev_read}, /* 13 : CFE_CMD_DEV_READ */
147 {sizeof(iocb_buffer_t), HV, cfe_cmd_dev_write}, /* 14 : CFE_CMD_DEV_WRITE */
148 {sizeof(iocb_buffer_t), HV, cfe_cmd_dev_ioctl}, /* 15 : CFE_CMD_DEV_IOCTL */
149 {0, HV, cfe_cmd_dev_close}, /* 16 : CFE_CMD_DEV_CLOSE */
150 {sizeof(iocb_buffer_t), 0, cfe_cmd_dev_getinfo}, /* 17 : CFE_CMD_DEV_GETINFO */
151 {-1, 0, NULL}, /* 18 : */
152 {-1, 0, NULL}, /* 19 : */
153 {sizeof(iocb_envbuf_t), 0, cfe_cmd_env_enum}, /* 20 : CFE_CMD_ENV_ENUM */
154 {-1, 0, NULL}, /* 21 : */
155 {sizeof(iocb_envbuf_t), 0, cfe_cmd_env_get}, /* 22 : CFE_CMD_ENV_GET */
156 {sizeof(iocb_envbuf_t), 0, cfe_cmd_env_set}, /* 23 : CFE_CMD_ENV_SET */
157 {sizeof(iocb_envbuf_t), 0, cfe_cmd_env_del}, /* 24 : CFE_CMD_ENV_DEL */
158 {-1, 0, NULL}, /* 25 : */
159 {-1, 0, NULL}, /* 26 : */
160 {-1, 0, NULL}, /* 27 : */
161 {-1, 0, NULL}, /* 28 : */
162 {-1, 0, NULL}, /* 29 : */
163 {-1, 0, NULL}, /* 30 : */
164 {-1, 0, NULL} /* 31 : */
167 /* *********************************************************************
168 * IOCB dispatch routines
169 ********************************************************************* */
171 void cfe_device_poll(void *x)
173 int idx;
174 cfe_devctx_t **ctx = cfe_handle_table;
176 for (idx = 0; idx < CFE_MAX_HANDLE; idx++,ctx++) {
177 if ((*ctx) && ((*ctx)->dev_dev->dev_dispatch->dev_poll)) {
178 (*ctx)->dev_dev->dev_dispatch->dev_poll(*ctx,cfe_ticks);
183 int cfe_iocb_dispatch(cfe_iocb_t *iocb)
185 const struct cfe_cmd_dispatch_s *disp;
186 int res;
187 cfe_devctx_t *ctx;
190 * Check for commands codes out of range
193 if ((iocb->iocb_fcode < 0) || (iocb->iocb_fcode >= CFE_CMD_MAX)) {
194 iocb->iocb_status = CFE_ERR_INV_COMMAND;
195 return iocb->iocb_status;
199 * Check for command codes in range but invalid
202 disp = &cfe_cmd_dispatch_table[iocb->iocb_fcode];
204 if (disp->plistsize < 0) {
205 iocb->iocb_status = CFE_ERR_INV_COMMAND;
206 return iocb->iocb_status;
210 * Check for invalid parameter list size
213 if (disp->plistsize != iocb->iocb_psize) {
214 iocb->iocb_status = CFE_ERR_INV_PARAM;
215 return iocb->iocb_status;
219 * Determine handle
222 ctx = NULL;
223 if (disp->flags & HV) {
224 if ((iocb->iocb_handle >= CFE_MAX_HANDLE) ||
225 (iocb->iocb_handle < 0) ||
226 (cfe_handle_table[iocb->iocb_handle] == NULL)){
227 iocb->iocb_status = CFE_ERR_INV_PARAM;
228 return iocb->iocb_status;
230 ctx = cfe_handle_table[iocb->iocb_handle];
234 * Dispatch to handler routine
237 res = (*disp->func)(ctx,iocb);
239 iocb->iocb_status = res;
240 return res;
243 static int cfe_newhandle(void)
245 int idx;
247 for (idx = 0; idx < CFE_MAX_HANDLE; idx++) {
248 if (cfe_handle_table[idx] == NULL) break;
251 if (idx == CFE_MAX_HANDLE) return -1;
253 return idx;
257 /* *********************************************************************
258 * Implementation routines for each IOCB function
259 ********************************************************************* */
261 static int cfe_cmd_fw_getinfo(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
263 iocb_fwinfo_t *info = &iocb->plist.iocb_fwinfo;
265 info->fwi_version = (CFE_VER_MAJOR << 16) |
266 (CFE_VER_MINOR << 8) |
267 (CFE_VER_BUILD);
268 info->fwi_totalmem = ((cfe_int64_t) mem_totalsize) << 10;
269 info->fwi_flags =
270 #ifdef __long64
271 CFE_FWI_64BIT |
272 #else
273 CFE_FWI_32BIT |
274 #endif
275 #if CFG_EMBEDDED_PIC
276 CFE_FWI_RELOC |
277 #endif
278 #if !CFG_RUNFROMKSEG0
279 CFE_FWI_UNCACHED |
280 #endif
281 #if CFG_MULTI_CPUS
282 CFE_FWI_MULTICPU |
283 #endif
284 #ifdef _VERILOG_
285 CFE_FWI_RTLSIM |
286 #endif
287 #ifdef _FUNCSIM_
288 CFE_FWI_FUNCSIM |
289 #endif
292 info->fwi_boardid = CFG_BOARD_ID;
293 info->fwi_bootarea_pa = (cfe_int64_t) mem_bootarea_start;
294 info->fwi_bootarea_va = BOOT_START_ADDRESS;
295 info->fwi_bootarea_size = (cfe_int64_t) mem_bootarea_size;
296 info->fwi_reserved1 = 0;
297 info->fwi_reserved2 = 0;
298 info->fwi_reserved3 = 0;
300 return CFE_OK;
303 static int cfe_cmd_fw_restart(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
305 if (iocb->iocb_flags & CFE_FLG_WARMSTART) {
306 cfe_warmstart(iocb->plist.iocb_exitstat.status);
308 else {
309 cfe_restart();
312 /* should not get here */
314 return CFE_OK;
317 static int cfe_cmd_fw_boot(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
319 return CFE_ERR_INV_COMMAND; /* not implemented yet */
322 static int cfe_cmd_fw_cpuctl(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
324 #if CFG_MULTI_CPUS
325 int res;
326 uint64_t startargs[4];
328 switch (iocb->plist.iocb_cpuctl.cpu_command) {
329 case CFE_CPU_CMD_START:
331 startargs[0] = iocb->plist.iocb_cpuctl.start_addr;
332 startargs[1] = iocb->plist.iocb_cpuctl.sp_val;
333 startargs[2] = iocb->plist.iocb_cpuctl.gp_val;
334 startargs[3] = iocb->plist.iocb_cpuctl.a1_val;
336 res = altcpu_cmd_start(iocb->plist.iocb_cpuctl.cpu_number,
337 startargs);
338 break;
339 case CFE_CPU_CMD_STOP:
340 res = altcpu_cmd_stop(iocb->plist.iocb_cpuctl.cpu_number);
341 break;
342 default:
343 res = CFE_ERR_INV_PARAM;
346 return res;
347 #else
348 return CFE_ERR_INV_COMMAND;
349 #endif
352 static int cfe_cmd_fw_gettime(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
354 POLL();
356 iocb->plist.iocb_time.ticks = cfe_ticks;
358 return CFE_OK;
361 static int cfe_cmd_fw_memenum(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
363 int type;
364 int res;
365 uint64_t addr,size;
367 res = cfe_arena_enum(iocb->plist.iocb_meminfo.mi_idx,
368 &type,
369 &addr,
370 &size,
371 (iocb->iocb_flags & CFE_FLG_FULL_ARENA) ? TRUE : FALSE);
373 iocb->plist.iocb_meminfo.mi_addr = addr;
374 iocb->plist.iocb_meminfo.mi_size = size;
375 iocb->plist.iocb_meminfo.mi_type = type;
377 if (res == 0) {
378 if (type == MEMTYPE_DRAM_AVAILABLE) {
379 iocb->plist.iocb_meminfo.mi_type = CFE_MI_AVAILABLE;
381 else {
382 iocb->plist.iocb_meminfo.mi_type = CFE_MI_RESERVED;
386 return res;
389 static int cfe_cmd_fw_flushcache(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
391 _cfe_flushcache(iocb->iocb_flags);
392 return CFE_OK;
395 static int cfe_cmd_dev_enum(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
397 return CFE_ERR_INV_COMMAND;
400 static int cfe_cmd_dev_gethandle(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
402 switch (iocb->iocb_flags) {
403 case CFE_STDHANDLE_CONSOLE:
404 if (console_handle == -1) return CFE_ERR_DEVNOTFOUND;
405 iocb->iocb_handle = console_handle;
406 return CFE_OK;
407 break;
408 default:
409 return CFE_ERR_INV_PARAM;
413 static int cfe_cmd_dev_open(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
415 int h;
416 cfe_device_t *dev;
417 char devname[64];
418 int res;
421 * Get device name
424 xstrncpy(devname,(char *)iocb->plist.iocb_buffer.buf_ptr,sizeof(devname));
427 * Find device in device table
430 dev = cfe_finddev(devname);
431 if (!dev) return CFE_ERR_DEVNOTFOUND;
434 * Fail if someone else already has the device open
437 if (dev->dev_opencount > 0) return CFE_ERR_DEVOPEN;
440 * Generate a new handle
443 h = cfe_newhandle();
444 if (h < 0) return CFE_ERR_NOMEM;
447 * Allocate a context
450 ctx = (cfe_devctx_t *) KMALLOC(sizeof(cfe_devctx_t),0);
451 if (ctx == NULL) return CFE_ERR_NOMEM;
454 * Fill in the context
457 ctx->dev_dev = dev;
458 ctx->dev_softc = dev->dev_softc;
459 ctx->dev_openinfo = NULL;
462 * Call driver's open func
465 res = dev->dev_dispatch->dev_open(ctx);
467 if (res != 0) {
468 KFREE(ctx);
469 return res;
473 * Increment refcnt and save handle
476 dev->dev_opencount++;
477 cfe_handle_table[h] = ctx;
478 iocb->iocb_handle = h;
481 * Success!
484 return CFE_OK;
487 static int cfe_cmd_dev_inpstat(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
489 int status;
491 status = ctx->dev_dev->dev_dispatch->dev_inpstat(ctx,&(iocb->plist.iocb_inpstat));
493 return status;
496 static int cfe_cmd_dev_read(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
498 int status;
500 status = ctx->dev_dev->dev_dispatch->dev_read(ctx,&(iocb->plist.iocb_buffer));
502 return status;
505 static int cfe_cmd_dev_write(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
507 int status;
509 status = ctx->dev_dev->dev_dispatch->dev_write(ctx,&(iocb->plist.iocb_buffer));
511 return status;
514 static int cfe_cmd_dev_ioctl(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
516 int status;
518 status = ctx->dev_dev->dev_dispatch->dev_ioctl(ctx,&(iocb->plist.iocb_buffer));
520 return status;
523 static int cfe_cmd_dev_close(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
526 * Call device close function
529 ctx->dev_dev->dev_dispatch->dev_close(ctx);
532 * Decrement refcnt
535 ctx->dev_dev->dev_opencount--;
538 * Wipe out handle
541 cfe_handle_table[iocb->iocb_handle] = NULL;
544 * Release device context
547 KFREE(ctx);
549 return CFE_OK;
552 static int cfe_cmd_dev_getinfo(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
554 cfe_device_t *dev;
555 char devname[64];
556 char *x;
559 * Get device name
562 xstrncpy(devname,(char *)iocb->plist.iocb_buffer.buf_ptr,sizeof(devname));
565 * Find device in device table
568 if ((x = strchr(devname,':'))) *x = '\0';
569 dev = cfe_finddev(devname);
570 if (!dev) return CFE_ERR_DEVNOTFOUND;
573 * Return device class
576 iocb->plist.iocb_buffer.buf_devflags = dev->dev_class;
578 return CFE_OK;
581 static int cfe_cmd_env_enum(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
583 int vallen,namelen,res;
585 namelen = iocb->plist.iocb_envbuf.name_length;
586 vallen = iocb->plist.iocb_envbuf.val_length;
588 res = env_enum(iocb->plist.iocb_envbuf.enum_idx,
589 (char *)iocb->plist.iocb_envbuf.name_ptr,
590 &namelen,
591 (char *)iocb->plist.iocb_envbuf.val_ptr,
592 &vallen);
594 if (res < 0) return CFE_ERR_ENVNOTFOUND;
596 return CFE_OK;
600 static int cfe_cmd_env_get(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
602 char *env;
604 env = env_getenv((char *)iocb->plist.iocb_envbuf.name_ptr);
606 if (env == NULL) return CFE_ERR_ENVNOTFOUND;
608 xstrncpy((char *)iocb->plist.iocb_envbuf.val_ptr,
609 env,
610 iocb->plist.iocb_envbuf.val_length);
612 return CFE_OK;
615 static int cfe_cmd_env_set(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
617 int res;
618 int flg;
621 flg = (iocb->iocb_flags & CFE_FLG_ENV_PERMANENT) ?
622 ENV_FLG_NORMAL : ENV_FLG_BUILTIN;
624 res = env_setenv((char *)iocb->plist.iocb_envbuf.name_ptr,
625 (char *)iocb->plist.iocb_envbuf.val_ptr,
626 flg);
628 if (res == 0) {
629 if (iocb->iocb_flags & CFE_FLG_ENV_PERMANENT) res = env_save();
632 if (res < 0) return res;
634 return CFE_OK;
637 static int cfe_cmd_env_del(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
639 int res;
641 res = env_delenv((char *)iocb->plist.iocb_envbuf.name_ptr);
643 return res;