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