1/* ********************************************************************* 2 * Broadcom Common Firmware Environment (CFE) 3 * 4 * IOCB dispatcher File: cfe_xreq.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 * This module looks similar to cfe_iocb_dispatch - it is different 11 * in that the data structure used, cfe_xiocb_t, uses fixed 12 * size field members (specifically, all 64-bits) no matter how 13 * the firmware is compiled. This ensures a consistent API 14 * interface on any implementation. When you call CFE 15 * from another program, the entry vector comes here first. 16 * 17 * Should the normal cfe_iocb interface change, this one should 18 * be kept the same for backward compatibility reasons. 19 * 20 * Author: Mitch Lichtenberg 21 * 22 ********************************************************************* 23 * 24 * Copyright 2000,2001,2002,2003 25 * Broadcom Corporation. All rights reserved. 26 * 27 * This software is furnished under license and may be used and 28 * copied only in accordance with the following terms and 29 * conditions. Subject to these conditions, you may download, 30 * copy, install, use, modify and distribute modified or unmodified 31 * copies of this software in source and/or binary form. No title 32 * or ownership is transferred hereby. 33 * 34 * 1) Any source code used, modified or distributed must reproduce 35 * and retain this copyright notice and list of conditions 36 * as they appear in the source file. 37 * 38 * 2) No right is granted to use any trade name, trademark, or 39 * logo of Broadcom Corporation. The "Broadcom Corporation" 40 * name may not be used to endorse or promote products derived 41 * from this software without the prior written permission of 42 * Broadcom Corporation. 43 * 44 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR 45 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED 46 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 47 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT 48 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN 49 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, 50 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 51 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 52 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 53 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 54 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 55 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF 56 * THE POSSIBILITY OF SUCH DAMAGE. 57 ********************************************************************* */ 58 59 60#include "cfe.h" 61#include "cfe_xiocb.h" 62#if CFG_VENDOR_EXTENSIONS 63#include "cfe_vendor_iocb.h" 64#include "cfe_vendor_xiocb.h" 65#endif 66#include "env_subr.h" 67 68 69/* ********************************************************************* 70 * Constants 71 ********************************************************************* */ 72 73/* enum values for various plist types */ 74 75#define PLBUF 1 /* iocb_buffer_t */ 76#define PLCPU 2 /* iocb_cpuctl_t */ 77#define PLMEM 3 /* iocb_meminfo_t */ 78#define PLENV 4 /* iocb_envbuf_t */ 79#define PLINP 5 /* iocb_inpstat_t */ 80#define PLTIM 6 /* iocb_time_t */ 81#define PLINF 7 /* iocb_fwinfo_t */ 82#define PLEXIT 8 /* iocb_exitstat_t */ 83 84/* ********************************************************************* 85 * Structures 86 ********************************************************************* */ 87 88struct cfe_xcmd_dispatch_s { 89 int xplistsize; 90 int iplistsize; 91 int plisttype; 92}; 93 94 95/* ********************************************************************* 96 * Command conversion table 97 * This table contains useful information for converting 98 * iocbs to xiocbs. 99 ********************************************************************* */ 100 101const static struct cfe_xcmd_dispatch_s cfe_xcmd_dispatch_table[CFE_CMD_MAX] = { 102 {sizeof(xiocb_fwinfo_t), sizeof(iocb_fwinfo_t), PLINF}, /* 0 : CFE_CMD_FW_GETINFO */ 103 {sizeof(xiocb_exitstat_t),sizeof(iocb_exitstat_t),PLEXIT}, /* 1 : CFE_CMD_FW_RESTART */ 104 {sizeof(xiocb_buffer_t), sizeof(iocb_buffer_t), PLBUF}, /* 2 : CFE_CMD_FW_BOOT */ 105 {sizeof(xiocb_cpuctl_t), sizeof(iocb_cpuctl_t), PLCPU}, /* 3 : CFE_CMD_FW_CPUCTL */ 106 {sizeof(xiocb_time_t), sizeof(iocb_time_t), PLTIM}, /* 4 : CFE_CMD_FW_GETTIME */ 107 {sizeof(xiocb_meminfo_t),sizeof(iocb_meminfo_t),PLMEM}, /* 5 : CFE_CMD_FW_MEMENUM */ 108 {0, 0, 0}, /* 6 : CFE_CMD_FW_FLUSHCACHE */ 109 {-1, 0, 0}, /* 7 : */ 110 {-1, 0, 0}, /* 8 : */ 111 {0, 0, 0}, /* 9 : CFE_CMD_DEV_GETHANDLE */ 112 {sizeof(xiocb_envbuf_t), sizeof(iocb_envbuf_t), PLENV}, /* 10 : CFE_CMD_DEV_ENUM */ 113 {sizeof(xiocb_buffer_t), sizeof(iocb_buffer_t), PLBUF}, /* 11 : CFE_CMD_DEV_OPEN_*/ 114 {sizeof(xiocb_inpstat_t),sizeof(iocb_inpstat_t),PLINP}, /* 12 : CFE_CMD_DEV_INPSTAT */ 115 {sizeof(xiocb_buffer_t), sizeof(iocb_buffer_t), PLBUF}, /* 13 : CFE_CMD_DEV_READ */ 116 {sizeof(xiocb_buffer_t), sizeof(iocb_buffer_t), PLBUF}, /* 14 : CFE_CMD_DEV_WRITE */ 117 {sizeof(xiocb_buffer_t), sizeof(iocb_buffer_t), PLBUF}, /* 15 : CFE_CMD_DEV_IOCTL */ 118 {0, 0, 0}, /* 16 : CFE_CMD_DEV_CLOSE */ 119 {sizeof(xiocb_buffer_t), sizeof(iocb_buffer_t), PLBUF}, /* 17 : CFE_CMD_DEV_GETINFO */ 120 {-1, 0, 0}, /* 18 : */ 121 {-1, 0, 0}, /* 19 : */ 122 {sizeof(xiocb_envbuf_t), sizeof(iocb_envbuf_t), PLENV}, /* 20 : CFE_CMD_ENV_ENUM */ 123 {-1, 0, 0}, /* 21 : */ 124 {sizeof(xiocb_envbuf_t), sizeof(iocb_envbuf_t), PLENV}, /* 22 : CFE_CMD_ENV_GET */ 125 {sizeof(xiocb_envbuf_t), sizeof(iocb_envbuf_t), PLENV}, /* 23 : CFE_CMD_ENV_SET */ 126 {sizeof(xiocb_envbuf_t), sizeof(iocb_envbuf_t), PLENV}, /* 24 : CFE_CMD_ENV_DEL */ 127 {-1, 0, 0}, /* 25 : */ 128 {-1, 0, 0}, /* 26 : */ 129 {-1, 0, 0}, /* 27 : */ 130 {-1, 0, 0}, /* 28 : */ 131 {-1, 0, 0}, /* 29 : */ 132 {-1, 0, 0}, /* 30 : */ 133 {-1, 0, 0} /* 31 : */ 134}; 135 136 137/* ********************************************************************* 138 * Externs 139 ********************************************************************* */ 140 141extern int cfe_iocb_dispatch(cfe_iocb_t *iocb); 142cfe_int_t cfe_doxreq(cfe_xiocb_t *xiocb); 143#if CFG_VENDOR_EXTENSIONS 144extern cfe_int_t cfe_vendor_doxreq(cfe_vendor_xiocb_t *xiocb); 145#endif 146 147/* ********************************************************************* 148 * cfe_doxreq(xiocb) 149 * 150 * Process an xiocb request. This routine converts an xiocb 151 * into an iocb, calls the IOCB dispatcher, converts the results 152 * back into the xiocb, and returns. 153 * 154 * Input parameters: 155 * xiocb - pointer to user xiocb 156 * 157 * Return value: 158 * command status, <0 if error occured 159 ********************************************************************* */ 160 161cfe_int_t cfe_doxreq(cfe_xiocb_t *xiocb) 162{ 163 const struct cfe_xcmd_dispatch_s *disp; 164 cfe_iocb_t iiocb; 165 cfe_int_t res; 166 167 /* 168 * Call out to customer-specific IOCBs. Customers may choose 169 * to implement their own XIOCBs directly, or go through their own 170 * translation layer (xiocb->iocb like CFE does) to insulate 171 * themselves from IOCB changes in the future. 172 */ 173 if (xiocb->xiocb_fcode >= CFE_CMD_VENDOR_USE) { 174#if CFG_VENDOR_EXTENSIONS 175 return cfe_vendor_doxreq((cfe_vendor_xiocb_t *)xiocb); 176#else 177 return CFE_ERR_INV_COMMAND; 178#endif 179 } 180 181 /* 182 * Check for commands codes out of range 183 */ 184 185 if ((xiocb->xiocb_fcode < 0) || (xiocb->xiocb_fcode >= CFE_CMD_MAX)) { 186 xiocb->xiocb_status = CFE_ERR_INV_COMMAND; 187 return xiocb->xiocb_status; 188 } 189 190 /* 191 * Check for command codes in range but invalid 192 */ 193 194 disp = &cfe_xcmd_dispatch_table[xiocb->xiocb_fcode]; 195 196 if (disp->xplistsize < 0) { 197 xiocb->xiocb_status = CFE_ERR_INV_COMMAND; 198 return xiocb->xiocb_status; 199 } 200 201 /* 202 * Check for invalid parameter list size 203 */ 204 205 if (disp->xplistsize != xiocb->xiocb_psize) { 206 xiocb->xiocb_status = CFE_ERR_INV_PARAM; 207 return xiocb->xiocb_status; 208 } 209 210 /* 211 * Okay, copy parameters into the internal IOCB. 212 * First, the fixed header. 213 */ 214 215 iiocb.iocb_fcode = (unsigned int) xiocb->xiocb_fcode; 216 iiocb.iocb_status = (int) xiocb->xiocb_status; 217 iiocb.iocb_handle = (int) xiocb->xiocb_handle; 218 iiocb.iocb_flags = (unsigned int) xiocb->xiocb_flags; 219 iiocb.iocb_psize = (unsigned int) disp->iplistsize; 220 221 /* 222 * Now the parameter list 223 */ 224 225 switch (disp->plisttype) { 226 case PLBUF: 227 iiocb.plist.iocb_buffer.buf_offset = (cfe_offset_t) xiocb->plist.xiocb_buffer.buf_offset; 228 iiocb.plist.iocb_buffer.buf_ptr = xiocb->plist.xiocb_buffer.buf_ptr; 229 iiocb.plist.iocb_buffer.buf_length = (unsigned int) xiocb->plist.xiocb_buffer.buf_length; 230 iiocb.plist.iocb_buffer.buf_retlen = (unsigned int) xiocb->plist.xiocb_buffer.buf_retlen; 231 iiocb.plist.iocb_buffer.buf_ioctlcmd = (unsigned int) xiocb->plist.xiocb_buffer.buf_ioctlcmd; 232 break; 233 case PLCPU: 234 iiocb.plist.iocb_cpuctl.cpu_number = (unsigned int) xiocb->plist.xiocb_cpuctl.cpu_number; 235 iiocb.plist.iocb_cpuctl.cpu_command = (unsigned int) xiocb->plist.xiocb_cpuctl.cpu_command; 236 iiocb.plist.iocb_cpuctl.start_addr = xiocb->plist.xiocb_cpuctl.start_addr; 237 iiocb.plist.iocb_cpuctl.gp_val = xiocb->plist.xiocb_cpuctl.gp_val; 238 iiocb.plist.iocb_cpuctl.sp_val = xiocb->plist.xiocb_cpuctl.sp_val; 239 iiocb.plist.iocb_cpuctl.a1_val = xiocb->plist.xiocb_cpuctl.a1_val; 240 break; 241 case PLMEM: 242 iiocb.plist.iocb_meminfo.mi_idx = (int) xiocb->plist.xiocb_meminfo.mi_idx; 243 iiocb.plist.iocb_meminfo.mi_type = (int) xiocb->plist.xiocb_meminfo.mi_type; 244 iiocb.plist.iocb_meminfo.mi_addr = (unsigned long long) xiocb->plist.xiocb_meminfo.mi_addr; 245 iiocb.plist.iocb_meminfo.mi_size = (unsigned long long) xiocb->plist.xiocb_meminfo.mi_size; 246 break; 247 case PLENV: 248 iiocb.plist.iocb_envbuf.enum_idx = (int) xiocb->plist.xiocb_envbuf.enum_idx; 249 iiocb.plist.iocb_envbuf.name_ptr = (unsigned char *) (uintptr_t) xiocb->plist.xiocb_envbuf.name_ptr; 250 iiocb.plist.iocb_envbuf.name_length = (int) xiocb->plist.xiocb_envbuf.name_length; 251 iiocb.plist.iocb_envbuf.val_ptr = (unsigned char *) (uintptr_t) xiocb->plist.xiocb_envbuf.val_ptr; 252 iiocb.plist.iocb_envbuf.val_length = (int) xiocb->plist.xiocb_envbuf.val_length; 253 break; 254 case PLINP: 255 iiocb.plist.iocb_inpstat.inp_status = (int) xiocb->plist.xiocb_inpstat.inp_status; 256 break; 257 case PLTIM: 258 iiocb.plist.iocb_time.ticks = (long long) xiocb->plist.xiocb_time.ticks; 259 break; 260 case PLINF: 261 break; 262 case PLEXIT: 263 iiocb.plist.iocb_exitstat.status = (long long) xiocb->plist.xiocb_exitstat.status; 264 break; 265 } 266 267 /* 268 * Do the internal function dispatch 269 */ 270 271 res = (cfe_int_t) cfe_iocb_dispatch(&iiocb); 272 273 /* 274 * Now convert the parameter list members back 275 */ 276 277 switch (disp->plisttype) { 278 case PLBUF: 279 xiocb->plist.xiocb_buffer.buf_offset = (cfe_uint_t) iiocb.plist.iocb_buffer.buf_offset; 280 xiocb->plist.xiocb_buffer.buf_ptr = (cfe_xptr_t) (uintptr_t) iiocb.plist.iocb_buffer.buf_ptr; 281 xiocb->plist.xiocb_buffer.buf_length = (cfe_uint_t) iiocb.plist.iocb_buffer.buf_length; 282 xiocb->plist.xiocb_buffer.buf_retlen = (cfe_uint_t) iiocb.plist.iocb_buffer.buf_retlen; 283 xiocb->plist.xiocb_buffer.buf_ioctlcmd = (cfe_uint_t) iiocb.plist.iocb_buffer.buf_ioctlcmd; 284 break; 285 case PLCPU: 286 xiocb->plist.xiocb_cpuctl.cpu_number = (cfe_uint_t) iiocb.plist.iocb_cpuctl.cpu_number; 287 xiocb->plist.xiocb_cpuctl.cpu_command = (cfe_uint_t) iiocb.plist.iocb_cpuctl.cpu_command; 288 xiocb->plist.xiocb_cpuctl.start_addr = iiocb.plist.iocb_cpuctl.start_addr; 289 break; 290 case PLMEM: 291 xiocb->plist.xiocb_meminfo.mi_idx = (cfe_int_t) iiocb.plist.iocb_meminfo.mi_idx; 292 xiocb->plist.xiocb_meminfo.mi_type = (cfe_int_t) iiocb.plist.iocb_meminfo.mi_type; 293 xiocb->plist.xiocb_meminfo.mi_addr = (cfe_int64_t) iiocb.plist.iocb_meminfo.mi_addr; 294 xiocb->plist.xiocb_meminfo.mi_size = (cfe_int64_t) iiocb.plist.iocb_meminfo.mi_size; 295 break; 296 case PLENV: 297 xiocb->plist.xiocb_envbuf.enum_idx = (cfe_int_t) iiocb.plist.iocb_envbuf.enum_idx; 298 xiocb->plist.xiocb_envbuf.name_ptr = (cfe_xptr_t) (uintptr_t) iiocb.plist.iocb_envbuf.name_ptr; 299 xiocb->plist.xiocb_envbuf.name_length = (cfe_int_t) iiocb.plist.iocb_envbuf.name_length; 300 xiocb->plist.xiocb_envbuf.val_ptr = (cfe_xptr_t) (uintptr_t) iiocb.plist.iocb_envbuf.val_ptr; 301 xiocb->plist.xiocb_envbuf.val_length = (cfe_int_t) iiocb.plist.iocb_envbuf.val_length; 302 break; 303 case PLINP: 304 xiocb->plist.xiocb_inpstat.inp_status = (cfe_int_t) iiocb.plist.iocb_inpstat.inp_status; 305 break; 306 case PLTIM: 307 xiocb->plist.xiocb_time.ticks = (cfe_int_t) iiocb.plist.iocb_time.ticks; 308 break; 309 case PLINF: 310 xiocb->plist.xiocb_fwinfo.fwi_version = iiocb.plist.iocb_fwinfo.fwi_version; 311 xiocb->plist.xiocb_fwinfo.fwi_totalmem = iiocb.plist.iocb_fwinfo.fwi_totalmem; 312 xiocb->plist.xiocb_fwinfo.fwi_flags = iiocb.plist.iocb_fwinfo.fwi_flags; 313 xiocb->plist.xiocb_fwinfo.fwi_boardid = iiocb.plist.iocb_fwinfo.fwi_boardid; 314 xiocb->plist.xiocb_fwinfo.fwi_bootarea_va = iiocb.plist.iocb_fwinfo.fwi_bootarea_va; 315 xiocb->plist.xiocb_fwinfo.fwi_bootarea_pa = iiocb.plist.iocb_fwinfo.fwi_bootarea_pa; 316 xiocb->plist.xiocb_fwinfo.fwi_bootarea_size = iiocb.plist.iocb_fwinfo.fwi_bootarea_size; 317 xiocb->plist.xiocb_fwinfo.fwi_reserved1 = iiocb.plist.iocb_fwinfo.fwi_reserved1; 318 xiocb->plist.xiocb_fwinfo.fwi_reserved2 = iiocb.plist.iocb_fwinfo.fwi_reserved2; 319 xiocb->plist.xiocb_fwinfo.fwi_reserved3 = iiocb.plist.iocb_fwinfo.fwi_reserved3; 320 break; 321 case PLEXIT: 322 xiocb->plist.xiocb_exitstat.status = (cfe_int_t) iiocb.plist.iocb_exitstat.status; 323 break; 324 } 325 326 /* 327 * And the fixed header 328 */ 329 330 xiocb->xiocb_status = (cfe_int_t) iiocb.iocb_status; 331 xiocb->xiocb_handle = (cfe_int_t) iiocb.iocb_handle; 332 xiocb->xiocb_flags = (cfe_uint_t) iiocb.iocb_flags; 333 334 return xiocb->xiocb_status; 335} 336