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