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