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 (c) 2001 by Sun Microsystems, Inc.
24  * All rights reserved.
25  */
26 
27 #ifndef	_FCAL_LEDS_H
28 #define	_FCAL_LEDS_H
29 
30 #include <picl.h>
31 #include <picltree.h>
32 #include <picldefs.h>
33 
34 #ifdef	__cplusplus
35 extern "C" {
36 #endif
37 
38 /*
39  * Header file for the FC-AL LEDs PICL plugin.
40  * Contains message texts, constant definitions, typedefs for enums and
41  * structs, global data and function templates.
42  */
43 
44 #define	SYSLOG	syslog
45 
46 /*
47  * log message tests
48  */
49 #define	EM_CANT_OPEN	\
50 	gettext("SUNW_fcal_leds: open fail: %s\n")
51 #define	EM_NONALF_TOK	\
52 	gettext("SUNW_fcal_leds: line %d token begins non-alpha\n")
53 #define	EM_LONG_TOK	\
54 	gettext("SUNW_fcal_leds: line %d token too long\n")
55 #define	EM_UNKN_TOK	\
56 	gettext("SUNW_fcal_leds: line %d unknown token\n")
57 #define	EM_INVAL_TOK	\
58 	gettext("SUNW_fcal_leds: line %d invalid token at start of line\n")
59 #define	EM_NOCOLON	\
60 	gettext("SUNW_fcal_leds: line %d leading token not followed by ':'\n")
61 #define	EM_NOVERS	\
62 	gettext("SUNW_fcal_leds: first token not VERSION\n")
63 #define	EM_NUM_TERM	\
64 	gettext("SUNW_fcal_leds: invalid number terminator\n")
65 #define	EM_LOGIC_LVL	\
66 	gettext("SUNW_fcal_leds: logic level specified as neither 0 nor 1\n")
67 #define	EM_NOTPOS	\
68 	gettext("SUNW_fcal_leds: numeric field greater than 0 expected\n")
69 #define	EM_DISK_RANGE	\
70 	gettext("SUNW_fcal_leds: disk number out of range\n")
71 #define	EM_NDISKS_DBL	\
72 	gettext("SUNW_fcal_leds: number of disks defined twice\n")
73 #define	EM_NO_DISKS	\
74 	gettext("SUNW_fcal_leds: no disks defined\n")
75 #define	EM_VER_FRMT	\
76 	gettext("SUNW_fcal_leds: format error in VERSION string\n")
77 #define	EM_WRNGVER	\
78 	gettext("SUNW_fcal_leds: config version %d.%d not supported\n")
79 #define	EM_REL_PATH	\
80 	gettext("SUNW_fcal_leds: path names must be absolute\n")
81 #define	EM_ERRLINE	\
82 	gettext("SUNW_fcal_leds: error on line %d\n")
83 #define	EM_NO_LED_PROP	\
84 	gettext("SUNW_fcal_leds: LED property name missing\n")
85 #define	EM_PROP_TERM	\
86 	gettext("SUNW_fcal_leds: expected comma (',') after property name\n")
87 #define	EM_STR_NOT_SET	\
88 	gettext("SUNW_fcal_leds: %s not defined")
89 #define	EM_I2C_GET_PORT	\
90 	gettext("SUNW_fcal_leds: I2C_GET_PORT: %s\n")
91 #define	EM_DI_INIT_FAIL	\
92 	gettext("SUNW_fcal_leds: di_init failed: %s\n")
93 #define	EM_THREAD_CREATE_FAILED \
94 	gettext("SUNW_fcal_leds: pthread_create() call failed: %s\n")
95 #define	EM_MUTEX_FAIL	\
96 	gettext("SUNW_fcal_leds: pthread_mutex_lock returned: %s\n")
97 #define	EM_CONDWAITFAIL	\
98 	gettext("SUNW_fcal_leds: pthread_cond_wait returned: %s\n")
99 #define	EM_SPURIOUS_FP	\
100 	gettext("SUNW_fcal_leds: deleting spurious PICL fp node\n")
101 #define	EM_NO_FP_NODE \
102 	gettext(	\
103 	    "SUNW_fcal_leds: cannot get PICL disk node for hot plug disk %d\n")
104 #define	EM_POLL_FAIL	\
105 	gettext("SUNW_fcal_leds: poll() returned: %s, no more timed events\n")
106 
107 /*
108  * config file terminal name
109  */
110 #define	FCAL_LEDS_CONF_FILE	"fcal_leds.conf"
111 
112 /*
113  * devinfo hardware properties
114  */
115 #define	HW_PROP_TARGET		"target"
116 #define	HW_PROP_PORT		"port-wwn"
117 
118 /*
119  * PICL node names
120  */
121 #define	FCAL_PICL_DISK_UNIT	"disk-unit"
122 
123 /*
124  * PICL property names
125  */
126 #define	FCAL_PICL_REF		"_"
127 #define	FCAL_PICL_PROP_BUS_ADDR	"bus-addr"
128 #define	FCAL_PICL_PROP_TARGET	"target"
129 #define	FCAL_PICL_LED_REF	FCAL_PICL_REF PICL_CLASS_LED FCAL_PICL_REF
130 #define	FCAL_PICL_BLOCK_REF	FCAL_PICL_REF PICL_CLASS_BLOCK FCAL_PICL_REF
131 
132 /*
133  * String values for led State property
134  */
135 #define	FCAL_PICL_LED_ON	"on"
136 #define	FCAL_PICL_LED_OFF	"off"
137 #define	FCAL_PICL_LED_TEST	"led test"
138 /*
139  * MAX_LEN_LED_STATE is (strlen(FCAL_PICL_LED_TEST) + 1)
140  */
141 #define	MAX_LEN_LED_STATE	9
142 
143 /*
144  * Space for 0123456789ABCDEF,0123456789ABCDEF<nul>
145  */
146 #define	MAX_LEN_UNIT_ADDRESS	34
147 
148 /*
149  * properties per row in Device table
150  */
151 #define	FCAL_DEVTABLE_NCOLS	2
152 
153 /*
154  * number of LEDs per disk
155  */
156 #define	FCAL_LED_CNT	3
157 
158 /*
159  * special values for status when ioctl fails
160  */
161 #define	I2C_IOCTL_FAIL	(-1)
162 #define	I2C_IOCTL_INIT	(-2)
163 #define	MINORS_UNKNOWN	(-1)
164 
165 /*
166  * other status values
167  */
168 #define	NO_MINORS	0
169 #define	HAS_MINORS	1
170 
171 /*
172  * event flags
173  */
174 #define	FCAL_EV_POLL	1
175 #define	FCAL_EV_CONFIG	2
176 
177 /*
178  * default timer values - overridden by .conf file
179  */
180 #define	DFLT_SLOW_POLL	59
181 #define	DFLT_FAST_POLL	2
182 #define	DFLT_RELAX_TIME	300
183 #define	DFLT_TEST_TIME	10
184 
185 typedef enum token {
186 	NO_TOKEN,
187 	TOKEN_ERROR,
188 	FCAL_VERSION,
189 	LED_PROPS_START,	/* next enums are for led properties */
190 	FCAL_REMOK_LED,
191 	FCAL_FAULT_LED,
192 	FCAL_READY_LED,
193 	LED_PROPS_END,		/* no more led properties */
194 	LINE_DEFS,		/* next enums define configuration lines */
195 	FCAL_LEDS_BOARD,
196 	FCAL_STATUS_BOARD,
197 	FCAL_DISK_DRIVER,
198 	FCAL_N_DISKS,
199 	FCAL_ASSERT_PRESENT,
200 	FCAL_ASSERT_FAULT,
201 	FCAL_LED_ON,
202 	FCAL_DISK_PRESENT,
203 	FCAL_DISK_FAULT,
204 	FCAL_LED_ID,
205 	FCAL_SLOW_POLL,
206 	FCAL_FAST_POLL,
207 	FCAL_RELAX_INTERVAL,
208 	FCAL_TEST_INTERVAL,
209 	FCAL_DISK_PARENT,
210 	FCAL_UNIT_PARENT,
211 	FCAL_LED_NODES
212 } token_t;
213 
214 typedef enum led_state_enum {
215 	LED_STATE_OFF,
216 	LED_STATE_ON,
217 	LED_STATE_TEST
218 } led_state_t;
219 
220 typedef char *str;
221 typedef const char *cstr;
222 
223 /*
224  * Note on disk_prev and disk_ready flags.
225  * The following entries are dynamically created arrays:
226  * presence, faults, disk_detected, disk_ready, disk_prev, led_test_end,
227  * disk_port, led_addr.
228  * The disk_prev and disk_ready flags (one per disk) are used as follows:
229  * disk removed (disk_detected = 0), disk_ready[d] = 0, disk_prev[d] = 0
230  * disk present (disk_detected = 1) use this table:
231  * disk_ready[d] | disk_prev[d] | meaning
232  *      0        |      0       | driver not (yet) attached (show green led)
233  *      0        |      1       | driver has been detached (show blue led)
234  *      1        |      0       | driver attached, PICL update needed (green)
235  *      1        |      1       | driver attached, normal running (green)
236  * OK to remove (blue) is only lit for the attached -> detached transition
237  * state 1 0 (PICL update needed) is really transient and is cleared after
238  * calling update_picl.
239  */
240 typedef struct led_dtls {
241 	int		ver_maj;
242 	int		ver_min;
243 	cstr		fcal_leds;	/* path name of leds board */
244 	cstr		fcal_status;	/* path of back-plane status board */
245 	cstr		fcal_driver;	/* name of fcal disk driver */
246 	int		n_disks;	/* number of fcal disks */
247 	int		*presence;	/* presence detection masks */
248 	int		*faults;	/* fault status masks */
249 	int		*disk_detected;	/* working store for detected disks */
250 	int		*disk_ready;	/* working store for disk ready */
251 	int		*disk_prev;	/* previous ready state */
252 	volatile int	*led_test_end;	/* (per disk) ticks to end led test */
253 	boolean_t	*picl_retry;	/* (per disk) retry picl update flag */
254 	uchar_t		**disk_port;	/* for FC-AL this is WWN */
255 	int		assert_presence; /* status value for presence */
256 	int		assert_fault;	/* status value for fault */
257 	int		assert_led_on;	/* level required to light led */
258 	uint_t		*led_addr[FCAL_LED_CNT]; /* 2D array to leds */
259 	led_state_t	*led_state[FCAL_LED_CNT]; /* current states */
260 	boolean_t	led_retry;	/* flag set after led ioctl failure */
261 	volatile boolean_t polling;	/* set to B_FALSE after poll failure */
262 	volatile int	fast_poll_end;	/* fast_poll ticks left */
263 	int		fast_poll;	/* fast_poll interval in seconds */
264 	int		slow_poll_ticks; /* fast polls per slow poll */
265 	int		relax_time_ticks; /* time interval to do fast polling */
266 	int		led_test_time;	/* fast polls in led test interval */
267 	cstr		fcal_disk_parent; /* search string for /platform */
268 	cstr		disk_unit_parent; /* search template for disk-slots */
269 	cstr		disk_led_nodes;	/* search template for disk-leds */
270 } led_dtls_t;
271 
272 typedef int (*actfun_t)(str *p_str, led_dtls_t *dtls);
273 
274 typedef struct lookup {
275 	token_t		tok;
276 	cstr		tok_str;
277 	actfun_t	action;
278 } lookup_t;
279 
280 /*
281  * global data
282  */
283 extern led_dtls_t	*g_led_dtls;
284 extern pthread_cond_t	g_cv;
285 extern pthread_cond_t	g_cv_ack;
286 extern pthread_mutex_t	g_mutex;
287 extern volatile int	g_event_flag;
288 extern volatile boolean_t g_finish_now;
289 extern volatile boolean_t g_leds_thread_ack;
290 extern volatile boolean_t g_poll_thread_ack;
291 
292 /*
293  * function templates
294  */
295 char *mystrerror(int err);
296 void *fcal_leds_thread(void *args);
297 int fc_led_parse(FILE *fp, led_dtls_t **p_dtls);
298 void free_led_dtls(led_dtls_t *dtls);
299 int find_disk_slot(led_dtls_t *dtls, int disk, picl_nodehdl_t *nodeh);
300 void delete_disk_unit(led_dtls_t *dtls, int disk);
301 boolean_t is_led_test(led_dtls_t *dtls);
302 int create_Device_table(picl_prophdl_t *tbl_h, picl_prophdl_t *tableh);
303 void clr_led(int diskNo, token_t led_tok, led_dtls_t *dtls);
304 
305 #ifdef	__cplusplus
306 }
307 #endif
308 
309 #endif	/* _FCAL_LEDS_H */
310