1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <stddef.h> 30 #include <locale.h> 31 #include <ctype.h> 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <string.h> 35 #include <fcntl.h> 36 #include <unistd.h> 37 #include <errno.h> 38 #include <locale.h> 39 #include <langinfo.h> 40 #include <time.h> 41 #include <stdarg.h> 42 #include <sys/types.h> 43 #include <sys/ioctl.h> 44 #include <sys/dditypes.h> 45 #include <sys/modctl.h> 46 #include <sys/obpdefs.h> 47 #include <sys/fhc.h> 48 #include <sys/sysctrl.h> 49 #include <sys/openpromio.h> 50 #ifdef SIM 51 #include <sys/stat.h> 52 #endif 53 #define CFGA_PLUGIN_LIB 54 #include <config_admin.h> 55 56 #ifdef DEBUG 57 #define DBG printf 58 #define DBG1 printf 59 #define DBG3 printf 60 #define DBG4 printf 61 #else 62 #define DBG(a, b) 63 #define DBG1(a) 64 #define DBG3(a, b, c) 65 #define DBG4(a, b, c, d) 66 #endif 67 68 #define BD_CPU 1 69 #define BD_MEM 2 70 #define BD_IO_2SBUS 3 71 #define BD_IO_SBUS_FFB 4 72 #define BD_IO_PCI 5 73 #define BD_DISK 6 74 #define BD_IO_2SBUS_SOCPLUS 7 75 #define BD_IO_SBUS_FFB_SOCPLUS 8 76 #define BD_UNKNOWN 9 77 #define CMD_GETSTAT 10 78 #define CMD_LIST 11 79 #define CMD_CONNECT 12 80 #define CMD_DISCONNECT 13 81 #define CMD_CONFIGURE 14 82 #define CMD_UNCONFIGURE 15 83 #define CMD_QUIESCE 16 84 #define CMD_INSERT 17 85 #define CMD_REMOVE 18 86 #define CMD_SET_COND 19 87 #define OPT_ENABLE 20 88 #define OPT_DISABLE 21 89 #define ERR_PROM_OPEN 22 90 #define ERR_PROM_GETPROP 23 91 #define ERR_PROM_SETPROP 24 92 #define ERR_TRANS 25 93 #define ERR_CMD_INVAL 26 94 #define ERR_OPT_INVAL 27 95 #define ERR_AP_INVAL 28 96 #define ERR_DISABLED 29 97 #define DIAG_FORCE 30 98 #define DIAG_TRANS_OK 31 99 #define DIAG_FAILED 32 100 #define DIAG_WAS_ENABLED 33 101 #define DIAG_WAS_DISABLED 34 102 #define DIAG_WILL_ENABLE 35 103 #define DIAG_WILL_DISABLE 36 104 #define HELP_HEADER 37 105 #define HELP_QUIESCE 38 106 #define HELP_INSERT 39 107 #define HELP_REMOVE 40 108 #define HELP_SET_COND 41 109 #define HELP_ENABLE 42 110 #define HELP_DISABLE 43 111 #define HELP_UNKNOWN 44 112 #define ASK_CONNECT 45 113 #define STR_BD 46 114 #define STR_COL 47 115 #define COND_UNKNOWN 48 116 #define COND_OK 49 117 #define COND_FAILING 50 118 #define COND_FAILED 51 119 #define COND_UNUSABLE 52 120 #define SYSC_COOLING 53 121 #define SYSC_POWER 54 122 #define SYSC_PRECHARGE 55 123 #define SYSC_INTRANS 56 124 #define SYSC_UTHREAD 57 125 #define SYSC_KTHREAD 58 126 #define SYSC_DEV_ATTACH 59 127 #define SYSC_DEV_DETACH 60 128 #define SYSC_NDI_ATTACH 61 129 #define SYSC_NDI_DETACH 62 130 #define SYSC_CORE_RESOURCE 63 131 #define SYSC_OSTATE 64 132 #define SYSC_RSTATE 65 133 #define SYSC_COND 66 134 #define SYSC_PROM 67 135 #define SYSC_NOMEM 68 136 #define SYSC_HOTPLUG 69 137 #define SYSC_HW_COMPAT 70 138 #define SYSC_NON_DR_PROM 71 139 #define SYSC_SUSPEND 72 140 #define SYSC_RESUME 73 141 #define SYSC_UNKNOWN 74 142 #define SYSC_DEVSTR 75 143 144 /* 145 * The string table contains all the strings used by the platform 146 * library. The comment next to each string specifies whether the 147 * string should be internationalized (y) or not (n). 148 * Note that there are calls to dgettext() with strings other than 149 * the ones below, they are marked by the li18 symbol. 150 */ 151 static char * 152 cfga_strs[] = { 153 /* */ NULL, 154 /* n */ "cpu/mem ", 155 /* n */ "mem ", 156 /* n */ "dual-sbus ", 157 /* n */ "sbus-upa ", 158 /* n */ "dual-pci ", 159 /* n */ "disk ", 160 /* n */ "soc+sbus ", 161 /* n */ "soc+upa ", 162 /* n */ "unknown ", 163 /* n */ "get-status", 164 /* n */ "list", 165 /* n */ "connect", 166 /* n */ "disconnect", 167 /* n */ "configure", 168 /* n */ "unconfigure", 169 /* n */ "quiesce-test", 170 /* n */ "insert-test", 171 /* n */ "remove-test", 172 /* n */ "set-condition-test", 173 /* n */ "enable-at-boot", 174 /* n */ "disable-at-boot", 175 /* n */ "prom open", 176 /* n */ "prom getprop", 177 /* n */ "prom setprop", 178 /* y */ "invalid transition", 179 /* y */ "invalid command: ", 180 /* y */ "invalid option: ", 181 /* y */ "invalid attachment point: ", 182 /* y */ "board is disabled: must override with ", 183 /* n */ "[-f][-o enable-at-boot]", 184 /* y */ "transition succeeded but ", 185 /* y */ " failed: ", 186 /* y */ "was already enabled at boot time", 187 /* y */ "was already disabled at boot time", 188 /* y */ "will be enabled at boot time", 189 /* y */ "will be disabled at boot time", 190 /* y */ "\nSysctrl specific commands/options:", 191 /* n */ "\t-x quiesce-test ap_id [ap_id...]", 192 /* n */ "\t-x insert-test ap_id [ap_id...]", 193 /* n */ "\t-x remove-test ap_id [ap_id...]", 194 /* n */ "\t-x set-condition-test=<condition>", 195 /* n */ "\t-o enable-at-boot", 196 /* n */ "\t-o disable-at-boot", 197 /* y */ "\tunknown command or option: ", 198 /* y */ 199 "system will be temporarily suspended to connect a board: proceed", 200 /* y */ "board ", 201 /* y */ ": ", 202 /* n */ "unknown", 203 /* n */ "ok", 204 /* n */ "failing", 205 /* n */ "failed", 206 /* n */ "unusable", 207 /* y */ "not enough cooling for a new board", 208 /* y */ "not enough power for a new board", 209 /* y */ "not enough precharge power for a new board", 210 /* y */ "configuration operation already in progress on this board", 211 /* y */ "could not suspend user process: ", 212 /* y */ "could not suspend system processes", 213 /* y */ "device did not attach", 214 /* y */ "device did not detach", 215 /* y */ "nexus error during attach", 216 /* y */ "nexus error during detach", 217 /* y */ "attempt to remove core system resource", 218 /* y */ "invalid occupant state", 219 /* y */ "invalid receptacle state", 220 /* y */ "insufficient condition", 221 /* y */ "firmware operation error", 222 /* y */ "not enough memory", 223 /* y */ "hotplug feature unavailable on this machine", 224 /* y */ "board does not support dynamic reconfiguration", 225 /* y */ "firmware does not support dynamic reconfiguration", 226 /* y */ "system suspend error", 227 /* y */ "system resume error", 228 /* y */ "unknown system error", 229 /* */ NULL 230 }; 231 232 #define cfga_str(i) cfga_strs[(i)] 233 234 #define cfga_eid(a, b) (((a) << 8) + (b)) 235 236 /* 237 * 238 * Translation table for mapping from an <errno,sysc_err> 239 * pair to an error string. 240 * 241 * 242 * SYSC_COOLING, EAGAIN, SYSC_ERR_COOLING 243 * SYSC_POWER, EAGAIN, SYSC_ERR_POWER 244 * SYSC_PRECHARGE, EAGAIN, SYSC_ERR_PRECHARGE 245 * SYSC_INTRANS, EBUSY, SYSC_ERR_INTRANS 246 * SYSC_KTHREAD, EBUSY, SYSC_ERR_KTHREAD 247 * SYSC_DEV_ATTACH, EBUSY, SYSC_ERR_NDI_ATTACH 248 * SYSC_DEV_DETACH, EBUSY, SYSC_ERR_NDI_DETACH 249 * SYSC_NDI_ATTACH, EFAULT, SYSC_ERR_NDI_ATTACH 250 * SYSC_NDI_DETACH, EFAULT, SYSC_ERR_NDI_DETACH 251 * SYSC_CORE_RESOURCE, EINVAL, SYSC_ERR_CORE_RESOURCE 252 * SYSC_OSTATE, EINVAL, SYSC_ERR_OSTATE 253 * SYSC_RSTATE, EINVAL, SYSC_ERR_RSTATE 254 * SYSC_COND, EINVAL, SYSC_ERR_COND 255 * SYSC_PROM, EIO, SYSC_ERR_PROM 256 * SYSC_NOMEM, ENOMEM, SYSC_ERR_DR_INIT 257 * SYSC_NOMEM, ENOMEM, SYSC_ERR_NDI_ATTACH 258 * SYSC_NOMEM, ENOMEM, SYSC_ERR_NDI_DETACH 259 * SYSC_HOTPLUG, ENOTSUP, SYSC_ERR_HOTPLUG 260 * SYSC_HW_COMPAT, ENOTSUP, SYSC_ERR_HW_COMPAT 261 * SYSC_NON_DR_PROM, ENOTSUP, SYSC_ERR_NON_DR_PROM 262 * SYSC_SUSPEND, ENXIO, SYSC_ERR_SUSPEND 263 * SYSC_RESUME, ENXIO, SYSC_ERR_RESUME 264 * SYSC_UTHREAD, ESRCH, SYSC_ERR_UTHREAD 265 */ 266 static int 267 cfga_sid(int err, int scerr) 268 { 269 if (scerr == SYSC_ERR_DEFAULT) 270 return (SYSC_UNKNOWN); 271 272 switch (cfga_eid(err, scerr)) { 273 case cfga_eid(EAGAIN, SYSC_ERR_COOLING): 274 return (SYSC_COOLING); 275 case cfga_eid(EAGAIN, SYSC_ERR_POWER): 276 return (SYSC_POWER); 277 case cfga_eid(EAGAIN, SYSC_ERR_PRECHARGE): 278 return (SYSC_PRECHARGE); 279 case cfga_eid(EBUSY, SYSC_ERR_INTRANS): 280 return (SYSC_INTRANS); 281 case cfga_eid(EBUSY, SYSC_ERR_KTHREAD): 282 return (SYSC_KTHREAD); 283 case cfga_eid(EBUSY, SYSC_ERR_NDI_ATTACH): 284 return (SYSC_DEV_ATTACH); 285 case cfga_eid(EBUSY, SYSC_ERR_NDI_DETACH): 286 return (SYSC_DEV_DETACH); 287 case cfga_eid(EFAULT, SYSC_ERR_NDI_ATTACH): 288 return (SYSC_NDI_ATTACH); 289 case cfga_eid(EFAULT, SYSC_ERR_NDI_DETACH): 290 return (SYSC_NDI_DETACH); 291 case cfga_eid(EINVAL, SYSC_ERR_CORE_RESOURCE): 292 return (SYSC_CORE_RESOURCE); 293 case cfga_eid(EINVAL, SYSC_ERR_OSTATE): 294 return (SYSC_OSTATE); 295 case cfga_eid(EINVAL, SYSC_ERR_RSTATE): 296 return (SYSC_RSTATE); 297 case cfga_eid(EINVAL, SYSC_ERR_COND): 298 return (SYSC_COND); 299 case cfga_eid(EIO, SYSC_ERR_PROM): 300 return (SYSC_PROM); 301 case cfga_eid(ENOMEM, SYSC_ERR_DR_INIT): 302 return (SYSC_NOMEM); 303 case cfga_eid(ENOMEM, SYSC_ERR_NDI_ATTACH): 304 return (SYSC_NOMEM); 305 case cfga_eid(ENOMEM, SYSC_ERR_NDI_DETACH): 306 return (SYSC_NOMEM); 307 case cfga_eid(ENOTSUP, SYSC_ERR_HOTPLUG): 308 return (SYSC_HOTPLUG); 309 case cfga_eid(ENOTSUP, SYSC_ERR_HW_COMPAT): 310 return (SYSC_HW_COMPAT); 311 case cfga_eid(ENOTSUP, SYSC_ERR_NON_DR_PROM): 312 return (SYSC_NON_DR_PROM); 313 case cfga_eid(ENXIO, SYSC_ERR_SUSPEND): 314 return (SYSC_SUSPEND); 315 case cfga_eid(ENXIO, SYSC_ERR_RESUME): 316 return (SYSC_RESUME); 317 case cfga_eid(ESRCH, SYSC_ERR_UTHREAD): 318 return (SYSC_UTHREAD); 319 default: 320 break; 321 } 322 323 return (SYSC_UNKNOWN); 324 } 325 326 static void 327 sysc_cmd_init(sysc_cfga_cmd_t *sc, char *outputstr, int force) 328 { 329 sc->force = force; 330 sc->outputstr = outputstr; 331 sc->errtype = SYSC_ERR_DEFAULT; 332 333 (void) memset((void *)outputstr, 0, sizeof (outputstr)); 334 335 cfga_str(SYSC_DEVSTR) = outputstr; 336 } 337 338 /* 339 * cfga_err() accepts a variable number of message IDs and constructs 340 * a corresponding error string which is returned via the errstring argument. 341 * cfga_err() calls dgettext() to internationalize proper messages. 342 */ 343 static void 344 cfga_err(sysc_cfga_cmd_t *sc, char **errstring, ...) 345 { 346 int a; 347 int i; 348 int n; 349 int len; 350 int flen; 351 char *p; 352 char *q; 353 char *s[32]; 354 char *failed; 355 va_list ap; 356 char syserr_num[20]; 357 358 /* 359 * If errstring is null it means user in not interested in getting 360 * error status. So we don't do all the work 361 */ 362 if (errstring == NULL) { 363 return; 364 } 365 va_start(ap, errstring); 366 367 failed = dgettext(TEXT_DOMAIN, cfga_str(DIAG_FAILED)); 368 flen = strlen(failed); 369 370 for (n = len = 0; (a = va_arg(ap, int)) != 0; n++) { 371 372 switch (a) { 373 case ERR_PROM_OPEN: 374 case ERR_PROM_GETPROP: 375 case ERR_PROM_SETPROP: 376 case CMD_GETSTAT: 377 case CMD_LIST: 378 case CMD_CONNECT: 379 case CMD_DISCONNECT: 380 case CMD_CONFIGURE: 381 case CMD_UNCONFIGURE: 382 case CMD_QUIESCE: 383 case CMD_INSERT: 384 case CMD_REMOVE: 385 case CMD_SET_COND: 386 p = cfga_str(a); 387 len += (strlen(p) + flen); 388 s[n] = p; 389 s[++n] = failed; 390 391 DBG("<%s>", p); 392 DBG("<%s>", failed); 393 break; 394 395 case OPT_ENABLE: 396 case OPT_DISABLE: 397 p = dgettext(TEXT_DOMAIN, cfga_str(DIAG_TRANS_OK)); 398 q = cfga_str(a); 399 len += (strlen(p) + strlen(q) + flen); 400 s[n] = p; 401 s[++n] = q; 402 s[++n] = failed; 403 404 DBG("<%s>", p); 405 DBG("<%s>", q); 406 DBG("<%s>", failed); 407 break; 408 409 case ERR_CMD_INVAL: 410 case ERR_AP_INVAL: 411 case ERR_OPT_INVAL: 412 p = dgettext(TEXT_DOMAIN, cfga_str(a)); 413 q = va_arg(ap, char *); 414 len += (strlen(p) + strlen(q)); 415 s[n] = p; 416 s[++n] = q; 417 418 DBG("<%s>", p); 419 DBG("<%s>", q); 420 break; 421 422 case ERR_TRANS: 423 case ERR_DISABLED: 424 p = dgettext(TEXT_DOMAIN, cfga_str(a)); 425 len += strlen(p); 426 s[n] = p; 427 428 DBG("<%s>", p); 429 break; 430 431 case DIAG_FORCE: 432 default: 433 p = cfga_str(a); 434 len += strlen(p); 435 s[n] = p; 436 437 DBG("<%s>", p); 438 break; 439 } 440 } 441 442 DBG1("\n"); 443 va_end(ap); 444 445 if (errno) { 446 if (sc) 447 i = cfga_sid(errno, (int)sc->errtype); 448 else 449 i = SYSC_UNKNOWN; 450 451 DBG4("cfga_sid(%d,%d)=%d\n", errno, sc->errtype, i); 452 453 if (i == SYSC_UNKNOWN) { 454 p = strerror(errno); 455 if (p == NULL) { 456 (void) sprintf(syserr_num, "errno=%d", errno); 457 p = syserr_num; 458 } 459 } else 460 p = dgettext(TEXT_DOMAIN, cfga_str(i)); 461 462 len += strlen(p); 463 s[n++] = p; 464 p = cfga_str(SYSC_DEVSTR); 465 if (p && p[0]) { 466 q = cfga_str(STR_COL); 467 468 len += strlen(q); 469 s[n++] = q; 470 len += strlen(p); 471 s[n++] = p; 472 } 473 } 474 475 if ((p = (char *)calloc(len, 1)) == NULL) 476 return; 477 478 for (i = 0; i < n; i++) 479 (void) strcat(p, s[i]); 480 481 *errstring = p; 482 #ifdef SIM_MSG 483 printf("%s\n", *errstring); 484 #endif 485 } 486 487 /* 488 * This routine accepts a variable number of message IDs and constructs 489 * a corresponding error string which is printed via the message print routine 490 * argument. The HELP_UNKNOWN message ID has an argument string (the unknown 491 * help topic) that follows. 492 */ 493 static void 494 cfga_msg(struct cfga_msg *msgp, ...) 495 { 496 int a; 497 int i; 498 int n; 499 int len; 500 char *p; 501 char *s[32]; 502 va_list ap; 503 504 va_start(ap, msgp); 505 506 for (n = len = 0; (a = va_arg(ap, int)) != 0; n++) { 507 DBG("<%d>", a); 508 p = dgettext(TEXT_DOMAIN, cfga_str(a)); 509 len += strlen(p); 510 s[n] = p; 511 if (a == HELP_UNKNOWN) { 512 p = va_arg(ap, char *); 513 len += strlen(p); 514 s[++n] = p; 515 } 516 } 517 518 va_end(ap); 519 520 if ((p = (char *)calloc(len + 1, 1)) == NULL) 521 return; 522 523 for (i = 0; i < n; i++) 524 (void) strcat(p, s[i]); 525 (void) strcat(p, "\n"); 526 527 #ifdef SIM_MSG 528 printf("%s", p); 529 #else 530 (*msgp->message_routine)(msgp->appdata_ptr, p); 531 #endif 532 free(p); 533 } 534 535 static sysc_cfga_stat_t * 536 sysc_stat(const char *ap_id, int *fdp) 537 { 538 int fd; 539 static sysc_cfga_stat_t sc_list[MAX_BOARDS]; 540 541 542 if ((fd = open(ap_id, O_RDWR, 0)) == -1) 543 return (NULL); 544 else if (ioctl(fd, SYSC_CFGA_CMD_GETSTATUS, sc_list) == -1) { 545 (void) close(fd); 546 return (NULL); 547 } else if (fdp) 548 *fdp = fd; 549 else 550 (void) close(fd); 551 552 return (sc_list); 553 } 554 555 /* 556 * This code implementes the simulation of the ioctls that transition state. 557 * The GETSTAT ioctl is not simulated. In this way a snapshot of the system 558 * state is read and manipulated by the simulation routines. It is basically 559 * a useful debugging tool. 560 */ 561 #ifdef SIM 562 static int sim_idx; 563 static int sim_fd = -1; 564 static int sim_size = MAX_BOARDS * sizeof (sysc_cfga_stat_t); 565 static sysc_cfga_stat_t sim_sc_list[MAX_BOARDS]; 566 567 static sysc_cfga_stat_t * 568 sim_sysc_stat(const char *ap_id, int *fdp) 569 { 570 int fd; 571 struct stat buf; 572 573 if (sim_fd != -1) 574 return (sim_sc_list); 575 576 if ((sim_fd = open("/tmp/cfga_simdata", O_RDWR|O_CREAT)) == -1) { 577 perror("sim_open"); 578 exit(1); 579 } else if (fstat(sim_fd, &buf) == -1) { 580 perror("sim_stat"); 581 exit(1); 582 } 583 584 if (buf.st_size) { 585 if (buf.st_size != sim_size) { 586 perror("sim_size"); 587 exit(1); 588 } else if (read(sim_fd, sim_sc_list, sim_size) == -1) { 589 perror("sim_read"); 590 exit(1); 591 } 592 } else if ((fd = open(ap_id, O_RDWR, 0)) == -1) 593 return (NULL); 594 else if (ioctl(fd, SYSC_CFGA_CMD_GETSTATUS, sim_sc_list) == -1) { 595 (void) close(fd); 596 return (NULL); 597 } else if (fdp) 598 *fdp = fd; 599 600 return (sim_sc_list); 601 } 602 603 static int 604 sim_open(char *a, int b, int c) 605 { 606 printf("sim_open(%s)\n", a); 607 608 if (strcmp(a, "/dev/openprom") == 0) 609 return (open(a, b, c)); 610 return (0); 611 } 612 613 static int 614 sim_close(int a) { return (0); } 615 616 static int 617 sim_ioctl(int fd, int cmd, void *a) 618 { 619 printf("sim_ioctl(%d)\n", sim_idx); 620 621 switch (cmd) { 622 case SYSC_CFGA_CMD_CONNECT: 623 sim_sc_list[sim_idx].rstate = SYSC_CFGA_RSTATE_CONNECTED; 624 break; 625 case SYSC_CFGA_CMD_CONFIGURE: 626 sim_sc_list[sim_idx].ostate = SYSC_CFGA_OSTATE_CONFIGURED; 627 break; 628 case SYSC_CFGA_CMD_UNCONFIGURE: 629 sim_sc_list[sim_idx].ostate = SYSC_CFGA_OSTATE_UNCONFIGURED; 630 break; 631 case SYSC_CFGA_CMD_DISCONNECT: 632 sim_sc_list[sim_idx].rstate = SYSC_CFGA_RSTATE_DISCONNECTED; 633 break; 634 case SYSC_CFGA_CMD_QUIESCE_TEST: 635 case SYSC_CFGA_CMD_TEST: 636 return (0); 637 case OPROMGETOPT: 638 return (ioctl(fd, OPROMGETOPT, a)); 639 case OPROMSETOPT: 640 return (ioctl(fd, OPROMSETOPT, a)); 641 } 642 643 if (lseek(sim_fd, SEEK_SET, 0) == -1) { 644 perror("sim_seek"); 645 exit(1); 646 } 647 if (write(sim_fd, sim_sc_list, sim_size) == -1) { 648 perror("sim_write"); 649 exit(1); 650 } 651 652 return (0); 653 } 654 655 #define open(a, b, c) sim_open((char *)(a), (int)(b), (int)(c)) 656 #define close(a) sim_close(a) 657 #define ioctl(a, b, c) sim_ioctl((int)(a), (int)(b), (void *)(c)) 658 #define sysc_stat(a, b) sim_sysc_stat(a, b) 659 #endif /* SIM */ 660 661 static char *promdev = "/dev/openprom"; 662 static char *dlprop = "disabled-board-list"; 663 664 #define BUFSIZE 128 665 666 typedef union { 667 char buf[BUFSIZE]; 668 struct openpromio opp; 669 } oppbuf_t; 670 671 static int 672 prom_get_prop(int prom_fd, char *var, char **val) 673 { 674 static oppbuf_t oppbuf; 675 struct openpromio *opp = &(oppbuf.opp); 676 677 (void) strncpy(opp->oprom_array, var, OBP_MAXPROPNAME); 678 opp->oprom_array[OBP_MAXPROPNAME + 1] = '\0'; 679 opp->oprom_size = BUFSIZE; 680 681 DBG3("getprop(%s, %d)\n", opp->oprom_array, opp->oprom_size); 682 683 if (ioctl(prom_fd, OPROMGETOPT, opp) < 0) 684 return (ERR_PROM_GETPROP); 685 else if (opp->oprom_size > 0) 686 *val = opp->oprom_array; 687 else 688 *val = NULL; 689 690 return (0); 691 } 692 693 static cfga_err_t 694 prom_set_prop(int prom_fd, char *var, char *val) 695 { 696 oppbuf_t oppbuf; 697 struct openpromio *opp = &(oppbuf.opp); 698 int varlen = strlen(var) + 1; 699 int vallen = strlen(val); 700 701 DBG("prom_set_prop(%s)\n", val); 702 703 (void) strcpy(opp->oprom_array, var); 704 (void) strcpy(opp->oprom_array + varlen, val); 705 opp->oprom_size = varlen + vallen; 706 707 if (ioctl(prom_fd, OPROMSETOPT, opp) < 0) 708 return (ERR_PROM_SETPROP); 709 710 return (0); 711 } 712 713 static int 714 dlist_find(int board, char **dlist, int *disabled) 715 { 716 int i; 717 int err; 718 int prom_fd; 719 char *p; 720 char *dl; 721 char b[2]; 722 723 if ((prom_fd = open(promdev, O_RDWR, 0)) < 0) 724 return (ERR_PROM_OPEN); 725 else if (err = prom_get_prop(prom_fd, dlprop, dlist)) { 726 (void) close(prom_fd); 727 return (err); 728 } else 729 (void) close(prom_fd); 730 731 b[1] = 0; 732 *disabled = 0; 733 734 if ((dl = *dlist) != NULL) { 735 int len = strlen(dl); 736 737 for (i = 0; i < len; i++) { 738 int bd; 739 740 b[0] = dl[i]; 741 bd = strtol(b, &p, 16); 742 743 if (p != b && bd == board) 744 (*disabled)++; 745 } 746 } 747 748 return (0); 749 } 750 751 static int 752 dlist_update(int board, int disable, char *dlist, struct cfga_msg *msgp, 753 int verbose) 754 { 755 int i, j, n; 756 int err; 757 int found; 758 int update; 759 int prom_fd; 760 char *p; 761 char b[2]; 762 char ndlist[64]; 763 764 b[1] = 0; 765 ndlist[0] = 0; 766 j = 0; 767 found = 0; 768 update = 0; 769 770 if ((prom_fd = open(promdev, O_RDWR, 0)) < 0) 771 return (ERR_PROM_OPEN); 772 773 if (dlist) { 774 int len = strlen(dlist); 775 776 for (i = 0; i < len; i++) { 777 int bd; 778 779 b[0] = dlist[i]; 780 bd = strtol(b, &p, 16); 781 782 if (p != b && bd == board) { 783 784 found++; 785 if (disable) { 786 if (verbose) 787 cfga_msg(msgp, STR_BD, 788 DIAG_WAS_DISABLED, 0); 789 } else { 790 if (verbose) 791 cfga_msg(msgp, STR_BD, 792 DIAG_WILL_ENABLE, 0); 793 update++; 794 continue; 795 } 796 } 797 ndlist[j++] = dlist[i]; 798 } 799 ndlist[j] = 0; 800 } 801 802 if (!found) 803 if (disable) { 804 if (verbose) 805 cfga_msg(msgp, STR_BD, DIAG_WILL_DISABLE, 0); 806 p = &ndlist[j]; 807 n = sprintf(p, "%x", board); 808 p[n] = 0; 809 update++; 810 } else { 811 if (verbose) 812 cfga_msg(msgp, STR_BD, DIAG_WAS_ENABLED, 0); 813 } 814 815 if (update) 816 err = prom_set_prop(prom_fd, dlprop, ndlist); 817 else 818 err = 0; 819 820 (void) close(prom_fd); 821 822 return (err); 823 } 824 825 static int 826 ap_idx(const char *ap_id) 827 { 828 int id; 829 char *s; 830 static char *slot = "slot"; 831 832 DBG("ap_idx(%s)\n", ap_id); 833 834 if ((s = strstr(ap_id, slot)) == NULL) 835 return (-1); 836 else { 837 int n; 838 839 s += strlen(slot); 840 n = strlen(s); 841 842 DBG3("ap_idx: s=%s, n=%d\n", s, n); 843 844 switch (n) { 845 case 2: 846 if (!isdigit(s[1])) 847 return (-1); 848 /* FALLTHROUGH */ 849 case 1: 850 if (!isdigit(s[0])) 851 return (-1); 852 break; 853 default: 854 return (-1); 855 } 856 } 857 858 if ((id = atoi(s)) > MAX_BOARDS) 859 return (-1); 860 861 DBG3("ap_idx(%s)=%d\n", s, id); 862 863 return (id); 864 } 865 866 /*ARGSUSED*/ 867 cfga_err_t 868 cfga_change_state( 869 cfga_cmd_t state_change_cmd, 870 const char *ap_id, 871 const char *options, 872 struct cfga_confirm *confp, 873 struct cfga_msg *msgp, 874 char **errstring, 875 cfga_flags_t flags) 876 { 877 int fd; 878 int idx; 879 int err; 880 int force; 881 int verbose; 882 int opterr; 883 int disable; 884 int disabled; 885 cfga_err_t rc; 886 sysc_cfga_stat_t *ss; 887 sysc_cfga_cmd_t *sc, sysc_cmd; 888 sysc_cfga_rstate_t rs; 889 sysc_cfga_ostate_t os; 890 char *dlist; 891 char outputstr[SYSC_OUTPUT_LEN]; 892 893 if (errstring != NULL) 894 *errstring = NULL; 895 896 rc = CFGA_ERROR; 897 898 if (options) { 899 disable = 0; 900 if (strcmp(options, cfga_str(OPT_DISABLE)) == 0) 901 disable++; 902 else if (strcmp(options, cfga_str(OPT_ENABLE))) { 903 cfga_err(NULL, errstring, ERR_OPT_INVAL, options, 0); 904 return (rc); 905 } 906 } 907 908 if ((idx = ap_idx(ap_id)) == -1) { 909 cfga_err(NULL, errstring, ERR_AP_INVAL, ap_id, 0); 910 return (rc); 911 } else if ((ss = sysc_stat(ap_id, &fd)) == NULL) { 912 cfga_err(NULL, errstring, CMD_GETSTAT, 0); 913 return (rc); 914 } 915 #ifdef SIM 916 sim_idx = idx; 917 #endif 918 /* 919 * We disallow connecting on the disabled list unless 920 * either the FORCE flag or the enable-at-boot option 921 * is set. The check is made further below 922 */ 923 if (opterr = dlist_find(idx, &dlist, &disabled)) { 924 err = disable ? OPT_DISABLE : OPT_ENABLE; 925 cfga_err(NULL, errstring, err, opterr, 0); 926 (void) close(fd); 927 return (rc); 928 } else 929 force = flags & CFGA_FLAG_FORCE; 930 931 rs = ss[idx].rstate; 932 os = ss[idx].ostate; 933 934 sc = &sysc_cmd; 935 sysc_cmd_init(sc, outputstr, force); 936 verbose = flags & CFGA_FLAG_VERBOSE; 937 938 switch (state_change_cmd) { 939 case CFGA_CMD_CONNECT: 940 if (rs != SYSC_CFGA_RSTATE_DISCONNECTED) 941 cfga_err(NULL, errstring, ERR_TRANS, 0); 942 else if (disabled && !(force || (options && !disable))) 943 cfga_err(NULL, errstring, CMD_CONNECT, 944 ERR_DISABLED, DIAG_FORCE, 0); 945 else if (!(*confp->confirm)(confp->appdata_ptr, 946 cfga_str(ASK_CONNECT))) { 947 (void) close(fd); 948 return (CFGA_NACK); 949 } else if (ioctl(fd, SYSC_CFGA_CMD_CONNECT, sc) == -1) 950 cfga_err(sc, errstring, CMD_CONNECT, 0); 951 else if (options && (opterr = dlist_update(idx, disable, 952 dlist, msgp, verbose))) { 953 err = disable ? OPT_DISABLE : OPT_ENABLE; 954 cfga_err(NULL, errstring, err, opterr, 0); 955 } else 956 rc = CFGA_OK; 957 break; 958 959 case CFGA_CMD_DISCONNECT: 960 if ((os == SYSC_CFGA_OSTATE_CONFIGURED) && 961 (ioctl(fd, SYSC_CFGA_CMD_UNCONFIGURE, sc) == -1)) { 962 cfga_err(sc, errstring, CMD_UNCONFIGURE, 0); 963 (void) close(fd); 964 return (CFGA_ERROR); 965 } else 966 sysc_cmd_init(sc, outputstr, force); 967 968 if (rs == SYSC_CFGA_RSTATE_CONNECTED) { 969 if (ioctl(fd, SYSC_CFGA_CMD_DISCONNECT, sc) == -1) 970 cfga_err(sc, errstring, CMD_DISCONNECT, 0); 971 else if (options && (opterr = dlist_update(idx, disable, 972 dlist, msgp, verbose))) { 973 err = disable ? OPT_DISABLE : OPT_ENABLE; 974 cfga_err(NULL, errstring, err, opterr, 0); 975 } else 976 rc = CFGA_OK; 977 } else 978 cfga_err(NULL, errstring, ERR_TRANS, 0); 979 break; 980 981 case CFGA_CMD_CONFIGURE: 982 if (rs == SYSC_CFGA_RSTATE_DISCONNECTED) 983 if (disabled && !(force || (options && !disable))) { 984 cfga_err(NULL, errstring, CMD_CONFIGURE, 985 ERR_DISABLED, DIAG_FORCE, 0); 986 (void) close(fd); 987 return (CFGA_ERROR); 988 } else if (!(*confp->confirm)(confp->appdata_ptr, 989 cfga_str(ASK_CONNECT))) { 990 (void) close(fd); 991 return (CFGA_NACK); 992 } else if (ioctl(fd, SYSC_CFGA_CMD_CONNECT, sc) == -1) { 993 cfga_err(sc, errstring, CMD_CONNECT, 0); 994 (void) close(fd); 995 return (CFGA_ERROR); 996 } else 997 sysc_cmd_init(sc, outputstr, force); 998 999 if (os == SYSC_CFGA_OSTATE_UNCONFIGURED) { 1000 if (ioctl(fd, SYSC_CFGA_CMD_CONFIGURE, sc) == -1) 1001 cfga_err(sc, errstring, CMD_CONFIGURE, 0); 1002 else if (options && (opterr = dlist_update(idx, 1003 disable, dlist, msgp, verbose))) { 1004 err = disable ? OPT_DISABLE : OPT_ENABLE; 1005 cfga_err(NULL, errstring, err, opterr, 0); 1006 } else 1007 rc = CFGA_OK; 1008 } else 1009 cfga_err(NULL, errstring, ERR_TRANS, 0); 1010 break; 1011 1012 case CFGA_CMD_UNCONFIGURE: 1013 if (os != SYSC_CFGA_OSTATE_CONFIGURED) 1014 cfga_err(NULL, errstring, ERR_TRANS, 0); 1015 else if (ioctl(fd, SYSC_CFGA_CMD_UNCONFIGURE, sc) == -1) 1016 cfga_err(sc, errstring, CMD_UNCONFIGURE, 0); 1017 else if (options && (opterr = dlist_update(idx, disable, 1018 dlist, msgp, verbose))) { 1019 err = disable ? OPT_DISABLE : OPT_ENABLE; 1020 cfga_err(NULL, errstring, err, opterr, 0); 1021 } else 1022 rc = CFGA_OK; 1023 break; 1024 1025 default: 1026 rc = CFGA_OPNOTSUPP; 1027 break; 1028 } 1029 1030 (void) close(fd); 1031 return (rc); 1032 } 1033 1034 static int 1035 str2cond(const char *cond) 1036 { 1037 int c; 1038 1039 if (strcmp(cond, cfga_str(COND_UNKNOWN)) == 0) 1040 c = SYSC_CFGA_COND_UNKNOWN; 1041 else if (strcmp(cond, cfga_str(COND_OK)) == 0) 1042 c = SYSC_CFGA_COND_OK; 1043 else if (strcmp(cond, cfga_str(COND_FAILING)) == 0) 1044 c = SYSC_CFGA_COND_FAILING; 1045 else if (strcmp(cond, cfga_str(COND_FAILED)) == 0) 1046 c = SYSC_CFGA_COND_FAILED; 1047 else if (strcmp(cond, cfga_str(COND_UNUSABLE)) == 0) 1048 c = SYSC_CFGA_COND_UNUSABLE; 1049 else 1050 c = -1; 1051 1052 return (c); 1053 } 1054 1055 /*ARGSUSED*/ 1056 cfga_err_t 1057 cfga_private_func( 1058 const char *function, 1059 const char *ap_id, 1060 const char *options, 1061 struct cfga_confirm *confp, 1062 struct cfga_msg *msgp, 1063 char **errstring, 1064 cfga_flags_t flags) 1065 { 1066 int fd; 1067 int idx; 1068 int len; 1069 int cmd; 1070 int cond; 1071 int err; 1072 int opterr; 1073 int verbose; 1074 int disable; 1075 int disabled; 1076 cfga_err_t rc; 1077 char *str; 1078 char *dlist; 1079 char outputstr[SYSC_OUTPUT_LEN]; 1080 sysc_cfga_cmd_t *sc, sysc_cmd; 1081 1082 if (errstring != NULL) 1083 *errstring = NULL; 1084 1085 verbose = flags & CFGA_FLAG_VERBOSE; 1086 1087 rc = CFGA_ERROR; 1088 1089 if (options) { 1090 disable = 0; 1091 if (strcmp(options, cfga_str(OPT_DISABLE)) == 0) 1092 disable++; 1093 else if (strcmp(options, cfga_str(OPT_ENABLE))) { 1094 cfga_err(NULL, errstring, ERR_OPT_INVAL, options, 0); 1095 return (rc); 1096 } 1097 } 1098 1099 sc = &sysc_cmd; 1100 str = cfga_str(CMD_SET_COND); 1101 len = strlen(str); 1102 1103 if ((strncmp(function, str, len) == 0) && (function[len++] == '=') && 1104 ((cond = (str2cond(&function[len]))) != -1)) { 1105 cmd = SYSC_CFGA_CMD_TEST_SET_COND; 1106 err = CMD_SET_COND; 1107 sc->arg = cond; 1108 } else if (strcmp(function, cfga_str(CMD_QUIESCE)) == 0) { 1109 cmd = SYSC_CFGA_CMD_QUIESCE_TEST; 1110 err = CMD_QUIESCE; 1111 } else if (strcmp(function, cfga_str(CMD_INSERT)) == 0) { 1112 cmd = SYSC_CFGA_CMD_TEST; 1113 err = CMD_INSERT; 1114 } else if (strcmp(function, cfga_str(CMD_REMOVE)) == 0) { 1115 cmd = SYSC_CFGA_CMD_TEST; 1116 err = CMD_REMOVE; 1117 } else { 1118 cfga_err(NULL, errstring, ERR_CMD_INVAL, (char *)function, 0); 1119 return (rc); 1120 } 1121 1122 sysc_cmd_init(sc, outputstr, 0); 1123 1124 if ((idx = ap_idx(ap_id)) == -1) 1125 cfga_err(NULL, errstring, ERR_AP_INVAL, ap_id, 0); 1126 else if (((fd = open(ap_id, O_RDWR, 0)) == -1) || 1127 (ioctl(fd, cmd, sc) == -1)) 1128 cfga_err(NULL, errstring, err, 0); 1129 else 1130 rc = CFGA_OK; 1131 1132 if (options) { 1133 opterr = (dlist_find(idx, &dlist, &disabled) || 1134 dlist_update(idx, disable, dlist, msgp, verbose)); 1135 if (opterr) { 1136 err = disable ? OPT_DISABLE : OPT_ENABLE; 1137 if (verbose) 1138 cfga_msg(msgp, err, opterr, 0); 1139 } 1140 } 1141 1142 (void) close(fd); 1143 return (rc); 1144 } 1145 1146 1147 /*ARGSUSED*/ 1148 cfga_err_t 1149 cfga_test( 1150 const char *ap_id, 1151 const char *options, 1152 struct cfga_msg *msgp, 1153 char **errstring, 1154 cfga_flags_t flags) 1155 { 1156 if (errstring != NULL) 1157 *errstring = NULL; 1158 1159 return (CFGA_OPNOTSUPP); 1160 } 1161 1162 static cfga_stat_t 1163 rstate_cvt(sysc_cfga_rstate_t rs) 1164 { 1165 cfga_stat_t cs; 1166 1167 switch (rs) { 1168 case SYSC_CFGA_RSTATE_EMPTY: 1169 cs = CFGA_STAT_EMPTY; 1170 break; 1171 case SYSC_CFGA_RSTATE_DISCONNECTED: 1172 cs = CFGA_STAT_DISCONNECTED; 1173 break; 1174 case SYSC_CFGA_RSTATE_CONNECTED: 1175 cs = CFGA_STAT_CONNECTED; 1176 break; 1177 default: 1178 cs = CFGA_STAT_NONE; 1179 break; 1180 } 1181 1182 return (cs); 1183 } 1184 1185 static cfga_stat_t 1186 ostate_cvt(sysc_cfga_ostate_t os) 1187 { 1188 cfga_stat_t cs; 1189 1190 switch (os) { 1191 case SYSC_CFGA_OSTATE_UNCONFIGURED: 1192 cs = CFGA_STAT_UNCONFIGURED; 1193 break; 1194 case SYSC_CFGA_OSTATE_CONFIGURED: 1195 cs = CFGA_STAT_CONFIGURED; 1196 break; 1197 default: 1198 cs = CFGA_STAT_NONE; 1199 break; 1200 } 1201 1202 return (cs); 1203 } 1204 1205 static cfga_cond_t 1206 cond_cvt(sysc_cfga_cond_t sc) 1207 { 1208 cfga_cond_t cc; 1209 1210 switch (sc) { 1211 case SYSC_CFGA_COND_OK: 1212 cc = CFGA_COND_OK; 1213 break; 1214 case SYSC_CFGA_COND_FAILING: 1215 cc = CFGA_COND_FAILING; 1216 break; 1217 case SYSC_CFGA_COND_FAILED: 1218 cc = CFGA_COND_FAILED; 1219 break; 1220 case SYSC_CFGA_COND_UNUSABLE: 1221 cc = CFGA_COND_UNUSABLE; 1222 break; 1223 case SYSC_CFGA_COND_UNKNOWN: 1224 default: 1225 cc = CFGA_COND_UNKNOWN; 1226 break; 1227 } 1228 1229 return (cc); 1230 } 1231 1232 static char * 1233 type_str(enum board_type type) 1234 { 1235 char *type_str; 1236 1237 switch (type) { 1238 case MEM_BOARD: 1239 type_str = cfga_str(BD_MEM); 1240 break; 1241 case CPU_BOARD: 1242 type_str = cfga_str(BD_CPU); 1243 break; 1244 case IO_2SBUS_BOARD: 1245 type_str = cfga_str(BD_IO_2SBUS); 1246 break; 1247 case IO_SBUS_FFB_BOARD: 1248 type_str = cfga_str(BD_IO_SBUS_FFB); 1249 break; 1250 case IO_PCI_BOARD: 1251 type_str = cfga_str(BD_IO_PCI); 1252 break; 1253 case DISK_BOARD: 1254 type_str = cfga_str(BD_DISK); 1255 break; 1256 case IO_2SBUS_SOCPLUS_BOARD: 1257 type_str = cfga_str(BD_IO_2SBUS_SOCPLUS); 1258 break; 1259 case IO_SBUS_FFB_SOCPLUS_BOARD: 1260 type_str = cfga_str(BD_IO_SBUS_FFB_SOCPLUS); 1261 break; 1262 case UNKNOWN_BOARD: 1263 default: 1264 type_str = cfga_str(BD_UNKNOWN); 1265 break; 1266 } 1267 return (type_str); 1268 } 1269 1270 static void 1271 info_set(sysc_cfga_stat_t *sc, cfga_info_t info, int disabled) 1272 { 1273 int i; 1274 struct cpu_info *cpu; 1275 union bd_un *bd = &sc->bd; 1276 1277 *info = NULL; 1278 1279 switch (sc->type) { 1280 case CPU_BOARD: 1281 for (i = 0, cpu = bd->cpu; i < 2; i++, cpu++) { 1282 if (cpu->cpu_speed > 1) { 1283 info += sprintf(info, "cpu %d: ", i); 1284 info += sprintf(info, "%3d MHz ", 1285 cpu->cpu_speed); 1286 if (cpu->cache_size) 1287 info += sprintf(info, "%0.1fM ", 1288 (float)cpu->cache_size / 1289 (float)(1024 * 1024)); 1290 } 1291 } 1292 break; 1293 case IO_SBUS_FFB_BOARD: 1294 switch (bd->io2.ffb_size) { 1295 case FFB_SINGLE: 1296 info += sprintf(info, "single buffered ffb "); 1297 break; 1298 case FFB_DOUBLE: 1299 info += sprintf(info, "double buffered ffb "); 1300 break; 1301 case FFB_NOT_FOUND: 1302 #ifdef FFB_DR_SUPPORT 1303 info += sprintf(info, "no ffb installed "); 1304 #endif 1305 break; 1306 default: 1307 info += sprintf(info, "illegal ffb size "); 1308 break; 1309 } 1310 break; 1311 case DISK_BOARD: 1312 for (i = 0; i < 2; i++) 1313 if (bd->dsk.disk_pres[i]) 1314 info += sprintf(info, "target: %2d ", 1315 bd->dsk.disk_id[i]); 1316 else 1317 info += sprintf(info, "no disk "); 1318 break; 1319 } 1320 1321 if (disabled) 1322 info += sprintf(info, "disabled at boot "); 1323 1324 if (sc->no_detach) 1325 info += sprintf(info, "non-detachable "); 1326 1327 if (sc->plus_board) 1328 info += sprintf(info, "100 MHz capable "); 1329 } 1330 1331 static void 1332 sysc_cvt(sysc_cfga_stat_t *sc, cfga_stat_data_t *cs, int disabled) 1333 { 1334 (void) strcpy(cs->ap_type, type_str(sc->type)); 1335 cs->ap_r_state = rstate_cvt(sc->rstate); 1336 cs->ap_o_state = ostate_cvt(sc->ostate); 1337 cs->ap_cond = cond_cvt(sc->condition); 1338 cs->ap_busy = (cfga_busy_t)sc->in_transition; 1339 cs->ap_status_time = sc->last_change; 1340 info_set(sc, cs->ap_info, disabled); 1341 cs->ap_log_id[0] = NULL; 1342 cs->ap_phys_id[0] = NULL; 1343 } 1344 1345 /*ARGSUSED*/ 1346 cfga_err_t 1347 cfga_list( 1348 const char *ap_id, 1349 cfga_stat_data_t **ap_list, 1350 int *nlist, 1351 const char *options, 1352 char **errstring) 1353 { 1354 int i; 1355 cfga_err_t rc; 1356 sysc_cfga_stat_t *sc; 1357 cfga_stat_data_t *cs; 1358 1359 if (errstring != NULL) 1360 *errstring = NULL; 1361 1362 rc = CFGA_ERROR; 1363 1364 if (ap_idx(ap_id) == -1) 1365 cfga_err(NULL, errstring, ERR_AP_INVAL, ap_id, 0); 1366 else if ((sc = sysc_stat(ap_id, NULL)) == NULL) 1367 cfga_err(NULL, errstring, CMD_LIST, 0); 1368 else if (!(cs = (cfga_stat_data_t *)malloc(MAX_BOARDS * sizeof (*cs)))) 1369 cfga_err(NULL, errstring, CMD_LIST, 0); 1370 else { 1371 *ap_list = cs; 1372 1373 for (*nlist = 0, i = 0; i < MAX_BOARDS; i++, sc++) { 1374 if (sc->board == -1) 1375 continue; 1376 sysc_cvt(sc, cs++, 0); /* XXX - disable */ 1377 (*nlist)++; 1378 } 1379 1380 rc = CFGA_OK; 1381 } 1382 1383 return (rc); 1384 } 1385 1386 /*ARGSUSED*/ 1387 cfga_err_t 1388 cfga_stat( 1389 const char *ap_id, 1390 struct cfga_stat_data *cs, 1391 const char *options, 1392 char **errstring) 1393 { 1394 cfga_err_t rc; 1395 int idx; 1396 int err; 1397 int opterr; 1398 int disable; 1399 int disabled; 1400 char *dlist; 1401 sysc_cfga_stat_t *sc; 1402 1403 if (errstring != NULL) 1404 *errstring = NULL; 1405 1406 rc = CFGA_ERROR; 1407 1408 if (options && options[0]) { 1409 disable = 0; 1410 if (strcmp(options, cfga_str(OPT_DISABLE)) == 0) 1411 disable++; 1412 else if (strcmp(options, cfga_str(OPT_ENABLE))) { 1413 cfga_err(NULL, errstring, ERR_OPT_INVAL, options, 0); 1414 return (rc); 1415 } 1416 } 1417 1418 if ((idx = ap_idx(ap_id)) == -1) 1419 cfga_err(NULL, errstring, ERR_AP_INVAL, ap_id, 0); 1420 else if ((sc = sysc_stat(ap_id, NULL)) == NULL) 1421 cfga_err(NULL, errstring, CMD_GETSTAT, 0); 1422 else { 1423 opterr = dlist_find(idx, &dlist, &disabled); 1424 sysc_cvt(sc + idx, cs, disabled); 1425 1426 rc = CFGA_OK; 1427 1428 if (options && options[0] && ((opterr != 0) || 1429 ((opterr = dlist_update(idx, disable, dlist, NULL, 0)) 1430 != 0))) { 1431 err = disable ? OPT_DISABLE : OPT_ENABLE; 1432 cfga_err(NULL, errstring, err, opterr, 0); 1433 } 1434 } 1435 1436 return (rc); 1437 } 1438 1439 /*ARGSUSED*/ 1440 cfga_err_t 1441 cfga_help(struct cfga_msg *msgp, const char *options, cfga_flags_t flags) 1442 { 1443 int help = 0; 1444 1445 if (options) { 1446 if (strcmp(options, cfga_str(OPT_DISABLE)) == 0) 1447 help = HELP_DISABLE; 1448 else if (strcmp(options, cfga_str(OPT_ENABLE)) == 0) 1449 help = HELP_ENABLE; 1450 else if (strcmp(options, cfga_str(CMD_INSERT)) == 0) 1451 help = HELP_INSERT; 1452 else if (strcmp(options, cfga_str(CMD_REMOVE)) == 0) 1453 help = HELP_REMOVE; 1454 else if (strcmp(options, cfga_str(CMD_QUIESCE)) == 0) 1455 help = HELP_QUIESCE; 1456 else 1457 help = HELP_UNKNOWN; 1458 } 1459 1460 if (help) { 1461 if (help == HELP_UNKNOWN) 1462 cfga_msg(msgp, help, options, 0); 1463 else 1464 cfga_msg(msgp, help, 0); 1465 } else { 1466 cfga_msg(msgp, HELP_HEADER, 0); 1467 cfga_msg(msgp, HELP_DISABLE, 0); 1468 cfga_msg(msgp, HELP_ENABLE, 0); 1469 cfga_msg(msgp, HELP_INSERT, 0); 1470 cfga_msg(msgp, HELP_REMOVE, 0); 1471 cfga_msg(msgp, HELP_QUIESCE, 0); 1472 cfga_msg(msgp, HELP_SET_COND, 0); 1473 } 1474 1475 return (CFGA_OK); 1476 } 1477 1478 /* 1479 * cfga_ap_id_cmp -- use default_ap_id_cmp() in libcfgadm 1480 */ 1481