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