4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
32 #include <libdevinfo.h>
35 #define CFGA_PLUGIN_LIB
36 #include <config_admin.h>
38 #include <sys/obpdefs.h>
39 #include <sys/processor.h>
41 #include <sys/sbd_ioctl.h>
42 #include <sys/int_fmtio.h>
45 ap_getncm(apd_t
*a
, sbd_comp_type_t type
, int *ncm
)
50 if (a
->fd
== -1 || a
->ctl
== NULL
)
51 return (CFGA_LIB_ERROR
);
53 ctl
= (sbd_ioctl_arg_t
*)a
->ctl
;
55 ctl
->ic_name
[0] = '\0';
60 DBG("ioctl(%d SBD_CMD_GETNCM, 0x%p)\n", a
->fd
, (void *)ctl
);
62 if (ioctl(a
->fd
, SBD_CMD_GETNCM
, ctl
) == -1) {
63 ap_err(a
, ERR_CMD_FAIL
, CMD_GETNCM
);
67 cp
= &ctl
->i_cmd
.cmd_getncm
;
69 DBG("ncm(%d)=%d\n", type
, cp
->g_ncm
);
78 ap_stat(apd_t
*a
, int all
)
92 DBG("ap_stat(%s)\n", a
->path
);
94 /* Open the file descriptor if not already open */
96 DBG("open(%s)\n", a
->path
);
101 if ((fd
= open(a
->path
, oflag
, 0)) == -1) {
102 ap_err(a
, ERR_AP_INVAL
);
110 if (a
->ctl
== NULL
&& (a
->ctl
= calloc(1, sizeof (*ctl
))) == NULL
) {
111 ap_err(a
, ERR_CMD_FAIL
, CMD_STATUS
);
115 if (a
->tgt
== AP_BOARD
) {
117 * The status target is the board. If we need to
118 * return component data (to support the -a option),
119 * get the number of components on the board.
124 r
= ap_getncm(a
, SBD_COMP_NONE
, &ncm
);
136 DBG("ncm=%d\n", ncm
);
141 * The status structure contains space for one component;
142 * add the space for the other components if necessary.
144 stsize
= sizeof (sbd_stat_t
);
146 stsize
+= ((ncm
- 1) * sizeof (sbd_dev_stat_t
));
148 if ((new_stat
= realloc(a
->stat
, stsize
)) == NULL
) {
149 ap_err(a
, ERR_CMD_FAIL
, CMD_STATUS
);
156 ctl
= (sbd_ioctl_arg_t
*)a
->ctl
;
159 ctl
->ic_type
= SBD_COMP_NONE
;
161 ctl
->i_flags
|= SBD_FLAG_ALLCMP
;
162 sc
= &ctl
->i_cmd
.cmd_stat
;
163 sc
->s_statp
= (caddr_t
)a
->stat
;
164 sc
->s_nbytes
= stsize
;
168 * The target is a specific component. Pass its
169 * name and unit number to the driver. Set its
170 * type to UNKNOWN since the plugin does not know
171 * the type of the component specified by the user.
173 ctl
->ic_type
= SBD_COMP_UNKNOWN
;
174 ctl
->ic_unit
= a
->cnum
;
175 (void) strcpy(ctl
->ic_name
, a
->cname
);
178 DBG("ioctl(%d SBD_CMD_STATUS, sc=0x%p sz=%d flags=%d",
179 fd
, (void *)sc
->s_statp
, sc
->s_nbytes
, ctl
->i_flags
);
181 DBG(" cname=<%s> cnum=%d", a
->cname
, a
->cnum
);
184 if (ioctl(fd
, SBD_CMD_STATUS
, ctl
) == -1) {
185 ap_err(a
, ERR_CMD_FAIL
, CMD_STATUS
);
190 DBG("ap_stat()=%d\n", rc
);
196 * Convert a component to a target type.
199 ap_cm_tgt(sbd_comp_type_t type
)
225 apd_init(apd_t
*a
, int all
)
234 * Ideally, for board operations (other than status) it is not
235 * necessary to issue the STATUS ioctl. The call however allows a
236 * final sanity check to ensure that the board number returned
237 * by the driver matches the plugin's notion of the board number
238 * as extracted from the ap_id. If this check is not desirable,
239 * we can change the code to issue the status call only when
240 * necessary. Note that for component operations, we need to do
241 * the STATUS in order to figure out the component type and
242 * validate the command/options accordingly. XXX
244 if ((rc
= ap_stat(a
, all
)) != CFGA_OK
) {
245 ap_err(a
, ERR_AP_INVAL
);
249 st
= (sbd_stat_t
*)a
->stat
;
252 * Set the component count to the returned stat count.
254 if (a
->ncm
> st
->s_nstat
) {
256 DBG("ncm=%d nstat=%d (truncated)\n", a
->ncm
, st
->s_nstat
);
258 a
->ncm
= st
->s_nstat
;
261 if (a
->tgt
== AP_BOARD
) {
263 DBG("tgt=%d\n", a
->tgt
);
266 * Initialize the RCM module here so that it can record
267 * the initial state of the capacity information.
277 DBG("cname=<%s> cunit=<%d>\n", a
->cname
, a
->cnum
);
279 for (dst
= st
->s_stat
, i
= 0; i
< st
->s_nstat
; i
++, dst
++) {
281 DBG("ds_name,ds_unit,ds_type=<%s,%d,%d> ",
282 dst
->ds_name
, dst
->ds_unit
, dst
->ds_type
);
284 if (dst
->ds_unit
!= a
->cnum
)
288 * Consider the names matched if they are either
289 * both absent or the same. It is conceivable that
290 * a NULL component name be considered valid
295 if ((dn
== NULL
&& cn
== NULL
) ||
296 (dn
!= NULL
&& cn
!= NULL
&& strcmp(dn
, cn
) == 0)) {
297 a
->tgt
= ap_cm_tgt(dst
->ds_type
);
298 a
->cmstat
= (void *)dst
;
306 DBG("tgt=%d\n", a
->tgt
);
308 if (a
->tgt
== AP_NONE
) {
309 ap_err(a
, ERR_CM_INVAL
, a
->cid
);
314 * Initialize the RCM module here so that it can record
315 * the initial state of the capacity information.
345 apd_alloc(const char *ap_id
, cfga_flags_t flags
, char **errstring
,
346 struct cfga_msg
*msgp
, struct cfga_confirm
*confp
)
350 if ((a
= calloc(1, sizeof (*a
))) == NULL
)
353 if (errstring
!= NULL
)
357 a
->errstring
= errstring
;
362 if (flags
& CFGA_FLAG_LIST_ALL
)
363 ap_setopt(a
, OPT_LIST_ALL
);
364 if (flags
& CFGA_FLAG_FORCE
)
365 ap_setopt(a
, OPT_FORCE
);
366 if (flags
& CFGA_FLAG_VERBOSE
)
367 ap_setopt(a
, OPT_VERBOSE
);
369 if (ap_id
== NULL
|| ap_parse(a
, ap_id
) == 0)
377 * The type field is defined to be parsable by cfgadm(1M): It
378 * must not contain white space characters. This function
379 * converts white space to underscore.
383 parsable_strncpy(char *op
, const char *ip
, size_t n
)
398 ap_init(apd_t
*a
, cfga_list_data_t
*ap
)
402 st
= (sbd_stat_t
*)a
->stat
;
404 DBG("ap_init bd=%d rs=%d os=%d type=<%s>\n",
405 a
->bnum
, st
->s_rstate
, st
->s_ostate
, st
->s_type
);
407 parsable_strncpy(ap
->ap_type
, st
->s_type
, sizeof (ap
->ap_type
));
408 ap
->ap_r_state
= (cfga_stat_t
)st
->s_rstate
;
409 ap
->ap_o_state
= (cfga_stat_t
)st
->s_ostate
;
410 ap
->ap_cond
= (cfga_cond_t
)st
->s_cond
;
411 ap
->ap_busy
= (cfga_busy_t
)st
->s_busy
;
412 ap
->ap_status_time
= st
->s_time
;
413 ap_info(a
, ap
->ap_info
, AP_BOARD
);
423 {CMD_ASSIGN
, SBD_CMD_ASSIGN
},
424 {CMD_POWERON
, SBD_CMD_POWERON
},
425 {CMD_TEST
, SBD_CMD_TEST
},
426 {CMD_CONNECT
, SBD_CMD_CONNECT
},
427 {CMD_CONFIGURE
, SBD_CMD_CONFIGURE
},
428 {CMD_UNCONFIGURE
, SBD_CMD_UNCONFIGURE
},
429 {CMD_DISCONNECT
, SBD_CMD_DISCONNECT
},
430 {CMD_POWEROFF
, SBD_CMD_POWEROFF
},
431 {CMD_STATUS
, SBD_CMD_STATUS
},
432 {CMD_GETNCM
, SBD_CMD_GETNCM
},
433 {CMD_UNASSIGN
, SBD_CMD_UNASSIGN
},
434 {CMD_PASSTHRU
, SBD_CMD_PASSTHRU
},
443 DBG("ap_ioc(%d)\n", cmd
);
445 for (acp
= ap_iocs
; acp
->cmd
!= CMD_NONE
; acp
++)
449 DBG("ap_ioc(%d)=0x%x\n", cmd
, acp
->ioc
);
455 ap_suspend_query(apd_t
*a
, int cmd
, int *check
)
461 * See if the a quiesce operation is required for
462 * this command for any of the components. If the
463 * command does not map to an ioctl, then there is
466 if ((ioc
= ap_ioc(cmd
)) == 0)
468 else if (a
->tgt
== AP_BOARD
) {
471 dst
= ((sbd_stat_t
*)a
->stat
)->s_stat
;
474 * See if any component requires a
475 * OS suspension for this command.
477 for (i
= 0; i
< a
->ncm
; i
++, dst
++)
478 if (SBD_CHECK_SUSPEND(ioc
, dst
->ds_suspend
))
481 dst
= (sbd_dev_stat_t
*)a
->cmstat
;
482 if (SBD_CHECK_SUSPEND(ioc
, dst
->ds_suspend
))
490 ap_platopts_check(apd_t
*a
, int first
, int last
)
498 stat
= (sbd_stat_t
*)a
->stat
;
499 platopts
= stat
->s_platopts
;
503 * If there are no platform options set then there
504 * is no need to check this operation
506 if (opts
->platform
== NULL
)
510 * Check if any of the steps in the sequence
511 * allows for a platform option
513 for (c
= first
; c
<= last
; c
++)
515 * If the platopt is set it means that the platform does not
516 * support options for this cmd
518 if (SBD_CHECK_PLATOPTS(ap_ioc(c
), platopts
) == 0) {
522 ap_err(a
, ERR_OPT_INVAL
, opts
->platform
);
528 ap_ioctl(apd_t
*a
, int cmd
)
531 sbd_ioctl_arg_t
*ctl
;
533 if (a
->ctl
== NULL
&& (a
->ctl
= calloc(1, sizeof (*ctl
))) == NULL
) {
534 ap_err(a
, ERR_CMD_FAIL
, cmd
);
535 return (CFGA_LIB_ERROR
);
538 ap_msg(a
, MSG_ISSUE
, cmd
, a
->target
);
540 ctl
= (sbd_ioctl_arg_t
*)a
->ctl
;
545 if (ap_getopt(a
, OPT_FORCE
))
546 ctl
->i_flags
|= SBD_FLAG_FORCE
;
547 if (ap_getopt(a
, OPT_SUSPEND_OK
))
548 ctl
->i_flags
|= SBD_FLAG_QUIESCE_OKAY
;
550 if (a
->tgt
== AP_BOARD
)
551 ctl
->ic_type
= SBD_COMP_NONE
;
553 ctl
->ic_type
= SBD_COMP_UNKNOWN
;
554 ctl
->ic_unit
= a
->cnum
;
555 (void) strcpy(ctl
->ic_name
, a
->cname
);
558 if (!(ioc
= ap_ioc(cmd
))) {
559 ap_err(a
, ERR_CMD_FAIL
, cmd
);
560 return (CFGA_LIB_ERROR
);
564 * If this is a passthru command, pass all of its
565 * options; otherwise, pass all options after the
568 if (cmd
== CMD_PASSTHRU
)
569 ctl
->i_opts
= a
->options
;
572 * Only pass the platform option to the cmds that the platform
573 * has specified as ok
577 stat
= (sbd_stat_t
*)a
->stat
;
578 if (SBD_CHECK_PLATOPTS(ioc
, stat
->s_platopts
) == 0)
579 ctl
->i_opts
= a
->opts
.platform
;
582 if (ctl
->i_opts
!= NULL
)
583 ctl
->i_len
= strlen(ctl
->i_opts
) + 1;
585 DBG("i_opts=%s\n", ctl
->i_opts
? ctl
->i_opts
: "NULL");
586 DBG("i_flags=0x%x\n", ctl
->i_flags
);
588 if (ap_getopt(a
, OPT_SIM
)) {
589 ap_msg(a
, MSG_DONE
, cmd
, a
->target
);
593 if (ioctl(a
->fd
, ioc
, ctl
) == -1) {
594 ap_err(a
, ERR_CMD_FAIL
, cmd
);
597 ap_msg(a
, MSG_DONE
, cmd
, a
->target
);
603 * Return the error string corresponding to a given error code.
604 * String table and error code sets are provided by sbd_etab. This data
605 * structure is automatically generated at compile time from the error
606 * code and message text information in sbd_ioctl.h.
613 extern sbd_etab_t sbd_etab
[];
614 extern int sbd_etab_len
;
618 for (i
= 0; i
< sbd_etab_len
; i
++) {
619 sbd_etab_t
*eptr
= &sbd_etab
[i
];
621 if ((code
>= eptr
->t_base
) && (code
<= eptr
->t_bnd
)) {
626 * Found it. Just extract the string
628 index
= code
- eptr
->t_base
;
629 t_text
= eptr
->t_text
;
630 s
= strdup(t_text
[index
]);
635 if (i
== sbd_etab_len
) {
638 (void) snprintf(buf
, sizeof (buf
), "error %d", code
);
646 ap_sys_err(apd_t
*a
, char **rp
)
652 sbd_ioctl_arg_t
*ctl
= (sbd_ioctl_arg_t
*)a
->ctl
;
655 * The driver sets the errno to EIO if it returns
656 * more detailed error info via e_code. In all
657 * other cases, use standard error text.
659 if (ctl
== NULL
|| errno
!= EIO
) {
660 if ((p
= strerror(errno
)) != NULL
)
670 else if ((p
= strerror(errno
)) != NULL
)
673 if (*rsc
!= '\0' && rp
!= NULL
)
680 * cfgadm -o err=plugin-err,cmd=name,code=ecode -x errtest ap_id.
683 ap_test_err(apd_t
*a
, const char *options
)
692 cmd
= CMD_DISCONNECT
;
694 DBG("ap_test_err(%d %d)\n", opts
->code
, opts
->err
);
698 ap_err(a
, err
, ap_cmd_name(cmd
));
700 case ERR_CMD_NOTSUPP
:
705 ctl
.i_err
.e_code
= opts
->code
;
706 *ctl
.i_err
.e_rsc
= '\0';
712 ap_err(a
, err
, options
);
715 ap_err(a
, err
, options
);
721 ap_err(a
, err
, a
->cid
);
723 case ERR_TRANS_INVAL
:
724 ap_err(a
, ERR_TRANS_INVAL
, cmd
);
728 return (CFGA_LIB_ERROR
);
733 "\nSbd specific commands/options:\n\n",
734 "\tcfgadm [-o parsable] -l ap_id\n",
735 "\tcfgadm [-o unassign|nopoweroff] -c disconnect ap_id\n",
736 "\tcfgadm -t ap_id\n",
737 "\tcfgadm -x assign ap_id\n",
738 "\tcfgadm -x unassign ap_id\n",
739 "\tcfgadm -x poweron ap_id\n",
740 "\tcfgadm -x poweroff ap_id\n",
746 ap_help(struct cfga_msg
*msgp
, const char *options
, cfga_flags_t flags
)
752 if (msgp
== NULL
|| msgp
->message_routine
== NULL
)
755 for (p
= ap_help_topics
; *p
!= NULL
; p
++) {
756 if ((len
= strlen(*p
)) == 0)
758 if ((q
= (char *)calloc(len
+ 1, 1)) == NULL
)
760 (void) strcpy(q
, *p
);
761 (*msgp
->message_routine
)(msgp
->appdata_ptr
, q
);
769 ap_dev_type(sbd_dev_stat_t
*dst
)
773 switch (dst
->ds_type
) {
791 DBG("ap_dev_type(%d)=%s\n", dst
->ds_type
, type
);
796 static sbd_dev_stat_t
*
797 ap_cm_stat(apd_t
*a
, int seq
)
804 st
= (sbd_stat_t
*)a
->stat
;
805 return (st
->s_stat
+ seq
);
809 ap_cm_devpath(apd_t
*a
, int seq
)
818 * If no component sequence number is provided
819 * default to the current target component.
820 * Assume an io component so that we can get
821 * the path if the component is indeed of type io.
824 dst
= (sbd_io_stat_t
*)a
->cmstat
;
827 st
= (sbd_stat_t
*)a
->stat
;
828 dst
= (sbd_io_stat_t
*)st
->s_stat
+ seq
;
831 if (dst
->is_type
!= SBD_COMP_IO
)
834 path
= dst
->is_pathname
;
836 if (str_valid(path
)) {
837 len
= strlen(DEVDIR
) + strlen(path
) + 1;
839 if ((devpath
= calloc(1, len
)) == NULL
)
842 (void) snprintf(devpath
, len
, "%s%s", DEVDIR
, path
);
846 DBG("ap_cm_path(%d)=%s\n", seq
, devpath
? devpath
: "");
852 ap_cm_id(apd_t
*a
, int seq
, char *id
, size_t bufsize
)
858 dst
= ap_cm_stat(a
, seq
);
864 * If the component has a unit number,
865 * add it to the id, otherwise just use
866 * the component's name.
869 (void) snprintf(id
, bufsize
, "%s", name
);
871 (void) snprintf(id
, bufsize
, "%s%d", name
, unit
);
873 DBG("ap_cm_id(%d)=%s\n", seq
, id
);
877 * Convert a component to a target type.
880 ap_cm_type(apd_t
*a
, int seq
)
885 dst
= ap_cm_stat(a
, seq
);
887 switch (dst
->ds_type
) {
909 ap_cm_ncap(apd_t
*a
, int seq
)
914 dst
= ap_cm_stat(a
, seq
);
916 switch (dst
->ds_type
) {
923 ncap
= ((sbd_cmp_stat_t
*)dst
)->ps_ncores
;
934 ap_cm_capacity(apd_t
*a
, int seq
, void *cap
, int *ncap
, cfga_stat_t
*ostate
)
943 dst
= ap_cm_stat(a
, seq
);
944 os
= (cfga_stat_t
)dst
->ds_ostate
;
945 if (os
!= CFGA_STAT_CONFIGURED
&& os
!= CFGA_STAT_UNCONFIGURED
)
952 switch (dst
->ds_type
) {
954 sbd_cpu_stat_t
*cpu
= (sbd_cpu_stat_t
*)dst
;
955 *((processorid_t
*)cap
) = cpu
->cs_cpuid
;
959 sbd_mem_stat_t
*mem
= (sbd_mem_stat_t
*)dst
;
960 *((long *)cap
) = mem
->ms_totpages
;
964 sbd_cmp_stat_t
*cmp
= (sbd_cmp_stat_t
*)dst
;
965 processorid_t
*cpuid
;
967 cpuid
= (processorid_t
*)cap
;
968 for (i
= 0; i
< cmp
->ps_ncores
; i
++) {
969 cpuid
[i
] = cmp
->ps_cpuid
[i
];
972 *ncap
= cmp
->ps_ncores
;
979 DBG("ap_cm_capacity(%d)=(", seq
);
980 for (i
= 0; i
< *ncap
; i
++) {
981 DBG("%d ", ((int *)cap
)[i
]);
983 DBG("%d)\n", *ostate
);
989 ap_cm_init(apd_t
*a
, cfga_list_data_t
*ap
, int seq
)
995 st
= (sbd_stat_t
*)a
->stat
;
996 dst
= st
->s_stat
+ seq
;
997 type
= ap_dev_type(dst
);
999 a
->cmstat
= (void *)dst
;
1001 DBG("ap_cm_init bd=%d rs=%d os=%d type=<%s> seq=%d\n",
1002 a
->bnum
, st
->s_rstate
, dst
->ds_ostate
, type
, seq
);
1004 (void) strncpy(ap
->ap_type
, type
, sizeof (ap
->ap_type
));
1005 ap
->ap_r_state
= (cfga_stat_t
)st
->s_rstate
;
1006 ap
->ap_o_state
= (cfga_stat_t
)dst
->ds_ostate
;
1007 ap
->ap_cond
= (cfga_cond_t
)dst
->ds_cond
;
1008 ap
->ap_busy
= (cfga_busy_t
)dst
->ds_busy
;
1009 ap
->ap_status_time
= dst
->ds_time
;
1010 ap_info(a
, ap
->ap_info
, ap_cm_tgt(dst
->ds_type
));
1014 ap_state(apd_t
*a
, cfga_stat_t
*rs
, cfga_stat_t
*os
)
1017 sbd_dev_stat_t
*dst
;
1019 st
= (sbd_stat_t
*)a
->stat
;
1020 dst
= (sbd_dev_stat_t
*)a
->cmstat
;
1023 if (a
->tgt
== AP_NONE
)
1024 *rs
= CFGA_STAT_NONE
;
1026 *rs
= (cfga_stat_t
)st
->s_rstate
;
1030 if (a
->tgt
== AP_NONE
)
1031 *os
= CFGA_STAT_NONE
;
1032 else if (a
->tgt
== AP_BOARD
)
1033 *os
= (cfga_stat_t
)st
->s_ostate
;
1035 *os
= (cfga_stat_t
)dst
->ds_ostate
;
1039 #define BI_POWERED 0
1040 #define BI_ASSIGNED 1
1049 binfo_parsable
[] = {
1055 bd_info(apd_t
*a
, cfga_info_t info
, int parsable
)
1061 char *end
= &info
[sizeof (cfga_info_t
)];
1063 DBG("bd_info(%p)\n", (void *)info
);
1065 st
= (sbd_stat_t
*)a
->stat
;
1078 info
+= snprintf(info
, end
- info
, p
[BI_POWERED
]);
1082 info
+= snprintf(info
, end
- info
, p
[BI_ASSIGNED
] + i
);
1093 ", ecache %d MBytes"
1097 cpuinfo_parsable
[] = {
1104 cpu_info(apd_t
*a
, cfga_info_t info
, int parsable
)
1107 sbd_cpu_stat_t
*dst
;
1108 char *end
= &info
[sizeof (cfga_info_t
)];
1110 DBG("cpu_info(%p)\n", (void *)info
);
1112 dst
= (sbd_cpu_stat_t
*)a
->cmstat
;
1115 p
= cpuinfo_parsable
;
1119 info
+= snprintf(info
, end
- info
, p
[CI_CPUID
], dst
->cs_cpuid
);
1120 info
+= snprintf(info
, end
- info
, p
[CI_SPEED
], dst
->cs_speed
);
1121 info
+= snprintf(info
, end
- info
, p
[CI_ECACHE
], dst
->cs_ecache
);
1124 #define MI_ADDRESS 0
1126 #define MI_PERMANENT 2
1127 #define MI_UNCONFIGURABLE 3
1130 #define MI_DELETED 6
1131 #define MI_REMAINING 7
1132 #define MI_INTERLEAVE 8
1135 meminfo_nonparsable
[] = {
1136 "base address 0x%" PRIx64
,
1137 ", %lu KBytes total",
1138 ", %lu KBytes permanent",
1140 ", memory delete requested on %s",
1141 ", memory delete in progress on %s",
1142 ", %lu KBytes deleted",
1143 ", %lu KBytes remaining",
1144 ", inter board interleave"
1148 meminfo_parsable
[] = {
1149 "address=0x%" PRIx64
,
1157 " inter-board-interleave"
1164 * This function assumes pagesize > 1024 and that
1165 * pagesize is a multiple of 1024.
1168 pages_to_kbytes(uint_t pgs
)
1172 pagesize
= sysconf(_SC_PAGESIZE
);
1173 return (pgs
* (pagesize
/ _K1
));
1177 pages_to_bytes(uint_t pgs
)
1181 pagesize
= sysconf(_SC_PAGESIZE
);
1182 return ((uint64_t)pgs
* pagesize
);
1186 mem_info(apd_t
*a
, cfga_info_t info
, int parsable
)
1189 sbd_mem_stat_t
*dst
;
1191 char *end
= &info
[sizeof (cfga_info_t
)];
1193 DBG("mem_info(%p)\n", (void *)info
);
1195 dst
= (sbd_mem_stat_t
*)a
->cmstat
;
1198 p
= meminfo_parsable
;
1200 p
= meminfo_nonparsable
;
1202 info
+= snprintf(info
, end
- info
, p
[MI_ADDRESS
],
1203 pages_to_bytes(dst
->ms_basepfn
));
1204 info
+= snprintf(info
, end
- info
, p
[MI_SIZE
],
1205 pages_to_kbytes(dst
->ms_totpages
));
1207 if (dst
->ms_noreloc_pages
)
1208 info
+= snprintf(info
, end
- info
, p
[MI_PERMANENT
],
1209 pages_to_kbytes(dst
->ms_noreloc_pages
));
1210 if (!dst
->ms_cage_enabled
)
1211 info
+= snprintf(info
, end
- info
, p
[MI_UNCONFIGURABLE
]);
1212 if (dst
->ms_interleave
)
1213 info
+= snprintf(info
, end
- info
, p
[MI_INTERLEAVE
]);
1216 * If there is a valid peer physical ap_id specified,
1217 * convert it to a logical id.
1220 if (str_valid(dst
->ms_peer_ap_id
)) {
1223 char physid
[MAXPATHLEN
];
1224 char logid
[MAXPATHLEN
];
1226 (void) snprintf(physid
, sizeof (physid
), "%s%s",
1227 DEVDIR
, dst
->ms_peer_ap_id
);
1230 * Save the component portion of the physid and
1231 * add it back after converting to logical format.
1233 if ((cm
= strstr(physid
, "::")) != NULL
) {
1238 /* attempt to resolve to symlink */
1239 if (ap_symid(a
, physid
, logid
, sizeof (logid
)) == 0)
1244 if (dst
->ms_peer_is_target
) {
1245 info
+= snprintf(info
, end
- info
, p
[MI_TARGET
], peer
);
1247 info
+= snprintf(info
, end
- info
, "::%s", cm
);
1250 info
+= snprintf(info
, end
- info
, p
[MI_SOURCE
], peer
);
1252 info
+= snprintf(info
, end
- info
, "::%s", cm
);
1255 if (want_progress
||
1256 (dst
->ms_detpages
!= 0 && dst
->ms_detpages
!= dst
->ms_totpages
)) {
1257 info
+= snprintf(info
, end
- info
, p
[MI_DELETED
],
1258 pages_to_kbytes(dst
->ms_detpages
));
1259 info
+= snprintf(info
, end
- info
, p
[MI_REMAINING
],
1260 pages_to_kbytes(dst
->ms_totpages
-
1266 #define II_REFERENCED 1
1275 ioinfo_parsable
[] = {
1281 io_info(apd_t
*a
, cfga_info_t info
, int parsable
)
1285 char *end
= &info
[sizeof (cfga_info_t
)];
1287 dst
= (sbd_io_stat_t
*)a
->cmstat
;
1290 p
= ioinfo_parsable
;
1294 info
+= snprintf(info
, end
- info
, p
[II_DEVICE
], dst
->is_pathname
);
1295 if (dst
->is_referenced
)
1296 info
+= snprintf(info
, end
- info
, p
[II_REFERENCED
]);
1300 #define PI_CPUID_PAIR 1
1301 #define PI_CPUID_CONT 2
1302 #define PI_CPUID_LAST 3
1313 ", ecache %d MBytes"
1317 cmpinfo_parsable
[] = {
1327 cmp_info(apd_t
*a
, cfga_info_t info
, int parsable
)
1332 sbd_cmp_stat_t
*dst
;
1333 char *end
= &info
[sizeof (cfga_info_t
)];
1335 DBG("cmp_info(%p)\n", (void *)info
);
1337 dst
= (sbd_cmp_stat_t
*)a
->cmstat
;
1340 p
= cmpinfo_parsable
;
1344 /* Print the first cpuid */
1345 info
+= snprintf(info
, end
- info
, p
[PI_CPUID
], dst
->ps_cpuid
[0]);
1348 * Print the middle cpuids, if necessary. Stop before
1349 * the last one, since printing the last cpuid is a
1350 * special case for the non parsable form.
1352 for (i
= 1; i
< (dst
->ps_ncores
- 1); i
++) {
1353 info
+= snprintf(info
, end
- info
, p
[PI_CPUID_CONT
],
1357 /* Print the last cpuid, if necessary */
1358 if (dst
->ps_ncores
> 1) {
1359 last
= (dst
->ps_ncores
== 2) ? PI_CPUID_PAIR
: PI_CPUID_LAST
;
1360 info
+= snprintf(info
, end
- info
,
1361 dgettext(TEXT_DOMAIN
, p
[last
]), dst
->ps_cpuid
[i
]);
1364 info
+= snprintf(info
, end
- info
, p
[PI_SPEED
], dst
->ps_speed
);
1365 info
+= snprintf(info
, end
- info
, p
[PI_ECACHE
], dst
->ps_ecache
);
1369 ap_info(apd_t
*a
, cfga_info_t info
, ap_target_t tgt
)
1371 int parsable
= ap_getopt(a
, OPT_PARSABLE
);
1373 DBG("ap_info(%p, %d)\n", (void *)info
, parsable
);
1377 bd_info(a
, info
, parsable
);
1380 cpu_info(a
, info
, parsable
);
1383 mem_info(a
, info
, parsable
);
1386 io_info(a
, info
, parsable
);
1389 cmp_info(a
, info
, parsable
);