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