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 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 28 #include <sys/types.h> 29 #include <sys/conf.h> 30 #include <sys/ddi.h> 31 #include <sys/sunddi.h> 32 #include <sys/ddi_impldefs.h> 33 #include <sys/obpdefs.h> 34 #include <sys/promif.h> 35 #include <sys/cmn_err.h> 36 #include <sys/errno.h> 37 #include <sys/kmem.h> 38 #include <sys/vmem.h> 39 #include <sys/debug.h> 40 #include <sys/sysmacros.h> 41 #include <sys/intreg.h> 42 #include <sys/autoconf.h> 43 #include <sys/modctl.h> 44 #include <sys/spl.h> 45 #include <sys/time.h> 46 #include <sys/systm.h> 47 #include <sys/machsystm.h> 48 #include <sys/cpu.h> 49 #include <sys/cpuvar.h> 50 #include <sys/x_call.h> /* xt_one() */ 51 #include <sys/membar.h> 52 #include <sys/vm.h> 53 #include <vm/seg_kmem.h> 54 #include <vm/hat_sfmmu.h> 55 #include <sys/promimpl.h> 56 #include <sys/prom_plat.h> 57 #include <sys/cpu_module.h> /* flush_instr_mem() */ 58 #include <sys/procset.h> 59 #include <sys/fhc.h> 60 #include <sys/ac.h> 61 #include <sys/environ.h> 62 #include <sys/jtag.h> 63 #include <sys/nexusdebug.h> 64 #include <sys/ac.h> 65 #include <sys/ddi_subrdefs.h> 66 #include <sys/eeprom.h> 67 #include <sys/sdt.h> 68 #include <sys/ddi_implfuncs.h> 69 #include <sys/ontrap.h> 70 71 #ifndef TRUE 72 #define TRUE (1) 73 #endif 74 #ifndef FALSE 75 #define FALSE (0) 76 #endif 77 78 /* 79 * Function to register and deregister callbacks, for sunfire only. 80 */ 81 extern void plat_register_tod_fault(void (*func)(enum tod_fault_type)); 82 83 /* 84 * This table represents the FHC interrupt priorities. They range from 85 * 1-15, and have been modeled after the sun4d interrupts. The mondo 86 * number anded with 0x7 is used to index into this table. This was 87 * done to save table space. 88 */ 89 static int fhc_int_priorities[] = { 90 PIL_15, /* System interrupt priority */ 91 PIL_12, /* zs interrupt priority */ 92 PIL_15, /* TOD interrupt priority */ 93 PIL_15 /* Fan Fail priority */ 94 }; 95 96 static void fhc_tod_fault(enum tod_fault_type tod_bad); 97 98 /* 99 * The dont_calibrate variable is meant to be set to one in /etc/system 100 * or by boot -h so that the calibration tables are not used. This 101 * is useful for checking thermistors whose output seems to be incorrect. 102 */ 103 static int dont_calibrate = 0; 104 105 /* Only one processor should powerdown the system. */ 106 static int powerdown_started = 0; 107 108 /* Let user disable overtemp powerdown. */ 109 int enable_overtemp_powerdown = 1; 110 111 /* 112 * The following tables correspond to the degress Celcius for each count 113 * value possible from the 8-bit A/C convertors on each type of system 114 * board for the UltraSPARC Server systems. To access a temperature, 115 * just index into the correct table using the count from the A/D convertor 116 * register, and that is the correct temperature in degress Celsius. These 117 * values can be negative. 118 */ 119 static short cpu_table[] = { 120 -16, -14, -12, -10, -8, -6, -4, -2, /* 0-7 */ 121 1, 4, 6, 8, 10, 12, 13, 15, /* 8-15 */ 122 16, 18, 19, 20, 22, 23, 24, 25, /* 16-23 */ 123 26, 27, 28, 29, 30, 31, 32, 33, /* 24-31 */ 124 34, 35, 35, 36, 37, 38, 39, 39, /* 32-39 */ 125 40, 41, 41, 42, 43, 44, 44, 45, /* 40-47 */ 126 46, 46, 47, 47, 48, 49, 49, 50, /* 48-55 */ 127 51, 51, 52, 53, 53, 54, 54, 55, /* 56-63 */ 128 55, 56, 56, 57, 57, 58, 58, 59, /* 64-71 */ 129 60, 60, 61, 61, 62, 62, 63, 63, /* 72-79 */ 130 64, 64, 65, 65, 66, 66, 67, 67, /* 80-87 */ 131 68, 68, 69, 69, 70, 70, 71, 71, /* 88-95 */ 132 72, 72, 73, 73, 74, 74, 75, 75, /* 96-103 */ 133 76, 76, 77, 77, 78, 78, 79, 79, /* 104-111 */ 134 80, 80, 81, 81, 82, 82, 83, 83, /* 112-119 */ 135 84, 84, 85, 85, 86, 86, 87, 87, /* 120-127 */ 136 88, 88, 89, 89, 90, 90, 91, 91, /* 128-135 */ 137 92, 92, 93, 93, 94, 94, 95, 95, /* 136-143 */ 138 96, 96, 97, 98, 98, 99, 99, 100, /* 144-151 */ 139 100, 101, 101, 102, 103, 103, 104, 104, /* 152-159 */ 140 105, 106, 106, 107, 107, 108, 109, 109, /* 160-167 */ 141 110, /* 168 */ 142 }; 143 144 #define CPU_MX_CNT (sizeof (cpu_table)/sizeof (short)) 145 146 static short cpu2_table[] = { 147 -17, -16, -15, -14, -13, -12, -11, -10, /* 0-7 */ 148 -9, -8, -7, -6, -5, -4, -3, -2, /* 8-15 */ 149 -1, 0, 1, 2, 3, 4, 5, 6, /* 16-23 */ 150 7, 8, 9, 10, 11, 12, 13, 13, /* 24-31 */ 151 14, 15, 16, 16, 17, 18, 18, 19, /* 32-39 */ 152 20, 20, 21, 22, 22, 23, 24, 24, /* 40-47 */ 153 25, 25, 26, 26, 27, 27, 28, 28, /* 48-55 */ 154 29, 30, 30, 31, 31, 32, 32, 33, /* 56-63 */ 155 33, 34, 34, 35, 35, 36, 36, 37, /* 64-71 */ 156 37, 37, 38, 38, 39, 39, 40, 40, /* 72-79 */ 157 41, 41, 42, 42, 43, 43, 43, 44, /* 80-87 */ 158 44, 45, 45, 46, 46, 46, 47, 47, /* 88-95 */ 159 48, 48, 49, 49, 50, 50, 50, 51, /* 96-103 */ 160 51, 52, 52, 53, 53, 53, 54, 54, /* 104-111 */ 161 55, 55, 56, 56, 56, 57, 57, 58, /* 112-119 */ 162 58, 59, 59, 59, 60, 60, 61, 61, /* 120-127 */ 163 62, 62, 63, 63, 63, 64, 64, 65, /* 128-135 */ 164 65, 66, 66, 67, 67, 68, 68, 68, /* 136-143 */ 165 69, 69, 70, 70, 71, 71, 72, 72, /* 144-151 */ 166 73, 73, 74, 74, 75, 75, 76, 76, /* 152-159 */ 167 77, 77, 78, 78, 79, 79, 80, 80, /* 160-167 */ 168 81, 81, 82, 83, 83, 84, 84, 85, /* 168-175 */ 169 85, 86, 87, 87, 88, 88, 89, 90, /* 176-183 */ 170 90, 91, 92, 92, 93, 94, 94, 95, /* 184-191 */ 171 96, 96, 97, 98, 99, 99, 100, 101, /* 192-199 */ 172 102, 103, 103, 104, 105, 106, 107, 108, /* 200-207 */ 173 109, 110, /* 208-209 */ 174 }; 175 176 #define CPU2_MX_CNT (sizeof (cpu2_table)/sizeof (short)) 177 178 static short io_table[] = { 179 0, 0, 0, 0, 0, 0, 0, 0, /* 0-7 */ 180 0, 0, 0, 0, 0, 0, 0, 0, /* 8-15 */ 181 0, 0, 0, 0, 0, 0, 0, 0, /* 16-23 */ 182 0, 0, 0, 0, 0, 0, 0, 0, /* 24-31 */ 183 0, 0, 0, 0, 0, 0, 0, 0, /* 32-39 */ 184 0, 3, 7, 10, 13, 15, 17, 19, /* 40-47 */ 185 21, 23, 25, 27, 28, 30, 31, 32, /* 48-55 */ 186 34, 35, 36, 37, 38, 39, 41, 42, /* 56-63 */ 187 43, 44, 45, 46, 46, 47, 48, 49, /* 64-71 */ 188 50, 51, 52, 53, 53, 54, 55, 56, /* 72-79 */ 189 57, 57, 58, 59, 60, 60, 61, 62, /* 80-87 */ 190 62, 63, 64, 64, 65, 66, 66, 67, /* 88-95 */ 191 68, 68, 69, 70, 70, 71, 72, 72, /* 96-103 */ 192 73, 73, 74, 75, 75, 76, 77, 77, /* 104-111 */ 193 78, 78, 79, 80, 80, 81, 81, 82, /* 112-119 */ 194 }; 195 196 #define IO_MN_CNT 40 197 #define IO_MX_CNT (sizeof (io_table)/sizeof (short)) 198 199 static short clock_table[] = { 200 0, 0, 0, 0, 0, 0, 0, 0, /* 0-7 */ 201 0, 0, 0, 0, 1, 2, 4, 5, /* 8-15 */ 202 7, 8, 10, 11, 12, 13, 14, 15, /* 16-23 */ 203 17, 18, 19, 20, 21, 22, 23, 24, /* 24-31 */ 204 24, 25, 26, 27, 28, 29, 29, 30, /* 32-39 */ 205 31, 32, 32, 33, 34, 35, 35, 36, /* 40-47 */ 206 37, 38, 38, 39, 40, 40, 41, 42, /* 48-55 */ 207 42, 43, 44, 44, 45, 46, 46, 47, /* 56-63 */ 208 48, 48, 49, 50, 50, 51, 52, 52, /* 64-71 */ 209 53, 54, 54, 55, 56, 57, 57, 58, /* 72-79 */ 210 59, 59, 60, 60, 61, 62, 63, 63, /* 80-87 */ 211 64, 65, 65, 66, 67, 68, 68, 69, /* 88-95 */ 212 70, 70, 71, 72, 73, 74, 74, 75, /* 96-103 */ 213 76, 77, 78, 78, 79, 80, 81, 82, /* 104-111 */ 214 }; 215 216 #define CLK_MN_CNT 11 217 #define CLK_MX_CNT (sizeof (clock_table)/sizeof (short)) 218 219 /* 220 * System temperature limits. 221 * 222 * The following variables are the warning and danger limits for the 223 * different types of system boards. The limits are different because 224 * the various boards reach different nominal temperatures because 225 * of the different components that they contain. 226 * 227 * The warning limit is the temperature at which the user is warned. 228 * The danger limit is the temperature at which the system is shutdown. 229 * In the case of CPU/Memory system boards, the system will attempt 230 * to offline and power down processors on a board in an attempt to 231 * bring the board back into the nominal temperature range before 232 * shutting down the system. 233 * 234 * These values can be tuned via /etc/system or boot -h. 235 */ 236 short cpu_warn_temp = 73; /* CPU/Memory Warning Temperature */ 237 short cpu_danger_temp = 83; /* CPU/Memory Danger Temperature */ 238 short io_warn_temp = 60; /* IO Board Warning Temperature */ 239 short io_danger_temp = 68; /* IO Board Danger Temperature */ 240 short clk_warn_temp = 60; /* Clock Board Warning Temperature */ 241 short clk_danger_temp = 68; /* Clock Board Danger Temperature */ 242 243 short dft_warn_temp = 60; /* default warning temp value */ 244 short dft_danger_temp = 68; /* default danger temp value */ 245 246 short cpu_warn_temp_4x = 60; /* CPU/Memory warning temp for 400 MHZ */ 247 short cpu_danger_temp_4x = 68; /* CPU/Memory danger temp for 400 MHZ */ 248 249 /* 250 * This variable tells us if we are in a heat chamber. It is set 251 * early on in boot, after we check the OBP 'mfg-mode' property in 252 * the options node. 253 */ 254 static int temperature_chamber = -1; 255 256 /* 257 * The fhc memloc structure is protected under the bdlist lock 258 */ 259 static struct fhc_memloc *fhc_base_memloc = NULL; 260 261 /* 262 * Driver global fault list mutex and list head pointer. The list is 263 * protected by the mutex and contains a record of all known faults. 264 * Faults can be inherited from the PROM or detected by the kernel. 265 */ 266 static kmutex_t ftlist_mutex; 267 static struct ft_link_list *ft_list = NULL; 268 static int ft_nfaults = 0; 269 270 /* 271 * Table of all known fault strings. This table is indexed by the fault 272 * type. Do not change the ordering of the table without redefining the 273 * fault type enum list on fhc.h. 274 */ 275 char *ft_str_table[] = { 276 "Core Power Supply", /* FT_CORE_PS */ 277 "Overtemp", /* FT_OVERTEMP */ 278 "AC Power", /* FT_AC_PWR */ 279 "Peripheral Power Supply", /* FT_PPS */ 280 "System 3.3 Volt Power", /* FT_CLK_33 */ 281 "System 5.0 Volt Power", /* FT_CLK_50 */ 282 "Peripheral 5.0 Volt Power", /* FT_V5_P */ 283 "Peripheral 12 Volt Power", /* FT_V12_P */ 284 "Auxiliary 5.0 Volt Power", /* FT_V5_AUX */ 285 "Peripheral 5.0 Volt Precharge", /* FT_V5_P_PCH */ 286 "Peripheral 12 Volt Precharge", /* FT_V12_P_PCH */ 287 "System 3.3 Volt Precharge", /* FT_V3_PCH */ 288 "System 5.0 Volt Precharge", /* FT_V5_PCH */ 289 "Peripheral Power Supply Fans", /* FT_PPS_FAN */ 290 "Rack Exhaust Fan", /* FT_RACK_EXH */ 291 "Disk Drive Fan", /* FT_DSK_FAN */ 292 "AC Box Fan", /* FT_AC_FAN */ 293 "Key Switch Fan", /* FT_KEYSW_FAN */ 294 "Minimum Power", /* FT_INSUFFICIENT_POWER */ 295 "PROM detected", /* FT_PROM */ 296 "Hot Plug Support System", /* FT_HOT_PLUG */ 297 "TOD" /* FT_TODFAULT */ 298 }; 299 300 static int ft_max_index = (sizeof (ft_str_table) / sizeof (char *)); 301 302 /* 303 * Function prototypes 304 */ 305 static int fhc_ctlops(dev_info_t *, dev_info_t *, ddi_ctl_enum_t, 306 void *, void *); 307 static int fhc_intr_ops(dev_info_t *dip, dev_info_t *rdip, 308 ddi_intr_op_t intr_op, ddi_intr_handle_impl_t *hdlp, void *result); 309 310 static int fhc_add_intr_impl(dev_info_t *dip, dev_info_t *rdip, 311 ddi_intr_handle_impl_t *hdlp); 312 static void fhc_remove_intr_impl(dev_info_t *dip, dev_info_t *rdip, 313 ddi_intr_handle_impl_t *hdlp); 314 315 static int fhc_attach(dev_info_t *devi, ddi_attach_cmd_t cmd); 316 static int fhc_detach(dev_info_t *devi, ddi_detach_cmd_t cmd); 317 static int fhc_init(struct fhc_soft_state *softsp); 318 static void fhc_unmap_regs(struct fhc_soft_state *softsp); 319 static enum board_type fhc_board_type(struct fhc_soft_state *, int); 320 321 static void 322 fhc_xlate_intrs(ddi_intr_handle_impl_t *hdlp, uint32_t ign); 323 324 static int 325 fhc_ctlops_peekpoke(ddi_ctl_enum_t, peekpoke_ctlops_t *, void *result); 326 327 static void fhc_add_kstats(struct fhc_soft_state *); 328 static int fhc_kstat_update(kstat_t *, int); 329 static int check_for_chamber(void); 330 static int ft_ks_snapshot(struct kstat *, void *, int); 331 static int ft_ks_update(struct kstat *, int); 332 static int check_central(int board); 333 334 /* 335 * board type and A/D convertor output passed in and real temperature 336 * is returned. 337 */ 338 static short calibrate_temp(enum board_type, uchar_t, uint_t); 339 static enum temp_state get_temp_state(enum board_type, short, int); 340 341 /* Routine to determine if there are CPUs on this board. */ 342 static int cpu_on_board(int); 343 344 static void build_bd_display_str(char *, enum board_type, int); 345 346 /* Interrupt distribution callback function. */ 347 static void fhc_intrdist(void *); 348 349 /* CPU power control */ 350 int fhc_cpu_poweroff(struct cpu *); /* cpu_poweroff()->platform */ 351 int fhc_cpu_poweron(struct cpu *); /* cpu_poweron()->platform */ 352 353 extern struct cpu_node cpunodes[]; 354 extern void halt(char *); 355 356 /* 357 * Configuration data structures 358 */ 359 static struct bus_ops fhc_bus_ops = { 360 BUSO_REV, 361 ddi_bus_map, /* map */ 362 0, /* get_intrspec */ 363 0, /* add_intrspec */ 364 0, /* remove_intrspec */ 365 i_ddi_map_fault, /* map_fault */ 366 ddi_no_dma_map, /* dma_map */ 367 ddi_no_dma_allochdl, 368 ddi_no_dma_freehdl, 369 ddi_no_dma_bindhdl, 370 ddi_no_dma_unbindhdl, 371 ddi_no_dma_flush, 372 ddi_no_dma_win, 373 ddi_dma_mctl, /* dma_ctl */ 374 fhc_ctlops, /* ctl */ 375 ddi_bus_prop_op, /* prop_op */ 376 0, /* (*bus_get_eventcookie)(); */ 377 0, /* (*bus_add_eventcall)(); */ 378 0, /* (*bus_remove_eventcall)(); */ 379 0, /* (*bus_post_event)(); */ 380 0, /* (*bus_intr_control)(); */ 381 0, /* (*bus_config)(); */ 382 0, /* (*bus_unconfig)(); */ 383 0, /* (*bus_fm_init)(); */ 384 0, /* (*bus_fm_fini)(); */ 385 0, /* (*bus_fm_access_enter)(); */ 386 0, /* (*bus_fm_access_exit)(); */ 387 0, /* (*bus_power)(); */ 388 fhc_intr_ops /* (*bus_intr_op)(); */ 389 }; 390 391 static struct cb_ops fhc_cb_ops = { 392 nulldev, /* open */ 393 nulldev, /* close */ 394 nulldev, /* strategy */ 395 nulldev, /* print */ 396 nulldev, /* dump */ 397 nulldev, /* read */ 398 nulldev, /* write */ 399 nulldev, /* ioctl */ 400 nodev, /* devmap */ 401 nodev, /* mmap */ 402 nodev, /* segmap */ 403 nochpoll, /* poll */ 404 ddi_prop_op, /* cb_prop_op */ 405 0, /* streamtab */ 406 D_MP|D_NEW|D_HOTPLUG, /* Driver compatibility flag */ 407 CB_REV, /* rev */ 408 nodev, /* cb_aread */ 409 nodev /* cb_awrite */ 410 }; 411 412 static struct dev_ops fhc_ops = { 413 DEVO_REV, /* rev */ 414 0, /* refcnt */ 415 ddi_no_info, /* getinfo */ 416 nulldev, /* identify */ 417 nulldev, /* probe */ 418 fhc_attach, /* attach */ 419 fhc_detach, /* detach */ 420 nulldev, /* reset */ 421 &fhc_cb_ops, /* cb_ops */ 422 &fhc_bus_ops, /* bus_ops */ 423 nulldev, /* power */ 424 ddi_quiesce_not_needed, /* quiesce */ 425 }; 426 427 /* 428 * Driver globals 429 * TODO - We need to investigate what locking needs to be done here. 430 */ 431 void *fhcp; /* fhc soft state hook */ 432 433 extern struct mod_ops mod_driverops; 434 435 static struct modldrv modldrv = { 436 &mod_driverops, /* Type of module. This one is a driver */ 437 "FHC Nexus", /* Name of module. */ 438 &fhc_ops, /* driver ops */ 439 }; 440 441 static struct modlinkage modlinkage = { 442 MODREV_1, /* rev */ 443 (void *)&modldrv, 444 NULL 445 }; 446 447 448 /* 449 * These are the module initialization routines. 450 */ 451 452 static caddr_t shutdown_va; 453 454 int 455 _init(void) 456 { 457 int error; 458 459 if ((error = ddi_soft_state_init(&fhcp, 460 sizeof (struct fhc_soft_state), 1)) != 0) 461 return (error); 462 463 fhc_bdlist_init(); 464 mutex_init(&ftlist_mutex, NULL, MUTEX_DEFAULT, NULL); 465 466 shutdown_va = vmem_alloc(heap_arena, PAGESIZE, VM_SLEEP); 467 ASSERT(shutdown_va != NULL); 468 469 plat_register_tod_fault(fhc_tod_fault); 470 471 return (mod_install(&modlinkage)); 472 } 473 474 int 475 _fini(void) 476 { 477 int error; 478 479 if ((error = mod_remove(&modlinkage)) != 0) 480 return (error); 481 482 plat_register_tod_fault(NULL); 483 484 mutex_destroy(&ftlist_mutex); 485 486 fhc_bdlist_fini(); 487 488 ddi_soft_state_fini(&fhcp); 489 490 return (0); 491 } 492 493 int 494 _info(struct modinfo *modinfop) 495 { 496 return (mod_info(&modlinkage, modinfop)); 497 } 498 499 /* 500 * Reset the interrupt mapping registers. 501 * This function resets the values during DDI_RESUME. 502 * 503 * NOTE: This function will not work for a full CPR cycle 504 * and is currently designed to handle the RESUME after a connect. 505 * 506 * Note about the PROM handling of moving CENTRAL to another board: 507 * The PROM moves the IGN identity (igr register) from the 508 * original CENTRAL to the new one. This means that we do not 509 * duplicate the fhc_attach code that sets it to (board number * 2). 510 * We rely on only using FHC interrupts from one board only 511 * (the UART and SYS interrupts) so that the values of the other IGNs 512 * are irrelevant. The benefit of this approach is that we don't 513 * have to have to tear down and rebuild the interrupt records 514 * for UART and SYS. It is also why we don't try to change the 515 * board number in the fhc instance for the clock board. 516 */ 517 static void 518 fhc_handle_imr(struct fhc_soft_state *softsp) 519 { 520 int i; 521 int cent; 522 uint_t tmp_reg; 523 524 525 if (softsp->is_central) { 526 uint_t want_igr, act_igr; 527 528 want_igr = softsp->list->sc.board << 1; 529 act_igr = *softsp->igr & 0x1f; 530 if (want_igr != act_igr) { 531 *softsp->igr = want_igr; 532 tmp_reg = *softsp->igr; 533 #ifdef lint 534 tmp_reg = tmp_reg; 535 #endif 536 /* We must now re-issue any pending interrupts. */ 537 for (i = 0; i < FHC_MAX_INO; i++) { 538 if (*(softsp->intr_regs[i].clear_reg) == 3) { 539 *(softsp->intr_regs[i].clear_reg) = 540 ISM_IDLE; 541 542 tmp_reg = 543 *(softsp->intr_regs[i].clear_reg); 544 #ifdef lint 545 tmp_reg = tmp_reg; 546 #endif 547 } 548 } 549 cmn_err(CE_NOTE, "central IGN corruption fixed: " 550 "got %x wanted %x", act_igr, want_igr); 551 } 552 return; 553 } 554 555 ASSERT(softsp->list->sc.board == FHC_BSR_TO_BD(*(softsp->bsr))); 556 cent = check_central(softsp->list->sc.board); 557 558 /* Loop through all 4 FHC interrupt mapping registers */ 559 for (i = 0; i < FHC_MAX_INO; i++) { 560 561 if (i == FHC_SYS_INO && 562 *(softsp->intr_regs[i].clear_reg) == 3) { 563 cmn_err(CE_NOTE, 564 "found lost system interrupt, resetting.."); 565 566 *(softsp->intr_regs[i].clear_reg) = ISM_IDLE; 567 568 /* 569 * ensure atomic write with this read. 570 */ 571 tmp_reg = *(softsp->intr_regs[i].clear_reg); 572 #ifdef lint 573 tmp_reg = tmp_reg; 574 #endif 575 } 576 577 /* 578 * The mapping registers on the board with the "central" bit 579 * set should not be touched as it has been taken care by POST. 580 */ 581 582 if (cent) 583 continue; 584 585 *(softsp->intr_regs[i].mapping_reg) = 0; 586 587 /* 588 * ensure atomic write with this read. 589 */ 590 tmp_reg = *(softsp->intr_regs[i].mapping_reg); 591 #ifdef lint 592 tmp_reg = tmp_reg; 593 #endif 594 595 } 596 } 597 598 static int 599 check_central(int board) 600 { 601 uint_t cs_value; 602 603 /* 604 * This is the value of AC configuration and status reg 605 * in the Local Devices space. We access it as a physical 606 * address. 607 */ 608 cs_value = ldphysio(AC_BCSR(board)); 609 if (cs_value & AC_CENTRAL) 610 return (TRUE); 611 else 612 return (FALSE); 613 } 614 615 static int 616 fhc_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) 617 { 618 struct fhc_soft_state *softsp; 619 int instance; 620 621 instance = ddi_get_instance(devi); 622 623 switch (cmd) { 624 case DDI_ATTACH: 625 break; 626 627 case DDI_RESUME: 628 softsp = ddi_get_soft_state(fhcp, instance); 629 /* IGR, NOT_BRD_PRES handled by prom */ 630 /* reset interrupt mapping registers */ 631 fhc_handle_imr(softsp); 632 633 return (DDI_SUCCESS); 634 635 default: 636 return (DDI_FAILURE); 637 } 638 639 640 if (ddi_soft_state_zalloc(fhcp, instance) != DDI_SUCCESS) 641 return (DDI_FAILURE); 642 643 softsp = ddi_get_soft_state(fhcp, instance); 644 645 /* Set the dip in the soft state */ 646 softsp->dip = devi; 647 648 if (fhc_init(softsp) != DDI_SUCCESS) 649 goto bad; 650 651 ddi_report_dev(devi); 652 653 return (DDI_SUCCESS); 654 655 bad: 656 ddi_soft_state_free(fhcp, instance); 657 return (DDI_FAILURE); 658 } 659 660 static int 661 fhc_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) 662 { 663 int board; 664 int instance; 665 struct fhc_soft_state *softsp; 666 fhc_bd_t *list = NULL; 667 668 /* get the instance of this devi */ 669 instance = ddi_get_instance(devi); 670 671 /* get the soft state pointer for this device node */ 672 softsp = ddi_get_soft_state(fhcp, instance); 673 674 board = softsp->list->sc.board; 675 676 switch (cmd) { 677 case DDI_SUSPEND: 678 679 return (DDI_SUCCESS); 680 681 case DDI_DETACH: 682 /* grab the lock on the board list */ 683 list = fhc_bdlist_lock(board); 684 685 if (fhc_bd_detachable(board) && 686 !fhc_bd_is_jtag_master(board)) 687 break; 688 else 689 fhc_bdlist_unlock(); 690 /* FALLTHROUGH */ 691 692 default: 693 return (DDI_FAILURE); 694 } 695 696 /* Remove the interrupt redistribution callback. */ 697 intr_dist_rem(fhc_intrdist, (void *)devi); 698 699 /* remove the soft state pointer from the board list */ 700 list->softsp = NULL; 701 702 /* clear inherited faults from the PROM. */ 703 clear_fault(list->sc.board, FT_PROM, FT_BOARD); 704 705 /* remove the kstat for this board */ 706 kstat_delete(softsp->fhc_ksp); 707 708 /* destroy the mutexes in this soft state structure */ 709 mutex_destroy(&softsp->poll_list_lock); 710 mutex_destroy(&softsp->ctrl_lock); 711 712 /* unmap all the register sets */ 713 fhc_unmap_regs(softsp); 714 715 /* release the board list lock now */ 716 fhc_bdlist_unlock(); 717 718 /* free the soft state structure */ 719 ddi_soft_state_free(fhcp, instance); 720 721 return (DDI_SUCCESS); 722 } 723 724 static enum board_type 725 fhc_board_type(struct fhc_soft_state *softsp, int board) 726 { 727 int proplen; 728 char *board_type; 729 enum board_type type; 730 731 if (softsp->is_central) 732 type = CLOCK_BOARD; 733 else if (ddi_getlongprop(DDI_DEV_T_ANY, softsp->dip, 734 DDI_PROP_DONTPASS, "board-type", (caddr_t)&board_type, 735 &proplen) == DDI_PROP_SUCCESS) { 736 /* match the board-type string */ 737 if (strcmp(CPU_BD_NAME, board_type) == 0) { 738 type = CPU_BOARD; 739 } else if (strcmp(MEM_BD_NAME, board_type) == 0) { 740 type = MEM_BOARD; 741 } else if (strcmp(IO_2SBUS_BD_NAME, board_type) == 0) { 742 type = IO_2SBUS_BOARD; 743 } else if (strcmp(IO_SBUS_FFB_BD_NAME, board_type) == 0) { 744 type = IO_SBUS_FFB_BOARD; 745 } else if (strcmp(IO_2SBUS_SOCPLUS_BD_NAME, board_type) == 0) { 746 type = IO_2SBUS_SOCPLUS_BOARD; 747 } else if (strcmp(IO_SBUS_FFB_SOCPLUS_BD_NAME, board_type) 748 == 0) { 749 type = IO_SBUS_FFB_SOCPLUS_BOARD; 750 } else if (strcmp(IO_PCI_BD_NAME, board_type) == 0) { 751 type = IO_PCI_BOARD; 752 } else { 753 type = UNKNOWN_BOARD; 754 } 755 kmem_free(board_type, proplen); 756 } else 757 type = UNKNOWN_BOARD; 758 759 /* 760 * if the board type is indeterminate, it must be determined. 761 */ 762 if (type == UNKNOWN_BOARD) { 763 /* 764 * Use the UPA64 bits from the FHC. 765 * This is not the best solution since we 766 * cannot fully type the IO boards. 767 */ 768 if (cpu_on_board(board)) 769 type = CPU_BOARD; 770 else if ((*(softsp->bsr) & FHC_UPADATA64A) || 771 (*(softsp->bsr) & FHC_UPADATA64B)) 772 type = IO_2SBUS_BOARD; 773 else 774 type = MEM_BOARD; 775 } 776 777 return (type); 778 } 779 780 static void 781 fhc_unmap_regs(struct fhc_soft_state *softsp) 782 { 783 dev_info_t *dip = softsp->dip; 784 785 if (softsp->id) { 786 ddi_unmap_regs(dip, 0, (caddr_t *)&softsp->id, 0, 0); 787 softsp->id = NULL; 788 } 789 if (softsp->igr) { 790 ddi_unmap_regs(dip, 1, (caddr_t *)&softsp->igr, 0, 0); 791 softsp->igr = NULL; 792 } 793 if (softsp->intr_regs[FHC_FANFAIL_INO].mapping_reg) { 794 ddi_unmap_regs(dip, 2, 795 (caddr_t *)&softsp->intr_regs[FHC_FANFAIL_INO].mapping_reg, 796 0, 0); 797 softsp->intr_regs[FHC_FANFAIL_INO].mapping_reg = NULL; 798 } 799 if (softsp->intr_regs[FHC_SYS_INO].mapping_reg) { 800 ddi_unmap_regs(dip, 3, 801 (caddr_t *)&softsp->intr_regs[FHC_SYS_INO].mapping_reg, 802 0, 0); 803 softsp->intr_regs[FHC_SYS_INO].mapping_reg = NULL; 804 } 805 if (softsp->intr_regs[FHC_UART_INO].mapping_reg) { 806 ddi_unmap_regs(dip, 4, 807 (caddr_t *)&softsp->intr_regs[FHC_UART_INO].mapping_reg, 808 0, 0); 809 softsp->intr_regs[FHC_UART_INO].mapping_reg = NULL; 810 } 811 if (softsp->intr_regs[FHC_TOD_INO].mapping_reg) { 812 ddi_unmap_regs(dip, 5, 813 (caddr_t *)&softsp->intr_regs[FHC_TOD_INO].mapping_reg, 814 0, 0); 815 softsp->intr_regs[FHC_TOD_INO].mapping_reg = NULL; 816 } 817 } 818 819 static int 820 fhc_init(struct fhc_soft_state *softsp) 821 { 822 int i; 823 uint_t tmp_reg; 824 int board; 825 826 /* 827 * Map in the FHC registers. Specifying length and offset of 828 * zero maps in the entire OBP register set. 829 */ 830 831 /* map in register set 0 */ 832 if (ddi_map_regs(softsp->dip, 0, 833 (caddr_t *)&softsp->id, 0, 0)) { 834 cmn_err(CE_WARN, "fhc%d: unable to map internal " 835 "registers", ddi_get_instance(softsp->dip)); 836 goto bad; 837 } 838 839 /* 840 * Fill in the virtual addresses of the registers in the 841 * fhc_soft_state structure. 842 */ 843 softsp->rctrl = (uint_t *)((char *)(softsp->id) + 844 FHC_OFF_RCTRL); 845 softsp->ctrl = (uint_t *)((char *)(softsp->id) + 846 FHC_OFF_CTRL); 847 softsp->bsr = (uint_t *)((char *)(softsp->id) + 848 FHC_OFF_BSR); 849 softsp->jtag_ctrl = (uint_t *)((char *)(softsp->id) + 850 FHC_OFF_JTAG_CTRL); 851 softsp->jt_master.jtag_cmd = (uint_t *)((char *)(softsp->id) + 852 FHC_OFF_JTAG_CMD); 853 854 /* map in register set 1 */ 855 if (ddi_map_regs(softsp->dip, 1, 856 (caddr_t *)&softsp->igr, 0, 0)) { 857 cmn_err(CE_WARN, "fhc%d: unable to map IGR " 858 "register", ddi_get_instance(softsp->dip)); 859 goto bad; 860 } 861 862 /* 863 * map in register set 2 864 * XXX this can never be used as an interrupt generator 865 * (hardware queue overflow in fhc) 866 */ 867 if (ddi_map_regs(softsp->dip, 2, 868 (caddr_t *)&softsp->intr_regs[FHC_FANFAIL_INO].mapping_reg, 869 0, 0)) { 870 cmn_err(CE_WARN, "fhc%d: unable to map Fan Fail " 871 "IMR register", ddi_get_instance(softsp->dip)); 872 goto bad; 873 } 874 875 /* map in register set 3 */ 876 if (ddi_map_regs(softsp->dip, 3, 877 (caddr_t *)&softsp->intr_regs[FHC_SYS_INO].mapping_reg, 878 0, 0)) { 879 cmn_err(CE_WARN, "fhc%d: unable to map System " 880 "IMR register\n", ddi_get_instance(softsp->dip)); 881 goto bad; 882 } 883 884 /* map in register set 4 */ 885 if (ddi_map_regs(softsp->dip, 4, 886 (caddr_t *)&softsp->intr_regs[FHC_UART_INO].mapping_reg, 887 0, 0)) { 888 cmn_err(CE_WARN, "fhc%d: unable to map UART " 889 "IMR register\n", ddi_get_instance(softsp->dip)); 890 goto bad; 891 } 892 893 /* map in register set 5 */ 894 if (ddi_map_regs(softsp->dip, 5, 895 (caddr_t *)&softsp->intr_regs[FHC_TOD_INO].mapping_reg, 896 0, 0)) { 897 cmn_err(CE_WARN, "fhc%d: unable to map FHC TOD " 898 "IMR register", ddi_get_instance(softsp->dip)); 899 goto bad; 900 } 901 902 /* Loop over all intr sets and setup the VAs for the ISMR */ 903 /* TODO - Make sure we are calculating the ISMR correctly. */ 904 for (i = 0; i < FHC_MAX_INO; i++) { 905 softsp->intr_regs[i].clear_reg = 906 (uint_t *)((char *)(softsp->intr_regs[i].mapping_reg) + 907 FHC_OFF_ISMR); 908 909 /* Now clear the state machines to idle */ 910 *(softsp->intr_regs[i].clear_reg) = ISM_IDLE; 911 } 912 913 /* 914 * It is OK to not have a OBP_BOARDNUM property. This happens for 915 * the board which is a child of central. However this FHC 916 * still needs a proper Interrupt Group Number programmed 917 * into the Interrupt Group register, because the other 918 * instance of FHC, which is not under central, will properly 919 * program the IGR. The numbers from the two settings of the 920 * IGR need to be the same. One driver cannot wait for the 921 * other to program the IGR, because there is no guarantee 922 * which instance of FHC will get attached first. 923 */ 924 if ((board = (int)ddi_getprop(DDI_DEV_T_ANY, softsp->dip, 925 DDI_PROP_DONTPASS, OBP_BOARDNUM, -1)) == -1) { 926 /* 927 * Now determine the board number by reading the 928 * hardware register. 929 */ 930 board = FHC_BSR_TO_BD(*(softsp->bsr)); 931 softsp->is_central = 1; 932 } 933 934 /* 935 * If this fhc holds JTAG master line, and is not the central fhc, 936 * (this avoids two JTAG master nodes) then initialize the 937 * mutex and set the flag in the structure. 938 */ 939 if ((*(softsp->jtag_ctrl) & JTAG_MASTER_EN) && !softsp->is_central) { 940 mutex_init(&(softsp->jt_master.lock), NULL, MUTEX_DEFAULT, 941 NULL); 942 softsp->jt_master.is_master = 1; 943 } else { 944 softsp->jt_master.is_master = 0; 945 } 946 947 fhc_bd_init(softsp, board, fhc_board_type(softsp, board)); 948 949 /* Initialize the mutex guarding the poll_list. */ 950 mutex_init(&softsp->poll_list_lock, NULL, MUTEX_DRIVER, NULL); 951 952 /* Initialize the mutex guarding the FHC CSR */ 953 mutex_init(&softsp->ctrl_lock, NULL, MUTEX_DRIVER, NULL); 954 955 /* Initialize the poll_list to be empty */ 956 for (i = 0; i < MAX_ZS_CNT; i++) { 957 softsp->poll_list[i].funcp = NULL; 958 } 959 960 /* Modify the various registers in the FHC now */ 961 962 /* 963 * We know this board to be present now, record that state and 964 * remove the NOT_BRD_PRES condition 965 */ 966 if (!(softsp->is_central)) { 967 mutex_enter(&softsp->ctrl_lock); 968 *(softsp->ctrl) |= FHC_NOT_BRD_PRES; 969 /* Now flush the hardware store buffers. */ 970 tmp_reg = *(softsp->ctrl); 971 #ifdef lint 972 tmp_reg = tmp_reg; 973 #endif 974 /* XXX record the board state in global space */ 975 mutex_exit(&softsp->ctrl_lock); 976 977 /* Add kstats for all non-central instances of the FHC. */ 978 fhc_add_kstats(softsp); 979 } 980 981 /* 982 * Read the device tree to see if this system is in an environmental 983 * chamber. 984 */ 985 if (temperature_chamber == -1) { 986 temperature_chamber = check_for_chamber(); 987 } 988 989 /* Check for inherited faults from the PROM. */ 990 if (*softsp->ctrl & FHC_LED_MID) { 991 reg_fault(softsp->list->sc.board, FT_PROM, FT_BOARD); 992 } 993 994 /* 995 * setup the IGR. Shift the board number over by one to get 996 * the UPA MID. 997 */ 998 *(softsp->igr) = (softsp->list->sc.board) << 1; 999 1000 /* Now flush the hardware store buffers. */ 1001 tmp_reg = *(softsp->id); 1002 #ifdef lint 1003 tmp_reg = tmp_reg; 1004 #endif 1005 1006 /* Add the interrupt redistribution callback. */ 1007 intr_dist_add(fhc_intrdist, (void *)softsp->dip); 1008 1009 return (DDI_SUCCESS); 1010 bad: 1011 fhc_unmap_regs(softsp); 1012 return (DDI_FAILURE); 1013 } 1014 1015 static uint_t 1016 fhc_intr_wrapper(caddr_t arg) 1017 { 1018 uint_t intr_return; 1019 uint_t tmpreg; 1020 struct fhc_wrapper_arg *intr_info = (struct fhc_wrapper_arg *)arg; 1021 uint_t (*funcp)(caddr_t, caddr_t) = intr_info->funcp; 1022 caddr_t iarg1 = intr_info->arg1; 1023 caddr_t iarg2 = intr_info->arg2; 1024 dev_info_t *dip = intr_info->child; 1025 1026 tmpreg = ISM_IDLE; 1027 1028 DTRACE_PROBE4(interrupt__start, dev_info_t, dip, 1029 void *, funcp, caddr_t, iarg1, caddr_t, iarg2); 1030 1031 intr_return = (*funcp)(iarg1, iarg2); 1032 1033 DTRACE_PROBE4(interrupt__complete, dev_info_t, dip, 1034 void *, funcp, caddr_t, iarg1, int, intr_return); 1035 1036 /* Idle the state machine. */ 1037 *(intr_info->clear_reg) = tmpreg; 1038 1039 /* Flush the hardware store buffers. */ 1040 tmpreg = *(intr_info->clear_reg); 1041 #ifdef lint 1042 tmpreg = tmpreg; 1043 #endif /* lint */ 1044 1045 return (intr_return); 1046 } 1047 1048 /* 1049 * fhc_zs_intr_wrapper 1050 * 1051 * This function handles intrerrupts where more than one device may interupt 1052 * the fhc with the same mondo. 1053 */ 1054 1055 #define MAX_INTR_CNT 10 1056 1057 static uint_t 1058 fhc_zs_intr_wrapper(caddr_t arg) 1059 { 1060 struct fhc_soft_state *softsp = (struct fhc_soft_state *)arg; 1061 uint_t (*funcp0)(caddr_t, caddr_t); 1062 uint_t (*funcp1)(caddr_t, caddr_t); 1063 caddr_t funcp0_arg1, funcp0_arg2, funcp1_arg1, funcp1_arg2; 1064 uint_t tmp_reg; 1065 uint_t result = DDI_INTR_UNCLAIMED; 1066 volatile uint_t *clear_reg; 1067 uchar_t *spurious_cntr = &softsp->spurious_zs_cntr; 1068 1069 funcp0 = softsp->poll_list[0].funcp; 1070 funcp1 = softsp->poll_list[1].funcp; 1071 funcp0_arg1 = softsp->poll_list[0].arg1; 1072 funcp0_arg2 = softsp->poll_list[0].arg2; 1073 funcp1_arg1 = softsp->poll_list[1].arg1; 1074 funcp1_arg2 = softsp->poll_list[1].arg2; 1075 clear_reg = softsp->intr_regs[FHC_UART_INO].clear_reg; 1076 1077 if (funcp0 != NULL) { 1078 if ((funcp0)(funcp0_arg1, funcp0_arg2) == DDI_INTR_CLAIMED) { 1079 result = DDI_INTR_CLAIMED; 1080 } 1081 } 1082 1083 if (funcp1 != NULL) { 1084 if ((funcp1)(funcp1_arg1, funcp1_arg2) == DDI_INTR_CLAIMED) { 1085 result = DDI_INTR_CLAIMED; 1086 } 1087 } 1088 1089 if (result == DDI_INTR_UNCLAIMED) { 1090 (*spurious_cntr)++; 1091 1092 if (*spurious_cntr < MAX_INTR_CNT) { 1093 result = DDI_INTR_CLAIMED; 1094 } else { 1095 *spurious_cntr = (uchar_t)0; 1096 } 1097 } else { 1098 *spurious_cntr = (uchar_t)0; 1099 } 1100 1101 /* Idle the state machine. */ 1102 *(clear_reg) = ISM_IDLE; 1103 1104 /* flush the store buffers. */ 1105 tmp_reg = *(clear_reg); 1106 #ifdef lint 1107 tmp_reg = tmp_reg; 1108 #endif 1109 1110 return (result); 1111 } 1112 1113 1114 /* 1115 * add_intrspec - Add an interrupt specification. 1116 */ 1117 static int 1118 fhc_add_intr_impl(dev_info_t *dip, dev_info_t *rdip, 1119 ddi_intr_handle_impl_t *hdlp) 1120 { 1121 int ino; 1122 struct fhc_wrapper_arg *fhc_arg; 1123 struct fhc_soft_state *softsp = (struct fhc_soft_state *) 1124 ddi_get_soft_state(fhcp, ddi_get_instance(dip)); 1125 volatile uint_t *mondo_vec_reg; 1126 uint_t tmp_mondo_vec; 1127 uint_t tmpreg; /* HW flush reg */ 1128 uint_t cpu_id; 1129 int ret = DDI_SUCCESS; 1130 1131 /* Xlate the interrupt */ 1132 fhc_xlate_intrs(hdlp, 1133 (softsp->list->sc.board << BD_IVINTR_SHFT)); 1134 1135 /* get the mondo number */ 1136 ino = FHC_INO(hdlp->ih_vector); 1137 mondo_vec_reg = softsp->intr_regs[ino].mapping_reg; 1138 1139 ASSERT(ino < FHC_MAX_INO); 1140 1141 /* We don't use the two spare interrupts. */ 1142 if (ino >= FHC_MAX_INO) { 1143 cmn_err(CE_WARN, "fhc%d: Spare interrupt %d not usable", 1144 ddi_get_instance(dip), ino); 1145 return (DDI_FAILURE); 1146 } 1147 1148 /* TOD and Fan Fail interrupts are not usable */ 1149 if (ino == FHC_TOD_INO) { 1150 cmn_err(CE_WARN, "fhc%d: TOD interrupt not usable", 1151 ddi_get_instance(dip)); 1152 return (DDI_FAILURE); 1153 } 1154 if (ino == FHC_FANFAIL_INO) { 1155 cmn_err(CE_WARN, "fhc%d: Fan fail interrupt not usable", 1156 ddi_get_instance(dip)); 1157 return (DDI_FAILURE); 1158 } 1159 1160 /* 1161 * If the interrupt is for the zs chips, use the vector 1162 * polling lists. Otherwise use a straight handler. 1163 */ 1164 if (ino == FHC_UART_INO) { 1165 int32_t zs_inst; 1166 /* First lock the mutex for this poll_list */ 1167 mutex_enter(&softsp->poll_list_lock); 1168 1169 /* 1170 * Add this interrupt to the polling list. 1171 */ 1172 1173 /* figure out where to add this item in the list */ 1174 for (zs_inst = 0; zs_inst < MAX_ZS_CNT; zs_inst++) { 1175 if (softsp->poll_list[zs_inst].funcp == NULL) { 1176 softsp->poll_list[zs_inst].arg1 = 1177 hdlp->ih_cb_arg1; 1178 softsp->poll_list[zs_inst].arg2 = 1179 hdlp->ih_cb_arg2; 1180 softsp->poll_list[zs_inst].funcp = 1181 (ddi_intr_handler_t *) 1182 hdlp->ih_cb_func; 1183 softsp->poll_list[zs_inst].inum = 1184 hdlp->ih_inum; 1185 softsp->poll_list[zs_inst].child = rdip; 1186 1187 break; 1188 } 1189 } 1190 1191 if (zs_inst >= MAX_ZS_CNT) { 1192 cmn_err(CE_WARN, 1193 "fhc%d: poll list overflow", 1194 ddi_get_instance(dip)); 1195 mutex_exit(&softsp->poll_list_lock); 1196 ret = DDI_FAILURE; 1197 goto done; 1198 } 1199 1200 /* 1201 * If polling list is empty, then install handler 1202 * and enable interrupts for this ino. 1203 */ 1204 if (zs_inst == 0) { 1205 DDI_INTR_ASSIGN_HDLR_N_ARGS(hdlp, 1206 (ddi_intr_handler_t *)fhc_zs_intr_wrapper, 1207 (caddr_t)softsp, NULL); 1208 1209 ret = i_ddi_add_ivintr(hdlp); 1210 1211 DDI_INTR_ASSIGN_HDLR_N_ARGS(hdlp, 1212 softsp->poll_list[zs_inst].funcp, 1213 softsp->poll_list[zs_inst].arg1, 1214 softsp->poll_list[zs_inst].arg2); 1215 1216 if (ret != DDI_SUCCESS) 1217 goto done; 1218 } 1219 1220 /* 1221 * If both zs handlers are active, then this is the 1222 * second add_intrspec called, so do not enable 1223 * the IMR_VALID bit, it is already on. 1224 */ 1225 if (zs_inst > 0) { 1226 /* now release the mutex and return */ 1227 mutex_exit(&softsp->poll_list_lock); 1228 1229 goto done; 1230 } else { 1231 /* just release the mutex */ 1232 mutex_exit(&softsp->poll_list_lock); 1233 } 1234 } else { /* normal interrupt installation */ 1235 int32_t i; 1236 1237 /* Allocate a nexus interrupt data structure */ 1238 fhc_arg = kmem_alloc(sizeof (struct fhc_wrapper_arg), KM_SLEEP); 1239 fhc_arg->child = rdip; 1240 fhc_arg->mapping_reg = mondo_vec_reg; 1241 fhc_arg->clear_reg = (softsp->intr_regs[ino].clear_reg); 1242 fhc_arg->softsp = softsp; 1243 fhc_arg->funcp = 1244 (ddi_intr_handler_t *)hdlp->ih_cb_func; 1245 fhc_arg->arg1 = hdlp->ih_cb_arg1; 1246 fhc_arg->arg2 = hdlp->ih_cb_arg2; 1247 fhc_arg->inum = hdlp->ih_inum; 1248 1249 for (i = 0; i < FHC_MAX_INO; i++) { 1250 if (softsp->intr_list[i] == 0) { 1251 softsp->intr_list[i] = fhc_arg; 1252 break; 1253 } 1254 } 1255 1256 /* 1257 * Save the fhc_arg in the ispec so we can use this info 1258 * later to uninstall this interrupt spec. 1259 */ 1260 DDI_INTR_ASSIGN_HDLR_N_ARGS(hdlp, 1261 (ddi_intr_handler_t *)fhc_intr_wrapper, 1262 (caddr_t)fhc_arg, NULL); 1263 1264 ret = i_ddi_add_ivintr(hdlp); 1265 1266 DDI_INTR_ASSIGN_HDLR_N_ARGS(hdlp, fhc_arg->funcp, 1267 fhc_arg->arg1, fhc_arg->arg2); 1268 1269 if (ret != DDI_SUCCESS) 1270 goto done; 1271 } 1272 1273 /* 1274 * Clear out a stale 'pending' or 'transmit' state in 1275 * this device's ISM that might have been left from a 1276 * previous session. 1277 * 1278 * Since all FHC interrupts are level interrupts, any 1279 * real interrupting condition will immediately transition 1280 * the ISM back to pending. 1281 */ 1282 *(softsp->intr_regs[ino].clear_reg) = ISM_IDLE; 1283 1284 /* 1285 * Program the mondo vector accordingly. This MUST be the 1286 * last thing we do. Once we program the ino, the device 1287 * may begin to interrupt. 1288 */ 1289 cpu_id = intr_dist_cpuid(); 1290 1291 tmp_mondo_vec = cpu_id << INR_PID_SHIFT; 1292 1293 /* don't do this for fan because fan has a special control */ 1294 if (ino == FHC_FANFAIL_INO) 1295 panic("fhc%d: enabling fanfail interrupt", 1296 ddi_get_instance(dip)); 1297 else 1298 tmp_mondo_vec |= IMR_VALID; 1299 1300 DPRINTF(FHC_INTERRUPT_DEBUG, 1301 ("Mondo 0x%x mapping reg: 0x%p", hdlp->ih_vector, 1302 (void *)mondo_vec_reg)); 1303 1304 /* Store it in the hardware reg. */ 1305 *mondo_vec_reg = tmp_mondo_vec; 1306 1307 /* Read a FHC register to flush store buffers */ 1308 tmpreg = *(softsp->id); 1309 #ifdef lint 1310 tmpreg = tmpreg; 1311 #endif 1312 1313 done: 1314 return (ret); 1315 } 1316 1317 /* 1318 * remove_intrspec - Remove an interrupt specification. 1319 */ 1320 static void 1321 fhc_remove_intr_impl(dev_info_t *dip, dev_info_t *rdip, 1322 ddi_intr_handle_impl_t *hdlp) 1323 { 1324 volatile uint_t *mondo_vec_reg; 1325 volatile uint_t tmpreg; 1326 int i; 1327 struct fhc_soft_state *softsp = (struct fhc_soft_state *) 1328 ddi_get_soft_state(fhcp, ddi_get_instance(dip)); 1329 int ino; 1330 1331 /* Xlate the interrupt */ 1332 fhc_xlate_intrs(hdlp, 1333 (softsp->list->sc.board << BD_IVINTR_SHFT)); 1334 1335 /* get the mondo number */ 1336 ino = FHC_INO(hdlp->ih_vector); 1337 1338 if (ino == FHC_UART_INO) { 1339 int intr_found = 0; 1340 1341 /* Lock the poll_list first */ 1342 mutex_enter(&softsp->poll_list_lock); 1343 1344 /* 1345 * Find which entry in the poll list belongs to this 1346 * intrspec. 1347 */ 1348 for (i = 0; i < MAX_ZS_CNT; i++) { 1349 if (softsp->poll_list[i].child == rdip && 1350 softsp->poll_list[i].inum == hdlp->ih_inum) { 1351 softsp->poll_list[i].funcp = NULL; 1352 intr_found++; 1353 } 1354 } 1355 1356 /* If we did not find an entry, then we have a problem */ 1357 if (!intr_found) { 1358 cmn_err(CE_WARN, "fhc%d: Intrspec not found in" 1359 " poll list", ddi_get_instance(dip)); 1360 mutex_exit(&softsp->poll_list_lock); 1361 goto done; 1362 } 1363 1364 /* 1365 * If we have removed all active entries for the poll 1366 * list, then we have to disable interupts at this point. 1367 */ 1368 if ((softsp->poll_list[0].funcp == NULL) && 1369 (softsp->poll_list[1].funcp == NULL)) { 1370 mondo_vec_reg = 1371 softsp->intr_regs[FHC_UART_INO].mapping_reg; 1372 *mondo_vec_reg &= ~IMR_VALID; 1373 1374 /* flush the hardware buffers */ 1375 tmpreg = *(softsp->ctrl); 1376 1377 /* Eliminate the particular handler from the system. */ 1378 i_ddi_rem_ivintr(hdlp); 1379 } 1380 1381 mutex_exit(&softsp->poll_list_lock); 1382 } else { 1383 int32_t i; 1384 1385 1386 for (i = 0; i < FHC_MAX_INO; i++) 1387 if (softsp->intr_list[i]->child == rdip && 1388 softsp->intr_list[i]->inum == hdlp->ih_inum) 1389 break; 1390 1391 if (i >= FHC_MAX_INO) 1392 goto done; 1393 1394 mondo_vec_reg = softsp->intr_list[i]->mapping_reg; 1395 1396 /* Turn off the valid bit in the mapping register. */ 1397 /* XXX what about FHC_FANFAIL owned imr? */ 1398 *mondo_vec_reg &= ~IMR_VALID; 1399 1400 /* flush the hardware store buffers */ 1401 tmpreg = *(softsp->id); 1402 #ifdef lint 1403 tmpreg = tmpreg; 1404 #endif 1405 1406 /* Eliminate the particular handler from the system. */ 1407 i_ddi_rem_ivintr(hdlp); 1408 1409 kmem_free(softsp->intr_list[i], 1410 sizeof (struct fhc_wrapper_arg)); 1411 softsp->intr_list[i] = 0; 1412 } 1413 1414 done: 1415 ; 1416 } 1417 1418 /* new intr_ops structure */ 1419 static int 1420 fhc_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op, 1421 ddi_intr_handle_impl_t *hdlp, void *result) 1422 { 1423 int ret = DDI_SUCCESS; 1424 1425 switch (intr_op) { 1426 case DDI_INTROP_GETCAP: 1427 *(int *)result = DDI_INTR_FLAG_LEVEL; 1428 break; 1429 case DDI_INTROP_ALLOC: 1430 *(int *)result = hdlp->ih_scratch1; 1431 break; 1432 case DDI_INTROP_FREE: 1433 break; 1434 case DDI_INTROP_GETPRI: 1435 if (hdlp->ih_pri == 0) { 1436 struct fhc_soft_state *softsp = 1437 (struct fhc_soft_state *)ddi_get_soft_state(fhcp, 1438 ddi_get_instance(dip)); 1439 1440 /* Xlate the interrupt */ 1441 fhc_xlate_intrs(hdlp, 1442 (softsp->list->sc.board << BD_IVINTR_SHFT)); 1443 } 1444 1445 *(int *)result = hdlp->ih_pri; 1446 break; 1447 case DDI_INTROP_SETPRI: 1448 break; 1449 case DDI_INTROP_ADDISR: 1450 ret = fhc_add_intr_impl(dip, rdip, hdlp); 1451 break; 1452 case DDI_INTROP_REMISR: 1453 fhc_remove_intr_impl(dip, rdip, hdlp); 1454 break; 1455 case DDI_INTROP_ENABLE: 1456 case DDI_INTROP_DISABLE: 1457 break; 1458 case DDI_INTROP_NINTRS: 1459 case DDI_INTROP_NAVAIL: 1460 *(int *)result = i_ddi_get_intx_nintrs(rdip); 1461 break; 1462 case DDI_INTROP_SETCAP: 1463 case DDI_INTROP_SETMASK: 1464 case DDI_INTROP_CLRMASK: 1465 case DDI_INTROP_GETPENDING: 1466 ret = DDI_ENOTSUP; 1467 break; 1468 case DDI_INTROP_SUPPORTED_TYPES: 1469 /* only support fixed interrupts */ 1470 *(int *)result = i_ddi_get_intx_nintrs(rdip) ? 1471 DDI_INTR_TYPE_FIXED : 0; 1472 break; 1473 default: 1474 ret = i_ddi_intr_ops(dip, rdip, intr_op, hdlp, result); 1475 break; 1476 } 1477 1478 return (ret); 1479 } 1480 1481 /* 1482 * FHC Control Ops routine 1483 * 1484 * Requests handled here: 1485 * DDI_CTLOPS_INITCHILD see impl_ddi_sunbus_initchild() for details 1486 * DDI_CTLOPS_UNINITCHILD see fhc_uninit_child() for details 1487 * DDI_CTLOPS_REPORTDEV TODO - need to implement this. 1488 */ 1489 static int 1490 fhc_ctlops(dev_info_t *dip, dev_info_t *rdip, 1491 ddi_ctl_enum_t op, void *arg, void *result) 1492 { 1493 1494 switch (op) { 1495 case DDI_CTLOPS_INITCHILD: 1496 DPRINTF(FHC_CTLOPS_DEBUG, ("DDI_CTLOPS_INITCHILD\n")); 1497 return (impl_ddi_sunbus_initchild((dev_info_t *)arg)); 1498 1499 case DDI_CTLOPS_UNINITCHILD: 1500 impl_ddi_sunbus_removechild((dev_info_t *)arg); 1501 return (DDI_SUCCESS); 1502 1503 case DDI_CTLOPS_REPORTDEV: 1504 /* 1505 * TODO - Figure out what makes sense to report here. 1506 */ 1507 return (DDI_SUCCESS); 1508 1509 case DDI_CTLOPS_POKE: 1510 case DDI_CTLOPS_PEEK: 1511 return (fhc_ctlops_peekpoke(op, (peekpoke_ctlops_t *)arg, 1512 result)); 1513 1514 default: 1515 return (ddi_ctlops(dip, rdip, op, arg, result)); 1516 } 1517 } 1518 1519 1520 /* 1521 * We're prepared to claim that the interrupt string is in 1522 * the form of a list of <FHCintr> specifications, or we're dealing 1523 * with on-board devices and we have an interrupt_number property which 1524 * gives us our mondo number. 1525 * Translate the mondos into fhcintrspecs. 1526 */ 1527 /* ARGSUSED */ 1528 static void 1529 fhc_xlate_intrs(ddi_intr_handle_impl_t *hdlp, uint32_t ign) 1530 1531 { 1532 uint32_t mondo; 1533 1534 mondo = hdlp->ih_vector; 1535 1536 hdlp->ih_vector = (mondo | ign); 1537 if (hdlp->ih_pri == 0) 1538 hdlp->ih_pri = fhc_int_priorities[FHC_INO(mondo)]; 1539 } 1540 1541 static int 1542 fhc_ctlops_peekpoke(ddi_ctl_enum_t cmd, peekpoke_ctlops_t *in_args, 1543 void *result) 1544 { 1545 int err = DDI_SUCCESS; 1546 on_trap_data_t otd; 1547 1548 /* No safe access except for peek/poke is supported. */ 1549 if (in_args->handle != NULL) 1550 return (DDI_FAILURE); 1551 1552 /* Set up protected environment. */ 1553 if (!on_trap(&otd, OT_DATA_ACCESS)) { 1554 uintptr_t tramp = otd.ot_trampoline; 1555 1556 if (cmd == DDI_CTLOPS_POKE) { 1557 otd.ot_trampoline = (uintptr_t)&poke_fault; 1558 err = do_poke(in_args->size, (void *)in_args->dev_addr, 1559 (void *)in_args->host_addr); 1560 } else { 1561 otd.ot_trampoline = (uintptr_t)&peek_fault; 1562 err = do_peek(in_args->size, (void *)in_args->dev_addr, 1563 (void *)in_args->host_addr); 1564 result = (void *)in_args->host_addr; 1565 } 1566 otd.ot_trampoline = tramp; 1567 } else 1568 err = DDI_FAILURE; 1569 1570 /* Take down protected environment. */ 1571 no_trap(); 1572 1573 return (err); 1574 } 1575 1576 /* 1577 * This function initializes the temperature arrays for use. All 1578 * temperatures are set in to invalid value to start. 1579 */ 1580 void 1581 init_temp_arrays(struct temp_stats *envstat) 1582 { 1583 int i; 1584 1585 envstat->index = 0; 1586 1587 for (i = 0; i < L1_SZ; i++) { 1588 envstat->l1[i] = NA_TEMP; 1589 } 1590 1591 for (i = 0; i < L2_SZ; i++) { 1592 envstat->l2[i] = NA_TEMP; 1593 } 1594 1595 for (i = 0; i < L3_SZ; i++) { 1596 envstat->l3[i] = NA_TEMP; 1597 } 1598 1599 for (i = 0; i < L4_SZ; i++) { 1600 envstat->l4[i] = NA_TEMP; 1601 } 1602 1603 for (i = 0; i < L5_SZ; i++) { 1604 envstat->l5[i] = NA_TEMP; 1605 } 1606 1607 envstat->max = NA_TEMP; 1608 envstat->min = NA_TEMP; 1609 envstat->trend = TREND_UNKNOWN; 1610 envstat->version = TEMP_KSTAT_VERSION; 1611 envstat->override = NA_TEMP; 1612 } 1613 1614 /* Inhibit warning messages below this temperature, eg for CPU poweron. */ 1615 static uint_t fhc_cpu_warning_temp_threshold = FHC_CPU_WARNING_TEMP_THRESHOLD; 1616 1617 /* 1618 * This function manages the temperature history in the temperature 1619 * statistics buffer passed in. It calls the temperature calibration 1620 * routines and maintains the time averaged temperature data. 1621 */ 1622 void 1623 update_temp(dev_info_t *pdip, struct temp_stats *envstat, uchar_t value) 1624 { 1625 uint_t index; /* The absolute temperature counter */ 1626 uint_t tmp_index; /* temp index into upper level array */ 1627 int count; /* Count of non-zero values in array */ 1628 int total; /* sum total of non-zero values in array */ 1629 short real_temp; /* calibrated temperature */ 1630 int i; 1631 struct fhc_soft_state *softsp; 1632 char buffer[256]; /* buffer for warning of overtemp */ 1633 enum temp_state temp_state; /* Temperature state */ 1634 1635 /* 1636 * NOTE: This global counter is not protected since we're called 1637 * serially for each board. 1638 */ 1639 static int shutdown_msg = 0; /* Flag if shutdown warning issued */ 1640 1641 /* determine soft state pointer of parent */ 1642 softsp = ddi_get_soft_state(fhcp, ddi_get_instance(pdip)); 1643 1644 envstat->index++; 1645 index = envstat->index; 1646 1647 /* 1648 * You need to update the level 5 intervals first, since 1649 * they are based on the data from the level 4 intervals, 1650 * and so on, down to the level 1 intervals. 1651 */ 1652 1653 /* update the level 5 intervals if it is time */ 1654 if (((tmp_index = L5_INDEX(index)) > 0) && (L5_REM(index) == 0)) { 1655 /* Generate the index within the level 5 array */ 1656 tmp_index -= 1; /* decrement by 1 for indexing */ 1657 tmp_index = tmp_index % L5_SZ; 1658 1659 /* take an average of the level 4 array */ 1660 for (i = 0, count = 0, total = 0; i < L4_SZ; i++) { 1661 /* Do not include zero values in average */ 1662 if (envstat->l4[i] != NA_TEMP) { 1663 total += (int)envstat->l4[i]; 1664 count++; 1665 } 1666 } 1667 1668 /* 1669 * If there were any level 4 data points to average, 1670 * do so. 1671 */ 1672 if (count != 0) { 1673 envstat->l5[tmp_index] = total/count; 1674 } else { 1675 envstat->l5[tmp_index] = NA_TEMP; 1676 } 1677 } 1678 1679 /* update the level 4 intervals if it is time */ 1680 if (((tmp_index = L4_INDEX(index)) > 0) && (L4_REM(index) == 0)) { 1681 /* Generate the index within the level 4 array */ 1682 tmp_index -= 1; /* decrement by 1 for indexing */ 1683 tmp_index = tmp_index % L4_SZ; 1684 1685 /* take an average of the level 3 array */ 1686 for (i = 0, count = 0, total = 0; i < L3_SZ; i++) { 1687 /* Do not include zero values in average */ 1688 if (envstat->l3[i] != NA_TEMP) { 1689 total += (int)envstat->l3[i]; 1690 count++; 1691 } 1692 } 1693 1694 /* 1695 * If there were any level 3 data points to average, 1696 * do so. 1697 */ 1698 if (count != 0) { 1699 envstat->l4[tmp_index] = total/count; 1700 } else { 1701 envstat->l4[tmp_index] = NA_TEMP; 1702 } 1703 } 1704 1705 /* update the level 3 intervals if it is time */ 1706 if (((tmp_index = L3_INDEX(index)) > 0) && (L3_REM(index) == 0)) { 1707 /* Generate the index within the level 3 array */ 1708 tmp_index -= 1; /* decrement by 1 for indexing */ 1709 tmp_index = tmp_index % L3_SZ; 1710 1711 /* take an average of the level 2 array */ 1712 for (i = 0, count = 0, total = 0; i < L2_SZ; i++) { 1713 /* Do not include zero values in average */ 1714 if (envstat->l2[i] != NA_TEMP) { 1715 total += (int)envstat->l2[i]; 1716 count++; 1717 } 1718 } 1719 1720 /* 1721 * If there were any level 2 data points to average, 1722 * do so. 1723 */ 1724 if (count != 0) { 1725 envstat->l3[tmp_index] = total/count; 1726 } else { 1727 envstat->l3[tmp_index] = NA_TEMP; 1728 } 1729 } 1730 1731 /* update the level 2 intervals if it is time */ 1732 if (((tmp_index = L2_INDEX(index)) > 0) && (L2_REM(index) == 0)) { 1733 /* Generate the index within the level 2 array */ 1734 tmp_index -= 1; /* decrement by 1 for indexing */ 1735 tmp_index = tmp_index % L2_SZ; 1736 1737 /* take an average of the level 1 array */ 1738 for (i = 0, count = 0, total = 0; i < L1_SZ; i++) { 1739 /* Do not include zero values in average */ 1740 if (envstat->l1[i] != NA_TEMP) { 1741 total += (int)envstat->l1[i]; 1742 count++; 1743 } 1744 } 1745 1746 /* 1747 * If there were any level 1 data points to average, 1748 * do so. 1749 */ 1750 if (count != 0) { 1751 envstat->l2[tmp_index] = total/count; 1752 } else { 1753 envstat->l2[tmp_index] = NA_TEMP; 1754 } 1755 } 1756 1757 /* determine the current temperature in degrees Celcius */ 1758 if (envstat->override != NA_TEMP) { 1759 /* use override temperature for this board */ 1760 real_temp = envstat->override; 1761 } else { 1762 /* Run the calibration function using this board type */ 1763 real_temp = calibrate_temp(softsp->list->sc.type, value, 1764 softsp->list->sc.ac_compid); 1765 } 1766 1767 envstat->l1[index % L1_SZ] = real_temp; 1768 1769 /* check if the temperature state for this device needs to change */ 1770 temp_state = get_temp_state(softsp->list->sc.type, real_temp, 1771 softsp->list->sc.board); 1772 1773 /* has the state changed? Then get the board string ready */ 1774 if (temp_state != envstat->state) { 1775 int board = softsp->list->sc.board; 1776 enum board_type type = softsp->list->sc.type; 1777 1778 build_bd_display_str(buffer, type, board); 1779 1780 if (temp_state > envstat->state) { 1781 if (envstat->state == TEMP_OK) { 1782 if (type == CLOCK_BOARD) { 1783 reg_fault(0, FT_OVERTEMP, FT_SYSTEM); 1784 } else { 1785 reg_fault(board, FT_OVERTEMP, 1786 FT_BOARD); 1787 } 1788 } 1789 1790 /* heating up, change state now */ 1791 envstat->temp_cnt = 0; 1792 envstat->state = temp_state; 1793 1794 if (temp_state == TEMP_WARN) { 1795 /* now warn the user of the problem */ 1796 cmn_err(CE_WARN, 1797 "%s is warm (temperature: %dC). " 1798 "Please check system cooling", buffer, 1799 real_temp); 1800 fhc_bd_update(board, SYSC_EVT_BD_OVERTEMP); 1801 if (temperature_chamber == -1) 1802 temperature_chamber = 1803 check_for_chamber(); 1804 } else if (temp_state == TEMP_DANGER) { 1805 cmn_err(CE_WARN, 1806 "%s is very hot (temperature: %dC)", 1807 buffer, real_temp); 1808 1809 envstat->shutdown_cnt = 1; 1810 if (temperature_chamber == -1) 1811 temperature_chamber = 1812 check_for_chamber(); 1813 if ((temperature_chamber == 0) && 1814 enable_overtemp_powerdown) { 1815 /* 1816 * NOTE: The "%d seconds" is not 1817 * necessarily accurate in the case 1818 * where we have multiple boards 1819 * overheating and subsequently cooling 1820 * down. 1821 */ 1822 if (shutdown_msg == 0) { 1823 cmn_err(CE_WARN, "System " 1824 "shutdown scheduled " 1825 "in %d seconds due to " 1826 "over-temperature " 1827 "condition on %s", 1828 SHUTDOWN_TIMEOUT_SEC, 1829 buffer); 1830 } 1831 shutdown_msg++; 1832 } 1833 } 1834 1835 /* 1836 * If this is a cpu board, power them off. 1837 */ 1838 if (temperature_chamber == 0) { 1839 mutex_enter(&cpu_lock); 1840 (void) fhc_board_poweroffcpus(board, NULL, 1841 CPU_FORCED); 1842 mutex_exit(&cpu_lock); 1843 } 1844 } else if (temp_state < envstat->state) { 1845 /* 1846 * Avert the sigpower that would 1847 * otherwise be sent to init. 1848 */ 1849 envstat->shutdown_cnt = 0; 1850 1851 /* cooling down, use state counter */ 1852 if (envstat->temp_cnt == 0) { 1853 envstat->temp_cnt = TEMP_STATE_COUNT; 1854 } else if (--envstat->temp_cnt == 0) { 1855 if (temp_state == TEMP_WARN) { 1856 cmn_err(CE_NOTE, 1857 "%s is cooling " 1858 "(temperature: %dC)", buffer, 1859 real_temp); 1860 1861 } else if (temp_state == TEMP_OK) { 1862 cmn_err(CE_NOTE, 1863 "%s has cooled down " 1864 "(temperature: %dC), system OK", 1865 buffer, real_temp); 1866 1867 if (type == CLOCK_BOARD) { 1868 clear_fault(0, FT_OVERTEMP, 1869 FT_SYSTEM); 1870 } else { 1871 clear_fault(board, FT_OVERTEMP, 1872 FT_BOARD); 1873 } 1874 } 1875 1876 /* 1877 * If we just came out of TEMP_DANGER, and 1878 * a warning was issued about shutting down, 1879 * let the user know it's been cancelled 1880 */ 1881 if (envstat->state == TEMP_DANGER && 1882 (temperature_chamber == 0) && 1883 enable_overtemp_powerdown && 1884 (powerdown_started == 0) && 1885 (--shutdown_msg == 0)) { 1886 cmn_err(CE_NOTE, "System " 1887 "shutdown due to over-" 1888 "temperature " 1889 "condition cancelled"); 1890 } 1891 envstat->state = temp_state; 1892 1893 fhc_bd_update(board, SYSC_EVT_BD_TEMP_OK); 1894 } 1895 } 1896 } else { 1897 envstat->temp_cnt = 0; 1898 1899 if (temp_state == TEMP_DANGER) { 1900 if (temperature_chamber == -1) { 1901 temperature_chamber = check_for_chamber(); 1902 } 1903 1904 if ((envstat->shutdown_cnt++ >= SHUTDOWN_COUNT) && 1905 (temperature_chamber == 0) && 1906 enable_overtemp_powerdown && 1907 (powerdown_started == 0)) { 1908 powerdown_started = 1; 1909 1910 /* the system is still too hot */ 1911 build_bd_display_str(buffer, 1912 softsp->list->sc.type, 1913 softsp->list->sc.board); 1914 1915 cmn_err(CE_WARN, "%s still too hot " 1916 "(temperature: %dC)." 1917 " Overtemp shutdown started", buffer, 1918 real_temp); 1919 1920 fhc_reboot(); 1921 } 1922 } 1923 } 1924 1925 /* update the maximum and minimum temperatures if necessary */ 1926 if ((envstat->max == NA_TEMP) || (real_temp > envstat->max)) { 1927 envstat->max = real_temp; 1928 } 1929 1930 if ((envstat->min == NA_TEMP) || (real_temp < envstat->min)) { 1931 envstat->min = real_temp; 1932 } 1933 1934 /* 1935 * Update the temperature trend. Currently, the temperature 1936 * trend algorithm is based on the level 2 stats. So, we 1937 * only need to run every time the level 2 stats get updated. 1938 */ 1939 if (((tmp_index = L2_INDEX(index)) > 0) && (L2_REM(index) == 0)) { 1940 enum board_type type = softsp->list->sc.type; 1941 1942 envstat->trend = temp_trend(envstat); 1943 1944 /* Issue a warning if the temperature is rising rapidly. */ 1945 /* For CPU boards, don't warn if CPUs just powered on. */ 1946 if (envstat->trend == TREND_RAPID_RISE && 1947 (type != CPU_BOARD || real_temp > 1948 fhc_cpu_warning_temp_threshold)) { 1949 int board = softsp->list->sc.board; 1950 1951 build_bd_display_str(buffer, type, board); 1952 cmn_err(CE_WARN, "%s temperature is rising rapidly! " 1953 "Current temperature is %dC", buffer, 1954 real_temp); 1955 } 1956 } 1957 } 1958 1959 #define PREV_L2_INDEX(x) ((x) ? ((x) - 1) : (L2_SZ - 1)) 1960 1961 /* 1962 * This routine determines if the temp of the device passed in is heating 1963 * up, cooling down, or staying stable. 1964 */ 1965 enum temp_trend 1966 temp_trend(struct temp_stats *tempstat) 1967 { 1968 int ii; 1969 uint_t curr_index; 1970 int curr_temp; 1971 uint_t prev_index; 1972 int prev_temp; 1973 int trail_temp; 1974 int delta; 1975 int read_cnt; 1976 enum temp_trend result = TREND_STABLE; 1977 1978 if (tempstat == NULL) 1979 return (TREND_UNKNOWN); 1980 1981 curr_index = (L2_INDEX(tempstat->index) - 1) % L2_SZ; 1982 curr_temp = tempstat->l2[curr_index]; 1983 1984 /* Count how many temperature readings are available */ 1985 prev_index = curr_index; 1986 for (read_cnt = 0; read_cnt < L2_SZ - 1; read_cnt++) { 1987 if (tempstat->l2[prev_index] == NA_TEMP) 1988 break; 1989 prev_index = PREV_L2_INDEX(prev_index); 1990 } 1991 1992 switch (read_cnt) { 1993 case 0: 1994 case 1: 1995 result = TREND_UNKNOWN; 1996 break; 1997 1998 default: 1999 delta = curr_temp - tempstat->l2[PREV_L2_INDEX(curr_index)]; 2000 prev_index = curr_index; 2001 trail_temp = prev_temp = curr_temp; 2002 if (delta >= RAPID_RISE_THRESH) { /* rapid rise? */ 2003 result = TREND_RAPID_RISE; 2004 } else if (delta > 0) { /* rise? */ 2005 for (ii = 1; ii < read_cnt; ii++) { 2006 prev_index = PREV_L2_INDEX(prev_index); 2007 prev_temp = tempstat->l2[prev_index]; 2008 if (prev_temp > trail_temp) { 2009 break; 2010 } 2011 trail_temp = prev_temp; 2012 if (prev_temp <= curr_temp - NOISE_THRESH) { 2013 result = TREND_RISE; 2014 break; 2015 } 2016 } 2017 } else if (delta <= -RAPID_FALL_THRESH) { /* rapid fall? */ 2018 result = TREND_RAPID_FALL; 2019 } else if (delta < 0) { /* fall? */ 2020 for (ii = 1; ii < read_cnt; ii++) { 2021 prev_index = PREV_L2_INDEX(prev_index); 2022 prev_temp = tempstat->l2[prev_index]; 2023 if (prev_temp < trail_temp) { 2024 break; 2025 } 2026 trail_temp = prev_temp; 2027 if (prev_temp >= curr_temp + NOISE_THRESH) { 2028 result = TREND_FALL; 2029 break; 2030 } 2031 } 2032 } 2033 } 2034 return (result); 2035 } 2036 2037 /* 2038 * Reboot the system if we can, otherwise attempt a power down 2039 */ 2040 void 2041 fhc_reboot(void) 2042 { 2043 proc_t *initpp; 2044 2045 /* send a SIGPWR to init process */ 2046 mutex_enter(&pidlock); 2047 initpp = prfind(P_INITPID); 2048 mutex_exit(&pidlock); 2049 2050 /* 2051 * If we're still booting and init(1) isn't 2052 * set up yet, simply halt. 2053 */ 2054 if (initpp != NULL) { 2055 psignal(initpp, SIGFPE); /* init 6 */ 2056 } else { 2057 power_down("Environmental Shutdown"); 2058 halt("Power off the System"); 2059 } 2060 } 2061 2062 int 2063 overtemp_kstat_update(kstat_t *ksp, int rw) 2064 { 2065 struct temp_stats *tempstat; 2066 char *kstatp; 2067 int i; 2068 2069 kstatp = (char *)ksp->ks_data; 2070 tempstat = (struct temp_stats *)ksp->ks_private; 2071 2072 /* 2073 * Kstat reads are used to retrieve the current system temperature 2074 * history. Kstat writes are used to reset the max and min 2075 * temperatures. 2076 */ 2077 if (rw == KSTAT_WRITE) { 2078 short max; /* temporary copy of max temperature */ 2079 short min; /* temporary copy of min temperature */ 2080 2081 /* 2082 * search for and reset the max and min to the current 2083 * array contents. Old max and min values will get 2084 * averaged out as they move into the higher level arrays. 2085 */ 2086 max = tempstat->l1[0]; 2087 min = tempstat->l1[0]; 2088 2089 /* Pull the max and min from Level 1 array */ 2090 for (i = 0; i < L1_SZ; i++) { 2091 if ((tempstat->l1[i] != NA_TEMP) && 2092 (tempstat->l1[i] > max)) { 2093 max = tempstat->l1[i]; 2094 } 2095 2096 if ((tempstat->l1[i] != NA_TEMP) && 2097 (tempstat->l1[i] < min)) { 2098 min = tempstat->l1[i]; 2099 } 2100 } 2101 2102 /* Pull the max and min from Level 2 array */ 2103 for (i = 0; i < L2_SZ; i++) { 2104 if ((tempstat->l2[i] != NA_TEMP) && 2105 (tempstat->l2[i] > max)) { 2106 max = tempstat->l2[i]; 2107 } 2108 2109 if ((tempstat->l2[i] != NA_TEMP) && 2110 (tempstat->l2[i] < min)) { 2111 min = tempstat->l2[i]; 2112 } 2113 } 2114 2115 /* Pull the max and min from Level 3 array */ 2116 for (i = 0; i < L3_SZ; i++) { 2117 if ((tempstat->l3[i] != NA_TEMP) && 2118 (tempstat->l3[i] > max)) { 2119 max = tempstat->l3[i]; 2120 } 2121 2122 if ((tempstat->l3[i] != NA_TEMP) && 2123 (tempstat->l3[i] < min)) { 2124 min = tempstat->l3[i]; 2125 } 2126 } 2127 2128 /* Pull the max and min from Level 4 array */ 2129 for (i = 0; i < L4_SZ; i++) { 2130 if ((tempstat->l4[i] != NA_TEMP) && 2131 (tempstat->l4[i] > max)) { 2132 max = tempstat->l4[i]; 2133 } 2134 2135 if ((tempstat->l4[i] != NA_TEMP) && 2136 (tempstat->l4[i] < min)) { 2137 min = tempstat->l4[i]; 2138 } 2139 } 2140 2141 /* Pull the max and min from Level 5 array */ 2142 for (i = 0; i < L5_SZ; i++) { 2143 if ((tempstat->l5[i] != NA_TEMP) && 2144 (tempstat->l5[i] > max)) { 2145 max = tempstat->l5[i]; 2146 } 2147 2148 if ((tempstat->l5[i] != NA_TEMP) && 2149 (tempstat->l5[i] < min)) { 2150 min = tempstat->l5[i]; 2151 } 2152 } 2153 } else { 2154 /* 2155 * copy the temperature history buffer into the 2156 * kstat structure. 2157 */ 2158 bcopy(tempstat, kstatp, sizeof (struct temp_stats)); 2159 } 2160 return (0); 2161 } 2162 2163 int 2164 temp_override_kstat_update(kstat_t *ksp, int rw) 2165 { 2166 short *over; 2167 short *kstatp; 2168 2169 kstatp = (short *)ksp->ks_data; 2170 over = (short *)ksp->ks_private; 2171 2172 /* 2173 * Kstat reads are used to get the temperature override setting. 2174 * Kstat writes are used to set the temperature override setting. 2175 */ 2176 if (rw == KSTAT_WRITE) { 2177 *over = *kstatp; 2178 } else { 2179 *kstatp = *over; 2180 } 2181 return (0); 2182 } 2183 2184 /* 2185 * This function uses the calibration tables at the beginning of this file 2186 * to lookup the actual temperature of the thermistor in degrees Celcius. 2187 * If the measurement is out of the bounds of the acceptable values, the 2188 * closest boundary value is used instead. 2189 */ 2190 static short 2191 calibrate_temp(enum board_type type, uchar_t temp, uint_t ac_comp) 2192 { 2193 short result = NA_TEMP; 2194 2195 if (dont_calibrate == 1) { 2196 return ((short)temp); 2197 } 2198 2199 switch (type) { 2200 case CPU_BOARD: 2201 /* 2202 * If AC chip revision is >= 4 or if it is unitialized, 2203 * then use the new calibration tables. 2204 */ 2205 if ((CHIP_REV(ac_comp) >= 4) || (CHIP_REV(ac_comp) == 0)) { 2206 if (temp >= CPU2_MX_CNT) { 2207 result = cpu2_table[CPU2_MX_CNT-1]; 2208 } else { 2209 result = cpu2_table[temp]; 2210 } 2211 } else { 2212 if (temp >= CPU_MX_CNT) { 2213 result = cpu_table[CPU_MX_CNT-1]; 2214 } else { 2215 result = cpu_table[temp]; 2216 } 2217 } 2218 break; 2219 2220 case IO_2SBUS_BOARD: 2221 case IO_SBUS_FFB_BOARD: 2222 case IO_PCI_BOARD: 2223 case IO_2SBUS_SOCPLUS_BOARD: 2224 case IO_SBUS_FFB_SOCPLUS_BOARD: 2225 if (temp < IO_MN_CNT) { 2226 result = io_table[IO_MN_CNT]; 2227 } else if (temp >= IO_MX_CNT) { 2228 result = io_table[IO_MX_CNT-1]; 2229 } else { 2230 result = io_table[temp]; 2231 } 2232 break; 2233 2234 case CLOCK_BOARD: 2235 if (temp < CLK_MN_CNT) { 2236 result = clock_table[CLK_MN_CNT]; 2237 } else if (temp >= CLK_MX_CNT) { 2238 result = clock_table[CLK_MX_CNT-1]; 2239 } else { 2240 result = clock_table[temp]; 2241 } 2242 break; 2243 2244 default: 2245 break; 2246 } 2247 2248 return (result); 2249 } 2250 2251 /* 2252 * Determine the temperature state of this board based on its type and 2253 * the actual temperature in degrees Celcius. 2254 */ 2255 static enum temp_state 2256 get_temp_state(enum board_type type, short temp, int board) 2257 { 2258 enum temp_state state = TEMP_OK; 2259 short warn_limit; 2260 short danger_limit; 2261 struct cpu *cpa, *cpb; 2262 2263 switch (type) { 2264 case CPU_BOARD: 2265 warn_limit = cpu_warn_temp; 2266 danger_limit = cpu_danger_temp; 2267 2268 /* 2269 * For CPU boards with frequency >= 400 MHZ, 2270 * temperature zones are different. 2271 */ 2272 2273 mutex_enter(&cpu_lock); 2274 2275 if ((cpa = cpu_get(FHC_BOARD2CPU_A(board))) != NULL) { 2276 if ((cpa->cpu_type_info.pi_clock) >= 400) { 2277 warn_limit = cpu_warn_temp_4x; 2278 danger_limit = cpu_danger_temp_4x; 2279 } 2280 } 2281 if ((cpb = cpu_get(FHC_BOARD2CPU_B(board))) != NULL) { 2282 if ((cpb->cpu_type_info.pi_clock) >= 400) { 2283 warn_limit = cpu_warn_temp_4x; 2284 danger_limit = cpu_danger_temp_4x; 2285 } 2286 } 2287 2288 mutex_exit(&cpu_lock); 2289 2290 break; 2291 2292 case IO_2SBUS_BOARD: 2293 case IO_SBUS_FFB_BOARD: 2294 case IO_PCI_BOARD: 2295 case IO_2SBUS_SOCPLUS_BOARD: 2296 case IO_SBUS_FFB_SOCPLUS_BOARD: 2297 warn_limit = io_warn_temp; 2298 danger_limit = io_danger_temp; 2299 break; 2300 2301 case CLOCK_BOARD: 2302 warn_limit = clk_warn_temp; 2303 danger_limit = clk_danger_temp; 2304 break; 2305 2306 case UNINIT_BOARD: 2307 case UNKNOWN_BOARD: 2308 case MEM_BOARD: 2309 default: 2310 warn_limit = dft_warn_temp; 2311 danger_limit = dft_danger_temp; 2312 break; 2313 } 2314 2315 if (temp >= danger_limit) { 2316 state = TEMP_DANGER; 2317 } else if (temp >= warn_limit) { 2318 state = TEMP_WARN; 2319 } 2320 2321 return (state); 2322 } 2323 2324 static void 2325 fhc_add_kstats(struct fhc_soft_state *softsp) 2326 { 2327 struct kstat *fhc_ksp; 2328 struct fhc_kstat *fhc_named_ksp; 2329 2330 if ((fhc_ksp = kstat_create("unix", softsp->list->sc.board, 2331 FHC_KSTAT_NAME, "misc", KSTAT_TYPE_NAMED, 2332 sizeof (struct fhc_kstat) / sizeof (kstat_named_t), 2333 KSTAT_FLAG_PERSISTENT)) == NULL) { 2334 cmn_err(CE_WARN, "fhc%d kstat_create failed", 2335 ddi_get_instance(softsp->dip)); 2336 return; 2337 } 2338 2339 fhc_named_ksp = (struct fhc_kstat *)(fhc_ksp->ks_data); 2340 2341 /* initialize the named kstats */ 2342 kstat_named_init(&fhc_named_ksp->csr, 2343 CSR_KSTAT_NAMED, 2344 KSTAT_DATA_UINT32); 2345 2346 kstat_named_init(&fhc_named_ksp->bsr, 2347 BSR_KSTAT_NAMED, 2348 KSTAT_DATA_UINT32); 2349 2350 fhc_ksp->ks_update = fhc_kstat_update; 2351 fhc_ksp->ks_private = (void *)softsp; 2352 softsp->fhc_ksp = fhc_ksp; 2353 kstat_install(fhc_ksp); 2354 } 2355 2356 static int 2357 fhc_kstat_update(kstat_t *ksp, int rw) 2358 { 2359 struct fhc_kstat *fhcksp; 2360 struct fhc_soft_state *softsp; 2361 2362 fhcksp = (struct fhc_kstat *)ksp->ks_data; 2363 softsp = (struct fhc_soft_state *)ksp->ks_private; 2364 2365 /* this is a read-only kstat. Bail out on a write */ 2366 if (rw == KSTAT_WRITE) { 2367 return (EACCES); 2368 } else { 2369 /* 2370 * copy the current state of the hardware into the 2371 * kstat structure. 2372 */ 2373 fhcksp->csr.value.ui32 = *softsp->ctrl; 2374 fhcksp->bsr.value.ui32 = *softsp->bsr; 2375 } 2376 return (0); 2377 } 2378 2379 static int 2380 cpu_on_board(int board) 2381 { 2382 int upa_a = board << 1; 2383 int upa_b = (board << 1) + 1; 2384 2385 if ((cpunodes[upa_a].nodeid != NULL) || 2386 (cpunodes[upa_b].nodeid != NULL)) { 2387 return (1); 2388 } else { 2389 return (0); 2390 } 2391 } 2392 2393 /* 2394 * This function uses the board list and toggles the OS green board 2395 * LED. The mask input tells which bit fields are being modified, 2396 * and the value input tells the states of the bits. 2397 */ 2398 void 2399 update_board_leds(fhc_bd_t *board, uint_t mask, uint_t value) 2400 { 2401 volatile uint_t temp; 2402 2403 ASSERT(fhc_bdlist_locked()); 2404 2405 /* mask off mask and value for only the LED bits */ 2406 mask &= (FHC_LED_LEFT|FHC_LED_MID|FHC_LED_RIGHT); 2407 value &= (FHC_LED_LEFT|FHC_LED_MID|FHC_LED_RIGHT); 2408 2409 if (board != NULL) { 2410 mutex_enter(&board->softsp->ctrl_lock); 2411 2412 /* read the current register state */ 2413 temp = *board->softsp->ctrl; 2414 2415 /* 2416 * The EPDA bits are special since the register is 2417 * special. We don't want to set them, since setting 2418 * the bits on a shutdown cpu keeps the cpu permanently 2419 * powered off. Also, the CSR_SYNC bit must always be 2420 * set to 0 as it is an OBP semaphore that is expected to 2421 * be clear for cpu restart. 2422 */ 2423 temp &= ~(FHC_CSR_SYNC | FHC_EPDA_OFF | FHC_EPDB_OFF); 2424 2425 /* mask off the bits to change */ 2426 temp &= ~mask; 2427 2428 /* or in the new values of the bits. */ 2429 temp |= value; 2430 2431 /* update the register */ 2432 *board->softsp->ctrl = temp; 2433 2434 /* flush the hardware registers */ 2435 temp = *board->softsp->ctrl; 2436 #ifdef lint 2437 temp = temp; 2438 #endif 2439 2440 mutex_exit(&board->softsp->ctrl_lock); 2441 } 2442 } 2443 2444 static int 2445 check_for_chamber(void) 2446 { 2447 int chamber = 0; 2448 dev_info_t *options_dip; 2449 pnode_t options_node_id; 2450 int mfgmode_len; 2451 int retval; 2452 char *mfgmode; 2453 2454 /* 2455 * The operator can disable overtemp powerdown from /etc/system or 2456 * boot -h. 2457 */ 2458 if (!enable_overtemp_powerdown) { 2459 cmn_err(CE_WARN, "Operator has disabled overtemp powerdown"); 2460 return (1); 2461 } 2462 2463 /* 2464 * An OBP option, 'mfg-mode' is being used to inform us as to 2465 * whether we are in an enviromental chamber. It exists in 2466 * the 'options' node. This is where all OBP 'setenv' (eeprom) 2467 * parameters live. 2468 */ 2469 if ((options_dip = ddi_find_devinfo("options", -1, 0)) != NULL) { 2470 options_node_id = (pnode_t)ddi_get_nodeid(options_dip); 2471 mfgmode_len = prom_getproplen(options_node_id, "mfg-mode"); 2472 if (mfgmode_len == -1) { 2473 return (chamber); 2474 } 2475 mfgmode = kmem_alloc(mfgmode_len+1, KM_SLEEP); 2476 2477 retval = prom_getprop(options_node_id, "mfg-mode", mfgmode); 2478 if (retval != -1) { 2479 mfgmode[retval] = 0; 2480 if (strcmp(mfgmode, CHAMBER_VALUE) == 0) { 2481 chamber = 1; 2482 cmn_err(CE_WARN, "System in Temperature" 2483 " Chamber Mode. Overtemperature" 2484 " Shutdown disabled"); 2485 } 2486 } 2487 kmem_free(mfgmode, mfgmode_len+1); 2488 } 2489 return (chamber); 2490 } 2491 2492 static void 2493 build_bd_display_str(char *buffer, enum board_type type, int board) 2494 { 2495 if (buffer == NULL) { 2496 return; 2497 } 2498 2499 /* fill in board type to display */ 2500 switch (type) { 2501 case UNINIT_BOARD: 2502 (void) sprintf(buffer, "Uninitialized Board type board %d", 2503 board); 2504 break; 2505 2506 case UNKNOWN_BOARD: 2507 (void) sprintf(buffer, "Unknown Board type board %d", board); 2508 break; 2509 2510 case CPU_BOARD: 2511 case MEM_BOARD: 2512 (void) sprintf(buffer, "CPU/Memory board %d", board); 2513 break; 2514 2515 case IO_2SBUS_BOARD: 2516 (void) sprintf(buffer, "2 SBus IO board %d", board); 2517 break; 2518 2519 case IO_SBUS_FFB_BOARD: 2520 (void) sprintf(buffer, "SBus FFB IO board %d", board); 2521 break; 2522 2523 case IO_PCI_BOARD: 2524 (void) sprintf(buffer, "PCI IO board %d", board); 2525 break; 2526 2527 case CLOCK_BOARD: 2528 (void) sprintf(buffer, "Clock board"); 2529 break; 2530 2531 case IO_2SBUS_SOCPLUS_BOARD: 2532 (void) sprintf(buffer, "2 SBus SOC+ IO board %d", board); 2533 break; 2534 2535 case IO_SBUS_FFB_SOCPLUS_BOARD: 2536 (void) sprintf(buffer, "SBus FFB SOC+ IO board %d", board); 2537 break; 2538 2539 default: 2540 (void) sprintf(buffer, "Unrecognized board type board %d", 2541 board); 2542 break; 2543 } 2544 } 2545 2546 void 2547 fhc_intrdist(void *arg) 2548 { 2549 struct fhc_soft_state *softsp; 2550 dev_info_t *dip = (dev_info_t *)arg; 2551 volatile uint_t *mondo_vec_reg; 2552 volatile uint_t *intr_state_reg; 2553 uint_t mondo_vec; 2554 uint_t tmp_reg; 2555 uint_t cpu_id; 2556 uint_t i; 2557 2558 /* extract the soft state pointer */ 2559 softsp = ddi_get_soft_state(fhcp, ddi_get_instance(dip)); 2560 2561 /* 2562 * Loop through all the interrupt mapping registers and reprogram 2563 * the target CPU for all valid registers. 2564 */ 2565 for (i = 0; i < FHC_MAX_INO; i++) { 2566 mondo_vec_reg = softsp->intr_regs[i].mapping_reg; 2567 intr_state_reg = softsp->intr_regs[i].clear_reg; 2568 2569 if ((*mondo_vec_reg & IMR_VALID) == 0) 2570 continue; 2571 2572 cpu_id = intr_dist_cpuid(); 2573 2574 /* Check the current target of the mondo */ 2575 if (((*mondo_vec_reg & INR_PID_MASK) >> INR_PID_SHIFT) == 2576 cpu_id) { 2577 /* It is the same, don't reprogram */ 2578 return; 2579 } 2580 2581 /* So it's OK to reprogram the CPU target */ 2582 2583 /* turn off the valid bit */ 2584 *mondo_vec_reg &= ~IMR_VALID; 2585 2586 /* flush the hardware registers */ 2587 tmp_reg = *softsp->id; 2588 2589 /* 2590 * wait for the state machine to idle. Do not loop on panic, so 2591 * that system does not hang. 2592 */ 2593 while (((*intr_state_reg & INT_PENDING) == INT_PENDING) && 2594 !panicstr) 2595 ; 2596 2597 /* re-target the mondo and turn it on */ 2598 mondo_vec = (cpu_id << INR_PID_SHIFT) | IMR_VALID; 2599 2600 /* write it back to the hardware. */ 2601 *mondo_vec_reg = mondo_vec; 2602 2603 /* flush the hardware buffers. */ 2604 tmp_reg = *(softsp->id); 2605 2606 #ifdef lint 2607 tmp_reg = tmp_reg; 2608 #endif /* lint */ 2609 } 2610 } 2611 2612 /* 2613 * reg_fault 2614 * 2615 * This routine registers a fault in the fault list. If the fault 2616 * is unique (does not exist in fault list) then a new fault is 2617 * added to the fault list, with the appropriate structure elements 2618 * filled in. 2619 */ 2620 void 2621 reg_fault(int unit, enum ft_type type, enum ft_class fclass) 2622 { 2623 struct ft_link_list *list; /* temporary list pointer */ 2624 2625 if (type >= ft_max_index) { 2626 cmn_err(CE_WARN, "Illegal Fault type %x", type); 2627 return; 2628 } 2629 2630 mutex_enter(&ftlist_mutex); 2631 2632 /* Search for the requested fault. If it already exists, return. */ 2633 for (list = ft_list; list != NULL; list = list->next) { 2634 if ((list->f.unit == unit) && (list->f.type == type) && 2635 (list->f.fclass == fclass)) { 2636 mutex_exit(&ftlist_mutex); 2637 return; 2638 } 2639 } 2640 2641 /* Allocate a new fault structure. */ 2642 list = kmem_zalloc(sizeof (struct ft_link_list), KM_SLEEP); 2643 2644 /* fill in the fault list elements */ 2645 list->f.unit = unit; 2646 list->f.type = type; 2647 list->f.fclass = fclass; 2648 list->f.create_time = (time32_t)gethrestime_sec(); /* XX64 */ 2649 (void) strncpy(list->f.msg, ft_str_table[type], MAX_FT_DESC); 2650 2651 /* link it into the list. */ 2652 list->next = ft_list; 2653 ft_list = list; 2654 2655 /* Update the total fault count */ 2656 ft_nfaults++; 2657 2658 mutex_exit(&ftlist_mutex); 2659 } 2660 2661 /* 2662 * clear_fault 2663 * 2664 * This routine finds the fault list entry specified by the caller, 2665 * deletes it from the fault list, and frees up the memory used for 2666 * the entry. If the requested fault is not found, it exits silently. 2667 */ 2668 void 2669 clear_fault(int unit, enum ft_type type, enum ft_class fclass) 2670 { 2671 struct ft_link_list *list; /* temporary list pointer */ 2672 struct ft_link_list **vect; 2673 2674 mutex_enter(&ftlist_mutex); 2675 2676 list = ft_list; 2677 vect = &ft_list; 2678 2679 /* 2680 * Search for the requested fault. If it exists, delete it 2681 * and relink the fault list. 2682 */ 2683 for (; list != NULL; vect = &list->next, list = list->next) { 2684 if ((list->f.unit == unit) && (list->f.type == type) && 2685 (list->f.fclass == fclass)) { 2686 /* remove the item from the list */ 2687 *vect = list->next; 2688 2689 /* free the memory allocated */ 2690 kmem_free(list, sizeof (struct ft_link_list)); 2691 2692 /* Update the total fault count */ 2693 ft_nfaults--; 2694 break; 2695 } 2696 } 2697 mutex_exit(&ftlist_mutex); 2698 } 2699 2700 /* 2701 * process_fault_list 2702 * 2703 * This routine walks the global fault list and updates the board list 2704 * with the current status of each Yellow LED. If any faults are found 2705 * in the system, then a non-zero value is returned. Else zero is returned. 2706 */ 2707 int 2708 process_fault_list(void) 2709 { 2710 int fault = 0; 2711 struct ft_link_list *ftlist; /* fault list pointer */ 2712 fhc_bd_t *bdlist; /* board list pointer */ 2713 2714 /* 2715 * Note on locking. The bdlist mutex is always acquired and 2716 * held around the ftlist mutex when both are needed for an 2717 * operation. This is to avoid deadlock. 2718 */ 2719 2720 /* First lock the board list */ 2721 (void) fhc_bdlist_lock(-1); 2722 2723 /* Grab the fault list lock first */ 2724 mutex_enter(&ftlist_mutex); 2725 2726 /* clear the board list of all faults first */ 2727 for (bdlist = fhc_bd_first(); bdlist; bdlist = fhc_bd_next(bdlist)) 2728 bdlist->fault = 0; 2729 2730 /* walk the fault list here */ 2731 for (ftlist = ft_list; ftlist != NULL; ftlist = ftlist->next) { 2732 fault++; 2733 2734 /* 2735 * If this is a board level fault, find the board, The 2736 * unit number for all board class faults must be the 2737 * actual board number. The caller of reg_fault must 2738 * ensure this for FT_BOARD class faults. 2739 */ 2740 if (ftlist->f.fclass == FT_BOARD) { 2741 /* Sanity check the board first */ 2742 if (fhc_bd_valid(ftlist->f.unit)) { 2743 bdlist = fhc_bd(ftlist->f.unit); 2744 bdlist->fault = 1; 2745 } else { 2746 cmn_err(CE_WARN, "No board %d list entry found", 2747 ftlist->f.unit); 2748 } 2749 } 2750 } 2751 2752 /* now unlock the fault list */ 2753 mutex_exit(&ftlist_mutex); 2754 2755 /* unlock the board list before leaving */ 2756 fhc_bdlist_unlock(); 2757 2758 return (fault); 2759 } 2760 2761 /* 2762 * Add a new memloc to the database (and keep 'em sorted by PA) 2763 */ 2764 void 2765 fhc_add_memloc(int board, uint64_t pa, uint_t size) 2766 { 2767 struct fhc_memloc *p, **pp; 2768 uint_t ipa = pa >> FHC_MEMLOC_SHIFT; 2769 2770 ASSERT(fhc_bdlist_locked()); 2771 ASSERT((size & (size-1)) == 0); /* size must be power of 2 */ 2772 2773 /* look for a comparable memloc (as long as new PA smaller) */ 2774 for (p = fhc_base_memloc, pp = &fhc_base_memloc; 2775 p != NULL; pp = &p->next, p = p->next) { 2776 /* have we passed our place in the sort? */ 2777 if (ipa < p->pa) { 2778 break; 2779 } 2780 } 2781 p = kmem_alloc(sizeof (struct fhc_memloc), KM_SLEEP); 2782 p->next = *pp; 2783 p->board = board; 2784 p->pa = ipa; 2785 p->size = size; 2786 #ifdef DEBUG_MEMDEC 2787 cmn_err(CE_NOTE, "fhc_add_memloc: adding %d 0x%x 0x%x", 2788 p->board, p->pa, p->size); 2789 #endif /* DEBUG_MEMDEC */ 2790 *pp = p; 2791 } 2792 2793 /* 2794 * Delete all memloc records for a board from the database 2795 */ 2796 void 2797 fhc_del_memloc(int board) 2798 { 2799 struct fhc_memloc *p, **pp; 2800 2801 ASSERT(fhc_bdlist_locked()); 2802 2803 /* delete all entries that match board */ 2804 pp = &fhc_base_memloc; 2805 while ((p = *pp) != NULL) { 2806 if (p->board == board) { 2807 #ifdef DEBUG_MEMDEC 2808 cmn_err(CE_NOTE, "fhc_del_memloc: removing %d " 2809 "0x%x 0x%x", board, p->pa, p->size); 2810 #endif /* DEBUG_MEMDEC */ 2811 *pp = p->next; 2812 kmem_free(p, sizeof (struct fhc_memloc)); 2813 } else { 2814 pp = &(p->next); 2815 } 2816 } 2817 } 2818 2819 /* 2820 * Find a physical address range of sufficient size and return a starting PA 2821 */ 2822 uint64_t 2823 fhc_find_memloc_gap(uint_t size) 2824 { 2825 struct fhc_memloc *p; 2826 uint_t base_pa = 0; 2827 uint_t mask = ~(size-1); 2828 2829 ASSERT(fhc_bdlist_locked()); 2830 ASSERT((size & (size-1)) == 0); /* size must be power of 2 */ 2831 2832 /* 2833 * walk the list of known memlocs and measure the 'gaps'. 2834 * we will need a hole that can align the 'size' requested. 2835 * (e.g. a 256mb bank needs to be on a 256mb boundary). 2836 */ 2837 for (p = fhc_base_memloc; p != NULL; p = p->next) { 2838 if (base_pa != (base_pa & mask)) 2839 base_pa = (base_pa + size) & mask; 2840 if (base_pa + size <= p->pa) 2841 break; 2842 base_pa = p->pa + p->size; 2843 } 2844 2845 /* 2846 * At this point, we assume that base_pa is good enough. 2847 */ 2848 ASSERT((base_pa + size) <= FHC_MEMLOC_MAX); 2849 if (base_pa != (base_pa & mask)) 2850 base_pa = (base_pa + size) & mask; /* align */ 2851 return ((uint64_t)base_pa << FHC_MEMLOC_SHIFT); 2852 } 2853 2854 /* 2855 * This simple function to write the MCRs can only be used when 2856 * the contents of memory are not valid as there is a bug in the AC 2857 * ASIC concerning refresh. 2858 */ 2859 static void 2860 fhc_write_mcrs( 2861 uint64_t cpa, 2862 uint64_t dpa0, 2863 uint64_t dpa1, 2864 uint64_t c, 2865 uint64_t d0, 2866 uint64_t d1) 2867 { 2868 stdphysio(cpa, c & ~AC_CSR_REFEN); 2869 (void) lddphysio(cpa); 2870 if (GRP_SIZE_IS_SET(d0)) { 2871 stdphysio(dpa0, d0); 2872 (void) lddphysio(dpa0); 2873 } 2874 if (GRP_SIZE_IS_SET(d1)) { 2875 stdphysio(dpa1, d1); 2876 (void) lddphysio(dpa1); 2877 } 2878 stdphysio(cpa, c); 2879 (void) lddphysio(cpa); 2880 } 2881 2882 /* compute the appropriate RASIZE for bank size */ 2883 static uint_t 2884 fhc_cvt_size(uint64_t bsz) 2885 { 2886 uint_t csz; 2887 2888 csz = 0; 2889 bsz /= 64; 2890 while (bsz) { 2891 csz++; 2892 bsz /= 2; 2893 } 2894 csz /= 2; 2895 2896 return (csz); 2897 } 2898 2899 void 2900 fhc_program_memory(int board, uint64_t pa) 2901 { 2902 uint64_t cpa, dpa0, dpa1; 2903 uint64_t c, d0, d1; 2904 uint64_t b0_pa, b1_pa; 2905 uint64_t memdec0, memdec1; 2906 uint_t b0_size, b1_size; 2907 2908 /* XXX gross hack to get to board via board number */ 2909 cpa = 0x1c0f9000060ull + (board * 0x400000000ull); 2910 #ifdef DEBUG_MEMDEC 2911 prom_printf("cpa = 0x%llx\n", cpa); 2912 #endif /* DEBUG_MEMDEC */ 2913 dpa0 = cpa + 0x10; 2914 dpa1 = cpa + 0x20; 2915 2916 /* assume size is set by connect */ 2917 memdec0 = lddphysio(dpa0); 2918 #ifdef DEBUG_MEMDEC 2919 prom_printf("memdec0 = 0x%llx\n", memdec0); 2920 #endif /* DEBUG_MEMDEC */ 2921 memdec1 = lddphysio(dpa1); 2922 #ifdef DEBUG_MEMDEC 2923 prom_printf("memdec1 = 0x%llx\n", memdec1); 2924 #endif /* DEBUG_MEMDEC */ 2925 if (GRP_SIZE_IS_SET(memdec0)) { 2926 b0_size = GRP_SPANMB(memdec0); 2927 } else { 2928 b0_size = 0; 2929 } 2930 if (GRP_SIZE_IS_SET(memdec1)) { 2931 b1_size = GRP_SPANMB(memdec1); 2932 } else { 2933 b1_size = 0; 2934 } 2935 2936 c = lddphysio(cpa); 2937 #ifdef DEBUG_MEMDEC 2938 prom_printf("c = 0x%llx\n", c); 2939 #endif /* DEBUG_MEMDEC */ 2940 if (b0_size) { 2941 b0_pa = pa; 2942 d0 = SETUP_DECODE(b0_pa, b0_size, 0, 0); 2943 d0 |= AC_MEM_VALID; 2944 2945 c &= ~0x7; 2946 c |= 0; 2947 c &= ~(0x7 << 8); 2948 c |= (fhc_cvt_size(b0_size) << 8); /* match row size */ 2949 } else { 2950 d0 = memdec0; 2951 } 2952 if (b1_size) { 2953 b1_pa = pa + 0x80000000ull; /* XXX 2gb */ 2954 d1 = SETUP_DECODE(b1_pa, b1_size, 0, 0); 2955 d1 |= AC_MEM_VALID; 2956 2957 c &= ~(0x7 << 3); 2958 c |= (0 << 3); 2959 c &= ~(0x7 << 11); 2960 c |= (fhc_cvt_size(b1_size) << 11); /* match row size */ 2961 } else { 2962 d1 = memdec1; 2963 } 2964 #ifdef DEBUG_MEMDEC 2965 prom_printf("c 0x%llx, d0 0x%llx, d1 0x%llx\n", c, d0, d1); 2966 #endif /* DEBUG_MEMDEC */ 2967 fhc_write_mcrs(cpa, dpa0, dpa1, c, d0, d1); 2968 } 2969 2970 /* 2971 * Creates a variable sized virtual kstat with a snapshot routine in order 2972 * to pass the linked list fault list up to userland. Also creates a 2973 * virtual kstat to pass up the string table for faults. 2974 */ 2975 void 2976 create_ft_kstats(int instance) 2977 { 2978 struct kstat *ksp; 2979 2980 ksp = kstat_create("unix", instance, FT_LIST_KSTAT_NAME, "misc", 2981 KSTAT_TYPE_RAW, 1, KSTAT_FLAG_VIRTUAL|KSTAT_FLAG_VAR_SIZE); 2982 2983 if (ksp != NULL) { 2984 ksp->ks_data = NULL; 2985 ksp->ks_update = ft_ks_update; 2986 ksp->ks_snapshot = ft_ks_snapshot; 2987 ksp->ks_data_size = 1; 2988 ksp->ks_lock = &ftlist_mutex; 2989 kstat_install(ksp); 2990 } 2991 } 2992 2993 /* 2994 * This routine creates a snapshot of all the fault list data. It is 2995 * called by the kstat framework when a kstat read is done. 2996 */ 2997 static int 2998 ft_ks_snapshot(struct kstat *ksp, void *buf, int rw) 2999 { 3000 struct ft_link_list *ftlist; 3001 3002 if (rw == KSTAT_WRITE) { 3003 return (EACCES); 3004 } 3005 3006 ksp->ks_snaptime = gethrtime(); 3007 3008 for (ftlist = ft_list; ftlist != NULL; ftlist = ftlist->next) { 3009 bcopy(&ftlist->f, buf, sizeof (struct ft_list)); 3010 buf = ((struct ft_list *)buf) + 1; 3011 } 3012 return (0); 3013 } 3014 3015 /* 3016 * Setup the kstat data size for the kstat framework. This is used in 3017 * conjunction with the ks_snapshot routine. This routine sets the size, 3018 * the kstat framework allocates the memory, and ks_shapshot does the 3019 * data transfer. 3020 */ 3021 static int 3022 ft_ks_update(struct kstat *ksp, int rw) 3023 { 3024 if (rw == KSTAT_WRITE) { 3025 return (EACCES); 3026 } else { 3027 if (ft_nfaults) { 3028 ksp->ks_data_size = ft_nfaults * 3029 sizeof (struct ft_list); 3030 } else { 3031 ksp->ks_data_size = 1; 3032 } 3033 } 3034 3035 return (0); 3036 } 3037 3038 /* 3039 * Power off any cpus on the board. 3040 */ 3041 int 3042 fhc_board_poweroffcpus(int board, char *errbuf, int cpu_flags) 3043 { 3044 cpu_t *cpa, *cpb; 3045 enum board_type type; 3046 int error = 0; 3047 3048 ASSERT(MUTEX_HELD(&cpu_lock)); 3049 3050 /* 3051 * what type of board are we dealing with? 3052 */ 3053 type = fhc_bd_type(board); 3054 3055 switch (type) { 3056 case CPU_BOARD: 3057 3058 /* 3059 * the shutdown sequence will be: 3060 * 3061 * idle both cpus then shut them off. 3062 * it looks like the hardware gets corrupted if one 3063 * cpu is busy while the other is shutting down... 3064 */ 3065 3066 if ((cpa = cpu_get(FHC_BOARD2CPU_A(board))) != NULL && 3067 cpu_is_active(cpa)) { 3068 if (!cpu_intr_on(cpa)) { 3069 cpu_intr_enable(cpa); 3070 } 3071 if ((error = cpu_offline(cpa, cpu_flags)) != 0) { 3072 cmn_err(CE_WARN, 3073 "Processor %d failed to offline.", 3074 cpa->cpu_id); 3075 if (errbuf != NULL) { 3076 (void) snprintf(errbuf, SYSC_OUTPUT_LEN, 3077 "processor %d failed to offline", 3078 cpa->cpu_id); 3079 } 3080 } 3081 } 3082 3083 if (error == 0 && 3084 (cpb = cpu_get(FHC_BOARD2CPU_B(board))) != NULL && 3085 cpu_is_active(cpb)) { 3086 if (!cpu_intr_on(cpb)) { 3087 cpu_intr_enable(cpb); 3088 } 3089 if ((error = cpu_offline(cpb, cpu_flags)) != 0) { 3090 cmn_err(CE_WARN, 3091 "Processor %d failed to offline.", 3092 cpb->cpu_id); 3093 3094 if (errbuf != NULL) { 3095 (void) snprintf(errbuf, SYSC_OUTPUT_LEN, 3096 "processor %d failed to offline", 3097 cpb->cpu_id); 3098 } 3099 } 3100 } 3101 3102 if (error == 0 && cpa != NULL && cpu_is_offline(cpa)) { 3103 if ((error = cpu_poweroff(cpa)) != 0) { 3104 cmn_err(CE_WARN, 3105 "Processor %d failed to power off.", 3106 cpa->cpu_id); 3107 if (errbuf != NULL) { 3108 (void) snprintf(errbuf, SYSC_OUTPUT_LEN, 3109 "processor %d failed to power off", 3110 cpa->cpu_id); 3111 } 3112 } else { 3113 cmn_err(CE_NOTE, "Processor %d powered off.", 3114 cpa->cpu_id); 3115 } 3116 } 3117 3118 if (error == 0 && cpb != NULL && cpu_is_offline(cpb)) { 3119 if ((error = cpu_poweroff(cpb)) != 0) { 3120 cmn_err(CE_WARN, 3121 "Processor %d failed to power off.", 3122 cpb->cpu_id); 3123 3124 if (errbuf != NULL) { 3125 (void) snprintf(errbuf, SYSC_OUTPUT_LEN, 3126 "processor %d failed to power off", 3127 cpb->cpu_id); 3128 } 3129 } else { 3130 cmn_err(CE_NOTE, "Processor %d powered off.", 3131 cpb->cpu_id); 3132 } 3133 } 3134 3135 /* 3136 * If all the shutdowns completed, ONLY THEN, clear the 3137 * incorrectly valid dtags... 3138 * 3139 * IMPORTANT: it is an error to read or write dtags while 3140 * they are 'active' 3141 */ 3142 if (error == 0 && (cpa != NULL || cpb != NULL)) { 3143 u_longlong_t base = 0; 3144 int i; 3145 #ifdef DEBUG 3146 int nonz0 = 0; 3147 int nonz1 = 0; 3148 #endif 3149 if (cpa != NULL) 3150 base = FHC_DTAG_BASE(cpa->cpu_id); 3151 if (cpb != NULL) 3152 base = FHC_DTAG_BASE(cpb->cpu_id); 3153 ASSERT(base != 0); 3154 3155 for (i = 0; i < FHC_DTAG_SIZE; i += FHC_DTAG_SKIP) { 3156 u_longlong_t value = lddphysio(base+i); 3157 #ifdef lint 3158 value = value; 3159 #endif 3160 #ifdef DEBUG 3161 if (cpa != NULL && (value & FHC_DTAG_LOW)) 3162 nonz0++; 3163 if (cpb != NULL && (value & FHC_DTAG_HIGH)) 3164 nonz1++; 3165 #endif 3166 /* always clear the dtags */ 3167 stdphysio(base + i, 0ull); 3168 } 3169 #ifdef DEBUG 3170 if (nonz0 || nonz1) { 3171 cmn_err(CE_NOTE, "!dtag results: " 3172 "cpua valid %d, cpub valid %d", 3173 nonz0, nonz1); 3174 } 3175 #endif 3176 } 3177 3178 break; 3179 3180 default: 3181 break; 3182 } 3183 3184 return (error); 3185 } 3186 3187 /* 3188 * platform code for shutting down cpus. 3189 */ 3190 int 3191 fhc_cpu_poweroff(struct cpu *cp) 3192 { 3193 int board; 3194 fhc_bd_t *bd_list; 3195 int delays; 3196 extern void idle_stop_xcall(void); 3197 static void fhc_cpu_shutdown_self(void); 3198 3199 ASSERT(MUTEX_HELD(&cpu_lock)); 3200 ASSERT((cp->cpu_flags & (CPU_EXISTS | CPU_OFFLINE | CPU_QUIESCED)) == 3201 (CPU_EXISTS | CPU_OFFLINE | CPU_QUIESCED)); 3202 3203 /* 3204 * Lock the board so that we can safely access the 3205 * registers. This cannot be done inside the pause_cpus(). 3206 */ 3207 board = FHC_CPU2BOARD(cp->cpu_id); 3208 bd_list = fhc_bdlist_lock(board); 3209 ASSERT(fhc_bd_valid(board) && (bd_list->sc.type == CPU_BOARD)); 3210 3211 /* 3212 * Capture all CPUs (except for detaching proc) to prevent 3213 * crosscalls to the detaching proc until it has cleared its 3214 * bit in cpu_ready_set. 3215 * 3216 * The CPU's remain paused and the prom_mutex is known to be free. 3217 * This prevents the x-trap victim from blocking when doing prom 3218 * IEEE-1275 calls at a high PIL level. 3219 */ 3220 promsafe_pause_cpus(); 3221 3222 /* 3223 * Quiesce interrupts on the target CPU. We do this by setting 3224 * the CPU 'not ready'- (i.e. removing the CPU from cpu_ready_set) to 3225 * prevent it from receiving cross calls and cross traps. 3226 * This prevents the processor from receiving any new soft interrupts. 3227 */ 3228 mp_cpu_quiesce(cp); 3229 3230 xt_one_unchecked(cp->cpu_id, (xcfunc_t *)idle_stop_xcall, 3231 (uint64_t)fhc_cpu_shutdown_self, (uint64_t)NULL); 3232 3233 /* 3234 * Wait for slave cpu to shutdown. 3235 * Sense this by watching the hardware EPDx bit. 3236 */ 3237 for (delays = FHC_SHUTDOWN_WAIT_MSEC; delays != 0; delays--) { 3238 uint_t temp; 3239 3240 DELAY(1000); 3241 3242 /* get the current cpu power status */ 3243 temp = *bd_list->softsp->ctrl; 3244 3245 /* has the cpu actually signalled shutdown? */ 3246 if (FHC_CPU_IS_A(cp->cpu_id)) { 3247 if (temp & FHC_EPDA_OFF) 3248 break; 3249 } else { 3250 if (temp & FHC_EPDB_OFF) 3251 break; 3252 } 3253 } 3254 3255 start_cpus(); 3256 3257 fhc_bdlist_unlock(); 3258 3259 /* A timeout means we've lost control of the cpu. */ 3260 if (delays == 0) 3261 panic("Processor %d failed during shutdown", cp->cpu_id); 3262 3263 return (0); 3264 } 3265 3266 /* 3267 * shutdown_self 3268 * slave side shutdown. clean up and execute the shutdown sequence. 3269 */ 3270 static void 3271 fhc_cpu_shutdown_self(void) 3272 { 3273 extern void flush_windows(void); 3274 static void os_completes_shutdown(void); 3275 3276 flush_windows(); 3277 3278 ASSERT(CPU->cpu_intr_actv == 0); 3279 ASSERT(CPU->cpu_thread == CPU->cpu_idle_thread || 3280 CPU->cpu_thread == CPU->cpu_startup_thread); 3281 3282 CPU->cpu_flags = CPU_POWEROFF | CPU_OFFLINE | CPU_QUIESCED; 3283 3284 (void) prom_sunfire_cpu_off(); /* inform Ultra Enterprise prom */ 3285 3286 os_completes_shutdown(); 3287 3288 panic("fhc_cpu_shutdown_self: cannot return"); 3289 /*NOTREACHED*/ 3290 } 3291 3292 /* 3293 * Warm start CPU. 3294 */ 3295 static int 3296 fhc_cpu_start(struct cpu *cp) 3297 { 3298 int rv; 3299 int cpuid = cp->cpu_id; 3300 pnode_t nodeid; 3301 extern void restart_other_cpu(int); 3302 3303 ASSERT(MUTEX_HELD(&cpu_lock)); 3304 3305 /* power on cpu */ 3306 nodeid = cpunodes[cpuid].nodeid; 3307 ASSERT(nodeid != (pnode_t)0); 3308 rv = prom_wakeupcpu(nodeid); 3309 if (rv != 0) { 3310 cmn_err(CE_WARN, "Processor %d failed to power on.", cpuid); 3311 return (EBUSY); 3312 } 3313 3314 cp->cpu_flags &= ~CPU_POWEROFF; 3315 3316 /* 3317 * NOTE: restart_other_cpu pauses cpus during the slave cpu start. 3318 * This helps to quiesce the bus traffic a bit which makes 3319 * the tick sync routine in the prom more robust. 3320 */ 3321 restart_other_cpu(cpuid); 3322 3323 return (0); 3324 } 3325 3326 /* 3327 * Power on CPU. 3328 */ 3329 int 3330 fhc_cpu_poweron(struct cpu *cp) 3331 { 3332 fhc_bd_t *bd_list; 3333 enum temp_state state; 3334 int board; 3335 int status; 3336 int status_other; 3337 struct cpu *cp_other; 3338 3339 ASSERT(MUTEX_HELD(&cpu_lock)); 3340 ASSERT(cpu_is_poweredoff(cp)); 3341 3342 /* do not power on overtemperature cpu */ 3343 board = FHC_CPU2BOARD(cp->cpu_id); 3344 bd_list = fhc_bdlist_lock(board); 3345 3346 ASSERT(bd_list != NULL); 3347 ASSERT(bd_list->sc.type == CPU_BOARD); 3348 ASSERT(bd_list->dev_softsp != NULL); 3349 3350 state = ((struct environ_soft_state *) 3351 bd_list->dev_softsp)->tempstat.state; 3352 3353 fhc_bdlist_unlock(); 3354 if ((state == TEMP_WARN) || (state == TEMP_DANGER)) 3355 return (EBUSY); 3356 3357 status = fhc_cpu_start(cp); 3358 3359 /* policy for dual cpu boards */ 3360 3361 if ((status == 0) && 3362 ((cp_other = cpu_get(FHC_OTHER_CPU_ID(cp->cpu_id))) != NULL)) { 3363 /* 3364 * Do not leave board's other cpu idling in the prom. 3365 * Start the other cpu and set its state to P_OFFLINE. 3366 */ 3367 status_other = fhc_cpu_start(cp_other); 3368 if (status_other != 0) { 3369 panic("fhc: failed to start second CPU" 3370 " in pair %d & %d, error %d", 3371 cp->cpu_id, cp_other->cpu_id, status_other); 3372 } 3373 } 3374 3375 return (status); 3376 } 3377 3378 /* 3379 * complete the shutdown sequence in case the firmware doesn't. 3380 * 3381 * If the firmware returns, then complete the shutdown code. 3382 * (sunfire firmware presently only updates its status. the 3383 * OS must flush the D-tags and execute the shutdown instruction.) 3384 */ 3385 static void 3386 os_completes_shutdown(void) 3387 { 3388 pfn_t pfn; 3389 tte_t tte; 3390 volatile uint_t *src; 3391 volatile uint_t *dst; 3392 caddr_t copy_addr; 3393 extern void fhc_shutdown_asm(u_longlong_t, int); 3394 extern void fhc_shutdown_asm_end(void); 3395 3396 copy_addr = shutdown_va + FHC_SRAM_OS_OFFSET; 3397 3398 /* compute sram global address for this operation */ 3399 pfn = FHC_LOCAL_OS_PAGEBASE >> MMU_PAGESHIFT; 3400 3401 /* force load i and d translations */ 3402 tte.tte_inthi = TTE_VALID_INT | TTE_SZ_INT(TTE8K) | 3403 TTE_PFN_INTHI(pfn); 3404 tte.tte_intlo = TTE_PFN_INTLO(pfn) | 3405 TTE_HWWR_INT | TTE_PRIV_INT | TTE_LCK_INT; /* un$ */ 3406 sfmmu_dtlb_ld_kva(shutdown_va, &tte); /* load dtlb */ 3407 sfmmu_itlb_ld_kva(shutdown_va, &tte); /* load itlb */ 3408 3409 /* 3410 * copy the special shutdown function to sram 3411 * (this is a special integer copy that synchronizes with localspace 3412 * accesses. we need special throttling to ensure copy integrity) 3413 */ 3414 for (src = (uint_t *)fhc_shutdown_asm, dst = (uint_t *)copy_addr; 3415 src < (uint_t *)fhc_shutdown_asm_end; 3416 src++, dst++) { 3417 volatile uint_t dummy; 3418 3419 *dst = *src; 3420 /* 3421 * ensure non corrupting single write operations to 3422 * localspace sram by interleaving reads with writes. 3423 */ 3424 dummy = *dst; 3425 #ifdef lint 3426 dummy = dummy; 3427 #endif 3428 } 3429 3430 /* 3431 * Call the shutdown sequencer. 3432 * NOTE: the base flush address must be unique for each MID. 3433 */ 3434 ((void (*)(u_longlong_t, int))copy_addr)( 3435 FHC_BASE_NOMEM + CPU->cpu_id * FHC_MAX_ECACHE_SIZE, 3436 cpunodes[CPU->cpu_id].ecache_size); 3437 } 3438 3439 enum temp_state 3440 fhc_env_temp_state(int board) 3441 { 3442 fhc_bd_t *bdp; 3443 struct environ_soft_state *envp; 3444 3445 ASSERT(fhc_bd_valid(board)); 3446 3447 bdp = fhc_bd(board); 3448 3449 /* 3450 * Due to asynchronous attach of environ, environ may 3451 * not be attached by the time we start calling this routine 3452 * to check the temperature state. Environ not attaching is 3453 * pathological so this will only cover the time between 3454 * board connect and environ attach. 3455 */ 3456 if (!bdp->dev_softsp) { 3457 return (TEMP_OK); 3458 } 3459 envp = (struct environ_soft_state *)bdp->dev_softsp; 3460 3461 return (envp->tempstat.state); 3462 } 3463 3464 static void 3465 fhc_tod_fault(enum tod_fault_type tod_bad) 3466 { 3467 int board_num = 0; 3468 enum ft_class class = FT_SYSTEM; 3469 uint64_t addr; 3470 3471 addr = (va_to_pa((void *)v_eeprom_addr)) >> BOARD_PHYADDR_SHIFT; 3472 3473 if ((addr & CLOCKBOARD_PHYADDR_BITS) != CLOCKBOARD_PHYADDR_BITS) { 3474 /* if tod is not on clock board, */ 3475 /* it'd be on one of io boards */ 3476 board_num = (addr >> IO_BOARD_NUMBER_SHIFT) 3477 & IO_BOARD_NUMBER_MASK; 3478 class = FT_BOARD; 3479 } 3480 3481 switch (tod_bad) { 3482 case TOD_NOFAULT: 3483 clear_fault(board_num, FT_TODFAULT, class); 3484 break; 3485 case TOD_REVERSED: 3486 case TOD_STALLED: 3487 case TOD_JUMPED: 3488 case TOD_RATECHANGED: 3489 reg_fault(board_num, FT_TODFAULT, class); 3490 break; 3491 default: 3492 break; 3493 } 3494 } 3495