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
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.
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]
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * Implementation to get PORT nodes state and condition information
39 #include <sys/types.h>
40 #include <sys/termios.h>
46 #include <config_admin.h>
49 #include "piclfrutree.h"
51 #define LINK_UP "link_up"
52 #define DUPLEX "duplex"
53 #define IF_SPEED "ifspeed"
54 #define IERRORS "ierrors"
55 #define IPACKETS "ipackets"
56 #define OERRORS "oerrors"
57 #define OPACKETS "opackets"
58 #define NOCANPUT "nocanput"
59 #define RUNT_ERRORS "runt_errors"
60 #define COLLISIONS "collisions"
62 typedef int (*funcp
)(kstat_ctl_t
*, char *, int);
64 static kstat_named_t
*kstat_name_lookup(kstat_ctl_t
*, char *, int, char *);
65 static int kstat_network_port_state(kstat_ctl_t
*kc
, char *, int);
66 static int kstat_network_port_cond(kstat_ctl_t
*kc
, char *, int);
67 static int serial_port_state(kstat_ctl_t
*, char *, int);
68 static int serial_port_cond(kstat_ctl_t
*kc
, char *, int);
69 static int parallel_port_state(kstat_ctl_t
*, char *, int);
70 static int parallel_port_cond(kstat_ctl_t
*kc
, char *, int);
71 static void sig_alarm_handler(int);
73 static funcp port_state
[] = {
74 kstat_network_port_state
,
79 static funcp port_cond
[] = {
80 kstat_network_port_cond
,
86 * kstat_port_state: returns ethernet, or serial, or parallel port status
87 * 1 = up, 0 = down, anything else = unknown
90 kstat_port_state(frutree_port_type_t port_type
, char *driver_name
,
94 kstat_ctl_t
*kc
= NULL
;
100 if ((kc
= kstat_open()) == NULL
) {
103 rc
= port_state
[port_type
](kc
, driver_name
, driver_instance
);
112 * kstat_port_cond: returns ethernet, or serial, or parallel port condition
115 kstat_port_cond(frutree_port_type_t port_type
, char *driver_name
,
119 kstat_ctl_t
*kc
= NULL
;
124 if ((kc
= kstat_open()) == NULL
) {
127 rc
= port_cond
[port_type
](kc
, driver_name
, driver_instance
);
135 static kstat_named_t
*
136 kstat_name_lookup(kstat_ctl_t
*kc
, char *ks_module
, int ks_instance
, char *name
)
144 for (ksp
= kc
->kc_chain
; ksp
; ksp
= ksp
->ks_next
) {
145 if (strcmp(ksp
->ks_module
, ks_module
) == 0 &&
146 ksp
->ks_instance
== ks_instance
&&
147 ksp
->ks_type
== KSTAT_TYPE_NAMED
&&
148 kstat_read(kc
, ksp
, NULL
) != -1 &&
149 kstat_data_lookup(ksp
, name
)) {
151 ksp
= kstat_lookup(kc
, ks_module
, ks_instance
,
155 if (kstat_read(kc
, ksp
, NULL
) == -1)
157 return ((kstat_named_t
*)kstat_data_lookup(ksp
, name
));
164 * kstat_network_port_state: returns kstat info of a network port
165 * 1 = up, 0 = down, anything else = unknown
168 kstat_network_port_state(kstat_ctl_t
*kc
, char *ks_module
, int ks_instance
)
170 kstat_named_t
*port_datap
= NULL
;
172 if ((port_datap
= kstat_name_lookup(kc
, ks_module
, ks_instance
,
176 if (port_datap
== NULL
) {
179 if (port_datap
->data_type
== KSTAT_DATA_UINT32
) {
180 if (port_datap
->value
.ui32
== 1) {
182 } else if (port_datap
->value
.ui32
== 0) {
188 if (port_datap
->value
.ui64
== 1) {
190 } else if (port_datap
->value
.ui64
== 0) {
199 * kstat_network_port_cond: returns kstat info of a network port
200 * 0 = OK, 1 = FAILING, 2 = FAILED, 3 = TESTING, -1 = unknown
203 kstat_network_port_cond(kstat_ctl_t
*kc
, char *ks_module
, int ks_instance
)
205 kstat_named_t
*port_datap
= NULL
;
206 uint64_t collisions
, runt
, link_up
, link_duplex
;
207 uint64_t ifspeed
, ierrors
, ipackets
, oerrors
, opackets
;
209 if ((port_datap
= kstat_name_lookup(kc
, ks_module
, ks_instance
,
214 if (port_datap
->data_type
== KSTAT_DATA_UINT32
) {
215 link_up
= port_datap
->value
.ui32
;
217 link_up
= port_datap
->value
.ui64
;
223 if ((port_datap
= kstat_name_lookup(kc
, ks_module
, ks_instance
,
228 if (port_datap
->data_type
== KSTAT_DATA_UINT32
) {
229 link_duplex
= port_datap
->value
.ui32
;
231 link_duplex
= port_datap
->value
.ui64
;
233 if (link_duplex
== 0) {
237 if ((port_datap
= kstat_name_lookup(kc
, ks_module
, ks_instance
,
238 IF_SPEED
)) == NULL
) {
241 if (port_datap
->data_type
== KSTAT_DATA_UINT32
) {
242 ifspeed
= port_datap
->value
.ui32
;
244 ifspeed
= port_datap
->value
.ui64
;
250 /* check for FAILING conditions */
251 if ((port_datap
= kstat_name_lookup(kc
, ks_module
, ks_instance
,
255 if (port_datap
->data_type
== KSTAT_DATA_UINT32
) {
256 ierrors
= port_datap
->value
.ui32
;
258 ierrors
= port_datap
->value
.ui64
;
261 if ((port_datap
= kstat_name_lookup(kc
, ks_module
, ks_instance
,
262 IPACKETS
)) == NULL
) {
266 if (port_datap
->data_type
== KSTAT_DATA_UINT32
) {
267 ipackets
= port_datap
->value
.ui32
;
269 ipackets
= port_datap
->value
.ui64
;
271 if (ierrors
> ipackets
/10) {
275 if ((port_datap
= kstat_name_lookup(kc
, ks_module
, ks_instance
,
279 if (port_datap
->data_type
== KSTAT_DATA_UINT32
) {
280 oerrors
= port_datap
->value
.ui32
;
282 oerrors
= port_datap
->value
.ui64
;
285 if ((port_datap
= kstat_name_lookup(kc
, ks_module
, ks_instance
,
286 OPACKETS
)) == NULL
) {
289 if (port_datap
->data_type
== KSTAT_DATA_UINT32
) {
290 opackets
= port_datap
->value
.ui32
;
292 opackets
= port_datap
->value
.ui64
;
294 if (oerrors
> opackets
/10) {
298 if ((port_datap
= kstat_name_lookup(kc
, ks_module
, ks_instance
,
299 RUNT_ERRORS
)) == NULL
) {
302 if (port_datap
->data_type
== KSTAT_DATA_UINT32
) {
303 runt
= port_datap
->value
.ui32
;
305 runt
= port_datap
->value
.ui64
;
307 if (runt
> ipackets
/10) {
311 if ((port_datap
= kstat_name_lookup(kc
, ks_module
, ks_instance
,
312 COLLISIONS
)) == NULL
) {
315 if (port_datap
->data_type
== KSTAT_DATA_UINT32
) {
316 collisions
= port_datap
->value
.ui32
;
318 collisions
= port_datap
->value
.ui64
;
320 if (collisions
> (opackets
+ipackets
)/30) {
327 * serial_port_state: returns status a serial port
328 * 1 = up, 0 = down, anything else = unknown
333 serial_port_state(kstat_ctl_t
*kc
, char *driver
, int instance
)
337 struct termios flags
;
338 struct sigaction old_sa
, new_sa
;
340 (void) memset(&old_sa
, 0, sizeof (old_sa
));
341 (void) memset(&new_sa
, 0, sizeof (new_sa
));
342 new_sa
.sa_handler
= sig_alarm_handler
;
343 (void) sigaction(SIGALRM
, &new_sa
, &old_sa
);
346 (void) snprintf(device
, sizeof (device
), "/dev/tty%c", instance
+'a');
347 fd
= open(device
, O_RDONLY
|O_NDELAY
|O_NONBLOCK
|O_NOCTTY
);
349 /* Restore sig action flags */
350 (void) sigaction(SIGALRM
, &old_sa
, (struct sigaction
*)0);
358 if (isatty(fd
) == 0) {
362 (void) memset(&flags
, 0, sizeof (flags
));
363 if (ioctl(fd
, TCGETS
, &flags
) != 0) {
368 return ((flags
.c_cflag
& TIOCM_LE
) ? 1 : 0);
373 sig_alarm_handler(int signo
)
378 * serial_port_cond: returns status of a serial port
379 * 0 = OK, 1 = FAILING, 2 = FAILED, 3 = TESTING, anything else = UNKNOWN
382 serial_port_cond(kstat_ctl_t
*kc
, char *driver
, int instance
)
384 switch (serial_port_state(kc
, driver
, instance
)) {
393 * parallel_port_state: returns kstat info of a serial port
394 * 1 = up, 0 = down, anything else = unknown
397 parallel_port_state(kstat_ctl_t
*kc
, char *ks_module
, int ks_instance
)
400 kstat_named_t
*port_datap
= NULL
;
404 (void) snprintf(ks_name
, sizeof (ks_name
), "%s%d", ks_module
,
406 if ((ksp
= kstat_lookup(kc
, ks_module
, ks_instance
, ks_name
)) == NULL
) {
409 if (kstat_read(kc
, ksp
, NULL
) == -1) {
413 port_datap
= (kstat_named_t
*)kstat_data_lookup(ksp
, data_lookup
);
414 if (port_datap
== NULL
) {
421 * parallel_port_cond: returns kstat info of a serial port
422 * 1 = up, 0 = down, anything else = unknown
425 parallel_port_cond(kstat_ctl_t
*kc
, char *ks_module
, int ks_instance
)
427 return (parallel_port_state(kc
, ks_module
, ks_instance
));