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
cfga_sid(int err,int scerr)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
sysc_cmd_init(sysc_cfga_cmd_t * sc,char * outputstr,int force)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
cfga_err(sysc_cfga_cmd_t * sc,char ** errstring,...)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
cfga_msg(struct cfga_msg * msgp,...)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 *
sysc_stat(const char * ap_id,int * fdp)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 *
sim_sysc_stat(const char * ap_id,int * fdp)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
sim_open(char * a,int b,int c)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
sim_close(int a)612 sim_close(int a)
613 {
614 return (0);
615 }
616
617 static int
sim_ioctl(int fd,int cmd,void * a)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
prom_get_prop(int prom_fd,char * var,char ** val)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
prom_set_prop(int prom_fd,char * var,char * val)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
dlist_find(int board,char ** dlist,int * disabled)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
dlist_update(int board,int disable,char * dlist,struct cfga_msg * msgp,int verbose)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
ap_idx(const char * ap_id)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
cfga_change_state(cfga_cmd_t state_change_cmd,const char * ap_id,const char * options,struct cfga_confirm * confp,struct cfga_msg * msgp,char ** errstring,cfga_flags_t flags)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
str2cond(const char * cond)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
cfga_private_func(const char * function,const char * ap_id,const char * options,struct cfga_confirm * confp,struct cfga_msg * msgp,char ** errstring,cfga_flags_t flags)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
cfga_test(const char * ap_id,const char * options,struct cfga_msg * msgp,char ** errstring,cfga_flags_t flags)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
rstate_cvt(sysc_cfga_rstate_t rs)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
ostate_cvt(sysc_cfga_ostate_t os)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
cond_cvt(sysc_cfga_cond_t sc)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 *
type_str(enum board_type type)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
info_set(sysc_cfga_stat_t * sc,cfga_info_t info,int disabled)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
sysc_cvt(sysc_cfga_stat_t * sc,cfga_stat_data_t * cs,int disabled)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
cfga_list(const char * ap_id,cfga_stat_data_t ** ap_list,int * nlist,const char * options,char ** errstring)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
cfga_stat(const char * ap_id,struct cfga_stat_data * cs,const char * options,char ** errstring)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
cfga_help(struct cfga_msg * msgp,const char * options,cfga_flags_t flags)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