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