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.
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.
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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
28 * bscv.c - multi-threaded lom driver for the Stiletto platform.
36 #include <sys/types.h>
37 #include <sys/param.h>
41 #include <sys/stream.h>
42 #include <sys/systm.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>
50 #include <sys/consdev.h>
55 #include <sys/sunddi.h>
56 #include <sys/stream.h>
57 #include <sys/strlog.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>
68 #include <sys/lom_io.h>
69 #include <sys/bscbus.h>
70 #include <sys/bscv_impl.h>
73 * Variables defined here and visible internally only
76 static void *bscv_statep
= NULL
;
79 * Forward declarations
82 static int bscv_getinfo(dev_info_t
*, ddi_info_cmd_t
, void *, void **);
83 static int bscv_attach(dev_info_t
*, ddi_attach_cmd_t
);
84 static int bscv_detach(dev_info_t
*, ddi_detach_cmd_t
);
85 static int bscv_quiesce(dev_info_t
*);
86 static int bscv_map_regs(bscv_soft_state_t
*);
87 static void bscv_unmap_regs(bscv_soft_state_t
*);
88 static void bscv_map_chan_logical_physical(bscv_soft_state_t
*);
90 static int bscv_open(dev_t
*, int, int, cred_t
*);
91 static int bscv_close(dev_t
, int, int, cred_t
*);
92 static void bscv_full_stop(bscv_soft_state_t
*);
94 static void bscv_enter(bscv_soft_state_t
*);
95 static int bscv_tryenter(bscv_soft_state_t
*ssp
);
96 static void bscv_exit(bscv_soft_state_t
*);
98 static int bscv_held(bscv_soft_state_t
*);
101 static void bscv_put8(bscv_soft_state_t
*, int, bscv_addr_t
, uint8_t);
102 static void bscv_put16(bscv_soft_state_t
*, int, bscv_addr_t
, uint16_t);
103 static void bscv_put32(bscv_soft_state_t
*, int, bscv_addr_t
, uint32_t);
104 static uint8_t bscv_get8(bscv_soft_state_t
*, int, bscv_addr_t
);
105 static uint16_t bscv_get16(bscv_soft_state_t
*, int, bscv_addr_t
);
106 static uint32_t bscv_get32(bscv_soft_state_t
*, int, bscv_addr_t
);
107 static void bscv_setclear8(bscv_soft_state_t
*, int,
108 bscv_addr_t
, uint8_t, uint8_t);
109 static void bscv_setclear8_volatile(bscv_soft_state_t
*, int,
110 bscv_addr_t
, uint8_t, uint8_t);
111 static void bscv_rep_rw8(bscv_soft_state_t
*, int,
112 uint8_t *, bscv_addr_t
, size_t, uint_t
, boolean_t
);
113 static uint8_t bscv_get8_cached(bscv_soft_state_t
*, bscv_addr_t
);
115 static uint8_t bscv_get8_locked(bscv_soft_state_t
*, int, bscv_addr_t
, int *);
116 static void bscv_rep_get8_locked(bscv_soft_state_t
*, int,
117 uint8_t *, bscv_addr_t
, size_t, uint_t
, int *);
119 static boolean_t
bscv_faulty(bscv_soft_state_t
*);
120 static void bscv_clear_fault(bscv_soft_state_t
*);
121 static void bscv_set_fault(bscv_soft_state_t
*);
122 static boolean_t
bscv_session_error(bscv_soft_state_t
*);
123 static int bscv_retcode(bscv_soft_state_t
*);
124 static int bscv_should_retry(bscv_soft_state_t
*);
125 static void bscv_locked_result(bscv_soft_state_t
*, int *);
127 static void bscv_put8_once(bscv_soft_state_t
*, int, bscv_addr_t
, uint8_t);
128 static uint8_t bscv_get8_once(bscv_soft_state_t
*, int, bscv_addr_t
);
129 static uint32_t bscv_probe(bscv_soft_state_t
*, int, uint32_t *);
130 static void bscv_resync_comms(bscv_soft_state_t
*, int);
132 static boolean_t
bscv_window_setup(bscv_soft_state_t
*);
133 static int bscv_eerw(bscv_soft_state_t
*, uint32_t, uint8_t *,
134 unsigned, boolean_t
);
136 static int bscv_ioctl(dev_t
, int, intptr_t, int, cred_t
*, int *);
137 static int bscv_ioc_dogstate(bscv_soft_state_t
*, intptr_t, int);
138 static int bscv_ioc_psustate(bscv_soft_state_t
*, intptr_t, int);
139 static int bscv_ioc_fanstate(bscv_soft_state_t
*, intptr_t, int);
140 static int bscv_ioc_fledstate(bscv_soft_state_t
*, intptr_t, int);
141 static int bscv_ioc_ledstate(bscv_soft_state_t
*, intptr_t, int);
142 static int bscv_ioc_info(bscv_soft_state_t
*, intptr_t, int);
143 static int bscv_ioc_mread(bscv_soft_state_t
*, intptr_t, int);
144 static int bscv_ioc_volts(bscv_soft_state_t
*, intptr_t, int);
145 static int bscv_ioc_stats(bscv_soft_state_t
*, intptr_t, int);
146 static int bscv_ioc_temp(bscv_soft_state_t
*, intptr_t, int);
147 static int bscv_ioc_cons(bscv_soft_state_t
*, intptr_t, int);
148 static int bscv_ioc_eventlog2(bscv_soft_state_t
*, intptr_t, int);
149 static int bscv_ioc_info2(bscv_soft_state_t
*, intptr_t, int);
150 static int bscv_ioc_test(bscv_soft_state_t
*, intptr_t, int);
151 static int bscv_ioc_mprog2(bscv_soft_state_t
*, intptr_t, int);
152 static int bscv_ioc_mread2(bscv_soft_state_t
*, intptr_t, int);
154 static void bscv_event_daemon(void *);
155 static void bscv_start_event_daemon(bscv_soft_state_t
*);
156 static int bscv_stop_event_daemon(bscv_soft_state_t
*);
157 static int bscv_pause_event_daemon(bscv_soft_state_t
*);
158 static void bscv_resume_event_daemon(bscv_soft_state_t
*);
159 static void bscv_event_process(bscv_soft_state_t
*ssp
, boolean_t
);
160 static int bscv_event_validate(bscv_soft_state_t
*, uint32_t, uint8_t);
161 static void bscv_event_process_one(bscv_soft_state_t
*, lom_event_t
*);
162 static void bscv_build_eventstring(bscv_soft_state_t
*,
163 lom_event_t
*, char *, char *);
164 static int bscv_level_of_event(lom_event_t
*);
165 static void bscv_status(bscv_soft_state_t
*, uint8_t, uint8_t);
166 char *bscv_get_label(char [][MAX_LOM2_NAME_STR
], int, int);
167 static void bscv_generic_sysevent(bscv_soft_state_t
*, char *, char *, char *,
168 char *, int32_t, char *);
169 static void bscv_sysevent(bscv_soft_state_t
*, lom_event_t
*);
171 static int bscv_prog(bscv_soft_state_t
*, intptr_t, int);
172 static int bscv_prog_image(bscv_soft_state_t
*, boolean_t
,
173 uint8_t *, int, uint32_t);
174 static int bscv_prog_receive_image(bscv_soft_state_t
*, lom_prog_t
*,
176 static void bscv_leave_programming_mode(bscv_soft_state_t
*, boolean_t
);
177 static int bscv_prog_stop_lom(bscv_soft_state_t
*);
178 static int bscv_prog_start_lom(bscv_soft_state_t
*);
180 static int bscv_attach_common(bscv_soft_state_t
*);
181 static int bscv_cleanup(bscv_soft_state_t
*);
182 static void bscv_setup_capability(bscv_soft_state_t
*);
183 static int bscv_probe_check(bscv_soft_state_t
*);
184 static void bscv_setup_hostname(bscv_soft_state_t
*);
185 static void bscv_read_hostname(bscv_soft_state_t
*, char *);
186 static void bscv_write_hostname(bscv_soft_state_t
*, char *, uint8_t);
187 static void bscv_setup_static_info(bscv_soft_state_t
*);
188 static uint8_t bscv_read_env_name(bscv_soft_state_t
*, uint8_t,
189 uint8_t, uint8_t, char [][MAX_LOM2_NAME_STR
], int);
190 static void bscv_setup_events(bscv_soft_state_t
*);
192 static void bscv_trace(bscv_soft_state_t
*, char, const char *,
196 static void bscv_idi_init();
197 static void bscv_idi_fini();
198 static void bscv_idi_new_instance(dev_info_t
*dip
);
199 static void bscv_idi_clear_err();
200 void bscv_idi_set(struct bscv_idi_info info
);
201 static boolean_t
bscv_idi_err();
202 static boolean_t
bscv_nodename_set(struct bscv_idi_info info
);
203 static boolean_t
bscv_sig_set(struct bscv_idi_info info
);
204 static boolean_t
bscv_wdog_pat(struct bscv_idi_info info
);
205 static boolean_t
bscv_wdog_cfg(struct bscv_idi_info info
);
206 static void bscv_write_sig(bscv_soft_state_t
*ssp
, bscv_sig_t s
);
209 static void bscv_setup_watchdog(bscv_soft_state_t
*ssp
);
210 static void bscv_write_wdog_cfg(bscv_soft_state_t
*,
211 uint_t
, boolean_t
, uint8_t);
213 #if defined(__i386) || defined(__amd64)
214 static void bscv_inform_bsc(bscv_soft_state_t
*, uint32_t);
215 static void bscv_watchdog_pat_request(void *);
216 static void bscv_watchdog_cfg_request(bscv_soft_state_t
*, uint8_t);
217 static uint_t
bscv_set_watchdog_timer(bscv_soft_state_t
*, uint_t
);
218 static void bscv_clear_watchdog_timer(bscv_soft_state_t
*);
220 static boolean_t
bscv_panic_callback(void *, int);
221 static void bscv_watchdog_cyclic_add(bscv_soft_state_t
*);
222 static void bscv_watchdog_cyclic_remove(bscv_soft_state_t
*);
224 static uint8_t wdog_reset_on_timeout
= 1;
228 #define CLK_WATCHDOG_DEFAULT 10 /* 10 seconds */
229 #define WATCHDOG_PAT_INTERVAL 1000000000 /* 1 second */
231 static int bscv_watchdog_enable
;
232 static int bscv_watchdog_available
;
233 static int watchdog_activated
;
234 static uint_t bscv_watchdog_timeout_seconds
;
235 #endif /* __i386 || __amd64 */
238 struct bscv_idi_callout bscv_idi_callout_table
[] = {
239 {BSCV_IDI_NODENAME
, &bscv_nodename_set
},
240 {BSCV_IDI_SIG
, &bscv_sig_set
},
241 {BSCV_IDI_WDOG_PAT
, &bscv_wdog_pat
},
242 {BSCV_IDI_WDOG_CFG
, &bscv_wdog_cfg
},
243 {BSCV_IDI_NULL
, NULL
}
246 static struct bscv_idi_callout_mgr bscv_idi_mgr
;
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)
258 * Strings for daemon event reporting
261 static char *eventSubsysStrings
[] =
264 "temperature sensor ", /* 02 */
265 "overheat sensor ", /* 03 */
267 "supply rail ", /* 05 */
268 "circuit breaker ", /* 06 */
271 "phonehome ", /* 09; unutilized */
274 "event log ", /* 0c */
275 "", /* 0d; EVENT_SUBSYS_EXTRA unutilized */
279 static char *eventTypeStrings
[] =
281 "[null event]", /* 00 */
284 "state change", /* 03 */
286 "power off", /* 05 */
287 "powered off unexpectedly", /* 06 */
288 "reset unexpectedly", /* 07 */
290 "watchdog enabled", /* 09 */
291 "watchdog disabled", /* 0a */
292 "watchdog triggered", /* 0b */
294 "recovered", /* 0d */
296 "XIR reset", /* 0f */
297 "console selected", /* 10 */
298 "time reference", /* 11 */
299 "script failure", /* 12 */
300 "modem access failure", /* 13 */
301 "modem dialing failure", /* 14 */
302 "bad checksum", /* 15 */
307 "password changed", /* 1a */
308 "login failed", /* 1b */
310 "flash download", /* 1d */
311 "data lost", /* 1e */
312 "device busy", /* 1f */
313 "fault led state", /* 20 */
315 "severe overheat", /* 22 */
316 "no overheat", /* 23 */
318 "device inaccessible", /* 25 */
319 "Hostname change", /* 26 */
320 "CPU signature timeout", /* 27 */
321 "Bootmode change", /* 28 */
322 "Watchdog change policy", /* 29 */
323 "Watchdog change timeout", /* 2a */
327 * These store to mapping between the logical service, e.g. chan_prog for
328 * programming, and the actual Xbus channel which carries that traffic.
329 * Any services can be shared on the same channel apart from chan_wdogpat.
331 static int chan_general
; /* General Traffic */
332 static int chan_wdogpat
; /* Watchdog Patting */
333 static int chan_cpusig
; /* CPU signatures */
334 static int chan_eeprom
; /* EEPROM I/O */
335 static int chan_prog
; /* Programming */
338 * cb_ops structure defining the driver entry points
341 static struct cb_ops bscv_cb_ops
= {
342 bscv_open
, /* open */
343 bscv_close
, /* close */
344 nodev
, /* strategy */
349 bscv_ioctl
, /* ioctl */
354 ddi_prop_op
, /* prop op */
355 NULL
, /* ! STREAMS */
356 D_NEW
| D_MP
/* MT/MP Safe */
360 * dev_ops structure defining autoconfiguration driver autoconfiguration
364 static struct dev_ops bscv_dev_ops
= {
365 DEVO_REV
, /* devo_rev */
367 bscv_getinfo
, /* devo_getinfo */
368 nulldev
, /* devo_identify */
369 nulldev
, /* devo_probe */
370 bscv_attach
, /* devo_attach */
371 bscv_detach
, /* devo_detach */
372 nodev
, /* devo_reset */
373 &bscv_cb_ops
, /* devo_cb_ops */
374 (struct bus_ops
*)0, /* devo_bus_ops */
375 NULL
, /* devo_power */
376 bscv_quiesce
, /* devo_quiesce */
380 * module configuration section
384 #define BSCV_VERSION_STRING "bscv driver - Debug"
386 #define BSCV_VERSION_STRING "bscv driver"
389 static struct modldrv modldrv
= {
395 static struct modlinkage modlinkage
= {
402 /* Tracing is enabled if value is non-zero. */
403 static int bscv_trace_flag
= 1;
405 #define BSCV_TRACE if (bscv_trace_flag != 0) bscv_trace
411 * kernel accessible routines. These routines are necessarily global so the
412 * driver can be loaded, and unloaded successfully
417 * description - initializes the driver state structure and installs the
418 * driver module into the kernel
420 * outputs - success or failure of module installation
428 if ((e
= ddi_soft_state_init(&bscv_statep
,
429 sizeof (bscv_soft_state_t
), 1)) != 0) {
433 if ((e
= mod_install(&modlinkage
)) != 0) {
434 ddi_soft_state_fini(&bscv_statep
);
438 if (e
== 0) bscv_idi_init();
445 * description - provide information about a kernel loaded module
446 * inputs - module infomation
447 * outputs - success or failure of information request
451 _info(struct modinfo
*modinfop
)
453 return (mod_info(&modlinkage
, modinfop
));
458 * description - removes a module from the kernel and frees the driver soft
461 * outputs - success or failure of module removal
469 if ((e
= mod_remove(&modlinkage
)) != 0) {
476 ddi_soft_state_fini(&bscv_statep
);
482 * function - bscv_getinfo
483 * description - routine used to provide information on the driver
484 * inputs - device information structure, command, command arg, storage
485 * area for the result
486 * outputs - DDI_SUCCESS or DDI_FAILURE
491 bscv_getinfo(dev_info_t
*dip
, ddi_info_cmd_t cmd
, void *arg
, void **result
)
493 bscv_soft_state_t
*ssp
;
494 dev_t dev
= (dev_t
)arg
;
498 instance
= DEVICETOINSTANCE(dev
);
501 case DDI_INFO_DEVT2INSTANCE
:
502 *result
= (void *)(uintptr_t)instance
;
506 case DDI_INFO_DEVT2DEVINFO
:
507 ssp
= ddi_get_soft_state(bscv_statep
, instance
);
509 return (DDI_FAILURE
);
510 *result
= (void *) ssp
->dip
;
526 bscv_idi_mgr
.valid_inst
= (uint32_t)~0; /* No valid instances */
527 bscv_idi_mgr
.tbl
= bscv_idi_callout_table
;
528 bscv_idi_mgr
.errs
= 0;
531 * Now that all fields are initialized, set the magic flag. This is
532 * a kind of integrity check for the data structure.
534 bscv_idi_mgr
.magic
= BSCV_IDI_CALLOUT_MAGIC
;
540 ASSERT(bscv_idi_mgr
.magic
== BSCV_IDI_CALLOUT_MAGIC
);
542 bscv_idi_mgr
.errs
= 0;
546 * function - bscv_idi_err
547 * description - error messaging service which throttles the number of error
548 * messages to avoid overflowing storage
550 * returns - boolean to indicate whether a message should be reported
551 * side-effects - updates the error number counter
556 ASSERT(bscv_idi_mgr
.magic
== BSCV_IDI_CALLOUT_MAGIC
);
560 if (bscv_idi_mgr
.errs
++ < BSCV_IDI_ERR_MSG_THRESHOLD
)
567 bscv_idi_new_instance(dev_info_t
*dip
)
569 ASSERT(bscv_idi_mgr
.magic
== BSCV_IDI_CALLOUT_MAGIC
);
572 * We don't care how many instances we have, or their value, so long
573 * as we have at least one valid value. This is so service routines
574 * can get any required locks via a soft state pointer.
576 if (bscv_idi_mgr
.valid_inst
== (uint32_t)~0) {
577 bscv_idi_mgr
.valid_inst
= ddi_get_instance(dip
);
584 bscv_idi_mgr
.valid_inst
= (uint32_t)~0; /* No valid instances */
585 bscv_idi_mgr
.tbl
= NULL
;
590 * function - bscv_attach
591 * description - this routine is responsible for setting aside memory for the
592 * driver data structures, initialising the mutexes and creating
593 * the device minor nodes. Additionally, this routine calls the
594 * the callback routine.
595 * inputs - device information structure, DDI_ATTACH command
596 * outputs - DDI_SUCCESS or DDI_FAILURE
600 bscv_attach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
)
602 bscv_soft_state_t
*ssp
;
608 instance
= ddi_get_instance(dip
);
610 if (ddi_soft_state_zalloc(bscv_statep
, instance
) !=
612 return (DDI_FAILURE
);
616 ssp
= ddi_get_soft_state(bscv_statep
, instance
);
621 ssp
->instance
= instance
;
622 ssp
->event_waiting
= B_FALSE
;
623 ssp
->status_change
= B_FALSE
;
624 ssp
->nodename_change
= B_FALSE
;
628 ssp
->prog_mode_only
= B_FALSE
;
629 ssp
->programming
= B_FALSE
;
630 ssp
->cssp_prog
= B_FALSE
;
632 ssp
->debug
= ddi_prop_get_int(DDI_DEV_T_ANY
, dip
,
633 DDI_PROP_DONTPASS
, "debug", 0);
634 ssp
->majornum
= ddi_driver_major(dip
);
635 ssp
->minornum
= BSCV_INST_TO_MINOR(instance
);
636 #if defined(__i386) || defined(__amd64)
637 ssp
->last_nodename
[0] = '\0';
638 #endif /* __i386 || __amd64 */
641 * initialise the mutexes
644 mutex_init(&ssp
->cmd_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
646 mutex_init(&ssp
->task_mu
, NULL
, MUTEX_DRIVER
, NULL
);
647 cv_init(&ssp
->task_cv
, NULL
, CV_DRIVER
, NULL
);
648 cv_init(&ssp
->task_evnt_cv
, NULL
, CV_DRIVER
, NULL
);
649 mutex_init(&ssp
->prog_mu
, NULL
, MUTEX_DRIVER
, NULL
);
650 ssp
->progress
|= BSCV_LOCKS
;
652 BSCV_TRACE(ssp
, 'A', "bscv_attach",
653 "bscv_attach: mutexes and condition vars initialised");
655 /* Map in physical communication channels */
657 if (bscv_map_regs(ssp
) != DDI_SUCCESS
) {
658 (void) bscv_cleanup(ssp
);
659 return (DDI_FAILURE
);
661 ssp
->progress
|= BSCV_MAPPED_REGS
;
663 /* Associate logical channels to physical channels */
665 bscv_map_chan_logical_physical(ssp
);
669 bscv_leave_programming_mode(ssp
, B_FALSE
);
671 if (bscv_attach_common(ssp
) == DDI_FAILURE
) {
673 (void) bscv_cleanup(ssp
);
674 return (DDI_FAILURE
);
679 * At this point the inter-driver-interface is made available.
680 * The IDI uses the event thread service which
681 * bscv_attach_common() sets up.
683 bscv_idi_new_instance(dip
);
689 * now create the minor nodes
691 if (ddi_create_minor_node(ssp
->dip
, "lom", S_IFCHR
,
692 BSCV_INST_TO_MINOR(instance
),
693 DDI_PSEUDO
, 0) != DDI_SUCCESS
) {
694 (void) bscv_cleanup(ssp
);
695 return (DDI_FAILURE
);
697 BSCV_TRACE(ssp
, 'A', "bscv_attach",
698 "bscv_attach: device minor nodes created");
699 ssp
->progress
|= BSCV_NODES
;
701 if (!ssp
->prog_mode_only
)
702 bscv_start_event_daemon(ssp
);
704 #if defined(__i386) || defined(__amd64)
705 bscv_watchdog_enable
= 1;
706 bscv_watchdog_available
= 1;
707 watchdog_activated
= 0;
708 bscv_watchdog_timeout_seconds
= CLK_WATCHDOG_DEFAULT
;
710 if (bscv_watchdog_enable
&& (boothowto
& RB_DEBUG
)) {
711 bscv_watchdog_available
= 0;
712 cmn_err(CE_WARN
, "bscv: kernel debugger "
713 "detected: hardware watchdog disabled");
717 * Before we enable the watchdog - register the panic
718 * callback so that we get called to stop the watchdog
719 * in the case of a panic.
721 ssp
->callb_id
= callb_add(bscv_panic_callback
,
722 (void *)ssp
, CB_CL_PANIC
, "");
724 if (bscv_watchdog_available
) {
725 (void) bscv_set_watchdog_timer(ssp
,
726 CLK_WATCHDOG_DEFAULT
);
728 bscv_setup_watchdog(ssp
); /* starts cyclic callback */
731 #endif /* __i386 || __amd64 */
733 return (DDI_SUCCESS
);
735 return (DDI_FAILURE
);
740 * function - bscv_detach
741 * description - routine that prepares a module to be unloaded. It undoes all
742 * the work done by the bscv_attach)() routine. This is
743 * facilitated by the use of the progress indicator
744 * inputs - device information structure, DDI_DETACH command
745 * outputs - DDI_SUCCESS or DDI_FAILURE
750 bscv_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
)
752 return (DDI_FAILURE
);
756 * quiesce(9E) entry point.
758 * This function is called when the system is single-threaded at high
759 * PIL with preemption disabled. Therefore, this function must not be
762 * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
763 * DDI_FAILURE indicates an error condition and should almost never happen.
766 bscv_quiesce(dev_info_t
*dip
)
768 bscv_soft_state_t
*ssp
;
772 instance
= ddi_get_instance(dip
);
773 ssp
= ddi_get_soft_state(bscv_statep
, instance
);
775 return (DDI_FAILURE
);
778 /* Disable tracing, as we are executing at High-Interrupt level */
781 /* quiesce the device */
784 return (DDI_SUCCESS
);
792 * function - bscv_open
793 * description - routine to provide association between user fd and device
794 * minor number. This routine is necessarily simple since a
795 * read/write interface is not provided. Additionally, the
796 * driver does not enforce exclusive access (FEXCL) or
797 * non-blocking during an open (FNDELAY). Deferred attach is
799 * inputs - device number, flag specifying open type, device type,
801 * outputs - success or failure of operation
806 bscv_open(dev_t
*devp
, int flag
, int otype
, cred_t
*cred
)
808 bscv_soft_state_t
*ssp
;
811 instance
= DEVICETOINSTANCE(*devp
);
812 ssp
= ddi_get_soft_state(bscv_statep
, instance
);
814 return (ENXIO
); /* not attached yet */
816 BSCV_TRACE(ssp
, 'O', "bscv_open", "instance 0x%x", instance
);
818 if (otype
!= OTYP_CHR
) {
826 * function - bscv_close
827 * description - routine to perform the final close on the device. As per the
828 * open routine, neither FEXCL or FNDELAY accesses are enforced
830 * inputs - device number,flag specifying open type, device type,
832 * outputs - success or failure of operation
837 bscv_close(dev_t dev
, int flag
, int otype
, cred_t
*cred
)
839 bscv_soft_state_t
*ssp
;
842 instance
= DEVICETOINSTANCE(dev
);
843 ssp
= ddi_get_soft_state(bscv_statep
, instance
);
847 BSCV_TRACE(ssp
, 'O', "bscv_close", "instance 0x%x", instance
);
853 bscv_map_regs(bscv_soft_state_t
*ssp
)
858 unsigned int nelements
;
865 * Work out how many channels are available by looking at the number
866 * of elements of the regs property array.
868 retval
= ddi_prop_lookup_int_array(DDI_DEV_T_ANY
, ssp
->dip
,
869 DDI_PROP_DONTPASS
, "reg", &props
, &nelements
);
871 /* We don't need props anymore. Free memory if it was allocated */
872 if (retval
== DDI_PROP_SUCCESS
)
873 ddi_prop_free(props
);
875 /* Check for sanity of nelements */
876 if (retval
!= DDI_PROP_SUCCESS
) {
877 BSCV_TRACE(ssp
, 'A', "bscv_map_regs", "lookup reg returned"
880 } else if (nelements
% LOMBUS_REGSPEC_SIZE
!= 0) {
881 BSCV_TRACE(ssp
, 'A', "bscv_map_regs", "nelements %d not"
882 " a multiple of %d", nelements
, LOMBUS_REGSPEC_SIZE
);
884 } else if (nelements
> BSCV_MAXCHANNELS
* LOMBUS_REGSPEC_SIZE
) {
885 BSCV_TRACE(ssp
, 'A', "bscv_map_regs", "nelements %d too large"
886 ", probably a misconfiguration", nelements
);
888 } else if (nelements
< BSCV_MINCHANNELS
* LOMBUS_REGSPEC_SIZE
) {
889 BSCV_TRACE(ssp
, 'A', "bscv_map_regs", "nelements %d too small"
890 ", need to have at least a general and a wdog channel",
895 ssp
->nchannels
= nelements
/ LOMBUS_REGSPEC_SIZE
;
897 ssp
->attr
.devacc_attr_version
= DDI_DEVICE_ATTR_V0
;
898 ssp
->attr
.devacc_attr_endian_flags
= DDI_STRUCTURE_LE_ACC
;
899 ssp
->attr
.devacc_attr_dataorder
= DDI_STRICTORDER_ACC
;
901 for (i
= 0; i
< ssp
->nchannels
; i
++) {
902 retval
= ddi_regs_map_setup(ssp
->dip
, i
,
903 (caddr_t
*)&ssp
->channel
[i
].regs
,
904 0, 0, &ssp
->attr
, &ssp
->channel
[i
].handle
);
905 if (retval
!= DDI_SUCCESS
) {
906 BSCV_TRACE(ssp
, 'A', "bscv_map_regs", "map failure"
907 " 0x%x on space %d", retval
, i
);
909 /* Rewind all current mappings - avoiding failed one */
911 for (; i
>= 0; i
--) {
912 ddi_regs_map_free(&ssp
->channel
[i
].handle
);
919 return (DDI_SUCCESS
);
923 * It is important to set nchannels to 0 even if, say, only one of
924 * the two required handles was mapped. If we cannot achieve our
925 * minimum config its not safe to do any IO; this keeps our failure
926 * mode handling simpler.
929 return (DDI_FAILURE
);
933 bscv_unmap_regs(bscv_soft_state_t
*ssp
)
939 for (i
= 0; i
< ssp
->nchannels
; i
++) {
940 ddi_regs_map_free(&ssp
->channel
[i
].handle
);
945 * Map logical services onto physical XBus channels.
948 bscv_map_chan_logical_physical(bscv_soft_state_t
*ssp
)
953 * We can assert that there will always be at least two channels,
954 * to allow watchdog pats to be segregated from all other traffic.
960 * By default move all other services onto the generic channel unless
961 * the hardware supports additional channels.
964 chan_cpusig
= chan_eeprom
= chan_prog
= chan_general
;
966 if (ssp
->nchannels
> 2)
968 if (ssp
->nchannels
> 3)
970 if (ssp
->nchannels
> 4)
976 * function - bscv_full_stop
977 * description - gracefully shut the lom down during panic or reboot.
978 * Disables the watchdog and sets up serial event reporting.
979 * inputs - soft state pointer
983 bscv_full_stop(bscv_soft_state_t
*ssp
)
985 uint8_t bits2set
= 0;
986 uint8_t bits2clear
= 0;
989 BSCV_TRACE(ssp
, 'W', "bscv_full_stop",
990 "turning off watchdog");
993 * Obtain the softstate lock only if it is not already owned,
994 * as this function can be called from a High-level interrupt
995 * context. As a result, our thread cannot sleep.
996 * At end of function, our thread releases the lock only if
997 * it acquired the lock.
999 obtained_lock
= (bscv_tryenter(ssp
) != 0);
1001 #if defined(__i386) || defined(__amd64)
1002 if (ddi_in_panic()) {
1003 bscv_inform_bsc(ssp
, BSC_INFORM_PANIC
);
1005 bscv_inform_bsc(ssp
, BSC_INFORM_OFFLINE
);
1007 #endif /* __i386 || __amd64 */
1009 /* set serial event reporting */
1010 switch (ssp
->serial_reporting
) {
1011 case LOM_SER_EVENTS_ON
:
1012 case LOM_SER_EVENTS_DEF
:
1013 /* Make sure serial event reporting is on */
1014 bits2clear
= EBUS_ALARM_NOEVENTS
;
1016 case LOM_SER_EVENTS_OFF
:
1017 /* Make sure serial event reporting is on */
1018 bits2set
= EBUS_ALARM_NOEVENTS
;
1023 bscv_setclear8_volatile(ssp
, chan_general
,
1024 EBUS_IDX_ALARM
, bits2set
, bits2clear
);
1026 /* Do not free the lock if our thread did not obtain it. */
1027 if (obtained_lock
!= 0) {
1037 * Two sets of routines are provided:
1038 * normal - must be called after acquiring an appropriate lock.
1039 * locked - perform all the locking required and return any error
1040 * code in the supplied 'res' argument. If there is no
1041 * error 'res' is not changed.
1042 * The locked routines are designed for use in ioctl commands where
1043 * only a single operation needs to be performed and the overhead of
1044 * locking and result checking adds significantly to code complexity.
1046 * locking primitives
1048 * bscv_enter() - acquires an I/O lock for the calling thread.
1049 * bscv_tryenter() - conditionally acquires an I/O lock for calling thread.
1050 * bscv_exit() - releases an I/O lock acquired by bscv_enter().
1051 * bscv_held() - used to assert ownership of an I/O lock.
1053 * normal I/O routines
1055 * Note bscv_{put|get}{16|32} routines are big-endian. This assumes that
1056 * the firmware works that way too.
1058 * bscv_put8(), bscv_put16, bscv_put32 - write values to the LOM
1059 * and handle any retries if necessary.
1060 * 16 and 32 bit values are big-endian.
1061 * bscv_get8(), bscv_get16, bscv_get32 - read values from the LOM
1062 * and handle any retries if necessary.
1063 * 16 and 32 bit values are big-endian.
1064 * bscv_setclear8() - set or clear the specified bits in the register
1065 * at the supplied address.
1066 * bscv_setclear8_volatile() - set or clear the specified bits in the
1067 * register at the supplied address. If the lom reports
1068 * that the registers has changed since the last read
1069 * re-read and apply the set or clear to the new bits.
1070 * bscv_get8_cached() - Return a cached register value (addr < 0x80).
1071 * Does not access the hardware. A read of the hardware
1072 * automatically updates this cache.
1074 * locked I/O routines
1076 * bscv_get8_locked(), bscv_rep_get8_locked().
1078 * Call the indicated function from above, but wrapping it with
1079 * bscv_enter()/bscv_exit().
1084 * LOM communications fault are grouped into three categories:
1085 * 1) Faulty - the LOM is not responding and no attempt to communicate
1086 * with it should be made.
1087 * 2) Transient fault - something which might recover after a retry
1088 * but which doesn't affect our ability to perform other
1090 * 3) Command error - an inappropriate command was executed. A retry
1091 * will not fix it but the command failed.
1093 * The current implementation of the bscv driver is not very good at
1094 * noticing command errors due to the structure of the original code
1095 * that it is based on. It is possible to extend the driver to do this
1096 * and would probably involve having a concept of a "session error"
1097 * which is less severe than a fault but means that a sequence of
1098 * commands had some fault which cannot be recovered.
1103 * bscv_faulty() - returns B_TRUE if the LOM (communications) have been
1105 * bscv_clear_fault() - marks the LOM as not faulty.
1106 * bscv_set_fault() - marks the LOM as being faulty.
1108 * bscv_clear_fault and bscv_set_fault should generally not be called
1111 * command errors/transient faults
1113 * bscv_retcode() - returns the actual error code of the last operation.
1114 * bscv_should_retry() - determines if last operation may suceed if
1116 * bscv_locked_result() - Set the result of a locked register access.
1118 * low level I/O primitives
1120 * These are generally not called directly. These perform a single
1121 * access to the LOM device. They do not handle retries.
1125 * bscv_probe() - perform a probe (NOP) operation to check out lom comms.
1126 * bscv_resync_comms() - resynchronise communications after a transient fault.
1130 bscv_enter(bscv_soft_state_t
*ssp
)
1132 BSCV_TRACE(ssp
, '@', "bscv_enter", "");
1133 mutex_enter(&ssp
->cmd_mutex
);
1134 ssp
->had_session_error
= B_FALSE
;
1138 bscv_tryenter(bscv_soft_state_t
*ssp
)
1142 BSCV_TRACE(ssp
, '@', "bscv_tryenter", "");
1143 if ((rv
= mutex_tryenter(&ssp
->cmd_mutex
)) != 0) {
1144 ssp
->had_session_error
= B_FALSE
;
1150 bscv_exit(bscv_soft_state_t
*ssp
)
1152 mutex_exit(&ssp
->cmd_mutex
);
1153 BSCV_TRACE(ssp
, '@', "bscv_exit", "");
1158 bscv_held(bscv_soft_state_t
*ssp
)
1160 return (mutex_owned(&ssp
->cmd_mutex
));
1165 bscv_put8(bscv_soft_state_t
*ssp
, int chan
, bscv_addr_t addr
, uint8_t val
)
1167 boolean_t needretry
;
1170 ASSERT(bscv_held(ssp
));
1172 if (bscv_faulty(ssp
)) {
1176 BSCV_TRACE(ssp
, '@', "bscv_put8",
1177 "addr 0x%x.%02x <= 0x%02x", addr
>> 8, addr
& 0xff, val
);
1179 for (num_failures
= 0;
1180 num_failures
< BSC_FAILURE_RETRY_LIMIT
;
1182 bscv_put8_once(ssp
, chan
, addr
, val
);
1183 needretry
= bscv_should_retry(ssp
);
1188 if (ssp
->command_error
!= 0) {
1189 ssp
->had_session_error
= B_TRUE
;
1193 /* Failure - we ran out of retries */
1194 cmn_err(CE_WARN
, "bscv_put8: addr 0x%x.%02x retried "
1195 "write %d times, giving up",
1196 addr
>> 8, addr
& 0xff, num_failures
);
1197 bscv_set_fault(ssp
);
1198 } else if (num_failures
> 0) {
1199 BSCV_TRACE(ssp
, 'R', "bscv_put8",
1200 "addr 0x%x.%02x retried write %d times, succeeded",
1201 addr
>> 8, addr
& 0xff, num_failures
);
1206 bscv_put16(bscv_soft_state_t
*ssp
, int chan
, bscv_addr_t addr
, uint16_t val
)
1208 ASSERT(bscv_held(ssp
));
1209 BSCV_TRACE(ssp
, '@', "bscv_put16",
1210 "addr 0x%x.%02x <= %04x", addr
>> 8, addr
& 0xff, val
);
1211 bscv_put8(ssp
, chan
, addr
, val
>> 8);
1212 bscv_put8(ssp
, chan
, addr
+ 1, val
& 0xff);
1216 bscv_put32(bscv_soft_state_t
*ssp
, int chan
, bscv_addr_t addr
, uint32_t val
)
1218 ASSERT(bscv_held(ssp
));
1219 BSCV_TRACE(ssp
, '@', "bscv_put32",
1220 "addr 0x%x.%02x <= %08x", addr
>> 8, addr
& 0xff, val
);
1221 bscv_put8(ssp
, chan
, addr
, (val
>> 24) & 0xff);
1222 bscv_put8(ssp
, chan
, addr
+ 1, (val
>> 16) & 0xff);
1223 bscv_put8(ssp
, chan
, addr
+ 2, (val
>> 8) & 0xff);
1224 bscv_put8(ssp
, chan
, addr
+ 3, val
& 0xff);
1228 bscv_get8(bscv_soft_state_t
*ssp
, int chan
, bscv_addr_t addr
)
1231 boolean_t needretry
;
1234 ASSERT(bscv_held(ssp
));
1236 if (bscv_faulty(ssp
)) {
1240 for (num_failures
= 0;
1241 num_failures
< BSC_FAILURE_RETRY_LIMIT
;
1243 retval
= bscv_get8_once(ssp
, chan
, addr
);
1244 needretry
= bscv_should_retry(ssp
);
1249 if (ssp
->command_error
!= 0) {
1250 ssp
->had_session_error
= B_TRUE
;
1255 cmn_err(CE_WARN
, "bscv_get8: addr 0x%x.%02x retried "
1256 "read %d times, giving up",
1257 addr
>> 8, addr
& 0xff, num_failures
);
1258 bscv_set_fault(ssp
);
1259 } else if (num_failures
> 0) {
1260 BSCV_TRACE(ssp
, 'R', "bscv_get8",
1261 "addr 0x%x.%02x retried read %d times, succeeded",
1262 addr
>> 8, addr
& 0xff, num_failures
);
1265 BSCV_TRACE(ssp
, '@', "bscv_get8",
1266 "addr 0x%x.%02x => %02x", addr
>> 8, addr
& 0xff, retval
);
1271 bscv_get16(bscv_soft_state_t
*ssp
, int chan
, bscv_addr_t addr
)
1275 ASSERT(bscv_held(ssp
));
1277 retval
= bscv_get8(ssp
, chan
, addr
) << 8;
1278 retval
|= bscv_get8(ssp
, chan
, addr
+ 1);
1280 BSCV_TRACE(ssp
, '@', "bscv_get16",
1281 "addr 0x%x.%02x => %04x", addr
>> 8, addr
& 0xff, retval
);
1286 bscv_get32(bscv_soft_state_t
*ssp
, int chan
, bscv_addr_t addr
)
1290 ASSERT(bscv_held(ssp
));
1292 retval
= bscv_get8(ssp
, chan
, addr
) << 24;
1293 retval
|= bscv_get8(ssp
, chan
, addr
+ 1) << 16;
1294 retval
|= bscv_get8(ssp
, chan
, addr
+ 2) << 8;
1295 retval
|= bscv_get8(ssp
, chan
, addr
+ 3);
1297 BSCV_TRACE(ssp
, '@', "bscv_get32",
1298 "addr 0x%x.%02x => %08x", addr
>> 8, addr
& 0xff, retval
);
1303 bscv_setclear8(bscv_soft_state_t
*ssp
, int chan
,
1304 bscv_addr_t addr
, uint8_t set
, uint8_t clear
)
1308 ASSERT(bscv_held(ssp
));
1309 ASSERT(addr
< BSC_ADDR_CACHE_LIMIT
);
1311 val
= ssp
->lom_regs
[addr
] | set
;
1314 BSCV_TRACE(ssp
, '@', "bscv_setclear8",
1315 "addr 0x%x.%02x, set %02x, clear %02x => %02x",
1316 addr
>> 8, addr
& 0xff,
1319 bscv_put8(ssp
, chan
, addr
, val
);
1323 bscv_setclear8_volatile(bscv_soft_state_t
*ssp
, int chan
,
1324 bscv_addr_t addr
, uint8_t set
, uint8_t clear
)
1327 boolean_t needretry
;
1330 ASSERT(bscv_held(ssp
));
1331 ASSERT(addr
< BSC_ADDR_CACHE_LIMIT
);
1333 if (bscv_faulty(ssp
)) {
1337 BSCV_TRACE(ssp
, '@', "bscv_setclear8_volatile",
1338 "addr 0x%x.%02x => set %02x clear %02x",
1339 addr
>> 8, addr
& 0xff, set
, clear
);
1341 val
= bscv_get8_cached(ssp
, addr
);
1342 for (num_failures
= 0;
1343 num_failures
< BSC_FAILURE_RETRY_LIMIT
;
1347 bscv_put8_once(ssp
, chan
, addr
, val
);
1348 if (ssp
->command_error
== EBUS_ERROR_STALEDATA
) {
1349 /* Re-read the stale register from the lom */
1350 val
= bscv_get8_once(ssp
, chan
, addr
);
1353 needretry
= bscv_should_retry(ssp
);
1359 if (ssp
->command_error
!= 0) {
1360 ssp
->had_session_error
= B_TRUE
;
1365 cmn_err(CE_WARN
, "bscv_setclear8_volatile: addr 0x%x.%02x "
1366 "retried write %d times, giving up",
1367 addr
>> 8, addr
& 0xff, num_failures
);
1368 if (ssp
->command_error
!= EBUS_ERROR_STALEDATA
) {
1369 bscv_set_fault(ssp
);
1371 } else if (num_failures
> 0) {
1372 BSCV_TRACE(ssp
, 'R', "bscv_setclear8_volatile",
1373 "addr 0x%x.%02x retried write %d times, succeeded",
1374 addr
>> 8, addr
& 0xff, num_failures
);
1379 bscv_rep_rw8(bscv_soft_state_t
*ssp
, int chan
, uint8_t *host_addr
,
1380 bscv_addr_t dev_addr
, size_t repcount
, uint_t flags
,
1385 ASSERT(bscv_held(ssp
));
1387 inc
= (flags
& DDI_DEV_AUTOINCR
) ? 1 : 0;
1388 for (; repcount
--; dev_addr
+= inc
) {
1389 if (flags
& DDI_DEV_AUTOINCR
) {
1391 bscv_put8(ssp
, chan
, dev_addr
, *host_addr
++);
1393 *host_addr
++ = bscv_get8(ssp
, chan
, dev_addr
);
1397 bscv_put8_once(ssp
, chan
,
1398 dev_addr
, *host_addr
++);
1400 *host_addr
++ = bscv_get8_once(ssp
, chan
,
1403 /* We need this because _once routines don't do it */
1404 if (ssp
->command_error
!= 0) {
1405 ssp
->had_session_error
= B_TRUE
;
1408 if (bscv_faulty(ssp
) || bscv_session_error(ssp
)) {
1410 * No retry here. If we were AUTOINCR then get/put
1411 * will have retried. For NO_AUTOINCR we cannot retry
1412 * because the data would be corrupted.
1420 bscv_get8_cached(bscv_soft_state_t
*ssp
, bscv_addr_t addr
)
1422 ASSERT(addr
< BSC_ADDR_CACHE_LIMIT
);
1423 /* Can be called with or without the lock held */
1425 return (ssp
->lom_regs
[addr
]);
1429 bscv_get8_locked(bscv_soft_state_t
*ssp
, int chan
, bscv_addr_t addr
, int *res
)
1433 ASSERT(addr
< BSC_ADDR_CACHE_LIMIT
);
1435 retval
= bscv_get8(ssp
, chan
, addr
);
1436 bscv_locked_result(ssp
, res
);
1438 BSCV_TRACE(ssp
, '@', "bscv_get8_locked",
1439 "addr 0x%x.%02x => %02x", addr
>> 8, addr
& 0xff, retval
);
1444 bscv_rep_get8_locked(bscv_soft_state_t
*ssp
, int chan
, uint8_t *host_addr
,
1445 bscv_addr_t dev_addr
, size_t repcount
, uint_t flags
, int *res
)
1448 bscv_rep_rw8(ssp
, chan
, host_addr
, dev_addr
, repcount
,
1449 flags
, B_FALSE
/* read */);
1450 bscv_locked_result(ssp
, res
);
1455 bscv_faulty(bscv_soft_state_t
*ssp
)
1457 ASSERT(bscv_held(ssp
));
1458 return (ssp
->had_fault
);
1462 bscv_clear_fault(bscv_soft_state_t
*ssp
)
1464 ASSERT(bscv_held(ssp
));
1465 BSCV_TRACE(ssp
, 'J', "bscv_clear_fault", "clearing fault flag");
1466 ssp
->had_fault
= B_FALSE
;
1467 ssp
->had_session_error
= B_FALSE
;
1471 bscv_set_fault(bscv_soft_state_t
*ssp
)
1473 ASSERT(bscv_held(ssp
));
1474 BSCV_TRACE(ssp
, 'J', "bscv_set_fault", "setting fault flag");
1475 ssp
->had_fault
= B_TRUE
;
1479 bscv_session_error(bscv_soft_state_t
*ssp
)
1481 ASSERT(bscv_held(ssp
));
1482 return (ssp
->had_session_error
);
1486 bscv_retcode(bscv_soft_state_t
*ssp
)
1488 BSCV_TRACE(ssp
, '@', "bscv_retcode",
1489 "code 0x%x", ssp
->command_error
);
1490 return (ssp
->command_error
);
1494 bscv_should_retry(bscv_soft_state_t
*ssp
)
1496 if ((ssp
->command_error
== EBUS_ERROR_DEVICEFAIL
) ||
1497 (ssp
->command_error
>= LOMBUS_ERR_BASE
)) {
1498 /* This command is due to an I/O fault - retry might fix */
1502 * The command itself was bad - there is no point in fixing
1503 * Note. Whatever happens we should know that if we were
1504 * doing EBUS_IDX_SELFTEST0..EBUS_IDX_SELFTEST7 and we
1505 * had 0x80 set then this is a test error not a retry
1513 bscv_locked_result(bscv_soft_state_t
*ssp
, int *res
)
1515 if (bscv_faulty(ssp
) || (bscv_retcode(ssp
) != 0)) {
1521 bscv_put8_once(bscv_soft_state_t
*ssp
, int chan
, bscv_addr_t addr
, uint8_t val
)
1525 ASSERT(bscv_held(ssp
));
1527 ssp
->command_error
= 0;
1529 if (bscv_faulty(ssp
)) {
1530 /* Bail out things are not working */
1532 } else if (ssp
->nchannels
== 0) {
1533 /* Didn't manage to map handles so ddi_{get,put}* broken */
1534 BSCV_TRACE(ssp
, '@', "bscv_put8_once",
1535 "nchannels is 0x0 so cannot do IO");
1539 /* Clear any pending fault */
1540 ddi_put32(ssp
->channel
[chan
].handle
,
1541 (uint32_t *)BSC_NEXUS_ADDR(ssp
, chan
, 0, LOMBUS_FAULT_REG
), 0);
1543 /* Do the access and get fault code - may take a long time */
1544 ddi_put8(ssp
->channel
[chan
].handle
,
1545 &ssp
->channel
[chan
].regs
[addr
], val
);
1546 fault
= ddi_get32(ssp
->channel
[chan
].handle
,
1547 (uint32_t *)BSC_NEXUS_ADDR(ssp
, chan
, 0, LOMBUS_FAULT_REG
));
1549 ssp
->command_error
= fault
;
1552 /* Things were ok - update cache entry */
1553 if (addr
< BSC_ADDR_CACHE_LIMIT
) {
1554 /* Store cacheable entries */
1555 ssp
->lom_regs
[addr
] = val
;
1557 } else if (fault
>= LOMBUS_ERR_BASE
) {
1558 /* lombus problem - do a resync session */
1559 cmn_err(CE_WARN
, "!bscv_put8_once: Had comms fault "
1560 "for address 0x%x.%02x - data 0x%x, fault 0x%x",
1561 addr
>> 8, addr
& 0xff, val
, fault
);
1562 /* Attempt to resync with the lom */
1563 bscv_resync_comms(ssp
, chan
);
1565 * Note: we do not set fault status here. That
1566 * is done if our caller decides to give up talking to
1567 * the lom. The observant might notice that this means
1568 * that if we mend things on the last attempt we still
1569 * get the fault set - we just live with that!
1573 BSCV_TRACE(ssp
, '@', "bscv_put8_once",
1574 "addr 0x%x.%02x <= 0x%02x", addr
>> 8, addr
& 0xff, val
);
1578 bscv_get8_once(bscv_soft_state_t
*ssp
, int chan
, bscv_addr_t addr
)
1583 ASSERT(bscv_held(ssp
));
1585 ssp
->command_error
= 0;
1587 if (bscv_faulty(ssp
)) {
1588 /* Bail out things are not working */
1590 } else if (ssp
->nchannels
== 0) {
1591 /* Didn't manage to map handles so ddi_{get,put}* broken */
1592 BSCV_TRACE(ssp
, '@', "bscv_get8_once",
1593 "nchannels is 0x0 so cannot do IO");
1597 /* Clear any pending fault */
1598 ddi_put32(ssp
->channel
[chan
].handle
,
1599 (uint32_t *)BSC_NEXUS_ADDR(ssp
, chan
, 0, LOMBUS_FAULT_REG
), 0);
1601 /* Do the access and get fault code - may take a long time */
1602 val
= ddi_get8(ssp
->channel
[chan
].handle
,
1603 &ssp
->channel
[chan
].regs
[addr
]);
1604 fault
= ddi_get32(ssp
->channel
[chan
].handle
,
1605 (uint32_t *)BSC_NEXUS_ADDR(ssp
, chan
, 0, LOMBUS_FAULT_REG
));
1606 ssp
->command_error
= fault
;
1608 if (fault
>= LOMBUS_ERR_BASE
) {
1609 /* lombus problem - do a resync session */
1610 cmn_err(CE_WARN
, "!bscv_get8_once: Had comms fault "
1611 "for address 0x%x.%02x - data 0x%x, fault 0x%x",
1612 addr
>> 8, addr
& 0xff, val
, fault
);
1613 /* Attempt to resync with the lom */
1614 bscv_resync_comms(ssp
, chan
);
1616 * Note: we do not set fault status here. That
1617 * is done if our caller decides to give up talking to
1618 * the lom. The observant might notice that this means
1619 * that if we mend things on the last attempt we still
1620 * get the fault set - we just live with that!
1624 * FIXME - should report error if you get
1625 * EBUS_ERROR_DEVICEFAIL reported from the BSC. That gets
1626 * logged as a failure in bscv_should_retry and may contribute
1627 * to a permanent failure. Reference issues seen by Mitac.
1630 if (!bscv_faulty(ssp
)) {
1631 if (addr
< BSC_ADDR_CACHE_LIMIT
) {
1632 /* Store cacheable entries */
1633 ssp
->lom_regs
[addr
] = val
;
1637 BSCV_TRACE(ssp
, '@', "bscv_get8_once",
1638 "addr 0x%x.%02x => 0x%02x", addr
>> 8, addr
& 0xff, val
);
1643 bscv_probe(bscv_soft_state_t
*ssp
, int chan
, uint32_t *fault
)
1647 if (ssp
->nchannels
== 0) {
1649 * Failed to map handles, so cannot do any IO. Set the
1650 * fault indicator and return a dummy value.
1652 BSCV_TRACE(ssp
, '@', "bscv_probe",
1653 "nchannels is 0x0 so cannot do any IO");
1654 *fault
= LOMBUS_ERR_REG_NUM
;
1655 return ((~(int8_t)0));
1659 ddi_put32(ssp
->channel
[chan
].handle
,
1660 (uint32_t *)BSC_NEXUS_ADDR(ssp
, chan
, 0, LOMBUS_FAULT_REG
), 0);
1661 /* Probe and Check faults */
1662 *fault
= ddi_get32(ssp
->channel
[chan
].handle
,
1663 (uint32_t *)BSC_NEXUS_ADDR(ssp
, chan
, 0, LOMBUS_PROBE_REG
));
1665 async_reg
= ddi_get32(ssp
->channel
[chan
].handle
,
1666 (uint32_t *)BSC_NEXUS_ADDR(ssp
, chan
, 0, LOMBUS_ASYNC_REG
));
1668 BSCV_TRACE(ssp
, '@', "bscv_probe",
1669 "async status 0x%x, fault 0x%x", async_reg
, *fault
);
1674 bscv_resync_comms(bscv_soft_state_t
*ssp
, int chan
)
1677 uint32_t command_error
= ssp
->command_error
;
1680 if (ssp
->nchannels
== 0) {
1682 * Didn't manage to map handles so ddi_{get,put}* broken.
1683 * Therefore, there is no way to resync comms.
1685 BSCV_TRACE(ssp
, '@', "bscv_resync_comms",
1686 "nchannels is 0x0 so not possible to resync comms");
1689 if (command_error
>= LOMBUS_ERR_BASE
&&
1690 command_error
!= LOMBUS_ERR_REG_NUM
&&
1691 command_error
!= LOMBUS_ERR_REG_SIZE
&&
1692 command_error
!= LOMBUS_ERR_TIMEOUT
) {
1693 /* Resync here to make sure that the lom is talking */
1694 cmn_err(CE_WARN
, "!bscv_resync_comms: "
1695 "Attempting comms resync after comms fault 0x%x",
1697 for (try = 1; try <= 8; try++) {
1699 fault
= ddi_get32(ssp
->channel
[chan
].handle
,
1700 (uint32_t *)BSC_NEXUS_ADDR(ssp
, chan
, 0,
1706 cmn_err(CE_WARN
, "!bscv_resync_comms: "
1707 "comms resync (probing) - try 0x%x "
1708 "had fault 0x%x", try, fault
);
1712 cmn_err(CE_WARN
, "!bscv_resync_comms: "
1713 "Failed to resync comms - giving up");
1716 cmn_err(CE_WARN
, "!bscv_resync_comms: "
1717 "resync comms after 0x%x tries", try);
1718 ssp
->bad_resync
= 0;
1726 * LOMLite configuration/event eeprom access routines
1728 * bscv_window_setup() - Read/Sanity check the eeprom parameters.
1729 * This must be called prior to calling bscv_eerw().
1730 * bscv_eerw() - Read/write data from/to the eeprom.
1734 * function - bscv_window_setup
1735 * description - this routine reads the eeprom parameters and sanity
1736 * checks them to ensure that the lom is talking sense.
1737 * inputs - soft state ptr
1738 * outputs - B_TRUE if the eeprom is ok, B_FALSE if the eeprom is not OK.
1741 bscv_window_setup(bscv_soft_state_t
*ssp
)
1743 ASSERT(bscv_held(ssp
));
1745 if (ssp
->eeinfo_valid
) {
1746 /* Already have good cached values */
1747 return (ssp
->eeinfo_valid
);
1750 bscv_get8(ssp
, chan_general
, EBUS_IDX_EEPROM_SIZE_KB
) * 1024;
1751 ssp
->eventlog_start
= bscv_get16(ssp
, chan_general
,
1752 EBUS_IDX_LOG_START_HI
);
1755 * The log does not run to the end of the EEPROM because it is a
1756 * logical partition. The last 8K partition is reserved for FRUID
1759 ssp
->eventlog_size
= EBUS_LOG_END
- ssp
->eventlog_start
;
1761 BSCV_TRACE(ssp
, 'I', "bscv_window_setup", "eeprom size 0x%x log_start"
1762 " 0x%x log_size 0x%x", ssp
->eeprom_size
, ssp
->eventlog_start
,
1763 ssp
->eventlog_size
);
1765 if (bscv_faulty(ssp
) || bscv_session_error(ssp
)) {
1766 ssp
->eeinfo_valid
= B_FALSE
;
1767 } else if ((ssp
->eeprom_size
== 0) ||
1768 (ssp
->eventlog_start
>= ssp
->eeprom_size
)) {
1769 /* Sanity check values */
1771 "!bscv_window_setup: read invalid eeprom parameters");
1772 ssp
->eeinfo_valid
= B_FALSE
;
1774 ssp
->eeinfo_valid
= B_TRUE
;
1777 BSCV_TRACE(ssp
, 'I', "bscv_window_setup", "returning eeinfo_valid %s",
1778 ssp
->eeinfo_valid
? "true" : "false");
1779 return (ssp
->eeinfo_valid
);
1783 * function - bscv_eerw
1784 * description - this routine reads/write data from/to the eeprom.
1785 * It takes care of setting the window on the eeprom correctly.
1786 * inputs - soft state ptr, eeprom offset, data buffer, size, read/write
1787 * outputs - B_TRUE if the eeprom is ok, B_FALSE if the eeprom is not OK.
1790 bscv_eerw(bscv_soft_state_t
*ssp
, uint32_t eeoffset
, uint8_t *buf
,
1791 unsigned size
, boolean_t is_write
)
1793 uint32_t blk_addr
= eeoffset
;
1794 unsigned remaining
= size
;
1800 while (remaining
> 0) {
1801 page_idx
= blk_addr
& 0xff;
1802 if ((page_idx
+ remaining
) > 0x100) {
1803 blk_size
= 0x100 - page_idx
;
1805 blk_size
= remaining
;
1808 /* Select correct eeprom page */
1809 this_page
= blk_addr
>> 8;
1810 bscv_put8(ssp
, chan_eeprom
, EBUS_IDX_EEPROM_PAGESEL
, this_page
);
1812 BSCV_TRACE(ssp
, 'M', "lom_eerw",
1813 "%s data @0x%x.%02x, size 0x%x, 0x%x bytes remaining",
1814 is_write
? "writing" : "reading",
1815 this_page
, page_idx
, blk_size
, remaining
- blk_size
);
1817 bscv_rep_rw8(ssp
, chan_eeprom
,
1818 buf
, BSCVA(EBUS_CMD_SPACE_EEPROM
, page_idx
),
1819 blk_size
, DDI_DEV_AUTOINCR
, is_write
);
1821 if (bscv_faulty(ssp
) || bscv_session_error(ssp
)) {
1826 remaining
-= blk_size
;
1827 blk_addr
+= blk_size
;
1835 bscv_is_null_event(bscv_soft_state_t
*ssp
, lom_event_t
*e
)
1839 if (EVENT_DECODE_SUBSYS(e
->ev_subsys
) == EVENT_SUBSYS_NONE
&&
1840 e
->ev_event
== EVENT_NONE
) {
1842 * This marks a NULL event.
1844 BSCV_TRACE(ssp
, 'E', "bscv_is_null_event",
1845 "EVENT_SUBSYS_NONE/EVENT_NONE null event");
1847 } else if (e
->ev_subsys
== 0xff && e
->ev_event
== 0xff) {
1849 * Under some circumstances, we've seen all 1s to represent
1850 * a manually cleared event log at the BSC prompt. Only
1851 * a test/diagnosis environment is likely to show this.
1853 BSCV_TRACE(ssp
, 'E', "bscv_is_null_event", "0xffff null event");
1859 BSCV_TRACE(ssp
, 'E', "bscv_is_null_event", "returning False");
1865 * *********************************************************************
1867 * *********************************************************************
1871 * function - bscv_ioctl
1872 * description - routine that acts as a high level manager for ioctls. It
1873 * calls the appropriate handler for ioctls on the alarm:mon and
1874 * alarm:ctl minor nodes respectively
1876 * Unsupported ioctls (now deprecated)
1884 * LOMIOCDOGCTL, TSIOCDOGCTL
1885 * LOMIOCDOGPAT, TSIOCDOGPAT
1886 * LOMIOCDOGTIME, TSIOCDOGTIME
1891 * LOMIOCNBMON, TSIOCNBMON
1893 * LOMIOCUNLOCK, TSIOCUNLOCK
1894 * LOMIOCWTMON, TSIOCWTMON
1897 * LOMIOCDOGSTATE, TSIOCDOGSTATE
1914 * inputs - device number, command, user space arg, filemode, user
1915 * credentials, return value
1916 * outputs - the return value propagated back by the lower level routines.
1921 bscv_ioctl(dev_t dev
, int cmd
, intptr_t arg
, int mode
, cred_t
*cred
, int *rvalp
)
1923 bscv_soft_state_t
*ssp
;
1927 instance
= DEVICETOINSTANCE(dev
);
1928 ssp
= ddi_get_soft_state(bscv_statep
, instance
);
1934 * The Combined Switch and Service Processor takes care of configuration
1935 * and control. The CSSP tells the BSC chip about it; therefore the
1936 * bscv driver doesn't send such configuration and control to the BSC.
1937 * Additionally Watchdog configuration is no longer done from userland
1943 case LOMIOCCLEARLOG
:
1951 case LOMIOCEVENTLOG
:
1963 * set the default result.
1968 if (ssp
->cssp_prog
) {
1970 } else if ((ssp
->prog_mode_only
|| ssp
->programming
) &&
1971 cmd
!= LOMIOCPROG
) {
1976 * Check that the caller has appropriate access permissions
1977 * (FWRITE set in mode) for those ioctls which change lom
1980 if (!(mode
& FWRITE
)) {
1989 /* Does not require write access */
1996 case LOMIOCDOGSTATE
:
1997 res
= bscv_ioc_dogstate(ssp
, arg
, mode
);
2001 res
= bscv_prog(ssp
, arg
, mode
);
2004 case LOMIOCPSUSTATE
:
2005 res
= bscv_ioc_psustate(ssp
, arg
, mode
);
2008 case LOMIOCFANSTATE
:
2009 res
= bscv_ioc_fanstate(ssp
, arg
, mode
);
2012 case LOMIOCFLEDSTATE
:
2013 res
= bscv_ioc_fledstate(ssp
, arg
, mode
);
2016 case LOMIOCLEDSTATE
:
2017 res
= bscv_ioc_ledstate(ssp
, arg
, mode
);
2021 res
= bscv_ioc_info(ssp
, arg
, mode
);
2025 res
= bscv_ioc_mread(ssp
, arg
, mode
);
2029 res
= bscv_ioc_volts(ssp
, arg
, mode
);
2033 res
= bscv_ioc_stats(ssp
, arg
, mode
);
2037 res
= bscv_ioc_temp(ssp
, arg
, mode
);
2041 res
= bscv_ioc_cons(ssp
, arg
, mode
);
2044 case LOMIOCEVENTLOG2
:
2045 res
= bscv_ioc_eventlog2(ssp
, arg
, mode
);
2049 res
= bscv_ioc_info2(ssp
, arg
, mode
);
2053 res
= bscv_ioc_test(ssp
, arg
, mode
);
2057 res
= bscv_ioc_mprog2(ssp
, arg
, mode
);
2061 res
= bscv_ioc_mread2(ssp
, arg
, mode
);
2065 BSCV_TRACE(ssp
, 'I', "bscv_ioctl", "Invalid IOCTL 0x%x", cmd
);
2073 * TSIOCDOGSTATE - indicate whether the alarm watchdog and reset
2074 * circuitry is enabled or not.
2077 bscv_ioc_dogstate(bscv_soft_state_t
*ssp
, intptr_t arg
, int mode
)
2079 lom_dogstate_t dogstate
;
2083 dogval
= bscv_get8_locked(ssp
, chan_general
, EBUS_IDX_WDOG_CTRL
, &res
);
2084 dogstate
.dog_enable
= (dogval
& EBUS_WDOG_ENABLE
) ? 1 : 0;
2085 dogstate
.reset_enable
= (dogval
& EBUS_WDOG_RST
) ? 1 : 0;
2086 dogstate
.dog_timeout
= bscv_get8_locked(ssp
, chan_general
,
2087 EBUS_IDX_WDOG_TIME
, &res
);
2090 (ddi_copyout((caddr_t
)&dogstate
,
2091 (caddr_t
)arg
, sizeof (dogstate
), mode
) < 0)) {
2098 * LOMIOCPSUSTATE - returns full information for 4 PSUs. All this
2099 * information is available from two bytes of LOMlite RAM, but if
2100 * on the first read it is noticed that two or more of the PSUs are
2101 * not present only 1 byte will be read subsequently.
2104 bscv_ioc_psustate(bscv_soft_state_t
*ssp
, intptr_t arg
, int mode
)
2106 lom_psudata_t psudata
;
2111 for (i
= 0; i
< MAX_PSUS
; i
++) {
2112 psustat
= bscv_get8_locked(ssp
, chan_general
,
2113 EBUS_IDX_PSU1_STAT
+ i
, &res
);
2114 psudata
.fitted
[i
] = psustat
& EBUS_PSU_PRESENT
;
2115 psudata
.output
[i
] = psustat
& EBUS_PSU_OUTPUT
;
2116 psudata
.supplyb
[i
] = psustat
& EBUS_PSU_INPUTB
;
2117 psudata
.supplya
[i
] = psustat
& EBUS_PSU_INPUTA
;
2118 psudata
.standby
[i
] = psustat
& EBUS_PSU_STANDBY
;
2121 if (ddi_copyout((caddr_t
)&psudata
, (caddr_t
)arg
, sizeof (psudata
),
2129 * LOMIOCFANSTATE - returns full information including speed for 4
2130 * fans and the minimum and maximum operating speeds for each fan as
2131 * stored in the READ ONLY EEPROM data. As this EEPROM data is set
2132 * at manufacture time, this data should only be read by the driver
2133 * once and stored locally.
2136 bscv_ioc_fanstate(bscv_soft_state_t
*ssp
, intptr_t arg
, int mode
)
2138 lom_fandata_t fandata
;
2143 bzero(&fandata
, sizeof (lom_fandata_t
));
2144 numfans
= EBUS_CONFIG_NFAN_DEC(bscv_get8_locked(ssp
,
2145 chan_general
, EBUS_IDX_CONFIG
, &res
));
2146 for (i
= 0; (i
< numfans
) && (res
== 0); i
++) {
2147 if (ssp
->fanspeed
[i
] != LOM_FAN_NOT_PRESENT
) {
2148 fandata
.fitted
[i
] = 1;
2149 fandata
.speed
[i
] = ssp
->fanspeed
[i
];
2150 fandata
.minspeed
[i
] = bscv_get8_cached(ssp
,
2151 EBUS_IDX_FAN1_LOW
+ i
);
2156 (ddi_copyout((caddr_t
)&fandata
, (caddr_t
)arg
, sizeof (fandata
),
2164 * LOMIOCFLEDSTATE - returns the state of the fault LED
2167 bscv_ioc_fledstate(bscv_soft_state_t
*ssp
, intptr_t arg
, int mode
)
2169 lom_fled_info_t fled_info
;
2173 fledstate
= bscv_get8_locked(ssp
, chan_general
, EBUS_IDX_ALARM
, &res
);
2175 /* Decode of 0x0F is off and 0x00-0x07 is on. */
2176 if (EBUS_ALARM_LED_DEC(fledstate
) == 0x0F) {
2179 /* has +1 here - not 2 as in the info ioctl */
2180 fled_info
.on
= EBUS_ALARM_LED_DEC(fledstate
) + 1;
2183 (ddi_copyout((caddr_t
)&fled_info
, (caddr_t
)arg
,
2184 sizeof (fled_info
), mode
) < 0)) {
2191 * LOMIOCLEDSTATE - returns the state of the requested LED
2194 bscv_ioc_ledstate(bscv_soft_state_t
*ssp
, intptr_t arg
, int mode
)
2196 lom_led_state_t led_state
;
2200 /* copy in arguments supplied */
2201 if (ddi_copyin((caddr_t
)arg
, (caddr_t
)&led_state
,
2202 sizeof (lom_led_state_t
), mode
) < 0) {
2207 * check if led index is -1, if so set it to max value for
2208 * this implementation.
2210 if (led_state
.index
== -1) {
2211 led_state
.index
= MAX_LED_ID
;
2214 /* is the index in a valid range */
2215 if ((led_state
.index
> MAX_LED_ID
) || (led_state
.index
< 0)) {
2216 led_state
.state
= LOM_LED_OUTOFRANGE
;
2218 /* read the relevant led info */
2219 fw_led_state
= bscv_get8_locked(ssp
, chan_general
,
2220 EBUS_IDX_LED1_STATUS
+ led_state
.index
, &res
);
2222 /* set the state values accordingly */
2223 switch (fw_led_state
) {
2224 case LOM_LED_STATE_OFF
:
2225 led_state
.state
= LOM_LED_OFF
;
2226 led_state
.colour
= LOM_LED_COLOUR_ANY
;
2228 case LOM_LED_STATE_ON_STEADY
:
2229 led_state
.state
= LOM_LED_ON
;
2230 led_state
.colour
= LOM_LED_COLOUR_ANY
;
2232 case LOM_LED_STATE_ON_FLASHING
:
2233 case LOM_LED_STATE_ON_SLOWFLASH
:
2234 led_state
.state
= LOM_LED_BLINKING
;
2235 led_state
.colour
= LOM_LED_COLOUR_ANY
;
2237 case LOM_LED_STATE_NOT_PRESENT
:
2238 led_state
.state
= LOM_LED_NOT_IMPLEMENTED
;
2239 led_state
.colour
= LOM_LED_COLOUR_NONE
;
2241 case LOM_LED_STATE_INACCESSIBLE
:
2242 case LOM_LED_STATE_STANDBY
:
2244 led_state
.state
= LOM_LED_ACCESS_ERROR
;
2245 led_state
.colour
= LOM_LED_COLOUR_NONE
;
2249 /* set the label info */
2250 (void) strcpy(led_state
.label
,
2251 ssp
->led_names
[led_state
.index
]);
2254 /* copy out lom_state */
2256 (ddi_copyout((caddr_t
)&led_state
, (caddr_t
)arg
,
2257 sizeof (lom_led_state_t
), mode
) < 0)) {
2264 * LOMIOCINFO - returns with a structure containing any information
2265 * stored on the LOMlite which a user should not need to access but
2266 * may be useful for diagnostic problems. The structure contains: the
2267 * serial escape character, alarm3 mode, version and checksum read from
2268 * RAM and the Product revision and ID read from EEPROM.
2271 bscv_ioc_info(bscv_soft_state_t
*ssp
, intptr_t arg
, int mode
)
2278 info
.ser_char
= bscv_get8_locked(ssp
, chan_general
, EBUS_IDX_ESCAPE
,
2280 info
.a3mode
= WATCHDOG
;
2281 info
.fver
= bscv_get8_locked(ssp
, chan_general
, EBUS_IDX_FW_REV
, &res
);
2282 csum
= bscv_get8_locked(ssp
, chan_general
, EBUS_IDX_CHECK_HI
, &res
)
2284 csum
|= bscv_get8_locked(ssp
, chan_general
, EBUS_IDX_CHECK_LO
, &res
);
2285 info
.fchksum
= csum
;
2286 info
.prod_rev
= bscv_get8_locked(ssp
, chan_general
, EBUS_IDX_MODEL_REV
,
2288 for (i
= 0; i
< sizeof (info
.prod_id
); i
++) {
2289 info
.prod_id
[i
] = bscv_get8_locked(ssp
,
2290 chan_general
, EBUS_IDX_MODEL_ID1
+ i
, &res
);
2292 if (bscv_get8_locked(ssp
, chan_general
, EBUS_IDX_ALARM
, &res
) &
2293 EBUS_ALARM_NOEVENTS
) {
2300 (ddi_copyout((caddr_t
)&info
, (caddr_t
)arg
, sizeof (info
),
2308 * LOMIOCMREAD - used to query the LOMlite configuration parameters
2311 bscv_ioc_mread(bscv_soft_state_t
*ssp
, intptr_t arg
, int mode
)
2318 for (i
= 0; i
< sizeof (mprog
.mod_id
); i
++) {
2319 mprog
.mod_id
[i
] = bscv_get8_locked(ssp
, chan_general
,
2320 EBUS_IDX_MODEL_ID1
+ i
, &res
);
2322 mprog
.mod_rev
= bscv_get8_locked(ssp
, chan_general
, EBUS_IDX_MODEL_REV
,
2324 mprog
.config
= bscv_get8_locked(ssp
, chan_general
, EBUS_IDX_CONFIG
,
2327 /* Read the fan calibration values */
2328 fanz
= sizeof (mprog
.fanhz
) / sizeof (mprog
.fanhz
[0]);
2329 for (i
= 0; i
< fanz
; i
++) {
2330 mprog
.fanhz
[i
] = bscv_get8_cached(ssp
,
2331 EBUS_IDX_FAN1_CAL
+ i
);
2332 mprog
.fanmin
[i
] = bscv_get8_cached(ssp
,
2333 EBUS_IDX_FAN1_LOW
+ i
);
2337 (ddi_copyout((caddr_t
)&mprog
, (caddr_t
)arg
, sizeof (mprog
),
2348 bscv_ioc_volts(bscv_soft_state_t
*ssp
, intptr_t arg
, int mode
)
2354 supply
= (bscv_get8_locked(ssp
, chan_general
, EBUS_IDX_SUPPLY_HI
, &res
)
2355 << 8) | bscv_get8_locked(ssp
, chan_general
, EBUS_IDX_SUPPLY_LO
,
2358 for (i
= 0; i
< ssp
->volts
.num
; i
++) {
2359 ssp
->volts
.status
[i
] = (supply
>> i
) & 1;
2363 (ddi_copyout((caddr_t
)&ssp
->volts
, (caddr_t
)arg
,
2364 sizeof (ssp
->volts
), mode
) < 0)) {
2374 bscv_ioc_stats(bscv_soft_state_t
*ssp
, intptr_t arg
, int mode
)
2380 status
= bscv_get8_locked(ssp
, chan_general
, EBUS_IDX_CBREAK_STATUS
,
2382 for (i
= 0; i
< ssp
->sflags
.num
; i
++) {
2383 ssp
->sflags
.status
[i
] = (int)((status
>> i
) & 1);
2387 (ddi_copyout((caddr_t
)&ssp
->sflags
, (caddr_t
)arg
,
2388 sizeof (ssp
->sflags
), mode
) < 0)) {
2398 bscv_ioc_temp(bscv_soft_state_t
*ssp
, intptr_t arg
, int mode
)
2406 bzero(&temps
, sizeof (temps
));
2408 for (i
= 0; i
< ssp
->temps
.num
; i
++) {
2409 if (ssp
->temps
.temp
[i
] != LOM_TEMP_STATE_NOT_PRESENT
) {
2410 temps
.temp
[idx
] = ssp
->temps
.temp
[i
];
2411 bcopy(ssp
->temps
.name
[i
], temps
.name
[idx
],
2412 sizeof (temps
.name
[idx
]));
2413 temps
.warning
[idx
] = ssp
->temps
.warning
[i
];
2414 temps
.shutdown
[idx
] = ssp
->temps
.shutdown
[i
];
2420 bcopy(ssp
->temps
.name_ov
, temps
.name_ov
, sizeof (temps
.name_ov
));
2421 temps
.num_ov
= ssp
->temps
.num_ov
;
2422 status_ov
= bscv_get8_locked(ssp
, chan_general
, EBUS_IDX_OTEMP_STATUS
,
2424 for (i
= 0; i
< ssp
->temps
.num_ov
; i
++) {
2425 ssp
->temps
.status_ov
[i
] = (status_ov
>> i
) & 1;
2429 (ddi_copyout((caddr_t
)&temps
, (caddr_t
)arg
, sizeof (temps
),
2440 bscv_ioc_cons(bscv_soft_state_t
*ssp
, intptr_t arg
, int mode
)
2446 bzero(&cbuf
, sizeof (cbuf
));
2447 datasize
= EBUS_IDX1_CONS_BUF_END
- EBUS_IDX1_CONS_BUF_START
+ 1;
2448 /* Ensure that we do not overfill cbuf and that it is NUL terminated */
2449 if (datasize
> (sizeof (cbuf
) - 1)) {
2450 datasize
= sizeof (cbuf
) - 1;
2452 bscv_rep_get8_locked(ssp
, chan_general
, (uint8_t *)cbuf
.lrbuf
,
2453 BSCVA(EBUS_CMD_SPACE1
, (EBUS_IDX1_CONS_BUF_END
- datasize
+ 1)),
2454 datasize
, DDI_DEV_AUTOINCR
, &res
);
2455 /* This is always within the array due to the checks above */
2456 cbuf
.lrbuf
[datasize
] = '\0';
2459 (ddi_copyout((caddr_t
)&cbuf
, (caddr_t
)arg
, sizeof (cbuf
),
2470 bscv_ioc_eventlog2(bscv_soft_state_t
*ssp
, intptr_t arg
, int mode
)
2472 lom_eventlog2_t
*eventlog2
;
2473 int events_recorded
;
2475 uint16_t next_offset
;
2479 eventlog2
= (lom_eventlog2_t
*)kmem_zalloc(sizeof (*eventlog2
),
2483 * First get number of events and level requested.
2486 if (ddi_copyin((caddr_t
)arg
, (caddr_t
)eventlog2
,
2487 sizeof (lom_eventlog2_t
), mode
) < 0) {
2488 kmem_free((void *)eventlog2
, sizeof (*eventlog2
));
2495 * OK we have full private access to the LOM now so loop
2496 * over the eventlog addr spaces until we get the required
2500 if (!bscv_window_setup(ssp
)) {
2503 kmem_free((void *)eventlog2
, sizeof (*eventlog2
));
2508 * Read count, next event ptr MSB,LSB. Note a read of count
2509 * is necessary to latch values for the next event ptr
2511 (void) bscv_get8(ssp
, chan_general
, EBUS_IDX_UNREAD_EVENTS
);
2512 next_offset
= bscv_get16(ssp
, chan_general
, EBUS_IDX_LOG_PTR_HI
);
2513 BSCV_TRACE(ssp
, 'I', "bscv_ioc_eventlog2", "log_ptr_hi 0x%x",
2516 events_recorded
= 0;
2518 while (events_recorded
< eventlog2
->num
) {
2520 * Working backwards - read an event at a time.
2521 * next_offset is one event on from where we want to be!
2522 * Decrement next_offset and maybe wrap to the end of the
2524 * Note the unsigned arithmetic, so check values first!
2526 if (next_offset
<= ssp
->eventlog_start
) {
2527 /* Wrap to the end of the buffer */
2528 next_offset
= ssp
->eventlog_start
+ ssp
->eventlog_size
;
2529 BSCV_TRACE(ssp
, 'I', "bscv_ioc_eventlog2", "wrapping"
2530 " around to end of buffer; next_offset 0x%x",
2533 next_offset
-= sizeof (event
);
2535 if (bscv_eerw(ssp
, next_offset
, (uint8_t *)&event
,
2536 sizeof (event
), B_FALSE
/* read */) != 0) {
2537 /* Fault reading data - stop */
2538 BSCV_TRACE(ssp
, 'I', "bscv_ioc_eventlog2", "read"
2539 " failure for offset 0x%x", next_offset
);
2544 if (bscv_is_null_event(ssp
, &event
)) {
2546 * No more events in this log so give up.
2548 BSCV_TRACE(ssp
, 'I', "bscv_ioc_eventlog2", "no more"
2549 " events left at offset 0x%x", next_offset
);
2554 * Are we interested in this event
2557 level
= bscv_level_of_event(&event
);
2558 if (level
<= eventlog2
->level
) {
2559 /* Arggh why the funny byte ordering 3, 2, 0, 1 */
2560 eventlog2
->code
[events_recorded
] =
2561 ((unsigned)event
.ev_event
|
2562 ((unsigned)event
.ev_subsys
<< 8) |
2563 ((unsigned)event
.ev_resource
<< 16) |
2564 ((unsigned)event
.ev_detail
<< 24));
2566 eventlog2
->time
[events_recorded
] =
2567 ((unsigned)event
.ev_data
[0] |
2568 ((unsigned)event
.ev_data
[1] << 8) |
2569 ((unsigned)event
.ev_data
[3] << 16) |
2570 ((unsigned)event
.ev_data
[2] << 24));
2572 bscv_build_eventstring(ssp
,
2573 &event
, eventlog2
->string
[events_recorded
],
2574 eventlog2
->string
[events_recorded
] +
2575 sizeof (eventlog2
->string
[events_recorded
]));
2580 eventlog2
->num
= events_recorded
;
2585 (ddi_copyout((caddr_t
)eventlog2
, (caddr_t
)arg
,
2586 sizeof (lom_eventlog2_t
), mode
) < 0)) {
2590 kmem_free((void *)eventlog2
, sizeof (lom_eventlog2_t
));
2598 bscv_ioc_info2(bscv_soft_state_t
*ssp
, intptr_t arg
, int mode
)
2605 bzero(&info2
, sizeof (info2
));
2607 (void) strncpy(info2
.escape_chars
, ssp
->escape_chars
,
2608 sizeof (info2
.escape_chars
));
2609 info2
.serial_events
= ssp
->reporting_level
| ssp
->serial_reporting
;
2610 info2
.a3mode
= WATCHDOG
;
2612 info2
.fver
= bscv_get8_locked(ssp
, chan_general
, EBUS_IDX_FW_REV
, &res
);
2613 csum
= bscv_get8_locked(ssp
, chan_general
, EBUS_IDX_CHECK_HI
, &res
)
2615 csum
|= bscv_get8_locked(ssp
, chan_general
, EBUS_IDX_CHECK_LO
, &res
);
2616 info2
.fchksum
= csum
;
2617 info2
.prod_rev
= bscv_get8_locked(ssp
, chan_general
,
2618 EBUS_IDX_MODEL_REV
, &res
);
2619 for (i
= 0; i
< sizeof (info2
.prod_id
); i
++) {
2620 info2
.prod_id
[i
] = bscv_get8_locked(ssp
, chan_general
,
2621 EBUS_IDX_MODEL_ID1
+ i
, &res
);
2623 info2
.serial_config
= bscv_get8_locked(ssp
, chan_general
,
2624 EBUS_IDX_SER_TIMEOUT
, &res
);
2625 if (bscv_get8_locked(ssp
, chan_general
, EBUS_IDX_CONFIG_MISC
, &res
) &
2626 EBUS_CONFIG_MISC_SECURITY_ENABLED
) {
2627 info2
.serial_config
|= LOM_SER_SECURITY
;
2629 if (bscv_get8_locked(ssp
, chan_general
, EBUS_IDX_CONFIG_MISC
, &res
) &
2630 EBUS_CONFIG_MISC_AUTO_CONSOLE
) {
2631 info2
.serial_config
|= LOM_SER_RETURN
;
2633 if (bscv_get8_locked(ssp
, chan_general
, EBUS_IDX_WDOG_CTRL
, &res
) &
2634 EBUS_WDOG_BREAK_DISABLE
) {
2635 info2
.serial_config
|= LOM_DISABLE_WDOG_BREAK
;
2637 info2
.baud_rate
= bscv_get8_locked(ssp
, chan_general
,
2638 EBUS_IDX_SER_BAUD
, &res
);
2639 info2
.serial_hw_config
=
2640 ((int)bscv_get8_locked(ssp
, chan_general
,
2641 EBUS_IDX_SER_CHARMODE
, &res
) |
2642 ((int)bscv_get8_locked(ssp
, chan_general
,
2643 EBUS_IDX_SER_FLOWCTL
, &res
) << 8) |
2644 ((int)bscv_get8_locked(ssp
, chan_general
,
2645 EBUS_IDX_SER_MODEMTYPE
, &res
) << 16));
2648 * There is no phone home support on the blade platform. We hardcode
2649 * FALSE and NUL for config and script respectively.
2651 info2
.phone_home_config
= B_FALSE
;
2652 info2
.phone_home_script
[0] = '\0';
2654 for (i
= 0; i
< ssp
->num_fans
; i
++) {
2655 (void) strcpy(info2
.fan_names
[i
], ssp
->fan_names
[i
]);
2659 (ddi_copyout((caddr_t
)&info2
, (caddr_t
)arg
, sizeof (info2
),
2670 bscv_ioc_test(bscv_soft_state_t
*ssp
, intptr_t arg
, int mode
)
2677 if (ddi_copyin((caddr_t
)arg
, (caddr_t
)&test
, sizeof (test
),
2683 * Extract num iterations.
2686 testarg
= (test
& 0xff00) >> 8;
2687 testnum
= test
& 0xff;
2689 BSCV_TRACE(ssp
, 'F', "bscv_ioc_test",
2690 "LOMIOCTEST data 0x%x (test 0x%x, arg 0x%x)",
2691 test
, (EBUS_IDX_SELFTEST0
+ testnum
), testarg
);
2693 switch (testnum
+ EBUS_IDX_SELFTEST0
) {
2699 case EBUS_IDX_SELFTEST0
: /* power on self-test result */
2700 case EBUS_IDX_SELFTEST1
: /* not used currently */
2701 case EBUS_IDX_SELFTEST2
: /* not used currently */
2702 case EBUS_IDX_SELFTEST3
: /* not used currently */
2703 case EBUS_IDX_SELFTEST4
: /* not used currently */
2704 case EBUS_IDX_SELFTEST5
: /* not used currently */
2705 case EBUS_IDX_SELFTEST6
: /* LED self-test */
2706 case EBUS_IDX_SELFTEST7
: /* platform-specific tests */
2709 /* Stop other things and then run the test */
2713 * Then we simply write the argument to the relevant register
2714 * and wait for the return code.
2716 bscv_put8(ssp
, chan_general
,
2717 EBUS_IDX_SELFTEST0
+ testnum
, testarg
);
2718 if (bscv_faulty(ssp
)) {
2721 /* Get hold of the SunVTS error code */
2722 test
= bscv_retcode(ssp
);
2729 BSCV_TRACE(ssp
, 'F', "bscv_ioc_test",
2730 "LOMIOCTEST status 0x%x, res 0x%x", test
, res
);
2732 (ddi_copyout((caddr_t
)&test
, (caddr_t
)arg
, sizeof (test
),
2743 bscv_ioc_mprog2(bscv_soft_state_t
*ssp
, intptr_t arg
, int mode
)
2745 lom2_mprog_t mprog2
;
2748 uint32_t eeprom_size
;
2751 if (ddi_copyin((caddr_t
)arg
, (caddr_t
)&mprog2
, sizeof (mprog2
),
2757 * Note that originally this was accessed as 255 byte pages
2758 * in address spaces 240-255. We have to emulate this behaviour.
2760 if ((mprog2
.addr_space
< 240) || (mprog2
.addr_space
> 255)) {
2766 /* Calculate required data location */
2768 base_addr
= (mprog2
.addr_space
- 240) * data_size
;
2770 eeprom_size
= bscv_get8(ssp
, chan_general
, EBUS_IDX_EEPROM_SIZE_KB
) *
2773 if (bscv_faulty(ssp
)) {
2776 } else if ((base_addr
+ data_size
) > eeprom_size
) {
2777 BSCV_TRACE(ssp
, 'M', "bscv_ioc_mprog2",
2778 "Request extends past end of eeprom");
2783 bscv_put8(ssp
, chan_general
, EBUS_IDX_CMD_RES
, EBUS_CMD_UNLOCK1
);
2784 if (bscv_faulty(ssp
)) {
2785 BSCV_TRACE(ssp
, 'M', "bscv_ioc_mprog2", "ML1 Write failed");
2790 bscv_put8(ssp
, chan_general
, EBUS_IDX_CMD_RES
, EBUS_CMD_UNLOCK2
);
2791 if (bscv_faulty(ssp
)) {
2792 BSCV_TRACE(ssp
, 'M', "bscv_ioc_mprog2", "ML2 Write failed");
2797 if (bscv_eerw(ssp
, base_addr
, &mprog2
.data
[0],
2798 data_size
, B_TRUE
/* write */) != 0) {
2802 /* Read a probe key to release the lock. */
2803 (void) bscv_get8(ssp
, chan_general
, EBUS_IDX_PROBEAA
);
2805 if (bscv_faulty(ssp
)) {
2817 bscv_ioc_mread2(bscv_soft_state_t
*ssp
, intptr_t arg
, int mode
)
2819 lom2_mprog_t mprog2
;
2822 uint32_t eeprom_size
;
2825 if (ddi_copyin((caddr_t
)arg
, (caddr_t
)&mprog2
, sizeof (mprog2
),
2831 * Need to stop the queue and then just read
2832 * the bytes blind to the relevant addresses.
2833 * Note that originally this was accessed as 255 byte pages
2834 * in address spaces 240-255. We have to emulate this behaviour.
2836 if ((mprog2
.addr_space
< 240) || (mprog2
.addr_space
> 255)) {
2842 /* Calculate required data location */
2844 base_addr
= (mprog2
.addr_space
- 240) * data_size
;
2845 eeprom_size
= bscv_get8(ssp
, chan_general
, EBUS_IDX_EEPROM_SIZE_KB
) *
2848 if (bscv_faulty(ssp
)) {
2851 } else if ((base_addr
+ data_size
) > eeprom_size
) {
2852 BSCV_TRACE(ssp
, 'M', "bscv_ioc_mread2",
2853 "Request extends past end of eeprom");
2858 if (bscv_eerw(ssp
, base_addr
, &mprog2
.data
[0],
2859 data_size
, B_FALSE
/* read */) != 0) {
2863 if (bscv_faulty(ssp
)) {
2869 (ddi_copyout((caddr_t
)&mprog2
, (caddr_t
)arg
, sizeof (mprog2
),
2877 bscv_get_state_changes(bscv_soft_state_t
*ssp
)
2879 int i
= STATUS_READ_LIMIT
;
2883 ASSERT(bscv_held(ssp
));
2885 while (i
-- && !ssp
->cssp_prog
) {
2886 /* Are there any changes to process? */
2887 change
= bscv_get8(ssp
, chan_general
, EBUS_IDX_STATE_CHNG
);
2888 change
&= EBUS_STATE_MASK
;
2892 /* Clarify the pending change */
2893 detail
= bscv_get8(ssp
, chan_general
, EBUS_IDX_EVENT_DETAIL
);
2895 bscv_status(ssp
, change
, detail
);
2898 BSCV_TRACE(ssp
, 'D', "bscv_get_state_changes",
2899 "loop index %d ssp->cssp_prog 0x%x", i
, ssp
->cssp_prog
);
2903 * *********************************************************************
2905 * *********************************************************************
2909 * function - bscv_event_daemon
2910 * description - Perform periodic lom tasks in a separate thread.
2911 * inputs - LOM soft state structure pointer
2915 bscv_event_daemon(void *arg
)
2917 bscv_soft_state_t
*ssp
= (void *)arg
;
2918 boolean_t do_events
;
2919 boolean_t do_status
;
2920 boolean_t do_nodename
;
2921 boolean_t do_watchdog
;
2924 clock_t poll_period
= BSC_EVENT_POLL_NORMAL
;
2927 BSCV_TRACE(ssp
, 'D', "bscv_event_daemon",
2928 "bscv_event_daemon: started");
2930 /* Acquire task daemon lock. */
2931 mutex_enter(&ssp
->task_mu
);
2933 ssp
->task_flags
|= TASK_ALIVE_FLG
;
2936 if ((ssp
->task_flags
& TASK_STOP_FLG
) != 0) {
2937 /* Stop request seen - terminate */
2940 if ((ssp
->task_flags
& TASK_PAUSE_FLG
) == 0) {
2941 /* Poll for events reported to the nexus */
2942 mutex_exit(&ssp
->task_mu
);
2943 /* Probe and Check faults */
2945 async_reg
= bscv_probe(ssp
, chan_general
, &fault
);
2946 BSCV_TRACE(ssp
, 'D', "bscv_event_daemon",
2947 "process event: async_reg 0x%x, fault 0x%x",
2951 /* Treat non-fault conditions */
2953 if (ssp
->cssp_prog
|| ssp
->prog_mode_only
) {
2955 * The BSC has become available again.
2958 ssp
->cssp_prog
= B_FALSE
;
2959 ssp
->prog_mode_only
= B_FALSE
;
2960 (void) bscv_attach_common(ssp
);
2961 } else if (fault_cnt
> 0) {
2962 /* Previous fault has cleared */
2963 bscv_clear_fault(ssp
);
2966 "!bscv_event_daemon previous fault "
2968 } else if (bscv_faulty(ssp
)) {
2969 /* Previous fault has cleared */
2970 bscv_clear_fault(ssp
);
2971 /* Sleep to avoid busy waiting */
2972 ssp
->event_sleep
= B_TRUE
;
2974 poll_period
= BSC_EVENT_POLL_NORMAL
;
2977 ssp
->status_change
= B_TRUE
;
2978 ssp
->event_waiting
= B_TRUE
;
2980 } else if (ssp
->cssp_prog
) {
2982 * Expect radio silence or error values
2983 * when the CSSP is upgrading the BSC firmware
2984 * so throw away any fault indication.
2987 } else if (fault_cnt
== BSC_PROBE_FAULT_LIMIT
) {
2988 /* Count previous faults and maybe fail */
2989 /* Declare the lom broken */
2990 bscv_set_fault(ssp
);
2991 poll_period
= BSC_EVENT_POLL_FAULTY
;
2993 "!bscv_event_daemon had faults probing "
2994 "lom - marking it as faulty.");
2996 * Increment fault_cnt to ensure that
2997 * next time we do not report a message
2998 * i.e. we drop out of the bottom
3000 fault_cnt
= BSC_PROBE_FAULT_LIMIT
+ 1;
3001 ssp
->event_sleep
= B_TRUE
;
3002 } else if (fault_cnt
< BSC_PROBE_FAULT_LIMIT
) {
3003 if (bscv_faulty(ssp
)) {
3004 poll_period
= BSC_EVENT_POLL_FAULTY
;
3006 * No recovery messages in this case
3007 * because there was never a fault
3012 /* Getting ready to explode */
3015 "!bscv_event_daemon had fault 0x%x",
3018 ssp
->event_sleep
= B_TRUE
;
3021 mutex_enter(&ssp
->task_mu
);
3024 #if defined(__i386) || defined(__amd64)
3026 * we have no platmod hook on Solaris x86 to report
3027 * a change to the nodename so we keep a copy so
3028 * we can detect a change and request that the bsc
3029 * be updated when appropriate.
3031 if (strcmp(ssp
->last_nodename
, utsname
.nodename
) != 0) {
3033 BSCV_TRACE(ssp
, 'X', "bscv_event_daemon",
3034 "utsname.nodename='%s' possible change detected",
3036 ssp
->nodename_change
= B_TRUE
;
3037 (void) strncpy(ssp
->last_nodename
, utsname
.nodename
,
3038 sizeof (ssp
->last_nodename
));
3039 /* enforce null termination */
3040 ssp
->last_nodename
[sizeof (ssp
->last_nodename
) - 1] =
3043 #endif /* __i386 || __amd64 */
3045 if (((ssp
->task_flags
& TASK_PAUSE_FLG
) == 0) &&
3046 fault_cnt
== 0 && ssp
->cssp_prog
== B_FALSE
&&
3047 (ssp
->event_waiting
|| ssp
->status_change
||
3048 ssp
->nodename_change
|| ssp
->watchdog_change
)) {
3050 do_events
= ssp
->event_waiting
;
3051 ssp
->event_waiting
= B_FALSE
;
3052 ssp
->task_flags
|= do_events
?
3053 TASK_EVENT_PENDING_FLG
: 0;
3054 do_status
= ssp
->status_change
;
3055 ssp
->status_change
= B_FALSE
;
3056 do_nodename
= ssp
->nodename_change
;
3057 ssp
->nodename_change
= B_FALSE
;
3058 do_watchdog
= ssp
->watchdog_change
;
3059 if (ssp
->watchdog_change
) {
3060 ssp
->watchdog_change
= B_FALSE
;
3063 mutex_exit(&ssp
->task_mu
);
3065 * We must not hold task_mu whilst processing
3066 * events because this can lead to priority
3067 * inversion and hence our interrupts getting
3072 bscv_event_process(ssp
, do_events
);
3075 BSCV_TRACE(ssp
, 'D', "bscv_event_daemon",
3076 "do_nodename task");
3077 bscv_setup_hostname(ssp
);
3080 BSCV_TRACE(ssp
, 'D', "bscv_event_daemon",
3081 "do_watchdog task");
3082 bscv_setup_watchdog(ssp
);
3085 * Pending status changes are dealt with last because
3086 * if we see that the BSC is about to be programmed,
3087 * then it will expect us to to quiescent in the
3088 * first second so it can cleanly tear down its comms
3089 * protocols; this takes ~100 ms.
3092 bscv_get_state_changes(ssp
);
3094 if (bscv_session_error(ssp
)) {
3096 * Had fault during event session. We always
3097 * sleep after one of these because there
3098 * may be a problem with the lom which stops
3099 * us doing useful work in the event daemon.
3100 * If we don't sleep then we may livelock.
3102 BSCV_TRACE(ssp
, 'D', "bscv_event_daemon",
3103 "had session error - sleeping");
3104 ssp
->event_sleep
= B_TRUE
;
3108 mutex_enter(&ssp
->task_mu
);
3110 if (ssp
->task_flags
& TASK_EVENT_PENDING_FLG
) {
3112 * We have read any events which were
3113 * pending. Let the consumer continue.
3114 * Ignore the race condition with new events
3115 * arriving - just let the consumer have
3116 * whatever was pending when they asked.
3118 ssp
->event_active_count
++;
3119 ssp
->task_flags
&= ~(TASK_EVENT_PENDING_FLG
|
3120 TASK_EVENT_CONSUMER_FLG
);
3121 cv_broadcast(&ssp
->task_evnt_cv
);
3124 /* There was nothing to do - sleep */
3125 ssp
->event_sleep
= B_TRUE
;
3128 if (ssp
->event_sleep
) {
3129 ssp
->task_flags
|= TASK_SLEEPING_FLG
;
3130 /* Sleep until there is something to do */
3131 (void) cv_reltimedwait(&ssp
->task_cv
,
3132 &ssp
->task_mu
, poll_period
, TR_CLOCK_TICK
);
3133 ssp
->task_flags
&= ~TASK_SLEEPING_FLG
;
3134 ssp
->event_sleep
= B_FALSE
;
3138 if (ssp
->task_flags
& TASK_EVENT_CONSUMER_FLG
) {
3140 * We are going away so wake up any event consumer.
3141 * Pretend that any pending events have been processed.
3143 ssp
->event_active_count
+= 2;
3144 cv_broadcast(&ssp
->task_evnt_cv
);
3147 ASSERT(!(ssp
->task_flags
& TASK_EVENT_PENDING_FLG
));
3149 ~(TASK_STOP_FLG
| TASK_ALIVE_FLG
| TASK_EVENT_CONSUMER_FLG
);
3150 mutex_exit(&ssp
->task_mu
);
3152 BSCV_TRACE(ssp
, 'D', "bscv_event_daemon",
3157 * function - bscv_start_event_daemon
3158 * description - Create the event daemon thread.
3159 * inputs - LOM soft state structure pointer
3163 bscv_start_event_daemon(bscv_soft_state_t
*ssp
)
3165 if (ssp
->progress
& BSCV_THREAD
)
3168 /* Start the event thread after the queue has started */
3169 (void) thread_create(NULL
, 0, (void (*)())bscv_event_daemon
, ssp
,
3170 0, &p0
, TS_RUN
, minclsyspri
);
3172 ssp
->progress
|= BSCV_THREAD
;
3176 * function - bscv_stop_event_daemon
3177 * description - Attempt to stop the event daemon thread.
3178 * inputs - LOM soft state structure pointer
3179 * outputs - DDI_SUCCESS OR DDI_FAILURE
3182 bscv_stop_event_daemon(bscv_soft_state_t
*ssp
)
3185 int res
= DDI_SUCCESS
;
3187 mutex_enter(&ssp
->task_mu
);
3189 /* Wait for task daemon to stop running. */
3191 ((ssp
->task_flags
& TASK_ALIVE_FLG
) && try < 10);
3193 /* Signal that the task daemon should stop */
3194 ssp
->task_flags
|= TASK_STOP_FLG
;
3195 cv_signal(&ssp
->task_cv
);
3196 /* Release task daemon lock. */
3197 mutex_exit(&ssp
->task_mu
);
3199 * TODO - when the driver is modified to support
3200 * system suspend or if this routine gets called
3201 * during panic we should use drv_usecwait() rather
3202 * than delay in those circumstances.
3204 delay(drv_usectohz(1000000));
3205 mutex_enter(&ssp
->task_mu
);
3208 if (ssp
->task_flags
& TASK_ALIVE_FLG
) {
3211 mutex_exit(&ssp
->task_mu
);
3217 * function - bscv_pause_event_daemon
3218 * description - Attempt to pause the event daemon thread.
3219 * inputs - LOM soft state structure pointer
3220 * outputs - DDI_SUCCESS OR DDI_FAILURE
3223 bscv_pause_event_daemon(bscv_soft_state_t
*ssp
)
3227 if (!(ssp
->progress
& BSCV_THREAD
)) {
3229 return (BSCV_SUCCESS
);
3232 BSCV_TRACE(ssp
, 'D', "bscv_pause_event_daemon",
3233 "Attempting to pause event daemon");
3235 mutex_enter(&ssp
->task_mu
);
3236 /* Signal that the task daemon should pause */
3237 ssp
->task_flags
|= TASK_PAUSE_FLG
;
3239 /* Wait for task daemon to pause. */
3241 (!(ssp
->task_flags
& TASK_SLEEPING_FLG
) &&
3242 (ssp
->task_flags
& TASK_ALIVE_FLG
) &&
3246 ssp
->task_flags
|= TASK_PAUSE_FLG
;
3247 cv_signal(&ssp
->task_cv
);
3248 /* Release task daemon lock. */
3249 mutex_exit(&ssp
->task_mu
);
3250 delay(drv_usectohz(1000000));
3251 mutex_enter(&ssp
->task_mu
);
3253 if ((ssp
->task_flags
& TASK_SLEEPING_FLG
) ||
3254 !(ssp
->task_flags
& TASK_ALIVE_FLG
)) {
3255 mutex_exit(&ssp
->task_mu
);
3256 BSCV_TRACE(ssp
, 'D', "bscv_pause_event_daemon",
3257 "Pause event daemon - success");
3258 return (BSCV_SUCCESS
);
3260 mutex_exit(&ssp
->task_mu
);
3261 BSCV_TRACE(ssp
, 'D', "bscv_pause_event_daemon",
3262 "Pause event daemon - failed");
3263 return (BSCV_FAILURE
);
3267 * function - bscv_resume_event_daemon
3268 * description - Resumethe event daemon thread.
3269 * inputs - LOM soft state structure pointer
3273 bscv_resume_event_daemon(bscv_soft_state_t
*ssp
)
3275 if (!(ssp
->progress
& BSCV_THREAD
)) {
3280 mutex_enter(&ssp
->task_mu
);
3281 /* Allow the task daemon to resume event processing */
3282 ssp
->task_flags
&= ~TASK_PAUSE_FLG
;
3283 cv_signal(&ssp
->task_cv
);
3284 mutex_exit(&ssp
->task_mu
);
3286 BSCV_TRACE(ssp
, 'D', "bscv_pause_event_daemon",
3287 "Event daemon resumed");
3291 * function - bscv_event_process
3292 * description - process (report) events
3293 * inputs - Soft state ptr, process event request
3297 bscv_event_process(bscv_soft_state_t
*ssp
, boolean_t do_events
)
3302 /* Raw values read from the lom */
3310 * Read count, next event ptr MSB,LSB. Note a read of count
3311 * latches values for the next event ptr
3313 evcount
= bscv_get8(ssp
, chan_general
, EBUS_IDX_UNREAD_EVENTS
);
3314 logptr
= bscv_get16(ssp
, chan_general
, EBUS_IDX_LOG_PTR_HI
);
3316 /* Sanity check the values from the lom */
3317 count
= bscv_event_validate(ssp
, logptr
, evcount
);
3321 * Nothing to do - or badly configured event log.
3322 * We really do not want to touch the lom in this
3323 * case because any data that we access may be bad!
3324 * This differs from zero because if we have zero
3325 * to read the lom probably things that unread is
3326 * non-zero and we want that to be set to zero!
3327 * Signal event fault to make the thread wait
3328 * before attempting to re-read the log.
3330 ssp
->event_sleep
= B_TRUE
;
3334 if (ssp
->event_fault_reported
) {
3335 /* Clear down any old status - things are fixed */
3336 cmn_err(CE_NOTE
, "Event pointer fault recovered.");
3337 ssp
->event_fault_reported
= B_FALSE
;
3340 /* Compute the first entry that we need to read. */
3341 currptr
= logptr
- ssp
->eventlog_start
;
3342 currptr
+= ssp
->eventlog_size
;
3343 currptr
-= (count
* sizeof (event
));
3344 currptr
%= ssp
->eventlog_size
;
3345 currptr
+= ssp
->eventlog_start
;
3347 BSCV_TRACE(ssp
, 'E', "bscv_event_process",
3348 "processing %d events from 0x%x in 0x%x:0x%x",
3350 ssp
->eventlog_start
,
3351 ssp
->eventlog_start
+ ssp
->eventlog_size
);
3353 for (; count
> 0; count
--) {
3354 /* Ensure window is positioned correctly */
3355 if (bscv_eerw(ssp
, currptr
, (uint8_t *)&event
,
3356 sizeof (event
), B_FALSE
/* read */) != 0) {
3357 /* Fault reading data - stop */
3361 bscv_event_process_one(ssp
, &event
);
3362 bscv_sysevent(ssp
, &event
);
3364 currptr
+= sizeof (event
);
3365 if (currptr
>= ssp
->eventlog_start
+
3366 ssp
->eventlog_size
) {
3367 currptr
= ssp
->eventlog_start
;
3371 * Clear event count - write the evcount value to remove that
3372 * many from the unread total.
3373 * Adjust the value to reflect how many we have left to
3374 * read just in case we had a failure reading events.
3378 ASSERT(logptr
== currptr
);
3379 } else if (count
> evcount
) {
3384 bscv_put8(ssp
, chan_general
, EBUS_IDX_UNREAD_EVENTS
, evcount
);
3385 /* Remember where we were for next time */
3386 ssp
->oldeeptr
= currptr
;
3387 ssp
->oldeeptr_valid
= B_TRUE
;
3394 * function - bscv_event_validate
3395 * description - validate the event data supplied by the lom and determine
3396 * how many (if any) events to read.
3397 * This function performs complex checks to ensure that
3398 * events are not lost due to lom resets or host resets.
3399 * A combination of lom reset and host reset (i.e. power fail)
3400 * may cause some events to not be reported.
3401 * inputs - Soft state ptr, next event pointer, number of unread events.
3402 * outputs - the number of events to read. -1 on error.
3403 * zero is a valid value because it forces the loms unread
3404 * count to be cleared.
3407 bscv_event_validate(bscv_soft_state_t
*ssp
, uint32_t newptr
, uint8_t unread
)
3412 if (!bscv_window_setup(ssp
)) {
3413 /* Problem with lom eeprom setup we cannot do anything */
3417 /* Sanity check the event pointers */
3418 if ((newptr
< ssp
->eventlog_start
) ||
3419 (newptr
>= (ssp
->eventlog_start
+ ssp
->eventlog_size
))) {
3420 if (!ssp
->event_fault_reported
) {
3421 cmn_err(CE_WARN
, "Event pointer out of range. "
3422 "Cannot read events.");
3423 ssp
->event_fault_reported
= B_TRUE
;
3427 oldptr
= ssp
->oldeeptr
;
3428 /* Now sanity check log pointer against count */
3429 if (newptr
< oldptr
) {
3431 * Must have wrapped add eventlog_size to get the
3432 * correct relative values - this makes the checks
3435 newptr
+= ssp
->eventlog_size
;
3437 if (!ssp
->oldeeptr_valid
) {
3438 /* We have just started up - we have to trust lom */
3440 } else if ((unread
== 0) && (newptr
== oldptr
)) {
3441 /* Nothing to do - we were just polling */
3443 } else if (oldptr
+ (unread
* sizeof (lom_event_t
)) == newptr
) {
3444 /* Ok - got as many events as we expected */
3446 } else if (oldptr
+ (unread
* sizeof (lom_event_t
)) > newptr
) {
3448 * Errrm more messages than there should have been.
3450 * 1. the event log has filled - we have been
3451 * away for a long time
3452 * 2. software bug in lom or driver.
3453 * 3. something that I haven't thought of!
3454 * Always warn about this we should really never
3457 count
= (newptr
- oldptr
) / sizeof (lom_event_t
);
3458 BSCV_TRACE(ssp
, 'E', "bscv_event_process",
3459 "bscv_event_process: lom reported "
3460 "more events (%d) than expected (%d).",
3462 cmn_err(CE_CONT
, "only processing %d events", count
);
3464 /* Less messages - perhaps the lom has been reset */
3465 count
= (newptr
- oldptr
) / sizeof (lom_event_t
);
3466 BSCV_TRACE(ssp
, 'E', "bscv_event_process",
3467 "lom reported less events (%d) than expected (%d)"
3468 " - the lom may have been reset",
3471 /* Whatever happens only read a maximum of 255 entries */
3472 if ((count
>= 0xff)) {
3474 "bscv_event_process: too many events (%d) to "
3475 "process - some may have been lost", count
);
3482 * function - bscv_event_process_one
3483 * description - reports on state changes to the host.
3485 * inputs - LOM soft state structure pointer.
3491 bscv_event_process_one(bscv_soft_state_t
*ssp
, lom_event_t
*event
)
3497 if (bscv_is_null_event(ssp
, event
)) {
3498 /* Cleared entry - do not report it */
3502 level
= bscv_level_of_event(event
);
3509 case EVENT_LEVEL_FATAL
:
3510 case EVENT_LEVEL_FAULT
:
3515 bscv_build_eventstring(ssp
, event
, eventstr
, eventstr
+
3518 if (level
<= ssp
->reporting_level
) {
3520 * The message is important enough to be shown on the console
3521 * as well as the log.
3523 cmn_err(msg_type
, "%s", eventstr
);
3526 * The message goes only to the log.
3528 cmn_err(msg_type
, "!%s", eventstr
);
3535 * The BSC represents times as seconds since epoch 1970. Currently it gives
3536 * us 32 bits, unsigned. In the future this might change to a 64-bit count,
3537 * to allow a greater range.
3539 * Timestamp values below BSC_TIME_SANITY do not represent an absolute time,
3540 * but instead represent an offset from the last reset. This must be
3541 * borne in mind by output routines.
3544 typedef uint32_t bsctime_t
;
3546 #define BSC_TIME_SANITY 1000000000
3549 * render a formatted time for display
3553 bscv_event_snprintgmttime(char *buf
, size_t bufsz
, todinfo_t t
)
3557 /* tod_year is base 1900 so this code needs to adjust */
3558 year
= 1900 + t
.tod_year
;
3560 return (snprintf(buf
, bufsz
, "%04d-%02d-%02d %02d:%02d:%02dZ",
3561 year
, t
.tod_month
, t
.tod_day
, t
.tod_hour
,
3562 t
.tod_min
, t
.tod_sec
));
3566 * function - bscv_build_eventstring
3567 * description - reports on state changes to the host.
3569 * inputs - LOM soft state structure pointer.
3575 bscv_build_eventstring(bscv_soft_state_t
*ssp
, lom_event_t
*event
,
3576 char *buf
, char *bufend
)
3582 BSCV_TRACE(ssp
, 'S', "bscv_build_eventstring", "event %2x%2x%2x%2x",
3583 event
->ev_subsys
, event
->ev_event
,
3584 event
->ev_resource
, event
->ev_detail
);
3585 BSCV_TRACE(ssp
, 'S', "bscv_build_eventstring", "time %2x%2x%2x%2x",
3586 event
->ev_data
[0], event
->ev_data
[1],
3587 event
->ev_data
[2], event
->ev_data
[3]);
3590 * We accept bad subsystems and event type codes here.
3591 * The code decodes as much as possible and then produces
3594 subsystem
= EVENT_DECODE_SUBSYS(event
->ev_subsys
);
3595 eventtype
= event
->ev_event
;
3598 bsctm
= (((uint32_t)event
->ev_data
[0]) << 24) |
3599 (((uint32_t)event
->ev_data
[1]) << 16) |
3600 (((uint32_t)event
->ev_data
[2]) << 8) |
3601 ((uint32_t)event
->ev_data
[3]);
3602 if (bsctm
< BSC_TIME_SANITY
) {
3604 buf
+= snprintf(buf
, bufend
-buf
, "+P%dd%02dh%02dm%02ds",
3605 (int)(bsctm
/86400), (int)(bsctm
/3600%24),
3606 (int)(bsctm
/60%60), (int)(bsctm
%60));
3609 mutex_enter(&tod_lock
);
3610 buf
+= bscv_event_snprintgmttime(buf
, bufend
-buf
,
3612 mutex_exit(&tod_lock
);
3614 buf
+= snprintf(buf
, bufend
-buf
, " ");
3618 (sizeof (eventSubsysStrings
)/sizeof (*eventSubsysStrings
))) {
3619 buf
+= snprintf(buf
, bufend
- buf
, "%s",
3620 eventSubsysStrings
[subsystem
]);
3622 buf
+= snprintf(buf
, bufend
- buf
,
3623 "unknown subsystem %d ", subsystem
);
3627 switch (subsystem
) {
3628 case EVENT_SUBSYS_ALARM
:
3629 case EVENT_SUBSYS_TEMP
:
3630 case EVENT_SUBSYS_OVERTEMP
:
3631 case EVENT_SUBSYS_FAN
:
3632 case EVENT_SUBSYS_SUPPLY
:
3633 case EVENT_SUBSYS_BREAKER
:
3634 case EVENT_SUBSYS_PSU
:
3635 buf
+= snprintf(buf
, bufend
- buf
, "%d ", event
->ev_resource
);
3637 case EVENT_SUBSYS_LED
:
3638 buf
+= snprintf(buf
, bufend
- buf
, "%s ", bscv_get_label(
3639 ssp
->led_names
, MAX_LED_ID
, event
->ev_resource
- 1));
3646 if (event
->ev_subsys
& EVENT_MASK_FAULT
) {
3647 if (event
->ev_subsys
& EVENT_MASK_FATAL
) {
3648 buf
+= snprintf(buf
, bufend
- buf
, "FATAL FAULT: ");
3650 buf
+= snprintf(buf
, bufend
- buf
, "FAULT: ");
3656 (sizeof (eventTypeStrings
)/sizeof (*eventTypeStrings
))) {
3657 buf
+= snprintf(buf
, bufend
- buf
, "%s",
3658 eventTypeStrings
[eventtype
]);
3660 buf
+= snprintf(buf
, bufend
- buf
,
3661 "unknown event 0x%02x%02x%02x%02x",
3662 event
->ev_subsys
, event
->ev_event
,
3663 event
->ev_resource
, event
->ev_detail
);
3667 switch (subsystem
) {
3668 case EVENT_SUBSYS_TEMP
:
3669 if ((eventtype
!= EVENT_RECOVERED
) &&
3670 eventtype
!= EVENT_DEVICE_INACCESSIBLE
) {
3671 buf
+= snprintf(buf
, bufend
- buf
, " - %d degC",
3672 (int8_t)event
->ev_detail
);
3675 case EVENT_SUBSYS_FAN
:
3676 if (eventtype
== EVENT_FAILED
) {
3677 buf
+= snprintf(buf
, bufend
- buf
,
3678 " %d%%", event
->ev_detail
);
3681 case EVENT_SUBSYS_LOM
:
3682 switch (eventtype
) {
3683 case EVENT_FLASH_DOWNLOAD
:
3684 buf
+= snprintf(buf
, bufend
- buf
,
3685 ": v%d.%d to v%d.%d",
3686 (event
->ev_resource
>> 4),
3687 (event
->ev_resource
& 0x0f),
3688 (event
->ev_detail
>> 4),
3689 (event
->ev_detail
& 0x0f));
3691 case EVENT_WATCHDOG_TRIGGER
:
3692 buf
+= snprintf(buf
, bufend
- buf
,
3693 event
->ev_detail
? "- soft" : " - hard");
3695 case EVENT_UNEXPECTED_RESET
:
3696 if (event
->ev_detail
&
3697 LOM_UNEXPECTEDRESET_MASK_BADTRAP
) {
3698 buf
+= snprintf(buf
, bufend
- buf
,
3699 " - unclaimed exception 0x%x",
3701 ~LOM_UNEXPECTEDRESET_MASK_BADTRAP
);
3705 switch (event
->ev_detail
) {
3706 case LOM_RESET_DETAIL_BYUSER
:
3707 buf
+= snprintf(buf
, bufend
- buf
, " by user");
3709 case LOM_RESET_DETAIL_REPROGRAMMING
:
3710 buf
+= snprintf(buf
, bufend
- buf
,
3711 " after flash download");
3714 buf
+= snprintf(buf
, bufend
- buf
,
3715 " - unknown reason");
3723 case EVENT_SUBSYS_LED
:
3724 switch (event
->ev_detail
) {
3725 case LOM_LED_STATE_OFF
:
3726 buf
+= snprintf(buf
, bufend
- buf
, ": OFF");
3728 case LOM_LED_STATE_ON_STEADY
:
3729 buf
+= snprintf(buf
, bufend
- buf
, ": ON");
3731 case LOM_LED_STATE_ON_FLASHING
:
3732 case LOM_LED_STATE_ON_SLOWFLASH
:
3733 buf
+= snprintf(buf
, bufend
- buf
, ": BLINKING");
3735 case LOM_LED_STATE_INACCESSIBLE
:
3736 buf
+= snprintf(buf
, bufend
- buf
, ": inaccessible");
3738 case LOM_LED_STATE_STANDBY
:
3739 buf
+= snprintf(buf
, bufend
- buf
, ": standby");
3741 case LOM_LED_STATE_NOT_PRESENT
:
3742 buf
+= snprintf(buf
, bufend
- buf
, ": not present");
3745 buf
+= snprintf(buf
, bufend
- buf
, ": 0x%x",
3746 event
->ev_resource
);
3750 case EVENT_SUBSYS_USER
:
3751 switch (eventtype
) {
3752 case EVENT_USER_ADDED
:
3753 case EVENT_USER_REMOVED
:
3754 case EVENT_USER_PERMSCHANGED
:
3755 case EVENT_USER_LOGIN
:
3756 case EVENT_USER_PASSWORD_CHANGE
:
3757 case EVENT_USER_LOGINFAIL
:
3758 case EVENT_USER_LOGOUT
:
3759 buf
+= snprintf(buf
, bufend
- buf
, " %d",
3760 event
->ev_resource
);
3765 case EVENT_SUBSYS_PSU
:
3766 if (event
->ev_detail
& LOM_PSU_NOACCESS
) {
3767 buf
+= snprintf(buf
, bufend
- buf
, " - inaccessible");
3768 } else if ((event
->ev_detail
& LOM_PSU_STATUS_MASK
)
3769 == LOM_PSU_STATUS_MASK
) {
3770 buf
+= snprintf(buf
, bufend
- buf
, " - OK");
3772 buf
+= snprintf(buf
, bufend
- buf
, " -");
3774 * If both inputs are seen to have failed then simply
3775 * indicate that the PSU input has failed
3777 if (!(event
->ev_detail
&
3778 (LOM_PSU_INPUT_A_OK
| LOM_PSU_INPUT_B_OK
))) {
3779 buf
+= snprintf(buf
, bufend
- buf
, " Input");
3781 /* At least one input is ok */
3782 if (!(event
->ev_detail
& LOM_PSU_INPUT_A_OK
)) {
3783 buf
+= snprintf(buf
, bufend
- buf
,
3786 if (!(event
->ev_detail
& LOM_PSU_INPUT_B_OK
)) {
3787 buf
+= snprintf(buf
, bufend
- buf
,
3791 * Only flag an output error if an input is
3794 if (!(event
->ev_detail
& LOM_PSU_OUTPUT_OK
)) {
3795 buf
+= snprintf(buf
, bufend
- buf
,
3799 buf
+= snprintf(buf
, bufend
- buf
, " failed");
3802 case EVENT_SUBSYS_NONE
:
3803 if (eventtype
== EVENT_FAULT_LED
) {
3804 switch (event
->ev_detail
) {
3806 buf
+= snprintf(buf
, bufend
- buf
, " - ON");
3809 buf
+= snprintf(buf
, bufend
- buf
, " - OFF");
3812 buf
+= snprintf(buf
, bufend
- buf
,
3813 " - %dHz", event
->ev_detail
);
3818 case EVENT_SUBSYS_HOST
:
3819 if (eventtype
== EVENT_BOOTMODE_CHANGE
) {
3820 switch (event
->ev_detail
&
3821 ~EBUS_BOOTMODE_FORCE_CONSOLE
) {
3822 case EBUS_BOOTMODE_FORCE_NOBOOT
:
3823 buf
+= snprintf(buf
, bufend
- buf
,
3826 case EBUS_BOOTMODE_RESET_DEFAULT
:
3827 buf
+= snprintf(buf
, bufend
- buf
,
3828 " - reset defaults");
3830 case EBUS_BOOTMODE_FULLDIAG
:
3831 buf
+= snprintf(buf
, bufend
- buf
,
3834 case EBUS_BOOTMODE_SKIPDIAG
:
3835 buf
+= snprintf(buf
, bufend
- buf
,
3842 if (eventtype
== EVENT_SCC_STATUS
) {
3843 switch (event
->ev_detail
) {
3845 buf
+= snprintf(buf
, bufend
- buf
,
3849 buf
+= snprintf(buf
, bufend
- buf
,
3863 if (event
->ev_subsys
& EVENT_MASK_SHUTDOWN_REQD
) {
3864 buf
+= snprintf(buf
, bufend
- buf
, " - shutdown req'd");
3867 buf
+= snprintf(buf
, bufend
- buf
, "\n");
3869 if (buf
>= bufend
) {
3870 /* Ensure newline at end of string */
3874 cmn_err(CE_WARN
, "!bscv_build_eventstring: buffer too small!");
3880 * function - bscv_level_of_event
3881 * description - This routine determines which level an event should be
3883 * inputs - lom event structure pointer
3884 * outputs - event level.
3887 bscv_level_of_event(lom_event_t
*event
)
3891 * This is the same criteria that the firmware uses except we
3892 * log the fault led on as being EVENT_LEVEL_FAULT
3894 if (EVENT_DECODE_SUBSYS(event
->ev_subsys
) == EVENT_SUBSYS_USER
) {
3895 level
= EVENT_LEVEL_USER
;
3896 } else if ((EVENT_DECODE_SUBSYS(event
->ev_subsys
) ==
3897 EVENT_SUBSYS_ALARM
) && (event
->ev_event
== EVENT_STATE_ON
)) {
3898 level
= EVENT_LEVEL_FAULT
;
3899 } else if ((EVENT_DECODE_SUBSYS(event
->ev_subsys
) ==
3900 EVENT_SUBSYS_NONE
) &&
3901 (event
->ev_event
== EVENT_FAULT_LED
) &&
3902 (event
->ev_detail
!= 0xff)) {
3903 level
= EVENT_LEVEL_FAULT
;
3904 } else if ((EVENT_DECODE_SUBSYS(event
->ev_subsys
) ==
3905 EVENT_SUBSYS_LOM
) && event
->ev_event
== EVENT_TIME_REFERENCE
) {
3906 level
= EVENT_LEVEL_NOTICE
;
3907 } else if (event
->ev_event
== EVENT_RECOVERED
) {
3909 * All recovery messages need to be reported to the console
3910 * because during boot, the faults which occurred whilst
3911 * Solaris was not running are relayed to the console. There
3912 * is a case whereby a fatal fault (eg. over temp) could
3913 * have occurred and then recovered. The recovery condition
3914 * needs to be reported so the user doesn't think that the
3915 * failure (over temp) is still present.
3917 level
= EVENT_LEVEL_FAULT
;
3918 } else if (EVENT_DECODE_FAULT(event
->ev_subsys
) == 0) {
3919 /* None of FAULT, FATAL or SHUTDOWN REQD are set */
3920 level
= EVENT_LEVEL_NOTICE
;
3921 } else if (EVENT_DECODE_FAULT(event
->ev_subsys
) == EVENT_MASK_FAULT
) {
3922 /* Only FAULT set i.e not FATAL or SHUTDOWN REQD */
3923 level
= EVENT_LEVEL_FAULT
;
3925 level
= EVENT_LEVEL_FATAL
;
3932 * function - bscv_status
3933 * description - This routine is called when any change in the LOMlite2 status
3934 * is indicated by the status registers.
3936 * inputs - LOM soft state structure pointer
3941 bscv_status(bscv_soft_state_t
*ssp
, uint8_t state_chng
, uint8_t dev_no
)
3946 ASSERT(bscv_held(ssp
));
3948 BSCV_TRACE(ssp
, 'D', "bscv_status", "state_chng 0x%x dev_no 0x%x",
3949 state_chng
, dev_no
);
3952 * The device that has changed is given by the state change
3953 * register and the event detail register so react
3957 if (state_chng
== EBUS_STATE_NOTIFY
) {
3959 * The BSC is indicating a self state change
3961 if (dev_no
== EBUS_DETAIL_FLASH
) {
3962 ssp
->cssp_prog
= B_TRUE
;
3963 BSCV_TRACE(ssp
, 'D', "bscv_status",
3964 "ssp->cssp_prog changed to 0x%x",
3967 * It takes the BSC at least 100 ms to
3968 * clear down the comms protocol.
3969 * We back-off from talking to the
3970 * BSC during this period.
3972 delay(BSC_EVENT_POLL_NORMAL
);
3973 BSCV_TRACE(ssp
, 'D', "bscv_status",
3975 } else if (dev_no
== EBUS_DETAIL_RESET
) {
3979 BSCV_TRACE(ssp
, 'D', "bscv_status",
3980 "BSC reset occured, re-synching");
3981 (void) bscv_attach_common(ssp
);
3982 BSCV_TRACE(ssp
, 'D', "bscv_status",
3983 "completed attach_common");
3988 if ((state_chng
& EBUS_STATE_FAN
) && ((dev_no
- 1) < MAX_FANS
)) {
3989 fanspeed
= bscv_get8(ssp
, chan_general
,
3990 EBUS_IDX_FAN1_SPEED
+ dev_no
- 1);
3992 * Only remember fanspeeds which are real values or
3993 * NOT PRESENT values.
3995 if ((fanspeed
<= LOM_FAN_MAX_SPEED
) ||
3996 (fanspeed
== LOM_FAN_NOT_PRESENT
)) {
3997 ssp
->fanspeed
[dev_no
- 1] = fanspeed
;
4001 if ((state_chng
& EBUS_STATE_PSU
) && ((dev_no
- 1) < MAX_PSUS
)) {
4002 (void) bscv_get8(ssp
, chan_general
,
4003 EBUS_IDX_PSU1_STAT
+ dev_no
- 1);
4006 if (state_chng
& EBUS_STATE_GP
) {
4007 (void) bscv_get8(ssp
, chan_general
, EBUS_IDX_GPIP
);
4010 if (state_chng
& EBUS_STATE_CB
) {
4011 (void) bscv_get8(ssp
, chan_general
, EBUS_IDX_CBREAK_STATUS
);
4014 if ((state_chng
& EBUS_STATE_TEMPERATURE
) &&
4015 ((dev_no
- 1) < MAX_TEMPS
)) {
4016 temp
= bscv_get8(ssp
, chan_general
,
4017 EBUS_IDX_TEMP1
+ dev_no
- 1);
4019 * Only remember temperatures which are real values or
4020 * a NOT PRESENT value.
4022 if ((temp
<= LOM_TEMP_MAX_VALUE
) ||
4023 (temp
== LOM_TEMP_STATE_NOT_PRESENT
)) {
4024 ssp
->temps
.temp
[dev_no
- 1] = temp
;
4028 if (state_chng
& EBUS_STATE_RAIL
) {
4029 (void) bscv_get8(ssp
, chan_general
, EBUS_IDX_SUPPLY_LO
);
4030 (void) bscv_get8(ssp
, chan_general
, EBUS_IDX_SUPPLY_HI
);
4035 bscv_get_label(char labels
[][MAX_LOM2_NAME_STR
], int limit
, int index
)
4041 if (limit
< 0 || index
< 0 || index
> limit
)
4044 return (labels
[index
]);
4048 bscv_generic_sysevent(bscv_soft_state_t
*ssp
, char *class, char *subclass
,
4049 char *fru_id
, char *res_id
, int32_t fru_state
, char *msg
)
4052 nvlist_t
*attr_list
;
4054 BSCV_TRACE(ssp
, 'E', "bscv_generic_sysevent", "%s/%s:(%s,%s,%d) %s",
4055 class, subclass
, fru_id
, res_id
, fru_state
, msg
);
4058 if (nvlist_alloc(&attr_list
, NV_UNIQUE_NAME_TYPE
, KM_SLEEP
)) {
4059 BSCV_TRACE(ssp
, 'E', "bscv_generic_sysevent",
4060 "nvlist alloc failure");
4063 if (nvlist_add_uint32(attr_list
, ENV_VERSION
, 1)) {
4064 BSCV_TRACE(ssp
, 'E', "bscv_generic_sysevent",
4065 "nvlist ENV_VERSION failure");
4066 nvlist_free(attr_list
);
4069 if (nvlist_add_string(attr_list
, ENV_FRU_ID
, fru_id
)) {
4070 BSCV_TRACE(ssp
, 'E', "bscv_generic_sysevent",
4071 "nvlist ENV_FRU_ID failure");
4072 nvlist_free(attr_list
);
4075 if (nvlist_add_string(attr_list
, ENV_FRU_RESOURCE_ID
, res_id
)) {
4076 BSCV_TRACE(ssp
, 'E', "bscv_generic_sysevent",
4077 "nvlist ENV_FRU_RESOURCE_ID failure");
4078 nvlist_free(attr_list
);
4081 if (nvlist_add_string(attr_list
, ENV_FRU_DEVICE
, ENV_RESERVED_ATTR
)) {
4082 BSCV_TRACE(ssp
, 'E', "bscv_generic_sysevent",
4083 "nvlist ENV_FRU_DEVICE failure");
4084 nvlist_free(attr_list
);
4087 if (nvlist_add_int32(attr_list
, ENV_FRU_STATE
, fru_state
)) {
4088 BSCV_TRACE(ssp
, 'E', "bscv_generic_sysevent",
4089 "nvlist ENV_FRU_STATE failure");
4090 nvlist_free(attr_list
);
4093 if (nvlist_add_string(attr_list
, ENV_MSG
, msg
)) {
4094 BSCV_TRACE(ssp
, 'E', "bscv_generic_sysevent",
4095 "nvlist ENV_MSG failure");
4096 nvlist_free(attr_list
);
4100 rv
= ddi_log_sysevent(ssp
->dip
, DDI_VENDOR_SUNW
, class,
4101 subclass
, attr_list
, NULL
, DDI_SLEEP
);
4103 if (rv
== DDI_SUCCESS
) {
4104 BSCV_TRACE(ssp
, 'E', "bscv_generic_sysevent", "sent sysevent");
4106 cmn_err(CE_WARN
, "!cannot deliver sysevent");
4109 nvlist_free(attr_list
);
4113 * function - bscv_sysevent
4114 * description - send out a sysevent on the given change if needed
4115 * inputs - soft state pointer, event to report
4120 bscv_sysevent(bscv_soft_state_t
*ssp
, lom_event_t
*event
)
4123 char *subclass
= NULL
;
4124 char *fru_id
= "Blade"; /* The blade is only one FRU */
4126 int32_t fru_state
= 0;
4128 BSCV_TRACE(ssp
, 'E', "bscv_sysevent", "processing event");
4130 ASSERT(event
!= NULL
);
4132 /* Map ev_subsys to sysevent class/sub-class */
4134 switch (EVENT_DECODE_SUBSYS(event
->ev_subsys
)) {
4135 case EVENT_SUBSYS_NONE
:
4137 case EVENT_SUBSYS_ALARM
:
4139 case EVENT_SUBSYS_TEMP
:
4140 class = EC_ENV
, subclass
= ESC_ENV_TEMP
;
4141 res_id
= bscv_get_label(ssp
->temps
.name
, ssp
->temps
.num
,
4142 event
->ev_resource
- 1);
4143 switch (event
->ev_event
) {
4144 case EVENT_SEVERE_OVERHEAT
:
4145 fru_state
= ENV_FAILED
;
4147 case EVENT_OVERHEAT
:
4148 fru_state
= ENV_WARNING
;
4150 case EVENT_NO_OVERHEAT
:
4157 case EVENT_SUBSYS_OVERTEMP
:
4159 case EVENT_SUBSYS_FAN
:
4160 class = EC_ENV
, subclass
= ESC_ENV_FAN
;
4161 res_id
= bscv_get_label(ssp
->fan_names
, ssp
->num_fans
,
4162 event
->ev_resource
- 1);
4163 switch (event
->ev_event
) {
4165 fru_state
= ENV_FAILED
;
4167 case EVENT_RECOVERED
:
4174 case EVENT_SUBSYS_SUPPLY
:
4175 class = EC_ENV
, subclass
= ESC_ENV_POWER
;
4176 res_id
= bscv_get_label(ssp
->sflags
.name
, ssp
->sflags
.num
,
4177 event
->ev_resource
- 1);
4178 switch (event
->ev_event
) {
4180 fru_state
= ENV_FAILED
;
4182 case EVENT_RECOVERED
:
4189 case EVENT_SUBSYS_BREAKER
:
4191 case EVENT_SUBSYS_PSU
:
4193 case EVENT_SUBSYS_USER
:
4195 case EVENT_SUBSYS_PHONEHOME
:
4197 case EVENT_SUBSYS_LOM
:
4199 case EVENT_SUBSYS_HOST
:
4201 case EVENT_SUBSYS_EVENTLOG
:
4203 case EVENT_SUBSYS_EXTRA
:
4205 case EVENT_SUBSYS_LED
:
4206 if (event
->ev_event
!= EVENT_FAULT_LED
&&
4207 event
->ev_event
!= EVENT_STATE_CHANGE
)
4210 * There are 3 LEDs : Power, Service, Ready-to-Remove on a
4211 * JBOS blade. We'll never report the Power since Solaris
4212 * won't be running when it is _switched_ ON. Ready-to-Remove
4213 * will only be lit when we're powered down which also means
4214 * Solaris won't be running. We don't want to report it
4215 * during system testing / Sun VTS exercising the LEDs.
4217 * Therefore, we only report the Service Required LED.
4219 class = EC_ENV
, subclass
= ESC_ENV_LED
;
4220 res_id
= bscv_get_label(ssp
->led_names
, MAX_LED_ID
,
4221 event
->ev_resource
- 1);
4223 switch (event
->ev_detail
) {
4224 case LOM_LED_STATE_ON_STEADY
:
4225 fru_state
= ENV_LED_ON
;
4227 case LOM_LED_STATE_ON_FLASHING
:
4228 case LOM_LED_STATE_ON_SLOWFLASH
:
4229 fru_state
= ENV_LED_BLINKING
;
4231 case LOM_LED_STATE_OFF
:
4232 fru_state
= ENV_LED_OFF
;
4234 case LOM_LED_STATE_INACCESSIBLE
:
4235 fru_state
= ENV_LED_INACCESSIBLE
;
4237 case LOM_LED_STATE_STANDBY
:
4238 fru_state
= ENV_LED_STANDBY
;
4240 case LOM_LED_STATE_NOT_PRESENT
:
4241 fru_state
= ENV_LED_NOT_PRESENT
;
4244 fru_state
= ENV_LED_INACCESSIBLE
;
4252 if (class == NULL
|| subclass
== NULL
) {
4253 BSCV_TRACE(ssp
, 'E', "bscv_sysevent", "class/subclass NULL");
4257 bscv_generic_sysevent(ssp
, class, subclass
, fru_id
, res_id
, fru_state
,
4262 * *********************************************************************
4263 * Firmware download (programming)
4264 * *********************************************************************
4268 * function - bscv_prog
4269 * description - LOMlite2 flash programming code.
4271 * bscv_prog_image - download a complete image to the lom.
4272 * bscv_prog_receive_image - receive data to build up a
4274 * bscv_prog_stop_lom - pause the event daemon and prepare
4275 * lom for firmware upgrade.
4276 * bscv_prog_start_lom - reinit the driver/lom after upgrade
4277 * and restart the event daemon
4279 * inputs - soft state pointer, arg ptr, ioctl mode
4284 bscv_prog(bscv_soft_state_t
*ssp
, intptr_t arg
, int mode
)
4290 * We will get repeatedly called with bits of data first for
4291 * loader, then for main image.
4293 prog
= (lom_prog_t
*)kmem_alloc(sizeof (lom_prog_t
), KM_SLEEP
);
4295 if (ddi_copyin((caddr_t
)arg
, (caddr_t
)prog
, sizeof (*prog
),
4297 kmem_free((void *)prog
, sizeof (*prog
));
4301 BSCV_TRACE(ssp
, 'U', "bscv_prog",
4302 "index 0x%x size 0x%x", prog
->index
, prog
->size
);
4304 mutex_enter(&ssp
->prog_mu
);
4305 if (prog
->size
== 0) {
4306 if (prog
->index
== 2) {
4308 * This is the initial request for the chip type so we
4309 * know what we are programming.
4310 * The type will have been read in at init so just
4311 * return it in data[0].
4313 prog
->data
[0] = bscv_get8_cached(ssp
,
4314 EBUS_IDX_CPU_IDENT
);
4316 if (ddi_copyout((caddr_t
)prog
, (caddr_t
)arg
,
4317 sizeof (lom_prog_t
), mode
) < 0) {
4320 } else if (prog
->index
== 0) {
4321 res
= bscv_prog_stop_lom(ssp
);
4322 } else if (prog
->index
== 1) {
4323 res
= bscv_prog_start_lom(ssp
);
4328 if (ssp
->image
== NULL
) {
4329 ssp
->image
= (uint8_t *)kmem_zalloc(
4330 BSC_IMAGE_MAX_SIZE
, KM_SLEEP
);
4332 res
= bscv_prog_receive_image(ssp
, prog
,
4333 ssp
->image
, BSC_IMAGE_MAX_SIZE
);
4335 mutex_exit(&ssp
->prog_mu
);
4336 kmem_free((void *)prog
, sizeof (lom_prog_t
));
4342 bscv_check_loader_config(bscv_soft_state_t
*ssp
, boolean_t is_image2
)
4344 BSCV_TRACE(ssp
, 'U', "bscv_check_loader_config",
4345 "loader_running %d, is_image2 %d",
4346 ssp
->loader_running
, is_image2
);
4349 * loader_running TRUE means that we have told the microcontroller to
4350 * JUMP into the loader code which has been downloaded into its RAM.
4351 * At this point its an error to try and download another loader. We
4352 * should be downloading the actual image at this point.
4353 * Conversely, it is an error to download an image when the loader is
4354 * not already downloaded and the microcontroller hasn't JUMPed into it.
4355 * is_image2 TRUE means the image is being downloaded.
4356 * is_image2 FALSE means the loader is being downloaded.
4358 if (ssp
->loader_running
&& !is_image2
) {
4359 cmn_err(CE_WARN
, "Attempt to download loader image "
4360 "with loader image already active");
4361 cmn_err(CE_CONT
, "This maybe an attempt to restart a "
4362 "failed firmware download - ignoring download attempt");
4364 } else if (!ssp
->loader_running
&& is_image2
) {
4365 cmn_err(CE_WARN
, "Attempt to download firmware image "
4366 "without loader image active");
4375 bscv_get_pagesize(bscv_soft_state_t
*ssp
)
4379 ASSERT(bscv_held(ssp
));
4381 pagesize
= bscv_get32(ssp
, chan_prog
,
4382 BSCVA(EBUS_CMD_SPACE_PROGRAM
, EBUS_PROGRAM_PAGE0
));
4384 BSCV_TRACE(ssp
, 'U', "bscv_get_pagesize", "pagesize 0x%x", pagesize
);
4390 * Sets the pagesize, returning the old value.
4393 bscv_set_pagesize(bscv_soft_state_t
*ssp
, uint32_t pagesize
)
4395 uint32_t old_pagesize
;
4397 ASSERT(bscv_held(ssp
));
4399 old_pagesize
= bscv_get_pagesize(ssp
);
4402 * The microcontroller remembers this value until until someone
4405 bscv_put32(ssp
, chan_prog
,
4406 BSCVA(EBUS_CMD_SPACE_PROGRAM
, EBUS_PROGRAM_PSIZ0
), pagesize
);
4408 return (old_pagesize
);
4412 bscv_enter_programming_mode(bscv_soft_state_t
*ssp
)
4416 ASSERT(bscv_held(ssp
));
4418 bscv_put8(ssp
, chan_prog
,
4419 BSCVA(EBUS_CMD_SPACE_PROGRAM
, EBUS_PROGRAM_PCSR
),
4420 EBUS_PROGRAM_PCR_PRGMODE_ON
);
4422 retval
= bscv_get8(ssp
, chan_prog
, BSCVA(EBUS_CMD_SPACE_PROGRAM
,
4423 EBUS_PROGRAM_PCSR
));
4429 bscv_leave_programming_mode(bscv_soft_state_t
*ssp
, boolean_t with_jmp
)
4432 ASSERT(bscv_held(ssp
));
4435 reg
= EBUS_PROGRAM_PCR_PROGOFF_JUMPTOADDR
;
4436 BSCV_TRACE(ssp
, 'U', "bscv_leave_programming_mode",
4439 reg
= EBUS_PROGRAM_PCR_PRGMODE_OFF
;
4440 BSCV_TRACE(ssp
, 'U', "bscv_leave_programming_mode",
4444 bscv_put8(ssp
, chan_prog
,
4445 BSCVA(EBUS_CMD_SPACE_PROGRAM
, EBUS_PROGRAM_PCSR
), reg
);
4450 bscv_set_jump_to_addr(bscv_soft_state_t
*ssp
, uint32_t loadaddr
)
4452 ASSERT(bscv_held(ssp
));
4454 bscv_put32(ssp
, chan_prog
,
4455 BSCVA(EBUS_CMD_SPACE_PROGRAM
, EBUS_PROGRAM_PADR0
), loadaddr
);
4457 BSCV_TRACE(ssp
, 'U', "bscv_set_jump_to_addr",
4458 "set jump to loadaddr 0x%x", loadaddr
);
4462 bscv_erase_once(bscv_soft_state_t
*ssp
, uint32_t loadaddr
, uint32_t image_size
)
4466 ASSERT(bscv_held(ssp
));
4469 * write PADR, PSIZ to define area to be erased
4470 * We do not send erase for zero size because the current
4471 * downloader gets this wrong
4477 BSCV_TRACE(ssp
, 'U', "bscv_erase_once", "sending erase command");
4479 bscv_put32(ssp
, chan_prog
,
4480 BSCVA(EBUS_CMD_SPACE_PROGRAM
, EBUS_PROGRAM_PADR0
),
4483 /* set PSIZ to full size of image to be programmed */
4484 bscv_put32(ssp
, chan_prog
,
4485 BSCVA(EBUS_CMD_SPACE_PROGRAM
, EBUS_PROGRAM_PSIZ0
),
4488 /* write ERASE to PCSR */
4489 bscv_put8(ssp
, chan_prog
,
4490 BSCVA(EBUS_CMD_SPACE_PROGRAM
, EBUS_PROGRAM_PCSR
),
4491 EBUS_PROGRAM_PCR_ERASE
);
4493 /* read PCSR to check status */
4494 retval
= bscv_get8(ssp
, chan_prog
,
4495 BSCVA(EBUS_CMD_SPACE_PROGRAM
, EBUS_PROGRAM_PCSR
));
4500 bscv_do_erase(bscv_soft_state_t
*ssp
, uint32_t loadaddr
, uint32_t image_size
,
4501 boolean_t is_image2
)
4503 int retryable
= BSC_ERASE_RETRY_LIMIT
;
4506 while (retryable
--) {
4507 retval
= bscv_erase_once(ssp
, loadaddr
, image_size
);
4508 if (PSR_SUCCESS(retval
))
4511 cmn_err(CE_WARN
, "erase error 0x%x, attempt %d"
4512 ", base 0x%x, size 0x%x, %s image",
4513 retval
, BSC_ERASE_RETRY_LIMIT
- retryable
,
4514 loadaddr
, image_size
,
4515 is_image2
? "main" : "loader");
4522 bscv_set_page(bscv_soft_state_t
*ssp
, uint32_t addr
)
4525 int retryable
= BSC_PAGE_RETRY_LIMIT
;
4527 ASSERT(bscv_held(ssp
));
4529 while (retryable
--) {
4532 * Write the page address and read it back for confirmation.
4534 bscv_put32(ssp
, chan_prog
,
4535 BSCVA(EBUS_CMD_SPACE_PROGRAM
, EBUS_PROGRAM_PADR0
),
4537 retval
= bscv_get32(ssp
, chan_prog
,
4538 BSCVA(EBUS_CMD_SPACE_PROGRAM
, EBUS_PROGRAM_PADR0
));
4543 cmn_err(CE_WARN
, "programmming error, attempt %d, "
4544 "set page 0x%x, read back 0x%x",
4545 BSC_PAGE_RETRY_LIMIT
- retryable
,
4549 return ((addr
== retval
) ? EBUS_PROGRAM_PSR_SUCCESS
:
4550 EBUS_PROGRAM_PSR_INVALID_OPERATION
);
4554 bscv_do_page_data_once(bscv_soft_state_t
*ssp
, uint32_t index
,
4555 uint32_t image_size
, uint32_t pagesize
, uint8_t *imagep
,
4556 uint16_t *calcd_chksum
)
4563 ASSERT(bscv_held(ssp
));
4565 BSCV_TRACE(ssp
, 'P', "bscv_do_page_data_once", "index 0x%x", index
);
4567 /* write PSIZ bytes to PDAT */
4568 if (index
+ pagesize
< image_size
) {
4569 bscv_rep_rw8(ssp
, chan_prog
, imagep
+ index
,
4570 BSCVA(EBUS_CMD_SPACE_PROGRAM
, EBUS_PROGRAM_DATA
),
4571 pagesize
, DDI_DEV_NO_AUTOINCR
, B_TRUE
/* write */);
4574 BSCV_TRACE(ssp
, 'P', "bscv_do_page_once",
4575 "Sending last block, last 0x%x bytes",
4576 (image_size
% pagesize
));
4577 size
= (image_size
- index
);
4578 bscv_rep_rw8(ssp
, chan_prog
, imagep
+ index
,
4579 BSCVA(EBUS_CMD_SPACE_PROGRAM
, EBUS_PROGRAM_DATA
),
4580 size
, DDI_DEV_NO_AUTOINCR
, B_TRUE
/* write */);
4581 /* Now pad the rest of the page with zeros */
4582 for (i
= size
; i
< pagesize
; i
++) {
4583 bscv_put8(ssp
, chan_prog
,
4584 BSCVA(EBUS_CMD_SPACE_PROGRAM
,
4590 /* write the checksum to PCSM */
4592 for (i
= 0; i
< size
; i
++) {
4593 chksum
= ((chksum
<< 3) | (chksum
>> 13)) ^
4594 *(imagep
+ index
+ i
);
4596 /* Cope with non-pagesize sized bufers */
4597 for (; i
< pagesize
; i
++) {
4598 chksum
= ((chksum
<< 3) | (chksum
>> 13)) ^ 0;
4600 bscv_put16(ssp
, chan_prog
,
4601 BSCVA(EBUS_CMD_SPACE_PROGRAM
, EBUS_PROGRAM_PCSM0
), chksum
);
4603 bscv_put8(ssp
, chan_prog
,
4604 BSCVA(EBUS_CMD_SPACE_PROGRAM
, EBUS_PROGRAM_PCSR
),
4605 EBUS_PROGRAM_PCR_PROGRAM
);
4607 retval
= bscv_get8(ssp
, chan_prog
,
4608 BSCVA(EBUS_CMD_SPACE_PROGRAM
, EBUS_PROGRAM_PCSR
));
4610 *calcd_chksum
= chksum
;
4614 static uint8_t bscv_do_page(bscv_soft_state_t
*ssp
, uint32_t loadaddr
,
4615 uint32_t index
, uint32_t image_size
, uint32_t pagesize
, uint8_t *imagep
,
4616 boolean_t is_image2
)
4618 int retryable
= BSC_PAGE_RETRY_LIMIT
;
4622 BSCV_TRACE(ssp
, 'P', "bscv_do_page", "index 0x%x", index
);
4624 while (retryable
--) {
4626 * Set the page address (with retries). If this is not
4627 * successful, then there is no point carrying on and sending
4628 * the page's data since that could cause random memory
4629 * corruption in the microcontroller.
4631 retval
= bscv_set_page(ssp
, loadaddr
+ index
);
4632 if (!PSR_SUCCESS(retval
)) {
4633 cmn_err(CE_WARN
, "programming error 0x%x, "
4634 "could not setup page address 0x%x, %s image",
4635 retval
, loadaddr
+ index
,
4636 is_image2
? "main" : "loader");
4641 * Send down the data for the page
4644 BSCV_TRACE(ssp
, 'P', "bscv_do_page", "sending data for page");
4646 retval
= bscv_do_page_data_once(ssp
, index
, image_size
,
4647 pagesize
, imagep
, &checksum
);
4648 if (PSR_SUCCESS(retval
))
4651 cmn_err(CE_WARN
, "programming error 0x%x,"
4652 " attempt %d, index 0x%x, checksum 0x%x, %s image",
4653 retval
, BSC_PAGE_RETRY_LIMIT
- retryable
,
4654 index
, checksum
, is_image2
? "main" : "loader");
4657 BSCV_TRACE(ssp
, 'U', "bscv_do_page", "Returning 0x%x for index 0x%x,"
4658 " checksum 0x%x, %s image", retval
, index
, checksum
,
4659 is_image2
? "main" : "loader");
4665 bscv_do_pages(bscv_soft_state_t
*ssp
, uint32_t loadaddr
, uint32_t image_size
,
4666 uint32_t pagesize
, uint8_t *imagep
, boolean_t is_image2
)
4671 BSCV_TRACE(ssp
, 'P', "bscv_do_pages", "entered");
4673 for (index
= 0; index
< image_size
; index
+= pagesize
) {
4674 retval
= bscv_do_page(ssp
, loadaddr
, index
, image_size
,
4675 pagesize
, imagep
, is_image2
);
4676 if (bscv_faulty(ssp
) || !PSR_SUCCESS(retval
)) {
4677 BSCV_TRACE(ssp
, 'U', "bscv_do_pages",
4678 "Failed to program lom (status 0x%x)", retval
);
4687 bscv_prog_image(bscv_soft_state_t
*ssp
, boolean_t is_image2
,
4688 uint8_t *imagep
, int image_size
, uint32_t loadaddr
)
4694 BSCV_TRACE(ssp
, 'U', "bscv_prog_image",
4695 "image 0x%x, imagep %p, size 0x%x",
4696 is_image2
? 2 : 1, imagep
, image_size
);
4698 if (!bscv_check_loader_config(ssp
, is_image2
))
4700 * Return no error to allow userland to continue on with
4701 * downloading the image.
4707 pagesize
= bscv_get_pagesize(ssp
);
4709 retval
= bscv_enter_programming_mode(ssp
);
4710 if (bscv_faulty(ssp
) || !PSR_PROG(retval
)) {
4711 cmn_err(CE_WARN
, "lom: Failed to enter program mode, error 0x%x"
4712 ", %s image", retval
, is_image2
? "main" : "loader");
4714 goto BSCV_PROG_IMAGE_END
;
4716 BSCV_TRACE(ssp
, 'U', "bscv_prog_image", "entered programming mode");
4719 * Only issue an erase if we are downloading the image. The loader
4720 * does not need this step.
4722 if (is_image2
&& (image_size
!= 0)) {
4723 retval
= bscv_do_erase(ssp
, loadaddr
, image_size
, is_image2
);
4724 if (bscv_faulty(ssp
) || !PSR_SUCCESS(retval
)) {
4726 "lom: Erase failed during programming, status 0x%x",
4729 goto BSCV_PROG_IMAGE_END
;
4731 BSCV_TRACE(ssp
, 'U', "bscv_prog_image",
4732 "erase complete - programming...");
4737 (void) bscv_set_pagesize(ssp
, pagesize
);
4739 retval
= bscv_do_pages(ssp
, loadaddr
, image_size
, pagesize
, imagep
,
4741 if (bscv_faulty(ssp
) || !PSR_SUCCESS(retval
)) {
4742 BSCV_TRACE(ssp
, 'U', "bscv_prog_image",
4743 "Failed to program lom (status 0x%x)", retval
);
4745 goto BSCV_PROG_IMAGE_END
;
4748 BSCV_PROG_IMAGE_END
:
4749 if (res
== 0 && !is_image2
) {
4751 * We've downloaded the loader successfully. Now make the
4752 * microcontroller jump to it.
4754 bscv_set_jump_to_addr(ssp
, loadaddr
);
4755 ssp
->loader_running
= B_TRUE
;
4756 bscv_leave_programming_mode(ssp
, B_TRUE
);
4759 * We've just downloaded either the loader which failed, or
4760 * the image (which may or may not have been successful).
4762 bscv_set_jump_to_addr(ssp
, 0);
4765 BSCV_TRACE(ssp
, 'U', "bscv_prog_image",
4766 "got error 0x%x - leaving programming mode",
4768 cmn_err(CE_WARN
, "programming error 0x%x, %s image",
4769 res
, is_image2
? "main" : "loader");
4771 BSCV_TRACE(ssp
, 'U', "bscv_prog_image",
4772 "programming complete - leaving programming mode");
4775 bscv_leave_programming_mode(ssp
, B_FALSE
);
4776 ssp
->loader_running
= B_FALSE
;
4786 bscv_prog_receive_image(bscv_soft_state_t
*ssp
, lom_prog_t
*prog
,
4787 uint8_t *imagep
, int max_size
)
4792 lom_prog_data_t
*prog_data
;
4794 if ((prog
->index
& 0x7FFF) != ssp
->prog_index
) {
4795 BSCV_TRACE(ssp
, 'U', "bscv_prog_receive_image",
4796 "Got wrong buffer 0x%x, expected 0x%x",
4797 prog
->index
& 0x7fff, ssp
->prog_index
);
4802 * We want to get the whole image and then do the download.
4803 * It is assumed the device is now in programming mode.
4806 if ((prog
->index
& 0x7fff) == 0) {
4807 /* Starting a new image */
4811 if ((ssp
->image_ptr
+ prog
->size
) > max_size
) {
4813 "lom image exceeded maximum size: got 0x%x, maximum 0x%x",
4814 (ssp
->image_ptr
+ prog
->size
), max_size
);
4817 bcopy(prog
->data
, &imagep
[ssp
->image_ptr
], prog
->size
);
4818 ssp
->image_ptr
+= prog
->size
;
4822 if (prog
->index
& 0x8000) {
4824 * OK we have the whole image so synch up and start download.
4826 prog_data
= (lom_prog_data_t
*)imagep
;
4827 if (prog_data
->header
.magic
!= PROG_MAGIC
) {
4828 /* Old style programming data */
4829 /* Take care image may not fill all of structure */
4831 /* sign extend loadaddr from 16 to 32 bits */
4832 loadaddr
= (int16_t)((uint16_t)((imagep
[2] << 8) +
4835 size
= (imagep
[0] << 8) + imagep
[1];
4836 if (size
!= (ssp
->image_ptr
- 4)) {
4837 cmn_err(CE_WARN
, "Image size mismatch:"
4838 " expected 0x%x, got 0x%x",
4839 size
, (ssp
->image_ptr
- 1));
4842 res
= bscv_prog_image(ssp
,
4843 ssp
->image2_processing
,
4844 imagep
+ 4, ssp
->image_ptr
- 4, loadaddr
);
4847 * Done the loading so set the flag to say we are doing
4850 ssp
->image2_processing
= !ssp
->image2_processing
;
4851 } else if ((ssp
->image_ptr
< sizeof (*prog_data
)) ||
4852 (prog_data
->platform
.bscv
.size
!=
4853 (ssp
->image_ptr
- sizeof (*prog_data
)))) {
4854 /* Image too small for new style image */
4855 cmn_err(CE_WARN
, "image too small");
4858 /* New style programming image */
4859 switch (prog_data
->platmagic
) {
4860 case PROG_PLAT_BSCV_IMAGE
:
4861 res
= bscv_prog_image(ssp
, B_TRUE
,
4862 imagep
+ sizeof (*prog_data
),
4863 prog_data
->platform
.bscv
.size
,
4864 prog_data
->platform
.bscv
.loadaddr
);
4865 ssp
->image2_processing
= B_FALSE
;
4867 case PROG_PLAT_BSCV_LOADER
:
4868 res
= bscv_prog_image(ssp
, B_FALSE
,
4869 imagep
+ sizeof (*prog_data
),
4870 prog_data
->platform
.bscv
.size
,
4871 prog_data
->platform
.bscv
.loadaddr
);
4872 ssp
->image2_processing
= B_TRUE
;
4875 cmn_err(CE_WARN
, "unknown platmagic 0x%x",
4876 prog_data
->platmagic
);
4881 ssp
->prog_index
= 0;
4888 bscv_prog_stop_lom(bscv_soft_state_t
*ssp
)
4890 if (ssp
->programming
) {
4892 * Already programming - this may be a retry of a failed
4893 * programming attempt or just a software error!
4898 if (bscv_pause_event_daemon(ssp
) == BSCV_FAILURE
) {
4899 BSCV_TRACE(ssp
, 'Q', "bscv_prog_stop_lom",
4900 "failed to pause event daemon thread");
4906 ssp
->programming
= B_TRUE
;
4912 ssp
->prog_index
= 0;
4913 ssp
->image2_processing
= B_FALSE
;
4919 bscv_prog_start_lom(bscv_soft_state_t
*ssp
)
4923 if (!ssp
->programming
) {
4924 /* Not programming so this is not a valid command */
4928 if (ssp
->image
!= NULL
) {
4929 kmem_free((void *)ssp
->image
, BSC_IMAGE_MAX_SIZE
);
4934 * OK we are out of reset now so:
4935 * Probe the firmware and set everything up.
4940 /* Explicit clear fault because things may have been mended now */
4941 bscv_clear_fault(ssp
);
4943 if (ssp
->loader_running
) {
4944 cmn_err(CE_WARN
, "Firmware upgrade failed to exit loader - "
4945 "performing forced exit");
4946 /* Must try to restart the lom here. */
4947 /* Ensure prog mode entry to enable PRGMODE_OFF */
4948 bscv_put8(ssp
, chan_prog
,
4949 BSCVA(EBUS_CMD_SPACE_PROGRAM
, EBUS_PROGRAM_PCSR
),
4950 EBUS_PROGRAM_PCR_PRGMODE_ON
);
4951 bscv_put8(ssp
, chan_prog
,
4952 BSCVA(EBUS_CMD_SPACE_PROGRAM
, EBUS_PROGRAM_PCSR
),
4953 EBUS_PROGRAM_PCR_PRGMODE_OFF
);
4954 ssp
->loader_running
= B_FALSE
;
4955 /* give the lom chance to recover */
4956 delay(drv_usectohz(5000000)); /* 5 seconds */
4959 ssp
->prog_mode_only
= B_FALSE
;
4960 ssp
->programming
= B_FALSE
;
4962 if (bscv_attach_common(ssp
) == DDI_FAILURE
) {
4963 ssp
->prog_mode_only
= B_TRUE
;
4969 if (!ssp
->prog_mode_only
) {
4971 * Start the event thread after the queue has started
4973 * Not sure if this is entirely correct because
4974 * the other code at the end of bscv_attach()
4975 * does not get run here.
4977 bscv_start_event_daemon(ssp
);
4978 bscv_resume_event_daemon(ssp
);
4986 * *********************************************************************
4988 * *********************************************************************
4992 * function - bscv_attach_common
4993 * description - this routine co-ordinates the initialisation of the
4994 * driver both at attach time and after firmware programming.
4995 * sequence - bscv_setup_capability - read LOMlite2 capabilities
4996 * bscv_probe_check - test comms and setup register cache
4997 * bscv_setup_hostname - sync stored name in lom with nodename.
4998 * bscv_setup_static_info - read device names etc.
4999 * bscv_setup_events - start event daemon etc.
5001 * inputs - device information structure, DDI_ATTACH command
5002 * outputs - DDI_SUCCESS or DDI_FAILURE
5006 bscv_attach_common(bscv_soft_state_t
*ssp
)
5008 ASSERT(bscv_held(ssp
));
5010 BSCV_TRACE(ssp
, 'A', "bscv_attach_common:", "");
5013 * Set the threshold for reporting messages to the console to
5014 * Warnings or higher.
5016 ssp
->reporting_level
= 2;
5019 * When the system is not running the Operating System, make
5020 * the microcontroller print event messages straight onto the
5023 ssp
->serial_reporting
= LOM_SER_EVENTS_DEF
;
5025 /* Setup capabilities */
5026 bscv_setup_capability(ssp
);
5028 if (bscv_probe_check(ssp
) == DDI_FAILURE
) {
5029 cmn_err(CE_WARN
, "BSC chip not responding");
5031 * We want lom -G to talk to this driver upon broken firmware
5032 * so we prematurely return success here.
5034 return (DDI_SUCCESS
);
5037 bscv_setup_hostname(ssp
);
5038 bscv_setup_static_info(ssp
);
5039 bscv_setup_events(ssp
);
5041 #if defined(__i386) || defined(__amd64)
5042 bscv_inform_bsc(ssp
, BSC_INFORM_ONLINE
);
5043 #endif /* __i386 || __amd64 */
5045 * Watchdog configuration and CPU signatures are sent asynchronously
5046 * with respect to attach so only inform the BSC if we've already
5047 * sent the data in the past.
5050 if (ssp
->progress
& BSCV_WDOG_CFG
)
5051 bscv_setup_watchdog(ssp
);
5054 if (ssp
->progress
& BSCV_SIG_SENT
)
5055 bscv_write_sig(ssp
, ssp
->last_sig
);
5056 #endif /* __sparc */
5058 return (DDI_SUCCESS
);
5062 * function - bscv_cleanup
5063 * description - routine that does the necessary tidying up if the attach
5064 * request fails or the driver is to be detached.
5065 * If the event thread has been started we may fail to
5066 * stop it (because it is busy) so we fail the cleanup
5067 * and hence the detach. All other calls to bscv_cleanup
5068 * are done before the event daemon is started.
5069 * inputs - soft state structure address.
5070 * outputs - DDI_SUCCESS or DDI_FAILURE.
5074 bscv_cleanup(bscv_soft_state_t
*ssp
)
5080 instance
= ssp
->instance
;
5082 if (ssp
->progress
& BSCV_LOCKS
) {
5086 if (ssp
->progress
& BSCV_THREAD
) {
5087 if (bscv_stop_event_daemon(ssp
) == DDI_FAILURE
) {
5088 /* Fail the cleanup - may be able to cleanup later */
5089 if (ssp
->progress
& BSCV_LOCKS
) {
5092 return (DDI_FAILURE
);
5096 if (ssp
->progress
& BSCV_NODES
) {
5097 ddi_remove_minor_node(ssp
->dip
, NULL
);
5100 if (ssp
->progress
& BSCV_MAPPED_REGS
) {
5102 * switch back on serial event reporting - cover all configs.
5106 if (ssp
->serial_reporting
== LOM_SER_EVENTS_ON
) {
5107 bits2clear
|= EBUS_ALARM_NOEVENTS
;
5108 } else if (ssp
->serial_reporting
== LOM_SER_EVENTS_OFF
) {
5109 bits2set
|= EBUS_ALARM_NOEVENTS
;
5110 } else if (ssp
->serial_reporting
== LOM_SER_EVENTS_DEF
) {
5111 bits2clear
|= EBUS_ALARM_NOEVENTS
;
5113 bscv_setclear8_volatile(ssp
, chan_general
, EBUS_IDX_ALARM
,
5114 bits2set
, bits2clear
);
5117 * disable the reset function if we have enabled
5118 * it. We don't want any nasty surprises like system
5119 * rebooting unexpectedly. If we timeout on the busy
5120 * flag we just have to carry on.
5123 BSCV_TRACE(ssp
, 'W', "bscv_cleanup",
5124 "bscv_cleanup - disable wdog");
5125 if (bscv_get8_cached(ssp
, EBUS_IDX_WDOG_CTRL
) &
5127 bscv_setclear8(ssp
, chan_general
, EBUS_IDX_WDOG_CTRL
,
5128 0, EBUS_WDOG_RST
| EBUS_WDOG_ENABLE
);
5136 if (ssp
->progress
& BSCV_MAPPED_REGS
) {
5137 bscv_unmap_regs(ssp
);
5141 * release any memory allocated for mutexes and condition
5142 * variables before deallocating the structures containing them
5145 if (ssp
->progress
& BSCV_LOCKS
) {
5147 cv_destroy(&ssp
->task_cv
);
5148 cv_destroy(&ssp
->task_evnt_cv
);
5149 mutex_destroy(&ssp
->task_mu
);
5150 mutex_destroy(&ssp
->prog_mu
);
5151 mutex_destroy(&ssp
->cmd_mutex
);
5154 if (ssp
->image
!= NULL
) {
5155 kmem_free((void *)ssp
->image
, BSC_IMAGE_MAX_SIZE
);
5158 #if defined(__i386) || defined(__amd64)
5159 bscv_watchdog_cyclic_remove(ssp
);
5160 #endif /* __i386 || __amd64 */
5161 ddi_soft_state_free(bscv_statep
, instance
);
5163 return (DDI_SUCCESS
);
5167 * function - bscv_setup_capability
5168 * description - probe the lom find what capabilities are present for
5170 * inputs - soft state ptr
5171 * outputs - returns DDI_SUCCESS or DDI_FAILURE
5173 static void bscv_setup_capability(bscv_soft_state_t
*ssp
)
5175 ASSERT(bscv_held(ssp
));
5177 if (ssp
->prog_mode_only
) {
5178 /* Turn off all capabilities */
5185 ssp
->cap0
= bscv_get8(ssp
, chan_general
, EBUS_IDX_CAP0
);
5186 ssp
->cap1
= bscv_get8(ssp
, chan_general
, EBUS_IDX_CAP1
);
5187 ssp
->cap2
= bscv_get8(ssp
, chan_general
, EBUS_IDX_CAP2
);
5188 if (!bscv_faulty(ssp
)) {
5189 BSCV_TRACE(ssp
, 'A', "bscv_setup_capability",
5190 "Capability flags cap0=0x%x cap1=0x%x, cap2=0x%x",
5191 ssp
->cap0
, ssp
->cap1
, ssp
->cap2
);
5193 cmn_err(CE_WARN
, "!Could not read capability flags");
5194 ssp
->cap0
= 0; ssp
->cap1
= 0; ssp
->cap2
= 0;
5199 * function - bscv_probe_check
5200 * description - probe the lom to check for correct operation
5201 * has a side effect of setting up the cached registers and
5202 * updates ssp->prog_mode_only.
5203 * inputs - soft state ptr
5204 * outputs - returns DDI_SUCCESS or DDI_FAILURE
5207 static int bscv_probe_check(bscv_soft_state_t
*ssp
)
5212 ASSERT(bscv_held(ssp
));
5214 BSCV_TRACE(ssp
, 'A', "bscv_probe_check", "");
5216 if (!ssp
->prog_mode_only
) {
5218 * Make sure probe location is OK so that we are
5220 * We want to make sure that this is not faulty so we
5221 * do a bscv_clear_fault to clear any existing
5222 * fault records down.
5224 bscv_clear_fault(ssp
);
5225 probeval
= bscv_get8(ssp
, chan_general
, EBUS_IDX_PROBEAA
);
5226 if (bscv_faulty(ssp
)) {
5227 ssp
->prog_mode_only
= B_TRUE
;
5228 } else if (probeval
!= 0xAA) {
5229 BSCV_TRACE(ssp
, 'A', "bscv_probe_check",
5230 "LOMlite out of sync");
5233 * It may be that the LOMlite was out of
5234 * sync so lets try the read again.
5236 probeval
= bscv_get8(ssp
, chan_general
,
5238 if (bscv_faulty(ssp
)) {
5239 BSCV_TRACE(ssp
, 'A', "bscv_probe_check",
5240 "Init readAA1 failed");
5241 ssp
->prog_mode_only
= B_TRUE
;
5242 } else if (probeval
!= 0xAA) {
5244 * OK that is twice we are out so I
5245 * guess the LOMlite is in trouble
5247 BSCV_TRACE(ssp
, 'A', "bscv_probe_check",
5248 "Init readAA probe failed - got 0x%x",
5250 ssp
->prog_mode_only
= B_TRUE
;
5256 * Read in all page zero lom registers.
5257 * Read state change 1st so we dont miss anything and clear it.
5258 * Note: we discard the values because we rely on bscv_get8 to
5259 * setup the cache of register values.
5262 if (!ssp
->prog_mode_only
) {
5263 (void) bscv_get8(ssp
, chan_general
, EBUS_IDX_STATE_CHNG
);
5264 if (bscv_faulty(ssp
)) {
5265 BSCV_TRACE(ssp
, 'A', "bscv_probe_check",
5266 "Read of state change register failed");
5267 ssp
->prog_mode_only
= B_TRUE
;
5271 if (!ssp
->prog_mode_only
) {
5272 for (i
= 1; i
< 0x80; i
++) {
5274 case EBUS_IDX_STATE_CHNG
:
5275 case EBUS_IDX_CMD_RES
:
5276 case EBUS_IDX_HNAME_CHAR
:
5278 * Should not read these - they have side
5283 (void) bscv_get8(ssp
, chan_general
, i
);
5286 if (bscv_faulty(ssp
)) {
5287 BSCV_TRACE(ssp
, 'A', "bscv_probe_check",
5288 "Initial read or register %2x failed", i
);
5289 ssp
->prog_mode_only
= B_TRUE
;
5290 /* Might as well give up now! */
5297 * Check the probe keys so we know the lom is OK
5300 if (!ssp
->prog_mode_only
) {
5301 if ((bscv_get8_cached(ssp
, EBUS_IDX_PROBE55
) != 0x55) ||
5302 (bscv_get8_cached(ssp
, EBUS_IDX_PROBEAA
) != 0xAA)) {
5304 BSCV_TRACE(ssp
, 'A', "bscv_probe_check",
5305 "LOMlite Probe failed");
5306 for (i
= 0; i
< 0x8; i
++) {
5307 BSCV_TRACE(ssp
, 'A', "bscv_probe_check",
5308 "%2x %2x %2x %2x %2x %2x %2x %2x %2x "
5309 "%2x %2x %2x %2x %2x %2x %2x %2x %2x",
5310 bscv_get8_cached(ssp
, i
),
5311 bscv_get8_cached(ssp
, i
+ 1),
5312 bscv_get8_cached(ssp
, i
+ 2),
5313 bscv_get8_cached(ssp
, i
+ 3),
5314 bscv_get8_cached(ssp
, i
+ 4),
5315 bscv_get8_cached(ssp
, i
+ 5),
5316 bscv_get8_cached(ssp
, i
+ 6),
5317 bscv_get8_cached(ssp
, i
+ 7),
5318 bscv_get8_cached(ssp
, i
+ 8),
5319 bscv_get8_cached(ssp
, i
+ 9),
5320 bscv_get8_cached(ssp
, i
+ 10),
5321 bscv_get8_cached(ssp
, i
+ 11),
5322 bscv_get8_cached(ssp
, i
+ 12),
5323 bscv_get8_cached(ssp
, i
+ 13),
5324 bscv_get8_cached(ssp
, i
+ 14),
5325 bscv_get8_cached(ssp
, i
+ 15));
5327 ssp
->prog_mode_only
= B_TRUE
;
5331 return ((ssp
->prog_mode_only
== B_FALSE
) ? DDI_SUCCESS
: DDI_FAILURE
);
5336 * function - bscv_idi_set
5337 * description - bscv inter driver interface set function
5338 * inputs - structure which defines type of service required and data
5341 * This is the Entry Point function for the platmod driver. It works out which
5342 * X Bus channel ought to deliver the service requested.
5345 bscv_idi_set(struct bscv_idi_info info
)
5347 struct bscv_idi_callout
*tbl
;
5350 ASSERT(bscv_idi_mgr
.magic
== BSCV_IDI_CALLOUT_MAGIC
);
5352 if (bscv_idi_mgr
.tbl
== NULL
) {
5354 cmn_err(CE_WARN
, "!bscv_idi_set : cannot find "
5355 "bscv_callout_table");
5357 } else if (bscv_idi_mgr
.valid_inst
== (uint32_t)~0) {
5360 * This error message can appear in the context of
5361 * another driver, say platmod or todblade. We want
5362 * to clearly indicate the culprit driver so put in
5365 cmn_err(CE_WARN
, "!bscv_idi_set : no valid "
5366 "driver instance of "
5371 tbl
= bscv_idi_mgr
.tbl
;
5373 while (tbl
->type
!= BSCV_IDI_NULL
) {
5374 if (tbl
->type
== info
.type
) {
5376 * We service the request with a valid instance number
5379 retval
= ((tbl
->fn
) (info
));
5382 * If the request was serviced, clear any accumulated
5383 * error counters so future warnings will be reported if
5386 if (retval
== B_TRUE
)
5387 bscv_idi_clear_err();
5395 cmn_err(CE_WARN
, "!bscv_idi_set : cannot match info.type %d",
5400 * function - bscv_nodename_set
5401 * description - notify the event thread that a nodename change has occurred.
5402 * inputs - data from client driver
5404 * side-effects - the event thread will schedule an update to the lom firmware.
5408 bscv_nodename_set(struct bscv_idi_info info
)
5410 bscv_soft_state_t
*ssp
;
5412 ssp
= ddi_get_soft_state(bscv_statep
, bscv_idi_mgr
.valid_inst
);
5416 cmn_err(CE_WARN
, "!blade_nodename_set: cannot get ssp");
5420 /* Get a lock on the SSP, notify our change, then exit */
5421 mutex_enter(&ssp
->task_mu
);
5422 ssp
->nodename_change
= B_TRUE
;
5423 cv_signal(&ssp
->task_cv
);
5424 mutex_exit(&ssp
->task_mu
);
5430 * function - bscv_sig_set
5431 * description - write a signature
5432 * inputs - data from client driver
5436 bscv_sig_set(struct bscv_idi_info info
)
5438 bscv_soft_state_t
*ssp
;
5441 ssp
= ddi_get_soft_state(bscv_statep
, bscv_idi_mgr
.valid_inst
);
5445 cmn_err(CE_WARN
, "!blade_nodename_set: cannot get ssp");
5449 /* Service the request */
5450 bcopy(info
.data
, &sig
, sizeof (sig
));
5452 bscv_write_sig(ssp
, sig
);
5457 #endif /* __sparc */
5460 bscv_wdog_do_pat(bscv_soft_state_t
*ssp
)
5465 * The value of the dog pat is a sequence number which wraps around,
5466 * bounded by BSCV_WDOG_PAT_SEQ_MASK.
5468 pat
= ssp
->pat_seq
++;
5469 pat
&= EBUS_WDOG_NB_PAT_SEQ_MASK
;
5471 /* Set top nibble to indicate a pat */
5472 pat
|= EBUS_WDOG_NB_PAT
;
5475 * Now pat the dog. This exercises a special protocol in the
5476 * bus nexus that offers : non-blocking IO, and timely delivery,
5477 * callable from high-level interrupt context. The requirement
5478 * on us is that the channel is not shared for any other use.
5479 * This means for chan_wdogpat, nothing may use channel[chan].regs
5480 * or channel.[chan].handle.
5483 ddi_put8(ssp
->channel
[chan_wdogpat
].handle
,
5484 ssp
->channel
[chan_wdogpat
].regs
, pat
);
5486 BSCV_TRACE(ssp
, 'W', "bscv_wdog_pat", "patted the dog with seq %d",
5492 * function - bscv_wdog_pat
5493 * description - pat the watchdog
5494 * inputs - data from client driver
5499 bscv_wdog_pat(struct bscv_idi_info info
)
5502 * This function remembers if it has ever been called with the
5503 * configure option set.
5505 bscv_soft_state_t
*ssp
;
5507 ssp
= ddi_get_soft_state(bscv_statep
, bscv_idi_mgr
.valid_inst
);
5511 cmn_err(CE_WARN
, "!bscv_wdog_pat: cannot get ssp");
5513 } else if (ssp
->nchannels
== 0) {
5514 /* Didn't manage to map handles so ddi_{get,put}* broken */
5516 cmn_err(CE_WARN
, "!bscv_wdog_pat: handle not mapped");
5520 bscv_wdog_do_pat(ssp
);
5525 * function - bscv_wdog_cfg
5526 * description - configure the watchdog
5527 * inputs - data from client driver
5531 bscv_wdog_cfg(struct bscv_idi_info info
)
5533 bscv_soft_state_t
*ssp
;
5535 ssp
= ddi_get_soft_state(bscv_statep
, bscv_idi_mgr
.valid_inst
);
5539 cmn_err(CE_WARN
, "!bscv_wdog_cfg: cannot get ssp");
5541 } else if (ssp
->nchannels
== 0) {
5542 /* Didn't manage to map handles so ddi_{get,put}* broken */
5544 cmn_err(CE_WARN
, "!bscv_wdog_cfg: handle not mapped");
5548 if (sizeof (bscv_wdog_t
) != info
.size
) {
5549 BSCV_TRACE(ssp
, 'W', "bscv_wdog_set", "data passed in is size"
5550 " %d instead of %d", info
.size
,
5551 sizeof (bscv_wdog_t
));
5555 BSCV_TRACE(ssp
, 'W', "bscv_wdog_cfg", "enable_wdog %s, "
5556 "wdog_timeout_s %d, reset_system_on_timeout %s",
5557 ((bscv_wdog_t
*)info
.data
)->enable_wdog
? "enabled" : "disabled",
5558 ((bscv_wdog_t
*)info
.data
)->wdog_timeout_s
,
5559 ((bscv_wdog_t
*)info
.data
)->reset_system_on_timeout
? "yes" : "no");
5560 bscv_write_wdog_cfg(ssp
,
5561 ((bscv_wdog_t
*)info
.data
)->wdog_timeout_s
,
5562 ((bscv_wdog_t
*)info
.data
)->enable_wdog
,
5563 ((bscv_wdog_t
*)info
.data
)->reset_system_on_timeout
);
5566 #endif /* __sparc */
5569 bscv_write_wdog_cfg(bscv_soft_state_t
*ssp
,
5570 uint_t wdog_timeout_s
,
5571 boolean_t enable_wdog
,
5572 uint8_t reset_system_on_timeout
)
5574 uint8_t cfg
= EBUS_WDOG_NB_CFG
;
5577 * Configure the timeout value (1 to 127 seconds).
5578 * Note that a policy is implemented at the bsc/ssp which bounds
5579 * the value further. The bounding here is to fit the timeout value
5580 * into the 7 bits the bsc uses.
5582 if (wdog_timeout_s
< 1)
5583 ssp
->watchdog_timeout
= 1;
5584 else if (wdog_timeout_s
> 127)
5585 ssp
->watchdog_timeout
= 127;
5587 ssp
->watchdog_timeout
= wdog_timeout_s
;
5590 * Configure the watchdog on or off.
5593 cfg
|= EBUS_WDOG_NB_CFG_ENB
;
5595 cfg
&= ~EBUS_WDOG_NB_CFG_ENB
;
5598 * Configure whether the microcontroller should reset the system when
5599 * the watchdog expires.
5601 ssp
->watchdog_reset_on_timeout
= reset_system_on_timeout
;
5603 ddi_put8(ssp
->channel
[chan_wdogpat
].handle
,
5604 ssp
->channel
[chan_wdogpat
].regs
, cfg
);
5606 /* have the event daemon set the timeout value and whether to reset */
5607 ssp
->watchdog_change
= B_TRUE
;
5609 BSCV_TRACE(ssp
, 'W', "bscv_wdog_cfg",
5610 "configured the dog with cfg 0x%x", cfg
);
5614 * function - bscv_setup_watchdog
5615 * description - setup the bsc watchdog
5616 * inputs - soft state ptr
5619 static void bscv_setup_watchdog(bscv_soft_state_t
*ssp
)
5624 extern int watchdog_activated
;
5625 #endif /* __sparc */
5627 ASSERT(bscv_held(ssp
));
5629 /* Set the timeout */
5630 bscv_put8(ssp
, chan_general
,
5631 EBUS_IDX_WDOG_TIME
, ssp
->watchdog_timeout
);
5633 /* Set whether to reset the system on timeout */
5634 if (ssp
->watchdog_reset_on_timeout
) {
5635 set
|= EBUS_WDOG_RST
;
5637 clear
|= EBUS_WDOG_RST
;
5640 if (watchdog_activated
) {
5641 set
|= EBUS_WDOG_ENABLE
;
5643 clear
|= EBUS_WDOG_ENABLE
;
5646 /* Set other host defaults */
5647 clear
|= (EBUS_WDOG_BREAK_DISABLE
| EBUS_WDOG_AL3_FANPSU
5648 | EBUS_WDOG_AL3_WDOG
);
5650 bscv_setclear8_volatile(ssp
, chan_general
, EBUS_IDX_WDOG_CTRL
,
5653 #if defined(__i386) || defined(__amd64)
5654 /* start the cyclic based watchdog patter */
5655 bscv_watchdog_cyclic_add(ssp
);
5656 #endif /* __i386 || __amd64 */
5657 ssp
->progress
|= BSCV_WDOG_CFG
;
5662 * function - bscv_setup_hostname
5663 * description - setup the lom hostname if different from the nodename
5664 * inputs - soft state ptr
5668 static void bscv_setup_hostname(bscv_soft_state_t
*ssp
)
5670 char host_nodename
[128];
5671 char lom_nodename
[128];
5675 ASSERT(bscv_held(ssp
));
5678 * Check machine label is the same as the
5681 (void) strncpy(host_nodename
, utsname
.nodename
,
5682 sizeof (host_nodename
));
5684 /* read in lom hostname */
5685 bscv_read_hostname(ssp
, lom_nodename
);
5687 /* Enforce null termination */
5688 host_nodename
[sizeof (host_nodename
) - 1] = '\0';
5689 lom_nodename
[sizeof (lom_nodename
) - 1] = '\0';
5691 hostlen
= (size_t)bscv_get8(ssp
, chan_general
, EBUS_IDX_HNAME_LENGTH
);
5692 nodelen
= (size_t)strlen(host_nodename
);
5693 if ((nodelen
> 0) &&
5694 ((hostlen
!= nodelen
) || (strcmp((const char *)&lom_nodename
,
5695 (const char *)&host_nodename
)) ||
5697 BSCV_TRACE(ssp
, 'A', "bscv_setup_hostname",
5698 "nodename(%s,%d) != bsc label(%s,%d)",
5699 host_nodename
, nodelen
, lom_nodename
, hostlen
);
5701 /* Write new label into LOM EEPROM */
5702 bscv_write_hostname(ssp
,
5704 (uint8_t)strlen(host_nodename
));
5707 ssp
->progress
|= BSCV_HOSTNAME_DONE
;
5711 * function - bscv_read_hostname
5712 * description - read the current hostname from the lom
5713 * inputs - soft state pointer and buffer to store the hostname in.
5718 bscv_read_hostname(bscv_soft_state_t
*ssp
, char *lom_nodename
)
5721 boolean_t needretry
;
5725 ASSERT(bscv_held(ssp
));
5728 * We have a special failure case here because a retry of a read
5729 * causes data to be lost. Thus we handle the retries ourselves
5730 * and are also responsible for detemining if the lom is faulty
5732 for (num_failures
= 0;
5733 num_failures
< BSC_FAILURE_RETRY_LIMIT
;
5735 bscv_clear_fault(ssp
);
5736 length
= bscv_get8(ssp
, chan_general
, EBUS_IDX_HNAME_LENGTH
);
5737 if (bscv_faulty(ssp
)) {
5741 for (i
= 0; i
< length
; i
++) {
5742 lom_nodename
[i
] = bscv_get8_once(ssp
,
5743 chan_general
, EBUS_IDX_HNAME_CHAR
);
5744 /* Retry on any error */
5745 if (bscv_retcode(ssp
) != 0) {
5750 /* null terminate for strcmp later */
5751 lom_nodename
[length
] = '\0';
5756 /* Force the nodename to be empty */
5757 lom_nodename
[0] = '\0';
5761 /* Failure - we ran out of retries */
5763 "bscv_read_hostname: retried %d times, giving up",
5765 ssp
->had_fault
= B_TRUE
;
5766 } else if (num_failures
> 0) {
5767 BSCV_TRACE(ssp
, 'R', "bscv_read_hostname",
5768 "retried %d times, succeeded", num_failures
);
5773 * function - bscv_write_hostname
5774 * description - write a new hostname to the lom
5775 * inputs - soft state pointer, pointer to new name, name length
5779 bscv_write_hostname(bscv_soft_state_t
*ssp
,
5780 char *host_nodename
, uint8_t length
)
5783 boolean_t needretry
;
5786 ASSERT(bscv_held(ssp
));
5789 * We have a special failure case here because a retry of a read
5790 * causes data to be lost. Thus we handle the retries ourselves
5791 * and are also responsible for detemining if the lom is faulty
5793 for (num_failures
= 0;
5794 num_failures
< BSC_FAILURE_RETRY_LIMIT
;
5796 bscv_clear_fault(ssp
);
5797 bscv_put8(ssp
, chan_general
, EBUS_IDX_HNAME_LENGTH
, length
);
5798 if (bscv_faulty(ssp
)) {
5802 for (i
= 0; i
< length
; i
++) {
5803 bscv_put8_once(ssp
, chan_general
,
5804 EBUS_IDX_HNAME_CHAR
, host_nodename
[i
]);
5805 /* Retry on any error */
5806 if (bscv_retcode(ssp
) != 0) {
5818 /* Failure - we ran out of retries */
5820 "bscv_write_hostname: retried %d times, giving up",
5822 ssp
->had_fault
= B_TRUE
;
5823 } else if (num_failures
> 0) {
5824 BSCV_TRACE(ssp
, 'R', "bscv_write_hostname",
5825 "retried %d times, succeeded", num_failures
);
5830 * function - bscv_setup_static_info
5831 * description - read in static information from the lom at attach time.
5832 * inputs - soft state ptr
5837 bscv_setup_static_info(bscv_soft_state_t
*ssp
)
5839 uint8_t addr_space_ptr
;
5842 int oldtemps
[MAX_TEMPS
];
5846 ASSERT(bscv_held(ssp
));
5849 * Finally read in some static info like device names,
5850 * shutdown enabled, etc before the queue starts.
5854 * To get the volts static info we need address space 2
5856 bzero(&ssp
->volts
, sizeof (lom_volts_t
));
5857 ssp
->volts
.num
= EBUS_CONFIG2_NSUPPLY_DEC(
5858 bscv_get8(ssp
, chan_general
, EBUS_IDX_CONFIG2
));
5859 if (ssp
->volts
.num
> MAX_VOLTS
) {
5861 "lom: firmware reported too many voltage lines. ");
5862 cmn_err(CE_CONT
, "Reported %d, maximum is %d",
5863 ssp
->volts
.num
, MAX_VOLTS
);
5864 ssp
->volts
.num
= MAX_VOLTS
;
5867 BSCV_TRACE(ssp
, 'A', "bscv_setup_static_info",
5868 "num volts %d", ssp
->volts
.num
);
5869 (void) bscv_read_env_name(ssp
,
5871 EBUS_IDX2_SUPPLY_NAME_START
,
5872 EBUS_IDX2_SUPPLY_NAME_END
,
5876 mask
= bscv_get8(ssp
, chan_general
, BSCVA(EBUS_CMD_SPACE2
,
5877 EBUS_IDX2_SUPPLY_FATAL_MASK1
)) << 8;
5878 mask
|= bscv_get8(ssp
, chan_general
, BSCVA(EBUS_CMD_SPACE2
,
5879 EBUS_IDX2_SUPPLY_FATAL_MASK2
));
5881 for (i
= 0; i
< ssp
->volts
.num
; i
++) {
5882 ssp
->volts
.shutdown_enabled
[i
] =
5883 (((mask
>> i
) & 1) == 0) ? 0 : 1;
5887 * Get the temperature static info and populate initial temperatures.
5888 * Do not destroy old temperature values if the new value is not
5889 * known i.e. if the device is inaccessible.
5891 bcopy(ssp
->temps
.temp
, oldtemps
, sizeof (oldtemps
));
5893 bzero(&ssp
->temps
, sizeof (lom_temp_t
));
5894 ssp
->temps
.num
= EBUS_CONFIG2_NTEMP_DEC(
5895 bscv_get8(ssp
, chan_general
, EBUS_IDX_CONFIG2
));
5896 if (ssp
->temps
.num
> MAX_TEMPS
) {
5898 "lom: firmware reported too many temperatures being "
5900 cmn_err(CE_CONT
, "Reported %d, maximum is %d",
5901 ssp
->temps
.num
, MAX_TEMPS
);
5902 ssp
->temps
.num
= MAX_TEMPS
;
5904 ssp
->temps
.num_ov
= EBUS_CONFIG3_NOTEMP_DEC(
5905 bscv_get8(ssp
, chan_general
, EBUS_IDX_CONFIG3
));
5906 if (ssp
->temps
.num_ov
> MAX_TEMPS
) {
5908 "lom: firmware reported too many over temperatures being "
5910 cmn_err(CE_CONT
, "Reported %d, maximum is %d",
5911 ssp
->temps
.num_ov
, MAX_TEMPS
);
5912 ssp
->temps
.num_ov
= MAX_TEMPS
;
5914 BSCV_TRACE(ssp
, 'A', "bscv_setup_static_info",
5915 "num temps %d, over temps %d",
5916 ssp
->temps
.num
, ssp
->temps
.num_ov
);
5918 addr_space_ptr
= bscv_read_env_name(ssp
,
5920 EBUS_IDX4_TEMP_NAME_START
,
5921 EBUS_IDX4_TEMP_NAME_END
,
5925 for (i
= 0; i
< ssp
->temps
.num
; i
++) {
5926 ssp
->temps
.warning
[i
] = (int8_t)bscv_get8(ssp
, chan_general
,
5927 BSCVA(EBUS_CMD_SPACE4
, EBUS_IDX4_TEMP_WARN1
+ i
));
5930 * If shutdown is not enabled then set it as zero so
5931 * it is not displayed by the utility.
5933 if ((bscv_get8(ssp
, chan_general
, BSCVA(EBUS_CMD_SPACE4
,
5934 EBUS_IDX4_TEMP_FATAL_MASK
)) >> i
) & 0x01) {
5935 ssp
->temps
.shutdown
[i
] = (int8_t)bscv_get8(ssp
,
5937 BSCVA(EBUS_CMD_SPACE4
, EBUS_IDX4_TEMP_SDOWN1
+ i
));
5939 ssp
->temps
.shutdown
[i
] = 0;
5943 for (i
= 0; i
< ssp
->temps
.num
; i
++) {
5944 temp
= bscv_get8(ssp
, chan_general
, EBUS_IDX_TEMP1
+ i
);
5945 if ((temp
<= LOM_TEMP_MAX_VALUE
) ||
5946 (temp
== LOM_TEMP_STATE_NOT_PRESENT
)) {
5947 ssp
->temps
.temp
[i
] = temp
;
5949 /* New value is not known - use old value */
5950 ssp
->temps
.temp
[i
] = oldtemps
[i
];
5955 * Check for and skip a single 0xff character between the
5956 * temperature and over temperature names
5958 if (bscv_get8(ssp
, chan_general
,
5959 BSCVA(EBUS_CMD_SPACE4
, addr_space_ptr
)) == 0xff) {
5963 (void) bscv_read_env_name(ssp
,
5966 EBUS_IDX4_TEMP_NAME_END
,
5971 * To get the CB static info we need address space 3
5973 bzero(&ssp
->sflags
, sizeof (lom_sflags_t
));
5974 ssp
->sflags
.num
= EBUS_CONFIG3_NBREAKERS_DEC(bscv_get8(ssp
,
5975 chan_general
, EBUS_IDX_CONFIG3
));
5976 if (ssp
->sflags
.num
> MAX_STATS
) {
5978 "lom: firmware reported too many status flags.");
5980 "Reported %d, maximum is %d",
5981 ssp
->sflags
.num
, MAX_STATS
);
5982 ssp
->sflags
.num
= MAX_STATS
;
5984 BSCV_TRACE(ssp
, 'A', "bscv_setup_static_info",
5985 "num sflags %d", ssp
->sflags
.num
);
5987 (void) bscv_read_env_name(ssp
,
5989 EBUS_IDX3_BREAKER_NAME_START
,
5990 EBUS_IDX3_BREAKER_NAME_END
,
5996 * To get the fan static info we need address space 5
5998 ssp
->num_fans
= EBUS_CONFIG_NFAN_DEC(
5999 bscv_get8(ssp
, chan_general
, EBUS_IDX_CONFIG
));
6000 if (ssp
->num_fans
> MAX_FANS
) {
6002 "lom: firmware reported too many fans. ");
6004 "Reported %d, maximum is %d",
6005 ssp
->num_fans
, MAX_FANS
);
6006 ssp
->num_fans
= MAX_FANS
;
6009 for (i
= 0; i
< ssp
->num_fans
; i
++) {
6010 fanspeed
= bscv_get8(ssp
, chan_general
,
6011 EBUS_IDX_FAN1_SPEED
+ i
);
6012 if ((fanspeed
<= LOM_FAN_MAX_SPEED
) ||
6013 (fanspeed
== LOM_FAN_NOT_PRESENT
)) {
6015 * Do not destroy previous values unless the
6016 * value is definitive.
6018 ssp
->fanspeed
[i
] = fanspeed
;
6022 BSCV_TRACE(ssp
, 'A', "bscv_setup_static_info",
6023 "num fans %d", ssp
->num_fans
);
6025 (void) bscv_read_env_name(ssp
,
6027 EBUS_IDX5_FAN_NAME_START
,
6028 EBUS_IDX5_FAN_NAME_END
,
6032 /* Get led static information from address space 10 */
6034 (void) bscv_read_env_name(ssp
,
6035 EBUS_CMD_SPACE_LEDS
,
6036 EBUS_IDX10_LED_NAME_START
,
6037 EBUS_IDX10_LED_NAME_END
,
6043 * function - bscv_read_env_name
6044 * description - read in static environment names
6045 * warning changes address space and the caller relies
6046 * on this behaviour.
6047 * inputs - soft state ptr, chosen address space,
6048 * start of name data, end of name data,
6049 * name storage, number of names.
6050 * outputs - next address for reading name data.
6054 bscv_read_env_name(bscv_soft_state_t
*ssp
,
6058 char namebuf
[][MAX_LOM2_NAME_STR
],
6064 unsigned int addr_space_ptr
;
6067 ASSERT(bscv_held(ssp
));
6069 BSCV_TRACE(ssp
, 'A', "bscv_read_env_name",
6070 "bscv_read_env_name, space %d, start 0x%x, end 0x%x, numnames %d",
6071 addr_space
, addr_start
, addr_end
, numnames
);
6073 addr_space_ptr
= addr_start
;
6075 for (i
= 0; i
< numnames
; i
++) {
6077 namemax
= sizeof (namebuf
[i
]);
6078 bzero(namebuf
[i
], namemax
);
6080 while (addr_space_ptr
<= addr_end
) {
6082 * Read the current character.
6084 this_char
= bscv_get8(ssp
, chan_general
,
6085 BSCVA(addr_space
, addr_space_ptr
));
6087 if (this_char
== 0xff) {
6089 * Ran out of names - this must
6090 * be the end of the name.
6091 * This is really an error because
6092 * we have just seen either a non-NUL
6093 * terminated string or the number of
6094 * strings did not match what was
6100 * We increment the buffer pointer now so that
6101 * it is ready for the next read
6105 if (this_char
== '\0') {
6106 /* Found end of string - done */
6109 if (nameidx
< (namemax
- 1)) {
6111 * Buffer not full - record character
6112 * NOTE we always leave room for the NUL
6115 namebuf
[i
][nameidx
++] = this_char
;
6118 /* Ensure null termination */
6119 namebuf
[i
][nameidx
] = '\0';
6121 /* Clamp addr_space_ptr to 0xff because we return uint8_t */
6122 if (addr_space_ptr
> 0xff) {
6123 addr_space_ptr
= 0xff;
6125 return (addr_space_ptr
);
6129 * function - bscv_setup_events
6130 * description - initialise the event reporting code
6131 * inputs - soft state ptr
6132 * outputs - DDI_SUCCESS or DDI_FAILURE
6136 bscv_setup_events(bscv_soft_state_t
*ssp
)
6141 ASSERT(bscv_held(ssp
));
6144 * deal with event reporting - cover all cases
6149 if (ssp
->serial_reporting
== LOM_SER_EVENTS_ON
) {
6150 bits2clear
|= EBUS_ALARM_NOEVENTS
;
6151 } else if (ssp
->serial_reporting
== LOM_SER_EVENTS_OFF
) {
6152 bits2set
|= EBUS_ALARM_NOEVENTS
;
6153 } else if (ssp
->serial_reporting
== LOM_SER_EVENTS_DEF
) {
6154 bits2set
|= EBUS_ALARM_NOEVENTS
;
6156 bscv_setclear8_volatile(ssp
, chan_general
, EBUS_IDX_ALARM
,
6157 bits2set
, bits2clear
);
6162 * function - bscv_write_sig
6163 * description - write out a signature, taking care to deal with any strange
6165 * inputs - soft state ptr, signature
6169 bscv_write_sig(bscv_soft_state_t
*ssp
, bscv_sig_t s
)
6171 ASSERT(bscv_held(ssp
));
6173 /* Upload the signature */
6174 bscv_put32(ssp
, chan_cpusig
,
6175 BSCVA(EBUS_CMD_SPACE_CPUSIG
, EBUS_IDX11_CPU_SIG_MSB
),
6176 s
.sig_info
.signature
);
6179 * We always write the CPU ID last because this tells the firmware
6180 * that the signature is fully uploaded and therefore to consume the
6181 * data. This is required since the signature is > 1 byte in size
6182 * and we transmit data in single bytes.
6185 /* ~0 means the signature applies to any CPU. */
6186 bscv_put8(ssp
, chan_cpusig
,
6187 BSCVA(EBUS_CMD_SPACE_CPUSIG
, EBUS_IDX11_CPU_ID
),
6192 * The CPU ID supplied is unexpectedly large. Lets
6193 * just use the bottom bits, in case other high order
6194 * bits are being used for special meaning.
6196 cmn_err(CE_WARN
, "CPU Signature ID 0x%x > 255", s
.cpu
);
6198 cmn_err(CE_CONT
, "using ID 0x%x instead ", s
.cpu
);
6200 bscv_put8(ssp
, chan_cpusig
,
6201 BSCVA(EBUS_CMD_SPACE_CPUSIG
, EBUS_IDX11_CPU_ID
),
6206 ssp
->progress
|= BSCV_SIG_SENT
;
6208 #endif /* __sparc */
6210 #if defined(__i386) || defined(__amd64)
6213 * function - bscv_inform_bsc
6214 * description - inform bsc of driver state for logging purposes
6215 * inputs - driver soft state, state
6220 bscv_inform_bsc(bscv_soft_state_t
*ssp
, uint32_t state
)
6222 ASSERT(bscv_held(ssp
));
6224 BSCV_TRACE(ssp
, 'X', "bscv_inform_bsc",
6225 "bscv_inform_bsc: state=%d", state
);
6227 bscv_put32(ssp
, chan_general
,
6228 BSCVA(EBUS_CMD_SPACE_CPUSIG
, EBUS_IDX11_CPU_SIG_MSB
), state
);
6229 bscv_put8(ssp
, chan_cpusig
,
6230 BSCVA(EBUS_CMD_SPACE_CPUSIG
, EBUS_IDX11_CPU_ID
), EBUS_ANY_CPU_ID
);
6234 * function - bscv_watchdog_pat_request
6235 * description - request a heartbeat pat
6236 * inputs - timeout value in seconds
6240 bscv_watchdog_pat_request(void *arg
)
6242 bscv_soft_state_t
*ssp
= (bscv_soft_state_t
*)arg
;
6244 bscv_wdog_do_pat(ssp
);
6248 * function - bscv_watchdog_cfg_request
6249 * description - request configuration of the bsc hardware watchdog
6250 * inputs - new state (0=disabled, 1=enabled)
6251 * outputs - one if successful, zero if unsuccesful
6254 bscv_watchdog_cfg_request(bscv_soft_state_t
*ssp
, uint8_t new_state
)
6256 ASSERT(new_state
== WDOG_ON
|| new_state
== WDOG_OFF
);
6258 watchdog_activated
= new_state
;
6259 BSCV_TRACE(ssp
, 'X', "bscv_watchdog_cfg_request",
6260 "watchdog_activated=%d", watchdog_activated
);
6261 bscv_write_wdog_cfg(ssp
,
6262 bscv_watchdog_timeout_seconds
,
6264 wdog_reset_on_timeout
);
6268 * function - bscv_set_watchdog_timer
6269 * description - setup the heartbeat timeout value
6270 * inputs - timeout value in seconds
6271 * outputs - zero if the value was not changed
6272 * otherwise the current value
6275 bscv_set_watchdog_timer(bscv_soft_state_t
*ssp
, uint_t timeoutval
)
6277 BSCV_TRACE(ssp
, 'X', "bscv_set_watchdog_timer:",
6278 "timeout=%d", timeoutval
);
6281 * We get started during bscv_attach only
6282 * if bscv_watchdog_enable is set.
6284 if (bscv_watchdog_available
&& (!watchdog_activated
||
6285 (watchdog_activated
&&
6286 (timeoutval
!= bscv_watchdog_timeout_seconds
)))) {
6287 bscv_watchdog_timeout_seconds
= timeoutval
;
6288 bscv_watchdog_cfg_request(ssp
, WDOG_ON
);
6289 return (bscv_watchdog_timeout_seconds
);
6295 * function - bscv_clear_watchdog_timer
6296 * description - add the watchdog patter cyclic
6297 * inputs - driver soft state
6298 * outputs - value of watchdog timeout in seconds
6300 * This function is a copy of the SPARC implementation
6301 * in the todblade clock driver.
6304 bscv_clear_watchdog_timer(bscv_soft_state_t
*ssp
)
6306 BSCV_TRACE(ssp
, 'X', "bscv_clear_watchdog_timer", "");
6308 if (bscv_watchdog_available
&& watchdog_activated
) {
6309 bscv_watchdog_enable
= 0;
6310 bscv_watchdog_cfg_request(ssp
, WDOG_OFF
);
6315 * function - bscv_panic_callback
6316 * description - called when we panic so we can disabled the watchdog
6317 * inputs - driver soft state pointer
6318 * outputs - DDI_SUCCESS
6322 bscv_panic_callback(void *arg
, int code
)
6324 bscv_soft_state_t
*ssp
= (bscv_soft_state_t
*)arg
;
6326 BSCV_TRACE(ssp
, 'X', "bscv_panic_callback",
6327 "disabling watchdog");
6329 bscv_clear_watchdog_timer(ssp
);
6331 * We dont get interrupts during the panic callback. But bscbus
6332 * takes care of all this
6334 bscv_full_stop(ssp
);
6335 return (DDI_SUCCESS
);
6339 * function - bscv_watchdog_cyclic_add
6340 * description - add the watchdog patter cyclic
6341 * inputs - driver soft state
6345 bscv_watchdog_cyclic_add(bscv_soft_state_t
*ssp
)
6347 if (ssp
->periodic_id
!= NULL
) {
6351 ssp
->periodic_id
= ddi_periodic_add(bscv_watchdog_pat_request
, ssp
,
6352 WATCHDOG_PAT_INTERVAL
, DDI_IPL_10
);
6354 BSCV_TRACE(ssp
, 'X', "bscv_watchdog_cyclic_add:",
6359 * function - bscv_watchdog_cyclic_remove
6360 * description - remove the watchdog patter cyclic
6361 * inputs - soft state ptr
6365 bscv_watchdog_cyclic_remove(bscv_soft_state_t
*ssp
)
6367 if (ssp
->periodic_id
== NULL
) {
6370 ddi_periodic_delete(ssp
->periodic_id
);
6371 ssp
->periodic_id
= NULL
;
6372 BSCV_TRACE(ssp
, 'X', "bscv_watchdog_cyclic_remove:",
6375 #endif /* __i386 || __amd64 */
6379 * General utility routines ...
6385 bscv_trace(bscv_soft_state_t
*ssp
, char code
, const char *caller
,
6386 const char *fmt
, ...)
6392 if (ssp
->debug
& (1 << (code
-'@'))) {
6394 (void) snprintf(p
, sizeof (buf
) - (p
- buf
),
6395 "%s/%s: ", MYNAME
, caller
);
6399 (void) vsnprintf(p
, sizeof (buf
) - (p
- buf
), fmt
, va
);
6402 buf
[sizeof (buf
) - 1] = '\0';
6403 (void) strlog((short)ssp
->majornum
, (short)ssp
->minornum
, code
,
6412 bscv_trace(bscv_soft_state_t
*ssp
, char code
, const char *caller
,
6413 const char *fmt
, ...)