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)
11    *
12    *********************************************************************
13    *
14    *  Copyright 2000,2001,2002,2003
15    *  Broadcom Corporation. All rights reserved.
16    *
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.
23    *
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.
27    *
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.
33    *
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    ********************************************************************* */
48
49
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"
67
68/*  *********************************************************************
69    *  Constants
70    ********************************************************************* */
71
72#define HV	1			/* handle valid */
73
74#ifndef CFG_BOARD_ID
75#define CFG_BOARD_ID 0
76#endif
77
78/*  *********************************************************************
79    *  Globals
80    ********************************************************************* */
81
82cfe_devctx_t *cfe_handle_table[CFE_MAX_HANDLE];
83
84extern void _cfe_flushcache(int);
85
86/*  *********************************************************************
87    *  Prototypes
88    ********************************************************************* */
89
90int cfe_iocb_dispatch(cfe_iocb_t *iocb);
91void cfe_device_poll(void *);
92
93#if CFG_MULTI_CPUS
94extern int altcpu_cmd_start(uint64_t,uint64_t *);
95extern int altcpu_cmd_stop(uint64_t);
96#endif
97
98/*  *********************************************************************
99    *  Dispatch table
100    ********************************************************************* */
101
102struct cfe_cmd_dispatch_s {
103    int plistsize;
104    int flags;
105    int (*func)(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
106};
107
108
109static int cfe_cmd_fw_getinfo(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
110static int cfe_cmd_fw_restart(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
111static int cfe_cmd_fw_boot(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
112static int cfe_cmd_fw_cpuctl(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
113static int cfe_cmd_fw_gettime(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
114static int cfe_cmd_fw_memenum(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
115static int cfe_cmd_fw_flushcache(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
116
117static int cfe_cmd_dev_gethandle(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
118static int cfe_cmd_dev_enum(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
119static int cfe_cmd_dev_open(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
120static int cfe_cmd_dev_inpstat(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
121static int cfe_cmd_dev_read(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
122static int cfe_cmd_dev_write(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
123static int cfe_cmd_dev_ioctl(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
124static int cfe_cmd_dev_close(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
125static int cfe_cmd_dev_getinfo(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
126
127static int cfe_cmd_env_enum(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
128static int cfe_cmd_env_get(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
129static int cfe_cmd_env_set(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
130static int cfe_cmd_env_del(cfe_devctx_t *ctx,cfe_iocb_t *iocb);
131
132const 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 : */
165};
166
167/*  *********************************************************************
168    *  IOCB dispatch routines
169    ********************************************************************* */
170
171void cfe_device_poll(void *x)
172{
173    int idx;
174    cfe_devctx_t **ctx = cfe_handle_table;
175
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);
179	    }
180	}
181}
182
183int cfe_iocb_dispatch(cfe_iocb_t *iocb)
184{
185    const struct cfe_cmd_dispatch_s *disp;
186    int res;
187    cfe_devctx_t *ctx;
188
189    /*
190     * Check for commands codes out of range
191     */
192
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;
196	}
197
198    /*
199     * Check for command codes in range but invalid
200     */
201
202    disp = &cfe_cmd_dispatch_table[iocb->iocb_fcode];
203
204    if (disp->plistsize < 0) {
205	iocb->iocb_status = CFE_ERR_INV_COMMAND;
206	return iocb->iocb_status;
207	}
208
209    /*
210     * Check for invalid parameter list size
211     */
212
213    if (disp->plistsize != iocb->iocb_psize) {
214	iocb->iocb_status = CFE_ERR_INV_PARAM;
215	return iocb->iocb_status;
216	}
217
218    /*
219     * Determine handle
220     */
221
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;
229	    }
230	ctx = cfe_handle_table[iocb->iocb_handle];
231	}
232
233    /*
234     * Dispatch to handler routine
235     */
236
237    res = (*disp->func)(ctx,iocb);
238
239    iocb->iocb_status = res;
240    return res;
241}
242
243static int cfe_newhandle(void)
244{
245    int idx;
246
247    for (idx = 0; idx < CFE_MAX_HANDLE; idx++) {
248	if (cfe_handle_table[idx] == NULL) break;
249	}
250
251    if (idx == CFE_MAX_HANDLE) return -1;
252
253    return idx;
254}
255
256
257/*  *********************************************************************
258    *  Implementation routines for each IOCB function
259    ********************************************************************* */
260
261static int cfe_cmd_fw_getinfo(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
262{
263    iocb_fwinfo_t *info = &iocb->plist.iocb_fwinfo;
264
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
290	0;
291
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;
299
300    return CFE_OK;
301}
302
303static int cfe_cmd_fw_restart(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
304{
305    if (iocb->iocb_flags & CFE_FLG_WARMSTART) {
306	cfe_warmstart(iocb->plist.iocb_exitstat.status);
307	}
308    else {
309	cfe_restart();
310	}
311
312    /* should not get here */
313
314    return CFE_OK;
315}
316
317static int cfe_cmd_fw_boot(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
318{
319    return CFE_ERR_INV_COMMAND;		/* not implemented yet */
320}
321
322static int cfe_cmd_fw_cpuctl(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
323{
324#if CFG_MULTI_CPUS
325    int res;
326    uint64_t startargs[4];
327
328    switch (iocb->plist.iocb_cpuctl.cpu_command) {
329	case CFE_CPU_CMD_START:
330
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;
335
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;
344	}
345
346    return res;
347#else
348    return CFE_ERR_INV_COMMAND;
349#endif
350}
351
352static int cfe_cmd_fw_gettime(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
353{
354    POLL();
355
356    iocb->plist.iocb_time.ticks = cfe_ticks;
357
358    return CFE_OK;
359}
360
361static int cfe_cmd_fw_memenum(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
362{
363    int type;
364    int res;
365    uint64_t addr,size;
366
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);
372
373    iocb->plist.iocb_meminfo.mi_addr = addr;
374    iocb->plist.iocb_meminfo.mi_size = size;
375    iocb->plist.iocb_meminfo.mi_type = type;
376
377    if (res == 0) {
378	if (type == MEMTYPE_DRAM_AVAILABLE) {
379	    iocb->plist.iocb_meminfo.mi_type = CFE_MI_AVAILABLE;
380	    }
381	else {
382	    iocb->plist.iocb_meminfo.mi_type = CFE_MI_RESERVED;
383	    }
384	}
385
386    return res;
387}
388
389static int cfe_cmd_fw_flushcache(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
390{
391    _cfe_flushcache(iocb->iocb_flags);
392    return CFE_OK;
393}
394
395static int cfe_cmd_dev_enum(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
396{
397    return CFE_ERR_INV_COMMAND;
398}
399
400static int cfe_cmd_dev_gethandle(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
401{
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;
410	}
411}
412
413static int cfe_cmd_dev_open(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
414{
415    int h;
416    cfe_device_t *dev;
417    char devname[64];
418    int res;
419
420    /*
421     * Get device name
422     */
423
424    xstrncpy(devname,iocb->plist.iocb_buffer.buf_ptr,sizeof(devname));
425
426    /*
427     * Find device in device table
428     */
429
430    dev = cfe_finddev(devname);
431    if (!dev) return CFE_ERR_DEVNOTFOUND;
432
433    /*
434     * Fail if someone else already has the device open
435     */
436
437    if (dev->dev_opencount > 0) return CFE_ERR_DEVOPEN;
438
439    /*
440     * Generate a new handle
441     */
442
443    h = cfe_newhandle();
444    if (h < 0) return CFE_ERR_NOMEM;
445
446    /*
447     * Allocate a context
448     */
449
450    ctx = (cfe_devctx_t *) KMALLOC(sizeof(cfe_devctx_t),0);
451    if (ctx == NULL) return CFE_ERR_NOMEM;
452
453    /*
454     * Fill in the context
455     */
456
457    ctx->dev_dev = dev;
458    ctx->dev_softc = dev->dev_softc;
459    ctx->dev_openinfo = NULL;
460
461    /*
462     * Call driver's open func
463     */
464
465    res = dev->dev_dispatch->dev_open(ctx);
466
467    if (res != 0) {
468	KFREE(ctx);
469	return res;
470	}
471
472    /*
473     * Increment refcnt and save handle
474     */
475
476    dev->dev_opencount++;
477    cfe_handle_table[h] = ctx;
478    iocb->iocb_handle = h;
479
480    /*
481     * Success!
482     */
483
484    return CFE_OK;
485}
486
487static int cfe_cmd_dev_inpstat(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
488{
489    int status;
490
491    status = ctx->dev_dev->dev_dispatch->dev_inpstat(ctx,&(iocb->plist.iocb_inpstat));
492
493    return status;
494}
495
496static int cfe_cmd_dev_read(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
497{
498    int status;
499
500    status = ctx->dev_dev->dev_dispatch->dev_read(ctx,&(iocb->plist.iocb_buffer));
501
502    return status;
503}
504
505static int cfe_cmd_dev_write(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
506{
507    int status;
508
509    status = ctx->dev_dev->dev_dispatch->dev_write(ctx,&(iocb->plist.iocb_buffer));
510
511    return status;
512}
513
514static int cfe_cmd_dev_ioctl(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
515{
516    int status;
517
518    status = ctx->dev_dev->dev_dispatch->dev_ioctl(ctx,&(iocb->plist.iocb_buffer));
519
520    return status;
521}
522
523static int cfe_cmd_dev_close(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
524{
525    /*
526     * Call device close function
527     */
528
529    ctx->dev_dev->dev_dispatch->dev_close(ctx);
530
531    /*
532     * Decrement refcnt
533     */
534
535    ctx->dev_dev->dev_opencount--;
536
537    /*
538     * Wipe out handle
539     */
540
541    cfe_handle_table[iocb->iocb_handle] = NULL;
542
543    /*
544     * Release device context
545     */
546
547    KFREE(ctx);
548
549    return CFE_OK;
550}
551
552static int cfe_cmd_dev_getinfo(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
553{
554    cfe_device_t *dev;
555    char devname[64];
556    char *x;
557
558    /*
559     * Get device name
560     */
561
562    xstrncpy(devname,iocb->plist.iocb_buffer.buf_ptr,sizeof(devname));
563
564    /*
565     * Find device in device table
566     */
567
568    if ((x = strchr(devname,':'))) *x = '\0';
569    dev = cfe_finddev(devname);
570    if (!dev) return CFE_ERR_DEVNOTFOUND;
571
572    /*
573     * Return device class
574     */
575
576    iocb->plist.iocb_buffer.buf_devflags = dev->dev_class;
577
578    return CFE_OK;
579}
580
581static int cfe_cmd_env_enum(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
582{
583    int vallen,namelen,res;
584
585    namelen = iocb->plist.iocb_envbuf.name_length;
586    vallen  = iocb->plist.iocb_envbuf.val_length;
587
588    res = env_enum(iocb->plist.iocb_envbuf.enum_idx,
589		   iocb->plist.iocb_envbuf.name_ptr,
590		   &namelen,
591		   iocb->plist.iocb_envbuf.val_ptr,
592		   &vallen);
593
594    if (res < 0) return CFE_ERR_ENVNOTFOUND;
595
596    return CFE_OK;
597}
598
599
600static int cfe_cmd_env_get(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
601{
602    char *env;
603
604    env = env_getenv(iocb->plist.iocb_envbuf.name_ptr);
605
606    if (env == NULL) return CFE_ERR_ENVNOTFOUND;
607
608    xstrncpy(iocb->plist.iocb_envbuf.val_ptr,
609	     env,
610	     iocb->plist.iocb_envbuf.val_length);
611
612    return CFE_OK;
613}
614
615static int cfe_cmd_env_set(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
616{
617    int res;
618    int flg;
619
620
621    flg = (iocb->iocb_flags & CFE_FLG_ENV_PERMANENT) ?
622	ENV_FLG_NORMAL : ENV_FLG_BUILTIN;
623
624    res = env_setenv(iocb->plist.iocb_envbuf.name_ptr,
625		     iocb->plist.iocb_envbuf.val_ptr,
626		     flg);
627
628    if (res == 0) {
629	if (iocb->iocb_flags & CFE_FLG_ENV_PERMANENT) res = env_save();
630	}
631
632    if (res < 0) return res;
633
634    return CFE_OK;
635}
636
637static int cfe_cmd_env_del(cfe_devctx_t *ctx,cfe_iocb_t *iocb)
638{
639    int res;
640
641    res = env_delenv(iocb->plist.iocb_envbuf.name_ptr);
642
643    return res;
644}
645
646
647
648