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