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