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 (c) 2001 by Sun Microsystems, Inc.
24 * All rights reserved.
35 #include "fcal_leds.h"
38 * function templates for static functions
40 static token_t
get_token(char **pptr
, int lineNo
, actfun_t
*fun
);
41 static int get_cstr(str
*p_str
, cstr
*p_cstr_res
);
42 static int get_assert(str
*p_str
, int *assert);
43 static int get_pnz(str
*p_str
, int *pnz
);
44 static int get_mask(str
*p_str
, int n_disks
, int *p_intarray
);
47 * Templates for functions which may be returned by get_token().
48 * These functions are all called with a pointer to the position just
49 * beyond the token being actioned.
51 static int act_version(str
*p_str
, led_dtls_t
*dtls
);
52 static int act_leds_board(str
*p_str
, led_dtls_t
*dtls
);
53 static int act_status_board(str
*p_str
, led_dtls_t
*dtls
);
54 static int act_disk_driver(str
*p_str
, led_dtls_t
*dtls
);
55 static int act_n_disks(str
*p_str
, led_dtls_t
*dtls
);
56 static int act_asrt_pres(str
*p_str
, led_dtls_t
*dtls
);
57 static int act_asrt_fault(str
*p_str
, led_dtls_t
*dtls
);
58 static int act_led_on(str
*p_str
, led_dtls_t
*dtls
);
59 static int act_disk_present(str
*p_str
, led_dtls_t
*dtls
);
60 static int act_disk_fault(str
*p_str
, led_dtls_t
*dtls
);
61 static int act_led_id(str
*p_str
, led_dtls_t
*dtls
);
62 static int act_slow_poll(str
*p_str
, led_dtls_t
*dtls
);
63 static int act_fast_poll(str
*p_str
, led_dtls_t
*dtls
);
64 static int act_relax_interval(str
*p_str
, led_dtls_t
*dtls
);
65 static int act_test_interval(str
*p_str
, led_dtls_t
*dtls
);
66 static int act_disk_parent(str
*p_str
, led_dtls_t
*dtls
);
67 static int act_unit_parent(str
*p_str
, led_dtls_t
*dtls
);
68 static int act_led_nodes(str
*p_str
, led_dtls_t
*dtls
);
71 * The table below is used to lookup .conf file keywords to yield either
72 * a corresponding enum or a function to process the keyword.
74 static lookup_t table
[] = {
75 { FCAL_VERSION
, "VERSION", act_version
},
76 { FCAL_REMOK_LED
, "REMOK", NULL
},
77 { FCAL_FAULT_LED
, "FAULT", NULL
},
78 { FCAL_READY_LED
, "READY", NULL
},
79 { FCAL_LEDS_BOARD
, "FCAL-LEDS", act_leds_board
},
80 { FCAL_STATUS_BOARD
, "FCAL-STATUS", act_status_board
},
81 { FCAL_DISK_DRIVER
, "FCAL-DISK-DRIVER", act_disk_driver
},
82 { FCAL_N_DISKS
, "N-DISKS", act_n_disks
},
83 { FCAL_ASSERT_PRESENT
, "ASSERT-PRESENT", act_asrt_pres
},
84 { FCAL_ASSERT_FAULT
, "ASSERT-FAULT", act_asrt_fault
},
85 { FCAL_LED_ON
, "LED-ON", act_led_on
},
86 { FCAL_DISK_PRESENT
, "DISK-PRESENT", act_disk_present
},
87 { FCAL_DISK_FAULT
, "DISK-FAULT", act_disk_fault
},
88 { FCAL_LED_ID
, "LED", act_led_id
},
89 { FCAL_SLOW_POLL
, "SLOW-POLL", act_slow_poll
},
90 { FCAL_FAST_POLL
, "FAST-POLL", act_fast_poll
},
91 { FCAL_RELAX_INTERVAL
, "RELAX-INTERVAL", act_relax_interval
},
92 { FCAL_TEST_INTERVAL
, "LED-TEST-INTERVAL", act_test_interval
},
93 { FCAL_DISK_PARENT
, "FCAL-DISK-PARENT", act_disk_parent
},
94 { FCAL_UNIT_PARENT
, "DISK-UNIT-PARENT", act_unit_parent
},
95 { FCAL_LED_NODES
, "DISK-LED-NODES", act_led_nodes
}
99 * length of longest string in table (with space for null terminator)
101 #define MAX_FCAL_TOKEN_LEN 18
103 static const int tab_len
= (sizeof (table
))/sizeof (table
[0]);
107 * Parses the current line of data and returns the next token.
108 * If there are no significant characters in the line, NO_TOKEN is returned.
109 * If a syntax error is encountered, TOKEN_ERROR is returned.
110 * Pointer to position in current line is updated to point to the terminator
111 * of the token, unless TOKEN_ERROR is returned.
115 char **pptr
, /* pointer to pointer to position in current line */
116 /* *ptr is updated by the function */
117 int lineNo
, /* current line number, used for syslog. If set to */
118 /* zero, syslogging is supressed */
119 actfun_t
*fun
) /* pointer to function variable to receive action */
120 /* pointer for the token found. NULL may be returned */
131 /* strip leading white space */
133 ch
= (unsigned)(*ptr
++);
135 } while (isspace(ch
));
137 if ((ch
== '\0') || (ch
== '#')) {
139 return (NO_TOKEN
); /* empty line or comment */
144 SYSLOG(LOG_ERR
, EM_NONALF_TOK
, lineNo
);
145 return (TOKEN_ERROR
);
147 token_start
= ptr
- 1;
148 toklen
= strcspn(token_start
, ",: \t");
149 *pptr
= token_start
+ toklen
;
151 * got token, now look it up
153 for (i
= 0; i
< tab_len
; i
++) {
154 if ((strncasecmp(token_start
, table
[i
].tok_str
,
155 toklen
) == 0) && (table
[i
].tok_str
[toklen
] == '\0')) {
156 *fun
= table
[i
].action
;
157 return (table
[i
].tok
);
161 SYSLOG(LOG_ERR
, EM_UNKN_TOK
, lineNo
);
162 return (TOKEN_ERROR
);
166 act_version(str
*p_str
, led_dtls_t
*dtls
)
168 dtls
->ver_maj
= strtoul(*p_str
, p_str
, 0);
169 if (*(*p_str
)++ != '.') {
170 SYSLOG(LOG_ERR
, EM_VER_FRMT
);
173 dtls
->ver_min
= strtoul(*p_str
, p_str
, 0);
174 if ((**p_str
!= '\0') && !isspace(**p_str
)) {
175 SYSLOG(LOG_ERR
, EM_VER_FRMT
);
178 if ((dtls
->ver_maj
!= 1) || (dtls
->ver_min
!= 0)) {
179 SYSLOG(LOG_ERR
, EM_WRNGVER
, dtls
->ver_maj
, dtls
->ver_min
);
186 * get space to hold white-space terminated string at *p_str
187 * advance *p_str to point to terminator
188 * return copy of string, null terminated
191 get_cstr(str
*p_str
, cstr
*p_cstr_res
)
197 while (isspace(**p_str
))
203 } while ((ch
!= '\0') && (!isspace(ch
)));
206 if (*p_cstr_res
!= NULL
)
207 free((void *)(*p_cstr_res
));
208 ptr
= malloc(len
+ 1);
213 (void) memcpy(ptr
, *p_str
, len
);
220 act_leds_board(str
*p_str
, led_dtls_t
*dtls
)
222 int res
= get_cstr(p_str
, &dtls
->fcal_leds
);
224 if (dtls
->fcal_leds
[0] != '/') {
225 free((void *)dtls
->fcal_leds
);
226 dtls
->fcal_leds
= NULL
;
227 SYSLOG(LOG_ERR
, EM_REL_PATH
);
235 act_status_board(str
*p_str
, led_dtls_t
*dtls
)
237 int res
= get_cstr(p_str
, &dtls
->fcal_status
);
239 if (dtls
->fcal_status
[0] != '/') {
240 free((void *)dtls
->fcal_status
);
241 dtls
->fcal_status
= NULL
;
242 SYSLOG(LOG_ERR
, EM_REL_PATH
);
250 act_disk_driver(str
*p_str
, led_dtls_t
*dtls
)
252 return (get_cstr(p_str
, &dtls
->fcal_driver
));
256 act_disk_parent(str
*p_str
, led_dtls_t
*dtls
)
258 return (get_cstr(p_str
, &dtls
->fcal_disk_parent
));
262 act_unit_parent(str
*p_str
, led_dtls_t
*dtls
)
264 return (get_cstr(p_str
, &dtls
->disk_unit_parent
));
268 act_led_nodes(str
*p_str
, led_dtls_t
*dtls
)
270 return (get_cstr(p_str
, &dtls
->disk_led_nodes
));
274 * A number of fields in the led_dtls_t structure have per-disk copies.
275 * This action routine creates the space for all such fields.
276 * Following any failure, an error is returned and the calling routine
277 * must handle the fact that only a subset of these fields are populated.
278 * In practice, this function is only called by get_token() on behalf of
279 * fc_led_parse(). fc_led_parse calls free_led_dtls() after any error.
282 act_n_disks(str
*p_str
, led_dtls_t
*dtls
)
286 if (dtls
->n_disks
!= 0) {
287 SYSLOG(LOG_ERR
, EM_NDISKS_DBL
);
290 dtls
->n_disks
= strtoul(*p_str
, p_str
, 0);
291 if ((**p_str
!= '\0') && !isspace(**p_str
)) {
292 SYSLOG(LOG_ERR
, EM_NUM_TERM
);
295 if (dtls
->n_disks
< 1) {
296 SYSLOG(LOG_ERR
, EM_NO_DISKS
);
299 dtls
->presence
= calloc(dtls
->n_disks
, sizeof (int));
300 if (dtls
->presence
== NULL
)
302 dtls
->faults
= calloc(dtls
->n_disks
, sizeof (int));
303 if (dtls
->faults
== NULL
)
305 dtls
->disk_detected
= calloc(dtls
->n_disks
, sizeof (int));
306 if (dtls
->disk_detected
== NULL
)
308 dtls
->disk_ready
= calloc(dtls
->n_disks
, sizeof (int));
309 if (dtls
->disk_ready
== NULL
)
311 dtls
->disk_prev
= calloc(dtls
->n_disks
, sizeof (int));
312 if (dtls
->disk_prev
== NULL
)
314 dtls
->led_test_end
= calloc(dtls
->n_disks
, sizeof (int));
315 if (dtls
->led_test_end
== NULL
)
317 dtls
->picl_retry
= calloc(dtls
->n_disks
, sizeof (boolean_t
));
318 if (dtls
->picl_retry
== NULL
)
320 dtls
->disk_port
= calloc(dtls
->n_disks
, sizeof (char *));
321 if (dtls
->disk_port
== NULL
) {
324 for (i
= 0; i
< FCAL_LED_CNT
; i
++) {
325 dtls
->led_addr
[i
] = calloc(dtls
->n_disks
, sizeof (int));
326 if (dtls
->led_addr
[i
] == NULL
)
328 dtls
->led_state
[i
] = calloc(dtls
->n_disks
,
329 sizeof (led_state_t
));
330 if (dtls
->led_state
[i
] == NULL
)
337 get_assert(str
*p_str
, int *assert)
339 int i
= strtoul(*p_str
, p_str
, 0);
340 if ((**p_str
!= '\0') && !isspace(**p_str
)) {
341 SYSLOG(LOG_ERR
, EM_NUM_TERM
);
344 if ((i
!= 0) && (i
!= 1)) {
345 SYSLOG(LOG_ERR
, EM_LOGIC_LVL
);
353 get_pnz(str
*p_str
, int *pnz
)
355 int i
= strtoul(*p_str
, p_str
, 0);
356 if ((**p_str
!= '\0') && !isspace(**p_str
)) {
357 SYSLOG(LOG_ERR
, EM_NUM_TERM
);
361 SYSLOG(LOG_ERR
, EM_NOTPOS
);
369 act_asrt_pres(str
*p_str
, led_dtls_t
*dtls
)
371 return (get_assert(p_str
, &dtls
->assert_presence
));
375 act_asrt_fault(str
*p_str
, led_dtls_t
*dtls
)
377 return (get_assert(p_str
, &dtls
->assert_fault
));
381 act_led_on(str
*p_str
, led_dtls_t
*dtls
)
383 return (get_assert(p_str
, &dtls
->assert_led_on
));
387 get_mask(str
*p_str
, int n_disks
, int *p_intarray
)
390 int j
= strtoul(*p_str
, p_str
, 0);
391 if (*(*p_str
)++ != ',') {
392 SYSLOG(LOG_ERR
, EM_NUM_TERM
);
395 if ((j
< 0) || (j
> n_disks
)) {
396 SYSLOG(LOG_ERR
, EM_DISK_RANGE
);
399 i
= strtoul(*p_str
, p_str
, 0);
400 if ((**p_str
!= '\0') && !isspace(**p_str
)) {
401 SYSLOG(LOG_ERR
, EM_NUM_TERM
);
409 act_disk_present(str
*p_str
, led_dtls_t
*dtls
)
411 return (get_mask(p_str
, dtls
->n_disks
, dtls
->presence
));
415 act_disk_fault(str
*p_str
, led_dtls_t
*dtls
)
417 return (get_mask(p_str
, dtls
->n_disks
, dtls
->faults
));
421 act_led_id(str
*p_str
, led_dtls_t
*dtls
)
426 int j
= strtoul(*p_str
, p_str
, 0);
428 if (*(*p_str
)++ != ',') {
429 SYSLOG(LOG_ERR
, EM_NUM_TERM
);
432 if ((j
< 0) || (j
>= dtls
->n_disks
)) {
433 SYSLOG(LOG_ERR
, EM_DISK_RANGE
);
436 tok
= get_token(p_str
, 0, &action
);
437 if ((tok
<= LED_PROPS_START
) || (tok
>= LED_PROPS_END
)) {
438 SYSLOG(LOG_ERR
, EM_NO_LED_PROP
);
441 if (*(*p_str
)++ != ',') {
442 SYSLOG(LOG_ERR
, EM_PROP_TERM
);
445 i
= strtoul(*p_str
, p_str
, 0);
446 if ((**p_str
!= '\0') && !isspace(**p_str
)) {
447 SYSLOG(LOG_ERR
, EM_NUM_TERM
);
450 dtls
->led_addr
[tok
- FCAL_REMOK_LED
][j
] = i
;
455 act_slow_poll(str
*p_str
, led_dtls_t
*dtls
)
457 return (get_pnz(p_str
, &dtls
->slow_poll_ticks
));
461 act_fast_poll(str
*p_str
, led_dtls_t
*dtls
)
463 return (get_pnz(p_str
, &dtls
->fast_poll
));
467 act_relax_interval(str
*p_str
, led_dtls_t
*dtls
)
469 return (get_pnz(p_str
, &dtls
->relax_time_ticks
));
473 act_test_interval(str
*p_str
, led_dtls_t
*dtls
)
475 return (get_pnz(p_str
, &dtls
->led_test_time
));
479 * Create a led_dtls_t structure
480 * Parse configuration file and populate the led_dtls_t
481 * In the event of an error, free the structure and return an error
484 fc_led_parse(FILE *fp
, led_dtls_t
**p_dtls
)
490 led_dtls_t
*dtls
= calloc(1, sizeof (led_dtls_t
));
498 dtls
->ver_min
= -1; /* mark as version unknown */
500 while ((ptr
= fgets(linebuf
, sizeof (linebuf
), fp
)) != NULL
) {
502 tok
= get_token(&ptr
, lineNo
, &action
);
505 if (tok
== TOKEN_ERROR
) {
509 if (tok
== FCAL_VERSION
) {
510 if ((err
= (*action
)(&ptr
, dtls
)) != 0)
515 if (dtls
->ver_min
< 0) {
516 SYSLOG(LOG_ERR
, EM_NOVERS
);
520 if (tok
<= LINE_DEFS
) {
521 SYSLOG(LOG_ERR
, EM_INVAL_TOK
, lineNo
);
526 SYSLOG(LOG_ERR
, EM_NOCOLON
, lineNo
);
530 if ((err
= (*action
)(&ptr
, dtls
)) != 0) {
531 SYSLOG(LOG_ERR
, EM_ERRLINE
, lineNo
);
539 err
= -1; /* just in case */
540 if (dtls
->ver_min
< 0) {
541 SYSLOG(LOG_ERR
, EM_NOVERS
);
542 } else if (dtls
->n_disks
== 0) {
543 SYSLOG(LOG_ERR
, EM_NO_DISKS
);
544 } else if (dtls
->fcal_leds
== NULL
) {
545 SYSLOG(LOG_ERR
, EM_STR_NOT_SET
, "fcal-leds");
546 } else if (dtls
->fcal_status
== NULL
) {
547 SYSLOG(LOG_ERR
, EM_STR_NOT_SET
, "fcal-status");
548 } else if (dtls
->fcal_driver
== NULL
) {
549 SYSLOG(LOG_ERR
, EM_STR_NOT_SET
, "fcal-driver");
556 * clean up after error detected
564 * set any unset timers to default time
566 if (dtls
->slow_poll_ticks
== 0)
567 dtls
->slow_poll_ticks
= DFLT_SLOW_POLL
;
568 if (dtls
->fast_poll
== 0)
569 dtls
->fast_poll
= DFLT_FAST_POLL
;
570 if (dtls
->relax_time_ticks
== 0)
571 dtls
->relax_time_ticks
= DFLT_RELAX_TIME
;
572 if (dtls
->led_test_time
== 0)
573 dtls
->led_test_time
= DFLT_TEST_TIME
;
576 * set polling flag to avoid a start-up glitch
577 * it will be cleared again if the poll thread fails
579 dtls
->polling
= B_TRUE
;
582 * convert derived timers to multiples of fast poll time
584 dtls
->slow_poll_ticks
+= dtls
->fast_poll
- 1; /* for round up */
585 dtls
->slow_poll_ticks
/= dtls
->fast_poll
;
586 dtls
->relax_time_ticks
+= dtls
->fast_poll
- 1;
587 dtls
->relax_time_ticks
/= dtls
->fast_poll
;
588 dtls
->led_test_time
+= dtls
->fast_poll
- 1;
589 dtls
->led_test_time
/= dtls
->fast_poll
;
594 free_led_dtls(led_dtls_t
*dtls
)
600 if (dtls
->fcal_leds
!= NULL
)
601 free((void *)dtls
->fcal_leds
);
602 if (dtls
->fcal_status
!= NULL
)
603 free((void *)dtls
->fcal_status
);
604 if (dtls
->fcal_driver
!= NULL
)
605 free((void *)dtls
->fcal_driver
);
606 if (dtls
->presence
!= NULL
)
607 free((void *)dtls
->presence
);
608 if (dtls
->faults
!= NULL
)
609 free((void *)dtls
->faults
);
610 if (dtls
->disk_detected
!= NULL
)
611 free((void *)dtls
->disk_detected
);
612 if (dtls
->disk_ready
!= NULL
)
613 free((void *)dtls
->disk_ready
);
614 if (dtls
->disk_prev
!= NULL
)
615 free((void *)dtls
->disk_prev
);
616 if (dtls
->led_test_end
!= NULL
)
617 free((void *)dtls
->led_test_end
);
618 if (dtls
->picl_retry
!= NULL
)
619 free((void *)dtls
->picl_retry
);
620 if (dtls
->disk_port
!= NULL
) {
621 for (i
= 0; i
< dtls
->n_disks
; i
++) {
622 free(dtls
->disk_port
[i
]);
624 free(dtls
->disk_port
);
626 for (i
= 0; i
< FCAL_LED_CNT
; i
++) {
627 if (dtls
->led_addr
[i
] != NULL
)
628 free((void *)dtls
->led_addr
[i
]);
629 if (dtls
->led_state
[i
] != NULL
)
630 free((void *)dtls
->led_state
[i
]);