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