Home | History | Annotate | Line # | Download | only in cfe
      1 /* $NetBSD: cfe_api.c,v 1.5 2005/12/11 12:18:07 christos Exp $ */
      2 /* from: SiByte Id: cfe_api.c,v 1.16 2002/07/09 23:29:11 cgd Exp $ */
      3 
      4 /*
      5  * Copyright 2000, 2001, 2002
      6  * Broadcom Corporation. All rights reserved.
      7  *
      8  * This software is furnished under license and may be used and copied only
      9  * in accordance with the following terms and conditions.  Subject to these
     10  * conditions, you may download, copy, install, use, modify and distribute
     11  * modified or unmodified copies of this software in source and/or binary
     12  * form. No title or ownership is transferred hereby.
     13  *
     14  * 1) Any source code used, modified or distributed must reproduce and
     15  *    retain this copyright notice and list of conditions as they appear in
     16  *    the source file.
     17  *
     18  * 2) No right is granted to use any trade name, trademark, or logo of
     19  *    Broadcom Corporation.  The "Broadcom Corporation" name may not be
     20  *    used to endorse or promote products derived from this software
     21  *    without the prior written permission of Broadcom Corporation.
     22  *
     23  * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR IMPLIED
     24  *    WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF
     25  *    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
     26  *    NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM BE LIABLE
     27  *    FOR ANY DAMAGES WHATSOEVER, AND IN PARTICULAR, BROADCOM SHALL NOT BE
     28  *    LIABLE FOR DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     29  *    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     30  *    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     31  *    BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     32  *    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     33  *    OR OTHERWISE), EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     34  */
     35 
     36 /*  *********************************************************************
     37     *
     38     *  Broadcom Common Firmware Environment (CFE)
     39     *
     40     *  Device Function stubs			File: cfe_api.c
     41     *
     42     *  This module contains device function stubs (small routines to
     43     *  call the standard "iocb" interface entry point to CFE).
     44     *  There should be one routine here per iocb function call.
     45     *
     46     *  Authors:  Mitch Lichtenberg, Chris Demetriou
     47     *
     48     ********************************************************************* */
     49 
     50 #include <sys/cdefs.h>
     51 __KERNEL_RCSID(0, "$NetBSD: cfe_api.c,v 1.5 2005/12/11 12:18:07 christos Exp $");
     52 
     53 #include "cfe_api.h"
     54 #include "cfe_api_int.h"
     55 
     56 /* Cast from a native pointer to a cfe_xptr_t and back.  */
     57 #define XPTR_FROM_NATIVE(n)	((cfe_xptr_t) (intptr_t) (n))
     58 #define NATIVE_FROM_XPTR(x)	((void *) (intptr_t) (x))
     59 
     60 #ifdef CFE_API_IMPL_NAMESPACE
     61 #define cfe_iocb_dispatch(a)		__cfe_iocb_dispatch(a)
     62 #endif
     63 int cfe_iocb_dispatch(cfe_xiocb_t *xiocb);
     64 
     65 #if defined(CFE_API_common) || defined(CFE_API_ALL)
     66 /*
     67  * Declare the dispatch function with args of "intptr_t".
     68  * This makes sure whatever model we're compiling in
     69  * puts the pointers in a single register.  For example,
     70  * combining -mlong64 and -mips1 or -mips2 would lead to
     71  * trouble, since the handle and IOCB pointer will be
     72  * passed in two registers each, and CFE expects one.
     73  */
     74 
     75 static int (*cfe_dispfunc)(intptr_t handle, intptr_t xiocb) = 0;
     76 static cfe_xuint_t cfe_handle = 0;
     77 
     78 int
     79 cfe_init(cfe_xuint_t handle, cfe_xuint_t ept)
     80 {
     81     cfe_dispfunc = NATIVE_FROM_XPTR(ept);
     82     cfe_handle = handle;
     83     return 0;
     84 }
     85 
     86 int
     87 cfe_iocb_dispatch(cfe_xiocb_t *xiocb)
     88 {
     89     if (!cfe_dispfunc) return -1;
     90     return (*cfe_dispfunc)((intptr_t)cfe_handle, (intptr_t)xiocb);
     91 }
     92 #endif /* CFE_API_common || CFE_API_ALL */
     93 
     94 #if defined(CFE_API_close) || defined(CFE_API_ALL)
     95 int
     96 cfe_close(int handle)
     97 {
     98     cfe_xiocb_t xiocb;
     99 
    100     xiocb.xiocb_fcode = CFE_CMD_DEV_CLOSE;
    101     xiocb.xiocb_status = 0;
    102     xiocb.xiocb_handle = handle;
    103     xiocb.xiocb_flags = 0;
    104     xiocb.xiocb_psize = 0;
    105 
    106     cfe_iocb_dispatch(&xiocb);
    107 
    108     return xiocb.xiocb_status;
    109 
    110 }
    111 #endif /* CFE_API_close || CFE_API_ALL */
    112 
    113 #if defined(CFE_API_cpu_start) || defined(CFE_API_ALL)
    114 int
    115 cfe_cpu_start(int cpu, void (*fn)(void), long sp, long gp, long a1)
    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_START;
    126     xiocb.plist.xiocb_cpuctl.gp_val = gp;
    127     xiocb.plist.xiocb_cpuctl.sp_val = sp;
    128     xiocb.plist.xiocb_cpuctl.a1_val = a1;
    129     xiocb.plist.xiocb_cpuctl.start_addr = (long)fn;
    130 
    131     cfe_iocb_dispatch(&xiocb);
    132 
    133     return xiocb.xiocb_status;
    134 }
    135 #endif /* CFE_API_cpu_start || CFE_API_ALL */
    136 
    137 #if defined(CFE_API_cpu_stop) || defined(CFE_API_ALL)
    138 int
    139 cfe_cpu_stop(int cpu)
    140 {
    141     cfe_xiocb_t xiocb;
    142 
    143     xiocb.xiocb_fcode = CFE_CMD_FW_CPUCTL;
    144     xiocb.xiocb_status = 0;
    145     xiocb.xiocb_handle = 0;
    146     xiocb.xiocb_flags  = 0;
    147     xiocb.xiocb_psize = sizeof(xiocb_cpuctl_t);
    148     xiocb.plist.xiocb_cpuctl.cpu_number = cpu;
    149     xiocb.plist.xiocb_cpuctl.cpu_command = CFE_CPU_CMD_STOP;
    150 
    151     cfe_iocb_dispatch(&xiocb);
    152 
    153     return xiocb.xiocb_status;
    154 }
    155 #endif /* CFE_API_cpu_stop || CFE_API_ALL */
    156 
    157 #if defined(CFE_API_enumenv) || defined(CFE_API_ALL)
    158 int
    159 cfe_enumenv(int idx, char *name, int namelen, char *val, int vallen)
    160 {
    161     cfe_xiocb_t xiocb;
    162 
    163     xiocb.xiocb_fcode = CFE_CMD_ENV_SET;
    164     xiocb.xiocb_status = 0;
    165     xiocb.xiocb_handle = 0;
    166     xiocb.xiocb_flags = 0;
    167     xiocb.xiocb_psize = sizeof(xiocb_envbuf_t);
    168     xiocb.plist.xiocb_envbuf.enum_idx = idx;
    169     xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
    170     xiocb.plist.xiocb_envbuf.name_length = namelen;
    171     xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(val);
    172     xiocb.plist.xiocb_envbuf.val_length = vallen;
    173 
    174     cfe_iocb_dispatch(&xiocb);
    175 
    176     return xiocb.xiocb_status;
    177 }
    178 #endif /* CFE_API_enumenv || CFE_API_ALL */
    179 
    180 #if defined(CFE_API_enummem) || defined(CFE_API_ALL)
    181 int
    182 cfe_enummem(int idx, int flags, cfe_xuint_t *start, cfe_xuint_t *length,
    183 	    cfe_xuint_t *type)
    184 {
    185     cfe_xiocb_t xiocb;
    186 
    187     xiocb.xiocb_fcode = CFE_CMD_FW_MEMENUM;
    188     xiocb.xiocb_status = 0;
    189     xiocb.xiocb_handle = 0;
    190     xiocb.xiocb_flags = flags;
    191     xiocb.xiocb_psize = sizeof(xiocb_meminfo_t);
    192     xiocb.plist.xiocb_meminfo.mi_idx = idx;
    193 
    194     cfe_iocb_dispatch(&xiocb);
    195 
    196     if (xiocb.xiocb_status < 0)
    197 	return xiocb.xiocb_status;
    198 
    199     *start = xiocb.plist.xiocb_meminfo.mi_addr;
    200     *length = xiocb.plist.xiocb_meminfo.mi_size;
    201     *type = xiocb.plist.xiocb_meminfo.mi_type;
    202 
    203     return 0;
    204 }
    205 #endif /* CFE_API_enummem || CFE_API_ALL */
    206 
    207 #if defined(CFE_API_exit) || defined(CFE_API_ALL)
    208 int
    209 cfe_exit(int warm, int status)
    210 {
    211     cfe_xiocb_t xiocb;
    212 
    213     xiocb.xiocb_fcode = CFE_CMD_FW_RESTART;
    214     xiocb.xiocb_status = 0;
    215     xiocb.xiocb_handle = 0;
    216     xiocb.xiocb_flags = warm ? CFE_FLG_WARMSTART : 0;
    217     xiocb.xiocb_psize = sizeof(xiocb_exitstat_t);
    218     xiocb.plist.xiocb_exitstat.status = status;
    219 
    220     cfe_iocb_dispatch(&xiocb);
    221 
    222     return xiocb.xiocb_status;
    223 }
    224 #endif /* CFE_API_exit || CFE_API_ALL */
    225 
    226 #if defined(CFE_API_flushcache) || defined(CFE_API_ALL)
    227 int
    228 cfe_flushcache(int flg)
    229 {
    230     cfe_xiocb_t xiocb;
    231 
    232     xiocb.xiocb_fcode = CFE_CMD_FW_FLUSHCACHE;
    233     xiocb.xiocb_status = 0;
    234     xiocb.xiocb_handle = 0;
    235     xiocb.xiocb_flags = flg;
    236     xiocb.xiocb_psize = 0;
    237 
    238     cfe_iocb_dispatch(&xiocb);
    239 
    240     return xiocb.xiocb_status;
    241 }
    242 #endif /* CFE_API_flushcache || CFE_API_ALL */
    243 
    244 #if defined(CFE_API_getdevinfo) || defined(CFE_API_ALL)
    245 int
    246 cfe_getdevinfo(char *name)
    247 {
    248     cfe_xiocb_t xiocb;
    249 
    250     xiocb.xiocb_fcode = CFE_CMD_DEV_GETINFO;
    251     xiocb.xiocb_status = 0;
    252     xiocb.xiocb_handle = 0;
    253     xiocb.xiocb_flags = 0;
    254     xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
    255     xiocb.plist.xiocb_buffer.buf_offset = 0;
    256     xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name);
    257     xiocb.plist.xiocb_buffer.buf_length = cfe_strlen(name);
    258 
    259     cfe_iocb_dispatch(&xiocb);
    260 
    261     if (xiocb.xiocb_status < 0)
    262 	return xiocb.xiocb_status;
    263     return xiocb.plist.xiocb_buffer.buf_devflags;
    264 }
    265 #endif /* CFE_API_getdevinfo || CFE_API_ALL */
    266 
    267 #if defined(CFE_API_getenv) || defined(CFE_API_ALL)
    268 int
    269 cfe_getenv(char *name, char *dest, int destlen)
    270 {
    271     cfe_xiocb_t xiocb;
    272 
    273     *dest = 0;
    274 
    275     xiocb.xiocb_fcode = CFE_CMD_ENV_GET;
    276     xiocb.xiocb_status = 0;
    277     xiocb.xiocb_handle = 0;
    278     xiocb.xiocb_flags = 0;
    279     xiocb.xiocb_psize = sizeof(xiocb_envbuf_t);
    280     xiocb.plist.xiocb_envbuf.enum_idx = 0;
    281     xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
    282     xiocb.plist.xiocb_envbuf.name_length = cfe_strlen(name);
    283     xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(dest);
    284     xiocb.plist.xiocb_envbuf.val_length = destlen;
    285 
    286     cfe_iocb_dispatch(&xiocb);
    287 
    288     return xiocb.xiocb_status;
    289 }
    290 #endif /* CFE_API_getenv || CFE_API_ALL */
    291 
    292 #if defined(CFE_API_getfwinfo) || defined(CFE_API_ALL)
    293 int
    294 cfe_getfwinfo(cfe_fwinfo_t *info)
    295 {
    296     cfe_xiocb_t xiocb;
    297 
    298     xiocb.xiocb_fcode = CFE_CMD_FW_GETINFO;
    299     xiocb.xiocb_status = 0;
    300     xiocb.xiocb_handle = 0;
    301     xiocb.xiocb_flags = 0;
    302     xiocb.xiocb_psize = sizeof(xiocb_fwinfo_t);
    303 
    304     cfe_iocb_dispatch(&xiocb);
    305 
    306     if (xiocb.xiocb_status < 0)
    307 	return xiocb.xiocb_status;
    308 
    309     info->fwi_version = xiocb.plist.xiocb_fwinfo.fwi_version;
    310     info->fwi_totalmem = xiocb.plist.xiocb_fwinfo.fwi_totalmem;
    311     info->fwi_flags = xiocb.plist.xiocb_fwinfo.fwi_flags;
    312     info->fwi_boardid = xiocb.plist.xiocb_fwinfo.fwi_boardid;
    313     info->fwi_bootarea_va = xiocb.plist.xiocb_fwinfo.fwi_bootarea_va;
    314     info->fwi_bootarea_pa = xiocb.plist.xiocb_fwinfo.fwi_bootarea_pa;
    315     info->fwi_bootarea_size = xiocb.plist.xiocb_fwinfo.fwi_bootarea_size;
    316 #if 0
    317     info->fwi_reserved1 = xiocb.plist.xiocb_fwinfo.fwi_reserved1;
    318     info->fwi_reserved2 = xiocb.plist.xiocb_fwinfo.fwi_reserved2;
    319     info->fwi_reserved3 = xiocb.plist.xiocb_fwinfo.fwi_reserved3;
    320 #endif
    321 
    322     return 0;
    323 }
    324 #endif /* CFE_API_getfwinfo || CFE_API_ALL */
    325 
    326 #if defined(CFE_API_getstdhandle) || defined(CFE_API_ALL)
    327 int
    328 cfe_getstdhandle(int flg)
    329 {
    330     cfe_xiocb_t xiocb;
    331 
    332     xiocb.xiocb_fcode = CFE_CMD_DEV_GETHANDLE;
    333     xiocb.xiocb_status = 0;
    334     xiocb.xiocb_handle = 0;
    335     xiocb.xiocb_flags = flg;
    336     xiocb.xiocb_psize = 0;
    337 
    338     cfe_iocb_dispatch(&xiocb);
    339 
    340     if (xiocb.xiocb_status < 0)
    341 	return xiocb.xiocb_status;
    342     return xiocb.xiocb_handle;
    343 
    344 }
    345 #endif /* CFE_API_getstdhandle || CFE_API_ALL */
    346 
    347 #if defined(CFE_API_getticks) || defined(CFE_API_ALL)
    348 int64_t
    349 #ifdef CFE_API_IMPL_NAMESPACE
    350 __cfe_getticks(void)
    351 #else
    352 cfe_getticks(void)
    353 #endif
    354 {
    355     cfe_xiocb_t xiocb;
    356 
    357     xiocb.xiocb_fcode = CFE_CMD_FW_GETTIME;
    358     xiocb.xiocb_status = 0;
    359     xiocb.xiocb_handle = 0;
    360     xiocb.xiocb_flags = 0;
    361     xiocb.xiocb_psize = sizeof(xiocb_time_t);
    362     xiocb.plist.xiocb_time.ticks = 0;
    363 
    364     cfe_iocb_dispatch(&xiocb);
    365 
    366     return xiocb.plist.xiocb_time.ticks;
    367 
    368 }
    369 #endif /* CFE_API_getticks || CFE_API_ALL */
    370 
    371 #if defined(CFE_API_inpstat) || defined(CFE_API_ALL)
    372 int
    373 cfe_inpstat(int handle)
    374 {
    375     cfe_xiocb_t xiocb;
    376 
    377     xiocb.xiocb_fcode = CFE_CMD_DEV_INPSTAT;
    378     xiocb.xiocb_status = 0;
    379     xiocb.xiocb_handle = handle;
    380     xiocb.xiocb_flags = 0;
    381     xiocb.xiocb_psize = sizeof(xiocb_inpstat_t);
    382     xiocb.plist.xiocb_inpstat.inp_status = 0;
    383 
    384     cfe_iocb_dispatch(&xiocb);
    385 
    386     if (xiocb.xiocb_status < 0)
    387 	return xiocb.xiocb_status;
    388     return xiocb.plist.xiocb_inpstat.inp_status;
    389 
    390 }
    391 #endif /* CFE_API_inpstat || CFE_API_ALL */
    392 
    393 #if defined(CFE_API_ioctl) || defined(CFE_API_ALL)
    394 int
    395 cfe_ioctl(int handle, unsigned int ioctlnum, unsigned char *buffer, int length,
    396 	  int *retlen, cfe_xuint_t offset)
    397 {
    398     cfe_xiocb_t xiocb;
    399 
    400     xiocb.xiocb_fcode = CFE_CMD_DEV_IOCTL;
    401     xiocb.xiocb_status = 0;
    402     xiocb.xiocb_handle = handle;
    403     xiocb.xiocb_flags = 0;
    404     xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
    405     xiocb.plist.xiocb_buffer.buf_offset = offset;
    406     xiocb.plist.xiocb_buffer.buf_ioctlcmd = ioctlnum;
    407     xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
    408     xiocb.plist.xiocb_buffer.buf_length = length;
    409 
    410     cfe_iocb_dispatch(&xiocb);
    411 
    412     if (retlen)
    413 	*retlen = xiocb.plist.xiocb_buffer.buf_retlen;
    414     return xiocb.xiocb_status;
    415 }
    416 #endif /* CFE_API_ioctl || CFE_API_ALL */
    417 
    418 #if defined(CFE_API_open) || defined(CFE_API_ALL)
    419 int
    420 cfe_open(char *name)
    421 {
    422     cfe_xiocb_t xiocb;
    423 
    424     xiocb.xiocb_fcode = CFE_CMD_DEV_OPEN;
    425     xiocb.xiocb_status = 0;
    426     xiocb.xiocb_handle = 0;
    427     xiocb.xiocb_flags = 0;
    428     xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
    429     xiocb.plist.xiocb_buffer.buf_offset = 0;
    430     xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name);
    431     xiocb.plist.xiocb_buffer.buf_length = cfe_strlen(name);
    432 
    433     cfe_iocb_dispatch(&xiocb);
    434 
    435     if (xiocb.xiocb_status < 0)
    436 	return xiocb.xiocb_status;
    437     return xiocb.xiocb_handle;
    438 }
    439 #endif /* CFE_API_open || CFE_API_ALL */
    440 
    441 #if defined(CFE_API_read) || defined(CFE_API_ALL)
    442 int
    443 cfe_read(int handle, unsigned char *buffer, int length)
    444 {
    445     return cfe_readblk(handle, 0, buffer, length);
    446 }
    447 #endif /* CFE_API_read || CFE_API_ALL */
    448 
    449 #if defined(CFE_API_readblk) || defined(CFE_API_ALL)
    450 int
    451 cfe_readblk(int handle, cfe_xint_t offset, unsigned char *buffer, int length)
    452 {
    453     cfe_xiocb_t xiocb;
    454 
    455     xiocb.xiocb_fcode = CFE_CMD_DEV_READ;
    456     xiocb.xiocb_status = 0;
    457     xiocb.xiocb_handle = handle;
    458     xiocb.xiocb_flags = 0;
    459     xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
    460     xiocb.plist.xiocb_buffer.buf_offset = offset;
    461     xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
    462     xiocb.plist.xiocb_buffer.buf_length = length;
    463 
    464     cfe_iocb_dispatch(&xiocb);
    465 
    466     if (xiocb.xiocb_status < 0)
    467 	return xiocb.xiocb_status;
    468     return xiocb.plist.xiocb_buffer.buf_retlen;
    469 }
    470 #endif /* CFE_API_readblk || CFE_API_ALL */
    471 
    472 #if defined(CFE_API_setenv) || defined(CFE_API_ALL)
    473 int
    474 cfe_setenv(char *name, char *val)
    475 {
    476     cfe_xiocb_t xiocb;
    477 
    478     xiocb.xiocb_fcode = CFE_CMD_ENV_SET;
    479     xiocb.xiocb_status = 0;
    480     xiocb.xiocb_handle = 0;
    481     xiocb.xiocb_flags = 0;
    482     xiocb.xiocb_psize = sizeof(xiocb_envbuf_t);
    483     xiocb.plist.xiocb_envbuf.enum_idx = 0;
    484     xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
    485     xiocb.plist.xiocb_envbuf.name_length = cfe_strlen(name);
    486     xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(val);
    487     xiocb.plist.xiocb_envbuf.val_length = cfe_strlen(val);
    488 
    489     cfe_iocb_dispatch(&xiocb);
    490 
    491     return xiocb.xiocb_status;
    492 }
    493 #endif /* CFE_API_setenv || CFE_API_ALL */
    494 
    495 #if (defined(CFE_API_strlen) || defined(CFE_API_ALL)) \
    496     && !defined(CFE_API_STRLEN_CUSTOM)
    497 int
    498 cfe_strlen(char *name)
    499 {
    500     int count = 0;
    501 
    502     while (*name++)
    503 	count++;
    504 
    505     return count;
    506 }
    507 #endif /* CFE_API_strlen || CFE_API_ALL */
    508 
    509 #if defined(CFE_API_write) || defined(CFE_API_ALL)
    510 int
    511 cfe_write(int handle, unsigned char *buffer, int length)
    512 {
    513     return cfe_writeblk(handle, 0, buffer, length);
    514 }
    515 #endif /* CFE_API_write || CFE_API_ALL */
    516 
    517 #if defined(CFE_API_writeblk) || defined(CFE_API_ALL)
    518 int
    519 cfe_writeblk(int handle, cfe_xint_t offset, unsigned char *buffer, int length)
    520 {
    521     cfe_xiocb_t xiocb;
    522 
    523     xiocb.xiocb_fcode = CFE_CMD_DEV_WRITE;
    524     xiocb.xiocb_status = 0;
    525     xiocb.xiocb_handle = handle;
    526     xiocb.xiocb_flags = 0;
    527     xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
    528     xiocb.plist.xiocb_buffer.buf_offset = offset;
    529     xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
    530     xiocb.plist.xiocb_buffer.buf_length = length;
    531 
    532     cfe_iocb_dispatch(&xiocb);
    533 
    534     if (xiocb.xiocb_status < 0)
    535 	return xiocb.xiocb_status;
    536     return xiocb.plist.xiocb_buffer.buf_retlen;
    537 }
    538 #endif /* CFE_API_writeblk || CFE_API_ALL */
    539