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