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