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