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