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