1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate /*
30*0Sstevel@tonic-gate  * Implementation to get PORT nodes state and condition information
31*0Sstevel@tonic-gate  */
32*0Sstevel@tonic-gate #include <stdio.h>
33*0Sstevel@tonic-gate #include <stdlib.h>
34*0Sstevel@tonic-gate #include <ctype.h>
35*0Sstevel@tonic-gate #include <strings.h>
36*0Sstevel@tonic-gate #include <fcntl.h>
37*0Sstevel@tonic-gate #include <unistd.h>
38*0Sstevel@tonic-gate #include <stropts.h>
39*0Sstevel@tonic-gate #include <locale.h>
40*0Sstevel@tonic-gate #include <syslog.h>
41*0Sstevel@tonic-gate #include <sys/types.h>
42*0Sstevel@tonic-gate #include <sys/termios.h>
43*0Sstevel@tonic-gate #include <sys/stat.h>
44*0Sstevel@tonic-gate #include <fcntl.h>
45*0Sstevel@tonic-gate #include <kstat.h>
46*0Sstevel@tonic-gate #include <signal.h>
47*0Sstevel@tonic-gate #include <assert.h>
48*0Sstevel@tonic-gate #include <config_admin.h>
49*0Sstevel@tonic-gate 
50*0Sstevel@tonic-gate #include <picl.h>
51*0Sstevel@tonic-gate #include "piclfrutree.h"
52*0Sstevel@tonic-gate 
53*0Sstevel@tonic-gate #define	LINK_UP 	"link_up"
54*0Sstevel@tonic-gate #define	DUPLEX		"duplex"
55*0Sstevel@tonic-gate #define	IF_SPEED	"ifspeed"
56*0Sstevel@tonic-gate #define	IERRORS		"ierrors"
57*0Sstevel@tonic-gate #define	IPACKETS	"ipackets"
58*0Sstevel@tonic-gate #define	OERRORS		"oerrors"
59*0Sstevel@tonic-gate #define	OPACKETS	"opackets"
60*0Sstevel@tonic-gate #define	NOCANPUT	"nocanput"
61*0Sstevel@tonic-gate #define	RUNT_ERRORS	"runt_errors"
62*0Sstevel@tonic-gate #define	COLLISIONS	"collisions"
63*0Sstevel@tonic-gate 
64*0Sstevel@tonic-gate typedef int (*funcp)(kstat_ctl_t *, char *, int);
65*0Sstevel@tonic-gate 
66*0Sstevel@tonic-gate static kstat_named_t *kstat_name_lookup(kstat_ctl_t *, char *, int, char *);
67*0Sstevel@tonic-gate static int kstat_network_port_state(kstat_ctl_t *kc, char *, int);
68*0Sstevel@tonic-gate static int kstat_network_port_cond(kstat_ctl_t *kc, char *, int);
69*0Sstevel@tonic-gate static int serial_port_state(kstat_ctl_t *, char *, int);
70*0Sstevel@tonic-gate static int serial_port_cond(kstat_ctl_t *kc, char *, int);
71*0Sstevel@tonic-gate static int parallel_port_state(kstat_ctl_t *, char *, int);
72*0Sstevel@tonic-gate static int parallel_port_cond(kstat_ctl_t *kc, char *, int);
73*0Sstevel@tonic-gate 
74*0Sstevel@tonic-gate static funcp port_state[] = {
75*0Sstevel@tonic-gate 	kstat_network_port_state,
76*0Sstevel@tonic-gate 	serial_port_state,
77*0Sstevel@tonic-gate 	parallel_port_state
78*0Sstevel@tonic-gate };
79*0Sstevel@tonic-gate 
80*0Sstevel@tonic-gate static funcp port_cond[] = {
81*0Sstevel@tonic-gate 	kstat_network_port_cond,
82*0Sstevel@tonic-gate 	serial_port_cond,
83*0Sstevel@tonic-gate 	parallel_port_cond
84*0Sstevel@tonic-gate };
85*0Sstevel@tonic-gate 
86*0Sstevel@tonic-gate /*
87*0Sstevel@tonic-gate  * kstat_port_state: returns ethernet, or serial, or parallel port status
88*0Sstevel@tonic-gate  * 1 = up, 0 = down, anything else = unknown
89*0Sstevel@tonic-gate  */
90*0Sstevel@tonic-gate int
kstat_port_state(frutree_port_type_t port_type,char * driver_name,int driver_instance)91*0Sstevel@tonic-gate kstat_port_state(frutree_port_type_t port_type, char *driver_name,
92*0Sstevel@tonic-gate 	int driver_instance)
93*0Sstevel@tonic-gate {
94*0Sstevel@tonic-gate 	int rc = -1;
95*0Sstevel@tonic-gate 	kstat_ctl_t	*kc = NULL;
96*0Sstevel@tonic-gate 
97*0Sstevel@tonic-gate 	switch (port_type) {
98*0Sstevel@tonic-gate 	case NETWORK_PORT:
99*0Sstevel@tonic-gate 	case SERIAL_PORT:
100*0Sstevel@tonic-gate 	case PARALLEL_PORT:
101*0Sstevel@tonic-gate 		if ((kc = kstat_open()) == NULL) {
102*0Sstevel@tonic-gate 			return (-1);
103*0Sstevel@tonic-gate 		}
104*0Sstevel@tonic-gate 		rc = port_state[port_type](kc, driver_name, driver_instance);
105*0Sstevel@tonic-gate 		kstat_close(kc);
106*0Sstevel@tonic-gate 		return (rc);
107*0Sstevel@tonic-gate 	default:
108*0Sstevel@tonic-gate 		return (-1);
109*0Sstevel@tonic-gate 	}
110*0Sstevel@tonic-gate }
111*0Sstevel@tonic-gate 
112*0Sstevel@tonic-gate /*
113*0Sstevel@tonic-gate  * kstat_port_cond: returns ethernet, or serial, or parallel port condition
114*0Sstevel@tonic-gate  */
115*0Sstevel@tonic-gate int
kstat_port_cond(frutree_port_type_t port_type,char * driver_name,int driver_instance)116*0Sstevel@tonic-gate kstat_port_cond(frutree_port_type_t port_type, char *driver_name,
117*0Sstevel@tonic-gate 	int driver_instance)
118*0Sstevel@tonic-gate {
119*0Sstevel@tonic-gate 	int rc = -1;
120*0Sstevel@tonic-gate 	kstat_ctl_t	*kc = NULL;
121*0Sstevel@tonic-gate 	switch (port_type) {
122*0Sstevel@tonic-gate 	case NETWORK_PORT:
123*0Sstevel@tonic-gate 	case SERIAL_PORT:
124*0Sstevel@tonic-gate 	case PARALLEL_PORT:
125*0Sstevel@tonic-gate 		if ((kc = kstat_open()) == NULL) {
126*0Sstevel@tonic-gate 			return (-1);
127*0Sstevel@tonic-gate 		}
128*0Sstevel@tonic-gate 		rc = port_cond[port_type](kc, driver_name, driver_instance);
129*0Sstevel@tonic-gate 		kstat_close(kc);
130*0Sstevel@tonic-gate 		return (rc);
131*0Sstevel@tonic-gate 	default:
132*0Sstevel@tonic-gate 		return (-1);
133*0Sstevel@tonic-gate 	}
134*0Sstevel@tonic-gate }
135*0Sstevel@tonic-gate 
136*0Sstevel@tonic-gate static kstat_named_t *
kstat_name_lookup(kstat_ctl_t * kc,char * ks_module,int ks_instance,char * name)137*0Sstevel@tonic-gate kstat_name_lookup(kstat_ctl_t *kc, char *ks_module, int ks_instance, char *name)
138*0Sstevel@tonic-gate {
139*0Sstevel@tonic-gate 	kstat_t		*ksp;
140*0Sstevel@tonic-gate 
141*0Sstevel@tonic-gate 	assert(kc);
142*0Sstevel@tonic-gate 	assert(ks_module);
143*0Sstevel@tonic-gate 	assert(name);
144*0Sstevel@tonic-gate 
145*0Sstevel@tonic-gate 	for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
146*0Sstevel@tonic-gate 		if (strcmp(ksp->ks_module, ks_module) == 0 &&
147*0Sstevel@tonic-gate 			ksp->ks_instance == ks_instance &&
148*0Sstevel@tonic-gate 			ksp->ks_type == KSTAT_TYPE_NAMED &&
149*0Sstevel@tonic-gate 			kstat_read(kc, ksp, NULL) != -1 &&
150*0Sstevel@tonic-gate 			kstat_data_lookup(ksp, name)) {
151*0Sstevel@tonic-gate 
152*0Sstevel@tonic-gate 			ksp = kstat_lookup(kc, ks_module, ks_instance,
153*0Sstevel@tonic-gate 				ksp->ks_name);
154*0Sstevel@tonic-gate 			if (!ksp)
155*0Sstevel@tonic-gate 				return (NULL);
156*0Sstevel@tonic-gate 			if (kstat_read(kc, ksp, NULL) == -1)
157*0Sstevel@tonic-gate 				return (NULL);
158*0Sstevel@tonic-gate 			return ((kstat_named_t *)kstat_data_lookup(ksp, name));
159*0Sstevel@tonic-gate 		}
160*0Sstevel@tonic-gate 	}
161*0Sstevel@tonic-gate 	return (NULL);
162*0Sstevel@tonic-gate }
163*0Sstevel@tonic-gate 
164*0Sstevel@tonic-gate /*
165*0Sstevel@tonic-gate  * kstat_network_port_state: returns kstat info of a network port
166*0Sstevel@tonic-gate  * 1 = up, 0 = down, anything else = unknown
167*0Sstevel@tonic-gate  */
168*0Sstevel@tonic-gate static int
kstat_network_port_state(kstat_ctl_t * kc,char * ks_module,int ks_instance)169*0Sstevel@tonic-gate kstat_network_port_state(kstat_ctl_t *kc, char *ks_module, int ks_instance)
170*0Sstevel@tonic-gate {
171*0Sstevel@tonic-gate 	kstat_named_t	*port_datap = NULL;
172*0Sstevel@tonic-gate 
173*0Sstevel@tonic-gate 	if ((port_datap = kstat_name_lookup(kc, ks_module, ks_instance,
174*0Sstevel@tonic-gate 		LINK_UP)) == NULL) {
175*0Sstevel@tonic-gate 		return (-1);
176*0Sstevel@tonic-gate 	}
177*0Sstevel@tonic-gate 	if (port_datap == NULL) {
178*0Sstevel@tonic-gate 		return (-1);
179*0Sstevel@tonic-gate 	}
180*0Sstevel@tonic-gate 	if (port_datap->data_type == KSTAT_DATA_UINT32) {
181*0Sstevel@tonic-gate 		if (port_datap->value.ui32 == 1) {
182*0Sstevel@tonic-gate 			return (1);
183*0Sstevel@tonic-gate 		} else if (port_datap->value.ui32 == 0) {
184*0Sstevel@tonic-gate 			return (0);
185*0Sstevel@tonic-gate 		} else {
186*0Sstevel@tonic-gate 			return (-1);
187*0Sstevel@tonic-gate 		}
188*0Sstevel@tonic-gate 	} else {
189*0Sstevel@tonic-gate 		if (port_datap->value.ui64 == 1) {
190*0Sstevel@tonic-gate 			return (1);
191*0Sstevel@tonic-gate 		} else if (port_datap->value.ui64 == 0) {
192*0Sstevel@tonic-gate 			return (0);
193*0Sstevel@tonic-gate 		} else {
194*0Sstevel@tonic-gate 			return (-1);
195*0Sstevel@tonic-gate 		}
196*0Sstevel@tonic-gate 	}
197*0Sstevel@tonic-gate }
198*0Sstevel@tonic-gate 
199*0Sstevel@tonic-gate /*
200*0Sstevel@tonic-gate  * kstat_network_port_cond: returns kstat info of a network port
201*0Sstevel@tonic-gate  * 0 = OK, 1 = FAILING, 2 = FAILED, 3 = TESTING, -1 = unknown
202*0Sstevel@tonic-gate  */
203*0Sstevel@tonic-gate static int
kstat_network_port_cond(kstat_ctl_t * kc,char * ks_module,int ks_instance)204*0Sstevel@tonic-gate kstat_network_port_cond(kstat_ctl_t *kc, char *ks_module, int ks_instance)
205*0Sstevel@tonic-gate {
206*0Sstevel@tonic-gate 	kstat_named_t	*port_datap = NULL;
207*0Sstevel@tonic-gate 	uint64_t	collisions, runt, link_up, link_duplex;
208*0Sstevel@tonic-gate 	uint64_t	ifspeed, ierrors, ipackets, oerrors, opackets;
209*0Sstevel@tonic-gate 
210*0Sstevel@tonic-gate 	if ((port_datap = kstat_name_lookup(kc, ks_module, ks_instance,
211*0Sstevel@tonic-gate 		LINK_UP)) == NULL) {
212*0Sstevel@tonic-gate 		return (-1);
213*0Sstevel@tonic-gate 	}
214*0Sstevel@tonic-gate 
215*0Sstevel@tonic-gate 	if (port_datap->data_type == KSTAT_DATA_UINT32) {
216*0Sstevel@tonic-gate 		link_up = port_datap->value.ui32;
217*0Sstevel@tonic-gate 	} else {
218*0Sstevel@tonic-gate 		link_up = port_datap->value.ui64;
219*0Sstevel@tonic-gate 	}
220*0Sstevel@tonic-gate 	if (link_up == 0) {
221*0Sstevel@tonic-gate 		return (2);
222*0Sstevel@tonic-gate 	}
223*0Sstevel@tonic-gate 
224*0Sstevel@tonic-gate 	if ((port_datap = kstat_name_lookup(kc, ks_module, ks_instance,
225*0Sstevel@tonic-gate 		DUPLEX)) == NULL) {
226*0Sstevel@tonic-gate 		return (-1);
227*0Sstevel@tonic-gate 	}
228*0Sstevel@tonic-gate 
229*0Sstevel@tonic-gate 	if (port_datap->data_type == KSTAT_DATA_UINT32) {
230*0Sstevel@tonic-gate 		link_duplex = port_datap->value.ui32;
231*0Sstevel@tonic-gate 	} else {
232*0Sstevel@tonic-gate 		link_duplex = port_datap->value.ui64;
233*0Sstevel@tonic-gate 	}
234*0Sstevel@tonic-gate 	if (link_duplex == 0) {
235*0Sstevel@tonic-gate 		return (2);
236*0Sstevel@tonic-gate 	}
237*0Sstevel@tonic-gate 
238*0Sstevel@tonic-gate 	if ((port_datap = kstat_name_lookup(kc, ks_module, ks_instance,
239*0Sstevel@tonic-gate 		IF_SPEED)) == NULL) {
240*0Sstevel@tonic-gate 		return (-1);
241*0Sstevel@tonic-gate 	}
242*0Sstevel@tonic-gate 	if (port_datap->data_type == KSTAT_DATA_UINT32) {
243*0Sstevel@tonic-gate 		ifspeed = port_datap->value.ui32;
244*0Sstevel@tonic-gate 	} else {
245*0Sstevel@tonic-gate 		ifspeed = port_datap->value.ui64;
246*0Sstevel@tonic-gate 	}
247*0Sstevel@tonic-gate 	if (ifspeed == 0) {
248*0Sstevel@tonic-gate 		return (2);
249*0Sstevel@tonic-gate 	}
250*0Sstevel@tonic-gate 
251*0Sstevel@tonic-gate 	/* check for FAILING conditions */
252*0Sstevel@tonic-gate 	if ((port_datap = kstat_name_lookup(kc, ks_module, ks_instance,
253*0Sstevel@tonic-gate 		IERRORS)) == NULL) {
254*0Sstevel@tonic-gate 		return (-1);
255*0Sstevel@tonic-gate 	}
256*0Sstevel@tonic-gate 	if (port_datap->data_type == KSTAT_DATA_UINT32) {
257*0Sstevel@tonic-gate 		ierrors = port_datap->value.ui32;
258*0Sstevel@tonic-gate 	} else {
259*0Sstevel@tonic-gate 		ierrors = port_datap->value.ui64;
260*0Sstevel@tonic-gate 	}
261*0Sstevel@tonic-gate 
262*0Sstevel@tonic-gate 	if ((port_datap = kstat_name_lookup(kc, ks_module, ks_instance,
263*0Sstevel@tonic-gate 		IPACKETS)) == NULL) {
264*0Sstevel@tonic-gate 		return (-1);
265*0Sstevel@tonic-gate 	}
266*0Sstevel@tonic-gate 
267*0Sstevel@tonic-gate 	if (port_datap->data_type == KSTAT_DATA_UINT32) {
268*0Sstevel@tonic-gate 		ipackets = port_datap->value.ui32;
269*0Sstevel@tonic-gate 	} else {
270*0Sstevel@tonic-gate 		ipackets = port_datap->value.ui64;
271*0Sstevel@tonic-gate 	}
272*0Sstevel@tonic-gate 	if (ierrors > ipackets/10) {
273*0Sstevel@tonic-gate 		return (1);
274*0Sstevel@tonic-gate 	}
275*0Sstevel@tonic-gate 
276*0Sstevel@tonic-gate 	if ((port_datap = kstat_name_lookup(kc, ks_module, ks_instance,
277*0Sstevel@tonic-gate 		OERRORS)) == NULL) {
278*0Sstevel@tonic-gate 		return (-1);
279*0Sstevel@tonic-gate 	}
280*0Sstevel@tonic-gate 	if (port_datap->data_type == KSTAT_DATA_UINT32) {
281*0Sstevel@tonic-gate 		oerrors = port_datap->value.ui32;
282*0Sstevel@tonic-gate 	} else {
283*0Sstevel@tonic-gate 		oerrors = port_datap->value.ui64;
284*0Sstevel@tonic-gate 	}
285*0Sstevel@tonic-gate 
286*0Sstevel@tonic-gate 	if ((port_datap = kstat_name_lookup(kc, ks_module, ks_instance,
287*0Sstevel@tonic-gate 		OPACKETS)) == NULL) {
288*0Sstevel@tonic-gate 		return (-1);
289*0Sstevel@tonic-gate 	}
290*0Sstevel@tonic-gate 	if (port_datap->data_type == KSTAT_DATA_UINT32) {
291*0Sstevel@tonic-gate 		opackets = port_datap->value.ui32;
292*0Sstevel@tonic-gate 	} else {
293*0Sstevel@tonic-gate 		opackets = port_datap->value.ui64;
294*0Sstevel@tonic-gate 	}
295*0Sstevel@tonic-gate 	if (oerrors > opackets/10) {
296*0Sstevel@tonic-gate 		return (1);
297*0Sstevel@tonic-gate 	}
298*0Sstevel@tonic-gate 
299*0Sstevel@tonic-gate 	if ((port_datap = kstat_name_lookup(kc, ks_module, ks_instance,
300*0Sstevel@tonic-gate 		RUNT_ERRORS)) == NULL) {
301*0Sstevel@tonic-gate 		return (-1);
302*0Sstevel@tonic-gate 	}
303*0Sstevel@tonic-gate 	if (port_datap->data_type == KSTAT_DATA_UINT32) {
304*0Sstevel@tonic-gate 		runt = port_datap->value.ui32;
305*0Sstevel@tonic-gate 	} else {
306*0Sstevel@tonic-gate 		runt = port_datap->value.ui64;
307*0Sstevel@tonic-gate 	}
308*0Sstevel@tonic-gate 	if (runt > ipackets/10) {
309*0Sstevel@tonic-gate 		return (1);
310*0Sstevel@tonic-gate 	}
311*0Sstevel@tonic-gate 
312*0Sstevel@tonic-gate 	if ((port_datap = kstat_name_lookup(kc, ks_module, ks_instance,
313*0Sstevel@tonic-gate 		COLLISIONS)) == NULL) {
314*0Sstevel@tonic-gate 		return (-1);
315*0Sstevel@tonic-gate 	}
316*0Sstevel@tonic-gate 	if (port_datap->data_type == KSTAT_DATA_UINT32) {
317*0Sstevel@tonic-gate 		collisions = port_datap->value.ui32;
318*0Sstevel@tonic-gate 	} else {
319*0Sstevel@tonic-gate 		collisions = port_datap->value.ui64;
320*0Sstevel@tonic-gate 	}
321*0Sstevel@tonic-gate 	if (collisions > (opackets+ipackets)/30) {
322*0Sstevel@tonic-gate 		return (1);
323*0Sstevel@tonic-gate 	}
324*0Sstevel@tonic-gate 	return (0);
325*0Sstevel@tonic-gate }
326*0Sstevel@tonic-gate 
327*0Sstevel@tonic-gate /*
328*0Sstevel@tonic-gate  * serial_port_state: returns status a serial port
329*0Sstevel@tonic-gate  * 1 = up, 0 = down, anything else = unknown
330*0Sstevel@tonic-gate  */
331*0Sstevel@tonic-gate 
332*0Sstevel@tonic-gate /* ARGSUSED */
333*0Sstevel@tonic-gate static int
serial_port_state(kstat_ctl_t * kc,char * driver,int instance)334*0Sstevel@tonic-gate serial_port_state(kstat_ctl_t *kc, char *driver, int instance)
335*0Sstevel@tonic-gate {
336*0Sstevel@tonic-gate 	int			fd;
337*0Sstevel@tonic-gate 	char			device[20];
338*0Sstevel@tonic-gate 	struct termios		flags;
339*0Sstevel@tonic-gate 	struct sigaction	old_sa, new_sa;
340*0Sstevel@tonic-gate 	static void		sig_alarm_handler(int);
341*0Sstevel@tonic-gate 
342*0Sstevel@tonic-gate 	(void) memset(&old_sa, 0, sizeof (old_sa));
343*0Sstevel@tonic-gate 	(void) memset(&new_sa, 0, sizeof (new_sa));
344*0Sstevel@tonic-gate 	new_sa.sa_handler = sig_alarm_handler;
345*0Sstevel@tonic-gate 	(void) sigaction(SIGALRM, &new_sa, &old_sa);
346*0Sstevel@tonic-gate 	(void) alarm(1);
347*0Sstevel@tonic-gate 
348*0Sstevel@tonic-gate 	(void) snprintf(device, sizeof (device), "/dev/tty%c", instance+'a');
349*0Sstevel@tonic-gate 	fd = open(device, O_RDONLY|O_NDELAY|O_NONBLOCK|O_NOCTTY);
350*0Sstevel@tonic-gate 
351*0Sstevel@tonic-gate 	/* Restore sig action flags */
352*0Sstevel@tonic-gate 	(void) sigaction(SIGALRM, &old_sa, (struct sigaction *)0);
353*0Sstevel@tonic-gate 	/* Disable alarm */
354*0Sstevel@tonic-gate 	(void) alarm(0);
355*0Sstevel@tonic-gate 
356*0Sstevel@tonic-gate 	if (fd == -1) {
357*0Sstevel@tonic-gate 		return (-1);
358*0Sstevel@tonic-gate 	}
359*0Sstevel@tonic-gate 
360*0Sstevel@tonic-gate 	if (isatty(fd) == 0) {
361*0Sstevel@tonic-gate 		(void) close(fd);
362*0Sstevel@tonic-gate 		return (-1);
363*0Sstevel@tonic-gate 	}
364*0Sstevel@tonic-gate 	(void) memset(&flags, 0, sizeof (flags));
365*0Sstevel@tonic-gate 	if (ioctl(fd, TCGETS, &flags) != 0) {
366*0Sstevel@tonic-gate 		(void) close(fd);
367*0Sstevel@tonic-gate 		return (-1);
368*0Sstevel@tonic-gate 	}
369*0Sstevel@tonic-gate 	(void) close(fd);
370*0Sstevel@tonic-gate 	return ((flags.c_cflag & TIOCM_LE) ? 1 : 0);
371*0Sstevel@tonic-gate }
372*0Sstevel@tonic-gate 
373*0Sstevel@tonic-gate /* ARGSUSED */
374*0Sstevel@tonic-gate static void
sig_alarm_handler(int signo)375*0Sstevel@tonic-gate sig_alarm_handler(int signo)
376*0Sstevel@tonic-gate {
377*0Sstevel@tonic-gate }
378*0Sstevel@tonic-gate 
379*0Sstevel@tonic-gate /*
380*0Sstevel@tonic-gate  * serial_port_cond: returns status of a serial port
381*0Sstevel@tonic-gate  * 0 = OK, 1 = FAILING, 2 = FAILED, 3 = TESTING, anything else = UNKNOWN
382*0Sstevel@tonic-gate  */
383*0Sstevel@tonic-gate static int
serial_port_cond(kstat_ctl_t * kc,char * driver,int instance)384*0Sstevel@tonic-gate serial_port_cond(kstat_ctl_t *kc, char *driver, int instance)
385*0Sstevel@tonic-gate {
386*0Sstevel@tonic-gate 	switch (serial_port_state(kc, driver, instance)) {
387*0Sstevel@tonic-gate 	case 1:
388*0Sstevel@tonic-gate 		return (0);
389*0Sstevel@tonic-gate 	default:
390*0Sstevel@tonic-gate 		return (-1);
391*0Sstevel@tonic-gate 	}
392*0Sstevel@tonic-gate }
393*0Sstevel@tonic-gate 
394*0Sstevel@tonic-gate /*
395*0Sstevel@tonic-gate  * parallel_port_state: returns kstat info of a serial port
396*0Sstevel@tonic-gate  * 1 = up, 0 = down, anything else = unknown
397*0Sstevel@tonic-gate  */
398*0Sstevel@tonic-gate static int
parallel_port_state(kstat_ctl_t * kc,char * ks_module,int ks_instance)399*0Sstevel@tonic-gate parallel_port_state(kstat_ctl_t *kc, char *ks_module, int ks_instance)
400*0Sstevel@tonic-gate {
401*0Sstevel@tonic-gate 	kstat_t		*ksp = NULL;
402*0Sstevel@tonic-gate 	kstat_named_t	*port_datap = NULL;
403*0Sstevel@tonic-gate 	char		*data_lookup;
404*0Sstevel@tonic-gate 	char		ks_name[20];
405*0Sstevel@tonic-gate 
406*0Sstevel@tonic-gate 	(void) snprintf(ks_name, sizeof (ks_name), "%s%d", ks_module,
407*0Sstevel@tonic-gate 		ks_instance);
408*0Sstevel@tonic-gate 	if ((ksp = kstat_lookup(kc, ks_module, ks_instance, ks_name)) == NULL) {
409*0Sstevel@tonic-gate 		return (-1);
410*0Sstevel@tonic-gate 	}
411*0Sstevel@tonic-gate 	if (kstat_read(kc, ksp, NULL) == -1) {
412*0Sstevel@tonic-gate 		return (-1);
413*0Sstevel@tonic-gate 	}
414*0Sstevel@tonic-gate 	data_lookup = "";
415*0Sstevel@tonic-gate 	port_datap = (kstat_named_t *)kstat_data_lookup(ksp, data_lookup);
416*0Sstevel@tonic-gate 	if (port_datap == NULL) {
417*0Sstevel@tonic-gate 		return (-1);
418*0Sstevel@tonic-gate 	}
419*0Sstevel@tonic-gate 	return (-1);
420*0Sstevel@tonic-gate }
421*0Sstevel@tonic-gate 
422*0Sstevel@tonic-gate /*
423*0Sstevel@tonic-gate  * parallel_port_cond: returns kstat info of a serial port
424*0Sstevel@tonic-gate  * 1 = up, 0 = down, anything else = unknown
425*0Sstevel@tonic-gate  */
426*0Sstevel@tonic-gate static int
parallel_port_cond(kstat_ctl_t * kc,char * ks_module,int ks_instance)427*0Sstevel@tonic-gate parallel_port_cond(kstat_ctl_t *kc, char *ks_module, int ks_instance)
428*0Sstevel@tonic-gate {
429*0Sstevel@tonic-gate 	return (parallel_port_state(kc, ks_module, ks_instance));
430*0Sstevel@tonic-gate }
431