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