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