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