1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
4 * IOCB dispatcher File: cfe_iocb_dispatch.c
6 * This routine is the main API dispatch for CFE. User API
7 * calls, via the ROM entry point, get dispatched to routines
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"
56 #include "cfe_error.h"
57 #include "cfe_device.h"
58 #include "cfe_timer.h"
60 #include "cfe_fileops.h"
64 #include "cfe_console.h"
65 #include "bsp_config.h"
68 /* *********************************************************************
70 ********************************************************************* */
72 #define HV 1 /* handle valid */
75 #define CFG_BOARD_ID 0
78 /* *********************************************************************
80 ********************************************************************* */
82 cfe_devctx_t
*cfe_handle_table
[CFE_MAX_HANDLE
];
84 extern void _cfe_flushcache(int);
86 /* *********************************************************************
88 ********************************************************************* */
90 int cfe_iocb_dispatch(cfe_iocb_t
*iocb
);
91 void cfe_device_poll(void *);
94 extern int altcpu_cmd_start(uint64_t,uint64_t *);
95 extern int altcpu_cmd_stop(uint64_t);
98 /* *********************************************************************
100 ********************************************************************* */
102 struct cfe_cmd_dispatch_s
{
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
)
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
;
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
;
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
;
243 static int cfe_newhandle(void)
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;
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) |
268 info
->fwi_totalmem
= ((cfe_int64_t
) mem_totalsize
) << 10;
278 #if !CFG_RUNFROMKSEG0
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;
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
);
312 /* should not get here */
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
)
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
,
339 case CFE_CPU_CMD_STOP
:
340 res
= altcpu_cmd_stop(iocb
->plist
.iocb_cpuctl
.cpu_number
);
343 res
= CFE_ERR_INV_PARAM
;
348 return CFE_ERR_INV_COMMAND
;
352 static int cfe_cmd_fw_gettime(cfe_devctx_t
*ctx
,cfe_iocb_t
*iocb
)
356 iocb
->plist
.iocb_time
.ticks
= cfe_ticks
;
361 static int cfe_cmd_fw_memenum(cfe_devctx_t
*ctx
,cfe_iocb_t
*iocb
)
367 res
= cfe_arena_enum(iocb
->plist
.iocb_meminfo
.mi_idx
,
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
;
378 if (type
== MEMTYPE_DRAM_AVAILABLE
) {
379 iocb
->plist
.iocb_meminfo
.mi_type
= CFE_MI_AVAILABLE
;
382 iocb
->plist
.iocb_meminfo
.mi_type
= CFE_MI_RESERVED
;
389 static int cfe_cmd_fw_flushcache(cfe_devctx_t
*ctx
,cfe_iocb_t
*iocb
)
391 _cfe_flushcache(iocb
->iocb_flags
);
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
;
409 return CFE_ERR_INV_PARAM
;
413 static int cfe_cmd_dev_open(cfe_devctx_t
*ctx
,cfe_iocb_t
*iocb
)
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
444 if (h
< 0) return CFE_ERR_NOMEM
;
450 ctx
= (cfe_devctx_t
*) KMALLOC(sizeof(cfe_devctx_t
),0);
451 if (ctx
== NULL
) return CFE_ERR_NOMEM
;
454 * Fill in the context
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
);
473 * Increment refcnt and save handle
476 dev
->dev_opencount
++;
477 cfe_handle_table
[h
] = ctx
;
478 iocb
->iocb_handle
= h
;
487 static int cfe_cmd_dev_inpstat(cfe_devctx_t
*ctx
,cfe_iocb_t
*iocb
)
491 status
= ctx
->dev_dev
->dev_dispatch
->dev_inpstat(ctx
,&(iocb
->plist
.iocb_inpstat
));
496 static int cfe_cmd_dev_read(cfe_devctx_t
*ctx
,cfe_iocb_t
*iocb
)
500 status
= ctx
->dev_dev
->dev_dispatch
->dev_read(ctx
,&(iocb
->plist
.iocb_buffer
));
505 static int cfe_cmd_dev_write(cfe_devctx_t
*ctx
,cfe_iocb_t
*iocb
)
509 status
= ctx
->dev_dev
->dev_dispatch
->dev_write(ctx
,&(iocb
->plist
.iocb_buffer
));
514 static int cfe_cmd_dev_ioctl(cfe_devctx_t
*ctx
,cfe_iocb_t
*iocb
)
518 status
= ctx
->dev_dev
->dev_dispatch
->dev_ioctl(ctx
,&(iocb
->plist
.iocb_buffer
));
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
);
535 ctx
->dev_dev
->dev_opencount
--;
541 cfe_handle_table
[iocb
->iocb_handle
] = NULL
;
544 * Release device context
552 static int cfe_cmd_dev_getinfo(cfe_devctx_t
*ctx
,cfe_iocb_t
*iocb
)
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
;
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
,
591 (char *)iocb
->plist
.iocb_envbuf
.val_ptr
,
594 if (res
< 0) return CFE_ERR_ENVNOTFOUND
;
600 static int cfe_cmd_env_get(cfe_devctx_t
*ctx
,cfe_iocb_t
*iocb
)
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
,
610 iocb
->plist
.iocb_envbuf
.val_length
);
615 static int cfe_cmd_env_set(cfe_devctx_t
*ctx
,cfe_iocb_t
*iocb
)
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
,
629 if (iocb
->iocb_flags
& CFE_FLG_ENV_PERMANENT
) res
= env_save();
632 if (res
< 0) return res
;
637 static int cfe_cmd_env_del(cfe_devctx_t
*ctx
,cfe_iocb_t
*iocb
)
641 res
= env_delenv((char *)iocb
->plist
.iocb_envbuf
.name_ptr
);