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 <asm/fw/cfe/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 43 int 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 55 static int (*cfe_dispfunc) (intptr_t handle, intptr_t xiocb) = 0; 56 static cfe_xuint_t cfe_handle = 0; 57 58 int 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 65 int 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) 74 int 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) 92 int 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) 115 int 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) 134 int 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) 156 int 157 cfe_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) 183 int 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) 201 int 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) 218 int 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) 240 int 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) 264 int 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 #if 0 288 info->fwi_reserved1 = xiocb.plist.xiocb_fwinfo.fwi_reserved1; 289 info->fwi_reserved2 = xiocb.plist.xiocb_fwinfo.fwi_reserved2; 290 info->fwi_reserved3 = xiocb.plist.xiocb_fwinfo.fwi_reserved3; 291 #endif 292 293 return 0; 294 } 295 #endif /* CFE_API_getfwinfo || CFE_API_ALL */ 296 297 #if defined(CFE_API_getstdhandle) || defined(CFE_API_ALL) 298 int cfe_getstdhandle(int flg) 299 { 300 cfe_xiocb_t xiocb; 301 302 xiocb.xiocb_fcode = CFE_CMD_DEV_GETHANDLE; 303 xiocb.xiocb_status = 0; 304 xiocb.xiocb_handle = 0; 305 xiocb.xiocb_flags = flg; 306 xiocb.xiocb_psize = 0; 307 308 cfe_iocb_dispatch(&xiocb); 309 310 if (xiocb.xiocb_status < 0) 311 return xiocb.xiocb_status; 312 return xiocb.xiocb_handle; 313 } 314 #endif /* CFE_API_getstdhandle || CFE_API_ALL */ 315 316 #if defined(CFE_API_getticks) || defined(CFE_API_ALL) 317 int64_t 318 #ifdef CFE_API_IMPL_NAMESPACE 319 __cfe_getticks(void) 320 #else 321 cfe_getticks(void) 322 #endif 323 { 324 cfe_xiocb_t xiocb; 325 326 xiocb.xiocb_fcode = CFE_CMD_FW_GETTIME; 327 xiocb.xiocb_status = 0; 328 xiocb.xiocb_handle = 0; 329 xiocb.xiocb_flags = 0; 330 xiocb.xiocb_psize = sizeof(xiocb_time_t); 331 xiocb.plist.xiocb_time.ticks = 0; 332 333 cfe_iocb_dispatch(&xiocb); 334 335 return xiocb.plist.xiocb_time.ticks; 336 337 } 338 #endif /* CFE_API_getticks || CFE_API_ALL */ 339 340 #if defined(CFE_API_inpstat) || defined(CFE_API_ALL) 341 int cfe_inpstat(int handle) 342 { 343 cfe_xiocb_t xiocb; 344 345 xiocb.xiocb_fcode = CFE_CMD_DEV_INPSTAT; 346 xiocb.xiocb_status = 0; 347 xiocb.xiocb_handle = handle; 348 xiocb.xiocb_flags = 0; 349 xiocb.xiocb_psize = sizeof(xiocb_inpstat_t); 350 xiocb.plist.xiocb_inpstat.inp_status = 0; 351 352 cfe_iocb_dispatch(&xiocb); 353 354 if (xiocb.xiocb_status < 0) 355 return xiocb.xiocb_status; 356 return xiocb.plist.xiocb_inpstat.inp_status; 357 } 358 #endif /* CFE_API_inpstat || CFE_API_ALL */ 359 360 #if defined(CFE_API_ioctl) || defined(CFE_API_ALL) 361 int 362 cfe_ioctl(int handle, unsigned int ioctlnum, unsigned char *buffer, 363 int length, int *retlen, cfe_xuint_t offset) 364 { 365 cfe_xiocb_t xiocb; 366 367 xiocb.xiocb_fcode = CFE_CMD_DEV_IOCTL; 368 xiocb.xiocb_status = 0; 369 xiocb.xiocb_handle = handle; 370 xiocb.xiocb_flags = 0; 371 xiocb.xiocb_psize = sizeof(xiocb_buffer_t); 372 xiocb.plist.xiocb_buffer.buf_offset = offset; 373 xiocb.plist.xiocb_buffer.buf_ioctlcmd = ioctlnum; 374 xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer); 375 xiocb.plist.xiocb_buffer.buf_length = length; 376 377 cfe_iocb_dispatch(&xiocb); 378 379 if (retlen) 380 *retlen = xiocb.plist.xiocb_buffer.buf_retlen; 381 return xiocb.xiocb_status; 382 } 383 #endif /* CFE_API_ioctl || CFE_API_ALL */ 384 385 #if defined(CFE_API_open) || defined(CFE_API_ALL) 386 int cfe_open(char *name) 387 { 388 cfe_xiocb_t xiocb; 389 390 xiocb.xiocb_fcode = CFE_CMD_DEV_OPEN; 391 xiocb.xiocb_status = 0; 392 xiocb.xiocb_handle = 0; 393 xiocb.xiocb_flags = 0; 394 xiocb.xiocb_psize = sizeof(xiocb_buffer_t); 395 xiocb.plist.xiocb_buffer.buf_offset = 0; 396 xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name); 397 xiocb.plist.xiocb_buffer.buf_length = cfe_strlen(name); 398 399 cfe_iocb_dispatch(&xiocb); 400 401 if (xiocb.xiocb_status < 0) 402 return xiocb.xiocb_status; 403 return xiocb.xiocb_handle; 404 } 405 #endif /* CFE_API_open || CFE_API_ALL */ 406 407 #if defined(CFE_API_read) || defined(CFE_API_ALL) 408 int cfe_read(int handle, unsigned char *buffer, int length) 409 { 410 return cfe_readblk(handle, 0, buffer, length); 411 } 412 #endif /* CFE_API_read || CFE_API_ALL */ 413 414 #if defined(CFE_API_readblk) || defined(CFE_API_ALL) 415 int 416 cfe_readblk(int handle, cfe_xint_t offset, unsigned char *buffer, 417 int length) 418 { 419 cfe_xiocb_t xiocb; 420 421 xiocb.xiocb_fcode = CFE_CMD_DEV_READ; 422 xiocb.xiocb_status = 0; 423 xiocb.xiocb_handle = handle; 424 xiocb.xiocb_flags = 0; 425 xiocb.xiocb_psize = sizeof(xiocb_buffer_t); 426 xiocb.plist.xiocb_buffer.buf_offset = offset; 427 xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer); 428 xiocb.plist.xiocb_buffer.buf_length = length; 429 430 cfe_iocb_dispatch(&xiocb); 431 432 if (xiocb.xiocb_status < 0) 433 return xiocb.xiocb_status; 434 return xiocb.plist.xiocb_buffer.buf_retlen; 435 } 436 #endif /* CFE_API_readblk || CFE_API_ALL */ 437 438 #if defined(CFE_API_setenv) || defined(CFE_API_ALL) 439 int cfe_setenv(char *name, char *val) 440 { 441 cfe_xiocb_t xiocb; 442 443 xiocb.xiocb_fcode = CFE_CMD_ENV_SET; 444 xiocb.xiocb_status = 0; 445 xiocb.xiocb_handle = 0; 446 xiocb.xiocb_flags = 0; 447 xiocb.xiocb_psize = sizeof(xiocb_envbuf_t); 448 xiocb.plist.xiocb_envbuf.enum_idx = 0; 449 xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name); 450 xiocb.plist.xiocb_envbuf.name_length = cfe_strlen(name); 451 xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(val); 452 xiocb.plist.xiocb_envbuf.val_length = cfe_strlen(val); 453 454 cfe_iocb_dispatch(&xiocb); 455 456 return xiocb.xiocb_status; 457 } 458 #endif /* CFE_API_setenv || CFE_API_ALL */ 459 460 #if (defined(CFE_API_strlen) || defined(CFE_API_ALL)) \ 461 && !defined(CFE_API_STRLEN_CUSTOM) 462 int cfe_strlen(char *name) 463 { 464 int count = 0; 465 466 while (*name++) 467 count++; 468 469 return count; 470 } 471 #endif /* CFE_API_strlen || CFE_API_ALL */ 472 473 #if defined(CFE_API_write) || defined(CFE_API_ALL) 474 int cfe_write(int handle, unsigned char *buffer, int length) 475 { 476 return cfe_writeblk(handle, 0, buffer, length); 477 } 478 #endif /* CFE_API_write || CFE_API_ALL */ 479 480 #if defined(CFE_API_writeblk) || defined(CFE_API_ALL) 481 int 482 cfe_writeblk(int handle, cfe_xint_t offset, unsigned char *buffer, 483 int length) 484 { 485 cfe_xiocb_t xiocb; 486 487 xiocb.xiocb_fcode = CFE_CMD_DEV_WRITE; 488 xiocb.xiocb_status = 0; 489 xiocb.xiocb_handle = handle; 490 xiocb.xiocb_flags = 0; 491 xiocb.xiocb_psize = sizeof(xiocb_buffer_t); 492 xiocb.plist.xiocb_buffer.buf_offset = offset; 493 xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer); 494 xiocb.plist.xiocb_buffer.buf_length = length; 495 496 cfe_iocb_dispatch(&xiocb); 497 498 if (xiocb.xiocb_status < 0) 499 return xiocb.xiocb_status; 500 return xiocb.plist.xiocb_buffer.buf_retlen; 501 } 502 #endif /* CFE_API_writeblk || CFE_API_ALL */ 503