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