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