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