xref: /titanic_44/usr/src/uts/common/io/bscv.c (revision 01ef659d9b1ead333ef0adc346e7051f7eae7520)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 
27 /*
28  * bscv.c - multi-threaded lom driver for the Stiletto platform.
29  */
30 
31 /*
32  * Included files.
33  */
34 
35 #include <sys/note.h>
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include <sys/uio.h>
39 #include <sys/open.h>
40 #include <sys/cred.h>
41 #include <sys/stream.h>
42 #include <sys/systm.h>
43 #include <sys/conf.h>
44 #include <sys/reboot.h>
45 #include <sys/modctl.h>
46 #include <sys/mkdev.h>
47 #include <sys/errno.h>
48 #include <sys/debug.h>
49 #include <sys/kmem.h>
50 #include <sys/consdev.h>
51 #include <sys/file.h>
52 #include <sys/stat.h>
53 #include <sys/disp.h>
54 #include <sys/ddi.h>
55 #include <sys/sunddi.h>
56 #include <sys/stream.h>
57 #include <sys/strlog.h>
58 #include <sys/log.h>
59 #include <sys/utsname.h>
60 #include <sys/callb.h>
61 #include <sys/sysevent.h>
62 #include <sys/nvpair.h>
63 #include <sys/sysevent/eventdefs.h>
64 #include <sys/sysevent/domain.h>
65 #include <sys/sysevent/env.h>
66 #include <sys/sysevent/dr.h>
67 
68 #include <sys/lom_io.h>
69 #include <sys/bscbus.h>
70 #include <sys/bscv_impl.h>
71 
72 /*
73  * Variables defined here and visible internally only
74  */
75 
76 static void *bscv_statep = NULL;
77 
78 /*
79  * Forward declarations
80  */
81 
82 static int bscv_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
83 static int bscv_attach(dev_info_t *, ddi_attach_cmd_t);
84 static int bscv_detach(dev_info_t *, ddi_detach_cmd_t);
85 static int bscv_reset(dev_info_t *, ddi_reset_cmd_t);
86 static int bscv_quiesce(dev_info_t *);
87 static int bscv_map_regs(bscv_soft_state_t *);
88 static void bscv_unmap_regs(bscv_soft_state_t *);
89 static void bscv_map_chan_logical_physical(bscv_soft_state_t *);
90 
91 static int bscv_open(dev_t *, int, int, cred_t *);
92 static int bscv_close(dev_t, int, int, cred_t *);
93 static void bscv_full_stop(bscv_soft_state_t *);
94 
95 static void bscv_enter(bscv_soft_state_t *);
96 static int bscv_tryenter(bscv_soft_state_t *ssp);
97 static void bscv_exit(bscv_soft_state_t *);
98 #ifdef DEBUG
99 static int bscv_held(bscv_soft_state_t *);
100 #endif /* DEBUG */
101 
102 static void bscv_put8(bscv_soft_state_t *, int, bscv_addr_t, uint8_t);
103 static void bscv_put16(bscv_soft_state_t *, int, bscv_addr_t, uint16_t);
104 static void bscv_put32(bscv_soft_state_t *, int, bscv_addr_t, uint32_t);
105 static uint8_t bscv_get8(bscv_soft_state_t *, int, bscv_addr_t);
106 static uint16_t bscv_get16(bscv_soft_state_t *, int, bscv_addr_t);
107 static uint32_t bscv_get32(bscv_soft_state_t *, int, bscv_addr_t);
108 static void bscv_setclear8(bscv_soft_state_t *, int,
109 	bscv_addr_t, uint8_t, uint8_t);
110 static void bscv_setclear8_volatile(bscv_soft_state_t *, int,
111 	bscv_addr_t, uint8_t, uint8_t);
112 static void bscv_rep_rw8(bscv_soft_state_t *, int,
113 	uint8_t *, bscv_addr_t, size_t, uint_t, boolean_t);
114 static uint8_t bscv_get8_cached(bscv_soft_state_t *, bscv_addr_t);
115 
116 static uint8_t bscv_get8_locked(bscv_soft_state_t *, int, bscv_addr_t, int *);
117 static void bscv_rep_get8_locked(bscv_soft_state_t *, int,
118 	uint8_t *, bscv_addr_t, size_t, uint_t, int *);
119 
120 static boolean_t bscv_faulty(bscv_soft_state_t *);
121 static void bscv_clear_fault(bscv_soft_state_t *);
122 static void bscv_set_fault(bscv_soft_state_t *);
123 static boolean_t bscv_session_error(bscv_soft_state_t *);
124 static int bscv_retcode(bscv_soft_state_t *);
125 static int bscv_should_retry(bscv_soft_state_t *);
126 static void bscv_locked_result(bscv_soft_state_t *, int *);
127 
128 static void bscv_put8_once(bscv_soft_state_t *, int, bscv_addr_t, uint8_t);
129 static uint8_t bscv_get8_once(bscv_soft_state_t *, int, bscv_addr_t);
130 static uint32_t bscv_probe(bscv_soft_state_t *, int, uint32_t *);
131 static void bscv_resync_comms(bscv_soft_state_t *, int);
132 
133 static boolean_t bscv_window_setup(bscv_soft_state_t *);
134 static int bscv_eerw(bscv_soft_state_t *, uint32_t, uint8_t *,
135     unsigned, boolean_t);
136 
137 static int bscv_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
138 static int bscv_ioc_dogstate(bscv_soft_state_t *, intptr_t, int);
139 static int bscv_ioc_psustate(bscv_soft_state_t *, intptr_t, int);
140 static int bscv_ioc_fanstate(bscv_soft_state_t *, intptr_t, int);
141 static int bscv_ioc_fledstate(bscv_soft_state_t *, intptr_t, int);
142 static int bscv_ioc_ledstate(bscv_soft_state_t *, intptr_t, int);
143 static int bscv_ioc_info(bscv_soft_state_t *, intptr_t, int);
144 static int bscv_ioc_mread(bscv_soft_state_t *, intptr_t, int);
145 static int bscv_ioc_volts(bscv_soft_state_t *, intptr_t, int);
146 static int bscv_ioc_stats(bscv_soft_state_t *, intptr_t, int);
147 static int bscv_ioc_temp(bscv_soft_state_t *, intptr_t, int);
148 static int bscv_ioc_cons(bscv_soft_state_t *, intptr_t, int);
149 static int bscv_ioc_eventlog2(bscv_soft_state_t *, intptr_t, int);
150 static int bscv_ioc_info2(bscv_soft_state_t *, intptr_t, int);
151 static int bscv_ioc_test(bscv_soft_state_t *, intptr_t, int);
152 static int bscv_ioc_mprog2(bscv_soft_state_t *, intptr_t, int);
153 static int bscv_ioc_mread2(bscv_soft_state_t *, intptr_t, int);
154 
155 static void bscv_event_daemon(void *);
156 static void bscv_start_event_daemon(bscv_soft_state_t *);
157 static int bscv_stop_event_daemon(bscv_soft_state_t *);
158 static int bscv_pause_event_daemon(bscv_soft_state_t *);
159 static void bscv_resume_event_daemon(bscv_soft_state_t *);
160 static void bscv_event_process(bscv_soft_state_t *ssp, boolean_t);
161 static int bscv_event_validate(bscv_soft_state_t *, uint32_t, uint8_t);
162 static void bscv_event_process_one(bscv_soft_state_t *, lom_event_t *);
163 static void bscv_build_eventstring(bscv_soft_state_t *,
164     lom_event_t *, char *, char *);
165 static int bscv_level_of_event(lom_event_t *);
166 static void bscv_status(bscv_soft_state_t *, uint8_t, uint8_t);
167 char *bscv_get_label(char [][MAX_LOM2_NAME_STR], int, int);
168 static void bscv_generic_sysevent(bscv_soft_state_t *, char *, char *, char *,
169     char *, int32_t, char *);
170 static void bscv_sysevent(bscv_soft_state_t *, lom_event_t *);
171 
172 static int bscv_prog(bscv_soft_state_t *, intptr_t, int);
173 static int bscv_prog_image(bscv_soft_state_t *, boolean_t,
174     uint8_t *, int, uint32_t);
175 static int bscv_prog_receive_image(bscv_soft_state_t *, lom_prog_t *,
176     uint8_t *, int);
177 static void bscv_leave_programming_mode(bscv_soft_state_t *, boolean_t);
178 static int bscv_prog_stop_lom(bscv_soft_state_t *);
179 static int bscv_prog_start_lom(bscv_soft_state_t *);
180 
181 static int bscv_attach_common(bscv_soft_state_t *);
182 static int bscv_cleanup(bscv_soft_state_t *);
183 static void bscv_setup_capability(bscv_soft_state_t *);
184 static int bscv_probe_check(bscv_soft_state_t *);
185 static void bscv_setup_hostname(bscv_soft_state_t *);
186 static void bscv_read_hostname(bscv_soft_state_t *, char *);
187 static void bscv_write_hostname(bscv_soft_state_t *, char *, uint8_t);
188 static void bscv_setup_static_info(bscv_soft_state_t *);
189 static uint8_t bscv_read_env_name(bscv_soft_state_t *, uint8_t,
190     uint8_t, uint8_t, char [][MAX_LOM2_NAME_STR], int);
191 static void bscv_setup_events(bscv_soft_state_t *);
192 
193 static void bscv_trace(bscv_soft_state_t *, char, const char *,
194     const char *, ...);
195 
196 #ifdef __sparc
197 static void bscv_idi_init();
198 static void bscv_idi_fini();
199 static void bscv_idi_new_instance(dev_info_t *dip);
200 static void bscv_idi_clear_err();
201 void bscv_idi_set(struct bscv_idi_info info);
202 static boolean_t bscv_idi_err();
203 static boolean_t bscv_nodename_set(struct bscv_idi_info info);
204 static boolean_t bscv_sig_set(struct bscv_idi_info info);
205 static boolean_t bscv_wdog_pat(struct bscv_idi_info info);
206 static boolean_t bscv_wdog_cfg(struct bscv_idi_info info);
207 static void bscv_write_sig(bscv_soft_state_t *ssp, bscv_sig_t s);
208 #endif /* __sparc */
209 
210 static void bscv_setup_watchdog(bscv_soft_state_t *ssp);
211 static void bscv_write_wdog_cfg(bscv_soft_state_t *,
212     uint_t, boolean_t, uint8_t);
213 
214 #if defined(__i386) || defined(__amd64)
215 static void bscv_inform_bsc(bscv_soft_state_t *, uint32_t);
216 static void bscv_watchdog_pat_request(void *);
217 static void bscv_watchdog_cfg_request(bscv_soft_state_t *, uint8_t);
218 static uint_t bscv_set_watchdog_timer(bscv_soft_state_t *, uint_t);
219 static void bscv_clear_watchdog_timer(bscv_soft_state_t *);
220 
221 static boolean_t bscv_panic_callback(void *, int);
222 static void bscv_watchdog_cyclic_add(bscv_soft_state_t *);
223 static void bscv_watchdog_cyclic_remove(bscv_soft_state_t *);
224 
225 static uint8_t	wdog_reset_on_timeout = 1;
226 
227 #define	WDOG_ON			1
228 #define	WDOG_OFF		0
229 #define	CLK_WATCHDOG_DEFAULT	10		/* 10 seconds */
230 #define	WATCHDOG_PAT_INTERVAL	1000000000	/* 1 second */
231 
232 static int	bscv_watchdog_enable;
233 static int	bscv_watchdog_available;
234 static int	watchdog_activated;
235 static uint_t	bscv_watchdog_timeout_seconds;
236 #endif /* __i386 || __amd64 */
237 
238 #ifdef __sparc
239 struct bscv_idi_callout bscv_idi_callout_table[] = {
240 	{BSCV_IDI_NODENAME,	&bscv_nodename_set	},
241 	{BSCV_IDI_SIG,		&bscv_sig_set		},
242 	{BSCV_IDI_WDOG_PAT,	&bscv_wdog_pat		},
243 	{BSCV_IDI_WDOG_CFG,	&bscv_wdog_cfg		},
244 	{BSCV_IDI_NULL,		NULL			}
245 };
246 
247 static struct bscv_idi_callout_mgr bscv_idi_mgr;
248 #endif /* __sparc */
249 
250 /*
251  * Local Definitions
252  */
253 #define	STATUS_READ_LIMIT	8   /* Read up to 8 status changes at a time */
254 #define	MYNAME			"bscv"
255 #define	BSCV_INST_TO_MINOR(i)	(i)
256 #define	BSCV_MINOR_TO_INST(m)	(m)
257 
258 /*
259  * Strings for daemon event reporting
260  */
261 
262 static char *eventSubsysStrings[] =
263 {	"",				/* 00 */
264 	"Alarm ",			/* 01 */
265 	"temperature sensor ",		/* 02 */
266 	"overheat sensor ",		/* 03 */
267 	"Fan ",				/* 04 */
268 	"supply rail ",			/* 05 */
269 	"circuit breaker ",		/* 06 */
270 	"PSU ",				/* 07 */
271 	"user ",			/* 08 */
272 	"phonehome ",			/* 09; unutilized */
273 	"LOM ",				/* 0a */
274 	"host ",			/* 0b */
275 	"event log ",			/* 0c */
276 	"",				/* 0d; EVENT_SUBSYS_EXTRA unutilized */
277 	"LED ",				/* 0e */
278 };
279 
280 static char *eventTypeStrings[] =
281 {
282 	"[null event]",			/* 00 */
283 	"ON",				/* 01 */
284 	"OFF",				/* 02 */
285 	"state change",			/* 03 */
286 	"power on",			/* 04 */
287 	"power off",			/* 05 */
288 	"powered off unexpectedly",	/* 06 */
289 	"reset unexpectedly",		/* 07 */
290 	"booted",			/* 08 */
291 	"watchdog enabled",		/* 09 */
292 	"watchdog disabled",		/* 0a */
293 	"watchdog triggered",		/* 0b */
294 	"failed",			/* 0c */
295 	"recovered",			/* 0d */
296 	"reset",			/* 0e */
297 	"XIR reset",			/* 0f */
298 	"console selected",		/* 10 */
299 	"time reference",		/* 11 */
300 	"script failure",		/* 12 */
301 	"modem access failure",		/* 13 */
302 	"modem dialing failure",	/* 14 */
303 	"bad checksum",			/* 15 */
304 	"added",			/* 16 */
305 	"removed",			/* 17 */
306 	"changed",			/* 18 */
307 	"login",			/* 19 */
308 	"password changed",		/* 1a */
309 	"login failed",			/* 1b */
310 	"logout",			/* 1c */
311 	"flash download",		/* 1d */
312 	"data lost",			/* 1e */
313 	"device busy",			/* 1f */
314 	"fault led state",		/* 20 */
315 	"overheat",			/* 21 */
316 	"severe overheat",		/* 22 */
317 	"no overheat",			/* 23 */
318 	"SCC",				/* 24 */
319 	"device inaccessible",		/* 25 */
320 	"Hostname change",		/* 26 */
321 	"CPU signature timeout",	/* 27 */
322 	"Bootmode change",		/* 28 */
323 	"Watchdog change policy",	/* 29 */
324 	"Watchdog change timeout",	/* 2a */
325 };
326 
327 /*
328  * These store to mapping between the logical service, e.g. chan_prog for
329  * programming, and the actual Xbus channel which carries that traffic.
330  * Any services can be shared on the same channel apart from chan_wdogpat.
331  */
332 static int chan_general;	/* General Traffic */
333 static int chan_wdogpat;	/* Watchdog Patting */
334 static int chan_cpusig;		/* CPU signatures */
335 static int chan_eeprom;		/* EEPROM I/O */
336 static int chan_prog;		/* Programming */
337 
338 /*
339  * cb_ops structure defining the driver entry points
340  */
341 
342 static struct cb_ops bscv_cb_ops = {
343 	bscv_open,	/* open */
344 	bscv_close,	/* close */
345 	nodev,		/* strategy */
346 	nodev,		/* print */
347 	nodev,		/* dump */
348 	nodev,		/* read */
349 	nodev,		/* write */
350 	bscv_ioctl,	/* ioctl */
351 	nodev,		/* devmap */
352 	nodev,		/* mmap */
353 	nodev,		/* segmap */
354 	nochpoll,	/* poll */
355 	ddi_prop_op,	/* prop op */
356 	NULL,		/* ! STREAMS */
357 	D_NEW | D_MP	/* MT/MP Safe */
358 };
359 
360 /*
361  * dev_ops structure defining autoconfiguration driver autoconfiguration
362  * routines
363  */
364 
365 static struct dev_ops bscv_dev_ops = {
366 	DEVO_REV,		/* devo_rev */
367 	0,			/* devo_refcnt */
368 	bscv_getinfo,		/* devo_getinfo */
369 	nulldev,		/* devo_identify */
370 	nulldev,		/* devo_probe */
371 	bscv_attach,		/* devo_attach */
372 	bscv_detach,		/* devo_detach */
373 	bscv_reset,		/* devo_reset */
374 	&bscv_cb_ops,		/* devo_cb_ops */
375 	(struct bus_ops *)0,	/* devo_bus_ops */
376 	NULL,			/* devo_power */
377 	bscv_quiesce,		/* devo_quiesce */
378 };
379 
380 /*
381  * module configuration section
382  */
383 
384 #ifdef DEBUG
385 #define	BSCV_VERSION_STRING "bscv driver - Debug"
386 #else /* DEBUG */
387 #define	BSCV_VERSION_STRING "bscv driver"
388 #endif /* DEBUG */
389 
390 static struct modldrv modldrv = {
391 	&mod_driverops,
392 	BSCV_VERSION_STRING,
393 	&bscv_dev_ops,
394 };
395 
396 static struct modlinkage modlinkage = {
397 	MODREV_1,
398 	&modldrv,
399 	NULL
400 };
401 
402 #ifdef DEBUG
403 /* Tracing is enabled if value is non-zero. */
404 static int bscv_trace_flag = 1;
405 
406 #define	BSCV_TRACE   if (bscv_trace_flag != 0)	bscv_trace
407 #else
408 #define	BSCV_TRACE
409 #endif
410 
411 /*
412  * kernel accessible routines. These routines are necessarily global so the
413  * driver can be loaded, and unloaded successfully
414  */
415 
416 /*
417  * function	- _init
418  * description	- initializes the driver state structure and installs the
419  *		  driver module into the kernel
420  * inputs	- none
421  * outputs	- success or failure of module installation
422  */
423 
424 int
425 _init(void)
426 {
427 	register int e;
428 
429 	if ((e = ddi_soft_state_init(&bscv_statep,
430 	    sizeof (bscv_soft_state_t), 1)) != 0) {
431 		return (e);
432 	}
433 
434 	if ((e = mod_install(&modlinkage)) != 0) {
435 		ddi_soft_state_fini(&bscv_statep);
436 	}
437 
438 #ifdef __sparc
439 	if (e == 0) bscv_idi_init();
440 #endif /* __sparc */
441 	return (e);
442 }
443 
444 /*
445  * function	- _info
446  * description	- provide information about a kernel loaded module
447  * inputs	- module infomation
448  * outputs	- success or failure of information request
449  */
450 
451 int
452 _info(struct modinfo *modinfop)
453 {
454 	return (mod_info(&modlinkage, modinfop));
455 }
456 
457 /*
458  * function	- _fini
459  * description	- removes a module from the kernel and frees the driver soft
460  *		  state memory
461  * inputs	- none
462  * outputs	- success or failure of module removal
463  */
464 
465 int
466 _fini(void)
467 {
468 	register int e;
469 
470 	if ((e = mod_remove(&modlinkage)) != 0) {
471 		return (e);
472 	}
473 
474 #ifdef __sparc
475 	bscv_idi_fini();
476 #endif /* __sparc */
477 	ddi_soft_state_fini(&bscv_statep);
478 
479 	return (e);
480 }
481 
482 /*
483  * function	- bscv_getinfo
484  * description	- routine used to provide information on the driver
485  * inputs	- device information structure, command, command arg, storage
486  *		  area for the result
487  * outputs	- DDI_SUCCESS or DDI_FAILURE
488  */
489 
490 /*ARGSUSED*/
491 static int
492 bscv_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
493 {
494 	bscv_soft_state_t *ssp;
495 	dev_t	dev = (dev_t)arg;
496 	int	instance;
497 	int	error;
498 
499 	instance = DEVICETOINSTANCE(dev);
500 
501 	switch (cmd) {
502 	case DDI_INFO_DEVT2INSTANCE:
503 		*result = (void *)(uintptr_t)instance;
504 		error = DDI_SUCCESS;
505 		break;
506 
507 	case DDI_INFO_DEVT2DEVINFO:
508 		ssp = ddi_get_soft_state(bscv_statep, instance);
509 		if (ssp == NULL)
510 			return (DDI_FAILURE);
511 		*result = (void *) ssp->dip;
512 		error = DDI_SUCCESS;
513 		break;
514 
515 	default:
516 		error = DDI_FAILURE;
517 		break;
518 	}
519 
520 	return (error);
521 }
522 
523 #ifdef __sparc
524 void
525 bscv_idi_init()
526 {
527 	bscv_idi_mgr.valid_inst = (uint32_t)~0;    /* No valid instances */
528 	bscv_idi_mgr.tbl = bscv_idi_callout_table;
529 	bscv_idi_mgr.errs = 0;
530 
531 	/*
532 	 * Now that all fields are initialized, set the magic flag.  This is
533 	 * a kind of integrity check for the data structure.
534 	 */
535 	bscv_idi_mgr.magic = BSCV_IDI_CALLOUT_MAGIC;
536 }
537 
538 static void
539 bscv_idi_clear_err()
540 {
541 	ASSERT(bscv_idi_mgr.magic == BSCV_IDI_CALLOUT_MAGIC);
542 
543 	bscv_idi_mgr.errs = 0;
544 }
545 
546 /*
547  * function	- bscv_idi_err
548  * description	- error messaging service which throttles the number of error
549  *		  messages to avoid overflowing storage
550  * inputs	- none
551  * returns	- boolean to indicate whether a message should be reported
552  * side-effects	- updates the error number counter
553  */
554 static boolean_t
555 bscv_idi_err()
556 {
557 	ASSERT(bscv_idi_mgr.magic == BSCV_IDI_CALLOUT_MAGIC);
558 
559 	bscv_idi_mgr.errs++;
560 
561 	if (bscv_idi_mgr.errs++ < BSCV_IDI_ERR_MSG_THRESHOLD)
562 		return (B_TRUE);
563 
564 	return (B_FALSE);
565 }
566 
567 void
568 bscv_idi_new_instance(dev_info_t *dip)
569 {
570 	ASSERT(bscv_idi_mgr.magic == BSCV_IDI_CALLOUT_MAGIC);
571 
572 	/*
573 	 * We don't care how many instances we have, or their value, so long
574 	 * as we have at least one valid value.  This is so service routines
575 	 * can get any required locks via a soft state pointer.
576 	 */
577 	if (bscv_idi_mgr.valid_inst == (uint32_t)~0) {
578 		bscv_idi_mgr.valid_inst = ddi_get_instance(dip);
579 	}
580 }
581 
582 void
583 bscv_idi_fini()
584 {
585 	bscv_idi_mgr.valid_inst = (uint32_t)~0;    /* No valid instances */
586 	bscv_idi_mgr.tbl = NULL;
587 }
588 #endif /* __sparc */
589 
590 /*
591  * function	- bscv_attach
592  * description	- this routine is responsible for setting aside memory for the
593  *		  driver data structures, initialising the mutexes and creating
594  *		  the device minor nodes. Additionally, this routine calls the
595  *		  the callback routine.
596  * inputs	- device information structure, DDI_ATTACH command
597  * outputs	- DDI_SUCCESS or DDI_FAILURE
598  */
599 
600 int
601 bscv_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
602 {
603 	bscv_soft_state_t *ssp;
604 	int	instance;
605 
606 	switch (cmd) {
607 	case DDI_ATTACH:
608 
609 		instance = ddi_get_instance(dip);
610 
611 		if (ddi_soft_state_zalloc(bscv_statep, instance) !=
612 		    DDI_SUCCESS) {
613 			return (DDI_FAILURE);
614 		}
615 
616 
617 		ssp = ddi_get_soft_state(bscv_statep, instance);
618 
619 		ssp->progress = 0;
620 
621 		ssp->dip = dip;
622 		ssp->instance = instance;
623 		ssp->event_waiting = B_FALSE;
624 		ssp->status_change = B_FALSE;
625 		ssp->nodename_change = B_FALSE;
626 		ssp->cap0 = 0;
627 		ssp->cap1 = 0;
628 		ssp->cap2 = 0;
629 		ssp->prog_mode_only = B_FALSE;
630 		ssp->programming = B_FALSE;
631 		ssp->cssp_prog = B_FALSE;
632 		ssp->task_flags = 0;
633 		ssp->debug = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
634 		    DDI_PROP_DONTPASS, "debug", 0);
635 		ssp->majornum = ddi_driver_major(dip);
636 		ssp->minornum = BSCV_INST_TO_MINOR(instance);
637 #if defined(__i386) || defined(__amd64)
638 		ssp->last_nodename[0] = '\0';
639 #endif /* __i386 || __amd64 */
640 
641 		/*
642 		 * initialise the mutexes
643 		 */
644 
645 		mutex_init(&ssp->cmd_mutex, NULL, MUTEX_DRIVER, NULL);
646 
647 		mutex_init(&ssp->task_mu, NULL, MUTEX_DRIVER, NULL);
648 		cv_init(&ssp->task_cv, NULL, CV_DRIVER, NULL);
649 		cv_init(&ssp->task_evnt_cv, NULL, CV_DRIVER, NULL);
650 		mutex_init(&ssp->prog_mu, NULL, MUTEX_DRIVER, NULL);
651 		ssp->progress |= BSCV_LOCKS;
652 
653 		BSCV_TRACE(ssp, 'A', "bscv_attach",
654 		    "bscv_attach: mutexes and condition vars initialised");
655 
656 		/* Map in physical communication channels */
657 
658 		if (bscv_map_regs(ssp) != DDI_SUCCESS) {
659 			(void) bscv_cleanup(ssp);
660 			return (DDI_FAILURE);
661 		}
662 		ssp->progress |= BSCV_MAPPED_REGS;
663 
664 		/* Associate logical channels to physical channels */
665 
666 		bscv_map_chan_logical_physical(ssp);
667 
668 		bscv_enter(ssp);
669 
670 		bscv_leave_programming_mode(ssp, B_FALSE);
671 
672 		if (bscv_attach_common(ssp) == DDI_FAILURE) {
673 			bscv_exit(ssp);
674 			(void) bscv_cleanup(ssp);
675 			return (DDI_FAILURE);
676 		}
677 
678 #ifdef __sparc
679 		/*
680 		 * At this point the inter-driver-interface is made available.
681 		 * The IDI uses the event thread service which
682 		 * bscv_attach_common() sets up.
683 		 */
684 		bscv_idi_new_instance(dip);
685 #endif /* __sparc */
686 
687 		bscv_exit(ssp);
688 
689 		/*
690 		 * now create the minor nodes
691 		 */
692 		if (ddi_create_minor_node(ssp->dip, "lom", S_IFCHR,
693 		    BSCV_INST_TO_MINOR(instance),
694 		    DDI_PSEUDO, 0) != DDI_SUCCESS) {
695 			(void) bscv_cleanup(ssp);
696 			return (DDI_FAILURE);
697 		}
698 		BSCV_TRACE(ssp, 'A', "bscv_attach",
699 		    "bscv_attach: device minor nodes created");
700 		ssp->progress |= BSCV_NODES;
701 
702 		if (!ssp->prog_mode_only)
703 			bscv_start_event_daemon(ssp);
704 
705 #if defined(__i386) || defined(__amd64)
706 		bscv_watchdog_enable = 1;
707 		bscv_watchdog_available = 1;
708 		watchdog_activated = 0;
709 		bscv_watchdog_timeout_seconds = CLK_WATCHDOG_DEFAULT;
710 
711 		if (bscv_watchdog_enable && (boothowto & RB_DEBUG)) {
712 			bscv_watchdog_available = 0;
713 			cmn_err(CE_WARN, "bscv: kernel debugger "
714 			    "detected: hardware watchdog disabled");
715 		}
716 
717 		/*
718 		 * Before we enable the watchdog - register the panic
719 		 * callback so that we get called to stop the watchdog
720 		 * in the case of a panic.
721 		 */
722 		ssp->callb_id = callb_add(bscv_panic_callback,
723 		    (void *)ssp, CB_CL_PANIC, "");
724 
725 		if (bscv_watchdog_available) {
726 			(void) bscv_set_watchdog_timer(ssp,
727 			    CLK_WATCHDOG_DEFAULT);
728 			bscv_enter(ssp);
729 			bscv_setup_watchdog(ssp);  /* starts cyclic callback */
730 			bscv_exit(ssp);
731 		}
732 #endif /* __i386 || __amd64 */
733 		ddi_report_dev(dip);
734 		return (DDI_SUCCESS);
735 	default:
736 		return (DDI_FAILURE);
737 	}
738 }
739 
740 /*
741  * function	- bscv_detach
742  * description	- routine that prepares a module to be unloaded. It undoes all
743  *		  the work done by the bscv_attach)() routine. This is
744  *		  facilitated by the use of the progress indicator
745  * inputs	- device information structure, DDI_DETACH command
746  * outputs	- DDI_SUCCESS or DDI_FAILURE
747  */
748 
749 /*ARGSUSED*/
750 static int
751 bscv_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
752 {
753 	return (DDI_FAILURE);
754 }
755 
756 /*
757  * function	- bscv_reset
758  * description	- routine that implements the obsolete devo_reset entry point.
759  *		  MAN page declares that devo_quiesce subsumes devo_reset
760  *		  functionality.
761  * inputs	- device information structure, DDI_RESET command
762  * outputs	- DDI_SUCCESS or DDI_FAILURE
763  */
764 static int
765 bscv_reset(dev_info_t *dip, ddi_reset_cmd_t cmd)
766 {
767 	switch (cmd) {
768 	case DDI_RESET_FORCE:
769 		return (bscv_quiesce(dip));
770 	default:
771 		return (DDI_FAILURE);
772 	}
773 }
774 
775 /*
776  * quiesce(9E) entry point.
777  *
778  * This function is called when the system is single-threaded at high
779  * PIL with preemption disabled. Therefore, this function must not be
780  * blocked.
781  *
782  * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
783  * DDI_FAILURE indicates an error condition and should almost never happen.
784  */
785 static int
786 bscv_quiesce(dev_info_t *dip)
787 {
788 	bscv_soft_state_t *ssp;
789 	int	instance;
790 
791 
792 	instance = ddi_get_instance(dip);
793 	ssp = ddi_get_soft_state(bscv_statep, instance);
794 	if (ssp == NULL) {
795 		return (DDI_FAILURE);
796 	}
797 #ifdef DEBUG
798 	/* Disable tracing, as we are executing at High-Interrupt level */
799 	bscv_trace_flag = 0;
800 #endif
801 	/* quiesce the device */
802 	bscv_full_stop(ssp);
803 
804 	return (DDI_SUCCESS);
805 }
806 
807 /*
808  * cb_ops routines
809  */
810 
811 /*
812  * function	- bscv_open
813  * description	- routine to provide association between user fd and device
814  *		  minor number. This routine is necessarily simple since a
815  *		  read/write interface is not provided. Additionally, the
816  *		  driver does not enforce exclusive access (FEXCL) or
817  *		  non-blocking during an open (FNDELAY). Deferred attach is
818  *		  supported.
819  * inputs	- device number, flag specifying open type, device type,
820  *		  permissions
821  * outputs	- success or failure of operation
822  */
823 
824 /*ARGSUSED*/
825 static int
826 bscv_open(dev_t *devp, int flag, int otype, cred_t *cred)
827 {
828 	bscv_soft_state_t *ssp;
829 	int instance;
830 
831 	instance = DEVICETOINSTANCE(*devp);
832 	ssp = ddi_get_soft_state(bscv_statep, instance);
833 	if (ssp == NULL) {
834 		return (ENXIO);	/* not attached yet */
835 	}
836 	BSCV_TRACE(ssp, 'O', "bscv_open", "instance 0x%x", instance);
837 
838 	if (otype != OTYP_CHR) {
839 		return (EINVAL);
840 	}
841 
842 	return (0);
843 }
844 
845 /*
846  * function	- bscv_close
847  * description	- routine to perform the final close on the device. As per the
848  *		  open routine, neither FEXCL or FNDELAY accesses are enforced
849  *		  by the driver.
850  * inputs	- device number,flag specifying open type, device type,
851  *		  permissions
852  * outputs	- success or failure of operation
853  */
854 
855 /*ARGSUSED1*/
856 static int
857 bscv_close(dev_t dev, int flag, int otype, cred_t *cred)
858 {
859 	bscv_soft_state_t *ssp;
860 	int instance;
861 
862 	instance = DEVICETOINSTANCE(dev);
863 	ssp = ddi_get_soft_state(bscv_statep, instance);
864 	if (ssp == NULL) {
865 		return (ENXIO);
866 	}
867 	BSCV_TRACE(ssp, 'O', "bscv_close", "instance 0x%x", instance);
868 
869 	return (0);
870 }
871 
872 static int
873 bscv_map_regs(bscv_soft_state_t *ssp)
874 {
875 	int i;
876 	int retval;
877 	int *props;
878 	unsigned int nelements;
879 
880 	ASSERT(ssp);
881 
882 	ssp->nchannels = 0;
883 
884 	/*
885 	 * Work out how many channels are available by looking at the number
886 	 * of elements of the regs property array.
887 	 */
888 	retval = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, ssp->dip,
889 	    DDI_PROP_DONTPASS, "reg", &props, &nelements);
890 
891 	/* We don't need props anymore.  Free memory if it was allocated */
892 	if (retval == DDI_PROP_SUCCESS)
893 		ddi_prop_free(props);
894 
895 	/* Check for sanity of nelements */
896 	if (retval != DDI_PROP_SUCCESS) {
897 		BSCV_TRACE(ssp, 'A', "bscv_map_regs", "lookup reg returned"
898 		    " 0x%x", retval);
899 		goto cleanup_exit;
900 	} else if (nelements % LOMBUS_REGSPEC_SIZE != 0) {
901 		BSCV_TRACE(ssp, 'A', "bscv_map_regs", "nelements %d not"
902 		    " a multiple of %d", nelements, LOMBUS_REGSPEC_SIZE);
903 		goto cleanup_exit;
904 	} else if (nelements > BSCV_MAXCHANNELS * LOMBUS_REGSPEC_SIZE) {
905 		BSCV_TRACE(ssp, 'A', "bscv_map_regs", "nelements %d too large"
906 		    ", probably a misconfiguration", nelements);
907 		goto cleanup_exit;
908 	} else if (nelements < BSCV_MINCHANNELS * LOMBUS_REGSPEC_SIZE) {
909 		BSCV_TRACE(ssp, 'A', "bscv_map_regs", "nelements %d too small"
910 		    ", need to have at least a general and a wdog channel",
911 		    nelements);
912 		goto cleanup_exit;
913 	}
914 
915 	ssp->nchannels = nelements / LOMBUS_REGSPEC_SIZE;
916 
917 	ssp->attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
918 	ssp->attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
919 	ssp->attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
920 
921 	for (i = 0; i < ssp->nchannels; i++) {
922 		retval = ddi_regs_map_setup(ssp->dip, i,
923 		    (caddr_t *)&ssp->channel[i].regs,
924 		    0, 0, &ssp->attr, &ssp->channel[i].handle);
925 		if (retval != DDI_SUCCESS) {
926 			BSCV_TRACE(ssp, 'A', "bscv_map_regs", "map failure"
927 			    " 0x%x on space %d", retval, i);
928 
929 			/* Rewind all current mappings - avoiding failed one */
930 			i--;
931 			for (; i >= 0; i--) {
932 				ddi_regs_map_free(&ssp->channel[i].handle);
933 			}
934 
935 			goto cleanup_exit;
936 		}
937 	}
938 
939 	return (DDI_SUCCESS);
940 
941 cleanup_exit:
942 	/*
943 	 * It is important to set nchannels to 0 even if, say, only one of
944 	 * the two required handles was mapped.  If we cannot achieve our
945 	 * minimum config its not safe to do any IO; this keeps our failure
946 	 * mode handling simpler.
947 	 */
948 	ssp->nchannels = 0;
949 	return (DDI_FAILURE);
950 }
951 
952 static void
953 bscv_unmap_regs(bscv_soft_state_t *ssp)
954 {
955 	int i;
956 
957 	ASSERT(ssp);
958 
959 	for (i = 0; i < ssp->nchannels; i++) {
960 		ddi_regs_map_free(&ssp->channel[i].handle);
961 	}
962 }
963 
964 /*
965  * Map logical services onto physical XBus channels.
966  */
967 static void
968 bscv_map_chan_logical_physical(bscv_soft_state_t *ssp)
969 {
970 	ASSERT(ssp);
971 
972 	/*
973 	 * We can assert that there will always be at least two channels,
974 	 * to allow watchdog pats to be segregated from all other traffic.
975 	 */
976 	chan_general = 0;
977 	chan_wdogpat = 1;
978 
979 	/*
980 	 * By default move all other services onto the generic channel unless
981 	 * the hardware supports additional channels.
982 	 */
983 
984 	chan_cpusig = chan_eeprom = chan_prog = chan_general;
985 
986 	if (ssp->nchannels > 2)
987 		chan_cpusig = 2;
988 	if (ssp->nchannels > 3)
989 		chan_eeprom = 3;
990 	if (ssp->nchannels > 4)
991 		chan_prog = 4;
992 }
993 
994 
995 /*
996  * function	- bscv_full_stop
997  * description	- gracefully shut the lom down during panic or reboot.
998  *		  Disables the watchdog and sets up serial event reporting.
999  * inputs	- soft state pointer
1000  * outputs	- none
1001  */
1002 void
1003 bscv_full_stop(bscv_soft_state_t *ssp)
1004 {
1005 	uint8_t bits2set = 0;
1006 	uint8_t bits2clear = 0;
1007 	int obtained_lock;
1008 
1009 	BSCV_TRACE(ssp, 'W', "bscv_full_stop",
1010 	    "turning off watchdog");
1011 
1012 	/*
1013 	 * Obtain the softstate lock only if it is not already owned,
1014 	 * as this function can be called from a High-level interrupt
1015 	 * context.  As a result, our thread cannot sleep.
1016 	 * At end of function, our thread releases the lock only if
1017 	 * it acquired the lock.
1018 	 */
1019 	obtained_lock = (bscv_tryenter(ssp) != 0);
1020 
1021 #if defined(__i386) || defined(__amd64)
1022 	if (ddi_in_panic()) {
1023 		bscv_inform_bsc(ssp, BSC_INFORM_PANIC);
1024 	} else {
1025 		bscv_inform_bsc(ssp, BSC_INFORM_OFFLINE);
1026 	}
1027 #endif /* __i386 || __amd64 */
1028 
1029 	/* set serial event reporting */
1030 	switch (ssp->serial_reporting) {
1031 	case LOM_SER_EVENTS_ON:
1032 	case LOM_SER_EVENTS_DEF:
1033 		/* Make sure serial event reporting is on */
1034 		bits2clear = EBUS_ALARM_NOEVENTS;
1035 		break;
1036 	case LOM_SER_EVENTS_OFF:
1037 		/* Make sure serial event reporting is on */
1038 		bits2set = EBUS_ALARM_NOEVENTS;
1039 		break;
1040 	default:
1041 		break;
1042 	}
1043 	bscv_setclear8_volatile(ssp, chan_general,
1044 	    EBUS_IDX_ALARM, bits2set, bits2clear);
1045 
1046 	/* Do not free the lock if our thread did not obtain it. */
1047 	if (obtained_lock != 0) {
1048 		bscv_exit(ssp);
1049 	}
1050 }
1051 
1052 /*
1053  * LOM I/O routines.
1054  *
1055  * locking
1056  *
1057  * Two sets of routines are provided:
1058  *	normal - must be called after acquiring an appropriate lock.
1059  *	locked - perform all the locking required and return any error
1060  *		 code in the supplied 'res' argument. If there is no
1061  *		 error 'res' is not changed.
1062  * The locked routines are designed for use in ioctl commands where
1063  * only a single operation needs to be performed and the overhead of
1064  * locking and result checking adds significantly to code complexity.
1065  *
1066  * locking primitives
1067  *
1068  * bscv_enter()    - acquires an I/O lock for the calling thread.
1069  * bscv_tryenter() - conditionally acquires an I/O lock for calling thread.
1070  * bscv_exit()     - releases an I/O lock acquired by bscv_enter().
1071  * bscv_held()     - used to assert ownership of an I/O lock.
1072  *
1073  * normal I/O routines
1074  *
1075  * Note bscv_{put|get}{16|32} routines are big-endian. This assumes that
1076  * the firmware works that way too.
1077  *
1078  * bscv_put8(), bscv_put16, bscv_put32 - write values to the LOM
1079  *		and handle any retries if necessary.
1080  *		16 and 32 bit values are big-endian.
1081  * bscv_get8(), bscv_get16, bscv_get32 - read values from the LOM
1082  *		and handle any retries if necessary.
1083  *		16 and 32 bit values are big-endian.
1084  * bscv_setclear8() - set or clear the specified bits in the register
1085  *		at the supplied address.
1086  * bscv_setclear8_volatile() - set or clear the specified bits in the
1087  *		register at the supplied address. If the lom reports
1088  *		that the registers has changed since the last read
1089  *		re-read and apply the set or clear to the new bits.
1090  * bscv_get8_cached() - Return a cached register value (addr < 0x80).
1091  *		Does not access the hardware. A read of the hardware
1092  *		automatically updates this cache.
1093  *
1094  * locked I/O routines
1095  *
1096  * bscv_get8_locked(), bscv_rep_get8_locked().
1097  *
1098  * Call the indicated function from above, but wrapping it with
1099  * bscv_enter()/bscv_exit().
1100  *
1101  *
1102  * Fault management
1103  *
1104  * LOM communications fault are grouped into three categories:
1105  * 1) Faulty - the LOM is not responding and no attempt to communicate
1106  *		with it should be made.
1107  * 2) Transient fault - something which might recover after a retry
1108  *		but which doesn't affect our ability to perform other
1109  *		commands.
1110  * 3) Command error - an inappropriate command was executed. A retry
1111  *		will not fix it but the command failed.
1112  *
1113  * The current implementation of the bscv driver is not very good at
1114  * noticing command errors due to the structure of the original code
1115  * that it is based on. It is possible to extend the driver to do this
1116  * and would probably involve having a concept of a "session error"
1117  * which is less severe than a fault but means that a sequence of
1118  * commands had some fault which cannot be recovered.
1119  *
1120  *
1121  * faults
1122  *
1123  * bscv_faulty() - returns B_TRUE if the LOM (communications) have been
1124  *		declared faulty.
1125  * bscv_clear_fault() - marks the LOM as not faulty.
1126  * bscv_set_fault() - marks the LOM as being faulty.
1127  *
1128  * bscv_clear_fault and bscv_set_fault should generally not be called
1129  * directly.
1130  *
1131  * command errors/transient faults
1132  *
1133  * bscv_retcode() - returns the actual error code of the last operation.
1134  * bscv_should_retry() - determines if last operation may suceed if
1135  *		retried.
1136  * bscv_locked_result() - Set the result of a locked register access.
1137  *
1138  * low level I/O primitives
1139  *
1140  * These are generally not called directly. These perform a single
1141  * access to the LOM device. They do not handle retries.
1142  *
1143  * bscv_put8_once()
1144  * bscv_get8_once()
1145  * bscv_probe() - perform a probe (NOP) operation to check out lom comms.
1146  * bscv_resync_comms() - resynchronise communications after a transient fault.
1147  */
1148 
1149 static void
1150 bscv_enter(bscv_soft_state_t *ssp)
1151 {
1152 	BSCV_TRACE(ssp, '@', "bscv_enter", "");
1153 	mutex_enter(&ssp->cmd_mutex);
1154 	ssp->had_session_error = B_FALSE;
1155 }
1156 
1157 static int
1158 bscv_tryenter(bscv_soft_state_t *ssp)
1159 {
1160 	int rv;
1161 
1162 	BSCV_TRACE(ssp, '@', "bscv_tryenter", "");
1163 	if ((rv = mutex_tryenter(&ssp->cmd_mutex)) != 0) {
1164 		ssp->had_session_error = B_FALSE;
1165 	}
1166 	return (rv);
1167 }
1168 
1169 static void
1170 bscv_exit(bscv_soft_state_t *ssp)
1171 {
1172 	mutex_exit(&ssp->cmd_mutex);
1173 	BSCV_TRACE(ssp, '@', "bscv_exit", "");
1174 }
1175 
1176 #ifdef DEBUG
1177 static int
1178 bscv_held(bscv_soft_state_t *ssp)
1179 {
1180 	return (mutex_owned(&ssp->cmd_mutex));
1181 }
1182 #endif /* DEBUG */
1183 
1184 static void
1185 bscv_put8(bscv_soft_state_t *ssp, int chan, bscv_addr_t addr, uint8_t val)
1186 {
1187 	boolean_t needretry;
1188 	int num_failures;
1189 
1190 	ASSERT(bscv_held(ssp));
1191 
1192 	if (bscv_faulty(ssp)) {
1193 		return;
1194 	}
1195 
1196 	BSCV_TRACE(ssp, '@', "bscv_put8",
1197 	    "addr 0x%x.%02x <= 0x%02x", addr >> 8, addr & 0xff, val);
1198 
1199 	for (num_failures = 0;
1200 	    num_failures < BSC_FAILURE_RETRY_LIMIT;
1201 	    num_failures++) {
1202 		bscv_put8_once(ssp, chan, addr, val);
1203 		needretry = bscv_should_retry(ssp);
1204 		if (!needretry) {
1205 			break;
1206 		}
1207 	}
1208 	if (ssp->command_error != 0) {
1209 		ssp->had_session_error = B_TRUE;
1210 	}
1211 
1212 	if (needretry) {
1213 		/* Failure - we ran out of retries */
1214 		cmn_err(CE_WARN, "bscv_put8: addr 0x%x.%02x retried "
1215 		    "write %d times, giving up",
1216 		    addr >> 8, addr & 0xff, num_failures);
1217 		bscv_set_fault(ssp);
1218 	} else if (num_failures > 0) {
1219 		BSCV_TRACE(ssp, 'R', "bscv_put8",
1220 		    "addr 0x%x.%02x retried write %d times, succeeded",
1221 		    addr >> 8, addr & 0xff, num_failures);
1222 	}
1223 }
1224 
1225 static void
1226 bscv_put16(bscv_soft_state_t *ssp, int chan, bscv_addr_t addr, uint16_t val)
1227 {
1228 	ASSERT(bscv_held(ssp));
1229 	BSCV_TRACE(ssp, '@', "bscv_put16",
1230 	    "addr 0x%x.%02x <= %04x", addr >> 8, addr & 0xff, val);
1231 	bscv_put8(ssp, chan, addr, val >> 8);
1232 	bscv_put8(ssp, chan, addr + 1, val & 0xff);
1233 }
1234 
1235 static void
1236 bscv_put32(bscv_soft_state_t *ssp, int chan, bscv_addr_t addr, uint32_t val)
1237 {
1238 	ASSERT(bscv_held(ssp));
1239 	BSCV_TRACE(ssp, '@', "bscv_put32",
1240 	    "addr 0x%x.%02x <= %08x", addr >> 8, addr & 0xff, val);
1241 	bscv_put8(ssp, chan, addr, (val >> 24) & 0xff);
1242 	bscv_put8(ssp, chan, addr + 1, (val >> 16) & 0xff);
1243 	bscv_put8(ssp, chan, addr + 2, (val >> 8) & 0xff);
1244 	bscv_put8(ssp, chan, addr + 3, val & 0xff);
1245 }
1246 
1247 static uint8_t
1248 bscv_get8(bscv_soft_state_t *ssp, int chan, bscv_addr_t addr)
1249 {
1250 	uint8_t retval;
1251 	boolean_t needretry;
1252 	int num_failures;
1253 
1254 	ASSERT(bscv_held(ssp));
1255 
1256 	if (bscv_faulty(ssp)) {
1257 		return (0);
1258 	}
1259 
1260 	for (num_failures = 0;
1261 	    num_failures < BSC_FAILURE_RETRY_LIMIT;
1262 	    num_failures++) {
1263 		retval = bscv_get8_once(ssp, chan, addr);
1264 		needretry = bscv_should_retry(ssp);
1265 		if (!needretry) {
1266 			break;
1267 		}
1268 	}
1269 	if (ssp->command_error != 0) {
1270 		ssp->had_session_error = B_TRUE;
1271 	}
1272 
1273 	if (needretry) {
1274 		/* Failure */
1275 		cmn_err(CE_WARN, "bscv_get8: addr 0x%x.%02x retried "
1276 		    "read %d times, giving up",
1277 		    addr >> 8, addr & 0xff, num_failures);
1278 		bscv_set_fault(ssp);
1279 	} else if (num_failures > 0) {
1280 		BSCV_TRACE(ssp, 'R', "bscv_get8",
1281 		    "addr 0x%x.%02x retried read %d times, succeeded",
1282 		    addr >> 8, addr & 0xff, num_failures);
1283 	}
1284 
1285 	BSCV_TRACE(ssp, '@', "bscv_get8",
1286 	    "addr 0x%x.%02x => %02x", addr >> 8, addr & 0xff, retval);
1287 	return (retval);
1288 }
1289 
1290 static uint16_t
1291 bscv_get16(bscv_soft_state_t *ssp, int chan, bscv_addr_t addr)
1292 {
1293 	uint16_t retval;
1294 
1295 	ASSERT(bscv_held(ssp));
1296 
1297 	retval = bscv_get8(ssp, chan, addr) << 8;
1298 	retval |= bscv_get8(ssp, chan, addr + 1);
1299 
1300 	BSCV_TRACE(ssp, '@', "bscv_get16",
1301 	    "addr 0x%x.%02x => %04x", addr >> 8, addr & 0xff, retval);
1302 	return (retval);
1303 }
1304 
1305 static uint32_t
1306 bscv_get32(bscv_soft_state_t *ssp, int chan, bscv_addr_t addr)
1307 {
1308 	uint32_t retval;
1309 
1310 	ASSERT(bscv_held(ssp));
1311 
1312 	retval = bscv_get8(ssp, chan, addr) << 24;
1313 	retval |= bscv_get8(ssp, chan, addr + 1) << 16;
1314 	retval |= bscv_get8(ssp, chan, addr + 2) << 8;
1315 	retval |= bscv_get8(ssp, chan, addr + 3);
1316 
1317 	BSCV_TRACE(ssp, '@', "bscv_get32",
1318 	    "addr 0x%x.%02x => %08x", addr >> 8, addr & 0xff, retval);
1319 	return (retval);
1320 }
1321 
1322 static void
1323 bscv_setclear8(bscv_soft_state_t *ssp, int chan,
1324     bscv_addr_t addr, uint8_t set, uint8_t clear)
1325 {
1326 	uint8_t val;
1327 
1328 	ASSERT(bscv_held(ssp));
1329 	ASSERT(addr < BSC_ADDR_CACHE_LIMIT);
1330 
1331 	val = ssp->lom_regs[addr] | set;
1332 	val &= ~clear;
1333 
1334 	BSCV_TRACE(ssp, '@', "bscv_setclear8",
1335 	    "addr 0x%x.%02x, set %02x, clear %02x => %02x",
1336 	    addr >> 8, addr & 0xff,
1337 	    set, clear, val);
1338 
1339 	bscv_put8(ssp, chan, addr, val);
1340 }
1341 
1342 static void
1343 bscv_setclear8_volatile(bscv_soft_state_t *ssp, int chan,
1344     bscv_addr_t addr, uint8_t set, uint8_t clear)
1345 {
1346 	uint8_t val;
1347 	boolean_t needretry;
1348 	int num_failures;
1349 
1350 	ASSERT(bscv_held(ssp));
1351 	ASSERT(addr < BSC_ADDR_CACHE_LIMIT);
1352 
1353 	if (bscv_faulty(ssp)) {
1354 		return;
1355 	}
1356 
1357 	BSCV_TRACE(ssp, '@', "bscv_setclear8_volatile",
1358 	    "addr 0x%x.%02x => set %02x clear %02x",
1359 	    addr >> 8, addr & 0xff, set, clear);
1360 
1361 	val = bscv_get8_cached(ssp, addr);
1362 	for (num_failures = 0;
1363 	    num_failures < BSC_FAILURE_RETRY_LIMIT;
1364 	    num_failures++) {
1365 		val |= set;
1366 		val &= ~clear;
1367 		bscv_put8_once(ssp, chan, addr, val);
1368 		if (ssp->command_error == EBUS_ERROR_STALEDATA) {
1369 			/* Re-read the stale register from the lom */
1370 			val = bscv_get8_once(ssp, chan, addr);
1371 			needretry = 1;
1372 		} else {
1373 			needretry = bscv_should_retry(ssp);
1374 			if (!needretry) {
1375 				break;
1376 			}
1377 		}
1378 	}
1379 	if (ssp->command_error != 0) {
1380 		ssp->had_session_error = B_TRUE;
1381 	}
1382 
1383 	if (needretry) {
1384 		/* Failure */
1385 		cmn_err(CE_WARN, "bscv_setclear8_volatile: addr 0x%x.%02x "
1386 		    "retried write %d times, giving up",
1387 		    addr >> 8, addr & 0xff, num_failures);
1388 		if (ssp->command_error != EBUS_ERROR_STALEDATA) {
1389 			bscv_set_fault(ssp);
1390 		}
1391 	} else if (num_failures > 0) {
1392 		BSCV_TRACE(ssp, 'R', "bscv_setclear8_volatile",
1393 		    "addr 0x%x.%02x retried write %d times, succeeded",
1394 		    addr >> 8, addr & 0xff, num_failures);
1395 	}
1396 }
1397 
1398 static void
1399 bscv_rep_rw8(bscv_soft_state_t *ssp, int chan, uint8_t *host_addr,
1400     bscv_addr_t dev_addr, size_t repcount, uint_t flags,
1401     boolean_t is_write)
1402 {
1403 	size_t inc;
1404 
1405 	ASSERT(bscv_held(ssp));
1406 
1407 	inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
1408 	for (; repcount--; dev_addr += inc) {
1409 		if (flags & DDI_DEV_AUTOINCR) {
1410 			if (is_write) {
1411 				bscv_put8(ssp, chan, dev_addr, *host_addr++);
1412 			} else {
1413 				*host_addr++ = bscv_get8(ssp, chan, dev_addr);
1414 			}
1415 		} else {
1416 			if (is_write) {
1417 				bscv_put8_once(ssp, chan,
1418 				    dev_addr, *host_addr++);
1419 			} else {
1420 				*host_addr++ = bscv_get8_once(ssp, chan,
1421 				    dev_addr);
1422 			}
1423 			/* We need this because _once routines don't do it */
1424 			if (ssp->command_error != 0) {
1425 				ssp->had_session_error = B_TRUE;
1426 			}
1427 		}
1428 		if (bscv_faulty(ssp) || bscv_session_error(ssp)) {
1429 			/*
1430 			 * No retry here. If we were AUTOINCR then get/put
1431 			 * will have retried. For NO_AUTOINCR we cannot retry
1432 			 * because the data would be corrupted.
1433 			 */
1434 			break;
1435 		}
1436 	}
1437 }
1438 
1439 static uint8_t
1440 bscv_get8_cached(bscv_soft_state_t *ssp, bscv_addr_t addr)
1441 {
1442 	ASSERT(addr < BSC_ADDR_CACHE_LIMIT);
1443 	/* Can be called with or without the lock held */
1444 
1445 	return (ssp->lom_regs[addr]);
1446 }
1447 
1448 static uint8_t
1449 bscv_get8_locked(bscv_soft_state_t *ssp, int chan, bscv_addr_t addr, int *res)
1450 {
1451 	uint8_t retval;
1452 
1453 	ASSERT(addr < BSC_ADDR_CACHE_LIMIT);
1454 	bscv_enter(ssp);
1455 	retval = bscv_get8(ssp, chan, addr);
1456 	bscv_locked_result(ssp, res);
1457 	bscv_exit(ssp);
1458 	BSCV_TRACE(ssp, '@', "bscv_get8_locked",
1459 	    "addr 0x%x.%02x => %02x", addr >> 8, addr & 0xff, retval);
1460 	return (retval);
1461 }
1462 
1463 static void
1464 bscv_rep_get8_locked(bscv_soft_state_t *ssp, int chan, uint8_t *host_addr,
1465     bscv_addr_t dev_addr, size_t repcount, uint_t flags, int *res)
1466 {
1467 	bscv_enter(ssp);
1468 	bscv_rep_rw8(ssp, chan, host_addr, dev_addr, repcount,
1469 	    flags, B_FALSE /* read */);
1470 	bscv_locked_result(ssp, res);
1471 	bscv_exit(ssp);
1472 }
1473 
1474 static boolean_t
1475 bscv_faulty(bscv_soft_state_t *ssp)
1476 {
1477 	ASSERT(bscv_held(ssp));
1478 	return (ssp->had_fault);
1479 }
1480 
1481 static void
1482 bscv_clear_fault(bscv_soft_state_t *ssp)
1483 {
1484 	ASSERT(bscv_held(ssp));
1485 	BSCV_TRACE(ssp, 'J', "bscv_clear_fault", "clearing fault flag");
1486 	ssp->had_fault = B_FALSE;
1487 	ssp->had_session_error = B_FALSE;
1488 }
1489 
1490 static void
1491 bscv_set_fault(bscv_soft_state_t *ssp)
1492 {
1493 	ASSERT(bscv_held(ssp));
1494 	BSCV_TRACE(ssp, 'J', "bscv_set_fault", "setting fault flag");
1495 	ssp->had_fault = B_TRUE;
1496 }
1497 
1498 static boolean_t
1499 bscv_session_error(bscv_soft_state_t *ssp)
1500 {
1501 	ASSERT(bscv_held(ssp));
1502 	return (ssp->had_session_error);
1503 }
1504 
1505 static int
1506 bscv_retcode(bscv_soft_state_t *ssp)
1507 {
1508 	BSCV_TRACE(ssp, '@', "bscv_retcode",
1509 	    "code 0x%x", ssp->command_error);
1510 	return (ssp->command_error);
1511 }
1512 
1513 static int
1514 bscv_should_retry(bscv_soft_state_t *ssp)
1515 {
1516 	if ((ssp->command_error == EBUS_ERROR_DEVICEFAIL) ||
1517 	    (ssp->command_error >= LOMBUS_ERR_BASE)) {
1518 		/* This command is due to an I/O fault - retry might fix */
1519 		return (1);
1520 	} else {
1521 		/*
1522 		 * The command itself was bad - there is no point in fixing
1523 		 * Note. Whatever happens we should know that if we were
1524 		 * doing EBUS_IDX_SELFTEST0..EBUS_IDX_SELFTEST7 and we
1525 		 * had 0x80 set then this is a test error not a retry
1526 		 * error.
1527 		 */
1528 		return (0);
1529 	}
1530 }
1531 
1532 static void
1533 bscv_locked_result(bscv_soft_state_t *ssp, int *res)
1534 {
1535 	if (bscv_faulty(ssp) || (bscv_retcode(ssp) != 0)) {
1536 		*res = EIO;
1537 	}
1538 }
1539 
1540 static void
1541 bscv_put8_once(bscv_soft_state_t *ssp, int chan, bscv_addr_t addr, uint8_t val)
1542 {
1543 	uint32_t fault;
1544 
1545 	ASSERT(bscv_held(ssp));
1546 
1547 	ssp->command_error = 0;
1548 
1549 	if (bscv_faulty(ssp)) {
1550 		/* Bail out things are not working */
1551 		return;
1552 	} else if (ssp->nchannels == 0) {
1553 		/* Didn't manage to map handles so ddi_{get,put}* broken */
1554 		BSCV_TRACE(ssp, '@', "bscv_put8_once",
1555 		    "nchannels is 0x0 so cannot do IO");
1556 		return;
1557 	}
1558 
1559 	/* Clear any pending fault */
1560 	ddi_put32(ssp->channel[chan].handle,
1561 	    (uint32_t *)BSC_NEXUS_ADDR(ssp, chan, 0, LOMBUS_FAULT_REG), 0);
1562 
1563 	/* Do the access and get fault code - may take a long time */
1564 	ddi_put8(ssp->channel[chan].handle,
1565 	    &ssp->channel[chan].regs[addr], val);
1566 	fault = ddi_get32(ssp->channel[chan].handle,
1567 	    (uint32_t *)BSC_NEXUS_ADDR(ssp, chan, 0, LOMBUS_FAULT_REG));
1568 
1569 	ssp->command_error = fault;
1570 
1571 	if (fault == 0) {
1572 		/* Things were ok - update cache entry */
1573 		if (addr < BSC_ADDR_CACHE_LIMIT) {
1574 			/* Store cacheable entries */
1575 			ssp->lom_regs[addr] = val;
1576 		}
1577 	} else if (fault >= LOMBUS_ERR_BASE) {
1578 		/* lombus problem - do a resync session */
1579 		cmn_err(CE_WARN, "!bscv_put8_once: Had comms fault "
1580 		    "for address 0x%x.%02x - data 0x%x, fault 0x%x",
1581 		    addr >> 8, addr & 0xff, val, fault);
1582 		/* Attempt to resync with the lom */
1583 		bscv_resync_comms(ssp, chan);
1584 		/*
1585 		 * Note: we do not set fault status here. That
1586 		 * is done if our caller decides to give up talking to
1587 		 * the lom. The observant might notice that this means
1588 		 * that if we mend things on the last attempt we still
1589 		 * get the fault set - we just live with that!
1590 		 */
1591 	}
1592 
1593 	BSCV_TRACE(ssp, '@', "bscv_put8_once",
1594 	    "addr 0x%x.%02x <= 0x%02x", addr >> 8, addr & 0xff, val);
1595 }
1596 
1597 static uint8_t
1598 bscv_get8_once(bscv_soft_state_t *ssp, int chan, bscv_addr_t addr)
1599 {
1600 	uint8_t val;
1601 	uint32_t fault;
1602 
1603 	ASSERT(bscv_held(ssp));
1604 
1605 	ssp->command_error = 0;
1606 
1607 	if (bscv_faulty(ssp)) {
1608 		/* Bail out things are not working */
1609 		return (0xff);
1610 	} else if (ssp->nchannels == 0) {
1611 		/* Didn't manage to map handles so ddi_{get,put}* broken */
1612 		BSCV_TRACE(ssp, '@', "bscv_get8_once",
1613 		    "nchannels is 0x0 so cannot do IO");
1614 		return (0xff);
1615 	}
1616 
1617 	/* Clear any pending fault */
1618 	ddi_put32(ssp->channel[chan].handle,
1619 	    (uint32_t *)BSC_NEXUS_ADDR(ssp, chan, 0, LOMBUS_FAULT_REG), 0);
1620 
1621 	/* Do the access and get fault code - may take a long time */
1622 	val = ddi_get8(ssp->channel[chan].handle,
1623 	    &ssp->channel[chan].regs[addr]);
1624 	fault = ddi_get32(ssp->channel[chan].handle,
1625 	    (uint32_t *)BSC_NEXUS_ADDR(ssp, chan, 0, LOMBUS_FAULT_REG));
1626 	ssp->command_error = fault;
1627 
1628 	if (fault >= LOMBUS_ERR_BASE) {
1629 		/* lombus problem - do a resync session */
1630 		cmn_err(CE_WARN, "!bscv_get8_once: Had comms fault "
1631 		    "for address 0x%x.%02x - data 0x%x, fault 0x%x",
1632 		    addr >> 8, addr & 0xff, val, fault);
1633 		/* Attempt to resync with the lom */
1634 		bscv_resync_comms(ssp, chan);
1635 		/*
1636 		 * Note: we do not set fault status here. That
1637 		 * is done if our caller decides to give up talking to
1638 		 * the lom. The observant might notice that this means
1639 		 * that if we mend things on the last attempt we still
1640 		 * get the fault set - we just live with that!
1641 		 */
1642 	}
1643 	/*
1644 	 * FIXME - should report error if you get
1645 	 * EBUS_ERROR_DEVICEFAIL reported from the BSC. That gets
1646 	 * logged as a failure in bscv_should_retry and may contribute
1647 	 * to a permanent failure. Reference issues seen by Mitac.
1648 	 */
1649 
1650 	if (!bscv_faulty(ssp)) {
1651 		if (addr < BSC_ADDR_CACHE_LIMIT) {
1652 			/* Store cacheable entries */
1653 			ssp->lom_regs[addr] = val;
1654 		}
1655 	}
1656 
1657 	BSCV_TRACE(ssp, '@', "bscv_get8_once",
1658 	    "addr 0x%x.%02x => 0x%02x", addr >> 8, addr & 0xff, val);
1659 	return (val);
1660 }
1661 
1662 static uint32_t
1663 bscv_probe(bscv_soft_state_t *ssp, int chan, uint32_t *fault)
1664 {
1665 	uint32_t async_reg;
1666 
1667 	if (ssp->nchannels == 0) {
1668 		/*
1669 		 * Failed to map handles, so cannot do any IO.  Set the
1670 		 * fault indicator and return a dummy value.
1671 		 */
1672 		BSCV_TRACE(ssp, '@', "bscv_probe",
1673 		    "nchannels is 0x0 so cannot do any IO");
1674 		*fault = LOMBUS_ERR_REG_NUM;
1675 		return ((~(int8_t)0));
1676 	}
1677 
1678 	/* Clear faults */
1679 	ddi_put32(ssp->channel[chan].handle,
1680 	    (uint32_t *)BSC_NEXUS_ADDR(ssp, chan, 0, LOMBUS_FAULT_REG), 0);
1681 	/* Probe and Check faults */
1682 	*fault = ddi_get32(ssp->channel[chan].handle,
1683 	    (uint32_t *)BSC_NEXUS_ADDR(ssp, chan, 0, LOMBUS_PROBE_REG));
1684 	/* Read status */
1685 	async_reg = ddi_get32(ssp->channel[chan].handle,
1686 	    (uint32_t *)BSC_NEXUS_ADDR(ssp, chan, 0, LOMBUS_ASYNC_REG));
1687 
1688 	BSCV_TRACE(ssp, '@', "bscv_probe",
1689 	    "async status 0x%x, fault 0x%x", async_reg, *fault);
1690 	return (async_reg);
1691 }
1692 
1693 static void
1694 bscv_resync_comms(bscv_soft_state_t *ssp, int chan)
1695 {
1696 	int try;
1697 	uint32_t command_error = ssp->command_error;
1698 	uint32_t fault = 0;
1699 
1700 	if (ssp->nchannels == 0) {
1701 		/*
1702 		 * Didn't manage to map handles so ddi_{get,put}* broken.
1703 		 * Therefore, there is no way to resync comms.
1704 		 */
1705 		BSCV_TRACE(ssp, '@', "bscv_resync_comms",
1706 		    "nchannels is 0x0 so not possible to resync comms");
1707 		return;
1708 	}
1709 	if (command_error >= LOMBUS_ERR_BASE &&
1710 	    command_error != LOMBUS_ERR_REG_NUM &&
1711 	    command_error != LOMBUS_ERR_REG_SIZE &&
1712 	    command_error != LOMBUS_ERR_TIMEOUT) {
1713 		/* Resync here to make sure that the lom is talking */
1714 		cmn_err(CE_WARN, "!bscv_resync_comms: "
1715 		    "Attempting comms resync after comms fault 0x%x",
1716 		    command_error);
1717 		for (try = 1; try <= 8; try++) {
1718 			/* Probe */
1719 			fault = ddi_get32(ssp->channel[chan].handle,
1720 			    (uint32_t *)BSC_NEXUS_ADDR(ssp, chan, 0,
1721 			    LOMBUS_PROBE_REG));
1722 
1723 			if (fault == 0) {
1724 				break;
1725 			} else {
1726 				cmn_err(CE_WARN, "!bscv_resync_comms: "
1727 				    "comms resync (probing) - try 0x%x "
1728 				    "had fault 0x%x", try, fault);
1729 			}
1730 		}
1731 		if (fault != 0) {
1732 			cmn_err(CE_WARN, "!bscv_resync_comms: "
1733 			    "Failed to resync comms - giving up");
1734 			ssp->bad_resync++;
1735 		} else {
1736 			cmn_err(CE_WARN, "!bscv_resync_comms: "
1737 			    "resync comms after 0x%x tries", try);
1738 			ssp->bad_resync = 0;
1739 		}
1740 	}
1741 
1742 }
1743 
1744 
1745 /*
1746  * LOMLite configuration/event eeprom access routines
1747  *
1748  * bscv_window_setup() - Read/Sanity check the eeprom parameters.
1749  *		This must be called prior to calling bscv_eerw().
1750  * bscv_eerw() - Read/write data from/to the eeprom.
1751  */
1752 
1753 /*
1754  * function	- bscv_window_setup
1755  * description	- this routine reads the eeprom parameters and sanity
1756  *		  checks them to ensure that the lom is talking sense.
1757  * inputs	- soft state ptr
1758  * outputs	- B_TRUE if the eeprom is ok, B_FALSE if the eeprom is not OK.
1759  */
1760 static boolean_t
1761 bscv_window_setup(bscv_soft_state_t *ssp)
1762 {
1763 	ASSERT(bscv_held(ssp));
1764 
1765 	if (ssp->eeinfo_valid) {
1766 		/* Already have good cached values */
1767 		return (ssp->eeinfo_valid);
1768 	}
1769 	ssp->eeprom_size =
1770 	    bscv_get8(ssp, chan_general, EBUS_IDX_EEPROM_SIZE_KB) * 1024;
1771 	ssp->eventlog_start = bscv_get16(ssp, chan_general,
1772 	    EBUS_IDX_LOG_START_HI);
1773 
1774 	/*
1775 	 * The log does not run to the end of the EEPROM because it is a
1776 	 * logical partition.  The last 8K partition is reserved for FRUID
1777 	 * usage.
1778 	 */
1779 	ssp->eventlog_size = EBUS_LOG_END - ssp->eventlog_start;
1780 
1781 	BSCV_TRACE(ssp, 'I', "bscv_window_setup", "eeprom size 0x%x log_start"
1782 	    " 0x%x log_size 0x%x", ssp->eeprom_size, ssp->eventlog_start,
1783 	    ssp->eventlog_size);
1784 
1785 	if (bscv_faulty(ssp) || bscv_session_error(ssp)) {
1786 		ssp->eeinfo_valid = B_FALSE;
1787 	} else if ((ssp->eeprom_size == 0) ||
1788 	    (ssp->eventlog_start >= ssp->eeprom_size)) {
1789 		/* Sanity check values */
1790 		cmn_err(CE_WARN,
1791 		    "!bscv_window_setup: read invalid eeprom parameters");
1792 		ssp->eeinfo_valid = B_FALSE;
1793 	} else {
1794 		ssp->eeinfo_valid = B_TRUE;
1795 	}
1796 
1797 	BSCV_TRACE(ssp, 'I', "bscv_window_setup", "returning eeinfo_valid %s",
1798 	    ssp->eeinfo_valid ? "true" : "false");
1799 	return (ssp->eeinfo_valid);
1800 }
1801 
1802 /*
1803  * function	- bscv_eerw
1804  * description	- this routine reads/write data from/to the eeprom.
1805  *		  It takes care of setting the window on the eeprom correctly.
1806  * inputs	- soft state ptr, eeprom offset, data buffer, size, read/write
1807  * outputs	- B_TRUE if the eeprom is ok, B_FALSE if the eeprom is not OK.
1808  */
1809 static int
1810 bscv_eerw(bscv_soft_state_t *ssp, uint32_t eeoffset, uint8_t *buf,
1811     unsigned size, boolean_t is_write)
1812 {
1813 	uint32_t blk_addr = eeoffset;
1814 	unsigned remaining = size;
1815 	uint8_t page_idx;
1816 	uint8_t this_page;
1817 	uint8_t blk_size;
1818 	int res = 0;
1819 
1820 	while (remaining > 0) {
1821 		page_idx = blk_addr & 0xff;
1822 		if ((page_idx + remaining) > 0x100) {
1823 			blk_size = 0x100 - page_idx;
1824 		} else {
1825 			blk_size = remaining;
1826 		}
1827 
1828 		/* Select correct eeprom page */
1829 		this_page = blk_addr >> 8;
1830 		bscv_put8(ssp, chan_eeprom, EBUS_IDX_EEPROM_PAGESEL, this_page);
1831 
1832 		BSCV_TRACE(ssp, 'M', "lom_eerw",
1833 		    "%s data @0x%x.%02x, size 0x%x, 0x%x bytes remaining",
1834 		    is_write ? "writing" : "reading",
1835 		    this_page, page_idx, blk_size, remaining - blk_size);
1836 
1837 		bscv_rep_rw8(ssp, chan_eeprom,
1838 		    buf, BSCVA(EBUS_CMD_SPACE_EEPROM, page_idx),
1839 		    blk_size, DDI_DEV_AUTOINCR, is_write);
1840 
1841 		if (bscv_faulty(ssp) || bscv_session_error(ssp)) {
1842 			res = EIO;
1843 			break;
1844 		}
1845 
1846 		remaining -= blk_size;
1847 		blk_addr += blk_size;
1848 		buf += blk_size;
1849 	}
1850 
1851 	return (res);
1852 }
1853 
1854 static boolean_t
1855 bscv_is_null_event(bscv_soft_state_t *ssp, lom_event_t *e)
1856 {
1857 	ASSERT(e != NULL);
1858 
1859 	if (EVENT_DECODE_SUBSYS(e->ev_subsys) == EVENT_SUBSYS_NONE &&
1860 	    e->ev_event == EVENT_NONE) {
1861 		/*
1862 		 * This marks a NULL event.
1863 		 */
1864 		BSCV_TRACE(ssp, 'E', "bscv_is_null_event",
1865 		    "EVENT_SUBSYS_NONE/EVENT_NONE null event");
1866 		return (B_TRUE);
1867 	} else if (e->ev_subsys == 0xff && e->ev_event == 0xff) {
1868 		/*
1869 		 * Under some circumstances, we've seen all 1s to represent
1870 		 * a manually cleared event log at the BSC prompt.  Only
1871 		 * a test/diagnosis environment is likely to show this.
1872 		 */
1873 		BSCV_TRACE(ssp, 'E', "bscv_is_null_event", "0xffff null event");
1874 		return (B_TRUE);
1875 	} else {
1876 		/*
1877 		 * Not a NULL event.
1878 		 */
1879 		BSCV_TRACE(ssp, 'E', "bscv_is_null_event", "returning False");
1880 		return (B_FALSE);
1881 	}
1882 }
1883 
1884 /*
1885  * *********************************************************************
1886  * IOCTL Processing
1887  * *********************************************************************
1888  */
1889 
1890 /*
1891  * function	- bscv_ioctl
1892  * description	- routine that acts as a high level manager for ioctls. It
1893  *		  calls the appropriate handler for ioctls on the alarm:mon and
1894  *		  alarm:ctl minor nodes respectively
1895  *
1896  *		  Unsupported ioctls (now deprecated)
1897  *			LOMIOCALCTL
1898  *			LOMIOCALSTATE
1899  *			LOMIOCCLEARLOG
1900  *			LOMIOCCTL
1901  *			LOMIOCCTL2
1902  *			LOMIOCDAEMON
1903  *			LOMIOCDMON
1904  *			LOMIOCDOGCTL, TSIOCDOGCTL
1905  *			LOMIOCDOGPAT, TSIOCDOGPAT
1906  *			LOMIOCDOGTIME, TSIOCDOGTIME
1907  *			LOMIOCEVENTLOG
1908  *			LOMIOCEVNT
1909  *			LOMIOCGETMASK
1910  *			LOMIOCMPROG
1911  *			LOMIOCNBMON, TSIOCNBMON
1912  *			LOMIOCSLEEP
1913  *			LOMIOCUNLOCK, TSIOCUNLOCK
1914  *			LOMIOCWTMON, TSIOCWTMON
1915  *
1916  *		  Supported ioctls
1917  *			LOMIOCDOGSTATE, TSIOCDOGSTATE
1918  *			LOMIOCPROG
1919  *			LOMIOCPSUSTATE
1920  *			LOMIOCFANSTATE
1921  *			LOMIOCFLEDSTATE
1922  *			LOMIOCINFO
1923  *			LOMIOCMREAD
1924  *			LOMIOCVOLTS
1925  *			LOMIOCSTATS
1926  *			LOMIOCTEMP
1927  *			LOMIOCCONS
1928  *			LOMIOCEVENTLOG2
1929  *			LOMIOCINFO2
1930  *			LOMIOCTEST
1931  *			LOMIOCMPROG2
1932  *			LOMIOCMREAD2
1933  *
1934  * inputs	- device number, command, user space arg, filemode, user
1935  *		  credentials, return value
1936  * outputs	- the return value propagated back by the lower level routines.
1937  */
1938 
1939 /*ARGSUSED*/
1940 static int
1941 bscv_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cred, int *rvalp)
1942 {
1943 	bscv_soft_state_t *ssp;
1944 	int instance;
1945 	int res = 0;
1946 
1947 	instance = DEVICETOINSTANCE(dev);
1948 	ssp = ddi_get_soft_state(bscv_statep, instance);
1949 	if (ssp == NULL) {
1950 		return (ENXIO);
1951 	}
1952 
1953 	/*
1954 	 * The Combined Switch and Service Processor takes care of configuration
1955 	 * and control.  The CSSP tells the BSC chip about it; therefore the
1956 	 * bscv driver doesn't send such configuration and control to the BSC.
1957 	 * Additionally Watchdog configuration is no longer done from userland
1958 	 * lom.
1959 	 */
1960 	switch (cmd) {
1961 	case LOMIOCALCTL:
1962 	case LOMIOCALSTATE:
1963 	case LOMIOCCLEARLOG:
1964 	case LOMIOCCTL:
1965 	case LOMIOCCTL2:
1966 	case LOMIOCDAEMON:
1967 	case LOMIOCDMON:
1968 	case LOMIOCDOGCTL:
1969 	case LOMIOCDOGPAT:
1970 	case LOMIOCDOGTIME:
1971 	case LOMIOCEVENTLOG:
1972 	case LOMIOCEVNT:
1973 	case LOMIOCGETMASK:
1974 	case LOMIOCMPROG:
1975 	case LOMIOCNBMON:
1976 	case LOMIOCSLEEP:
1977 	case LOMIOCUNLOCK:
1978 	case LOMIOCWTMON:
1979 		return (ENOTSUP);
1980 	}
1981 
1982 	/*
1983 	 * set the default result.
1984 	 */
1985 
1986 	*rvalp = 0;
1987 
1988 	if (ssp->cssp_prog) {
1989 		return (ENXIO);
1990 	} else if ((ssp->prog_mode_only || ssp->programming) &&
1991 	    cmd != LOMIOCPROG) {
1992 		return (ENXIO);
1993 	}
1994 
1995 	/*
1996 	 * Check that the caller has appropriate access permissions
1997 	 * (FWRITE set in mode) for those ioctls which change lom
1998 	 * state
1999 	 */
2000 	if (!(mode & FWRITE)) {
2001 		switch (cmd) {
2002 		case LOMIOCMPROG2:
2003 		case LOMIOCMREAD2:
2004 		case LOMIOCPROG:
2005 		case LOMIOCTEST:
2006 			return (EACCES);
2007 			/* NOTREACHED */
2008 		default:
2009 			/* Does not require write access */
2010 			break;
2011 		}
2012 	}
2013 
2014 	switch (cmd) {
2015 
2016 	case LOMIOCDOGSTATE:
2017 		res = bscv_ioc_dogstate(ssp, arg, mode);
2018 		break;
2019 
2020 	case LOMIOCPROG:
2021 		res = bscv_prog(ssp, arg, mode);
2022 		break;
2023 
2024 	case LOMIOCPSUSTATE:
2025 		res = bscv_ioc_psustate(ssp, arg, mode);
2026 		break;
2027 
2028 	case LOMIOCFANSTATE:
2029 		res = bscv_ioc_fanstate(ssp, arg, mode);
2030 		break;
2031 
2032 	case LOMIOCFLEDSTATE:
2033 		res = bscv_ioc_fledstate(ssp, arg, mode);
2034 		break;
2035 
2036 	case LOMIOCLEDSTATE:
2037 		res = bscv_ioc_ledstate(ssp, arg, mode);
2038 		break;
2039 
2040 	case LOMIOCINFO:
2041 		res = bscv_ioc_info(ssp, arg, mode);
2042 		break;
2043 
2044 	case LOMIOCMREAD:
2045 		res = bscv_ioc_mread(ssp, arg, mode);
2046 		break;
2047 
2048 	case LOMIOCVOLTS:
2049 		res = bscv_ioc_volts(ssp, arg, mode);
2050 		break;
2051 
2052 	case LOMIOCSTATS:
2053 		res = bscv_ioc_stats(ssp, arg, mode);
2054 		break;
2055 
2056 	case LOMIOCTEMP:
2057 		res = bscv_ioc_temp(ssp, arg, mode);
2058 		break;
2059 
2060 	case LOMIOCCONS:
2061 		res = bscv_ioc_cons(ssp, arg, mode);
2062 		break;
2063 
2064 	case LOMIOCEVENTLOG2:
2065 		res = bscv_ioc_eventlog2(ssp, arg, mode);
2066 		break;
2067 
2068 	case LOMIOCINFO2:
2069 		res = bscv_ioc_info2(ssp, arg, mode);
2070 		break;
2071 
2072 	case LOMIOCTEST:
2073 		res = bscv_ioc_test(ssp, arg, mode);
2074 		break;
2075 
2076 	case LOMIOCMPROG2:
2077 		res = bscv_ioc_mprog2(ssp, arg, mode);
2078 		break;
2079 
2080 	case LOMIOCMREAD2:
2081 		res = bscv_ioc_mread2(ssp, arg, mode);
2082 		break;
2083 
2084 	default:
2085 		BSCV_TRACE(ssp, 'I', "bscv_ioctl", "Invalid IOCTL 0x%x", cmd);
2086 		res = EINVAL;
2087 	}
2088 	return (res);
2089 }
2090 
2091 /*
2092  * LOMIOCDOGSTATE
2093  * TSIOCDOGSTATE - indicate whether the alarm watchdog and reset
2094  * circuitry is enabled or not.
2095  */
2096 static int
2097 bscv_ioc_dogstate(bscv_soft_state_t *ssp, intptr_t arg, int mode)
2098 {
2099 	lom_dogstate_t dogstate;
2100 	uint8_t dogval;
2101 	int res = 0;
2102 
2103 	dogval = bscv_get8_locked(ssp, chan_general, EBUS_IDX_WDOG_CTRL, &res);
2104 	dogstate.dog_enable = (dogval & EBUS_WDOG_ENABLE) ? 1 : 0;
2105 	dogstate.reset_enable = (dogval & EBUS_WDOG_RST) ? 1 : 0;
2106 	dogstate.dog_timeout = bscv_get8_locked(ssp, chan_general,
2107 	    EBUS_IDX_WDOG_TIME, &res);
2108 
2109 	if ((res == 0) &&
2110 	    (ddi_copyout((caddr_t)&dogstate,
2111 	    (caddr_t)arg, sizeof (dogstate), mode) < 0)) {
2112 		res = EFAULT;
2113 	}
2114 	return (res);
2115 }
2116 
2117 /*
2118  * LOMIOCPSUSTATE - returns full information for 4 PSUs. All this
2119  * information is available from two bytes of LOMlite RAM, but if
2120  * on the first read it is noticed that two or more of the PSUs are
2121  * not present only 1 byte will be read subsequently.
2122  */
2123 static int
2124 bscv_ioc_psustate(bscv_soft_state_t *ssp, intptr_t arg, int mode)
2125 {
2126 	lom_psudata_t psudata;
2127 	uint8_t psustat;
2128 	int i;
2129 	int res = 0;
2130 
2131 	for (i = 0; i < MAX_PSUS; i++) {
2132 		psustat = bscv_get8_locked(ssp, chan_general,
2133 		    EBUS_IDX_PSU1_STAT + i, &res);
2134 		psudata.fitted[i] = psustat & EBUS_PSU_PRESENT;
2135 		psudata.output[i] = psustat & EBUS_PSU_OUTPUT;
2136 		psudata.supplyb[i] = psustat & EBUS_PSU_INPUTB;
2137 		psudata.supplya[i] = psustat & EBUS_PSU_INPUTA;
2138 		psudata.standby[i] = psustat & EBUS_PSU_STANDBY;
2139 	}
2140 
2141 	if (ddi_copyout((caddr_t)&psudata, (caddr_t)arg, sizeof (psudata),
2142 	    mode) < 0) {
2143 		res = EFAULT;
2144 	}
2145 	return (res);
2146 }
2147 
2148 /*
2149  * LOMIOCFANSTATE - returns full information including speed for 4
2150  * fans and the minimum and maximum operating speeds for each fan as
2151  * stored in the READ ONLY EEPROM data. As this EEPROM data is set
2152  * at manufacture time, this data should only be read by the driver
2153  * once and stored locally.
2154  */
2155 static int
2156 bscv_ioc_fanstate(bscv_soft_state_t *ssp, intptr_t arg, int mode)
2157 {
2158 	lom_fandata_t fandata;
2159 	int numfans;
2160 	int i;
2161 	int res = 0;
2162 
2163 	bzero(&fandata, sizeof (lom_fandata_t));
2164 	numfans = EBUS_CONFIG_NFAN_DEC(bscv_get8_locked(ssp,
2165 	    chan_general, EBUS_IDX_CONFIG, &res));
2166 	for (i = 0; (i < numfans) && (res == 0); i++) {
2167 		if (ssp->fanspeed[i] != LOM_FAN_NOT_PRESENT) {
2168 			fandata.fitted[i] = 1;
2169 			fandata.speed[i] = ssp->fanspeed[i];
2170 			fandata.minspeed[i] = bscv_get8_cached(ssp,
2171 			    EBUS_IDX_FAN1_LOW + i);
2172 		}
2173 	}
2174 
2175 	if ((res == 0) &&
2176 	    (ddi_copyout((caddr_t)&fandata, (caddr_t)arg, sizeof (fandata),
2177 	    mode) < 0)) {
2178 		res = EFAULT;
2179 	}
2180 	return (res);
2181 }
2182 
2183 /*
2184  * LOMIOCFLEDSTATE - returns the state of the fault LED
2185  */
2186 static int
2187 bscv_ioc_fledstate(bscv_soft_state_t *ssp, intptr_t arg, int mode)
2188 {
2189 	lom_fled_info_t fled_info;
2190 	uint8_t fledstate;
2191 	int res = 0;
2192 
2193 	fledstate = bscv_get8_locked(ssp, chan_general, EBUS_IDX_ALARM, &res);
2194 
2195 	/* Decode of 0x0F is off and 0x00-0x07 is on. */
2196 	if (EBUS_ALARM_LED_DEC(fledstate) == 0x0F) {
2197 		fled_info.on = 0;
2198 	} else {
2199 		/* has +1 here - not 2 as in the info ioctl */
2200 		fled_info.on = EBUS_ALARM_LED_DEC(fledstate) + 1;
2201 	}
2202 	if ((res == 0) &&
2203 	    (ddi_copyout((caddr_t)&fled_info, (caddr_t)arg,
2204 	    sizeof (fled_info), mode) < 0)) {
2205 		res = EFAULT;
2206 	}
2207 	return (res);
2208 }
2209 
2210 /*
2211  * LOMIOCLEDSTATE - returns the state of the requested LED
2212  */
2213 static int
2214 bscv_ioc_ledstate(bscv_soft_state_t *ssp, intptr_t arg, int mode)
2215 {
2216 	lom_led_state_t led_state;
2217 	int fw_led_state;
2218 	int res = 0;
2219 
2220 	/* copy in arguments supplied */
2221 	if (ddi_copyin((caddr_t)arg, (caddr_t)&led_state,
2222 	    sizeof (lom_led_state_t), mode) < 0) {
2223 		return (EFAULT);
2224 	}
2225 
2226 	/*
2227 	 * check if led index is -1, if so set it to max value for
2228 	 * this implementation.
2229 	 */
2230 	if (led_state.index == -1) {
2231 		led_state.index = MAX_LED_ID;
2232 	}
2233 
2234 	/* is the index in a valid range */
2235 	if ((led_state.index > MAX_LED_ID) || (led_state.index < 0)) {
2236 		led_state.state = LOM_LED_OUTOFRANGE;
2237 	} else {
2238 		/* read the relevant led info */
2239 		fw_led_state = bscv_get8_locked(ssp, chan_general,
2240 		    EBUS_IDX_LED1_STATUS + led_state.index, &res);
2241 
2242 		/* set the state values accordingly */
2243 		switch (fw_led_state) {
2244 		case LOM_LED_STATE_OFF:
2245 			led_state.state = LOM_LED_OFF;
2246 			led_state.colour = LOM_LED_COLOUR_ANY;
2247 			break;
2248 		case LOM_LED_STATE_ON_STEADY:
2249 			led_state.state = LOM_LED_ON;
2250 			led_state.colour = LOM_LED_COLOUR_ANY;
2251 			break;
2252 		case LOM_LED_STATE_ON_FLASHING:
2253 		case LOM_LED_STATE_ON_SLOWFLASH:
2254 			led_state.state = LOM_LED_BLINKING;
2255 			led_state.colour = LOM_LED_COLOUR_ANY;
2256 			break;
2257 		case LOM_LED_STATE_NOT_PRESENT:
2258 			led_state.state = LOM_LED_NOT_IMPLEMENTED;
2259 			led_state.colour = LOM_LED_COLOUR_NONE;
2260 			break;
2261 		case LOM_LED_STATE_INACCESSIBLE:
2262 		case LOM_LED_STATE_STANDBY:
2263 		default:
2264 			led_state.state = LOM_LED_ACCESS_ERROR;
2265 			led_state.colour = LOM_LED_COLOUR_NONE;
2266 			break;
2267 		}
2268 
2269 		/* set the label info */
2270 		(void) strcpy(led_state.label,
2271 		    ssp->led_names[led_state.index]);
2272 	}
2273 
2274 	/* copy out lom_state */
2275 	if ((res == 0) &&
2276 	    (ddi_copyout((caddr_t)&led_state, (caddr_t)arg,
2277 	    sizeof (lom_led_state_t), mode) < 0)) {
2278 		res = EFAULT;
2279 	}
2280 	return (res);
2281 }
2282 
2283 /*
2284  * LOMIOCINFO - returns with a structure containing any information
2285  * stored on the LOMlite which a user should not need to access but
2286  * may be useful for diagnostic problems. The structure contains: the
2287  * serial escape character, alarm3 mode, version and checksum read from
2288  * RAM and the Product revision and ID read from EEPROM.
2289  */
2290 static int
2291 bscv_ioc_info(bscv_soft_state_t *ssp, intptr_t arg, int mode)
2292 {
2293 	lom_info_t info;
2294 	int i;
2295 	uint16_t csum;
2296 	int res = 0;
2297 
2298 	info.ser_char = bscv_get8_locked(ssp, chan_general, EBUS_IDX_ESCAPE,
2299 	    &res);
2300 	info.a3mode = WATCHDOG;
2301 	info.fver = bscv_get8_locked(ssp, chan_general, EBUS_IDX_FW_REV, &res);
2302 	csum = bscv_get8_locked(ssp, chan_general, EBUS_IDX_CHECK_HI, &res)
2303 	    << 8;
2304 	csum |= bscv_get8_locked(ssp, chan_general, EBUS_IDX_CHECK_LO, &res);
2305 	info.fchksum = csum;
2306 	info.prod_rev = bscv_get8_locked(ssp, chan_general, EBUS_IDX_MODEL_REV,
2307 	    &res);
2308 	for (i = 0; i < sizeof (info.prod_id); i++) {
2309 		info.prod_id[i] = bscv_get8_locked(ssp,
2310 		    chan_general, EBUS_IDX_MODEL_ID1 + i, &res);
2311 	}
2312 	if (bscv_get8_locked(ssp, chan_general, EBUS_IDX_ALARM, &res) &
2313 	    EBUS_ALARM_NOEVENTS) {
2314 		info.events = OFF;
2315 	} else {
2316 		info.events = ON;
2317 	}
2318 
2319 	if ((res == 0) &&
2320 	    (ddi_copyout((caddr_t)&info, (caddr_t)arg, sizeof (info),
2321 	    mode) < 0)) {
2322 		res = EFAULT;
2323 	}
2324 	return (res);
2325 }
2326 
2327 /*
2328  * LOMIOCMREAD - used to query the LOMlite configuration parameters
2329  */
2330 static int
2331 bscv_ioc_mread(bscv_soft_state_t *ssp, intptr_t arg, int mode)
2332 {
2333 	lom_mprog_t mprog;
2334 	int i;
2335 	int fanz;
2336 	int res = 0;
2337 
2338 	for (i = 0; i < sizeof (mprog.mod_id); i++) {
2339 		mprog.mod_id[i] = bscv_get8_locked(ssp, chan_general,
2340 		    EBUS_IDX_MODEL_ID1 + i, &res);
2341 	}
2342 	mprog.mod_rev = bscv_get8_locked(ssp, chan_general, EBUS_IDX_MODEL_REV,
2343 	    &res);
2344 	mprog.config = bscv_get8_locked(ssp, chan_general, EBUS_IDX_CONFIG,
2345 	    &res);
2346 
2347 	/* Read the fan calibration values */
2348 	fanz = sizeof (mprog.fanhz) / sizeof (mprog.fanhz[0]);
2349 	for (i = 0; i < fanz; i++) {
2350 		mprog.fanhz[i] = bscv_get8_cached(ssp,
2351 		    EBUS_IDX_FAN1_CAL + i);
2352 		mprog.fanmin[i] = bscv_get8_cached(ssp,
2353 		    EBUS_IDX_FAN1_LOW + i);
2354 	}
2355 
2356 	if ((res == 0) &&
2357 	    (ddi_copyout((caddr_t)&mprog, (caddr_t)arg, sizeof (mprog),
2358 	    mode) < 0)) {
2359 		res = EFAULT;
2360 	}
2361 	return (res);
2362 }
2363 
2364 /*
2365  * LOMIOCVOLTS
2366  */
2367 static int
2368 bscv_ioc_volts(bscv_soft_state_t *ssp, intptr_t arg, int mode)
2369 {
2370 	int i;
2371 	uint16_t supply;
2372 	int res = 0;
2373 
2374 	supply = (bscv_get8_locked(ssp, chan_general, EBUS_IDX_SUPPLY_HI, &res)
2375 	    << 8) | bscv_get8_locked(ssp, chan_general, EBUS_IDX_SUPPLY_LO,
2376 	    &res);
2377 
2378 	for (i = 0; i < ssp->volts.num; i++) {
2379 		ssp->volts.status[i] = (supply >> i) & 1;
2380 	}
2381 
2382 	if ((res == 0) &&
2383 	    (ddi_copyout((caddr_t)&ssp->volts, (caddr_t)arg,
2384 	    sizeof (ssp->volts), mode) < 0)) {
2385 		res = EFAULT;
2386 	}
2387 	return (res);
2388 }
2389 
2390 /*
2391  * LOMIOCSTATS
2392  */
2393 static int
2394 bscv_ioc_stats(bscv_soft_state_t *ssp, intptr_t arg, int mode)
2395 {
2396 	int i;
2397 	uint8_t status;
2398 	int res = 0;
2399 
2400 	status = bscv_get8_locked(ssp, chan_general, EBUS_IDX_CBREAK_STATUS,
2401 	    &res);
2402 	for (i = 0; i < ssp->sflags.num; i++) {
2403 		ssp->sflags.status[i] = (int)((status >> i) & 1);
2404 	}
2405 
2406 	if ((res == 0) &&
2407 	    (ddi_copyout((caddr_t)&ssp->sflags, (caddr_t)arg,
2408 	    sizeof (ssp->sflags), mode) < 0)) {
2409 		res = EFAULT;
2410 	}
2411 	return (res);
2412 }
2413 
2414 /*
2415  * LOMIOCTEMP
2416  */
2417 static int
2418 bscv_ioc_temp(bscv_soft_state_t *ssp, intptr_t arg, int mode)
2419 {
2420 	int i;
2421 	int idx;
2422 	uint8_t status_ov;
2423 	lom_temp_t temps;
2424 	int res = 0;
2425 
2426 	bzero(&temps, sizeof (temps));
2427 	idx = 0;
2428 	for (i = 0; i < ssp->temps.num; i++) {
2429 		if (ssp->temps.temp[i] != LOM_TEMP_STATE_NOT_PRESENT) {
2430 			temps.temp[idx] = ssp->temps.temp[i];
2431 			bcopy(ssp->temps.name[i], temps.name[idx],
2432 			    sizeof (temps.name[idx]));
2433 			temps.warning[idx] = ssp->temps.warning[i];
2434 			temps.shutdown[idx] = ssp->temps.shutdown[i];
2435 			idx++;
2436 		}
2437 	}
2438 	temps.num = idx;
2439 
2440 	bcopy(ssp->temps.name_ov, temps.name_ov, sizeof (temps.name_ov));
2441 	temps.num_ov = ssp->temps.num_ov;
2442 	status_ov = bscv_get8_locked(ssp, chan_general, EBUS_IDX_OTEMP_STATUS,
2443 	    &res);
2444 	for (i = 0; i < ssp->temps.num_ov; i++) {
2445 		ssp->temps.status_ov[i] = (status_ov >> i) & 1;
2446 	}
2447 
2448 	if ((res == 0) &&
2449 	    (ddi_copyout((caddr_t)&temps, (caddr_t)arg, sizeof (temps),
2450 	    mode) < 0)) {
2451 		res = EFAULT;
2452 	}
2453 	return (res);
2454 }
2455 
2456 /*
2457  * LOMIOCCONS
2458  */
2459 static int
2460 bscv_ioc_cons(bscv_soft_state_t *ssp, intptr_t arg, int mode)
2461 {
2462 	lom_cbuf_t cbuf;
2463 	int datasize;
2464 	int res = 0;
2465 
2466 	bzero(&cbuf, sizeof (cbuf));
2467 	datasize = EBUS_IDX1_CONS_BUF_END - EBUS_IDX1_CONS_BUF_START + 1;
2468 	/* Ensure that we do not overfill cbuf and that it is NUL terminated */
2469 	if (datasize > (sizeof (cbuf) - 1)) {
2470 		datasize = sizeof (cbuf) - 1;
2471 	}
2472 	bscv_rep_get8_locked(ssp, chan_general, (uint8_t *)cbuf.lrbuf,
2473 	    BSCVA(EBUS_CMD_SPACE1, (EBUS_IDX1_CONS_BUF_END - datasize + 1)),
2474 	    datasize, DDI_DEV_AUTOINCR, &res);
2475 	/* This is always within the array due to the checks above */
2476 	cbuf.lrbuf[datasize] = '\0';
2477 
2478 	if ((res == 0) &&
2479 	    (ddi_copyout((caddr_t)&cbuf, (caddr_t)arg, sizeof (cbuf),
2480 	    mode) < 0)) {
2481 		res = EFAULT;
2482 	}
2483 	return (res);
2484 }
2485 
2486 /*
2487  * LOMIOCEVENTLOG2
2488  */
2489 static int
2490 bscv_ioc_eventlog2(bscv_soft_state_t *ssp, intptr_t arg, int mode)
2491 {
2492 	lom_eventlog2_t *eventlog2;
2493 	int events_recorded;
2494 	int level;
2495 	uint16_t next_offset;
2496 	lom_event_t event;
2497 	int res = 0;
2498 
2499 	eventlog2 = (lom_eventlog2_t *)kmem_zalloc(sizeof (*eventlog2),
2500 	    KM_SLEEP);
2501 
2502 	/*
2503 	 * First get number of events and level requested.
2504 	 */
2505 
2506 	if (ddi_copyin((caddr_t)arg, (caddr_t)eventlog2,
2507 	    sizeof (lom_eventlog2_t), mode) < 0) {
2508 		kmem_free((void *)eventlog2, sizeof (*eventlog2));
2509 		return (EFAULT);
2510 	}
2511 
2512 	bscv_enter(ssp);
2513 
2514 	/*
2515 	 * OK we have full private access to the LOM now so loop
2516 	 * over the eventlog addr spaces until we get the required
2517 	 * number of events.
2518 	 */
2519 
2520 	if (!bscv_window_setup(ssp)) {
2521 		res = EIO;
2522 		bscv_exit(ssp);
2523 		kmem_free((void *)eventlog2, sizeof (*eventlog2));
2524 		return (res);
2525 	}
2526 
2527 	/*
2528 	 * Read count, next event ptr MSB,LSB. Note a read of count
2529 	 * is necessary to latch values for the next event ptr
2530 	 */
2531 	(void) bscv_get8(ssp, chan_general, EBUS_IDX_UNREAD_EVENTS);
2532 	next_offset = bscv_get16(ssp, chan_general, EBUS_IDX_LOG_PTR_HI);
2533 	BSCV_TRACE(ssp, 'I', "bscv_ioc_eventlog2", "log_ptr_hi 0x%x",
2534 	    next_offset);
2535 
2536 	events_recorded = 0;
2537 
2538 	while (events_recorded < eventlog2->num) {
2539 		/*
2540 		 * Working backwards - read an event at a time.
2541 		 * next_offset is one event on from where we want to be!
2542 		 * Decrement next_offset and maybe wrap to the end of the
2543 		 * buffer.
2544 		 * Note the unsigned arithmetic, so check values first!
2545 		 */
2546 		if (next_offset <= ssp->eventlog_start) {
2547 			/* Wrap to the end of the buffer */
2548 			next_offset = ssp->eventlog_start + ssp->eventlog_size;
2549 			BSCV_TRACE(ssp, 'I', "bscv_ioc_eventlog2", "wrapping"
2550 			    " around to end of buffer; next_offset 0x%x",
2551 			    next_offset);
2552 		}
2553 		next_offset -= sizeof (event);
2554 
2555 		if (bscv_eerw(ssp, next_offset, (uint8_t *)&event,
2556 		    sizeof (event), B_FALSE /* read */) != 0) {
2557 			/* Fault reading data - stop */
2558 			BSCV_TRACE(ssp, 'I', "bscv_ioc_eventlog2", "read"
2559 			    " failure for offset 0x%x", next_offset);
2560 			res = EIO;
2561 			break;
2562 		}
2563 
2564 		if (bscv_is_null_event(ssp, &event)) {
2565 			/*
2566 			 * No more events in this log so give up.
2567 			 */
2568 			BSCV_TRACE(ssp, 'I', "bscv_ioc_eventlog2", "no more"
2569 			    " events left at offset 0x%x", next_offset);
2570 			break;
2571 		}
2572 
2573 		/*
2574 		 * Are we interested in this event
2575 		 */
2576 
2577 		level = bscv_level_of_event(&event);
2578 		if (level <= eventlog2->level) {
2579 			/* Arggh why the funny byte ordering 3, 2, 0, 1 */
2580 			eventlog2->code[events_recorded] =
2581 			    ((unsigned)event.ev_event |
2582 			    ((unsigned)event.ev_subsys << 8) |
2583 			    ((unsigned)event.ev_resource << 16) |
2584 			    ((unsigned)event.ev_detail << 24));
2585 
2586 			eventlog2->time[events_recorded] =
2587 			    ((unsigned)event.ev_data[0] |
2588 			    ((unsigned)event.ev_data[1] << 8) |
2589 			    ((unsigned)event.ev_data[3] << 16) |
2590 			    ((unsigned)event.ev_data[2] << 24));
2591 
2592 			bscv_build_eventstring(ssp,
2593 			    &event, eventlog2->string[events_recorded],
2594 			    eventlog2->string[events_recorded] +
2595 			    sizeof (eventlog2->string[events_recorded]));
2596 			events_recorded++;
2597 		}
2598 	}
2599 
2600 	eventlog2->num = events_recorded;
2601 
2602 	bscv_exit(ssp);
2603 
2604 	if ((res == 0) &&
2605 	    (ddi_copyout((caddr_t)eventlog2, (caddr_t)arg,
2606 	    sizeof (lom_eventlog2_t), mode) < 0)) {
2607 		res = EFAULT;
2608 	}
2609 
2610 	kmem_free((void *)eventlog2, sizeof (lom_eventlog2_t));
2611 	return (res);
2612 }
2613 
2614 /*
2615  * LOMIOCINFO2
2616  */
2617 static int
2618 bscv_ioc_info2(bscv_soft_state_t *ssp, intptr_t arg, int mode)
2619 {
2620 	lom2_info_t info2;
2621 	int i;
2622 	uint16_t csum;
2623 	int res = 0;
2624 
2625 	bzero(&info2, sizeof (info2));
2626 
2627 	(void) strncpy(info2.escape_chars, ssp->escape_chars,
2628 	    sizeof (info2.escape_chars));
2629 	info2.serial_events = ssp->reporting_level | ssp->serial_reporting;
2630 	info2.a3mode = WATCHDOG;
2631 
2632 	info2.fver = bscv_get8_locked(ssp, chan_general, EBUS_IDX_FW_REV, &res);
2633 	csum = bscv_get8_locked(ssp, chan_general, EBUS_IDX_CHECK_HI, &res)
2634 	    << 8;
2635 	csum |= bscv_get8_locked(ssp, chan_general, EBUS_IDX_CHECK_LO, &res);
2636 	info2.fchksum = csum;
2637 	info2.prod_rev = bscv_get8_locked(ssp, chan_general,
2638 	    EBUS_IDX_MODEL_REV, &res);
2639 	for (i = 0; i < sizeof (info2.prod_id); i++) {
2640 		info2.prod_id[i] = bscv_get8_locked(ssp, chan_general,
2641 		    EBUS_IDX_MODEL_ID1 + i, &res);
2642 	}
2643 	info2.serial_config = bscv_get8_locked(ssp, chan_general,
2644 	    EBUS_IDX_SER_TIMEOUT, &res);
2645 	if (bscv_get8_locked(ssp, chan_general, EBUS_IDX_CONFIG_MISC, &res) &
2646 	    EBUS_CONFIG_MISC_SECURITY_ENABLED) {
2647 		info2.serial_config |= LOM_SER_SECURITY;
2648 	}
2649 	if (bscv_get8_locked(ssp, chan_general, EBUS_IDX_CONFIG_MISC, &res) &
2650 	    EBUS_CONFIG_MISC_AUTO_CONSOLE) {
2651 		info2.serial_config |= LOM_SER_RETURN;
2652 	}
2653 	if (bscv_get8_locked(ssp, chan_general, EBUS_IDX_WDOG_CTRL, &res) &
2654 	    EBUS_WDOG_BREAK_DISABLE) {
2655 		info2.serial_config |= LOM_DISABLE_WDOG_BREAK;
2656 	}
2657 	info2.baud_rate = bscv_get8_locked(ssp, chan_general,
2658 	    EBUS_IDX_SER_BAUD, &res);
2659 	info2.serial_hw_config =
2660 	    ((int)bscv_get8_locked(ssp, chan_general,
2661 	    EBUS_IDX_SER_CHARMODE, &res) |
2662 	    ((int)bscv_get8_locked(ssp, chan_general,
2663 	    EBUS_IDX_SER_FLOWCTL, &res) << 8) |
2664 	    ((int)bscv_get8_locked(ssp, chan_general,
2665 	    EBUS_IDX_SER_MODEMTYPE, &res) << 16));
2666 
2667 	/*
2668 	 * There is no phone home support on the blade platform.  We hardcode
2669 	 * FALSE and NUL for config and script respectively.
2670 	 */
2671 	info2.phone_home_config = B_FALSE;
2672 	info2.phone_home_script[0] = '\0';
2673 
2674 	for (i = 0; i < ssp->num_fans; i++) {
2675 		(void) strcpy(info2.fan_names[i], ssp->fan_names[i]);
2676 	}
2677 
2678 	if ((res == 0) &&
2679 	    (ddi_copyout((caddr_t)&info2, (caddr_t)arg, sizeof (info2),
2680 	    mode) < 0)) {
2681 		res = EFAULT;
2682 	}
2683 	return (res);
2684 }
2685 
2686 /*
2687  * LOMIOCTEST
2688  */
2689 static int
2690 bscv_ioc_test(bscv_soft_state_t *ssp, intptr_t arg, int mode)
2691 {
2692 	uint32_t test;
2693 	uint8_t testnum;
2694 	uint8_t testarg;
2695 	int res = 0;
2696 
2697 	if (ddi_copyin((caddr_t)arg, (caddr_t)&test, sizeof (test),
2698 	    mode) < 0) {
2699 		return (EFAULT);
2700 	}
2701 
2702 	/*
2703 	 * Extract num iterations.
2704 	 */
2705 
2706 	testarg = (test & 0xff00) >> 8;
2707 	testnum = test & 0xff;
2708 
2709 	BSCV_TRACE(ssp, 'F', "bscv_ioc_test",
2710 	    "LOMIOCTEST data 0x%x (test 0x%x, arg 0x%x)",
2711 	    test, (EBUS_IDX_SELFTEST0 + testnum), testarg);
2712 
2713 	switch (testnum + EBUS_IDX_SELFTEST0) {
2714 	default:
2715 		/* Invalid test */
2716 		res = EINVAL;
2717 		break;
2718 
2719 	case EBUS_IDX_SELFTEST0:	/* power on self-test result */
2720 	case EBUS_IDX_SELFTEST1:	/* not used currently */
2721 	case EBUS_IDX_SELFTEST2:	/* not used currently */
2722 	case EBUS_IDX_SELFTEST3:	/* not used currently */
2723 	case EBUS_IDX_SELFTEST4:	/* not used currently */
2724 	case EBUS_IDX_SELFTEST5:	/* not used currently */
2725 	case EBUS_IDX_SELFTEST6:	/* LED self-test */
2726 	case EBUS_IDX_SELFTEST7:	/* platform-specific tests */
2727 		/* Run the test */
2728 
2729 		/* Stop other things and then run the test */
2730 		bscv_enter(ssp);
2731 
2732 		/*
2733 		 * Then we simply write the argument to the relevant register
2734 		 * and wait for the return code.
2735 		 */
2736 		bscv_put8(ssp, chan_general,
2737 		    EBUS_IDX_SELFTEST0 + testnum, testarg);
2738 		if (bscv_faulty(ssp)) {
2739 			res = EIO;
2740 		} else {
2741 			/* Get hold of the SunVTS error code */
2742 			test = bscv_retcode(ssp);
2743 		}
2744 
2745 		bscv_exit(ssp);
2746 		break;
2747 	}
2748 
2749 	BSCV_TRACE(ssp, 'F', "bscv_ioc_test",
2750 	    "LOMIOCTEST status 0x%x, res 0x%x", test, res);
2751 	if ((res == 0) &&
2752 	    (ddi_copyout((caddr_t)&test, (caddr_t)arg, sizeof (test),
2753 	    mode) < 0)) {
2754 		res = EFAULT;
2755 	}
2756 	return (res);
2757 }
2758 
2759 /*
2760  * LOMIOCMPROG2
2761  */
2762 static int
2763 bscv_ioc_mprog2(bscv_soft_state_t *ssp, intptr_t arg, int mode)
2764 {
2765 	lom2_mprog_t  mprog2;
2766 	uint32_t base_addr;
2767 	uint32_t data_size;
2768 	uint32_t eeprom_size;
2769 	int res = 0;
2770 
2771 	if (ddi_copyin((caddr_t)arg, (caddr_t)&mprog2, sizeof (mprog2),
2772 	    mode) < 0) {
2773 		return (EFAULT);
2774 	}
2775 
2776 	/*
2777 	 * Note that originally this was accessed as 255 byte pages
2778 	 * in address spaces 240-255. We have to emulate this behaviour.
2779 	 */
2780 	if ((mprog2.addr_space < 240) || (mprog2.addr_space > 255)) {
2781 		return (EINVAL);
2782 	}
2783 
2784 	bscv_enter(ssp);
2785 
2786 	/* Calculate required data location */
2787 	data_size = 255;
2788 	base_addr = (mprog2.addr_space - 240) * data_size;
2789 
2790 	eeprom_size = bscv_get8(ssp, chan_general, EBUS_IDX_EEPROM_SIZE_KB) *
2791 	    1024;
2792 
2793 	if (bscv_faulty(ssp)) {
2794 		bscv_exit(ssp);
2795 		return (EIO);
2796 	} else if ((base_addr + data_size) > eeprom_size) {
2797 		BSCV_TRACE(ssp, 'M', "bscv_ioc_mprog2",
2798 		    "Request extends past end of eeprom");
2799 		bscv_exit(ssp);
2800 		return (ENXIO);
2801 	}
2802 
2803 	bscv_put8(ssp, chan_general, EBUS_IDX_CMD_RES, EBUS_CMD_UNLOCK1);
2804 	if (bscv_faulty(ssp)) {
2805 		BSCV_TRACE(ssp, 'M', "bscv_ioc_mprog2", "ML1 Write failed");
2806 		bscv_exit(ssp);
2807 		return (EIO);
2808 	}
2809 
2810 	bscv_put8(ssp, chan_general, EBUS_IDX_CMD_RES, EBUS_CMD_UNLOCK2);
2811 	if (bscv_faulty(ssp)) {
2812 		BSCV_TRACE(ssp, 'M', "bscv_ioc_mprog2", "ML2 Write failed");
2813 		bscv_exit(ssp);
2814 		return (EIO);
2815 	}
2816 
2817 	if (bscv_eerw(ssp, base_addr, &mprog2.data[0],
2818 	    data_size, B_TRUE /* write */) != 0) {
2819 		res = EIO;
2820 	}
2821 
2822 	/* Read a probe key to release the lock. */
2823 	(void) bscv_get8(ssp, chan_general, EBUS_IDX_PROBEAA);
2824 
2825 	if (bscv_faulty(ssp)) {
2826 		res = EIO;
2827 	}
2828 	bscv_exit(ssp);
2829 
2830 	return (res);
2831 }
2832 
2833 /*
2834  * LOMIOCMREAD2
2835  */
2836 static int
2837 bscv_ioc_mread2(bscv_soft_state_t *ssp, intptr_t arg, int mode)
2838 {
2839 	lom2_mprog_t  mprog2;
2840 	uint32_t base_addr;
2841 	uint32_t data_size;
2842 	uint32_t eeprom_size;
2843 	int res = 0;
2844 
2845 	if (ddi_copyin((caddr_t)arg, (caddr_t)&mprog2, sizeof (mprog2),
2846 	    mode) < 0) {
2847 		return (EFAULT);
2848 	}
2849 
2850 	/*
2851 	 * Need to stop the queue and then just read
2852 	 * the bytes blind to the relevant addresses.
2853 	 * Note that originally this was accessed as 255 byte pages
2854 	 * in address spaces 240-255. We have to emulate this behaviour.
2855 	 */
2856 	if ((mprog2.addr_space < 240) || (mprog2.addr_space > 255)) {
2857 		return (EINVAL);
2858 	}
2859 
2860 	bscv_enter(ssp);
2861 
2862 	/* Calculate required data location */
2863 	data_size = 255;
2864 	base_addr = (mprog2.addr_space - 240) * data_size;
2865 	eeprom_size = bscv_get8(ssp, chan_general, EBUS_IDX_EEPROM_SIZE_KB) *
2866 	    1024;
2867 
2868 	if (bscv_faulty(ssp)) {
2869 		bscv_exit(ssp);
2870 		return (EIO);
2871 	} else if ((base_addr + data_size) > eeprom_size) {
2872 		BSCV_TRACE(ssp, 'M', "bscv_ioc_mread2",
2873 		    "Request extends past end of eeprom");
2874 		bscv_exit(ssp);
2875 		return (ENXIO);
2876 	}
2877 
2878 	if (bscv_eerw(ssp, base_addr, &mprog2.data[0],
2879 	    data_size, B_FALSE /* read */) != 0) {
2880 		res = EIO;
2881 	}
2882 
2883 	if (bscv_faulty(ssp)) {
2884 		res = EIO;
2885 	}
2886 	bscv_exit(ssp);
2887 
2888 	if ((res == 0) &&
2889 	    (ddi_copyout((caddr_t)&mprog2, (caddr_t)arg, sizeof (mprog2),
2890 	    mode) < 0)) {
2891 		res = EFAULT;
2892 	}
2893 	return (res);
2894 }
2895 
2896 static void
2897 bscv_get_state_changes(bscv_soft_state_t *ssp)
2898 {
2899 	int i = STATUS_READ_LIMIT;
2900 	uint8_t change;
2901 	uint8_t detail;
2902 
2903 	ASSERT(bscv_held(ssp));
2904 
2905 	while (i-- && !ssp->cssp_prog) {
2906 		/* Are there any changes to process? */
2907 		change = bscv_get8(ssp, chan_general, EBUS_IDX_STATE_CHNG);
2908 		change &= EBUS_STATE_MASK;
2909 		if (!change)
2910 			break;
2911 
2912 		/* Clarify the pending change */
2913 		detail = bscv_get8(ssp, chan_general, EBUS_IDX_EVENT_DETAIL);
2914 
2915 		bscv_status(ssp, change, detail);
2916 	}
2917 
2918 	BSCV_TRACE(ssp, 'D', "bscv_get_state_changes",
2919 	    "loop index %d ssp->cssp_prog 0x%x", i, ssp->cssp_prog);
2920 }
2921 
2922 /*
2923  * *********************************************************************
2924  * Event Processing
2925  * *********************************************************************
2926  */
2927 
2928 /*
2929  * function	- bscv_event_daemon
2930  * description	- Perform periodic lom tasks in a separate thread.
2931  * inputs	- LOM soft state structure pointer
2932  * outputs	- none.
2933  */
2934 static void
2935 bscv_event_daemon(void *arg)
2936 {
2937 	bscv_soft_state_t	*ssp = (void *)arg;
2938 	boolean_t do_events;
2939 	boolean_t do_status;
2940 	boolean_t do_nodename;
2941 	boolean_t do_watchdog;
2942 	uint32_t async_reg;
2943 	uint32_t fault;
2944 	clock_t poll_period = BSC_EVENT_POLL_NORMAL;
2945 	int fault_cnt = 0;
2946 
2947 	BSCV_TRACE(ssp, 'D', "bscv_event_daemon",
2948 	    "bscv_event_daemon: started");
2949 
2950 	/* Acquire task daemon lock. */
2951 	mutex_enter(&ssp->task_mu);
2952 
2953 	ssp->task_flags |= TASK_ALIVE_FLG;
2954 
2955 	for (;;) {
2956 		if ((ssp->task_flags & TASK_STOP_FLG) != 0) {
2957 			/* Stop request seen - terminate */
2958 			break;
2959 		}
2960 		if ((ssp->task_flags & TASK_PAUSE_FLG) == 0) {
2961 			/* Poll for events reported to the nexus */
2962 			mutex_exit(&ssp->task_mu);
2963 			/* Probe and Check faults */
2964 			bscv_enter(ssp);
2965 			async_reg = bscv_probe(ssp, chan_general, &fault);
2966 			BSCV_TRACE(ssp, 'D', "bscv_event_daemon",
2967 			    "process event: async_reg 0x%x, fault 0x%x",
2968 			    async_reg, fault);
2969 
2970 			if (!fault) {
2971 				/* Treat non-fault conditions */
2972 
2973 				if (ssp->cssp_prog || ssp->prog_mode_only) {
2974 					/*
2975 					 * The BSC has become available again.
2976 					 */
2977 					fault_cnt = 0;
2978 					ssp->cssp_prog = B_FALSE;
2979 					ssp->prog_mode_only = B_FALSE;
2980 					(void) bscv_attach_common(ssp);
2981 				} else if (fault_cnt > 0) {
2982 					/* Previous fault has cleared */
2983 					bscv_clear_fault(ssp);
2984 					fault_cnt = 0;
2985 					cmn_err(CE_WARN,
2986 					    "!bscv_event_daemon previous fault "
2987 					    "cleared.");
2988 				} else if (bscv_faulty(ssp)) {
2989 					/* Previous fault has cleared */
2990 					bscv_clear_fault(ssp);
2991 					/* Sleep to avoid busy waiting */
2992 					ssp->event_sleep = B_TRUE;
2993 				}
2994 				poll_period = BSC_EVENT_POLL_NORMAL;
2995 
2996 				if (async_reg) {
2997 					ssp->status_change = B_TRUE;
2998 					ssp->event_waiting = B_TRUE;
2999 				}
3000 			} else if (ssp->cssp_prog) {
3001 				/*
3002 				 * Expect radio silence or error values
3003 				 * when the CSSP is upgrading the BSC firmware
3004 				 * so throw away any fault indication.
3005 				 */
3006 				fault = B_FALSE;
3007 			} else if (fault_cnt == BSC_PROBE_FAULT_LIMIT) {
3008 				/* Count previous faults and maybe fail */
3009 				/* Declare the lom broken */
3010 				bscv_set_fault(ssp);
3011 				poll_period = BSC_EVENT_POLL_FAULTY;
3012 				cmn_err(CE_WARN,
3013 				    "!bscv_event_daemon had faults probing "
3014 				    "lom - marking it as faulty.");
3015 				/*
3016 				 * Increment fault_cnt to ensure that
3017 				 * next time we do not report a message
3018 				 * i.e. we drop out of the bottom
3019 				 */
3020 				fault_cnt = BSC_PROBE_FAULT_LIMIT + 1;
3021 				ssp->event_sleep = B_TRUE;
3022 			} else if (fault_cnt < BSC_PROBE_FAULT_LIMIT) {
3023 				if (bscv_faulty(ssp)) {
3024 					poll_period = BSC_EVENT_POLL_FAULTY;
3025 					/*
3026 					 * No recovery messages in this case
3027 					 * because there was never a fault
3028 					 * message here.
3029 					 */
3030 					fault_cnt = 0;
3031 				} else {
3032 					/* Getting ready to explode */
3033 					fault_cnt++;
3034 					cmn_err(CE_WARN,
3035 					    "!bscv_event_daemon had fault 0x%x",
3036 					    fault);
3037 				}
3038 				ssp->event_sleep = B_TRUE;
3039 			}
3040 			bscv_exit(ssp);
3041 			mutex_enter(&ssp->task_mu);
3042 		}
3043 
3044 #if defined(__i386) || defined(__amd64)
3045 		/*
3046 		 * we have no platmod hook on Solaris x86 to report
3047 		 * a change to the nodename so we keep a copy so
3048 		 * we can detect a change and request that the bsc
3049 		 * be updated when appropriate.
3050 		 */
3051 		if (strcmp(ssp->last_nodename, utsname.nodename) != 0) {
3052 
3053 			BSCV_TRACE(ssp, 'X', "bscv_event_daemon",
3054 			    "utsname.nodename='%s' possible change detected",
3055 			    utsname.nodename);
3056 			ssp->nodename_change = B_TRUE;
3057 			(void) strncpy(ssp->last_nodename, utsname.nodename,
3058 			    sizeof (ssp->last_nodename));
3059 			/* enforce null termination */
3060 			ssp->last_nodename[sizeof (ssp->last_nodename) - 1] =
3061 			    '\0';
3062 		}
3063 #endif /* __i386 || __amd64 */
3064 
3065 		if (((ssp->task_flags & TASK_PAUSE_FLG) == 0) &&
3066 		    fault_cnt == 0 && ssp->cssp_prog == B_FALSE &&
3067 		    (ssp->event_waiting || ssp->status_change ||
3068 		    ssp->nodename_change || ssp->watchdog_change)) {
3069 
3070 			do_events = ssp->event_waiting;
3071 			ssp->event_waiting = B_FALSE;
3072 			ssp->task_flags |= do_events ?
3073 			    TASK_EVENT_PENDING_FLG : 0;
3074 			do_status = ssp->status_change;
3075 			ssp->status_change = B_FALSE;
3076 			do_nodename = ssp->nodename_change;
3077 			ssp->nodename_change = B_FALSE;
3078 			do_watchdog = ssp->watchdog_change;
3079 			if (ssp->watchdog_change) {
3080 				ssp->watchdog_change = B_FALSE;
3081 			}
3082 
3083 			mutex_exit(&ssp->task_mu);
3084 			/*
3085 			 * We must not hold task_mu whilst processing
3086 			 * events because this can lead to priority
3087 			 * inversion and hence our interrupts getting
3088 			 * locked out.
3089 			 */
3090 			bscv_enter(ssp);
3091 			if (do_events) {
3092 				bscv_event_process(ssp, do_events);
3093 			}
3094 			if (do_nodename) {
3095 				BSCV_TRACE(ssp, 'D', "bscv_event_daemon",
3096 				    "do_nodename task");
3097 				bscv_setup_hostname(ssp);
3098 			}
3099 			if (do_watchdog) {
3100 				BSCV_TRACE(ssp, 'D', "bscv_event_daemon",
3101 				    "do_watchdog task");
3102 				bscv_setup_watchdog(ssp);
3103 			}
3104 			/*
3105 			 * Pending status changes are dealt with last because
3106 			 * if we see that the BSC is about to be programmed,
3107 			 * then it will expect us to to quiescent in the
3108 			 * first second so it can cleanly tear down its comms
3109 			 * protocols; this takes ~100 ms.
3110 			 */
3111 			if (do_status) {
3112 				bscv_get_state_changes(ssp);
3113 			}
3114 			if (bscv_session_error(ssp)) {
3115 				/*
3116 				 * Had fault during event session. We always
3117 				 * sleep after one of these because there
3118 				 * may be a problem with the lom which stops
3119 				 * us doing useful work in the event daemon.
3120 				 * If we don't sleep then we may livelock.
3121 				 */
3122 				BSCV_TRACE(ssp, 'D', "bscv_event_daemon",
3123 				    "had session error - sleeping");
3124 				ssp->event_sleep = B_TRUE;
3125 			}
3126 			bscv_exit(ssp);
3127 
3128 			mutex_enter(&ssp->task_mu);
3129 
3130 			if (ssp->task_flags & TASK_EVENT_PENDING_FLG) {
3131 				/*
3132 				 * We have read any events which were
3133 				 * pending. Let the consumer continue.
3134 				 * Ignore the race condition with new events
3135 				 * arriving - just let the consumer have
3136 				 * whatever was pending when they asked.
3137 				 */
3138 				ssp->event_active_count++;
3139 				ssp->task_flags &= ~(TASK_EVENT_PENDING_FLG |
3140 				    TASK_EVENT_CONSUMER_FLG);
3141 				cv_broadcast(&ssp->task_evnt_cv);
3142 			}
3143 		} else {
3144 			/* There was nothing to do - sleep */
3145 			ssp->event_sleep = B_TRUE;
3146 		}
3147 
3148 		if (ssp->event_sleep) {
3149 			ssp->task_flags |= TASK_SLEEPING_FLG;
3150 			/* Sleep until there is something to do */
3151 			(void) cv_timedwait(&ssp->task_cv,
3152 			    &ssp->task_mu,
3153 			    poll_period + ddi_get_lbolt());
3154 			ssp->task_flags &= ~TASK_SLEEPING_FLG;
3155 			ssp->event_sleep = B_FALSE;
3156 		}
3157 	}
3158 
3159 	if (ssp->task_flags & TASK_EVENT_CONSUMER_FLG) {
3160 		/*
3161 		 * We are going away so wake up any event consumer.
3162 		 * Pretend that any pending events have been processed.
3163 		 */
3164 		ssp->event_active_count += 2;
3165 		cv_broadcast(&ssp->task_evnt_cv);
3166 	}
3167 
3168 	ASSERT(!(ssp->task_flags & TASK_EVENT_PENDING_FLG));
3169 	ssp->task_flags &=
3170 	    ~(TASK_STOP_FLG | TASK_ALIVE_FLG | TASK_EVENT_CONSUMER_FLG);
3171 	mutex_exit(&ssp->task_mu);
3172 
3173 	BSCV_TRACE(ssp, 'D', "bscv_event_daemon",
3174 	    "exiting.");
3175 }
3176 
3177 /*
3178  * function	- bscv_start_event_daemon
3179  * description	- Create the event daemon thread.
3180  * inputs	- LOM soft state structure pointer
3181  * outputs	- none
3182  */
3183 static void
3184 bscv_start_event_daemon(bscv_soft_state_t *ssp)
3185 {
3186 	if (ssp->progress & BSCV_THREAD)
3187 		return;
3188 
3189 	/* Start the event thread after the queue has started */
3190 	(void) thread_create(NULL, 0, (void (*)())bscv_event_daemon, ssp,
3191 	    0, &p0, TS_RUN, minclsyspri);
3192 
3193 	ssp->progress |= BSCV_THREAD;
3194 }
3195 
3196 /*
3197  * function	- bscv_stop_event_daemon
3198  * description	- Attempt to stop the event daemon thread.
3199  * inputs	- LOM soft state structure pointer
3200  * outputs	- DDI_SUCCESS OR DDI_FAILURE
3201  */
3202 static int
3203 bscv_stop_event_daemon(bscv_soft_state_t *ssp)
3204 {
3205 	int try;
3206 	int res = DDI_SUCCESS;
3207 
3208 	mutex_enter(&ssp->task_mu);
3209 
3210 	/* Wait for task daemon to stop running. */
3211 	for (try = 0;
3212 	    ((ssp->task_flags & TASK_ALIVE_FLG) && try < 10);
3213 	    try++) {
3214 		/* Signal that the task daemon should stop */
3215 		ssp->task_flags |= TASK_STOP_FLG;
3216 		cv_signal(&ssp->task_cv);
3217 		/* Release task daemon lock. */
3218 		mutex_exit(&ssp->task_mu);
3219 		/*
3220 		 * TODO - when the driver is modified to support
3221 		 * system suspend or if this routine gets called
3222 		 * during panic we should use drv_usecwait() rather
3223 		 * than delay in those circumstances.
3224 		 */
3225 		delay(drv_usectohz(1000000));
3226 		mutex_enter(&ssp->task_mu);
3227 	}
3228 
3229 	if (ssp->task_flags & TASK_ALIVE_FLG) {
3230 		res = DDI_FAILURE;
3231 	}
3232 	mutex_exit(&ssp->task_mu);
3233 
3234 	return (res);
3235 }
3236 
3237 /*
3238  * function	- bscv_pause_event_daemon
3239  * description	- Attempt to pause the event daemon thread.
3240  * inputs	- LOM soft state structure pointer
3241  * outputs	- DDI_SUCCESS OR DDI_FAILURE
3242  */
3243 static int
3244 bscv_pause_event_daemon(bscv_soft_state_t *ssp)
3245 {
3246 	int try;
3247 
3248 	if (!(ssp->progress & BSCV_THREAD)) {
3249 		/* Nothing to do */
3250 		return (BSCV_SUCCESS);
3251 	}
3252 
3253 	BSCV_TRACE(ssp, 'D', "bscv_pause_event_daemon",
3254 	    "Attempting to pause event daemon");
3255 
3256 	mutex_enter(&ssp->task_mu);
3257 	/* Signal that the task daemon should pause */
3258 	ssp->task_flags |= TASK_PAUSE_FLG;
3259 
3260 	/* Wait for task daemon to pause. */
3261 	for (try = 0;
3262 	    (!(ssp->task_flags & TASK_SLEEPING_FLG) &&
3263 	    (ssp->task_flags & TASK_ALIVE_FLG) &&
3264 	    try < 10);
3265 	    try++) {
3266 		/* Paranoia */
3267 		ssp->task_flags |= TASK_PAUSE_FLG;
3268 		cv_signal(&ssp->task_cv);
3269 		/* Release task daemon lock. */
3270 		mutex_exit(&ssp->task_mu);
3271 		delay(drv_usectohz(1000000));
3272 		mutex_enter(&ssp->task_mu);
3273 	}
3274 	if ((ssp->task_flags & TASK_SLEEPING_FLG) ||
3275 	    !(ssp->task_flags & TASK_ALIVE_FLG)) {
3276 		mutex_exit(&ssp->task_mu);
3277 		BSCV_TRACE(ssp, 'D', "bscv_pause_event_daemon",
3278 		    "Pause event daemon - success");
3279 		return (BSCV_SUCCESS);
3280 	}
3281 	mutex_exit(&ssp->task_mu);
3282 	BSCV_TRACE(ssp, 'D', "bscv_pause_event_daemon",
3283 	    "Pause event daemon - failed");
3284 	return (BSCV_FAILURE);
3285 }
3286 
3287 /*
3288  * function	- bscv_resume_event_daemon
3289  * description	- Resumethe event daemon thread.
3290  * inputs	- LOM soft state structure pointer
3291  * outputs	- None.
3292  */
3293 static void
3294 bscv_resume_event_daemon(bscv_soft_state_t *ssp)
3295 {
3296 	if (!(ssp->progress & BSCV_THREAD)) {
3297 		/* Nothing to do */
3298 		return;
3299 	}
3300 
3301 	mutex_enter(&ssp->task_mu);
3302 	/* Allow the task daemon to resume event processing */
3303 	ssp->task_flags &= ~TASK_PAUSE_FLG;
3304 	cv_signal(&ssp->task_cv);
3305 	mutex_exit(&ssp->task_mu);
3306 
3307 	BSCV_TRACE(ssp, 'D', "bscv_pause_event_daemon",
3308 	    "Event daemon resumed");
3309 }
3310 
3311 /*
3312  * function	- bscv_event_process
3313  * description	- process (report) events
3314  * inputs	- Soft state ptr, process event request
3315  * outputs	- none
3316  */
3317 static void
3318 bscv_event_process(bscv_soft_state_t *ssp, boolean_t do_events)
3319 {
3320 	uint32_t currptr;
3321 	unsigned int count;
3322 
3323 	/* Raw values read from the lom */
3324 	uint8_t evcount;
3325 	uint16_t logptr;
3326 
3327 	lom_event_t event;
3328 
3329 	if (do_events) {
3330 		/*
3331 		 * Read count, next event ptr MSB,LSB. Note a read of count
3332 		 * latches values for the next event ptr
3333 		 */
3334 		evcount = bscv_get8(ssp, chan_general, EBUS_IDX_UNREAD_EVENTS);
3335 		logptr = bscv_get16(ssp, chan_general, EBUS_IDX_LOG_PTR_HI);
3336 
3337 		/* Sanity check the values from the lom */
3338 		count = bscv_event_validate(ssp, logptr, evcount);
3339 
3340 		if (count == -1) {
3341 			/*
3342 			 * Nothing to do - or badly configured event log.
3343 			 * We really do not want to touch the lom in this
3344 			 * case because any data that we access may be bad!
3345 			 * This differs from zero because if we have zero
3346 			 * to read the lom probably things that unread is
3347 			 * non-zero and we want that to be set to zero!
3348 			 * Signal event fault to make the thread wait
3349 			 * before attempting to re-read the log.
3350 			 */
3351 			ssp->event_sleep = B_TRUE;
3352 
3353 			goto logdone;
3354 		}
3355 		if (ssp->event_fault_reported) {
3356 			/* Clear down any old status - things are fixed */
3357 			cmn_err(CE_NOTE, "Event pointer fault recovered.");
3358 			ssp->event_fault_reported = B_FALSE;
3359 		}
3360 
3361 		/* Compute the first entry that we need to read. */
3362 		currptr = logptr - ssp->eventlog_start;
3363 		currptr += ssp->eventlog_size;
3364 		currptr -= (count * sizeof (event));
3365 		currptr %= ssp->eventlog_size;
3366 		currptr += ssp->eventlog_start;
3367 
3368 		BSCV_TRACE(ssp, 'E', "bscv_event_process",
3369 		    "processing %d events from 0x%x in 0x%x:0x%x",
3370 		    count, currptr,
3371 		    ssp->eventlog_start,
3372 		    ssp->eventlog_start + ssp->eventlog_size);
3373 
3374 		for (; count > 0; count--) {
3375 			/* Ensure window is positioned correctly */
3376 			if (bscv_eerw(ssp, currptr, (uint8_t *)&event,
3377 			    sizeof (event), B_FALSE /* read */) != 0) {
3378 				/* Fault reading data - stop */
3379 				break;
3380 			}
3381 
3382 			bscv_event_process_one(ssp, &event);
3383 			bscv_sysevent(ssp, &event);
3384 
3385 			currptr += sizeof (event);
3386 			if (currptr >= ssp->eventlog_start +
3387 			    ssp->eventlog_size) {
3388 				currptr = ssp->eventlog_start;
3389 			}
3390 		}
3391 		/*
3392 		 * Clear event count - write the evcount value to remove that
3393 		 * many from the unread total.
3394 		 * Adjust the value to reflect how many we have left to
3395 		 * read just in case we had a failure reading events.
3396 		 */
3397 		if (count == 0) {
3398 			/*EMPTY*/
3399 			ASSERT(logptr == currptr);
3400 		} else if (count > evcount) {
3401 			evcount = 0;
3402 		} else {
3403 			evcount -= count;
3404 		}
3405 		bscv_put8(ssp, chan_general, EBUS_IDX_UNREAD_EVENTS, evcount);
3406 		    /* Remember where we were for next time */
3407 		ssp->oldeeptr = currptr;
3408 		ssp->oldeeptr_valid = B_TRUE;
3409 logdone:
3410 		;
3411 	}
3412 }
3413 
3414 /*
3415  * function	- bscv_event_validate
3416  * description	- validate the event data supplied by the lom and determine
3417  *		  how many (if any) events to read.
3418  *		  This function performs complex checks to ensure that
3419  *		  events are not lost due to lom resets or host resets.
3420  *		  A combination of lom reset and host reset (i.e. power fail)
3421  *		  may cause some events to not be reported.
3422  * inputs	- Soft state ptr, next event pointer, number of unread events.
3423  * outputs	- the number of events to read. -1 on error.
3424  *		  zero is a valid value because it forces the loms unread
3425  *		  count to be cleared.
3426  */
3427 static int
3428 bscv_event_validate(bscv_soft_state_t *ssp, uint32_t newptr, uint8_t unread)
3429 {
3430 	uint32_t oldptr;
3431 	unsigned int count;
3432 
3433 	if (!bscv_window_setup(ssp)) {
3434 		/* Problem with lom eeprom setup we cannot do anything */
3435 		return (-1);
3436 	}
3437 
3438 	/* Sanity check the event pointers */
3439 	if ((newptr < ssp->eventlog_start) ||
3440 	    (newptr >= (ssp->eventlog_start + ssp->eventlog_size))) {
3441 		if (!ssp->event_fault_reported) {
3442 			cmn_err(CE_WARN, "Event pointer out of range. "
3443 			    "Cannot read events.");
3444 			ssp->event_fault_reported = B_TRUE;
3445 		}
3446 		return (-1);
3447 	}
3448 	oldptr = ssp->oldeeptr;
3449 	/* Now sanity check log pointer against count */
3450 	if (newptr < oldptr) {
3451 		/*
3452 		 * Must have wrapped add eventlog_size to get the
3453 		 * correct relative values - this makes the checks
3454 		 * below work!
3455 		 */
3456 		newptr += ssp->eventlog_size;
3457 	}
3458 	if (!ssp->oldeeptr_valid) {
3459 		/* We have just started up - we have to trust lom */
3460 		count = unread;
3461 	} else if ((unread == 0) && (newptr == oldptr)) {
3462 		/* Nothing to do - we were just polling */
3463 		return (-1);
3464 	} else if (oldptr + (unread * sizeof (lom_event_t)) == newptr) {
3465 		/* Ok - got as many events as we expected */
3466 		count = unread;
3467 	} else if (oldptr + (unread * sizeof (lom_event_t)) > newptr) {
3468 		/*
3469 		 * Errrm more messages than there should have been.
3470 		 * Possible causes:
3471 		 * 1.	the event log has filled - we have been
3472 		 *	away for a long time
3473 		 * 2.	software bug in lom or driver.
3474 		 * 3.	something that I haven't thought of!
3475 		 * Always warn about this we should really never
3476 		 * see it!
3477 		 */
3478 		count = (newptr - oldptr) / sizeof (lom_event_t);
3479 		BSCV_TRACE(ssp, 'E', "bscv_event_process",
3480 		    "bscv_event_process: lom reported "
3481 		    "more events (%d) than expected (%d).",
3482 		    unread, count);
3483 		cmn_err(CE_CONT, "only processing %d events", count);
3484 	} else {
3485 		/* Less messages - perhaps the lom has been reset */
3486 		count = (newptr - oldptr) / sizeof (lom_event_t);
3487 		BSCV_TRACE(ssp, 'E', "bscv_event_process",
3488 		    "lom reported less events (%d) than expected (%d)"
3489 		    " - the lom may have been reset",
3490 		    unread, count);
3491 	}
3492 	/* Whatever happens only read a maximum of 255 entries */
3493 	if ((count >= 0xff)) {
3494 		cmn_err(CE_WARN,
3495 		    "bscv_event_process: too many events (%d) to "
3496 		    "process - some may have been lost", count);
3497 		count = 0xff;
3498 	}
3499 	return (count);
3500 }
3501 
3502 /*
3503  * function	- bscv_event_process_one
3504  * description	- reports on state changes to the host.
3505  *
3506  * inputs	- LOM soft state structure pointer.
3507  *
3508  * outputs	- none.
3509  */
3510 
3511 static void
3512 bscv_event_process_one(bscv_soft_state_t *ssp, lom_event_t *event)
3513 {
3514 	int level;
3515 	char eventstr[100];
3516 	int msg_type = 0;
3517 
3518 	if (bscv_is_null_event(ssp, event)) {
3519 		/* Cleared entry - do not report it */
3520 		return;
3521 	}
3522 
3523 	level = bscv_level_of_event(event);
3524 
3525 	switch (level) {
3526 	default:
3527 		msg_type = CE_NOTE;
3528 		break;
3529 
3530 	case EVENT_LEVEL_FATAL:
3531 	case EVENT_LEVEL_FAULT:
3532 		msg_type = CE_WARN;
3533 		break;
3534 	}
3535 
3536 	bscv_build_eventstring(ssp, event, eventstr, eventstr +
3537 	    sizeof (eventstr));
3538 
3539 	if (level <= ssp->reporting_level) {
3540 		/*
3541 		 * The message is important enough to be shown on the console
3542 		 * as well as the log.
3543 		 */
3544 		cmn_err(msg_type, "%s", eventstr);
3545 	} else {
3546 		/*
3547 		 * The message goes only to the log.
3548 		 */
3549 		cmn_err(msg_type, "!%s", eventstr);
3550 	}
3551 }
3552 
3553 /*
3554  * time formats
3555  *
3556  * The BSC represents times as seconds since epoch 1970.  Currently it gives
3557  * us 32 bits, unsigned.  In the future this might change to a 64-bit count,
3558  * to allow a greater range.
3559  *
3560  * Timestamp values below BSC_TIME_SANITY do not represent an absolute time,
3561  * but instead represent an offset from the last reset.  This must be
3562  * borne in mind by output routines.
3563  */
3564 
3565 typedef uint32_t bsctime_t;
3566 
3567 #define	BSC_TIME_SANITY		1000000000
3568 
3569 /*
3570  * render a formatted time for display
3571  */
3572 
3573 static size_t
3574 bscv_event_snprintgmttime(char *buf, size_t bufsz, todinfo_t t)
3575 {
3576 	int year;
3577 
3578 	/* tod_year is base 1900 so this code needs to adjust */
3579 	year = 1900 + t.tod_year;
3580 
3581 	return (snprintf(buf, bufsz, "%04d-%02d-%02d %02d:%02d:%02dZ",
3582 	    year, t.tod_month, t.tod_day, t.tod_hour,
3583 	    t.tod_min, t.tod_sec));
3584 }
3585 
3586 /*
3587  * function	- bscv_build_eventstring
3588  * description	- reports on state changes to the host.
3589  *
3590  * inputs	- LOM soft state structure pointer.
3591  *
3592  * outputs	- none.
3593  */
3594 
3595 static void
3596 bscv_build_eventstring(bscv_soft_state_t *ssp, lom_event_t *event,
3597     char *buf, char *bufend)
3598 {
3599 	uint8_t subsystem;
3600 	uint8_t eventtype;
3601 	bsctime_t bsctm;
3602 
3603 	BSCV_TRACE(ssp, 'S', "bscv_build_eventstring", "event %2x%2x%2x%2x",
3604 	    event->ev_subsys, event->ev_event,
3605 	    event->ev_resource, event->ev_detail);
3606 	BSCV_TRACE(ssp, 'S', "bscv_build_eventstring", "time %2x%2x%2x%2x",
3607 	    event->ev_data[0], event->ev_data[1],
3608 	    event->ev_data[2], event->ev_data[3]);
3609 
3610 	/*
3611 	 * We accept bad subsystems and event type codes here.
3612 	 * The code decodes as much as possible and then produces
3613 	 * suitable output.
3614 	 */
3615 	subsystem = EVENT_DECODE_SUBSYS(event->ev_subsys);
3616 	eventtype = event->ev_event;
3617 
3618 	/* time */
3619 	bsctm = (((uint32_t)event->ev_data[0]) << 24) |
3620 	    (((uint32_t)event->ev_data[1]) << 16) |
3621 	    (((uint32_t)event->ev_data[2]) << 8) |
3622 	    ((uint32_t)event->ev_data[3]);
3623 	if (bsctm < BSC_TIME_SANITY) {
3624 		/* offset */
3625 		buf += snprintf(buf, bufend-buf, "+P%dd%02dh%02dm%02ds",
3626 		    (int)(bsctm/86400), (int)(bsctm/3600%24),
3627 		    (int)(bsctm/60%60), (int)(bsctm%60));
3628 	} else {
3629 		/* absolute time */
3630 		mutex_enter(&tod_lock);
3631 		buf += bscv_event_snprintgmttime(buf, bufend-buf,
3632 		    utc_to_tod(bsctm));
3633 		mutex_exit(&tod_lock);
3634 	}
3635 	buf += snprintf(buf, bufend-buf, " ");
3636 
3637 	/* subsysp */
3638 	if (subsystem <
3639 	    (sizeof (eventSubsysStrings)/sizeof (*eventSubsysStrings))) {
3640 		buf += snprintf(buf, bufend - buf, "%s",
3641 		    eventSubsysStrings[subsystem]);
3642 	} else {
3643 		buf += snprintf(buf, bufend - buf,
3644 		    "unknown subsystem %d ", subsystem);
3645 	}
3646 
3647 	/* resource */
3648 	switch (subsystem) {
3649 	case EVENT_SUBSYS_ALARM:
3650 	case EVENT_SUBSYS_TEMP:
3651 	case EVENT_SUBSYS_OVERTEMP:
3652 	case EVENT_SUBSYS_FAN:
3653 	case EVENT_SUBSYS_SUPPLY:
3654 	case EVENT_SUBSYS_BREAKER:
3655 	case EVENT_SUBSYS_PSU:
3656 		buf += snprintf(buf, bufend - buf, "%d ", event->ev_resource);
3657 		break;
3658 	case EVENT_SUBSYS_LED:
3659 		buf += snprintf(buf, bufend - buf, "%s ", bscv_get_label(
3660 		    ssp->led_names, MAX_LED_ID, event->ev_resource - 1));
3661 		break;
3662 	default:
3663 		break;
3664 	}
3665 
3666 	/* fatal */
3667 	if (event->ev_subsys & EVENT_MASK_FAULT) {
3668 		if (event->ev_subsys & EVENT_MASK_FATAL) {
3669 			buf += snprintf(buf, bufend - buf, "FATAL FAULT: ");
3670 		} else {
3671 			buf += snprintf(buf, bufend - buf, "FAULT: ");
3672 		}
3673 	}
3674 
3675 	/* eventp */
3676 	if (eventtype <
3677 	    (sizeof (eventTypeStrings)/sizeof (*eventTypeStrings))) {
3678 		buf += snprintf(buf, bufend - buf, "%s",
3679 		    eventTypeStrings[eventtype]);
3680 	} else {
3681 		buf += snprintf(buf, bufend - buf,
3682 		    "unknown event 0x%02x%02x%02x%02x",
3683 		    event->ev_subsys, event->ev_event,
3684 		    event->ev_resource, event->ev_detail);
3685 	}
3686 
3687 	/* detail */
3688 	switch (subsystem) {
3689 	case EVENT_SUBSYS_TEMP:
3690 		if ((eventtype != EVENT_RECOVERED) &&
3691 		    eventtype != EVENT_DEVICE_INACCESSIBLE) {
3692 			buf += snprintf(buf, bufend - buf, " - %d degC",
3693 			    (int8_t)event->ev_detail);
3694 		}
3695 		break;
3696 	case EVENT_SUBSYS_FAN:
3697 		if (eventtype == EVENT_FAILED) {
3698 			buf += snprintf(buf, bufend - buf,
3699 			    " %d%%", event->ev_detail);
3700 		}
3701 		break;
3702 	case EVENT_SUBSYS_LOM:
3703 		switch (eventtype) {
3704 		case EVENT_FLASH_DOWNLOAD:
3705 			buf += snprintf(buf, bufend - buf,
3706 			    ": v%d.%d to v%d.%d",
3707 			    (event->ev_resource >> 4),
3708 			    (event->ev_resource & 0x0f),
3709 			    (event->ev_detail >> 4),
3710 			    (event->ev_detail & 0x0f));
3711 			break;
3712 		case EVENT_WATCHDOG_TRIGGER:
3713 			buf += snprintf(buf, bufend - buf,
3714 			    event->ev_detail ? "- soft" : " - hard");
3715 			break;
3716 		case EVENT_UNEXPECTED_RESET:
3717 			if (event->ev_detail &
3718 			    LOM_UNEXPECTEDRESET_MASK_BADTRAP) {
3719 				buf += snprintf(buf, bufend - buf,
3720 				    " - unclaimed exception 0x%x",
3721 				    event->ev_detail &
3722 				    ~LOM_UNEXPECTEDRESET_MASK_BADTRAP);
3723 			}
3724 			break;
3725 		case EVENT_RESET:
3726 			switch (event->ev_detail) {
3727 			case LOM_RESET_DETAIL_BYUSER:
3728 				buf += snprintf(buf, bufend - buf, " by user");
3729 				break;
3730 			case LOM_RESET_DETAIL_REPROGRAMMING:
3731 				buf += snprintf(buf, bufend - buf,
3732 				" after flash download");
3733 				break;
3734 			default:
3735 				buf += snprintf(buf, bufend - buf,
3736 				    " - unknown reason");
3737 				break;
3738 			}
3739 			break;
3740 		default:
3741 			break;
3742 		}
3743 		break;
3744 	case EVENT_SUBSYS_LED:
3745 		switch (event->ev_detail) {
3746 		case LOM_LED_STATE_OFF:
3747 			buf += snprintf(buf, bufend - buf, ": OFF");
3748 			break;
3749 		case LOM_LED_STATE_ON_STEADY:
3750 			buf += snprintf(buf, bufend - buf, ": ON");
3751 			break;
3752 		case LOM_LED_STATE_ON_FLASHING:
3753 		case LOM_LED_STATE_ON_SLOWFLASH:
3754 			buf += snprintf(buf, bufend - buf, ": BLINKING");
3755 			break;
3756 		case LOM_LED_STATE_INACCESSIBLE:
3757 			buf += snprintf(buf, bufend - buf, ": inaccessible");
3758 			break;
3759 		case LOM_LED_STATE_STANDBY:
3760 			buf += snprintf(buf, bufend - buf, ": standby");
3761 			break;
3762 		case LOM_LED_STATE_NOT_PRESENT:
3763 			buf += snprintf(buf, bufend - buf, ": not present");
3764 			break;
3765 		default:
3766 			buf += snprintf(buf, bufend - buf, ": 0x%x",
3767 			    event->ev_resource);
3768 			break;
3769 		}
3770 		break;
3771 	case EVENT_SUBSYS_USER:
3772 		switch (eventtype) {
3773 		case EVENT_USER_ADDED:
3774 		case EVENT_USER_REMOVED:
3775 		case EVENT_USER_PERMSCHANGED:
3776 		case EVENT_USER_LOGIN:
3777 		case EVENT_USER_PASSWORD_CHANGE:
3778 		case EVENT_USER_LOGINFAIL:
3779 		case EVENT_USER_LOGOUT:
3780 			buf += snprintf(buf, bufend - buf, " %d",
3781 			    event->ev_resource);
3782 		default:
3783 			break;
3784 		}
3785 		break;
3786 	case EVENT_SUBSYS_PSU:
3787 		if (event->ev_detail & LOM_PSU_NOACCESS) {
3788 			buf += snprintf(buf, bufend - buf, " - inaccessible");
3789 		} else if ((event->ev_detail & LOM_PSU_STATUS_MASK)
3790 		    == LOM_PSU_STATUS_MASK) {
3791 			buf += snprintf(buf, bufend - buf, " - OK");
3792 		} else {
3793 			buf += snprintf(buf, bufend - buf, " -");
3794 			/*
3795 			 * If both inputs are seen to have failed then simply
3796 			 * indicate that the PSU input has failed
3797 			 */
3798 			if (!(event->ev_detail &
3799 			    (LOM_PSU_INPUT_A_OK | LOM_PSU_INPUT_B_OK))) {
3800 				buf += snprintf(buf, bufend - buf, " Input");
3801 			} else {
3802 				/* At least one input is ok */
3803 				if (!(event->ev_detail & LOM_PSU_INPUT_A_OK)) {
3804 					buf += snprintf(buf, bufend - buf,
3805 					    " InA");
3806 				}
3807 				if (!(event->ev_detail & LOM_PSU_INPUT_B_OK)) {
3808 					buf += snprintf(buf, bufend - buf,
3809 					    " InB");
3810 				}
3811 				/*
3812 				 * Only flag an output error if an input is
3813 				 * still present
3814 				 */
3815 				if (!(event->ev_detail & LOM_PSU_OUTPUT_OK)) {
3816 					buf += snprintf(buf, bufend - buf,
3817 					    " Output");
3818 				}
3819 			}
3820 			buf += snprintf(buf, bufend - buf, " failed");
3821 		}
3822 		break;
3823 	case EVENT_SUBSYS_NONE:
3824 		if (eventtype == EVENT_FAULT_LED) {
3825 			switch (event->ev_detail) {
3826 			case 0:
3827 				buf += snprintf(buf, bufend - buf, " - ON");
3828 				break;
3829 			case 255:
3830 				buf += snprintf(buf, bufend - buf, " - OFF");
3831 				break;
3832 			default:
3833 				buf += snprintf(buf, bufend - buf,
3834 				    " - %dHz", event->ev_detail);
3835 				break;
3836 			}
3837 		}
3838 		break;
3839 	case EVENT_SUBSYS_HOST:
3840 		if (eventtype == EVENT_BOOTMODE_CHANGE) {
3841 			switch (event->ev_detail &
3842 			    ~EBUS_BOOTMODE_FORCE_CONSOLE) {
3843 			case EBUS_BOOTMODE_FORCE_NOBOOT:
3844 				buf += snprintf(buf, bufend - buf,
3845 				    " - no boot");
3846 				break;
3847 			case EBUS_BOOTMODE_RESET_DEFAULT:
3848 				buf += snprintf(buf, bufend - buf,
3849 				    " - reset defaults");
3850 				break;
3851 			case EBUS_BOOTMODE_FULLDIAG:
3852 				buf += snprintf(buf, bufend - buf,
3853 				    " - full diag");
3854 				break;
3855 			case EBUS_BOOTMODE_SKIPDIAG:
3856 				buf += snprintf(buf, bufend - buf,
3857 				    " - skip diag");
3858 				break;
3859 			default:
3860 				break;
3861 			}
3862 		}
3863 		if (eventtype == EVENT_SCC_STATUS) {
3864 			switch (event->ev_detail) {
3865 			case 0:
3866 				buf += snprintf(buf, bufend - buf,
3867 				    " - inserted");
3868 				break;
3869 			case 1:
3870 				buf += snprintf(buf, bufend - buf,
3871 				    " - removed");
3872 				break;
3873 			default:
3874 				break;
3875 			}
3876 		}
3877 		break;
3878 
3879 	default:
3880 		break;
3881 	}
3882 
3883 	/* shutd */
3884 	if (event->ev_subsys & EVENT_MASK_SHUTDOWN_REQD) {
3885 		buf += snprintf(buf, bufend - buf, " - shutdown req'd");
3886 	}
3887 
3888 	buf += snprintf(buf, bufend - buf, "\n");
3889 
3890 	if (buf >= bufend) {
3891 		/* Ensure newline at end of string */
3892 		bufend[-2] = '\n';
3893 		bufend[-1] = '\0';
3894 #ifdef DEBUG
3895 		cmn_err(CE_WARN, "!bscv_build_eventstring: buffer too small!");
3896 #endif /* DEBUG */
3897 	}
3898 }
3899 
3900 /*
3901  * function	- bscv_level_of_event
3902  * description	- This routine determines which level an event should be
3903  *		  reported at.
3904  * inputs	- lom event structure pointer
3905  * outputs	- event level.
3906  */
3907 static int
3908 bscv_level_of_event(lom_event_t *event)
3909 {
3910 	int level;
3911 	/*
3912 	 * This is the same criteria that the firmware uses except we
3913 	 * log the fault led on as being EVENT_LEVEL_FAULT
3914 	 */
3915 	if (EVENT_DECODE_SUBSYS(event->ev_subsys) == EVENT_SUBSYS_USER) {
3916 		level = EVENT_LEVEL_USER;
3917 	} else if ((EVENT_DECODE_SUBSYS(event->ev_subsys) ==
3918 	    EVENT_SUBSYS_ALARM) && (event->ev_event == EVENT_STATE_ON)) {
3919 		level = EVENT_LEVEL_FAULT;
3920 	} else if ((EVENT_DECODE_SUBSYS(event->ev_subsys) ==
3921 	    EVENT_SUBSYS_NONE) &&
3922 	    (event->ev_event == EVENT_FAULT_LED) &&
3923 	    (event->ev_detail != 0xff)) {
3924 		level = EVENT_LEVEL_FAULT;
3925 	} else if ((EVENT_DECODE_SUBSYS(event->ev_subsys) ==
3926 	    EVENT_SUBSYS_LOM) && event->ev_event == EVENT_TIME_REFERENCE) {
3927 		level = EVENT_LEVEL_NOTICE;
3928 	} else if (event->ev_event == EVENT_RECOVERED) {
3929 		/*
3930 		 * All recovery messages need to be reported to the console
3931 		 * because during boot, the faults which occurred whilst
3932 		 * Solaris was not running are relayed to the console.  There
3933 		 * is a case whereby a fatal fault (eg. over temp) could
3934 		 * have occurred and then recovered.  The recovery condition
3935 		 * needs to be reported so the user doesn't think that the
3936 		 * failure (over temp) is still present.
3937 		 */
3938 		level = EVENT_LEVEL_FAULT;
3939 	} else if (EVENT_DECODE_FAULT(event->ev_subsys) == 0) {
3940 		/* None of FAULT, FATAL or SHUTDOWN REQD are set */
3941 		level = EVENT_LEVEL_NOTICE;
3942 	} else if (EVENT_DECODE_FAULT(event->ev_subsys) == EVENT_MASK_FAULT) {
3943 		/* Only FAULT set i.e not FATAL or SHUTDOWN REQD */
3944 		level = EVENT_LEVEL_FAULT;
3945 	} else {
3946 		level = EVENT_LEVEL_FATAL;
3947 	}
3948 
3949 	return (level);
3950 }
3951 
3952 /*
3953  * function	- bscv_status
3954  * description	- This routine is called when any change in the LOMlite2 status
3955  *		  is indicated by the status registers.
3956  *
3957  * inputs	- LOM soft state structure pointer
3958  *
3959  * outputs	- none.
3960  */
3961 static void
3962 bscv_status(bscv_soft_state_t *ssp, uint8_t state_chng, uint8_t dev_no)
3963 {
3964 	int8_t temp;
3965 	uint8_t fanspeed;
3966 
3967 	ASSERT(bscv_held(ssp));
3968 
3969 	BSCV_TRACE(ssp, 'D', "bscv_status", "state_chng 0x%x dev_no 0x%x",
3970 	    state_chng, dev_no);
3971 
3972 	/*
3973 	 * The device that has changed is given by the state change
3974 	 * register and the event detail register so react
3975 	 * accordingly.
3976 	 */
3977 
3978 	if (state_chng == EBUS_STATE_NOTIFY) {
3979 		/*
3980 		 * The BSC is indicating a self state change
3981 		 */
3982 		if (dev_no == EBUS_DETAIL_FLASH) {
3983 			ssp->cssp_prog = B_TRUE;
3984 			BSCV_TRACE(ssp, 'D', "bscv_status",
3985 			    "ssp->cssp_prog changed to 0x%x",
3986 			    ssp->cssp_prog);
3987 			/*
3988 			 * It takes the BSC at least 100 ms to
3989 			 * clear down the comms protocol.
3990 			 * We back-off from talking to the
3991 			 * BSC during this period.
3992 			 */
3993 			delay(BSC_EVENT_POLL_NORMAL);
3994 			BSCV_TRACE(ssp, 'D', "bscv_status",
3995 			    "completed delay");
3996 		} else if (dev_no == EBUS_DETAIL_RESET) {
3997 			/*
3998 			 * The bsc has reset
3999 			 */
4000 			BSCV_TRACE(ssp, 'D', "bscv_status",
4001 			    "BSC reset occured, re-synching");
4002 			(void) bscv_attach_common(ssp);
4003 			BSCV_TRACE(ssp, 'D', "bscv_status",
4004 			    "completed attach_common");
4005 		}
4006 
4007 	}
4008 
4009 	if ((state_chng & EBUS_STATE_FAN) && ((dev_no - 1) < MAX_FANS)) {
4010 		fanspeed = bscv_get8(ssp, chan_general,
4011 		    EBUS_IDX_FAN1_SPEED + dev_no - 1);
4012 		/*
4013 		 * Only remember fanspeeds which are real values or
4014 		 * NOT PRESENT values.
4015 		 */
4016 		if ((fanspeed <= LOM_FAN_MAX_SPEED) ||
4017 		    (fanspeed == LOM_FAN_NOT_PRESENT)) {
4018 			ssp->fanspeed[dev_no - 1] = fanspeed;
4019 		}
4020 	}
4021 
4022 	if ((state_chng & EBUS_STATE_PSU) && ((dev_no - 1) < MAX_PSUS)) {
4023 		(void) bscv_get8(ssp, chan_general,
4024 		    EBUS_IDX_PSU1_STAT + dev_no - 1);
4025 	}
4026 
4027 	if (state_chng & EBUS_STATE_GP) {
4028 		(void) bscv_get8(ssp, chan_general, EBUS_IDX_GPIP);
4029 	}
4030 
4031 	if (state_chng & EBUS_STATE_CB) {
4032 		(void) bscv_get8(ssp, chan_general, EBUS_IDX_CBREAK_STATUS);
4033 	}
4034 
4035 	if ((state_chng & EBUS_STATE_TEMPERATURE) &&
4036 	    ((dev_no - 1) < MAX_TEMPS)) {
4037 		temp = bscv_get8(ssp, chan_general,
4038 		    EBUS_IDX_TEMP1 + dev_no - 1);
4039 		/*
4040 		 * Only remember temperatures which are real values or
4041 		 * a NOT PRESENT value.
4042 		 */
4043 		if ((temp <= LOM_TEMP_MAX_VALUE) ||
4044 		    (temp == LOM_TEMP_STATE_NOT_PRESENT)) {
4045 			ssp->temps.temp[dev_no - 1] = temp;
4046 		}
4047 	}
4048 
4049 	if (state_chng & EBUS_STATE_RAIL) {
4050 		(void) bscv_get8(ssp, chan_general, EBUS_IDX_SUPPLY_LO);
4051 		(void) bscv_get8(ssp, chan_general, EBUS_IDX_SUPPLY_HI);
4052 	}
4053 }
4054 
4055 char *
4056 bscv_get_label(char labels[][MAX_LOM2_NAME_STR], int limit, int index)
4057 {
4058 
4059 	if (labels == NULL)
4060 		return ("");
4061 
4062 	if (limit < 0 || index < 0 || index > limit)
4063 		return ("-");
4064 
4065 	return (labels[index]);
4066 }
4067 
4068 static void
4069 bscv_generic_sysevent(bscv_soft_state_t *ssp, char *class, char *subclass,
4070     char *fru_id, char *res_id, int32_t fru_state, char *msg)
4071 {
4072 	int rv;
4073 	nvlist_t *attr_list;
4074 
4075 	BSCV_TRACE(ssp, 'E', "bscv_generic_sysevent", "%s/%s:(%s,%s,%d) %s",
4076 	    class, subclass, fru_id, res_id, fru_state, msg);
4077 
4078 
4079 	if (nvlist_alloc(&attr_list, NV_UNIQUE_NAME_TYPE, KM_SLEEP)) {
4080 		BSCV_TRACE(ssp, 'E', "bscv_generic_sysevent",
4081 		    "nvlist alloc failure");
4082 		return;
4083 	}
4084 	if (nvlist_add_uint32(attr_list, ENV_VERSION, 1)) {
4085 		BSCV_TRACE(ssp, 'E', "bscv_generic_sysevent",
4086 		    "nvlist ENV_VERSION failure");
4087 		nvlist_free(attr_list);
4088 		return;
4089 	}
4090 	if (nvlist_add_string(attr_list, ENV_FRU_ID, fru_id)) {
4091 		BSCV_TRACE(ssp, 'E', "bscv_generic_sysevent",
4092 		    "nvlist ENV_FRU_ID failure");
4093 		nvlist_free(attr_list);
4094 		return;
4095 	}
4096 	if (nvlist_add_string(attr_list, ENV_FRU_RESOURCE_ID, res_id)) {
4097 		BSCV_TRACE(ssp, 'E', "bscv_generic_sysevent",
4098 		    "nvlist ENV_FRU_RESOURCE_ID failure");
4099 		nvlist_free(attr_list);
4100 		return;
4101 	}
4102 	if (nvlist_add_string(attr_list, ENV_FRU_DEVICE, ENV_RESERVED_ATTR)) {
4103 		BSCV_TRACE(ssp, 'E', "bscv_generic_sysevent",
4104 		    "nvlist ENV_FRU_DEVICE failure");
4105 		nvlist_free(attr_list);
4106 		return;
4107 	}
4108 	if (nvlist_add_int32(attr_list, ENV_FRU_STATE, fru_state)) {
4109 		BSCV_TRACE(ssp, 'E', "bscv_generic_sysevent",
4110 		    "nvlist ENV_FRU_STATE failure");
4111 		nvlist_free(attr_list);
4112 		return;
4113 	}
4114 	if (nvlist_add_string(attr_list, ENV_MSG, msg)) {
4115 		BSCV_TRACE(ssp, 'E', "bscv_generic_sysevent",
4116 		    "nvlist ENV_MSG failure");
4117 		nvlist_free(attr_list);
4118 		return;
4119 	}
4120 
4121 	rv = ddi_log_sysevent(ssp->dip, DDI_VENDOR_SUNW, class,
4122 	    subclass, attr_list, NULL, DDI_SLEEP);
4123 
4124 	if (rv == DDI_SUCCESS) {
4125 		BSCV_TRACE(ssp, 'E', "bscv_generic_sysevent", "sent sysevent");
4126 	} else {
4127 		cmn_err(CE_WARN, "!cannot deliver sysevent");
4128 	}
4129 
4130 	nvlist_free(attr_list);
4131 }
4132 
4133 /*
4134  * function	- bscv_sysevent
4135  * description	- send out a sysevent on the given change if needed
4136  * inputs	- soft state pointer, event to report
4137  * outputs	- none
4138  */
4139 
4140 static void
4141 bscv_sysevent(bscv_soft_state_t *ssp, lom_event_t *event)
4142 {
4143 	char *class = NULL;
4144 	char *subclass = NULL;
4145 	char *fru_id = "Blade";	/* The blade is only one FRU */
4146 	char *res_id;
4147 	int32_t fru_state = 0;
4148 
4149 	BSCV_TRACE(ssp, 'E', "bscv_sysevent", "processing event");
4150 
4151 	ASSERT(event != NULL);
4152 
4153 	/* Map ev_subsys to sysevent class/sub-class */
4154 
4155 	switch (EVENT_DECODE_SUBSYS(event->ev_subsys)) {
4156 		case EVENT_SUBSYS_NONE:
4157 		break;
4158 		case EVENT_SUBSYS_ALARM:
4159 		break;
4160 		case EVENT_SUBSYS_TEMP:
4161 		class = EC_ENV, subclass = ESC_ENV_TEMP;
4162 		res_id = bscv_get_label(ssp->temps.name, ssp->temps.num,
4163 		    event->ev_resource - 1);
4164 		switch (event->ev_event) {
4165 			case EVENT_SEVERE_OVERHEAT:
4166 			fru_state = ENV_FAILED;
4167 			break;
4168 			case EVENT_OVERHEAT:
4169 			fru_state = ENV_WARNING;
4170 			break;
4171 			case EVENT_NO_OVERHEAT:
4172 			fru_state = ENV_OK;
4173 			break;
4174 			default:
4175 			return;
4176 		}
4177 		break;
4178 		case EVENT_SUBSYS_OVERTEMP:
4179 		break;
4180 		case EVENT_SUBSYS_FAN:
4181 		class = EC_ENV, subclass = ESC_ENV_FAN;
4182 		res_id = bscv_get_label(ssp->fan_names, ssp->num_fans,
4183 		    event->ev_resource - 1);
4184 		switch (event->ev_event) {
4185 			case EVENT_FAILED:
4186 			fru_state = ENV_FAILED;
4187 			break;
4188 			case EVENT_RECOVERED:
4189 			fru_state = ENV_OK;
4190 			break;
4191 			default:
4192 			return;
4193 		}
4194 		break;
4195 		case EVENT_SUBSYS_SUPPLY:
4196 		class = EC_ENV, subclass = ESC_ENV_POWER;
4197 		res_id = bscv_get_label(ssp->sflags.name, ssp->sflags.num,
4198 		    event->ev_resource - 1);
4199 		switch (event->ev_event) {
4200 			case EVENT_FAILED:
4201 			fru_state = ENV_FAILED;
4202 			break;
4203 			case EVENT_RECOVERED:
4204 			fru_state = ENV_OK;
4205 			break;
4206 			default:
4207 			return;
4208 		}
4209 		break;
4210 		case EVENT_SUBSYS_BREAKER:
4211 		break;
4212 		case EVENT_SUBSYS_PSU:
4213 		break;
4214 		case EVENT_SUBSYS_USER:
4215 		break;
4216 		case EVENT_SUBSYS_PHONEHOME:
4217 		break;
4218 		case EVENT_SUBSYS_LOM:
4219 		break;
4220 		case EVENT_SUBSYS_HOST:
4221 		break;
4222 		case EVENT_SUBSYS_EVENTLOG:
4223 		break;
4224 		case EVENT_SUBSYS_EXTRA:
4225 		break;
4226 		case EVENT_SUBSYS_LED:
4227 		if (event->ev_event != EVENT_FAULT_LED &&
4228 		    event->ev_event != EVENT_STATE_CHANGE)
4229 			return;
4230 		/*
4231 		 * There are 3 LEDs : Power, Service, Ready-to-Remove on a
4232 		 * JBOS blade.  We'll never report the Power since Solaris
4233 		 * won't be running when it is _switched_ ON.  Ready-to-Remove
4234 		 * will only be lit when we're powered down which also means
4235 		 * Solaris won't be running. We don't want to report it
4236 		 * during system testing / Sun VTS exercising the LEDs.
4237 		 *
4238 		 * Therefore, we only report the Service Required LED.
4239 		 */
4240 		class = EC_ENV, subclass = ESC_ENV_LED;
4241 		res_id = bscv_get_label(ssp->led_names, MAX_LED_ID,
4242 		    event->ev_resource - 1);
4243 
4244 		switch (event->ev_detail) {
4245 			case LOM_LED_STATE_ON_STEADY:
4246 			fru_state = ENV_LED_ON;
4247 			break;
4248 			case LOM_LED_STATE_ON_FLASHING:
4249 			case LOM_LED_STATE_ON_SLOWFLASH:
4250 			fru_state = ENV_LED_BLINKING;
4251 			break;
4252 			case LOM_LED_STATE_OFF:
4253 			fru_state = ENV_LED_OFF;
4254 			break;
4255 			case LOM_LED_STATE_INACCESSIBLE:
4256 			fru_state = ENV_LED_INACCESSIBLE;
4257 			break;
4258 			case LOM_LED_STATE_STANDBY:
4259 			fru_state = ENV_LED_STANDBY;
4260 			break;
4261 			case LOM_LED_STATE_NOT_PRESENT:
4262 			fru_state = ENV_LED_NOT_PRESENT;
4263 			break;
4264 			default:
4265 			fru_state = ENV_LED_INACCESSIBLE;
4266 			break;
4267 		}
4268 		break;
4269 		default :
4270 		break;
4271 	}
4272 
4273 	if (class == NULL || subclass == NULL) {
4274 		BSCV_TRACE(ssp, 'E', "bscv_sysevent", "class/subclass NULL");
4275 		return;
4276 	}
4277 
4278 	bscv_generic_sysevent(ssp, class, subclass, fru_id, res_id, fru_state,
4279 	    ENV_RESERVED_ATTR);
4280 }
4281 
4282 /*
4283  * *********************************************************************
4284  * Firmware download (programming)
4285  * *********************************************************************
4286  */
4287 
4288 /*
4289  * function	- bscv_prog
4290  * description	- LOMlite2 flash programming code.
4291  *
4292  *		  bscv_prog_image - download a complete image to the lom.
4293  *		  bscv_prog_receive_image - receive data to build up a
4294  *			complete image.
4295  *		  bscv_prog_stop_lom - pause the event daemon and prepare
4296  *			lom for firmware upgrade.
4297  *		  bscv_prog_start_lom - reinit the driver/lom after upgrade
4298  *			and restart the event daemon
4299  *
4300  * inputs	- soft state pointer, arg ptr, ioctl mode
4301  * outputs	- status
4302  */
4303 
4304 static int
4305 bscv_prog(bscv_soft_state_t *ssp, intptr_t arg, int mode)
4306 {
4307 	lom_prog_t *prog;
4308 	int res = 0;
4309 
4310 	/*
4311 	 * We will get repeatedly called with bits of data first for
4312 	 * loader, then for main image.
4313 	 */
4314 	prog = (lom_prog_t *)kmem_alloc(sizeof (lom_prog_t), KM_SLEEP);
4315 
4316 	if (ddi_copyin((caddr_t)arg, (caddr_t)prog, sizeof (*prog),
4317 	    mode) < 0) {
4318 		kmem_free((void *)prog, sizeof (*prog));
4319 		return (EFAULT);
4320 	}
4321 
4322 	BSCV_TRACE(ssp, 'U', "bscv_prog",
4323 	    "index 0x%x size 0x%x", prog->index, prog->size);
4324 
4325 	mutex_enter(&ssp->prog_mu);
4326 	if (prog->size == 0) {
4327 		if (prog->index == 2) {
4328 			/*
4329 			 * This is the initial request for the chip type so we
4330 			 * know what we are programming.
4331 			 * The type will have been read in at init so just
4332 			 * return it in data[0].
4333 			 */
4334 			prog->data[0] = bscv_get8_cached(ssp,
4335 			    EBUS_IDX_CPU_IDENT);
4336 
4337 			if (ddi_copyout((caddr_t)prog, (caddr_t)arg,
4338 			    sizeof (lom_prog_t), mode) < 0) {
4339 				res = EFAULT;
4340 			}
4341 		} else if (prog->index == 0) {
4342 			res = bscv_prog_stop_lom(ssp);
4343 		} else if (prog->index == 1) {
4344 			res = bscv_prog_start_lom(ssp);
4345 		} else {
4346 			res = EINVAL;
4347 		}
4348 	} else {
4349 		if (ssp->image == NULL) {
4350 			ssp->image = (uint8_t *)kmem_zalloc(
4351 			    BSC_IMAGE_MAX_SIZE, KM_SLEEP);
4352 		}
4353 		res = bscv_prog_receive_image(ssp, prog,
4354 		    ssp->image, BSC_IMAGE_MAX_SIZE);
4355 	}
4356 	mutex_exit(&ssp->prog_mu);
4357 	kmem_free((void *)prog, sizeof (lom_prog_t));
4358 
4359 	return (res);
4360 }
4361 
4362 static int
4363 bscv_check_loader_config(bscv_soft_state_t *ssp, boolean_t is_image2)
4364 {
4365 	BSCV_TRACE(ssp, 'U', "bscv_check_loader_config",
4366 	    "loader_running %d, is_image2 %d",
4367 	    ssp->loader_running, is_image2);
4368 
4369 	/*
4370 	 * loader_running TRUE means that we have told the microcontroller to
4371 	 * JUMP into the loader code which has been downloaded into its RAM.
4372 	 * At this point its an error to try and download another loader.  We
4373 	 * should be downloading the actual image at this point.
4374 	 * Conversely, it is an error to download an image when the loader is
4375 	 * not already downloaded and the microcontroller hasn't JUMPed into it.
4376 	 * is_image2 TRUE means the image is being downloaded.
4377 	 * is_image2 FALSE means the loader is being downloaded.
4378 	 */
4379 	if (ssp->loader_running && !is_image2) {
4380 		cmn_err(CE_WARN, "Attempt to download loader image "
4381 		    "with loader image already active");
4382 		cmn_err(CE_CONT, "This maybe an attempt to restart a "
4383 		    "failed firmware download - ignoring download attempt");
4384 		return (B_FALSE);
4385 	} else if (!ssp->loader_running && is_image2) {
4386 		cmn_err(CE_WARN, "Attempt to download firmware image "
4387 		    "without loader image active");
4388 		return (B_FALSE);
4389 
4390 	}
4391 
4392 	return (B_TRUE);
4393 }
4394 
4395 static uint32_t
4396 bscv_get_pagesize(bscv_soft_state_t *ssp)
4397 {
4398 	uint32_t pagesize;
4399 
4400 	ASSERT(bscv_held(ssp));
4401 
4402 	pagesize = bscv_get32(ssp, chan_prog,
4403 	    BSCVA(EBUS_CMD_SPACE_PROGRAM, EBUS_PROGRAM_PAGE0));
4404 
4405 	BSCV_TRACE(ssp, 'U', "bscv_get_pagesize", "pagesize 0x%x", pagesize);
4406 
4407 	return (pagesize);
4408 }
4409 
4410 /*
4411  * Sets the pagesize, returning the old value.
4412  */
4413 static uint32_t
4414 bscv_set_pagesize(bscv_soft_state_t *ssp, uint32_t pagesize)
4415 {
4416 	uint32_t old_pagesize;
4417 
4418 	ASSERT(bscv_held(ssp));
4419 
4420 	old_pagesize = bscv_get_pagesize(ssp);
4421 
4422 	/*
4423 	 * The microcontroller remembers this value until until someone
4424 	 * changes it.
4425 	 */
4426 	bscv_put32(ssp, chan_prog,
4427 	    BSCVA(EBUS_CMD_SPACE_PROGRAM, EBUS_PROGRAM_PSIZ0), pagesize);
4428 
4429 	return (old_pagesize);
4430 }
4431 
4432 static uint8_t
4433 bscv_enter_programming_mode(bscv_soft_state_t *ssp)
4434 {
4435 	uint8_t retval;
4436 
4437 	ASSERT(bscv_held(ssp));
4438 
4439 	bscv_put8(ssp, chan_prog,
4440 	    BSCVA(EBUS_CMD_SPACE_PROGRAM, EBUS_PROGRAM_PCSR),
4441 	    EBUS_PROGRAM_PCR_PRGMODE_ON);
4442 
4443 	retval = bscv_get8(ssp, chan_prog, BSCVA(EBUS_CMD_SPACE_PROGRAM,
4444 	    EBUS_PROGRAM_PCSR));
4445 
4446 	return (retval);
4447 }
4448 
4449 static void
4450 bscv_leave_programming_mode(bscv_soft_state_t *ssp, boolean_t with_jmp)
4451 {
4452 	uint8_t reg;
4453 	ASSERT(bscv_held(ssp));
4454 
4455 	if (with_jmp) {
4456 		reg = EBUS_PROGRAM_PCR_PROGOFF_JUMPTOADDR;
4457 		BSCV_TRACE(ssp, 'U', "bscv_leave_programming_mode",
4458 		    "jumptoaddr");
4459 	} else {
4460 		reg = EBUS_PROGRAM_PCR_PRGMODE_OFF;
4461 		BSCV_TRACE(ssp, 'U', "bscv_leave_programming_mode",
4462 		    "prgmode_off");
4463 	}
4464 
4465 	bscv_put8(ssp, chan_prog,
4466 	    BSCVA(EBUS_CMD_SPACE_PROGRAM, EBUS_PROGRAM_PCSR), reg);
4467 }
4468 
4469 
4470 static void
4471 bscv_set_jump_to_addr(bscv_soft_state_t *ssp, uint32_t loadaddr)
4472 {
4473 	ASSERT(bscv_held(ssp));
4474 
4475 	bscv_put32(ssp, chan_prog,
4476 	    BSCVA(EBUS_CMD_SPACE_PROGRAM, EBUS_PROGRAM_PADR0), loadaddr);
4477 
4478 	BSCV_TRACE(ssp, 'U', "bscv_set_jump_to_addr",
4479 	    "set jump to loadaddr 0x%x", loadaddr);
4480 }
4481 
4482 static uint8_t
4483 bscv_erase_once(bscv_soft_state_t *ssp, uint32_t loadaddr, uint32_t image_size)
4484 {
4485 	uint8_t retval;
4486 
4487 	ASSERT(bscv_held(ssp));
4488 
4489 	/*
4490 	 * write PADR, PSIZ to define area to be erased
4491 	 * We do not send erase for zero size because the current
4492 	 * downloader gets this wrong
4493 	 */
4494 
4495 	/*
4496 	 * start at 0
4497 	 */
4498 	BSCV_TRACE(ssp, 'U', "bscv_erase_once", "sending erase command");
4499 
4500 	bscv_put32(ssp, chan_prog,
4501 	    BSCVA(EBUS_CMD_SPACE_PROGRAM, EBUS_PROGRAM_PADR0),
4502 	    loadaddr);
4503 
4504 	/* set PSIZ to full size of image to be programmed */
4505 	bscv_put32(ssp, chan_prog,
4506 	    BSCVA(EBUS_CMD_SPACE_PROGRAM, EBUS_PROGRAM_PSIZ0),
4507 	    image_size);
4508 
4509 	/* write ERASE to PCSR */
4510 	bscv_put8(ssp, chan_prog,
4511 	    BSCVA(EBUS_CMD_SPACE_PROGRAM, EBUS_PROGRAM_PCSR),
4512 	    EBUS_PROGRAM_PCR_ERASE);
4513 
4514 	/* read PCSR to check status */
4515 	retval = bscv_get8(ssp, chan_prog,
4516 	    BSCVA(EBUS_CMD_SPACE_PROGRAM, EBUS_PROGRAM_PCSR));
4517 	return (retval);
4518 }
4519 
4520 static uint8_t
4521 bscv_do_erase(bscv_soft_state_t *ssp, uint32_t loadaddr, uint32_t image_size,
4522     boolean_t is_image2)
4523 {
4524 	int retryable = BSC_ERASE_RETRY_LIMIT;
4525 	uint8_t retval;
4526 
4527 	while (retryable--) {
4528 		retval = bscv_erase_once(ssp, loadaddr, image_size);
4529 		if (PSR_SUCCESS(retval))
4530 			break;
4531 		else
4532 			cmn_err(CE_WARN, "erase error 0x%x, attempt %d"
4533 			    ", base 0x%x, size 0x%x, %s image",
4534 			    retval, BSC_ERASE_RETRY_LIMIT - retryable,
4535 			    loadaddr, image_size,
4536 			    is_image2 ? "main" : "loader");
4537 	}
4538 
4539 	return (retval);
4540 }
4541 
4542 static uint8_t
4543 bscv_set_page(bscv_soft_state_t *ssp, uint32_t addr)
4544 {
4545 	uint32_t retval;
4546 	int retryable = BSC_PAGE_RETRY_LIMIT;
4547 
4548 	ASSERT(bscv_held(ssp));
4549 
4550 	while (retryable--) {
4551 
4552 		/*
4553 		 * Write the page address and read it back for confirmation.
4554 		 */
4555 		bscv_put32(ssp, chan_prog,
4556 		    BSCVA(EBUS_CMD_SPACE_PROGRAM, EBUS_PROGRAM_PADR0),
4557 		    addr);
4558 		retval = bscv_get32(ssp, chan_prog,
4559 		    BSCVA(EBUS_CMD_SPACE_PROGRAM, EBUS_PROGRAM_PADR0));
4560 
4561 		if (retval == addr)
4562 			break;
4563 		else {
4564 			cmn_err(CE_WARN, "programmming error, attempt %d, "
4565 			    "set page 0x%x, read back 0x%x",
4566 			    BSC_PAGE_RETRY_LIMIT - retryable,
4567 			    addr, retval);
4568 		}
4569 	}
4570 	return ((addr == retval) ? EBUS_PROGRAM_PSR_SUCCESS :
4571 	    EBUS_PROGRAM_PSR_INVALID_OPERATION);
4572 }
4573 
4574 static uint8_t
4575 bscv_do_page_data_once(bscv_soft_state_t *ssp, uint32_t index,
4576     uint32_t image_size, uint32_t pagesize, uint8_t *imagep,
4577     uint16_t *calcd_chksum)
4578 {
4579 	uint32_t size;
4580 	uint16_t chksum;
4581 	int i;
4582 	uint8_t retval;
4583 
4584 	ASSERT(bscv_held(ssp));
4585 
4586 	BSCV_TRACE(ssp, 'P', "bscv_do_page_data_once", "index 0x%x", index);
4587 
4588 	/* write PSIZ bytes to PDAT */
4589 	if (index + pagesize < image_size) {
4590 		bscv_rep_rw8(ssp, chan_prog, imagep + index,
4591 		    BSCVA(EBUS_CMD_SPACE_PROGRAM, EBUS_PROGRAM_DATA),
4592 		    pagesize, DDI_DEV_NO_AUTOINCR, B_TRUE /* write */);
4593 		size = pagesize;
4594 	} else {
4595 		BSCV_TRACE(ssp, 'P', "bscv_do_page_once",
4596 		    "Sending last block, last 0x%x bytes",
4597 		    (image_size % pagesize));
4598 		size = (image_size - index);
4599 		bscv_rep_rw8(ssp, chan_prog, imagep + index,
4600 		    BSCVA(EBUS_CMD_SPACE_PROGRAM, EBUS_PROGRAM_DATA),
4601 		    size, DDI_DEV_NO_AUTOINCR, B_TRUE /* write */);
4602 		/* Now pad the rest of the page with zeros */
4603 		for (i = size; i < pagesize; i++) {
4604 			bscv_put8(ssp, chan_prog,
4605 			    BSCVA(EBUS_CMD_SPACE_PROGRAM,
4606 			    EBUS_PROGRAM_DATA),
4607 			    0);
4608 		}
4609 	}
4610 
4611 	/* write the checksum to PCSM */
4612 	chksum = 0;
4613 	for (i = 0; i < size; i++) {
4614 		chksum = ((chksum << 3) | (chksum >> 13)) ^
4615 		    *(imagep + index + i);
4616 	}
4617 	/* Cope with non-pagesize sized bufers */
4618 	for (; i < pagesize; i++) {
4619 		chksum = ((chksum << 3) | (chksum >> 13)) ^ 0;
4620 	}
4621 	bscv_put16(ssp, chan_prog,
4622 	    BSCVA(EBUS_CMD_SPACE_PROGRAM, EBUS_PROGRAM_PCSM0), chksum);
4623 
4624 	bscv_put8(ssp, chan_prog,
4625 	    BSCVA(EBUS_CMD_SPACE_PROGRAM, EBUS_PROGRAM_PCSR),
4626 	    EBUS_PROGRAM_PCR_PROGRAM);
4627 
4628 	retval = bscv_get8(ssp, chan_prog,
4629 	    BSCVA(EBUS_CMD_SPACE_PROGRAM, EBUS_PROGRAM_PCSR));
4630 
4631 	*calcd_chksum = chksum;
4632 	return (retval);
4633 }
4634 
4635 static uint8_t bscv_do_page(bscv_soft_state_t *ssp, uint32_t loadaddr,
4636     uint32_t index, uint32_t image_size, uint32_t pagesize, uint8_t *imagep,
4637     boolean_t is_image2)
4638 {
4639 	int retryable = BSC_PAGE_RETRY_LIMIT;
4640 	uint8_t retval;
4641 	uint16_t checksum;
4642 
4643 	BSCV_TRACE(ssp, 'P', "bscv_do_page", "index 0x%x", index);
4644 
4645 	while (retryable--) {
4646 		/*
4647 		 * Set the page address (with retries).  If this is not
4648 		 * successful, then there is no point carrying on and sending
4649 		 * the page's data since that could cause random memory
4650 		 * corruption in the microcontroller.
4651 		 */
4652 		retval = bscv_set_page(ssp, loadaddr + index);
4653 		if (!PSR_SUCCESS(retval)) {
4654 			cmn_err(CE_WARN, "programming error 0x%x, "
4655 			    "could not setup page address 0x%x, %s image",
4656 			    retval, loadaddr + index,
4657 			    is_image2 ? "main" : "loader");
4658 			break;
4659 		}
4660 
4661 		/*
4662 		 * Send down the data for the page
4663 		 */
4664 
4665 		BSCV_TRACE(ssp, 'P', "bscv_do_page", "sending data for page");
4666 
4667 		retval = bscv_do_page_data_once(ssp, index, image_size,
4668 		    pagesize, imagep, &checksum);
4669 		if (PSR_SUCCESS(retval))
4670 			break;
4671 		else
4672 			cmn_err(CE_WARN, "programming error 0x%x,"
4673 			    " attempt %d, index 0x%x, checksum 0x%x, %s image",
4674 			    retval, BSC_PAGE_RETRY_LIMIT - retryable,
4675 			    index, checksum, is_image2 ? "main" : "loader");
4676 	}
4677 
4678 	BSCV_TRACE(ssp, 'U', "bscv_do_page", "Returning 0x%x for index 0x%x,"
4679 	    " checksum 0x%x, %s image", retval, index, checksum,
4680 	    is_image2 ? "main" : "loader");
4681 
4682 	return (retval);
4683 }
4684 
4685 static uint8_t
4686 bscv_do_pages(bscv_soft_state_t *ssp, uint32_t loadaddr, uint32_t image_size,
4687     uint32_t pagesize, uint8_t *imagep, boolean_t is_image2)
4688 {
4689 	uint8_t retval;
4690 	uint32_t index;
4691 
4692 	BSCV_TRACE(ssp, 'P', "bscv_do_pages", "entered");
4693 
4694 	for (index = 0; index < image_size; index += pagesize) {
4695 		retval = bscv_do_page(ssp, loadaddr, index, image_size,
4696 		    pagesize, imagep, is_image2);
4697 		if (bscv_faulty(ssp) || !PSR_SUCCESS(retval)) {
4698 			BSCV_TRACE(ssp, 'U', "bscv_do_pages",
4699 			    "Failed to program lom (status 0x%x)", retval);
4700 			break;
4701 		}
4702 	}
4703 
4704 	return (retval);
4705 }
4706 
4707 static int
4708 bscv_prog_image(bscv_soft_state_t *ssp, boolean_t is_image2,
4709     uint8_t *imagep, int image_size, uint32_t loadaddr)
4710 {
4711 	uint32_t pagesize;
4712 	int res = 0;
4713 	uint8_t retval;
4714 
4715 	BSCV_TRACE(ssp, 'U', "bscv_prog_image",
4716 	    "image 0x%x, imagep %p, size 0x%x",
4717 	    is_image2 ? 2 : 1, imagep, image_size);
4718 
4719 	if (!bscv_check_loader_config(ssp, is_image2))
4720 		/*
4721 		 * Return no error to allow userland to continue on with
4722 		 * downloading the image.
4723 		 */
4724 		return (0);
4725 
4726 	bscv_enter(ssp);
4727 
4728 	pagesize = bscv_get_pagesize(ssp);
4729 
4730 	retval = bscv_enter_programming_mode(ssp);
4731 	if (bscv_faulty(ssp) || !PSR_PROG(retval)) {
4732 		cmn_err(CE_WARN, "lom: Failed to enter program mode, error 0x%x"
4733 		    ", %s image", retval, is_image2 ? "main" : "loader");
4734 		res = EIO;
4735 		goto BSCV_PROG_IMAGE_END;
4736 	}
4737 	BSCV_TRACE(ssp, 'U', "bscv_prog_image", "entered programming mode");
4738 
4739 	/*
4740 	 * Only issue an erase if we are downloading the image.  The loader
4741 	 * does not need this step.
4742 	 */
4743 	if (is_image2 && (image_size != 0)) {
4744 		retval = bscv_do_erase(ssp, loadaddr, image_size, is_image2);
4745 		if (bscv_faulty(ssp) || !PSR_SUCCESS(retval)) {
4746 			cmn_err(CE_WARN,
4747 			    "lom: Erase failed during programming, status 0x%x",
4748 			    retval);
4749 			res = EIO;
4750 			goto BSCV_PROG_IMAGE_END;
4751 		} else {
4752 			BSCV_TRACE(ssp, 'U', "bscv_prog_image",
4753 			    "erase complete - programming...");
4754 
4755 		}
4756 	}
4757 
4758 	(void) bscv_set_pagesize(ssp, pagesize);
4759 
4760 	retval = bscv_do_pages(ssp, loadaddr, image_size, pagesize, imagep,
4761 	    is_image2);
4762 	if (bscv_faulty(ssp) || !PSR_SUCCESS(retval)) {
4763 		BSCV_TRACE(ssp, 'U', "bscv_prog_image",
4764 		    "Failed to program lom (status 0x%x)", retval);
4765 		res = EIO;
4766 		goto BSCV_PROG_IMAGE_END;
4767 	}
4768 
4769 BSCV_PROG_IMAGE_END:
4770 	if (res == 0 && !is_image2) {
4771 		/*
4772 		 * We've downloaded the loader successfully.  Now make the
4773 		 * microcontroller jump to it.
4774 		 */
4775 		bscv_set_jump_to_addr(ssp, loadaddr);
4776 		ssp->loader_running = B_TRUE;
4777 		bscv_leave_programming_mode(ssp, B_TRUE);
4778 	} else {
4779 		/*
4780 		 * We've just downloaded either the loader which failed, or
4781 		 * the image (which may or may not have been successful).
4782 		 */
4783 		bscv_set_jump_to_addr(ssp, 0);
4784 
4785 		if (res != 0) {
4786 			BSCV_TRACE(ssp, 'U', "bscv_prog_image",
4787 			    "got error 0x%x - leaving programming mode",
4788 			    res);
4789 			cmn_err(CE_WARN, "programming error 0x%x, %s image",
4790 			    res, is_image2 ? "main" : "loader");
4791 		} else {
4792 			BSCV_TRACE(ssp, 'U', "bscv_prog_image",
4793 			    "programming complete - leaving programming mode");
4794 		}
4795 
4796 		bscv_leave_programming_mode(ssp, B_FALSE);
4797 		ssp->loader_running = B_FALSE;
4798 	}
4799 
4800 	bscv_exit(ssp);
4801 
4802 	return (res);
4803 }
4804 
4805 
4806 static int
4807 bscv_prog_receive_image(bscv_soft_state_t *ssp, lom_prog_t *prog,
4808     uint8_t *imagep, int max_size)
4809 {
4810 	int	res = 0;
4811 	uint_t	size;
4812 	int32_t loadaddr;
4813 	lom_prog_data_t *prog_data;
4814 
4815 	if ((prog->index & 0x7FFF) != ssp->prog_index) {
4816 		BSCV_TRACE(ssp, 'U', "bscv_prog_receive_image",
4817 		    "Got wrong buffer 0x%x, expected 0x%x",
4818 		    prog->index & 0x7fff, ssp->prog_index);
4819 		return (EINVAL);
4820 	}
4821 
4822 	/*
4823 	 * We want to get the whole image and then do the download.
4824 	 * It is assumed the device is now in programming mode.
4825 	 */
4826 
4827 	if ((prog->index & 0x7fff) == 0) {
4828 		/* Starting a new image */
4829 		ssp->image_ptr = 0;
4830 	}
4831 
4832 	if ((ssp->image_ptr + prog->size) > max_size) {
4833 		cmn_err(CE_WARN,
4834 		    "lom image exceeded maximum size: got 0x%x, maximum 0x%x",
4835 		    (ssp->image_ptr + prog->size), max_size);
4836 		return (EFAULT);
4837 	}
4838 	bcopy(prog->data, &imagep[ssp->image_ptr], prog->size);
4839 	ssp->image_ptr += prog->size;
4840 
4841 	ssp->prog_index++;
4842 
4843 	if (prog->index & 0x8000) {
4844 		/*
4845 		 * OK we have the whole image so synch up and start download.
4846 		 */
4847 		prog_data = (lom_prog_data_t *)imagep;
4848 		if (prog_data->header.magic != PROG_MAGIC) {
4849 			/* Old style programming data */
4850 			/* Take care image may not fill all of structure */
4851 
4852 			/* sign extend loadaddr from 16  to 32 bits */
4853 			loadaddr = (int16_t)((uint16_t)((imagep[2] << 8) +
4854 			    imagep[3]));
4855 
4856 			size = (imagep[0] << 8) + imagep[1];
4857 			if (size != (ssp->image_ptr - 4)) {
4858 				cmn_err(CE_WARN, "Image size mismatch:"
4859 				    " expected 0x%x, got 0x%x",
4860 				    size, (ssp->image_ptr - 1));
4861 			}
4862 
4863 			res = bscv_prog_image(ssp,
4864 			    ssp->image2_processing,
4865 			    imagep + 4, ssp->image_ptr - 4, loadaddr);
4866 
4867 			/*
4868 			 * Done the loading so set the flag to say we are doing
4869 			 * the other image.
4870 			 */
4871 			ssp->image2_processing = !ssp->image2_processing;
4872 		} else if ((ssp->image_ptr < sizeof (*prog_data)) ||
4873 		    (prog_data->platform.bscv.size !=
4874 		    (ssp->image_ptr - sizeof (*prog_data)))) {
4875 			/* Image too small for new style image */
4876 			cmn_err(CE_WARN, "image too small");
4877 			res = EINVAL;
4878 		} else {
4879 			/* New style programming image */
4880 			switch (prog_data->platmagic) {
4881 			case PROG_PLAT_BSCV_IMAGE:
4882 				res = bscv_prog_image(ssp, B_TRUE,
4883 				    imagep + sizeof (*prog_data),
4884 				    prog_data->platform.bscv.size,
4885 				    prog_data->platform.bscv.loadaddr);
4886 				ssp->image2_processing = B_FALSE;
4887 				break;
4888 			case PROG_PLAT_BSCV_LOADER:
4889 				res = bscv_prog_image(ssp, B_FALSE,
4890 				    imagep + sizeof (*prog_data),
4891 				    prog_data->platform.bscv.size,
4892 				    prog_data->platform.bscv.loadaddr);
4893 				ssp->image2_processing = B_TRUE;
4894 				break;
4895 			default:
4896 				cmn_err(CE_WARN, "unknown platmagic 0x%x",
4897 				    prog_data->platmagic);
4898 				res = EINVAL;
4899 				break;
4900 			}
4901 		}
4902 		ssp->prog_index = 0;
4903 		ssp->image_ptr = 0;
4904 	}
4905 	return (res);
4906 }
4907 
4908 static int
4909 bscv_prog_stop_lom(bscv_soft_state_t *ssp)
4910 {
4911 	if (ssp->programming) {
4912 		/*
4913 		 * Already programming - this may be a retry of a failed
4914 		 * programming attempt or just a software error!
4915 		 */
4916 		goto queue_stopped;
4917 	}
4918 
4919 	if (bscv_pause_event_daemon(ssp) == BSCV_FAILURE) {
4920 		BSCV_TRACE(ssp, 'Q', "bscv_prog_stop_lom",
4921 		    "failed to pause event daemon thread");
4922 		return (EAGAIN);
4923 	}
4924 
4925 	bscv_enter(ssp);
4926 
4927 	ssp->programming = B_TRUE;
4928 
4929 	bscv_exit(ssp);
4930 
4931 queue_stopped:
4932 
4933 	ssp->prog_index = 0;
4934 	ssp->image2_processing = B_FALSE;
4935 
4936 	return (0);
4937 }
4938 
4939 static int
4940 bscv_prog_start_lom(bscv_soft_state_t *ssp)
4941 {
4942 	int res = 0;
4943 
4944 	if (!ssp->programming) {
4945 		/* Not programming so this is not a valid command */
4946 		return (EINVAL);
4947 	}
4948 
4949 	if (ssp->image != NULL) {
4950 		kmem_free((void *)ssp->image, BSC_IMAGE_MAX_SIZE);
4951 		ssp->image = NULL;
4952 	}
4953 
4954 	/*
4955 	 * OK we are out of reset now so:
4956 	 * Probe the firmware and set everything up.
4957 	 */
4958 
4959 	bscv_enter(ssp);
4960 
4961 	/* Explicit clear fault because things may have been mended now */
4962 	bscv_clear_fault(ssp);
4963 
4964 	if (ssp->loader_running) {
4965 		cmn_err(CE_WARN, "Firmware upgrade failed to exit loader - "
4966 		    "performing forced exit");
4967 		/* Must try to restart the lom here. */
4968 		/* Ensure prog mode entry to enable PRGMODE_OFF */
4969 		bscv_put8(ssp, chan_prog,
4970 		    BSCVA(EBUS_CMD_SPACE_PROGRAM, EBUS_PROGRAM_PCSR),
4971 		    EBUS_PROGRAM_PCR_PRGMODE_ON);
4972 		bscv_put8(ssp, chan_prog,
4973 		    BSCVA(EBUS_CMD_SPACE_PROGRAM, EBUS_PROGRAM_PCSR),
4974 		    EBUS_PROGRAM_PCR_PRGMODE_OFF);
4975 		ssp->loader_running = B_FALSE;
4976 		/* give the lom chance to recover */
4977 		delay(drv_usectohz(5000000));	/* 5 seconds */
4978 	}
4979 
4980 	ssp->prog_mode_only = B_FALSE;
4981 	ssp->programming = B_FALSE;
4982 
4983 	if (bscv_attach_common(ssp) == DDI_FAILURE) {
4984 		ssp->prog_mode_only = B_TRUE;
4985 		res = EIO;
4986 	}
4987 
4988 	bscv_exit(ssp);
4989 
4990 	if (!ssp->prog_mode_only) {
4991 		/*
4992 		 * Start the event thread after the queue has started
4993 		 *
4994 		 * Not sure if this is entirely correct because
4995 		 * the other code at the end of bscv_attach()
4996 		 * does not get run here.
4997 		 */
4998 		bscv_start_event_daemon(ssp);
4999 		bscv_resume_event_daemon(ssp);
5000 	}
5001 
5002 	return (res);
5003 }
5004 
5005 
5006 /*
5007  * *********************************************************************
5008  * Attach processing
5009  * *********************************************************************
5010  */
5011 
5012 /*
5013  * function	- bscv_attach_common
5014  * description	- this routine co-ordinates the initialisation of the
5015  *		  driver both at attach time and after firmware programming.
5016  * sequence	- bscv_setup_capability - read LOMlite2 capabilities
5017  *		  bscv_probe_check - test comms and setup register cache
5018  *		  bscv_setup_hostname - sync stored name in lom with nodename.
5019  *		  bscv_setup_static_info - read device names etc.
5020  *		  bscv_setup_events - start event daemon etc.
5021  *
5022  * inputs	- device information structure, DDI_ATTACH command
5023  * outputs	- DDI_SUCCESS or DDI_FAILURE
5024  */
5025 
5026 static int
5027 bscv_attach_common(bscv_soft_state_t *ssp)
5028 {
5029 	ASSERT(bscv_held(ssp));
5030 
5031 	BSCV_TRACE(ssp, 'A', "bscv_attach_common:", "");
5032 
5033 	/*
5034 	 * Set the threshold for reporting messages to the console to
5035 	 * Warnings or higher.
5036 	 */
5037 	ssp->reporting_level = 2;
5038 
5039 	/*
5040 	 * When the system is not running the Operating System, make
5041 	 * the microcontroller print event messages straight onto the
5042 	 * console.
5043 	 */
5044 	ssp->serial_reporting = LOM_SER_EVENTS_DEF;
5045 
5046 	/* Setup capabilities */
5047 	bscv_setup_capability(ssp);
5048 
5049 	if (bscv_probe_check(ssp) == DDI_FAILURE) {
5050 		cmn_err(CE_WARN, "BSC chip not responding");
5051 		/*
5052 		 * We want lom -G to talk to this driver upon broken firmware
5053 		 * so we prematurely return success here.
5054 		 */
5055 		return (DDI_SUCCESS);
5056 	}
5057 
5058 	bscv_setup_hostname(ssp);
5059 	bscv_setup_static_info(ssp);
5060 	bscv_setup_events(ssp);
5061 
5062 #if defined(__i386) || defined(__amd64)
5063 	bscv_inform_bsc(ssp, BSC_INFORM_ONLINE);
5064 #endif /* __i386 || __amd64 */
5065 	/*
5066 	 * Watchdog configuration and CPU signatures are sent asynchronously
5067 	 * with respect to attach so only inform the BSC if we've already
5068 	 * sent the data in the past.
5069 	 */
5070 
5071 	if (ssp->progress & BSCV_WDOG_CFG)
5072 		bscv_setup_watchdog(ssp);
5073 
5074 #ifdef __sparc
5075 	if (ssp->progress & BSCV_SIG_SENT)
5076 		bscv_write_sig(ssp, ssp->last_sig);
5077 #endif /* __sparc */
5078 
5079 	return (DDI_SUCCESS);
5080 }
5081 
5082 /*
5083  * function	- bscv_cleanup
5084  * description	- routine that does the necessary tidying up if the attach
5085  *		  request fails or the driver is to be detached.
5086  *		  If the event thread has been started we may fail to
5087  *		  stop it (because it is busy) so we fail the cleanup
5088  *		  and hence the detach. All other calls to bscv_cleanup
5089  *		  are done before the event daemon is started.
5090  * inputs	- soft state structure address.
5091  * outputs	- DDI_SUCCESS or DDI_FAILURE.
5092  */
5093 
5094 static int
5095 bscv_cleanup(bscv_soft_state_t *ssp)
5096 {
5097 	int	instance;
5098 	uint8_t bits2set;
5099 	uint8_t bits2clear;
5100 
5101 	instance = ssp->instance;
5102 
5103 	if (ssp->progress & BSCV_LOCKS) {
5104 		bscv_enter(ssp);
5105 	}
5106 
5107 	if (ssp->progress & BSCV_THREAD) {
5108 		if (bscv_stop_event_daemon(ssp) == DDI_FAILURE) {
5109 			/* Fail the cleanup - may be able to cleanup later */
5110 			if (ssp->progress & BSCV_LOCKS) {
5111 				bscv_exit(ssp);
5112 			}
5113 			return (DDI_FAILURE);
5114 		}
5115 	}
5116 
5117 	if (ssp->progress & BSCV_NODES) {
5118 		ddi_remove_minor_node(ssp->dip, NULL);
5119 	}
5120 
5121 	if (ssp->progress & BSCV_MAPPED_REGS) {
5122 		/*
5123 		 * switch back on serial event reporting - cover all configs.
5124 		 */
5125 		bits2set = 0;
5126 		bits2clear = 0;
5127 		if (ssp->serial_reporting == LOM_SER_EVENTS_ON) {
5128 			bits2clear |= EBUS_ALARM_NOEVENTS;
5129 		} else if (ssp->serial_reporting == LOM_SER_EVENTS_OFF) {
5130 			bits2set |= EBUS_ALARM_NOEVENTS;
5131 		} else if (ssp->serial_reporting == LOM_SER_EVENTS_DEF) {
5132 			bits2clear |= EBUS_ALARM_NOEVENTS;
5133 		}
5134 		bscv_setclear8_volatile(ssp, chan_general, EBUS_IDX_ALARM,
5135 		    bits2set, bits2clear);
5136 
5137 		/*
5138 		 * disable the reset function if we have enabled
5139 		 * it. We don't want any nasty surprises like system
5140 		 * rebooting unexpectedly.  If we timeout on the busy
5141 		 * flag we just have to carry on.
5142 		 */
5143 
5144 		BSCV_TRACE(ssp, 'W', "bscv_cleanup",
5145 		    "bscv_cleanup - disable wdog");
5146 		if (bscv_get8_cached(ssp, EBUS_IDX_WDOG_CTRL) &
5147 		    EBUS_WDOG_ENABLE) {
5148 			bscv_setclear8(ssp, chan_general, EBUS_IDX_WDOG_CTRL,
5149 			    0, EBUS_WDOG_RST | EBUS_WDOG_ENABLE);
5150 		}
5151 	}
5152 
5153 	/*
5154 	 * unmap registers
5155 	 */
5156 
5157 	if (ssp->progress & BSCV_MAPPED_REGS) {
5158 		bscv_unmap_regs(ssp);
5159 	}
5160 
5161 	/*
5162 	 * release any memory allocated for mutexes and condition
5163 	 * variables before deallocating the structures containing them
5164 	 */
5165 
5166 	if (ssp->progress & BSCV_LOCKS) {
5167 		bscv_exit(ssp);
5168 		cv_destroy(&ssp->task_cv);
5169 		cv_destroy(&ssp->task_evnt_cv);
5170 		mutex_destroy(&ssp->task_mu);
5171 		mutex_destroy(&ssp->prog_mu);
5172 		mutex_destroy(&ssp->cmd_mutex);
5173 	}
5174 
5175 	if (ssp->image != NULL) {
5176 		kmem_free((void *)ssp->image, BSC_IMAGE_MAX_SIZE);
5177 	}
5178 
5179 #if defined(__i386) || defined(__amd64)
5180 	bscv_watchdog_cyclic_remove(ssp);
5181 #endif /* __i386 || __amd64 */
5182 	ddi_soft_state_free(bscv_statep, instance);
5183 
5184 	return (DDI_SUCCESS);
5185 }
5186 
5187 /*
5188  * function	- bscv_setup_capability
5189  * description	- probe the lom find what capabilities are present for
5190  *		  us to use.
5191  * inputs	- soft state ptr
5192  * outputs	- returns DDI_SUCCESS or DDI_FAILURE
5193  */
5194 static void bscv_setup_capability(bscv_soft_state_t *ssp)
5195 {
5196 	ASSERT(bscv_held(ssp));
5197 
5198 	if (ssp->prog_mode_only) {
5199 		/* Turn off all capabilities */
5200 		ssp->cap0 = 0;
5201 		ssp->cap1 = 0;
5202 		ssp->cap2 = 0;
5203 		return;
5204 	}
5205 
5206 	ssp->cap0 = bscv_get8(ssp, chan_general, EBUS_IDX_CAP0);
5207 	ssp->cap1 = bscv_get8(ssp, chan_general, EBUS_IDX_CAP1);
5208 	ssp->cap2 = bscv_get8(ssp, chan_general, EBUS_IDX_CAP2);
5209 	if (!bscv_faulty(ssp)) {
5210 		BSCV_TRACE(ssp, 'A', "bscv_setup_capability",
5211 		    "Capability flags cap0=0x%x cap1=0x%x, cap2=0x%x",
5212 		    ssp->cap0, ssp->cap1, ssp->cap2);
5213 	} else {
5214 		cmn_err(CE_WARN, "!Could not read capability flags");
5215 		ssp->cap0 = 0; ssp->cap1 = 0; ssp->cap2 = 0;
5216 	}
5217 }
5218 
5219 /*
5220  * function	- bscv_probe_check
5221  * description	- probe the lom to check for correct operation
5222  *		  has a side effect of setting up the cached registers and
5223  *		  updates ssp->prog_mode_only.
5224  * inputs	- soft state ptr
5225  * outputs	- returns DDI_SUCCESS or DDI_FAILURE
5226  */
5227 
5228 static int bscv_probe_check(bscv_soft_state_t *ssp)
5229 {
5230 	int i;
5231 	uint8_t probeval;
5232 
5233 	ASSERT(bscv_held(ssp));
5234 
5235 	BSCV_TRACE(ssp, 'A', "bscv_probe_check", "");
5236 
5237 	if (!ssp->prog_mode_only) {
5238 		/*
5239 		 * Make sure probe location is OK so that we are
5240 		 * in sync.
5241 		 * We want to make sure that this is not faulty so we
5242 		 * do a bscv_clear_fault to clear any existing
5243 		 * fault records down.
5244 		 */
5245 		bscv_clear_fault(ssp);
5246 		probeval = bscv_get8(ssp, chan_general, EBUS_IDX_PROBEAA);
5247 		if (bscv_faulty(ssp)) {
5248 			ssp->prog_mode_only = B_TRUE;
5249 		} else if (probeval != 0xAA) {
5250 			BSCV_TRACE(ssp, 'A', "bscv_probe_check",
5251 			    "LOMlite out of sync");
5252 
5253 			/*
5254 			 * It may be that the LOMlite was out of
5255 			 * sync so lets try the read again.
5256 			 */
5257 			probeval = bscv_get8(ssp, chan_general,
5258 			    EBUS_IDX_PROBEAA);
5259 			if (bscv_faulty(ssp)) {
5260 				BSCV_TRACE(ssp, 'A', "bscv_probe_check",
5261 				    "Init readAA1 failed");
5262 				ssp->prog_mode_only = B_TRUE;
5263 			} else if (probeval != 0xAA) {
5264 				/*
5265 				 * OK that is twice we are out so I
5266 				 * guess the LOMlite is in trouble
5267 				 */
5268 				BSCV_TRACE(ssp, 'A', "bscv_probe_check",
5269 				    "Init readAA probe failed - got 0x%x",
5270 				    probeval);
5271 				ssp->prog_mode_only = B_TRUE;
5272 			}
5273 		}
5274 	}
5275 
5276 	/*
5277 	 * Read in all page zero lom registers.
5278 	 * Read state change 1st so we dont miss anything and clear it.
5279 	 * Note: we discard the values because we rely on bscv_get8 to
5280 	 * setup the cache of register values.
5281 	 */
5282 
5283 	if (!ssp->prog_mode_only) {
5284 		(void) bscv_get8(ssp, chan_general, EBUS_IDX_STATE_CHNG);
5285 		if (bscv_faulty(ssp)) {
5286 			BSCV_TRACE(ssp, 'A', "bscv_probe_check",
5287 			    "Read of state change register failed");
5288 			ssp->prog_mode_only = B_TRUE;
5289 		}
5290 	}
5291 
5292 	if (!ssp->prog_mode_only) {
5293 		for (i = 1; i < 0x80; i++) {
5294 			switch (i) {
5295 			case EBUS_IDX_STATE_CHNG:
5296 			case EBUS_IDX_CMD_RES:
5297 			case EBUS_IDX_HNAME_CHAR:
5298 				/*
5299 				 * Should not read these - they have side
5300 				 * effects.
5301 				 */
5302 				break;
5303 			default:
5304 				(void) bscv_get8(ssp, chan_general, i);
5305 				break;
5306 			}
5307 			if (bscv_faulty(ssp)) {
5308 				BSCV_TRACE(ssp, 'A', "bscv_probe_check",
5309 				    "Initial read or register %2x failed", i);
5310 				ssp->prog_mode_only = B_TRUE;
5311 				/* Might as well give up now! */
5312 				break;
5313 			}
5314 		}
5315 	}
5316 
5317 	/*
5318 	 * Check the probe keys so we know the lom is OK
5319 	 */
5320 
5321 	if (!ssp->prog_mode_only) {
5322 		if ((bscv_get8_cached(ssp, EBUS_IDX_PROBE55) != 0x55) ||
5323 		    (bscv_get8_cached(ssp, EBUS_IDX_PROBEAA) != 0xAA)) {
5324 
5325 			BSCV_TRACE(ssp, 'A', "bscv_probe_check",
5326 			    "LOMlite Probe failed");
5327 			for (i = 0; i < 0x8; i++) {
5328 				BSCV_TRACE(ssp, 'A', "bscv_probe_check",
5329 				    "%2x %2x %2x %2x %2x %2x %2x %2x %2x "
5330 				    "%2x %2x %2x %2x %2x %2x %2x %2x %2x",
5331 				    bscv_get8_cached(ssp, i),
5332 				    bscv_get8_cached(ssp, i + 1),
5333 				    bscv_get8_cached(ssp, i + 2),
5334 				    bscv_get8_cached(ssp, i + 3),
5335 				    bscv_get8_cached(ssp, i + 4),
5336 				    bscv_get8_cached(ssp, i + 5),
5337 				    bscv_get8_cached(ssp, i + 6),
5338 				    bscv_get8_cached(ssp, i + 7),
5339 				    bscv_get8_cached(ssp, i + 8),
5340 				    bscv_get8_cached(ssp, i + 9),
5341 				    bscv_get8_cached(ssp, i + 10),
5342 				    bscv_get8_cached(ssp, i + 11),
5343 				    bscv_get8_cached(ssp, i + 12),
5344 				    bscv_get8_cached(ssp, i + 13),
5345 				    bscv_get8_cached(ssp, i + 14),
5346 				    bscv_get8_cached(ssp, i + 15));
5347 			}
5348 			ssp->prog_mode_only = B_TRUE;
5349 		}
5350 	}
5351 
5352 	return ((ssp->prog_mode_only == B_FALSE) ? DDI_SUCCESS : DDI_FAILURE);
5353 }
5354 
5355 #ifdef __sparc
5356 /*
5357  * function	- bscv_idi_set
5358  * description	- bscv inter driver interface set function
5359  * inputs	- structure which defines type of service required and data
5360  * ouputs	- none
5361  *
5362  * This is the Entry Point function for the platmod driver. It works out which
5363  * X Bus channel ought to deliver the service requested.
5364  */
5365 void
5366 bscv_idi_set(struct bscv_idi_info info)
5367 {
5368 	struct bscv_idi_callout *tbl;
5369 	boolean_t retval;
5370 
5371 	ASSERT(bscv_idi_mgr.magic == BSCV_IDI_CALLOUT_MAGIC);
5372 
5373 	if (bscv_idi_mgr.tbl == NULL) {
5374 		if (bscv_idi_err())
5375 			cmn_err(CE_WARN, "!bscv_idi_set : cannot find "
5376 			    "bscv_callout_table");
5377 		return;
5378 	} else if (bscv_idi_mgr.valid_inst == (uint32_t)~0) {
5379 		if (bscv_idi_err())
5380 			/*
5381 			 * This error message can appear in the context of
5382 			 * another driver, say platmod or todblade.  We want
5383 			 * to clearly indicate the culprit driver so put in
5384 			 * the driver name.
5385 			 */
5386 			cmn_err(CE_WARN, "!bscv_idi_set : no valid "
5387 			    "driver instance of "
5388 			    MYNAME);
5389 		return;
5390 	}
5391 
5392 	tbl = bscv_idi_mgr.tbl;
5393 
5394 	while (tbl->type != BSCV_IDI_NULL) {
5395 		if (tbl->type == info.type) {
5396 			/*
5397 			 * We service the request with a valid instance number
5398 			 * for the driver.
5399 			 */
5400 			retval = ((tbl->fn) (info));
5401 
5402 			/*
5403 			 * If the request was serviced, clear any accumulated
5404 			 * error counters so future warnings will be reported if
5405 			 * seen.
5406 			 */
5407 			if (retval == B_TRUE)
5408 				bscv_idi_clear_err();
5409 			return;
5410 		} else {
5411 			tbl++;
5412 		}
5413 	}
5414 
5415 	if (bscv_idi_err())
5416 		cmn_err(CE_WARN, "!bscv_idi_set : cannot match info.type %d",
5417 		    info.type);
5418 }
5419 
5420 /*
5421  * function     - bscv_nodename_set
5422  * description  - notify the event thread that a nodename change has occurred.
5423  * inputs       - data from client driver
5424  * outputs	- none.
5425  * side-effects - the event thread will schedule an update to the lom firmware.
5426  */
5427 /*ARGSUSED*/
5428 static boolean_t
5429 bscv_nodename_set(struct bscv_idi_info info)
5430 {
5431 	bscv_soft_state_t *ssp;
5432 
5433 	ssp = ddi_get_soft_state(bscv_statep, bscv_idi_mgr.valid_inst);
5434 
5435 	if (ssp == NULL) {
5436 		if (bscv_idi_err())
5437 			cmn_err(CE_WARN, "!blade_nodename_set: cannot get ssp");
5438 		return (B_FALSE);
5439 	}
5440 
5441 	/* Get a lock on the SSP, notify our change, then exit */
5442 	mutex_enter(&ssp->task_mu);
5443 	ssp->nodename_change = B_TRUE;
5444 	cv_signal(&ssp->task_cv);
5445 	mutex_exit(&ssp->task_mu);
5446 
5447 	return (B_TRUE);
5448 }
5449 
5450 /*
5451  * function	- bscv_sig_set
5452  * description	- write a signature
5453  * inputs	- data from client driver
5454  * outputs	- none.
5455  */
5456 static boolean_t
5457 bscv_sig_set(struct bscv_idi_info info)
5458 {
5459 	bscv_soft_state_t *ssp;
5460 	bscv_sig_t sig;
5461 
5462 	ssp = ddi_get_soft_state(bscv_statep, bscv_idi_mgr.valid_inst);
5463 
5464 	if (ssp == NULL) {
5465 		if (bscv_idi_err())
5466 			cmn_err(CE_WARN, "!blade_nodename_set: cannot get ssp");
5467 		return (B_FALSE);
5468 	}
5469 
5470 	/* Service the request */
5471 	bcopy(info.data, &sig, sizeof (sig));
5472 	bscv_enter(ssp);
5473 	bscv_write_sig(ssp, sig);
5474 	bscv_exit(ssp);
5475 
5476 	return (B_TRUE);
5477 }
5478 #endif /* __sparc */
5479 
5480 static void
5481 bscv_wdog_do_pat(bscv_soft_state_t *ssp)
5482 {
5483 	uint8_t pat;
5484 
5485 	/*
5486 	 * The value of the dog pat is a sequence number which wraps around,
5487 	 * bounded by BSCV_WDOG_PAT_SEQ_MASK.
5488 	 */
5489 	pat = ssp->pat_seq++;
5490 	pat &= EBUS_WDOG_NB_PAT_SEQ_MASK;
5491 
5492 	/* Set top nibble to indicate a pat */
5493 	pat |= EBUS_WDOG_NB_PAT;
5494 
5495 	/*
5496 	 * Now pat the dog.  This exercises a special protocol in the
5497 	 * bus nexus that offers : non-blocking IO, and timely delivery,
5498 	 * callable from high-level interrupt context.  The requirement
5499 	 * on us is that the channel is not shared for any other use.
5500 	 * This means for chan_wdogpat, nothing may use channel[chan].regs
5501 	 * or channel.[chan].handle.
5502 	 */
5503 
5504 	ddi_put8(ssp->channel[chan_wdogpat].handle,
5505 	    ssp->channel[chan_wdogpat].regs, pat);
5506 
5507 	BSCV_TRACE(ssp, 'W', "bscv_wdog_pat", "patted the dog with seq %d",
5508 	    pat);
5509 }
5510 
5511 #ifdef __sparc
5512 /*
5513  * function	- bscv_wdog_pat
5514  * description	- pat the watchdog
5515  * inputs	- data from client driver
5516  * outputs	- none.
5517  */
5518 /*ARGSUSED*/
5519 static boolean_t
5520 bscv_wdog_pat(struct bscv_idi_info info)
5521 {
5522 	/*
5523 	 * This function remembers if it has ever been called with the
5524 	 * configure option set.
5525 	 */
5526 	bscv_soft_state_t *ssp;
5527 
5528 	ssp = ddi_get_soft_state(bscv_statep, bscv_idi_mgr.valid_inst);
5529 
5530 	if (ssp == NULL) {
5531 		if (bscv_idi_err())
5532 			cmn_err(CE_WARN, "!bscv_wdog_pat: cannot get ssp");
5533 		return (B_FALSE);
5534 	} else if (ssp->nchannels == 0) {
5535 		/* Didn't manage to map handles so ddi_{get,put}* broken */
5536 		if (bscv_idi_err())
5537 			cmn_err(CE_WARN, "!bscv_wdog_pat: handle not mapped");
5538 		return (B_FALSE);
5539 	}
5540 
5541 	bscv_wdog_do_pat(ssp);
5542 	return (B_TRUE);
5543 }
5544 
5545 /*
5546  * function	- bscv_wdog_cfg
5547  * description	- configure the watchdog
5548  * inputs	- data from client driver
5549  * outputs	- none.
5550  */
5551 static boolean_t
5552 bscv_wdog_cfg(struct bscv_idi_info info)
5553 {
5554 	bscv_soft_state_t *ssp;
5555 
5556 	ssp = ddi_get_soft_state(bscv_statep, bscv_idi_mgr.valid_inst);
5557 
5558 	if (ssp == NULL) {
5559 		if (bscv_idi_err())
5560 			cmn_err(CE_WARN, "!bscv_wdog_cfg: cannot get ssp");
5561 		return (B_FALSE);
5562 	} else if (ssp->nchannels == 0) {
5563 		/* Didn't manage to map handles so ddi_{get,put}* broken */
5564 		if (bscv_idi_err())
5565 			cmn_err(CE_WARN, "!bscv_wdog_cfg: handle not mapped");
5566 		return (B_FALSE);
5567 	}
5568 
5569 	if (sizeof (bscv_wdog_t) != info.size) {
5570 		BSCV_TRACE(ssp, 'W', "bscv_wdog_set", "data passed in is size"
5571 		    " %d instead of %d", info.size,
5572 		    sizeof (bscv_wdog_t));
5573 		return (B_FALSE);
5574 	}
5575 
5576 	BSCV_TRACE(ssp, 'W', "bscv_wdog_cfg", "enable_wdog %s, "
5577 	    "wdog_timeout_s %d, reset_system_on_timeout %s",
5578 	    ((bscv_wdog_t *)info.data)->enable_wdog ? "enabled" : "disabled",
5579 	    ((bscv_wdog_t *)info.data)->wdog_timeout_s,
5580 	    ((bscv_wdog_t *)info.data)->reset_system_on_timeout ? "yes" : "no");
5581 	bscv_write_wdog_cfg(ssp,
5582 	    ((bscv_wdog_t *)info.data)->wdog_timeout_s,
5583 	    ((bscv_wdog_t *)info.data)->enable_wdog,
5584 	    ((bscv_wdog_t *)info.data)->reset_system_on_timeout);
5585 	return (B_TRUE);
5586 }
5587 #endif /* __sparc */
5588 
5589 static void
5590 bscv_write_wdog_cfg(bscv_soft_state_t *ssp,
5591     uint_t wdog_timeout_s,
5592     boolean_t enable_wdog,
5593     uint8_t reset_system_on_timeout)
5594 {
5595 	uint8_t cfg = EBUS_WDOG_NB_CFG;
5596 
5597 	/*
5598 	 * Configure the timeout value (1 to 127 seconds).
5599 	 * Note that a policy is implemented at the bsc/ssp which bounds
5600 	 * the value further. The bounding here is to fit the timeout value
5601 	 * into the 7 bits the bsc uses.
5602 	 */
5603 	if (wdog_timeout_s < 1)
5604 		ssp->watchdog_timeout = 1;
5605 	else if (wdog_timeout_s > 127)
5606 		ssp->watchdog_timeout = 127;
5607 	else
5608 		ssp->watchdog_timeout = wdog_timeout_s;
5609 
5610 	/*
5611 	 * Configure the watchdog on or off.
5612 	 */
5613 	if (enable_wdog)
5614 		cfg |= EBUS_WDOG_NB_CFG_ENB;
5615 	else
5616 		cfg &= ~EBUS_WDOG_NB_CFG_ENB;
5617 
5618 	/*
5619 	 * Configure whether the microcontroller should reset the system when
5620 	 * the watchdog expires.
5621 	 */
5622 	ssp->watchdog_reset_on_timeout = reset_system_on_timeout;
5623 
5624 	ddi_put8(ssp->channel[chan_wdogpat].handle,
5625 	    ssp->channel[chan_wdogpat].regs, cfg);
5626 
5627 	/* have the event daemon set the timeout value and whether to reset */
5628 	ssp->watchdog_change = B_TRUE;
5629 
5630 	BSCV_TRACE(ssp, 'W', "bscv_wdog_cfg",
5631 	    "configured the dog with cfg 0x%x", cfg);
5632 }
5633 
5634 /*
5635  * function	- bscv_setup_watchdog
5636  * description	- setup the  bsc watchdog
5637  * inputs	- soft state ptr
5638  * outputs	-
5639  */
5640 static void bscv_setup_watchdog(bscv_soft_state_t *ssp)
5641 {
5642 	uint8_t set = 0;
5643 	uint8_t clear = 0;
5644 #ifdef __sparc
5645 	extern int watchdog_activated;
5646 #endif /* __sparc */
5647 
5648 	ASSERT(bscv_held(ssp));
5649 
5650 	/* Set the timeout */
5651 	bscv_put8(ssp, chan_general,
5652 	    EBUS_IDX_WDOG_TIME, ssp->watchdog_timeout);
5653 
5654 	/* Set whether to reset the system on timeout */
5655 	if (ssp->watchdog_reset_on_timeout) {
5656 		set |= EBUS_WDOG_RST;
5657 	} else {
5658 		clear |= EBUS_WDOG_RST;
5659 	}
5660 
5661 	if (watchdog_activated) {
5662 		set |= EBUS_WDOG_ENABLE;
5663 	} else {
5664 		clear |= EBUS_WDOG_ENABLE;
5665 	}
5666 
5667 	/* Set other host defaults */
5668 	clear |= (EBUS_WDOG_BREAK_DISABLE | EBUS_WDOG_AL3_FANPSU
5669 	    | EBUS_WDOG_AL3_WDOG);
5670 
5671 	bscv_setclear8_volatile(ssp, chan_general, EBUS_IDX_WDOG_CTRL,
5672 	    set, clear);
5673 
5674 #if defined(__i386) || defined(__amd64)
5675 	/* start the cyclic based watchdog patter */
5676 	bscv_watchdog_cyclic_add(ssp);
5677 #endif /* __i386 || __amd64 */
5678 	ssp->progress |= BSCV_WDOG_CFG;
5679 }
5680 
5681 
5682 /*
5683  * function	- bscv_setup_hostname
5684  * description	- setup the lom hostname if different from the nodename
5685  * inputs	- soft state ptr
5686  * outputs	- none
5687  */
5688 
5689 static void bscv_setup_hostname(bscv_soft_state_t *ssp)
5690 {
5691 	char	host_nodename[128];
5692 	char	lom_nodename[128];
5693 	size_t	hostlen;
5694 	size_t	nodelen;
5695 
5696 	ASSERT(bscv_held(ssp));
5697 
5698 	/*
5699 	 * Check machine label is the same as the
5700 	 * system nodename.
5701 	 */
5702 	(void) strncpy(host_nodename, utsname.nodename,
5703 	    sizeof (host_nodename));
5704 
5705 	/* read in lom hostname */
5706 	bscv_read_hostname(ssp, lom_nodename);
5707 
5708 	/* Enforce null termination */
5709 	host_nodename[sizeof (host_nodename) - 1] = '\0';
5710 	lom_nodename[sizeof (lom_nodename) - 1] = '\0';
5711 
5712 	hostlen = (size_t)bscv_get8(ssp, chan_general, EBUS_IDX_HNAME_LENGTH);
5713 	nodelen = (size_t)strlen(host_nodename);
5714 	if ((nodelen > 0) &&
5715 	    ((hostlen != nodelen) || (strcmp((const char *)&lom_nodename,
5716 	    (const char *)&host_nodename)) ||
5717 	    (hostlen == 0))) {
5718 		BSCV_TRACE(ssp, 'A', "bscv_setup_hostname",
5719 		    "nodename(%s,%d) != bsc label(%s,%d)",
5720 		    host_nodename, nodelen, lom_nodename, hostlen);
5721 
5722 		/* Write new label into LOM EEPROM */
5723 		bscv_write_hostname(ssp,
5724 		    host_nodename,
5725 		    (uint8_t)strlen(host_nodename));
5726 	}
5727 
5728 	ssp->progress |= BSCV_HOSTNAME_DONE;
5729 }
5730 
5731 /*
5732  * function	- bscv_read_hostname
5733  * description	- read the current hostname from the lom
5734  * inputs	- soft state pointer and buffer to store the hostname in.
5735  * outputs	- none
5736  */
5737 
5738 static void
5739 bscv_read_hostname(bscv_soft_state_t *ssp, char *lom_nodename)
5740 {
5741 	int num_failures;
5742 	boolean_t needretry;
5743 	int length;
5744 	int i;
5745 
5746 	ASSERT(bscv_held(ssp));
5747 
5748 	/*
5749 	 * We have a special failure case here because a retry of a read
5750 	 * causes data to be lost. Thus we handle the retries ourselves
5751 	 * and are also responsible for detemining if the lom is faulty
5752 	 */
5753 	for (num_failures = 0;
5754 	    num_failures < BSC_FAILURE_RETRY_LIMIT;
5755 	    num_failures++) {
5756 		bscv_clear_fault(ssp);
5757 		length = bscv_get8(ssp, chan_general, EBUS_IDX_HNAME_LENGTH);
5758 		if (bscv_faulty(ssp)) {
5759 			needretry = 1;
5760 		} else {
5761 			needretry = 0;
5762 			for (i = 0; i < length; i++) {
5763 				lom_nodename[i] = bscv_get8_once(ssp,
5764 				    chan_general, EBUS_IDX_HNAME_CHAR);
5765 				/* Retry on any error */
5766 				if (bscv_retcode(ssp) != 0) {
5767 					needretry = 1;
5768 					break;
5769 				}
5770 			}
5771 			/* null terminate for strcmp later */
5772 			lom_nodename[length] = '\0';
5773 		}
5774 		if (!needretry) {
5775 			break;
5776 		}
5777 		/* Force the nodename to be empty */
5778 		lom_nodename[0] = '\0';
5779 	}
5780 
5781 	if (needretry) {
5782 		/* Failure - we ran out of retries */
5783 		cmn_err(CE_WARN,
5784 		    "bscv_read_hostname: retried %d times, giving up",
5785 		    num_failures);
5786 		ssp->had_fault = B_TRUE;
5787 	} else if (num_failures > 0) {
5788 		BSCV_TRACE(ssp, 'R', "bscv_read_hostname",
5789 		    "retried %d times, succeeded", num_failures);
5790 	}
5791 }
5792 
5793 /*
5794  * function	- bscv_write_hostname
5795  * description	- write a new hostname to the lom
5796  * inputs	- soft state pointer, pointer to new name, name length
5797  * outputs	- none
5798  */
5799 static void
5800 bscv_write_hostname(bscv_soft_state_t *ssp,
5801     char *host_nodename, uint8_t length)
5802 {
5803 	int num_failures;
5804 	boolean_t needretry;
5805 	int i;
5806 
5807 	ASSERT(bscv_held(ssp));
5808 
5809 	/*
5810 	 * We have a special failure case here because a retry of a read
5811 	 * causes data to be lost. Thus we handle the retries ourselves
5812 	 * and are also responsible for detemining if the lom is faulty
5813 	 */
5814 	for (num_failures = 0;
5815 	    num_failures < BSC_FAILURE_RETRY_LIMIT;
5816 	    num_failures++) {
5817 		bscv_clear_fault(ssp);
5818 		bscv_put8(ssp, chan_general, EBUS_IDX_HNAME_LENGTH, length);
5819 		if (bscv_faulty(ssp)) {
5820 			needretry = 1;
5821 		} else {
5822 			needretry = 0;
5823 			for (i = 0; i < length; i++) {
5824 				bscv_put8_once(ssp, chan_general,
5825 				    EBUS_IDX_HNAME_CHAR, host_nodename[i]);
5826 				/* Retry on any error */
5827 				if (bscv_retcode(ssp) != 0) {
5828 					needretry = 1;
5829 					break;
5830 				}
5831 			}
5832 		}
5833 		if (!needretry) {
5834 			break;
5835 		}
5836 	}
5837 
5838 	if (needretry) {
5839 		/* Failure - we ran out of retries */
5840 		cmn_err(CE_WARN,
5841 		    "bscv_write_hostname: retried %d times, giving up",
5842 		    num_failures);
5843 		ssp->had_fault = B_TRUE;
5844 	} else if (num_failures > 0) {
5845 		BSCV_TRACE(ssp, 'R', "bscv_write_hostname",
5846 		    "retried %d times, succeeded", num_failures);
5847 	}
5848 }
5849 
5850 /*
5851  * function	- bscv_setup_static_info
5852  * description	- read in static information from the lom at attach time.
5853  * inputs	- soft state ptr
5854  * outputs	- none
5855  */
5856 
5857 static void
5858 bscv_setup_static_info(bscv_soft_state_t *ssp)
5859 {
5860 	uint8_t	addr_space_ptr;
5861 	uint16_t mask;
5862 	uint8_t fanspeed;
5863 	int oldtemps[MAX_TEMPS];
5864 	int8_t temp;
5865 	int i;
5866 
5867 	ASSERT(bscv_held(ssp));
5868 
5869 	/*
5870 	 * Finally read in some static info like device names,
5871 	 * shutdown enabled, etc before the queue starts.
5872 	 */
5873 
5874 	/*
5875 	 * To get the volts static info we need address space 2
5876 	 */
5877 	bzero(&ssp->volts, sizeof (lom_volts_t));
5878 	ssp->volts.num = EBUS_CONFIG2_NSUPPLY_DEC(
5879 	    bscv_get8(ssp, chan_general, EBUS_IDX_CONFIG2));
5880 	if (ssp->volts.num > MAX_VOLTS) {
5881 		cmn_err(CE_WARN,
5882 		    "lom: firmware reported too many voltage lines. ");
5883 		cmn_err(CE_CONT, "Reported %d, maximum is %d",
5884 		    ssp->volts.num, MAX_VOLTS);
5885 		ssp->volts.num = MAX_VOLTS;
5886 	}
5887 
5888 	BSCV_TRACE(ssp, 'A', "bscv_setup_static_info",
5889 	    "num volts %d", ssp->volts.num);
5890 	(void) bscv_read_env_name(ssp,
5891 	    EBUS_CMD_SPACE2,
5892 	    EBUS_IDX2_SUPPLY_NAME_START,
5893 	    EBUS_IDX2_SUPPLY_NAME_END,
5894 	    ssp->volts.name,
5895 	    ssp->volts.num);
5896 
5897 	mask = bscv_get8(ssp, chan_general, BSCVA(EBUS_CMD_SPACE2,
5898 	    EBUS_IDX2_SUPPLY_FATAL_MASK1)) << 8;
5899 	mask |= bscv_get8(ssp, chan_general, BSCVA(EBUS_CMD_SPACE2,
5900 	    EBUS_IDX2_SUPPLY_FATAL_MASK2));
5901 
5902 	for (i = 0; i < ssp->volts.num; i++) {
5903 		ssp->volts.shutdown_enabled[i] =
5904 		    (((mask >> i) & 1) == 0) ? 0 : 1;
5905 	}
5906 
5907 	/*
5908 	 * Get the temperature static info and populate initial temperatures.
5909 	 * Do not destroy old temperature values if the new value is not
5910 	 * known i.e. if the device is inaccessible.
5911 	 */
5912 	bcopy(ssp->temps.temp, oldtemps, sizeof (oldtemps));
5913 
5914 	bzero(&ssp->temps, sizeof (lom_temp_t));
5915 	ssp->temps.num = EBUS_CONFIG2_NTEMP_DEC(
5916 	    bscv_get8(ssp, chan_general, EBUS_IDX_CONFIG2));
5917 	if (ssp->temps.num > MAX_TEMPS) {
5918 		cmn_err(CE_WARN,
5919 		    "lom: firmware reported too many temperatures being "
5920 		    "monitored.");
5921 		cmn_err(CE_CONT, "Reported %d, maximum is %d",
5922 		    ssp->temps.num, MAX_TEMPS);
5923 		ssp->temps.num = MAX_TEMPS;
5924 	}
5925 	ssp->temps.num_ov = EBUS_CONFIG3_NOTEMP_DEC(
5926 	    bscv_get8(ssp, chan_general, EBUS_IDX_CONFIG3));
5927 	if (ssp->temps.num_ov > MAX_TEMPS) {
5928 		cmn_err(CE_WARN,
5929 		    "lom: firmware reported too many over temperatures being "
5930 		    "monitored.");
5931 		cmn_err(CE_CONT, "Reported %d, maximum is %d",
5932 		    ssp->temps.num_ov, MAX_TEMPS);
5933 		ssp->temps.num_ov = MAX_TEMPS;
5934 	}
5935 	BSCV_TRACE(ssp, 'A', "bscv_setup_static_info",
5936 	    "num temps %d, over temps %d",
5937 	    ssp->temps.num, ssp->temps.num_ov);
5938 
5939 	addr_space_ptr = bscv_read_env_name(ssp,
5940 	    EBUS_CMD_SPACE4,
5941 	    EBUS_IDX4_TEMP_NAME_START,
5942 	    EBUS_IDX4_TEMP_NAME_END,
5943 	    ssp->temps.name,
5944 	    ssp->temps.num);
5945 
5946 	for (i = 0; i < ssp->temps.num; i++) {
5947 		ssp->temps.warning[i] = (int8_t)bscv_get8(ssp, chan_general,
5948 		    BSCVA(EBUS_CMD_SPACE4, EBUS_IDX4_TEMP_WARN1 + i));
5949 
5950 		/*
5951 		 * If shutdown is not enabled then set it as zero so
5952 		 * it is not displayed by the utility.
5953 		 */
5954 		if ((bscv_get8(ssp, chan_general, BSCVA(EBUS_CMD_SPACE4,
5955 		    EBUS_IDX4_TEMP_FATAL_MASK)) >> i) & 0x01) {
5956 			ssp->temps.shutdown[i] = (int8_t)bscv_get8(ssp,
5957 			    chan_general,
5958 			    BSCVA(EBUS_CMD_SPACE4, EBUS_IDX4_TEMP_SDOWN1 + i));
5959 		} else {
5960 			ssp->temps.shutdown[i] = 0;
5961 		}
5962 	}
5963 
5964 	for (i = 0; i < ssp->temps.num; i++) {
5965 		temp = bscv_get8(ssp, chan_general, EBUS_IDX_TEMP1 + i);
5966 		if ((temp <= LOM_TEMP_MAX_VALUE) ||
5967 		    (temp == LOM_TEMP_STATE_NOT_PRESENT)) {
5968 			ssp->temps.temp[i] = temp;
5969 		} else {
5970 			/* New value is not known - use old value */
5971 			ssp->temps.temp[i] = oldtemps[i];
5972 		}
5973 	}
5974 
5975 	/*
5976 	 * Check for and skip a single 0xff character between the
5977 	 * temperature and over temperature names
5978 	 */
5979 	if (bscv_get8(ssp, chan_general,
5980 	    BSCVA(EBUS_CMD_SPACE4, addr_space_ptr)) == 0xff) {
5981 		addr_space_ptr++;
5982 	}
5983 
5984 	(void) bscv_read_env_name(ssp,
5985 	    EBUS_CMD_SPACE4,
5986 	    addr_space_ptr,
5987 	    EBUS_IDX4_TEMP_NAME_END,
5988 	    ssp->temps.name_ov,
5989 	    ssp->temps.num_ov);
5990 
5991 	/*
5992 	 * To get the CB static info we need address space 3
5993 	 */
5994 	bzero(&ssp->sflags, sizeof (lom_sflags_t));
5995 	ssp->sflags.num = EBUS_CONFIG3_NBREAKERS_DEC(bscv_get8(ssp,
5996 	    chan_general, EBUS_IDX_CONFIG3));
5997 	if (ssp->sflags.num > MAX_STATS) {
5998 		cmn_err(CE_WARN,
5999 		    "lom: firmware reported too many status flags.");
6000 		cmn_err(CE_CONT,
6001 		    "Reported %d, maximum is %d",
6002 		    ssp->sflags.num, MAX_STATS);
6003 		ssp->sflags.num = MAX_STATS;
6004 	}
6005 	BSCV_TRACE(ssp, 'A', "bscv_setup_static_info",
6006 	    "num sflags %d", ssp->sflags.num);
6007 
6008 	(void) bscv_read_env_name(ssp,
6009 	    EBUS_CMD_SPACE3,
6010 	    EBUS_IDX3_BREAKER_NAME_START,
6011 	    EBUS_IDX3_BREAKER_NAME_END,
6012 	    ssp->sflags.name,
6013 	    ssp->sflags.num);
6014 
6015 
6016 	/*
6017 	 * To get the fan static info we need address space 5
6018 	 */
6019 	ssp->num_fans = EBUS_CONFIG_NFAN_DEC(
6020 	    bscv_get8(ssp, chan_general, EBUS_IDX_CONFIG));
6021 	if (ssp->num_fans > MAX_FANS) {
6022 		cmn_err(CE_WARN,
6023 		    "lom: firmware reported too many fans. ");
6024 		cmn_err(CE_CONT,
6025 		    "Reported %d, maximum is %d",
6026 		    ssp->num_fans, MAX_FANS);
6027 		ssp->num_fans = MAX_FANS;
6028 	}
6029 
6030 	for (i = 0; i < ssp->num_fans; i++) {
6031 		fanspeed = bscv_get8(ssp, chan_general,
6032 		    EBUS_IDX_FAN1_SPEED + i);
6033 		if ((fanspeed <= LOM_FAN_MAX_SPEED) ||
6034 		    (fanspeed == LOM_FAN_NOT_PRESENT)) {
6035 			/*
6036 			 * Do not destroy previous values unless the
6037 			 * value is definitive.
6038 			 */
6039 			ssp->fanspeed[i] = fanspeed;
6040 		}
6041 	}
6042 
6043 	BSCV_TRACE(ssp, 'A', "bscv_setup_static_info",
6044 	    "num fans %d", ssp->num_fans);
6045 
6046 	(void) bscv_read_env_name(ssp,
6047 	    EBUS_CMD_SPACE5,
6048 	    EBUS_IDX5_FAN_NAME_START,
6049 	    EBUS_IDX5_FAN_NAME_END,
6050 	    ssp->fan_names,
6051 	    ssp->num_fans);
6052 
6053 	/* Get led static information from address space 10 */
6054 
6055 	(void) bscv_read_env_name(ssp,
6056 	    EBUS_CMD_SPACE_LEDS,
6057 	    EBUS_IDX10_LED_NAME_START,
6058 	    EBUS_IDX10_LED_NAME_END,
6059 	    ssp->led_names,
6060 	    MAX_LED_ID);
6061 }
6062 
6063 /*
6064  * function	- bscv_read_env_name
6065  * description	- read in static environment names
6066  *		  warning changes address space and the caller relies
6067  *		  on this behaviour.
6068  * inputs	- soft state ptr, chosen address space,
6069  *		  start of name data, end of name data,
6070  *		  name storage, number of names.
6071  * outputs	- next address for reading name data.
6072  */
6073 
6074 static uint8_t
6075 bscv_read_env_name(bscv_soft_state_t *ssp,
6076     uint8_t addr_space,
6077     uint8_t addr_start,
6078     uint8_t addr_end,
6079     char namebuf[][MAX_LOM2_NAME_STR],
6080     int numnames)
6081 {
6082 	int i;
6083 	int nameidx;
6084 	int namemax;
6085 	unsigned int addr_space_ptr;
6086 	uint8_t this_char;
6087 
6088 	ASSERT(bscv_held(ssp));
6089 
6090 	BSCV_TRACE(ssp, 'A', "bscv_read_env_name",
6091 	    "bscv_read_env_name, space %d, start 0x%x, end 0x%x, numnames %d",
6092 	    addr_space, addr_start, addr_end, numnames);
6093 
6094 	addr_space_ptr = addr_start;
6095 
6096 	for (i = 0; i < numnames; i++) {
6097 		nameidx = 0;
6098 		namemax = sizeof (namebuf[i]);
6099 		bzero(namebuf[i], namemax);
6100 
6101 		while (addr_space_ptr <= addr_end) {
6102 			/*
6103 			 * Read the current character.
6104 			 */
6105 			this_char = bscv_get8(ssp, chan_general,
6106 			    BSCVA(addr_space, addr_space_ptr));
6107 
6108 			if (this_char == 0xff) {
6109 				/*
6110 				 * Ran out of names - this must
6111 				 * be the end of the name.
6112 				 * This is really an error because
6113 				 * we have just seen either a non-NUL
6114 				 * terminated string or the number of
6115 				 * strings did not match what was
6116 				 * reported.
6117 				 */
6118 				break;
6119 			}
6120 			/*
6121 			 * We increment the buffer pointer now so that
6122 			 * it is ready for the next read
6123 			 */
6124 			addr_space_ptr++;
6125 
6126 			if (this_char == '\0') {
6127 				/* Found end of string - done */
6128 				break;
6129 			}
6130 			if (nameidx < (namemax - 1)) {
6131 				/*
6132 				 * Buffer not full - record character
6133 				 * NOTE we always leave room for the NUL
6134 				 * terminator.
6135 				 */
6136 				namebuf[i][nameidx++] = this_char;
6137 			}
6138 		}
6139 		/* Ensure null termination */
6140 		namebuf[i][nameidx] = '\0';
6141 	}
6142 	/* Clamp addr_space_ptr to 0xff because we return uint8_t */
6143 	if (addr_space_ptr > 0xff) {
6144 		addr_space_ptr = 0xff;
6145 	}
6146 	return (addr_space_ptr);
6147 }
6148 
6149 /*
6150  * function	- bscv_setup_events
6151  * description	- initialise the event reporting code
6152  * inputs	- soft state ptr
6153  * outputs	- DDI_SUCCESS or DDI_FAILURE
6154  */
6155 
6156 static void
6157 bscv_setup_events(bscv_soft_state_t *ssp)
6158 {
6159 	uint8_t bits2set;
6160 	uint8_t bits2clear;
6161 
6162 	ASSERT(bscv_held(ssp));
6163 
6164 	/*
6165 	 * deal with event reporting - cover all cases
6166 	 */
6167 
6168 	bits2set = 0;
6169 	bits2clear = 0;
6170 	if (ssp->serial_reporting == LOM_SER_EVENTS_ON) {
6171 		bits2clear |= EBUS_ALARM_NOEVENTS;
6172 	} else if (ssp->serial_reporting == LOM_SER_EVENTS_OFF) {
6173 		bits2set |= EBUS_ALARM_NOEVENTS;
6174 	} else if (ssp->serial_reporting == LOM_SER_EVENTS_DEF) {
6175 		bits2set |= EBUS_ALARM_NOEVENTS;
6176 	}
6177 	bscv_setclear8_volatile(ssp, chan_general, EBUS_IDX_ALARM,
6178 	    bits2set, bits2clear);
6179 }
6180 
6181 #ifdef __sparc
6182 /*
6183  * function	- bscv_write_sig
6184  * description	- write out a signature, taking care to deal with any strange
6185  *		    values for CPU ID
6186  * inputs	- soft state ptr, signature
6187  * outputs	- none
6188  */
6189 static void
6190 bscv_write_sig(bscv_soft_state_t *ssp, bscv_sig_t s)
6191 {
6192 	ASSERT(bscv_held(ssp));
6193 
6194 	/* Upload the signature */
6195 	bscv_put32(ssp, chan_cpusig,
6196 	    BSCVA(EBUS_CMD_SPACE_CPUSIG, EBUS_IDX11_CPU_SIG_MSB),
6197 	    s.sig_info.signature);
6198 
6199 	/*
6200 	 * We always write the CPU ID last because this tells the firmware
6201 	 * that the signature is fully uploaded and therefore to consume the
6202 	 * data.  This is required since the signature is > 1 byte in size
6203 	 * and we transmit data in single bytes.
6204 	 */
6205 	if (s.cpu == ~0) {
6206 		/* ~0 means the signature applies to any CPU. */
6207 		bscv_put8(ssp, chan_cpusig,
6208 		    BSCVA(EBUS_CMD_SPACE_CPUSIG, EBUS_IDX11_CPU_ID),
6209 		    EBUS_ANY_CPU_ID);
6210 	} else {
6211 		if (s.cpu > 255) {
6212 			/*
6213 			 * The CPU ID supplied is unexpectedly large.  Lets
6214 			 * just use the bottom bits, in case other high order
6215 			 * bits are being used for special meaning.
6216 			 */
6217 			cmn_err(CE_WARN, "CPU Signature ID 0x%x > 255", s.cpu);
6218 			s.cpu %= 256;
6219 			cmn_err(CE_CONT, "using ID 0x%x instead ", s.cpu);
6220 		}
6221 		bscv_put8(ssp, chan_cpusig,
6222 		    BSCVA(EBUS_CMD_SPACE_CPUSIG, EBUS_IDX11_CPU_ID),
6223 		    (uint8_t)s.cpu);
6224 	}
6225 
6226 	ssp->last_sig = s;
6227 	ssp->progress |= BSCV_SIG_SENT;
6228 }
6229 #endif /* __sparc */
6230 
6231 #if defined(__i386) || defined(__amd64)
6232 
6233 /*
6234  * function	- bscv_inform_bsc
6235  * description	- inform bsc of driver state for logging purposes
6236  * inputs	- driver soft state, state
6237  * outputs	- none
6238  *
6239  */
6240 static void
6241 bscv_inform_bsc(bscv_soft_state_t *ssp, uint32_t state)
6242 {
6243 	ASSERT(bscv_held(ssp));
6244 
6245 	BSCV_TRACE(ssp, 'X', "bscv_inform_bsc",
6246 	    "bscv_inform_bsc: state=%d", state);
6247 
6248 	bscv_put32(ssp, chan_general,
6249 	    BSCVA(EBUS_CMD_SPACE_CPUSIG, EBUS_IDX11_CPU_SIG_MSB), state);
6250 	bscv_put8(ssp, chan_cpusig,
6251 	    BSCVA(EBUS_CMD_SPACE_CPUSIG, EBUS_IDX11_CPU_ID), EBUS_ANY_CPU_ID);
6252 }
6253 
6254 /*
6255  * function	- bscv_watchdog_pat_request
6256  * description	- request a heartbeat pat
6257  * inputs	- timeout value in seconds
6258  * outputs	- none
6259  */
6260 static void
6261 bscv_watchdog_pat_request(void *arg)
6262 {
6263 	bscv_soft_state_t *ssp = (bscv_soft_state_t *)arg;
6264 
6265 	bscv_wdog_do_pat(ssp);
6266 }
6267 
6268 /*
6269  * function	- bscv_watchdog_cfg_request
6270  * description	- request configuration of the bsc hardware watchdog
6271  * inputs	- new state (0=disabled, 1=enabled)
6272  * outputs	- one if successful, zero if unsuccesful
6273  */
6274 static void
6275 bscv_watchdog_cfg_request(bscv_soft_state_t *ssp, uint8_t new_state)
6276 {
6277 	ASSERT(new_state == WDOG_ON || new_state == WDOG_OFF);
6278 
6279 	watchdog_activated = new_state;
6280 	BSCV_TRACE(ssp, 'X', "bscv_watchdog_cfg_request",
6281 	    "watchdog_activated=%d", watchdog_activated);
6282 	bscv_write_wdog_cfg(ssp,
6283 	    bscv_watchdog_timeout_seconds,
6284 	    new_state,
6285 	    wdog_reset_on_timeout);
6286 }
6287 
6288 /*
6289  * function	- bscv_set_watchdog_timer
6290  * description	- setup the heartbeat timeout value
6291  * inputs	- timeout value in seconds
6292  * outputs	- zero if the value was not changed
6293  *                otherwise the current value
6294  */
6295 static uint_t
6296 bscv_set_watchdog_timer(bscv_soft_state_t *ssp, uint_t timeoutval)
6297 {
6298 	BSCV_TRACE(ssp, 'X', "bscv_set_watchdog_timer:",
6299 	    "timeout=%d", timeoutval);
6300 
6301 	/*
6302 	 * We get started during bscv_attach only
6303 	 * if bscv_watchdog_enable is set.
6304 	 */
6305 	if (bscv_watchdog_available && (!watchdog_activated ||
6306 	    (watchdog_activated &&
6307 	    (timeoutval != bscv_watchdog_timeout_seconds)))) {
6308 		bscv_watchdog_timeout_seconds = timeoutval;
6309 		bscv_watchdog_cfg_request(ssp, WDOG_ON);
6310 		return (bscv_watchdog_timeout_seconds);
6311 	}
6312 	return (0);
6313 }
6314 
6315 /*
6316  * function	- bscv_clear_watchdog_timer
6317  * description	- add the watchdog patter cyclic
6318  * inputs	- driver soft state
6319  * outputs	- value of watchdog timeout in seconds
6320  *
6321  * This function is a copy of the SPARC implementation
6322  * in the todblade clock driver.
6323  */
6324 static void
6325 bscv_clear_watchdog_timer(bscv_soft_state_t *ssp)
6326 {
6327 	BSCV_TRACE(ssp, 'X', "bscv_clear_watchdog_timer", "");
6328 
6329 	if (bscv_watchdog_available && watchdog_activated) {
6330 		bscv_watchdog_enable = 0;
6331 		bscv_watchdog_cfg_request(ssp, WDOG_OFF);
6332 	}
6333 }
6334 
6335 /*
6336  * function	- bscv_panic_callback
6337  * description	- called when we panic so we can disabled the watchdog
6338  * inputs	- driver soft state pointer
6339  * outputs	- DDI_SUCCESS
6340  */
6341 /*ARGSUSED1*/
6342 static boolean_t
6343 bscv_panic_callback(void *arg, int code)
6344 {
6345 	bscv_soft_state_t *ssp = (bscv_soft_state_t *)arg;
6346 
6347 	BSCV_TRACE(ssp, 'X', "bscv_panic_callback",
6348 	    "disabling watchdog");
6349 
6350 	bscv_clear_watchdog_timer(ssp);
6351 	/*
6352 	 * We dont get interrupts during the panic callback. But bscbus
6353 	 * takes care of all this
6354 	 */
6355 	bscv_full_stop(ssp);
6356 	return (DDI_SUCCESS);
6357 }
6358 
6359 /*
6360  * function	- bscv_watchdog_cyclic_add
6361  * description	- add the watchdog patter cyclic
6362  * inputs	- driver soft state
6363  * outputs	- none
6364  */
6365 static void
6366 bscv_watchdog_cyclic_add(bscv_soft_state_t *ssp)
6367 {
6368 	if (ssp->periodic_id != NULL) {
6369 		return;
6370 	}
6371 
6372 	ssp->periodic_id = ddi_periodic_add(bscv_watchdog_pat_request, ssp,
6373 	    WATCHDOG_PAT_INTERVAL, DDI_IPL_10);
6374 
6375 	BSCV_TRACE(ssp, 'X', "bscv_watchdog_cyclic_add:",
6376 	    "cyclic added");
6377 }
6378 
6379 /*
6380  * function	- bscv_watchdog_cyclic_remove
6381  * description	- remove the watchdog patter cyclic
6382  * inputs	- soft state ptr
6383  * outputs	- none
6384  */
6385 static void
6386 bscv_watchdog_cyclic_remove(bscv_soft_state_t *ssp)
6387 {
6388 	if (ssp->periodic_id == NULL) {
6389 		return;
6390 	}
6391 	ddi_periodic_delete(ssp->periodic_id);
6392 	ssp->periodic_id = NULL;
6393 	BSCV_TRACE(ssp, 'X', "bscv_watchdog_cyclic_remove:",
6394 	    "cyclic removed");
6395 }
6396 #endif /* __i386 || __amd64 */
6397 
6398 
6399 /*
6400  *  General utility routines ...
6401  */
6402 
6403 #ifdef DEBUG
6404 
6405 static void
6406 bscv_trace(bscv_soft_state_t *ssp, char code, const char *caller,
6407 	const char *fmt, ...)
6408 {
6409 	char buf[256];
6410 	char *p;
6411 	va_list va;
6412 
6413 	if (ssp->debug & (1 << (code-'@'))) {
6414 		p = buf;
6415 		(void) snprintf(p, sizeof (buf) - (p - buf),
6416 		    "%s/%s: ", MYNAME, caller);
6417 		p += strlen(p);
6418 
6419 		va_start(va, fmt);
6420 		(void) vsnprintf(p, sizeof (buf) - (p - buf), fmt, va);
6421 		va_end(va);
6422 
6423 		buf[sizeof (buf) - 1] = '\0';
6424 		(void) strlog((short)ssp->majornum, (short)ssp->minornum, code,
6425 		    SL_TRACE, buf);
6426 	}
6427 }
6428 
6429 #else /* DEBUG */
6430 
6431 _NOTE(ARGSUSED(0))
6432 static void
6433 bscv_trace(bscv_soft_state_t *ssp, char code, const char *caller,
6434 	const char *fmt, ...)
6435 {
6436 }
6437 
6438 #endif /* DEBUG */
6439