29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * CDDL HEADER START
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * The contents of this file are subject to the terms of the
29949e866e40b95795203f3ee46f44a197c946e4stevel * Common Development and Distribution License (the "License").
29949e866e40b95795203f3ee46f44a197c946e4stevel * You may not use this file except in compliance with the License.
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
29949e866e40b95795203f3ee46f44a197c946e4stevel * or http://www.opensolaris.org/os/licensing.
29949e866e40b95795203f3ee46f44a197c946e4stevel * See the License for the specific language governing permissions
29949e866e40b95795203f3ee46f44a197c946e4stevel * and limitations under the License.
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * When distributing Covered Code, include this CDDL HEADER in each
29949e866e40b95795203f3ee46f44a197c946e4stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
29949e866e40b95795203f3ee46f44a197c946e4stevel * If applicable, add the following below this CDDL HEADER, with the
29949e866e40b95795203f3ee46f44a197c946e4stevel * fields enclosed by brackets "[]" replaced with your own identifying
29949e866e40b95795203f3ee46f44a197c946e4stevel * information: Portions Copyright [yyyy] [name of copyright owner]
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * CDDL HEADER END
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
29949e866e40b95795203f3ee46f44a197c946e4stevel * Use is subject to license terms.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/types.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/conf.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/ddi.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/sunddi.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/ddi_impldefs.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/obpdefs.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/promif.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/cmn_err.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/errno.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/kmem.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/vmem.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/debug.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/sysmacros.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/intreg.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/autoconf.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/modctl.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/spl.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/time.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/systm.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/machsystm.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/cpu.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/cpuvar.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/x_call.h> /* xt_one() */
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/membar.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/vm.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <vm/seg_kmem.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <vm/hat_sfmmu.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/promimpl.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/prom_plat.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/cpu_module.h> /* flush_instr_mem() */
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/procset.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/fhc.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/ac.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/environ.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/jtag.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/nexusdebug.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/ac.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/ddi_subrdefs.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/eeprom.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/sdt.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/ddi_implfuncs.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/ontrap.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifndef TRUE
29949e866e40b95795203f3ee46f44a197c946e4stevel#define TRUE (1)
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifndef FALSE
29949e866e40b95795203f3ee46f44a197c946e4stevel#define FALSE (0)
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Function to register and deregister callbacks, for sunfire only.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelextern void plat_register_tod_fault(void (*func)(enum tod_fault_type));
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * This table represents the FHC interrupt priorities. They range from
29949e866e40b95795203f3ee46f44a197c946e4stevel * 1-15, and have been modeled after the sun4d interrupts. The mondo
29949e866e40b95795203f3ee46f44a197c946e4stevel * number anded with 0x7 is used to index into this table. This was
29949e866e40b95795203f3ee46f44a197c946e4stevel * done to save table space.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int fhc_int_priorities[] = {
29949e866e40b95795203f3ee46f44a197c946e4stevel PIL_15, /* System interrupt priority */
29949e866e40b95795203f3ee46f44a197c946e4stevel PIL_12, /* zs interrupt priority */
29949e866e40b95795203f3ee46f44a197c946e4stevel PIL_15, /* TOD interrupt priority */
29949e866e40b95795203f3ee46f44a197c946e4stevel PIL_15 /* Fan Fail priority */
29949e866e40b95795203f3ee46f44a197c946e4stevel};
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void fhc_tod_fault(enum tod_fault_type tod_bad);
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowestatic void fhc_cpu_shutdown_self(void);
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowestatic void os_completes_shutdown(void);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * The dont_calibrate variable is meant to be set to one in /etc/system
29949e866e40b95795203f3ee46f44a197c946e4stevel * or by boot -h so that the calibration tables are not used. This
29949e866e40b95795203f3ee46f44a197c946e4stevel * is useful for checking thermistors whose output seems to be incorrect.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int dont_calibrate = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/* Only one processor should powerdown the system. */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int powerdown_started = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/* Let user disable overtemp powerdown. */
29949e866e40b95795203f3ee46f44a197c946e4stevelint enable_overtemp_powerdown = 1;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * The following tables correspond to the degress Celcius for each count
29949e866e40b95795203f3ee46f44a197c946e4stevel * value possible from the 8-bit A/C convertors on each type of system
29949e866e40b95795203f3ee46f44a197c946e4stevel * board for the UltraSPARC Server systems. To access a temperature,
29949e866e40b95795203f3ee46f44a197c946e4stevel * just index into the correct table using the count from the A/D convertor
29949e866e40b95795203f3ee46f44a197c946e4stevel * register, and that is the correct temperature in degress Celsius. These
29949e866e40b95795203f3ee46f44a197c946e4stevel * values can be negative.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic short cpu_table[] = {
29949e866e40b95795203f3ee46f44a197c946e4stevel-16, -14, -12, -10, -8, -6, -4, -2, /* 0-7 */
29949e866e40b95795203f3ee46f44a197c946e4stevel1, 4, 6, 8, 10, 12, 13, 15, /* 8-15 */
29949e866e40b95795203f3ee46f44a197c946e4stevel16, 18, 19, 20, 22, 23, 24, 25, /* 16-23 */
29949e866e40b95795203f3ee46f44a197c946e4stevel26, 27, 28, 29, 30, 31, 32, 33, /* 24-31 */
29949e866e40b95795203f3ee46f44a197c946e4stevel34, 35, 35, 36, 37, 38, 39, 39, /* 32-39 */
29949e866e40b95795203f3ee46f44a197c946e4stevel40, 41, 41, 42, 43, 44, 44, 45, /* 40-47 */
29949e866e40b95795203f3ee46f44a197c946e4stevel46, 46, 47, 47, 48, 49, 49, 50, /* 48-55 */
29949e866e40b95795203f3ee46f44a197c946e4stevel51, 51, 52, 53, 53, 54, 54, 55, /* 56-63 */
29949e866e40b95795203f3ee46f44a197c946e4stevel55, 56, 56, 57, 57, 58, 58, 59, /* 64-71 */
29949e866e40b95795203f3ee46f44a197c946e4stevel60, 60, 61, 61, 62, 62, 63, 63, /* 72-79 */
29949e866e40b95795203f3ee46f44a197c946e4stevel64, 64, 65, 65, 66, 66, 67, 67, /* 80-87 */
29949e866e40b95795203f3ee46f44a197c946e4stevel68, 68, 69, 69, 70, 70, 71, 71, /* 88-95 */
29949e866e40b95795203f3ee46f44a197c946e4stevel72, 72, 73, 73, 74, 74, 75, 75, /* 96-103 */
29949e866e40b95795203f3ee46f44a197c946e4stevel76, 76, 77, 77, 78, 78, 79, 79, /* 104-111 */
29949e866e40b95795203f3ee46f44a197c946e4stevel80, 80, 81, 81, 82, 82, 83, 83, /* 112-119 */
29949e866e40b95795203f3ee46f44a197c946e4stevel84, 84, 85, 85, 86, 86, 87, 87, /* 120-127 */
29949e866e40b95795203f3ee46f44a197c946e4stevel88, 88, 89, 89, 90, 90, 91, 91, /* 128-135 */
29949e866e40b95795203f3ee46f44a197c946e4stevel92, 92, 93, 93, 94, 94, 95, 95, /* 136-143 */
29949e866e40b95795203f3ee46f44a197c946e4stevel96, 96, 97, 98, 98, 99, 99, 100, /* 144-151 */
29949e866e40b95795203f3ee46f44a197c946e4stevel100, 101, 101, 102, 103, 103, 104, 104, /* 152-159 */
29949e866e40b95795203f3ee46f44a197c946e4stevel105, 106, 106, 107, 107, 108, 109, 109, /* 160-167 */
29949e866e40b95795203f3ee46f44a197c946e4stevel110, /* 168 */
29949e866e40b95795203f3ee46f44a197c946e4stevel};
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel#define CPU_MX_CNT (sizeof (cpu_table)/sizeof (short))
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic short cpu2_table[] = {
29949e866e40b95795203f3ee46f44a197c946e4stevel-17, -16, -15, -14, -13, -12, -11, -10, /* 0-7 */
29949e866e40b95795203f3ee46f44a197c946e4stevel-9, -8, -7, -6, -5, -4, -3, -2, /* 8-15 */
29949e866e40b95795203f3ee46f44a197c946e4stevel-1, 0, 1, 2, 3, 4, 5, 6, /* 16-23 */
29949e866e40b95795203f3ee46f44a197c946e4stevel7, 8, 9, 10, 11, 12, 13, 13, /* 24-31 */
29949e866e40b95795203f3ee46f44a197c946e4stevel14, 15, 16, 16, 17, 18, 18, 19, /* 32-39 */
29949e866e40b95795203f3ee46f44a197c946e4stevel20, 20, 21, 22, 22, 23, 24, 24, /* 40-47 */
29949e866e40b95795203f3ee46f44a197c946e4stevel25, 25, 26, 26, 27, 27, 28, 28, /* 48-55 */
29949e866e40b95795203f3ee46f44a197c946e4stevel29, 30, 30, 31, 31, 32, 32, 33, /* 56-63 */
29949e866e40b95795203f3ee46f44a197c946e4stevel33, 34, 34, 35, 35, 36, 36, 37, /* 64-71 */
29949e866e40b95795203f3ee46f44a197c946e4stevel37, 37, 38, 38, 39, 39, 40, 40, /* 72-79 */
29949e866e40b95795203f3ee46f44a197c946e4stevel41, 41, 42, 42, 43, 43, 43, 44, /* 80-87 */
29949e866e40b95795203f3ee46f44a197c946e4stevel44, 45, 45, 46, 46, 46, 47, 47, /* 88-95 */
29949e866e40b95795203f3ee46f44a197c946e4stevel48, 48, 49, 49, 50, 50, 50, 51, /* 96-103 */
29949e866e40b95795203f3ee46f44a197c946e4stevel51, 52, 52, 53, 53, 53, 54, 54, /* 104-111 */
29949e866e40b95795203f3ee46f44a197c946e4stevel55, 55, 56, 56, 56, 57, 57, 58, /* 112-119 */
29949e866e40b95795203f3ee46f44a197c946e4stevel58, 59, 59, 59, 60, 60, 61, 61, /* 120-127 */
29949e866e40b95795203f3ee46f44a197c946e4stevel62, 62, 63, 63, 63, 64, 64, 65, /* 128-135 */
29949e866e40b95795203f3ee46f44a197c946e4stevel65, 66, 66, 67, 67, 68, 68, 68, /* 136-143 */
29949e866e40b95795203f3ee46f44a197c946e4stevel69, 69, 70, 70, 71, 71, 72, 72, /* 144-151 */
29949e866e40b95795203f3ee46f44a197c946e4stevel73, 73, 74, 74, 75, 75, 76, 76, /* 152-159 */
29949e866e40b95795203f3ee46f44a197c946e4stevel77, 77, 78, 78, 79, 79, 80, 80, /* 160-167 */
29949e866e40b95795203f3ee46f44a197c946e4stevel81, 81, 82, 83, 83, 84, 84, 85, /* 168-175 */
29949e866e40b95795203f3ee46f44a197c946e4stevel85, 86, 87, 87, 88, 88, 89, 90, /* 176-183 */
29949e866e40b95795203f3ee46f44a197c946e4stevel90, 91, 92, 92, 93, 94, 94, 95, /* 184-191 */
29949e866e40b95795203f3ee46f44a197c946e4stevel96, 96, 97, 98, 99, 99, 100, 101, /* 192-199 */
29949e866e40b95795203f3ee46f44a197c946e4stevel102, 103, 103, 104, 105, 106, 107, 108, /* 200-207 */
29949e866e40b95795203f3ee46f44a197c946e4stevel109, 110, /* 208-209 */
29949e866e40b95795203f3ee46f44a197c946e4stevel};
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel#define CPU2_MX_CNT (sizeof (cpu2_table)/sizeof (short))
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic short io_table[] = {
29949e866e40b95795203f3ee46f44a197c946e4stevel0, 0, 0, 0, 0, 0, 0, 0, /* 0-7 */
29949e866e40b95795203f3ee46f44a197c946e4stevel0, 0, 0, 0, 0, 0, 0, 0, /* 8-15 */
29949e866e40b95795203f3ee46f44a197c946e4stevel0, 0, 0, 0, 0, 0, 0, 0, /* 16-23 */
29949e866e40b95795203f3ee46f44a197c946e4stevel0, 0, 0, 0, 0, 0, 0, 0, /* 24-31 */
29949e866e40b95795203f3ee46f44a197c946e4stevel0, 0, 0, 0, 0, 0, 0, 0, /* 32-39 */
29949e866e40b95795203f3ee46f44a197c946e4stevel0, 3, 7, 10, 13, 15, 17, 19, /* 40-47 */
29949e866e40b95795203f3ee46f44a197c946e4stevel21, 23, 25, 27, 28, 30, 31, 32, /* 48-55 */
29949e866e40b95795203f3ee46f44a197c946e4stevel34, 35, 36, 37, 38, 39, 41, 42, /* 56-63 */
29949e866e40b95795203f3ee46f44a197c946e4stevel43, 44, 45, 46, 46, 47, 48, 49, /* 64-71 */
29949e866e40b95795203f3ee46f44a197c946e4stevel50, 51, 52, 53, 53, 54, 55, 56, /* 72-79 */
29949e866e40b95795203f3ee46f44a197c946e4stevel57, 57, 58, 59, 60, 60, 61, 62, /* 80-87 */
29949e866e40b95795203f3ee46f44a197c946e4stevel62, 63, 64, 64, 65, 66, 66, 67, /* 88-95 */
29949e866e40b95795203f3ee46f44a197c946e4stevel68, 68, 69, 70, 70, 71, 72, 72, /* 96-103 */
29949e866e40b95795203f3ee46f44a197c946e4stevel73, 73, 74, 75, 75, 76, 77, 77, /* 104-111 */
29949e866e40b95795203f3ee46f44a197c946e4stevel78, 78, 79, 80, 80, 81, 81, 82, /* 112-119 */
29949e866e40b95795203f3ee46f44a197c946e4stevel};
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel#define IO_MN_CNT 40
29949e866e40b95795203f3ee46f44a197c946e4stevel#define IO_MX_CNT (sizeof (io_table)/sizeof (short))
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic short clock_table[] = {
29949e866e40b95795203f3ee46f44a197c946e4stevel0, 0, 0, 0, 0, 0, 0, 0, /* 0-7 */
29949e866e40b95795203f3ee46f44a197c946e4stevel0, 0, 0, 0, 1, 2, 4, 5, /* 8-15 */
29949e866e40b95795203f3ee46f44a197c946e4stevel7, 8, 10, 11, 12, 13, 14, 15, /* 16-23 */
29949e866e40b95795203f3ee46f44a197c946e4stevel17, 18, 19, 20, 21, 22, 23, 24, /* 24-31 */
29949e866e40b95795203f3ee46f44a197c946e4stevel24, 25, 26, 27, 28, 29, 29, 30, /* 32-39 */
29949e866e40b95795203f3ee46f44a197c946e4stevel31, 32, 32, 33, 34, 35, 35, 36, /* 40-47 */
29949e866e40b95795203f3ee46f44a197c946e4stevel37, 38, 38, 39, 40, 40, 41, 42, /* 48-55 */
29949e866e40b95795203f3ee46f44a197c946e4stevel42, 43, 44, 44, 45, 46, 46, 47, /* 56-63 */
29949e866e40b95795203f3ee46f44a197c946e4stevel48, 48, 49, 50, 50, 51, 52, 52, /* 64-71 */
29949e866e40b95795203f3ee46f44a197c946e4stevel53, 54, 54, 55, 56, 57, 57, 58, /* 72-79 */
29949e866e40b95795203f3ee46f44a197c946e4stevel59, 59, 60, 60, 61, 62, 63, 63, /* 80-87 */
29949e866e40b95795203f3ee46f44a197c946e4stevel64, 65, 65, 66, 67, 68, 68, 69, /* 88-95 */
29949e866e40b95795203f3ee46f44a197c946e4stevel70, 70, 71, 72, 73, 74, 74, 75, /* 96-103 */
29949e866e40b95795203f3ee46f44a197c946e4stevel76, 77, 78, 78, 79, 80, 81, 82, /* 104-111 */
29949e866e40b95795203f3ee46f44a197c946e4stevel};
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel#define CLK_MN_CNT 11
29949e866e40b95795203f3ee46f44a197c946e4stevel#define CLK_MX_CNT (sizeof (clock_table)/sizeof (short))
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * System temperature limits.
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * The following variables are the warning and danger limits for the
29949e866e40b95795203f3ee46f44a197c946e4stevel * different types of system boards. The limits are different because
29949e866e40b95795203f3ee46f44a197c946e4stevel * the various boards reach different nominal temperatures because
29949e866e40b95795203f3ee46f44a197c946e4stevel * of the different components that they contain.
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * The warning limit is the temperature at which the user is warned.
29949e866e40b95795203f3ee46f44a197c946e4stevel * The danger limit is the temperature at which the system is shutdown.
29949e866e40b95795203f3ee46f44a197c946e4stevel * In the case of CPU/Memory system boards, the system will attempt
29949e866e40b95795203f3ee46f44a197c946e4stevel * to offline and power down processors on a board in an attempt to
29949e866e40b95795203f3ee46f44a197c946e4stevel * bring the board back into the nominal temperature range before
29949e866e40b95795203f3ee46f44a197c946e4stevel * shutting down the system.
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * These values can be tuned via /etc/system or boot -h.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelshort cpu_warn_temp = 73; /* CPU/Memory Warning Temperature */
29949e866e40b95795203f3ee46f44a197c946e4stevelshort cpu_danger_temp = 83; /* CPU/Memory Danger Temperature */
29949e866e40b95795203f3ee46f44a197c946e4stevelshort io_warn_temp = 60; /* IO Board Warning Temperature */
29949e866e40b95795203f3ee46f44a197c946e4stevelshort io_danger_temp = 68; /* IO Board Danger Temperature */
29949e866e40b95795203f3ee46f44a197c946e4stevelshort clk_warn_temp = 60; /* Clock Board Warning Temperature */
29949e866e40b95795203f3ee46f44a197c946e4stevelshort clk_danger_temp = 68; /* Clock Board Danger Temperature */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelshort dft_warn_temp = 60; /* default warning temp value */
29949e866e40b95795203f3ee46f44a197c946e4stevelshort dft_danger_temp = 68; /* default danger temp value */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelshort cpu_warn_temp_4x = 60; /* CPU/Memory warning temp for 400 MHZ */
29949e866e40b95795203f3ee46f44a197c946e4stevelshort cpu_danger_temp_4x = 68; /* CPU/Memory danger temp for 400 MHZ */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * This variable tells us if we are in a heat chamber. It is set
29949e866e40b95795203f3ee46f44a197c946e4stevel * early on in boot, after we check the OBP 'mfg-mode' property in
29949e866e40b95795203f3ee46f44a197c946e4stevel * the options node.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int temperature_chamber = -1;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * The fhc memloc structure is protected under the bdlist lock
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic struct fhc_memloc *fhc_base_memloc = NULL;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Driver global fault list mutex and list head pointer. The list is
29949e866e40b95795203f3ee46f44a197c946e4stevel * protected by the mutex and contains a record of all known faults.
29949e866e40b95795203f3ee46f44a197c946e4stevel * Faults can be inherited from the PROM or detected by the kernel.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic kmutex_t ftlist_mutex;
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic struct ft_link_list *ft_list = NULL;
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int ft_nfaults = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Table of all known fault strings. This table is indexed by the fault
29949e866e40b95795203f3ee46f44a197c946e4stevel * type. Do not change the ordering of the table without redefining the
29949e866e40b95795203f3ee46f44a197c946e4stevel * fault type enum list on fhc.h.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelchar *ft_str_table[] = {
29949e866e40b95795203f3ee46f44a197c946e4stevel "Core Power Supply", /* FT_CORE_PS */
29949e866e40b95795203f3ee46f44a197c946e4stevel "Overtemp", /* FT_OVERTEMP */
29949e866e40b95795203f3ee46f44a197c946e4stevel "AC Power", /* FT_AC_PWR */
29949e866e40b95795203f3ee46f44a197c946e4stevel "Peripheral Power Supply", /* FT_PPS */
29949e866e40b95795203f3ee46f44a197c946e4stevel "System 3.3 Volt Power", /* FT_CLK_33 */
29949e866e40b95795203f3ee46f44a197c946e4stevel "System 5.0 Volt Power", /* FT_CLK_50 */
29949e866e40b95795203f3ee46f44a197c946e4stevel "Peripheral 5.0 Volt Power", /* FT_V5_P */
29949e866e40b95795203f3ee46f44a197c946e4stevel "Peripheral 12 Volt Power", /* FT_V12_P */
29949e866e40b95795203f3ee46f44a197c946e4stevel "Auxiliary 5.0 Volt Power", /* FT_V5_AUX */
29949e866e40b95795203f3ee46f44a197c946e4stevel "Peripheral 5.0 Volt Precharge", /* FT_V5_P_PCH */
29949e866e40b95795203f3ee46f44a197c946e4stevel "Peripheral 12 Volt Precharge", /* FT_V12_P_PCH */
29949e866e40b95795203f3ee46f44a197c946e4stevel "System 3.3 Volt Precharge", /* FT_V3_PCH */
29949e866e40b95795203f3ee46f44a197c946e4stevel "System 5.0 Volt Precharge", /* FT_V5_PCH */
29949e866e40b95795203f3ee46f44a197c946e4stevel "Peripheral Power Supply Fans", /* FT_PPS_FAN */
29949e866e40b95795203f3ee46f44a197c946e4stevel "Rack Exhaust Fan", /* FT_RACK_EXH */
29949e866e40b95795203f3ee46f44a197c946e4stevel "Disk Drive Fan", /* FT_DSK_FAN */
29949e866e40b95795203f3ee46f44a197c946e4stevel "AC Box Fan", /* FT_AC_FAN */
29949e866e40b95795203f3ee46f44a197c946e4stevel "Key Switch Fan", /* FT_KEYSW_FAN */
29949e866e40b95795203f3ee46f44a197c946e4stevel "Minimum Power", /* FT_INSUFFICIENT_POWER */
29949e866e40b95795203f3ee46f44a197c946e4stevel "PROM detected", /* FT_PROM */
29949e866e40b95795203f3ee46f44a197c946e4stevel "Hot Plug Support System", /* FT_HOT_PLUG */
29949e866e40b95795203f3ee46f44a197c946e4stevel "TOD" /* FT_TODFAULT */
29949e866e40b95795203f3ee46f44a197c946e4stevel};
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int ft_max_index = (sizeof (ft_str_table) / sizeof (char *));
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Function prototypes
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int fhc_ctlops(dev_info_t *, dev_info_t *, ddi_ctl_enum_t,
29949e866e40b95795203f3ee46f44a197c946e4stevel void *, void *);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int fhc_intr_ops(dev_info_t *dip, dev_info_t *rdip,
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_intr_op_t intr_op, ddi_intr_handle_impl_t *hdlp, void *result);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int fhc_add_intr_impl(dev_info_t *dip, dev_info_t *rdip,
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_intr_handle_impl_t *hdlp);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void fhc_remove_intr_impl(dev_info_t *dip, dev_info_t *rdip,
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_intr_handle_impl_t *hdlp);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int fhc_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int fhc_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int fhc_init(struct fhc_soft_state *softsp);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void fhc_unmap_regs(struct fhc_soft_state *softsp);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic enum board_type fhc_board_type(struct fhc_soft_state *, int);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_xlate_intrs(ddi_intr_handle_impl_t *hdlp, uint32_t ign);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_ctlops_peekpoke(ddi_ctl_enum_t, peekpoke_ctlops_t *, void *result);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void fhc_add_kstats(struct fhc_soft_state *);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int fhc_kstat_update(kstat_t *, int);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int check_for_chamber(void);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int ft_ks_snapshot(struct kstat *, void *, int);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int ft_ks_update(struct kstat *, int);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int check_central(int board);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * board type and A/D convertor output passed in and real temperature
29949e866e40b95795203f3ee46f44a197c946e4stevel * is returned.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic short calibrate_temp(enum board_type, uchar_t, uint_t);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic enum temp_state get_temp_state(enum board_type, short, int);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/* Routine to determine if there are CPUs on this board. */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int cpu_on_board(int);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void build_bd_display_str(char *, enum board_type, int);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/* Interrupt distribution callback function. */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void fhc_intrdist(void *);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/* CPU power control */
29949e866e40b95795203f3ee46f44a197c946e4stevelint fhc_cpu_poweroff(struct cpu *); /* cpu_poweroff()->platform */
29949e866e40b95795203f3ee46f44a197c946e4stevelint fhc_cpu_poweron(struct cpu *); /* cpu_poweron()->platform */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelextern struct cpu_node cpunodes[];
29949e866e40b95795203f3ee46f44a197c946e4stevelextern void halt(char *);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Configuration data structures
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic struct bus_ops fhc_bus_ops = {
29949e866e40b95795203f3ee46f44a197c946e4stevel BUSO_REV,
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_bus_map, /* map */
29949e866e40b95795203f3ee46f44a197c946e4stevel 0, /* get_intrspec */
29949e866e40b95795203f3ee46f44a197c946e4stevel 0, /* add_intrspec */
29949e866e40b95795203f3ee46f44a197c946e4stevel 0, /* remove_intrspec */
29949e866e40b95795203f3ee46f44a197c946e4stevel i_ddi_map_fault, /* map_fault */
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_no_dma_map, /* dma_map */
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_no_dma_allochdl,
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_no_dma_freehdl,
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_no_dma_bindhdl,
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_no_dma_unbindhdl,
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_no_dma_flush,
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_no_dma_win,
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_dma_mctl, /* dma_ctl */
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_ctlops, /* ctl */
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_bus_prop_op, /* prop_op */
29949e866e40b95795203f3ee46f44a197c946e4stevel 0, /* (*bus_get_eventcookie)(); */
29949e866e40b95795203f3ee46f44a197c946e4stevel 0, /* (*bus_add_eventcall)(); */
29949e866e40b95795203f3ee46f44a197c946e4stevel 0, /* (*bus_remove_eventcall)(); */
29949e866e40b95795203f3ee46f44a197c946e4stevel 0, /* (*bus_post_event)(); */
29949e866e40b95795203f3ee46f44a197c946e4stevel 0, /* (*bus_intr_control)(); */
29949e866e40b95795203f3ee46f44a197c946e4stevel 0, /* (*bus_config)(); */
29949e866e40b95795203f3ee46f44a197c946e4stevel 0, /* (*bus_unconfig)(); */
29949e866e40b95795203f3ee46f44a197c946e4stevel 0, /* (*bus_fm_init)(); */
29949e866e40b95795203f3ee46f44a197c946e4stevel 0, /* (*bus_fm_fini)(); */
29949e866e40b95795203f3ee46f44a197c946e4stevel 0, /* (*bus_fm_access_enter)(); */
29949e866e40b95795203f3ee46f44a197c946e4stevel 0, /* (*bus_fm_access_exit)(); */
29949e866e40b95795203f3ee46f44a197c946e4stevel 0, /* (*bus_power)(); */
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_intr_ops /* (*bus_intr_op)(); */
29949e866e40b95795203f3ee46f44a197c946e4stevel};
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic struct cb_ops fhc_cb_ops = {
29949e866e40b95795203f3ee46f44a197c946e4stevel nulldev, /* open */
29949e866e40b95795203f3ee46f44a197c946e4stevel nulldev, /* close */
29949e866e40b95795203f3ee46f44a197c946e4stevel nulldev, /* strategy */
29949e866e40b95795203f3ee46f44a197c946e4stevel nulldev, /* print */
29949e866e40b95795203f3ee46f44a197c946e4stevel nulldev, /* dump */
29949e866e40b95795203f3ee46f44a197c946e4stevel nulldev, /* read */
29949e866e40b95795203f3ee46f44a197c946e4stevel nulldev, /* write */
29949e866e40b95795203f3ee46f44a197c946e4stevel nulldev, /* ioctl */
29949e866e40b95795203f3ee46f44a197c946e4stevel nodev, /* devmap */
29949e866e40b95795203f3ee46f44a197c946e4stevel nodev, /* mmap */
29949e866e40b95795203f3ee46f44a197c946e4stevel nodev, /* segmap */
29949e866e40b95795203f3ee46f44a197c946e4stevel nochpoll, /* poll */
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_prop_op, /* cb_prop_op */
29949e866e40b95795203f3ee46f44a197c946e4stevel 0, /* streamtab */
29949e866e40b95795203f3ee46f44a197c946e4stevel D_MP|D_NEW|D_HOTPLUG, /* Driver compatibility flag */
29949e866e40b95795203f3ee46f44a197c946e4stevel CB_REV, /* rev */
29949e866e40b95795203f3ee46f44a197c946e4stevel nodev, /* cb_aread */
29949e866e40b95795203f3ee46f44a197c946e4stevel nodev /* cb_awrite */
29949e866e40b95795203f3ee46f44a197c946e4stevel};
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic struct dev_ops fhc_ops = {
29949e866e40b95795203f3ee46f44a197c946e4stevel DEVO_REV, /* rev */
29949e866e40b95795203f3ee46f44a197c946e4stevel 0, /* refcnt */
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_no_info, /* getinfo */
29949e866e40b95795203f3ee46f44a197c946e4stevel nulldev, /* identify */
29949e866e40b95795203f3ee46f44a197c946e4stevel nulldev, /* probe */
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_attach, /* attach */
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_detach, /* detach */
29949e866e40b95795203f3ee46f44a197c946e4stevel nulldev, /* reset */
29949e866e40b95795203f3ee46f44a197c946e4stevel &fhc_cb_ops, /* cb_ops */
29949e866e40b95795203f3ee46f44a197c946e4stevel &fhc_bus_ops, /* bus_ops */
193974072f41a843678abf5f61979c748687e66bSherry Moore nulldev, /* power */
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_quiesce_not_needed, /* quiesce */
29949e866e40b95795203f3ee46f44a197c946e4stevel};
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Driver globals
29949e866e40b95795203f3ee46f44a197c946e4stevel * TODO - We need to investigate what locking needs to be done here.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelvoid *fhcp; /* fhc soft state hook */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelextern struct mod_ops mod_driverops;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic struct modldrv modldrv = {
29949e866e40b95795203f3ee46f44a197c946e4stevel &mod_driverops, /* Type of module. This one is a driver */
193974072f41a843678abf5f61979c748687e66bSherry Moore "FHC Nexus", /* Name of module. */
29949e866e40b95795203f3ee46f44a197c946e4stevel &fhc_ops, /* driver ops */
29949e866e40b95795203f3ee46f44a197c946e4stevel};
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic struct modlinkage modlinkage = {
29949e866e40b95795203f3ee46f44a197c946e4stevel MODREV_1, /* rev */
29949e866e40b95795203f3ee46f44a197c946e4stevel (void *)&modldrv,
29949e866e40b95795203f3ee46f44a197c946e4stevel NULL
29949e866e40b95795203f3ee46f44a197c946e4stevel};
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * These are the module initialization routines.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic caddr_t shutdown_va;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelint
29949e866e40b95795203f3ee46f44a197c946e4stevel_init(void)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel int error;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((error = ddi_soft_state_init(&fhcp,
29949e866e40b95795203f3ee46f44a197c946e4stevel sizeof (struct fhc_soft_state), 1)) != 0)
29949e866e40b95795203f3ee46f44a197c946e4stevel return (error);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bdlist_init();
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_init(&ftlist_mutex, NULL, MUTEX_DEFAULT, NULL);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel shutdown_va = vmem_alloc(heap_arena, PAGESIZE, VM_SLEEP);
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(shutdown_va != NULL);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel plat_register_tod_fault(fhc_tod_fault);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel return (mod_install(&modlinkage));
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelint
29949e866e40b95795203f3ee46f44a197c946e4stevel_fini(void)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel int error;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((error = mod_remove(&modlinkage)) != 0)
29949e866e40b95795203f3ee46f44a197c946e4stevel return (error);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel plat_register_tod_fault(NULL);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_destroy(&ftlist_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bdlist_fini();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_soft_state_fini(&fhcp);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel return (0);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelint
29949e866e40b95795203f3ee46f44a197c946e4stevel_info(struct modinfo *modinfop)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel return (mod_info(&modlinkage, modinfop));
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Reset the interrupt mapping registers.
29949e866e40b95795203f3ee46f44a197c946e4stevel * This function resets the values during DDI_RESUME.
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * NOTE: This function will not work for a full CPR cycle
29949e866e40b95795203f3ee46f44a197c946e4stevel * and is currently designed to handle the RESUME after a connect.
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * Note about the PROM handling of moving CENTRAL to another board:
29949e866e40b95795203f3ee46f44a197c946e4stevel * The PROM moves the IGN identity (igr register) from the
29949e866e40b95795203f3ee46f44a197c946e4stevel * original CENTRAL to the new one. This means that we do not
29949e866e40b95795203f3ee46f44a197c946e4stevel * duplicate the fhc_attach code that sets it to (board number * 2).
29949e866e40b95795203f3ee46f44a197c946e4stevel * We rely on only using FHC interrupts from one board only
29949e866e40b95795203f3ee46f44a197c946e4stevel * (the UART and SYS interrupts) so that the values of the other IGNs
29949e866e40b95795203f3ee46f44a197c946e4stevel * are irrelevant. The benefit of this approach is that we don't
29949e866e40b95795203f3ee46f44a197c946e4stevel * have to have to tear down and rebuild the interrupt records
29949e866e40b95795203f3ee46f44a197c946e4stevel * for UART and SYS. It is also why we don't try to change the
29949e866e40b95795203f3ee46f44a197c946e4stevel * board number in the fhc instance for the clock board.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_handle_imr(struct fhc_soft_state *softsp)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel int i;
29949e866e40b95795203f3ee46f44a197c946e4stevel int cent;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t tmp_reg;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (softsp->is_central) {
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t want_igr, act_igr;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel want_igr = softsp->list->sc.board << 1;
29949e866e40b95795203f3ee46f44a197c946e4stevel act_igr = *softsp->igr & 0x1f;
29949e866e40b95795203f3ee46f44a197c946e4stevel if (want_igr != act_igr) {
29949e866e40b95795203f3ee46f44a197c946e4stevel *softsp->igr = want_igr;
29949e866e40b95795203f3ee46f44a197c946e4stevel tmp_reg = *softsp->igr;
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef lint
29949e866e40b95795203f3ee46f44a197c946e4stevel tmp_reg = tmp_reg;
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif
29949e866e40b95795203f3ee46f44a197c946e4stevel /* We must now re-issue any pending interrupts. */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < FHC_MAX_INO; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if (*(softsp->intr_regs[i].clear_reg) == 3) {
29949e866e40b95795203f3ee46f44a197c946e4stevel *(softsp->intr_regs[i].clear_reg) =
29949e866e40b95795203f3ee46f44a197c946e4stevel ISM_IDLE;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel tmp_reg =
29949e866e40b95795203f3ee46f44a197c946e4stevel *(softsp->intr_regs[i].clear_reg);
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef lint
29949e866e40b95795203f3ee46f44a197c946e4stevel tmp_reg = tmp_reg;
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_NOTE, "central IGN corruption fixed: "
193974072f41a843678abf5f61979c748687e66bSherry Moore "got %x wanted %x", act_igr, want_igr);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel return;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(softsp->list->sc.board == FHC_BSR_TO_BD(*(softsp->bsr)));
29949e866e40b95795203f3ee46f44a197c946e4stevel cent = check_central(softsp->list->sc.board);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Loop through all 4 FHC interrupt mapping registers */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < FHC_MAX_INO; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (i == FHC_SYS_INO &&
29949e866e40b95795203f3ee46f44a197c946e4stevel *(softsp->intr_regs[i].clear_reg) == 3) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_NOTE,
29949e866e40b95795203f3ee46f44a197c946e4stevel "found lost system interrupt, resetting..");
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel *(softsp->intr_regs[i].clear_reg) = ISM_IDLE;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * ensure atomic write with this read.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel tmp_reg = *(softsp->intr_regs[i].clear_reg);
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef lint
29949e866e40b95795203f3ee46f44a197c946e4stevel tmp_reg = tmp_reg;
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * The mapping registers on the board with the "central" bit
29949e866e40b95795203f3ee46f44a197c946e4stevel * set should not be touched as it has been taken care by POST.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (cent)
29949e866e40b95795203f3ee46f44a197c946e4stevel continue;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel *(softsp->intr_regs[i].mapping_reg) = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * ensure atomic write with this read.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel tmp_reg = *(softsp->intr_regs[i].mapping_reg);
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef lint
29949e866e40b95795203f3ee46f44a197c946e4stevel tmp_reg = tmp_reg;
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int
29949e866e40b95795203f3ee46f44a197c946e4stevelcheck_central(int board)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t cs_value;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * This is the value of AC configuration and status reg
29949e866e40b95795203f3ee46f44a197c946e4stevel * in the Local Devices space. We access it as a physical
29949e866e40b95795203f3ee46f44a197c946e4stevel * address.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel cs_value = ldphysio(AC_BCSR(board));
29949e866e40b95795203f3ee46f44a197c946e4stevel if (cs_value & AC_CENTRAL)
29949e866e40b95795203f3ee46f44a197c946e4stevel return (TRUE);
29949e866e40b95795203f3ee46f44a197c946e4stevel else
29949e866e40b95795203f3ee46f44a197c946e4stevel return (FALSE);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct fhc_soft_state *softsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel int instance;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel instance = ddi_get_instance(devi);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel switch (cmd) {
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_ATTACH:
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_RESUME:
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp = ddi_get_soft_state(fhcp, instance);
29949e866e40b95795203f3ee46f44a197c946e4stevel /* IGR, NOT_BRD_PRES handled by prom */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* reset interrupt mapping registers */
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_handle_imr(softsp);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_SUCCESS);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel default:
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_FAILURE);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ddi_soft_state_zalloc(fhcp, instance) != DDI_SUCCESS)
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_FAILURE);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp = ddi_get_soft_state(fhcp, instance);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Set the dip in the soft state */
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->dip = devi;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (fhc_init(softsp) != DDI_SUCCESS)
29949e866e40b95795203f3ee46f44a197c946e4stevel goto bad;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_report_dev(devi);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_SUCCESS);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelbad:
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_soft_state_free(fhcp, instance);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_FAILURE);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel int board;
29949e866e40b95795203f3ee46f44a197c946e4stevel int instance;
29949e866e40b95795203f3ee46f44a197c946e4stevel struct fhc_soft_state *softsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bd_t *list = NULL;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* get the instance of this devi */
29949e866e40b95795203f3ee46f44a197c946e4stevel instance = ddi_get_instance(devi);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* get the soft state pointer for this device node */
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp = ddi_get_soft_state(fhcp, instance);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel board = softsp->list->sc.board;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel switch (cmd) {
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_SUSPEND:
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_SUCCESS);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_DETACH:
29949e866e40b95795203f3ee46f44a197c946e4stevel /* grab the lock on the board list */
29949e866e40b95795203f3ee46f44a197c946e4stevel list = fhc_bdlist_lock(board);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (fhc_bd_detachable(board) &&
29949e866e40b95795203f3ee46f44a197c946e4stevel !fhc_bd_is_jtag_master(board))
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel else
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bdlist_unlock();
29949e866e40b95795203f3ee46f44a197c946e4stevel /* FALLTHROUGH */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel default:
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_FAILURE);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Remove the interrupt redistribution callback. */
29949e866e40b95795203f3ee46f44a197c946e4stevel intr_dist_rem(fhc_intrdist, (void *)devi);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* remove the soft state pointer from the board list */
29949e866e40b95795203f3ee46f44a197c946e4stevel list->softsp = NULL;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* clear inherited faults from the PROM. */
29949e866e40b95795203f3ee46f44a197c946e4stevel clear_fault(list->sc.board, FT_PROM, FT_BOARD);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* remove the kstat for this board */
29949e866e40b95795203f3ee46f44a197c946e4stevel kstat_delete(softsp->fhc_ksp);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* destroy the mutexes in this soft state structure */
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_destroy(&softsp->poll_list_lock);
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_destroy(&softsp->ctrl_lock);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* unmap all the register sets */
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_unmap_regs(softsp);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* release the board list lock now */
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bdlist_unlock();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* free the soft state structure */
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_soft_state_free(fhcp, instance);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_SUCCESS);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic enum board_type
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_board_type(struct fhc_soft_state *softsp, int board)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel int proplen;
29949e866e40b95795203f3ee46f44a197c946e4stevel char *board_type;
29949e866e40b95795203f3ee46f44a197c946e4stevel enum board_type type;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (softsp->is_central)
29949e866e40b95795203f3ee46f44a197c946e4stevel type = CLOCK_BOARD;
29949e866e40b95795203f3ee46f44a197c946e4stevel else if (ddi_getlongprop(DDI_DEV_T_ANY, softsp->dip,
29949e866e40b95795203f3ee46f44a197c946e4stevel DDI_PROP_DONTPASS, "board-type", (caddr_t)&board_type,
29949e866e40b95795203f3ee46f44a197c946e4stevel &proplen) == DDI_PROP_SUCCESS) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* match the board-type string */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (strcmp(CPU_BD_NAME, board_type) == 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel type = CPU_BOARD;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else if (strcmp(MEM_BD_NAME, board_type) == 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel type = MEM_BOARD;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else if (strcmp(IO_2SBUS_BD_NAME, board_type) == 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel type = IO_2SBUS_BOARD;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else if (strcmp(IO_SBUS_FFB_BD_NAME, board_type) == 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel type = IO_SBUS_FFB_BOARD;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else if (strcmp(IO_2SBUS_SOCPLUS_BD_NAME, board_type) == 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel type = IO_2SBUS_SOCPLUS_BOARD;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else if (strcmp(IO_SBUS_FFB_SOCPLUS_BD_NAME, board_type)
29949e866e40b95795203f3ee46f44a197c946e4stevel == 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel type = IO_SBUS_FFB_SOCPLUS_BOARD;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else if (strcmp(IO_PCI_BD_NAME, board_type) == 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel type = IO_PCI_BOARD;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel type = UNKNOWN_BOARD;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel kmem_free(board_type, proplen);
29949e866e40b95795203f3ee46f44a197c946e4stevel } else
29949e866e40b95795203f3ee46f44a197c946e4stevel type = UNKNOWN_BOARD;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * if the board type is indeterminate, it must be determined.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (type == UNKNOWN_BOARD) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Use the UPA64 bits from the FHC.
29949e866e40b95795203f3ee46f44a197c946e4stevel * This is not the best solution since we
29949e866e40b95795203f3ee46f44a197c946e4stevel * cannot fully type the IO boards.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (cpu_on_board(board))
29949e866e40b95795203f3ee46f44a197c946e4stevel type = CPU_BOARD;
29949e866e40b95795203f3ee46f44a197c946e4stevel else if ((*(softsp->bsr) & FHC_UPADATA64A) ||
193974072f41a843678abf5f61979c748687e66bSherry Moore (*(softsp->bsr) & FHC_UPADATA64B))
29949e866e40b95795203f3ee46f44a197c946e4stevel type = IO_2SBUS_BOARD;
29949e866e40b95795203f3ee46f44a197c946e4stevel else
29949e866e40b95795203f3ee46f44a197c946e4stevel type = MEM_BOARD;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel return (type);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_unmap_regs(struct fhc_soft_state *softsp)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel dev_info_t *dip = softsp->dip;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (softsp->id) {
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_unmap_regs(dip, 0, (caddr_t *)&softsp->id, 0, 0);
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->id = NULL;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel if (softsp->igr) {
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_unmap_regs(dip, 1, (caddr_t *)&softsp->igr, 0, 0);
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->igr = NULL;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel if (softsp->intr_regs[FHC_FANFAIL_INO].mapping_reg) {
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_unmap_regs(dip, 2,
193974072f41a843678abf5f61979c748687e66bSherry Moore (caddr_t *)&softsp->intr_regs[FHC_FANFAIL_INO].mapping_reg,
193974072f41a843678abf5f61979c748687e66bSherry Moore 0, 0);
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->intr_regs[FHC_FANFAIL_INO].mapping_reg = NULL;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel if (softsp->intr_regs[FHC_SYS_INO].mapping_reg) {
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_unmap_regs(dip, 3,
193974072f41a843678abf5f61979c748687e66bSherry Moore (caddr_t *)&softsp->intr_regs[FHC_SYS_INO].mapping_reg,
193974072f41a843678abf5f61979c748687e66bSherry Moore 0, 0);
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->intr_regs[FHC_SYS_INO].mapping_reg = NULL;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel if (softsp->intr_regs[FHC_UART_INO].mapping_reg) {
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_unmap_regs(dip, 4,
193974072f41a843678abf5f61979c748687e66bSherry Moore (caddr_t *)&softsp->intr_regs[FHC_UART_INO].mapping_reg,
193974072f41a843678abf5f61979c748687e66bSherry Moore 0, 0);
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->intr_regs[FHC_UART_INO].mapping_reg = NULL;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel if (softsp->intr_regs[FHC_TOD_INO].mapping_reg) {
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_unmap_regs(dip, 5,
193974072f41a843678abf5f61979c748687e66bSherry Moore (caddr_t *)&softsp->intr_regs[FHC_TOD_INO].mapping_reg,
193974072f41a843678abf5f61979c748687e66bSherry Moore 0, 0);
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->intr_regs[FHC_TOD_INO].mapping_reg = NULL;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_init(struct fhc_soft_state *softsp)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel int i;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t tmp_reg;
29949e866e40b95795203f3ee46f44a197c946e4stevel int board;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Map in the FHC registers. Specifying length and offset of
29949e866e40b95795203f3ee46f44a197c946e4stevel * zero maps in the entire OBP register set.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* map in register set 0 */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ddi_map_regs(softsp->dip, 0,
29949e866e40b95795203f3ee46f44a197c946e4stevel (caddr_t *)&softsp->id, 0, 0)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "fhc%d: unable to map internal "
193974072f41a843678abf5f61979c748687e66bSherry Moore "registers", ddi_get_instance(softsp->dip));
29949e866e40b95795203f3ee46f44a197c946e4stevel goto bad;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Fill in the virtual addresses of the registers in the
29949e866e40b95795203f3ee46f44a197c946e4stevel * fhc_soft_state structure.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->rctrl = (uint_t *)((char *)(softsp->id) +
193974072f41a843678abf5f61979c748687e66bSherry Moore FHC_OFF_RCTRL);
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->ctrl = (uint_t *)((char *)(softsp->id) +
193974072f41a843678abf5f61979c748687e66bSherry Moore FHC_OFF_CTRL);
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bsr = (uint_t *)((char *)(softsp->id) +
193974072f41a843678abf5f61979c748687e66bSherry Moore FHC_OFF_BSR);
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->jtag_ctrl = (uint_t *)((char *)(softsp->id) +
193974072f41a843678abf5f61979c748687e66bSherry Moore FHC_OFF_JTAG_CTRL);
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->jt_master.jtag_cmd = (uint_t *)((char *)(softsp->id) +
193974072f41a843678abf5f61979c748687e66bSherry Moore FHC_OFF_JTAG_CMD);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* map in register set 1 */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ddi_map_regs(softsp->dip, 1,
29949e866e40b95795203f3ee46f44a197c946e4stevel (caddr_t *)&softsp->igr, 0, 0)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "fhc%d: unable to map IGR "
193974072f41a843678abf5f61979c748687e66bSherry Moore "register", ddi_get_instance(softsp->dip));
29949e866e40b95795203f3ee46f44a197c946e4stevel goto bad;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * map in register set 2
29949e866e40b95795203f3ee46f44a197c946e4stevel * XXX this can never be used as an interrupt generator
29949e866e40b95795203f3ee46f44a197c946e4stevel * (hardware queue overflow in fhc)
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ddi_map_regs(softsp->dip, 2,
29949e866e40b95795203f3ee46f44a197c946e4stevel (caddr_t *)&softsp->intr_regs[FHC_FANFAIL_INO].mapping_reg,
29949e866e40b95795203f3ee46f44a197c946e4stevel 0, 0)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "fhc%d: unable to map Fan Fail "
193974072f41a843678abf5f61979c748687e66bSherry Moore "IMR register", ddi_get_instance(softsp->dip));
29949e866e40b95795203f3ee46f44a197c946e4stevel goto bad;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* map in register set 3 */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ddi_map_regs(softsp->dip, 3,
29949e866e40b95795203f3ee46f44a197c946e4stevel (caddr_t *)&softsp->intr_regs[FHC_SYS_INO].mapping_reg,
29949e866e40b95795203f3ee46f44a197c946e4stevel 0, 0)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "fhc%d: unable to map System "
193974072f41a843678abf5f61979c748687e66bSherry Moore "IMR register\n", ddi_get_instance(softsp->dip));
29949e866e40b95795203f3ee46f44a197c946e4stevel goto bad;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* map in register set 4 */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ddi_map_regs(softsp->dip, 4,
29949e866e40b95795203f3ee46f44a197c946e4stevel (caddr_t *)&softsp->intr_regs[FHC_UART_INO].mapping_reg,
29949e866e40b95795203f3ee46f44a197c946e4stevel 0, 0)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "fhc%d: unable to map UART "
193974072f41a843678abf5f61979c748687e66bSherry Moore "IMR register\n", ddi_get_instance(softsp->dip));
29949e866e40b95795203f3ee46f44a197c946e4stevel goto bad;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* map in register set 5 */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ddi_map_regs(softsp->dip, 5,
29949e866e40b95795203f3ee46f44a197c946e4stevel (caddr_t *)&softsp->intr_regs[FHC_TOD_INO].mapping_reg,
29949e866e40b95795203f3ee46f44a197c946e4stevel 0, 0)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "fhc%d: unable to map FHC TOD "
193974072f41a843678abf5f61979c748687e66bSherry Moore "IMR register", ddi_get_instance(softsp->dip));
29949e866e40b95795203f3ee46f44a197c946e4stevel goto bad;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Loop over all intr sets and setup the VAs for the ISMR */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* TODO - Make sure we are calculating the ISMR correctly. */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < FHC_MAX_INO; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->intr_regs[i].clear_reg =
193974072f41a843678abf5f61979c748687e66bSherry Moore (uint_t *)((char *)(softsp->intr_regs[i].mapping_reg) +
193974072f41a843678abf5f61979c748687e66bSherry Moore FHC_OFF_ISMR);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Now clear the state machines to idle */
29949e866e40b95795203f3ee46f44a197c946e4stevel *(softsp->intr_regs[i].clear_reg) = ISM_IDLE;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * It is OK to not have a OBP_BOARDNUM property. This happens for
29949e866e40b95795203f3ee46f44a197c946e4stevel * the board which is a child of central. However this FHC
29949e866e40b95795203f3ee46f44a197c946e4stevel * still needs a proper Interrupt Group Number programmed
29949e866e40b95795203f3ee46f44a197c946e4stevel * into the Interrupt Group register, because the other
29949e866e40b95795203f3ee46f44a197c946e4stevel * instance of FHC, which is not under central, will properly
29949e866e40b95795203f3ee46f44a197c946e4stevel * program the IGR. The numbers from the two settings of the
29949e866e40b95795203f3ee46f44a197c946e4stevel * IGR need to be the same. One driver cannot wait for the
29949e866e40b95795203f3ee46f44a197c946e4stevel * other to program the IGR, because there is no guarantee
29949e866e40b95795203f3ee46f44a197c946e4stevel * which instance of FHC will get attached first.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((board = (int)ddi_getprop(DDI_DEV_T_ANY, softsp->dip,
29949e866e40b95795203f3ee46f44a197c946e4stevel DDI_PROP_DONTPASS, OBP_BOARDNUM, -1)) == -1) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Now determine the board number by reading the
29949e866e40b95795203f3ee46f44a197c946e4stevel * hardware register.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel board = FHC_BSR_TO_BD(*(softsp->bsr));
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->is_central = 1;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * If this fhc holds JTAG master line, and is not the central fhc,
29949e866e40b95795203f3ee46f44a197c946e4stevel * (this avoids two JTAG master nodes) then initialize the
29949e866e40b95795203f3ee46f44a197c946e4stevel * mutex and set the flag in the structure.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((*(softsp->jtag_ctrl) & JTAG_MASTER_EN) && !softsp->is_central) {
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_init(&(softsp->jt_master.lock), NULL, MUTEX_DEFAULT,
29949e866e40b95795203f3ee46f44a197c946e4stevel NULL);
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->jt_master.is_master = 1;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->jt_master.is_master = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bd_init(softsp, board, fhc_board_type(softsp, board));
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Initialize the mutex guarding the poll_list. */
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_init(&softsp->poll_list_lock, NULL, MUTEX_DRIVER, NULL);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Initialize the mutex guarding the FHC CSR */
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_init(&softsp->ctrl_lock, NULL, MUTEX_DRIVER, NULL);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Initialize the poll_list to be empty */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < MAX_ZS_CNT; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->poll_list[i].funcp = NULL;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Modify the various registers in the FHC now */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * We know this board to be present now, record that state and
29949e866e40b95795203f3ee46f44a197c946e4stevel * remove the NOT_BRD_PRES condition
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (!(softsp->is_central)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_enter(&softsp->ctrl_lock);
29949e866e40b95795203f3ee46f44a197c946e4stevel *(softsp->ctrl) |= FHC_NOT_BRD_PRES;
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Now flush the hardware store buffers. */
29949e866e40b95795203f3ee46f44a197c946e4stevel tmp_reg = *(softsp->ctrl);
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef lint
29949e866e40b95795203f3ee46f44a197c946e4stevel tmp_reg = tmp_reg;
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif
29949e866e40b95795203f3ee46f44a197c946e4stevel /* XXX record the board state in global space */
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&softsp->ctrl_lock);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Add kstats for all non-central instances of the FHC. */
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_add_kstats(softsp);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Read the device tree to see if this system is in an environmental
29949e866e40b95795203f3ee46f44a197c946e4stevel * chamber.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (temperature_chamber == -1) {
29949e866e40b95795203f3ee46f44a197c946e4stevel temperature_chamber = check_for_chamber();
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Check for inherited faults from the PROM. */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (*softsp->ctrl & FHC_LED_MID) {
29949e866e40b95795203f3ee46f44a197c946e4stevel reg_fault(softsp->list->sc.board, FT_PROM, FT_BOARD);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * setup the IGR. Shift the board number over by one to get
29949e866e40b95795203f3ee46f44a197c946e4stevel * the UPA MID.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel *(softsp->igr) = (softsp->list->sc.board) << 1;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Now flush the hardware store buffers. */
29949e866e40b95795203f3ee46f44a197c946e4stevel tmp_reg = *(softsp->id);
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef lint
29949e866e40b95795203f3ee46f44a197c946e4stevel tmp_reg = tmp_reg;
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Add the interrupt redistribution callback. */
29949e866e40b95795203f3ee46f44a197c946e4stevel intr_dist_add(fhc_intrdist, (void *)softsp->dip);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_SUCCESS);
29949e866e40b95795203f3ee46f44a197c946e4stevelbad:
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_unmap_regs(softsp);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_FAILURE);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic uint_t
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_intr_wrapper(caddr_t arg)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t intr_return;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t tmpreg;
29949e866e40b95795203f3ee46f44a197c946e4stevel struct fhc_wrapper_arg *intr_info = (struct fhc_wrapper_arg *)arg;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t (*funcp)(caddr_t, caddr_t) = intr_info->funcp;
29949e866e40b95795203f3ee46f44a197c946e4stevel caddr_t iarg1 = intr_info->arg1;
29949e866e40b95795203f3ee46f44a197c946e4stevel caddr_t iarg2 = intr_info->arg2;
29949e866e40b95795203f3ee46f44a197c946e4stevel dev_info_t *dip = intr_info->child;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel tmpreg = ISM_IDLE;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel DTRACE_PROBE4(interrupt__start, dev_info_t, dip,
29949e866e40b95795203f3ee46f44a197c946e4stevel void *, funcp, caddr_t, iarg1, caddr_t, iarg2);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel intr_return = (*funcp)(iarg1, iarg2);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel DTRACE_PROBE4(interrupt__complete, dev_info_t, dip,
29949e866e40b95795203f3ee46f44a197c946e4stevel void *, funcp, caddr_t, iarg1, int, intr_return);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Idle the state machine. */
29949e866e40b95795203f3ee46f44a197c946e4stevel *(intr_info->clear_reg) = tmpreg;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Flush the hardware store buffers. */
29949e866e40b95795203f3ee46f44a197c946e4stevel tmpreg = *(intr_info->clear_reg);
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef lint
29949e866e40b95795203f3ee46f44a197c946e4stevel tmpreg = tmpreg;
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif /* lint */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel return (intr_return);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * fhc_zs_intr_wrapper
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * This function handles intrerrupts where more than one device may interupt
29949e866e40b95795203f3ee46f44a197c946e4stevel * the fhc with the same mondo.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel#define MAX_INTR_CNT 10
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic uint_t
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_zs_intr_wrapper(caddr_t arg)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct fhc_soft_state *softsp = (struct fhc_soft_state *)arg;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t (*funcp0)(caddr_t, caddr_t);
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t (*funcp1)(caddr_t, caddr_t);
29949e866e40b95795203f3ee46f44a197c946e4stevel caddr_t funcp0_arg1, funcp0_arg2, funcp1_arg1, funcp1_arg2;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t tmp_reg;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t result = DDI_INTR_UNCLAIMED;
29949e866e40b95795203f3ee46f44a197c946e4stevel volatile uint_t *clear_reg;
29949e866e40b95795203f3ee46f44a197c946e4stevel uchar_t *spurious_cntr = &softsp->spurious_zs_cntr;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel funcp0 = softsp->poll_list[0].funcp;
29949e866e40b95795203f3ee46f44a197c946e4stevel funcp1 = softsp->poll_list[1].funcp;
29949e866e40b95795203f3ee46f44a197c946e4stevel funcp0_arg1 = softsp->poll_list[0].arg1;
29949e866e40b95795203f3ee46f44a197c946e4stevel funcp0_arg2 = softsp->poll_list[0].arg2;
29949e866e40b95795203f3ee46f44a197c946e4stevel funcp1_arg1 = softsp->poll_list[1].arg1;
29949e866e40b95795203f3ee46f44a197c946e4stevel funcp1_arg2 = softsp->poll_list[1].arg2;
29949e866e40b95795203f3ee46f44a197c946e4stevel clear_reg = softsp->intr_regs[FHC_UART_INO].clear_reg;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (funcp0 != NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((funcp0)(funcp0_arg1, funcp0_arg2) == DDI_INTR_CLAIMED) {
29949e866e40b95795203f3ee46f44a197c946e4stevel result = DDI_INTR_CLAIMED;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (funcp1 != NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((funcp1)(funcp1_arg1, funcp1_arg2) == DDI_INTR_CLAIMED) {
29949e866e40b95795203f3ee46f44a197c946e4stevel result = DDI_INTR_CLAIMED;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (result == DDI_INTR_UNCLAIMED) {
29949e866e40b95795203f3ee46f44a197c946e4stevel (*spurious_cntr)++;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (*spurious_cntr < MAX_INTR_CNT) {
29949e866e40b95795203f3ee46f44a197c946e4stevel result = DDI_INTR_CLAIMED;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel *spurious_cntr = (uchar_t)0;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel *spurious_cntr = (uchar_t)0;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Idle the state machine. */
29949e866e40b95795203f3ee46f44a197c946e4stevel *(clear_reg) = ISM_IDLE;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* flush the store buffers. */
29949e866e40b95795203f3ee46f44a197c946e4stevel tmp_reg = *(clear_reg);
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef lint
29949e866e40b95795203f3ee46f44a197c946e4stevel tmp_reg = tmp_reg;
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel return (result);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * add_intrspec - Add an interrupt specification.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_add_intr_impl(dev_info_t *dip, dev_info_t *rdip,
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_intr_handle_impl_t *hdlp)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel int ino;
29949e866e40b95795203f3ee46f44a197c946e4stevel struct fhc_wrapper_arg *fhc_arg;
29949e866e40b95795203f3ee46f44a197c946e4stevel struct fhc_soft_state *softsp = (struct fhc_soft_state *)
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_get_soft_state(fhcp, ddi_get_instance(dip));
29949e866e40b95795203f3ee46f44a197c946e4stevel volatile uint_t *mondo_vec_reg;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t tmp_mondo_vec;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t tmpreg; /* HW flush reg */
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t cpu_id;
29949e866e40b95795203f3ee46f44a197c946e4stevel int ret = DDI_SUCCESS;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Xlate the interrupt */
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_xlate_intrs(hdlp,
29949e866e40b95795203f3ee46f44a197c946e4stevel (softsp->list->sc.board << BD_IVINTR_SHFT));
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* get the mondo number */
29949e866e40b95795203f3ee46f44a197c946e4stevel ino = FHC_INO(hdlp->ih_vector);
29949e866e40b95795203f3ee46f44a197c946e4stevel mondo_vec_reg = softsp->intr_regs[ino].mapping_reg;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(ino < FHC_MAX_INO);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* We don't use the two spare interrupts. */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ino >= FHC_MAX_INO) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "fhc%d: Spare interrupt %d not usable",
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_get_instance(dip), ino);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_FAILURE);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* TOD and Fan Fail interrupts are not usable */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ino == FHC_TOD_INO) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "fhc%d: TOD interrupt not usable",
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_get_instance(dip));
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_FAILURE);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ino == FHC_FANFAIL_INO) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "fhc%d: Fan fail interrupt not usable",
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_get_instance(dip));
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_FAILURE);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * If the interrupt is for the zs chips, use the vector
29949e866e40b95795203f3ee46f44a197c946e4stevel * polling lists. Otherwise use a straight handler.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ino == FHC_UART_INO) {
29949e866e40b95795203f3ee46f44a197c946e4stevel int32_t zs_inst;
29949e866e40b95795203f3ee46f44a197c946e4stevel /* First lock the mutex for this poll_list */
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_enter(&softsp->poll_list_lock);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Add this interrupt to the polling list.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* figure out where to add this item in the list */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (zs_inst = 0; zs_inst < MAX_ZS_CNT; zs_inst++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if (softsp->poll_list[zs_inst].funcp == NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->poll_list[zs_inst].arg1 =
29949e866e40b95795203f3ee46f44a197c946e4stevel hdlp->ih_cb_arg1;
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->poll_list[zs_inst].arg2 =
29949e866e40b95795203f3ee46f44a197c946e4stevel hdlp->ih_cb_arg2;
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->poll_list[zs_inst].funcp =
29949e866e40b95795203f3ee46f44a197c946e4stevel (ddi_intr_handler_t *)
29949e866e40b95795203f3ee46f44a197c946e4stevel hdlp->ih_cb_func;
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->poll_list[zs_inst].inum =
29949e866e40b95795203f3ee46f44a197c946e4stevel hdlp->ih_inum;
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->poll_list[zs_inst].child = rdip;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (zs_inst >= MAX_ZS_CNT) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN,
29949e866e40b95795203f3ee46f44a197c946e4stevel "fhc%d: poll list overflow",
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_get_instance(dip));
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&softsp->poll_list_lock);
29949e866e40b95795203f3ee46f44a197c946e4stevel ret = DDI_FAILURE;
29949e866e40b95795203f3ee46f44a197c946e4stevel goto done;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * If polling list is empty, then install handler
29949e866e40b95795203f3ee46f44a197c946e4stevel * and enable interrupts for this ino.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (zs_inst == 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel DDI_INTR_ASSIGN_HDLR_N_ARGS(hdlp,
29949e866e40b95795203f3ee46f44a197c946e4stevel (ddi_intr_handler_t *)fhc_zs_intr_wrapper,
29949e866e40b95795203f3ee46f44a197c946e4stevel (caddr_t)softsp, NULL);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ret = i_ddi_add_ivintr(hdlp);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel DDI_INTR_ASSIGN_HDLR_N_ARGS(hdlp,
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->poll_list[zs_inst].funcp,
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->poll_list[zs_inst].arg1,
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->poll_list[zs_inst].arg2);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ret != DDI_SUCCESS)
29949e866e40b95795203f3ee46f44a197c946e4stevel goto done;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * If both zs handlers are active, then this is the
29949e866e40b95795203f3ee46f44a197c946e4stevel * second add_intrspec called, so do not enable
29949e866e40b95795203f3ee46f44a197c946e4stevel * the IMR_VALID bit, it is already on.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (zs_inst > 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* now release the mutex and return */
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&softsp->poll_list_lock);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel goto done;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* just release the mutex */
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&softsp->poll_list_lock);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel } else { /* normal interrupt installation */
29949e866e40b95795203f3ee46f44a197c946e4stevel int32_t i;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Allocate a nexus interrupt data structure */
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_arg = kmem_alloc(sizeof (struct fhc_wrapper_arg), KM_SLEEP);
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_arg->child = rdip;
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_arg->mapping_reg = mondo_vec_reg;
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_arg->clear_reg = (softsp->intr_regs[ino].clear_reg);
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_arg->softsp = softsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_arg->funcp =
29949e866e40b95795203f3ee46f44a197c946e4stevel (ddi_intr_handler_t *)hdlp->ih_cb_func;
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_arg->arg1 = hdlp->ih_cb_arg1;
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_arg->arg2 = hdlp->ih_cb_arg2;
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_arg->inum = hdlp->ih_inum;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < FHC_MAX_INO; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if (softsp->intr_list[i] == 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->intr_list[i] = fhc_arg;
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Save the fhc_arg in the ispec so we can use this info
29949e866e40b95795203f3ee46f44a197c946e4stevel * later to uninstall this interrupt spec.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel DDI_INTR_ASSIGN_HDLR_N_ARGS(hdlp,
29949e866e40b95795203f3ee46f44a197c946e4stevel (ddi_intr_handler_t *)fhc_intr_wrapper,
29949e866e40b95795203f3ee46f44a197c946e4stevel (caddr_t)fhc_arg, NULL);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ret = i_ddi_add_ivintr(hdlp);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel DDI_INTR_ASSIGN_HDLR_N_ARGS(hdlp, fhc_arg->funcp,
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_arg->arg1, fhc_arg->arg2);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ret != DDI_SUCCESS)
29949e866e40b95795203f3ee46f44a197c946e4stevel goto done;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Clear out a stale 'pending' or 'transmit' state in
29949e866e40b95795203f3ee46f44a197c946e4stevel * this device's ISM that might have been left from a
29949e866e40b95795203f3ee46f44a197c946e4stevel * previous session.
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * Since all FHC interrupts are level interrupts, any
29949e866e40b95795203f3ee46f44a197c946e4stevel * real interrupting condition will immediately transition
29949e866e40b95795203f3ee46f44a197c946e4stevel * the ISM back to pending.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel *(softsp->intr_regs[ino].clear_reg) = ISM_IDLE;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Program the mondo vector accordingly. This MUST be the
29949e866e40b95795203f3ee46f44a197c946e4stevel * last thing we do. Once we program the ino, the device
29949e866e40b95795203f3ee46f44a197c946e4stevel * may begin to interrupt.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel cpu_id = intr_dist_cpuid();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel tmp_mondo_vec = cpu_id << INR_PID_SHIFT;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* don't do this for fan because fan has a special control */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ino == FHC_FANFAIL_INO)
29949e866e40b95795203f3ee46f44a197c946e4stevel panic("fhc%d: enabling fanfail interrupt",
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_get_instance(dip));
29949e866e40b95795203f3ee46f44a197c946e4stevel else
29949e866e40b95795203f3ee46f44a197c946e4stevel tmp_mondo_vec |= IMR_VALID;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel DPRINTF(FHC_INTERRUPT_DEBUG,
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki ("Mondo 0x%x mapping reg: 0x%p", hdlp->ih_vector,
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void *)mondo_vec_reg));
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Store it in the hardware reg. */
29949e866e40b95795203f3ee46f44a197c946e4stevel *mondo_vec_reg = tmp_mondo_vec;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Read a FHC register to flush store buffers */
29949e866e40b95795203f3ee46f44a197c946e4stevel tmpreg = *(softsp->id);
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef lint
29949e866e40b95795203f3ee46f44a197c946e4stevel tmpreg = tmpreg;
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4steveldone:
29949e866e40b95795203f3ee46f44a197c946e4stevel return (ret);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * remove_intrspec - Remove an interrupt specification.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_remove_intr_impl(dev_info_t *dip, dev_info_t *rdip,
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_intr_handle_impl_t *hdlp)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel volatile uint_t *mondo_vec_reg;
29949e866e40b95795203f3ee46f44a197c946e4stevel volatile uint_t tmpreg;
29949e866e40b95795203f3ee46f44a197c946e4stevel int i;
29949e866e40b95795203f3ee46f44a197c946e4stevel struct fhc_soft_state *softsp = (struct fhc_soft_state *)
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_get_soft_state(fhcp, ddi_get_instance(dip));
29949e866e40b95795203f3ee46f44a197c946e4stevel int ino;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Xlate the interrupt */
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_xlate_intrs(hdlp,
29949e866e40b95795203f3ee46f44a197c946e4stevel (softsp->list->sc.board << BD_IVINTR_SHFT));
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* get the mondo number */
29949e866e40b95795203f3ee46f44a197c946e4stevel ino = FHC_INO(hdlp->ih_vector);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ino == FHC_UART_INO) {
29949e866e40b95795203f3ee46f44a197c946e4stevel int intr_found = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Lock the poll_list first */
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_enter(&softsp->poll_list_lock);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Find which entry in the poll list belongs to this
29949e866e40b95795203f3ee46f44a197c946e4stevel * intrspec.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < MAX_ZS_CNT; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if (softsp->poll_list[i].child == rdip &&
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->poll_list[i].inum == hdlp->ih_inum) {
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->poll_list[i].funcp = NULL;
29949e866e40b95795203f3ee46f44a197c946e4stevel intr_found++;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* If we did not find an entry, then we have a problem */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (!intr_found) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "fhc%d: Intrspec not found in"
193974072f41a843678abf5f61979c748687e66bSherry Moore " poll list", ddi_get_instance(dip));
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&softsp->poll_list_lock);
29949e866e40b95795203f3ee46f44a197c946e4stevel goto done;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * If we have removed all active entries for the poll
29949e866e40b95795203f3ee46f44a197c946e4stevel * list, then we have to disable interupts at this point.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((softsp->poll_list[0].funcp == NULL) &&
29949e866e40b95795203f3ee46f44a197c946e4stevel (softsp->poll_list[1].funcp == NULL)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel mondo_vec_reg =
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->intr_regs[FHC_UART_INO].mapping_reg;
29949e866e40b95795203f3ee46f44a197c946e4stevel *mondo_vec_reg &= ~IMR_VALID;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* flush the hardware buffers */
29949e866e40b95795203f3ee46f44a197c946e4stevel tmpreg = *(softsp->ctrl);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Eliminate the particular handler from the system. */
29949e866e40b95795203f3ee46f44a197c946e4stevel i_ddi_rem_ivintr(hdlp);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&softsp->poll_list_lock);
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel int32_t i;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < FHC_MAX_INO; i++)
29949e866e40b95795203f3ee46f44a197c946e4stevel if (softsp->intr_list[i]->child == rdip &&
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->intr_list[i]->inum == hdlp->ih_inum)
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (i >= FHC_MAX_INO)
29949e866e40b95795203f3ee46f44a197c946e4stevel goto done;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel mondo_vec_reg = softsp->intr_list[i]->mapping_reg;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Turn off the valid bit in the mapping register. */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* XXX what about FHC_FANFAIL owned imr? */
29949e866e40b95795203f3ee46f44a197c946e4stevel *mondo_vec_reg &= ~IMR_VALID;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* flush the hardware store buffers */
29949e866e40b95795203f3ee46f44a197c946e4stevel tmpreg = *(softsp->id);
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef lint
29949e866e40b95795203f3ee46f44a197c946e4stevel tmpreg = tmpreg;
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Eliminate the particular handler from the system. */
29949e866e40b95795203f3ee46f44a197c946e4stevel i_ddi_rem_ivintr(hdlp);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel kmem_free(softsp->intr_list[i],
29949e866e40b95795203f3ee46f44a197c946e4stevel sizeof (struct fhc_wrapper_arg));
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->intr_list[i] = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4steveldone:
29949e866e40b95795203f3ee46f44a197c946e4stevel ;
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/* new intr_ops structure */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op,
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_intr_handle_impl_t *hdlp, void *result)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel int ret = DDI_SUCCESS;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel switch (intr_op) {
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_INTROP_GETCAP:
29949e866e40b95795203f3ee46f44a197c946e4stevel *(int *)result = DDI_INTR_FLAG_LEVEL;
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_INTROP_ALLOC:
29949e866e40b95795203f3ee46f44a197c946e4stevel *(int *)result = hdlp->ih_scratch1;
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_INTROP_FREE:
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_INTROP_GETPRI:
29949e866e40b95795203f3ee46f44a197c946e4stevel if (hdlp->ih_pri == 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel struct fhc_soft_state *softsp =
29949e866e40b95795203f3ee46f44a197c946e4stevel (struct fhc_soft_state *)ddi_get_soft_state(fhcp,
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_get_instance(dip));
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Xlate the interrupt */
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_xlate_intrs(hdlp,
29949e866e40b95795203f3ee46f44a197c946e4stevel (softsp->list->sc.board << BD_IVINTR_SHFT));
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel *(int *)result = hdlp->ih_pri;
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_INTROP_SETPRI:
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_INTROP_ADDISR:
29949e866e40b95795203f3ee46f44a197c946e4stevel ret = fhc_add_intr_impl(dip, rdip, hdlp);
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_INTROP_REMISR:
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_remove_intr_impl(dip, rdip, hdlp);
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_INTROP_ENABLE:
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_INTROP_DISABLE:
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_INTROP_NINTRS:
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_INTROP_NAVAIL:
a54f81fbf66e3e4c14a94d571c0fe241e4cf2394anish *(int *)result = i_ddi_get_intx_nintrs(rdip);
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_INTROP_SETCAP:
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_INTROP_SETMASK:
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_INTROP_CLRMASK:
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_INTROP_GETPENDING:
29949e866e40b95795203f3ee46f44a197c946e4stevel ret = DDI_ENOTSUP;
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_INTROP_SUPPORTED_TYPES:
29949e866e40b95795203f3ee46f44a197c946e4stevel /* only support fixed interrupts */
a54f81fbf66e3e4c14a94d571c0fe241e4cf2394anish *(int *)result = i_ddi_get_intx_nintrs(rdip) ?
29949e866e40b95795203f3ee46f44a197c946e4stevel DDI_INTR_TYPE_FIXED : 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel default:
29949e866e40b95795203f3ee46f44a197c946e4stevel ret = i_ddi_intr_ops(dip, rdip, intr_op, hdlp, result);
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel return (ret);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * FHC Control Ops routine
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * Requests handled here:
29949e866e40b95795203f3ee46f44a197c946e4stevel * DDI_CTLOPS_INITCHILD see impl_ddi_sunbus_initchild() for details
29949e866e40b95795203f3ee46f44a197c946e4stevel * DDI_CTLOPS_UNINITCHILD see fhc_uninit_child() for details
29949e866e40b95795203f3ee46f44a197c946e4stevel * DDI_CTLOPS_REPORTDEV TODO - need to implement this.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_ctlops(dev_info_t *dip, dev_info_t *rdip,
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_ctl_enum_t op, void *arg, void *result)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel switch (op) {
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_CTLOPS_INITCHILD:
29949e866e40b95795203f3ee46f44a197c946e4stevel DPRINTF(FHC_CTLOPS_DEBUG, ("DDI_CTLOPS_INITCHILD\n"));
29949e866e40b95795203f3ee46f44a197c946e4stevel return (impl_ddi_sunbus_initchild((dev_info_t *)arg));
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_CTLOPS_UNINITCHILD:
29949e866e40b95795203f3ee46f44a197c946e4stevel impl_ddi_sunbus_removechild((dev_info_t *)arg);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_SUCCESS);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_CTLOPS_REPORTDEV:
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * TODO - Figure out what makes sense to report here.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_SUCCESS);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_CTLOPS_POKE:
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_CTLOPS_PEEK:
29949e866e40b95795203f3ee46f44a197c946e4stevel return (fhc_ctlops_peekpoke(op, (peekpoke_ctlops_t *)arg,
29949e866e40b95795203f3ee46f44a197c946e4stevel result));
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel default:
29949e866e40b95795203f3ee46f44a197c946e4stevel return (ddi_ctlops(dip, rdip, op, arg, result));
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * We're prepared to claim that the interrupt string is in
29949e866e40b95795203f3ee46f44a197c946e4stevel * the form of a list of <FHCintr> specifications, or we're dealing
29949e866e40b95795203f3ee46f44a197c946e4stevel * with on-board devices and we have an interrupt_number property which
29949e866e40b95795203f3ee46f44a197c946e4stevel * gives us our mondo number.
29949e866e40b95795203f3ee46f44a197c946e4stevel * Translate the mondos into fhcintrspecs.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel/* ARGSUSED */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_xlate_intrs(ddi_intr_handle_impl_t *hdlp, uint32_t ign)
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel uint32_t mondo;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel mondo = hdlp->ih_vector;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel hdlp->ih_vector = (mondo | ign);
29949e866e40b95795203f3ee46f44a197c946e4stevel if (hdlp->ih_pri == 0)
29949e866e40b95795203f3ee46f44a197c946e4stevel hdlp->ih_pri = fhc_int_priorities[FHC_INO(mondo)];
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_ctlops_peekpoke(ddi_ctl_enum_t cmd, peekpoke_ctlops_t *in_args,
29949e866e40b95795203f3ee46f44a197c946e4stevel void *result)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel int err = DDI_SUCCESS;
29949e866e40b95795203f3ee46f44a197c946e4stevel on_trap_data_t otd;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* No safe access except for peek/poke is supported. */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (in_args->handle != NULL)
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_FAILURE);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Set up protected environment. */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (!on_trap(&otd, OT_DATA_ACCESS)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel uintptr_t tramp = otd.ot_trampoline;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (cmd == DDI_CTLOPS_POKE) {
29949e866e40b95795203f3ee46f44a197c946e4stevel otd.ot_trampoline = (uintptr_t)&poke_fault;
29949e866e40b95795203f3ee46f44a197c946e4stevel err = do_poke(in_args->size, (void *)in_args->dev_addr,
29949e866e40b95795203f3ee46f44a197c946e4stevel (void *)in_args->host_addr);
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel otd.ot_trampoline = (uintptr_t)&peek_fault;
29949e866e40b95795203f3ee46f44a197c946e4stevel err = do_peek(in_args->size, (void *)in_args->dev_addr,
29949e866e40b95795203f3ee46f44a197c946e4stevel (void *)in_args->host_addr);
29949e866e40b95795203f3ee46f44a197c946e4stevel result = (void *)in_args->host_addr;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel otd.ot_trampoline = tramp;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else
29949e866e40b95795203f3ee46f44a197c946e4stevel err = DDI_FAILURE;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Take down protected environment. */
29949e866e40b95795203f3ee46f44a197c946e4stevel no_trap();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel return (err);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * This function initializes the temperature arrays for use. All
29949e866e40b95795203f3ee46f44a197c946e4stevel * temperatures are set in to invalid value to start.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelvoid
29949e866e40b95795203f3ee46f44a197c946e4stevelinit_temp_arrays(struct temp_stats *envstat)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel int i;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel envstat->index = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < L1_SZ; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel envstat->l1[i] = NA_TEMP;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < L2_SZ; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel envstat->l2[i] = NA_TEMP;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < L3_SZ; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel envstat->l3[i] = NA_TEMP;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < L4_SZ; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel envstat->l4[i] = NA_TEMP;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < L5_SZ; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel envstat->l5[i] = NA_TEMP;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel envstat->max = NA_TEMP;
29949e866e40b95795203f3ee46f44a197c946e4stevel envstat->min = NA_TEMP;
29949e866e40b95795203f3ee46f44a197c946e4stevel envstat->trend = TREND_UNKNOWN;
29949e866e40b95795203f3ee46f44a197c946e4stevel envstat->version = TEMP_KSTAT_VERSION;
29949e866e40b95795203f3ee46f44a197c946e4stevel envstat->override = NA_TEMP;
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/* Inhibit warning messages below this temperature, eg for CPU poweron. */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic uint_t fhc_cpu_warning_temp_threshold = FHC_CPU_WARNING_TEMP_THRESHOLD;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * This function manages the temperature history in the temperature
29949e866e40b95795203f3ee46f44a197c946e4stevel * statistics buffer passed in. It calls the temperature calibration
29949e866e40b95795203f3ee46f44a197c946e4stevel * routines and maintains the time averaged temperature data.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelvoid
29949e866e40b95795203f3ee46f44a197c946e4stevelupdate_temp(dev_info_t *pdip, struct temp_stats *envstat, uchar_t value)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t index; /* The absolute temperature counter */
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t tmp_index; /* temp index into upper level array */
29949e866e40b95795203f3ee46f44a197c946e4stevel int count; /* Count of non-zero values in array */
29949e866e40b95795203f3ee46f44a197c946e4stevel int total; /* sum total of non-zero values in array */
29949e866e40b95795203f3ee46f44a197c946e4stevel short real_temp; /* calibrated temperature */
29949e866e40b95795203f3ee46f44a197c946e4stevel int i;
29949e866e40b95795203f3ee46f44a197c946e4stevel struct fhc_soft_state *softsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel char buffer[256]; /* buffer for warning of overtemp */
29949e866e40b95795203f3ee46f44a197c946e4stevel enum temp_state temp_state; /* Temperature state */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * NOTE: This global counter is not protected since we're called
29949e866e40b95795203f3ee46f44a197c946e4stevel * serially for each board.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel static int shutdown_msg = 0; /* Flag if shutdown warning issued */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* determine soft state pointer of parent */
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp = ddi_get_soft_state(fhcp, ddi_get_instance(pdip));
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel envstat->index++;
29949e866e40b95795203f3ee46f44a197c946e4stevel index = envstat->index;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * You need to update the level 5 intervals first, since
29949e866e40b95795203f3ee46f44a197c946e4stevel * they are based on the data from the level 4 intervals,
29949e866e40b95795203f3ee46f44a197c946e4stevel * and so on, down to the level 1 intervals.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* update the level 5 intervals if it is time */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (((tmp_index = L5_INDEX(index)) > 0) && (L5_REM(index) == 0)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Generate the index within the level 5 array */
29949e866e40b95795203f3ee46f44a197c946e4stevel tmp_index -= 1; /* decrement by 1 for indexing */
29949e866e40b95795203f3ee46f44a197c946e4stevel tmp_index = tmp_index % L5_SZ;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* take an average of the level 4 array */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0, count = 0, total = 0; i < L4_SZ; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Do not include zero values in average */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (envstat->l4[i] != NA_TEMP) {
29949e866e40b95795203f3ee46f44a197c946e4stevel total += (int)envstat->l4[i];
29949e866e40b95795203f3ee46f44a197c946e4stevel count++;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * If there were any level 4 data points to average,
29949e866e40b95795203f3ee46f44a197c946e4stevel * do so.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (count != 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel envstat->l5[tmp_index] = total/count;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel envstat->l5[tmp_index] = NA_TEMP;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* update the level 4 intervals if it is time */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (((tmp_index = L4_INDEX(index)) > 0) && (L4_REM(index) == 0)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Generate the index within the level 4 array */
29949e866e40b95795203f3ee46f44a197c946e4stevel tmp_index -= 1; /* decrement by 1 for indexing */
29949e866e40b95795203f3ee46f44a197c946e4stevel tmp_index = tmp_index % L4_SZ;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* take an average of the level 3 array */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0, count = 0, total = 0; i < L3_SZ; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Do not include zero values in average */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (envstat->l3[i] != NA_TEMP) {
29949e866e40b95795203f3ee46f44a197c946e4stevel total += (int)envstat->l3[i];
29949e866e40b95795203f3ee46f44a197c946e4stevel count++;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * If there were any level 3 data points to average,
29949e866e40b95795203f3ee46f44a197c946e4stevel * do so.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (count != 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel envstat->l4[tmp_index] = total/count;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel envstat->l4[tmp_index] = NA_TEMP;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* update the level 3 intervals if it is time */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (((tmp_index = L3_INDEX(index)) > 0) && (L3_REM(index) == 0)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Generate the index within the level 3 array */
29949e866e40b95795203f3ee46f44a197c946e4stevel tmp_index -= 1; /* decrement by 1 for indexing */
29949e866e40b95795203f3ee46f44a197c946e4stevel tmp_index = tmp_index % L3_SZ;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* take an average of the level 2 array */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0, count = 0, total = 0; i < L2_SZ; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Do not include zero values in average */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (envstat->l2[i] != NA_TEMP) {
29949e866e40b95795203f3ee46f44a197c946e4stevel total += (int)envstat->l2[i];
29949e866e40b95795203f3ee46f44a197c946e4stevel count++;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * If there were any level 2 data points to average,
29949e866e40b95795203f3ee46f44a197c946e4stevel * do so.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (count != 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel envstat->l3[tmp_index] = total/count;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel envstat->l3[tmp_index] = NA_TEMP;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* update the level 2 intervals if it is time */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (((tmp_index = L2_INDEX(index)) > 0) && (L2_REM(index) == 0)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Generate the index within the level 2 array */
29949e866e40b95795203f3ee46f44a197c946e4stevel tmp_index -= 1; /* decrement by 1 for indexing */
29949e866e40b95795203f3ee46f44a197c946e4stevel tmp_index = tmp_index % L2_SZ;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* take an average of the level 1 array */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0, count = 0, total = 0; i < L1_SZ; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Do not include zero values in average */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (envstat->l1[i] != NA_TEMP) {
29949e866e40b95795203f3ee46f44a197c946e4stevel total += (int)envstat->l1[i];
29949e866e40b95795203f3ee46f44a197c946e4stevel count++;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * If there were any level 1 data points to average,
29949e866e40b95795203f3ee46f44a197c946e4stevel * do so.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (count != 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel envstat->l2[tmp_index] = total/count;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel envstat->l2[tmp_index] = NA_TEMP;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* determine the current temperature in degrees Celcius */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (envstat->override != NA_TEMP) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* use override temperature for this board */
29949e866e40b95795203f3ee46f44a197c946e4stevel real_temp = envstat->override;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Run the calibration function using this board type */
29949e866e40b95795203f3ee46f44a197c946e4stevel real_temp = calibrate_temp(softsp->list->sc.type, value,
193974072f41a843678abf5f61979c748687e66bSherry Moore softsp->list->sc.ac_compid);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel envstat->l1[index % L1_SZ] = real_temp;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* check if the temperature state for this device needs to change */
29949e866e40b95795203f3ee46f44a197c946e4stevel temp_state = get_temp_state(softsp->list->sc.type, real_temp,
193974072f41a843678abf5f61979c748687e66bSherry Moore softsp->list->sc.board);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* has the state changed? Then get the board string ready */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (temp_state != envstat->state) {
29949e866e40b95795203f3ee46f44a197c946e4stevel int board = softsp->list->sc.board;
29949e866e40b95795203f3ee46f44a197c946e4stevel enum board_type type = softsp->list->sc.type;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel build_bd_display_str(buffer, type, board);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (temp_state > envstat->state) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if (envstat->state == TEMP_OK) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if (type == CLOCK_BOARD) {
29949e866e40b95795203f3ee46f44a197c946e4stevel reg_fault(0, FT_OVERTEMP, FT_SYSTEM);
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel reg_fault(board, FT_OVERTEMP,
193974072f41a843678abf5f61979c748687e66bSherry Moore FT_BOARD);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* heating up, change state now */
29949e866e40b95795203f3ee46f44a197c946e4stevel envstat->temp_cnt = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel envstat->state = temp_state;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (temp_state == TEMP_WARN) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* now warn the user of the problem */
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s is warm (temperature: %dC). "
193974072f41a843678abf5f61979c748687e66bSherry Moore "Please check system cooling", buffer,
193974072f41a843678abf5f61979c748687e66bSherry Moore real_temp);
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bd_update(board, SYSC_EVT_BD_OVERTEMP);
29949e866e40b95795203f3ee46f44a197c946e4stevel if (temperature_chamber == -1)
29949e866e40b95795203f3ee46f44a197c946e4stevel temperature_chamber =
29949e866e40b95795203f3ee46f44a197c946e4stevel check_for_chamber();
29949e866e40b95795203f3ee46f44a197c946e4stevel } else if (temp_state == TEMP_DANGER) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s is very hot (temperature: %dC)",
193974072f41a843678abf5f61979c748687e66bSherry Moore buffer, real_temp);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel envstat->shutdown_cnt = 1;
29949e866e40b95795203f3ee46f44a197c946e4stevel if (temperature_chamber == -1)
29949e866e40b95795203f3ee46f44a197c946e4stevel temperature_chamber =
193974072f41a843678abf5f61979c748687e66bSherry Moore check_for_chamber();
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((temperature_chamber == 0) &&
29949e866e40b95795203f3ee46f44a197c946e4stevel enable_overtemp_powerdown) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * NOTE: The "%d seconds" is not
29949e866e40b95795203f3ee46f44a197c946e4stevel * necessarily accurate in the case
29949e866e40b95795203f3ee46f44a197c946e4stevel * where we have multiple boards
29949e866e40b95795203f3ee46f44a197c946e4stevel * overheating and subsequently cooling
29949e866e40b95795203f3ee46f44a197c946e4stevel * down.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (shutdown_msg == 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "System "
193974072f41a843678abf5f61979c748687e66bSherry Moore "shutdown scheduled "
193974072f41a843678abf5f61979c748687e66bSherry Moore "in %d seconds due to "
193974072f41a843678abf5f61979c748687e66bSherry Moore "over-temperature "
193974072f41a843678abf5f61979c748687e66bSherry Moore "condition on %s",
193974072f41a843678abf5f61979c748687e66bSherry Moore SHUTDOWN_TIMEOUT_SEC,
193974072f41a843678abf5f61979c748687e66bSherry Moore buffer);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel shutdown_msg++;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * If this is a cpu board, power them off.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (temperature_chamber == 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_enter(&cpu_lock);
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) fhc_board_poweroffcpus(board, NULL,
29949e866e40b95795203f3ee46f44a197c946e4stevel CPU_FORCED);
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&cpu_lock);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel } else if (temp_state < envstat->state) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Avert the sigpower that would
29949e866e40b95795203f3ee46f44a197c946e4stevel * otherwise be sent to init.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel envstat->shutdown_cnt = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* cooling down, use state counter */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (envstat->temp_cnt == 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel envstat->temp_cnt = TEMP_STATE_COUNT;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else if (--envstat->temp_cnt == 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if (temp_state == TEMP_WARN) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s is cooling "
193974072f41a843678abf5f61979c748687e66bSherry Moore "(temperature: %dC)", buffer,
193974072f41a843678abf5f61979c748687e66bSherry Moore real_temp);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel } else if (temp_state == TEMP_OK) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s has cooled down "
193974072f41a843678abf5f61979c748687e66bSherry Moore "(temperature: %dC), system OK",
193974072f41a843678abf5f61979c748687e66bSherry Moore buffer, real_temp);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (type == CLOCK_BOARD) {
29949e866e40b95795203f3ee46f44a197c946e4stevel clear_fault(0, FT_OVERTEMP,
193974072f41a843678abf5f61979c748687e66bSherry Moore FT_SYSTEM);
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel clear_fault(board, FT_OVERTEMP,
193974072f41a843678abf5f61979c748687e66bSherry Moore FT_BOARD);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * If we just came out of TEMP_DANGER, and
29949e866e40b95795203f3ee46f44a197c946e4stevel * a warning was issued about shutting down,
29949e866e40b95795203f3ee46f44a197c946e4stevel * let the user know it's been cancelled
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (envstat->state == TEMP_DANGER &&
29949e866e40b95795203f3ee46f44a197c946e4stevel (temperature_chamber == 0) &&
29949e866e40b95795203f3ee46f44a197c946e4stevel enable_overtemp_powerdown &&
29949e866e40b95795203f3ee46f44a197c946e4stevel (powerdown_started == 0) &&
29949e866e40b95795203f3ee46f44a197c946e4stevel (--shutdown_msg == 0)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_NOTE, "System "
193974072f41a843678abf5f61979c748687e66bSherry Moore "shutdown due to over-"
193974072f41a843678abf5f61979c748687e66bSherry Moore "temperature "
193974072f41a843678abf5f61979c748687e66bSherry Moore "condition cancelled");
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel envstat->state = temp_state;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bd_update(board, SYSC_EVT_BD_TEMP_OK);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel envstat->temp_cnt = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (temp_state == TEMP_DANGER) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if (temperature_chamber == -1) {
29949e866e40b95795203f3ee46f44a197c946e4stevel temperature_chamber = check_for_chamber();
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((envstat->shutdown_cnt++ >= SHUTDOWN_COUNT) &&
29949e866e40b95795203f3ee46f44a197c946e4stevel (temperature_chamber == 0) &&
29949e866e40b95795203f3ee46f44a197c946e4stevel enable_overtemp_powerdown &&
29949e866e40b95795203f3ee46f44a197c946e4stevel (powerdown_started == 0)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel powerdown_started = 1;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* the system is still too hot */
29949e866e40b95795203f3ee46f44a197c946e4stevel build_bd_display_str(buffer,
193974072f41a843678abf5f61979c748687e66bSherry Moore softsp->list->sc.type,
193974072f41a843678abf5f61979c748687e66bSherry Moore softsp->list->sc.board);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "%s still too hot "
193974072f41a843678abf5f61979c748687e66bSherry Moore "(temperature: %dC)."
193974072f41a843678abf5f61979c748687e66bSherry Moore " Overtemp shutdown started", buffer,
193974072f41a843678abf5f61979c748687e66bSherry Moore real_temp);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_reboot();
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* update the maximum and minimum temperatures if necessary */
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((envstat->max == NA_TEMP) || (real_temp > envstat->max)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel envstat->max = real_temp;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((envstat->min == NA_TEMP) || (real_temp < envstat->min)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel envstat->min = real_temp;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Update the temperature trend. Currently, the temperature
29949e866e40b95795203f3ee46f44a197c946e4stevel * trend algorithm is based on the level 2 stats. So, we
29949e866e40b95795203f3ee46f44a197c946e4stevel * only need to run every time the level 2 stats get updated.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (((tmp_index = L2_INDEX(index)) > 0) && (L2_REM(index) == 0)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel enum board_type type = softsp->list->sc.type;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel envstat->trend = temp_trend(envstat);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Issue a warning if the temperature is rising rapidly. */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* For CPU boards, don't warn if CPUs just powered on. */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (envstat->trend == TREND_RAPID_RISE &&
29949e866e40b95795203f3ee46f44a197c946e4stevel (type != CPU_BOARD || real_temp >
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_cpu_warning_temp_threshold)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel int board = softsp->list->sc.board;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel build_bd_display_str(buffer, type, board);
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "%s temperature is rising rapidly! "
193974072f41a843678abf5f61979c748687e66bSherry Moore "Current temperature is %dC", buffer,
193974072f41a843678abf5f61979c748687e66bSherry Moore real_temp);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel#define PREV_L2_INDEX(x) ((x) ? ((x) - 1) : (L2_SZ - 1))
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * This routine determines if the temp of the device passed in is heating
29949e866e40b95795203f3ee46f44a197c946e4stevel * up, cooling down, or staying stable.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelenum temp_trend
29949e866e40b95795203f3ee46f44a197c946e4steveltemp_trend(struct temp_stats *tempstat)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel int ii;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t curr_index;
29949e866e40b95795203f3ee46f44a197c946e4stevel int curr_temp;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t prev_index;
29949e866e40b95795203f3ee46f44a197c946e4stevel int prev_temp;
29949e866e40b95795203f3ee46f44a197c946e4stevel int trail_temp;
29949e866e40b95795203f3ee46f44a197c946e4stevel int delta;
29949e866e40b95795203f3ee46f44a197c946e4stevel int read_cnt;
29949e866e40b95795203f3ee46f44a197c946e4stevel enum temp_trend result = TREND_STABLE;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (tempstat == NULL)
29949e866e40b95795203f3ee46f44a197c946e4stevel return (TREND_UNKNOWN);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel curr_index = (L2_INDEX(tempstat->index) - 1) % L2_SZ;
29949e866e40b95795203f3ee46f44a197c946e4stevel curr_temp = tempstat->l2[curr_index];
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Count how many temperature readings are available */
29949e866e40b95795203f3ee46f44a197c946e4stevel prev_index = curr_index;
29949e866e40b95795203f3ee46f44a197c946e4stevel for (read_cnt = 0; read_cnt < L2_SZ - 1; read_cnt++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if (tempstat->l2[prev_index] == NA_TEMP)
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel prev_index = PREV_L2_INDEX(prev_index);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel switch (read_cnt) {
29949e866e40b95795203f3ee46f44a197c946e4stevel case 0:
29949e866e40b95795203f3ee46f44a197c946e4stevel case 1:
29949e866e40b95795203f3ee46f44a197c946e4stevel result = TREND_UNKNOWN;
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel default:
29949e866e40b95795203f3ee46f44a197c946e4stevel delta = curr_temp - tempstat->l2[PREV_L2_INDEX(curr_index)];
29949e866e40b95795203f3ee46f44a197c946e4stevel prev_index = curr_index;
29949e866e40b95795203f3ee46f44a197c946e4stevel trail_temp = prev_temp = curr_temp;
29949e866e40b95795203f3ee46f44a197c946e4stevel if (delta >= RAPID_RISE_THRESH) { /* rapid rise? */
29949e866e40b95795203f3ee46f44a197c946e4stevel result = TREND_RAPID_RISE;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else if (delta > 0) { /* rise? */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (ii = 1; ii < read_cnt; ii++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel prev_index = PREV_L2_INDEX(prev_index);
29949e866e40b95795203f3ee46f44a197c946e4stevel prev_temp = tempstat->l2[prev_index];
29949e866e40b95795203f3ee46f44a197c946e4stevel if (prev_temp > trail_temp) {
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel trail_temp = prev_temp;
29949e866e40b95795203f3ee46f44a197c946e4stevel if (prev_temp <= curr_temp - NOISE_THRESH) {
29949e866e40b95795203f3ee46f44a197c946e4stevel result = TREND_RISE;
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel } else if (delta <= -RAPID_FALL_THRESH) { /* rapid fall? */
29949e866e40b95795203f3ee46f44a197c946e4stevel result = TREND_RAPID_FALL;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else if (delta < 0) { /* fall? */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (ii = 1; ii < read_cnt; ii++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel prev_index = PREV_L2_INDEX(prev_index);
29949e866e40b95795203f3ee46f44a197c946e4stevel prev_temp = tempstat->l2[prev_index];
29949e866e40b95795203f3ee46f44a197c946e4stevel if (prev_temp < trail_temp) {
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel trail_temp = prev_temp;
29949e866e40b95795203f3ee46f44a197c946e4stevel if (prev_temp >= curr_temp + NOISE_THRESH) {
29949e866e40b95795203f3ee46f44a197c946e4stevel result = TREND_FALL;
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel return (result);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Reboot the system if we can, otherwise attempt a power down
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelvoid
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_reboot(void)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel proc_t *initpp;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* send a SIGPWR to init process */
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_enter(&pidlock);
29949e866e40b95795203f3ee46f44a197c946e4stevel initpp = prfind(P_INITPID);
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&pidlock);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * If we're still booting and init(1) isn't
29949e866e40b95795203f3ee46f44a197c946e4stevel * set up yet, simply halt.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (initpp != NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel psignal(initpp, SIGFPE); /* init 6 */
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel power_down("Environmental Shutdown");
29949e866e40b95795203f3ee46f44a197c946e4stevel halt("Power off the System");
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelint
29949e866e40b95795203f3ee46f44a197c946e4stevelovertemp_kstat_update(kstat_t *ksp, int rw)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct temp_stats *tempstat;
29949e866e40b95795203f3ee46f44a197c946e4stevel char *kstatp;
29949e866e40b95795203f3ee46f44a197c946e4stevel int i;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel kstatp = (char *)ksp->ks_data;
29949e866e40b95795203f3ee46f44a197c946e4stevel tempstat = (struct temp_stats *)ksp->ks_private;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Kstat reads are used to retrieve the current system temperature
29949e866e40b95795203f3ee46f44a197c946e4stevel * history. Kstat writes are used to reset the max and min
29949e866e40b95795203f3ee46f44a197c946e4stevel * temperatures.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (rw == KSTAT_WRITE) {
29949e866e40b95795203f3ee46f44a197c946e4stevel short max; /* temporary copy of max temperature */
29949e866e40b95795203f3ee46f44a197c946e4stevel short min; /* temporary copy of min temperature */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * search for and reset the max and min to the current
29949e866e40b95795203f3ee46f44a197c946e4stevel * array contents. Old max and min values will get
29949e866e40b95795203f3ee46f44a197c946e4stevel * averaged out as they move into the higher level arrays.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel max = tempstat->l1[0];
29949e866e40b95795203f3ee46f44a197c946e4stevel min = tempstat->l1[0];
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Pull the max and min from Level 1 array */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < L1_SZ; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((tempstat->l1[i] != NA_TEMP) &&
29949e866e40b95795203f3ee46f44a197c946e4stevel (tempstat->l1[i] > max)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel max = tempstat->l1[i];
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((tempstat->l1[i] != NA_TEMP) &&
29949e866e40b95795203f3ee46f44a197c946e4stevel (tempstat->l1[i] < min)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel min = tempstat->l1[i];
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Pull the max and min from Level 2 array */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < L2_SZ; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((tempstat->l2[i] != NA_TEMP) &&
29949e866e40b95795203f3ee46f44a197c946e4stevel (tempstat->l2[i] > max)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel max = tempstat->l2[i];
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((tempstat->l2[i] != NA_TEMP) &&
29949e866e40b95795203f3ee46f44a197c946e4stevel (tempstat->l2[i] < min)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel min = tempstat->l2[i];
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Pull the max and min from Level 3 array */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < L3_SZ; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((tempstat->l3[i] != NA_TEMP) &&
29949e866e40b95795203f3ee46f44a197c946e4stevel (tempstat->l3[i] > max)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel max = tempstat->l3[i];
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((tempstat->l3[i] != NA_TEMP) &&
29949e866e40b95795203f3ee46f44a197c946e4stevel (tempstat->l3[i] < min)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel min = tempstat->l3[i];
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Pull the max and min from Level 4 array */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < L4_SZ; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((tempstat->l4[i] != NA_TEMP) &&
29949e866e40b95795203f3ee46f44a197c946e4stevel (tempstat->l4[i] > max)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel max = tempstat->l4[i];
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((tempstat->l4[i] != NA_TEMP) &&
29949e866e40b95795203f3ee46f44a197c946e4stevel (tempstat->l4[i] < min)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel min = tempstat->l4[i];
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Pull the max and min from Level 5 array */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < L5_SZ; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((tempstat->l5[i] != NA_TEMP) &&
29949e866e40b95795203f3ee46f44a197c946e4stevel (tempstat->l5[i] > max)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel max = tempstat->l5[i];
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((tempstat->l5[i] != NA_TEMP) &&
29949e866e40b95795203f3ee46f44a197c946e4stevel (tempstat->l5[i] < min)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel min = tempstat->l5[i];
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * copy the temperature history buffer into the
29949e866e40b95795203f3ee46f44a197c946e4stevel * kstat structure.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel bcopy(tempstat, kstatp, sizeof (struct temp_stats));
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel return (0);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelint
29949e866e40b95795203f3ee46f44a197c946e4steveltemp_override_kstat_update(kstat_t *ksp, int rw)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel short *over;
29949e866e40b95795203f3ee46f44a197c946e4stevel short *kstatp;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel kstatp = (short *)ksp->ks_data;
29949e866e40b95795203f3ee46f44a197c946e4stevel over = (short *)ksp->ks_private;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Kstat reads are used to get the temperature override setting.
29949e866e40b95795203f3ee46f44a197c946e4stevel * Kstat writes are used to set the temperature override setting.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (rw == KSTAT_WRITE) {
29949e866e40b95795203f3ee46f44a197c946e4stevel *over = *kstatp;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel *kstatp = *over;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel return (0);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * This function uses the calibration tables at the beginning of this file
29949e866e40b95795203f3ee46f44a197c946e4stevel * to lookup the actual temperature of the thermistor in degrees Celcius.
29949e866e40b95795203f3ee46f44a197c946e4stevel * If the measurement is out of the bounds of the acceptable values, the
29949e866e40b95795203f3ee46f44a197c946e4stevel * closest boundary value is used instead.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic short
29949e866e40b95795203f3ee46f44a197c946e4stevelcalibrate_temp(enum board_type type, uchar_t temp, uint_t ac_comp)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel short result = NA_TEMP;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (dont_calibrate == 1) {
29949e866e40b95795203f3ee46f44a197c946e4stevel return ((short)temp);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel switch (type) {
29949e866e40b95795203f3ee46f44a197c946e4stevel case CPU_BOARD:
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * If AC chip revision is >= 4 or if it is unitialized,
29949e866e40b95795203f3ee46f44a197c946e4stevel * then use the new calibration tables.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((CHIP_REV(ac_comp) >= 4) || (CHIP_REV(ac_comp) == 0)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if (temp >= CPU2_MX_CNT) {
29949e866e40b95795203f3ee46f44a197c946e4stevel result = cpu2_table[CPU2_MX_CNT-1];
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel result = cpu2_table[temp];
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel if (temp >= CPU_MX_CNT) {
29949e866e40b95795203f3ee46f44a197c946e4stevel result = cpu_table[CPU_MX_CNT-1];
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel result = cpu_table[temp];
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel case IO_2SBUS_BOARD:
29949e866e40b95795203f3ee46f44a197c946e4stevel case IO_SBUS_FFB_BOARD:
29949e866e40b95795203f3ee46f44a197c946e4stevel case IO_PCI_BOARD:
29949e866e40b95795203f3ee46f44a197c946e4stevel case IO_2SBUS_SOCPLUS_BOARD:
29949e866e40b95795203f3ee46f44a197c946e4stevel case IO_SBUS_FFB_SOCPLUS_BOARD:
29949e866e40b95795203f3ee46f44a197c946e4stevel if (temp < IO_MN_CNT) {
29949e866e40b95795203f3ee46f44a197c946e4stevel result = io_table[IO_MN_CNT];
29949e866e40b95795203f3ee46f44a197c946e4stevel } else if (temp >= IO_MX_CNT) {
29949e866e40b95795203f3ee46f44a197c946e4stevel result = io_table[IO_MX_CNT-1];
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel result = io_table[temp];
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel case CLOCK_BOARD:
29949e866e40b95795203f3ee46f44a197c946e4stevel if (temp < CLK_MN_CNT) {
29949e866e40b95795203f3ee46f44a197c946e4stevel result = clock_table[CLK_MN_CNT];
29949e866e40b95795203f3ee46f44a197c946e4stevel } else if (temp >= CLK_MX_CNT) {
29949e866e40b95795203f3ee46f44a197c946e4stevel result = clock_table[CLK_MX_CNT-1];
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel result = clock_table[temp];
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel default:
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel return (result);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Determine the temperature state of this board based on its type and
29949e866e40b95795203f3ee46f44a197c946e4stevel * the actual temperature in degrees Celcius.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic enum temp_state
29949e866e40b95795203f3ee46f44a197c946e4stevelget_temp_state(enum board_type type, short temp, int board)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel enum temp_state state = TEMP_OK;
29949e866e40b95795203f3ee46f44a197c946e4stevel short warn_limit;
29949e866e40b95795203f3ee46f44a197c946e4stevel short danger_limit;
29949e866e40b95795203f3ee46f44a197c946e4stevel struct cpu *cpa, *cpb;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel switch (type) {
29949e866e40b95795203f3ee46f44a197c946e4stevel case CPU_BOARD:
29949e866e40b95795203f3ee46f44a197c946e4stevel warn_limit = cpu_warn_temp;
29949e866e40b95795203f3ee46f44a197c946e4stevel danger_limit = cpu_danger_temp;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * For CPU boards with frequency >= 400 MHZ,
29949e866e40b95795203f3ee46f44a197c946e4stevel * temperature zones are different.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_enter(&cpu_lock);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((cpa = cpu_get(FHC_BOARD2CPU_A(board))) != NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((cpa->cpu_type_info.pi_clock) >= 400) {
29949e866e40b95795203f3ee46f44a197c946e4stevel warn_limit = cpu_warn_temp_4x;
29949e866e40b95795203f3ee46f44a197c946e4stevel danger_limit = cpu_danger_temp_4x;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((cpb = cpu_get(FHC_BOARD2CPU_B(board))) != NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((cpb->cpu_type_info.pi_clock) >= 400) {
29949e866e40b95795203f3ee46f44a197c946e4stevel warn_limit = cpu_warn_temp_4x;
29949e866e40b95795203f3ee46f44a197c946e4stevel danger_limit = cpu_danger_temp_4x;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&cpu_lock);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel case IO_2SBUS_BOARD:
29949e866e40b95795203f3ee46f44a197c946e4stevel case IO_SBUS_FFB_BOARD:
29949e866e40b95795203f3ee46f44a197c946e4stevel case IO_PCI_BOARD:
29949e866e40b95795203f3ee46f44a197c946e4stevel case IO_2SBUS_SOCPLUS_BOARD:
29949e866e40b95795203f3ee46f44a197c946e4stevel case IO_SBUS_FFB_SOCPLUS_BOARD:
29949e866e40b95795203f3ee46f44a197c946e4stevel warn_limit = io_warn_temp;
29949e866e40b95795203f3ee46f44a197c946e4stevel danger_limit = io_danger_temp;
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel case CLOCK_BOARD:
29949e866e40b95795203f3ee46f44a197c946e4stevel warn_limit = clk_warn_temp;
29949e866e40b95795203f3ee46f44a197c946e4stevel danger_limit = clk_danger_temp;
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel case UNINIT_BOARD:
29949e866e40b95795203f3ee46f44a197c946e4stevel case UNKNOWN_BOARD:
29949e866e40b95795203f3ee46f44a197c946e4stevel case MEM_BOARD:
29949e866e40b95795203f3ee46f44a197c946e4stevel default:
29949e866e40b95795203f3ee46f44a197c946e4stevel warn_limit = dft_warn_temp;
29949e866e40b95795203f3ee46f44a197c946e4stevel danger_limit = dft_danger_temp;
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (temp >= danger_limit) {
29949e866e40b95795203f3ee46f44a197c946e4stevel state = TEMP_DANGER;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else if (temp >= warn_limit) {
29949e866e40b95795203f3ee46f44a197c946e4stevel state = TEMP_WARN;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel return (state);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_add_kstats(struct fhc_soft_state *softsp)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct kstat *fhc_ksp;
29949e866e40b95795203f3ee46f44a197c946e4stevel struct fhc_kstat *fhc_named_ksp;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((fhc_ksp = kstat_create("unix", softsp->list->sc.board,
29949e866e40b95795203f3ee46f44a197c946e4stevel FHC_KSTAT_NAME, "misc", KSTAT_TYPE_NAMED,
29949e866e40b95795203f3ee46f44a197c946e4stevel sizeof (struct fhc_kstat) / sizeof (kstat_named_t),
29949e866e40b95795203f3ee46f44a197c946e4stevel KSTAT_FLAG_PERSISTENT)) == NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "fhc%d kstat_create failed",
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_get_instance(softsp->dip));
29949e866e40b95795203f3ee46f44a197c946e4stevel return;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_named_ksp = (struct fhc_kstat *)(fhc_ksp->ks_data);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* initialize the named kstats */
29949e866e40b95795203f3ee46f44a197c946e4stevel kstat_named_init(&fhc_named_ksp->csr,
193974072f41a843678abf5f61979c748687e66bSherry Moore CSR_KSTAT_NAMED,
193974072f41a843678abf5f61979c748687e66bSherry Moore KSTAT_DATA_UINT32);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel kstat_named_init(&fhc_named_ksp->bsr,
193974072f41a843678abf5f61979c748687e66bSherry Moore BSR_KSTAT_NAMED,
193974072f41a843678abf5f61979c748687e66bSherry Moore KSTAT_DATA_UINT32);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_ksp->ks_update = fhc_kstat_update;
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_ksp->ks_private = (void *)softsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->fhc_ksp = fhc_ksp;
29949e866e40b95795203f3ee46f44a197c946e4stevel kstat_install(fhc_ksp);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_kstat_update(kstat_t *ksp, int rw)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct fhc_kstat *fhcksp;
29949e866e40b95795203f3ee46f44a197c946e4stevel struct fhc_soft_state *softsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel fhcksp = (struct fhc_kstat *)ksp->ks_data;
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp = (struct fhc_soft_state *)ksp->ks_private;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* this is a read-only kstat. Bail out on a write */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (rw == KSTAT_WRITE) {
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EACCES);
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * copy the current state of the hardware into the
29949e866e40b95795203f3ee46f44a197c946e4stevel * kstat structure.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel fhcksp->csr.value.ui32 = *softsp->ctrl;
29949e866e40b95795203f3ee46f44a197c946e4stevel fhcksp->bsr.value.ui32 = *softsp->bsr;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel return (0);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int
29949e866e40b95795203f3ee46f44a197c946e4stevelcpu_on_board(int board)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel int upa_a = board << 1;
29949e866e40b95795203f3ee46f44a197c946e4stevel int upa_b = (board << 1) + 1;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((cpunodes[upa_a].nodeid != NULL) ||
29949e866e40b95795203f3ee46f44a197c946e4stevel (cpunodes[upa_b].nodeid != NULL)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel return (1);
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel return (0);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * This function uses the board list and toggles the OS green board
29949e866e40b95795203f3ee46f44a197c946e4stevel * LED. The mask input tells which bit fields are being modified,
29949e866e40b95795203f3ee46f44a197c946e4stevel * and the value input tells the states of the bits.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelvoid
29949e866e40b95795203f3ee46f44a197c946e4stevelupdate_board_leds(fhc_bd_t *board, uint_t mask, uint_t value)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel volatile uint_t temp;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(fhc_bdlist_locked());
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* mask off mask and value for only the LED bits */
29949e866e40b95795203f3ee46f44a197c946e4stevel mask &= (FHC_LED_LEFT|FHC_LED_MID|FHC_LED_RIGHT);
29949e866e40b95795203f3ee46f44a197c946e4stevel value &= (FHC_LED_LEFT|FHC_LED_MID|FHC_LED_RIGHT);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (board != NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_enter(&board->softsp->ctrl_lock);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* read the current register state */
29949e866e40b95795203f3ee46f44a197c946e4stevel temp = *board->softsp->ctrl;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * The EPDA bits are special since the register is
29949e866e40b95795203f3ee46f44a197c946e4stevel * special. We don't want to set them, since setting
29949e866e40b95795203f3ee46f44a197c946e4stevel * the bits on a shutdown cpu keeps the cpu permanently
29949e866e40b95795203f3ee46f44a197c946e4stevel * powered off. Also, the CSR_SYNC bit must always be
29949e866e40b95795203f3ee46f44a197c946e4stevel * set to 0 as it is an OBP semaphore that is expected to
29949e866e40b95795203f3ee46f44a197c946e4stevel * be clear for cpu restart.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel temp &= ~(FHC_CSR_SYNC | FHC_EPDA_OFF | FHC_EPDB_OFF);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* mask off the bits to change */
29949e866e40b95795203f3ee46f44a197c946e4stevel temp &= ~mask;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* or in the new values of the bits. */
29949e866e40b95795203f3ee46f44a197c946e4stevel temp |= value;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* update the register */
29949e866e40b95795203f3ee46f44a197c946e4stevel *board->softsp->ctrl = temp;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* flush the hardware registers */
29949e866e40b95795203f3ee46f44a197c946e4stevel temp = *board->softsp->ctrl;
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef lint
29949e866e40b95795203f3ee46f44a197c946e4stevel temp = temp;
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&board->softsp->ctrl_lock);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int
29949e866e40b95795203f3ee46f44a197c946e4stevelcheck_for_chamber(void)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel int chamber = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel dev_info_t *options_dip;
29949e866e40b95795203f3ee46f44a197c946e4stevel pnode_t options_node_id;
29949e866e40b95795203f3ee46f44a197c946e4stevel int mfgmode_len;
29949e866e40b95795203f3ee46f44a197c946e4stevel int retval;
29949e866e40b95795203f3ee46f44a197c946e4stevel char *mfgmode;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * The operator can disable overtemp powerdown from /etc/system or
29949e866e40b95795203f3ee46f44a197c946e4stevel * boot -h.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (!enable_overtemp_powerdown) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "Operator has disabled overtemp powerdown");
29949e866e40b95795203f3ee46f44a197c946e4stevel return (1);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * An OBP option, 'mfg-mode' is being used to inform us as to
29949e866e40b95795203f3ee46f44a197c946e4stevel * whether we are in an enviromental chamber. It exists in
29949e866e40b95795203f3ee46f44a197c946e4stevel * the 'options' node. This is where all OBP 'setenv' (eeprom)
29949e866e40b95795203f3ee46f44a197c946e4stevel * parameters live.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((options_dip = ddi_find_devinfo("options", -1, 0)) != NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel options_node_id = (pnode_t)ddi_get_nodeid(options_dip);
29949e866e40b95795203f3ee46f44a197c946e4stevel mfgmode_len = prom_getproplen(options_node_id, "mfg-mode");
29949e866e40b95795203f3ee46f44a197c946e4stevel if (mfgmode_len == -1) {
29949e866e40b95795203f3ee46f44a197c946e4stevel return (chamber);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel mfgmode = kmem_alloc(mfgmode_len+1, KM_SLEEP);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel retval = prom_getprop(options_node_id, "mfg-mode", mfgmode);
29949e866e40b95795203f3ee46f44a197c946e4stevel if (retval != -1) {
29949e866e40b95795203f3ee46f44a197c946e4stevel mfgmode[retval] = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel if (strcmp(mfgmode, CHAMBER_VALUE) == 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel chamber = 1;
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "System in Temperature"
193974072f41a843678abf5f61979c748687e66bSherry Moore " Chamber Mode. Overtemperature"
193974072f41a843678abf5f61979c748687e66bSherry Moore " Shutdown disabled");
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel kmem_free(mfgmode, mfgmode_len+1);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel return (chamber);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void
29949e866e40b95795203f3ee46f44a197c946e4stevelbuild_bd_display_str(char *buffer, enum board_type type, int board)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel if (buffer == NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel return;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* fill in board type to display */
29949e866e40b95795203f3ee46f44a197c946e4stevel switch (type) {
29949e866e40b95795203f3ee46f44a197c946e4stevel case UNINIT_BOARD:
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) sprintf(buffer, "Uninitialized Board type board %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore board);
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel case UNKNOWN_BOARD:
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) sprintf(buffer, "Unknown Board type board %d", board);
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel case CPU_BOARD:
29949e866e40b95795203f3ee46f44a197c946e4stevel case MEM_BOARD:
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) sprintf(buffer, "CPU/Memory board %d", board);
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel case IO_2SBUS_BOARD:
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) sprintf(buffer, "2 SBus IO board %d", board);
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel case IO_SBUS_FFB_BOARD:
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) sprintf(buffer, "SBus FFB IO board %d", board);
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel case IO_PCI_BOARD:
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) sprintf(buffer, "PCI IO board %d", board);
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel case CLOCK_BOARD:
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) sprintf(buffer, "Clock board");
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel case IO_2SBUS_SOCPLUS_BOARD:
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) sprintf(buffer, "2 SBus SOC+ IO board %d", board);
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel case IO_SBUS_FFB_SOCPLUS_BOARD:
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) sprintf(buffer, "SBus FFB SOC+ IO board %d", board);
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel default:
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) sprintf(buffer, "Unrecognized board type board %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore board);
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelvoid
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_intrdist(void *arg)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct fhc_soft_state *softsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel dev_info_t *dip = (dev_info_t *)arg;
29949e866e40b95795203f3ee46f44a197c946e4stevel volatile uint_t *mondo_vec_reg;
29949e866e40b95795203f3ee46f44a197c946e4stevel volatile uint_t *intr_state_reg;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t mondo_vec;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t tmp_reg;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t cpu_id;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t i;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* extract the soft state pointer */
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp = ddi_get_soft_state(fhcp, ddi_get_instance(dip));
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Loop through all the interrupt mapping registers and reprogram
29949e866e40b95795203f3ee46f44a197c946e4stevel * the target CPU for all valid registers.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < FHC_MAX_INO; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel mondo_vec_reg = softsp->intr_regs[i].mapping_reg;
29949e866e40b95795203f3ee46f44a197c946e4stevel intr_state_reg = softsp->intr_regs[i].clear_reg;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((*mondo_vec_reg & IMR_VALID) == 0)
29949e866e40b95795203f3ee46f44a197c946e4stevel continue;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel cpu_id = intr_dist_cpuid();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Check the current target of the mondo */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (((*mondo_vec_reg & INR_PID_MASK) >> INR_PID_SHIFT) ==
29949e866e40b95795203f3ee46f44a197c946e4stevel cpu_id) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* It is the same, don't reprogram */
29949e866e40b95795203f3ee46f44a197c946e4stevel return;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* So it's OK to reprogram the CPU target */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* turn off the valid bit */
29949e866e40b95795203f3ee46f44a197c946e4stevel *mondo_vec_reg &= ~IMR_VALID;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* flush the hardware registers */
29949e866e40b95795203f3ee46f44a197c946e4stevel tmp_reg = *softsp->id;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * wait for the state machine to idle. Do not loop on panic, so
29949e866e40b95795203f3ee46f44a197c946e4stevel * that system does not hang.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel while (((*intr_state_reg & INT_PENDING) == INT_PENDING) &&
29949e866e40b95795203f3ee46f44a197c946e4stevel !panicstr)
29949e866e40b95795203f3ee46f44a197c946e4stevel ;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* re-target the mondo and turn it on */
29949e866e40b95795203f3ee46f44a197c946e4stevel mondo_vec = (cpu_id << INR_PID_SHIFT) | IMR_VALID;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* write it back to the hardware. */
29949e866e40b95795203f3ee46f44a197c946e4stevel *mondo_vec_reg = mondo_vec;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* flush the hardware buffers. */
29949e866e40b95795203f3ee46f44a197c946e4stevel tmp_reg = *(softsp->id);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef lint
29949e866e40b95795203f3ee46f44a197c946e4stevel tmp_reg = tmp_reg;
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif /* lint */
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * reg_fault
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * This routine registers a fault in the fault list. If the fault
29949e866e40b95795203f3ee46f44a197c946e4stevel * is unique (does not exist in fault list) then a new fault is
29949e866e40b95795203f3ee46f44a197c946e4stevel * added to the fault list, with the appropriate structure elements
29949e866e40b95795203f3ee46f44a197c946e4stevel * filled in.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelvoid
29949e866e40b95795203f3ee46f44a197c946e4stevelreg_fault(int unit, enum ft_type type, enum ft_class fclass)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct ft_link_list *list; /* temporary list pointer */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (type >= ft_max_index) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "Illegal Fault type %x", type);
29949e866e40b95795203f3ee46f44a197c946e4stevel return;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_enter(&ftlist_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Search for the requested fault. If it already exists, return. */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (list = ft_list; list != NULL; list = list->next) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((list->f.unit == unit) && (list->f.type == type) &&
29949e866e40b95795203f3ee46f44a197c946e4stevel (list->f.fclass == fclass)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&ftlist_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel return;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Allocate a new fault structure. */
29949e866e40b95795203f3ee46f44a197c946e4stevel list = kmem_zalloc(sizeof (struct ft_link_list), KM_SLEEP);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* fill in the fault list elements */
29949e866e40b95795203f3ee46f44a197c946e4stevel list->f.unit = unit;
29949e866e40b95795203f3ee46f44a197c946e4stevel list->f.type = type;
29949e866e40b95795203f3ee46f44a197c946e4stevel list->f.fclass = fclass;
29949e866e40b95795203f3ee46f44a197c946e4stevel list->f.create_time = (time32_t)gethrestime_sec(); /* XX64 */
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) strncpy(list->f.msg, ft_str_table[type], MAX_FT_DESC);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* link it into the list. */
29949e866e40b95795203f3ee46f44a197c946e4stevel list->next = ft_list;
29949e866e40b95795203f3ee46f44a197c946e4stevel ft_list = list;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Update the total fault count */
29949e866e40b95795203f3ee46f44a197c946e4stevel ft_nfaults++;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&ftlist_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * clear_fault
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * This routine finds the fault list entry specified by the caller,
29949e866e40b95795203f3ee46f44a197c946e4stevel * deletes it from the fault list, and frees up the memory used for
29949e866e40b95795203f3ee46f44a197c946e4stevel * the entry. If the requested fault is not found, it exits silently.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelvoid
29949e866e40b95795203f3ee46f44a197c946e4stevelclear_fault(int unit, enum ft_type type, enum ft_class fclass)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct ft_link_list *list; /* temporary list pointer */
29949e866e40b95795203f3ee46f44a197c946e4stevel struct ft_link_list **vect;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_enter(&ftlist_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel list = ft_list;
29949e866e40b95795203f3ee46f44a197c946e4stevel vect = &ft_list;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Search for the requested fault. If it exists, delete it
29949e866e40b95795203f3ee46f44a197c946e4stevel * and relink the fault list.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (; list != NULL; vect = &list->next, list = list->next) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((list->f.unit == unit) && (list->f.type == type) &&
29949e866e40b95795203f3ee46f44a197c946e4stevel (list->f.fclass == fclass)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* remove the item from the list */
29949e866e40b95795203f3ee46f44a197c946e4stevel *vect = list->next;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* free the memory allocated */
29949e866e40b95795203f3ee46f44a197c946e4stevel kmem_free(list, sizeof (struct ft_link_list));
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Update the total fault count */
29949e866e40b95795203f3ee46f44a197c946e4stevel ft_nfaults--;
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&ftlist_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * process_fault_list
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * This routine walks the global fault list and updates the board list
29949e866e40b95795203f3ee46f44a197c946e4stevel * with the current status of each Yellow LED. If any faults are found
29949e866e40b95795203f3ee46f44a197c946e4stevel * in the system, then a non-zero value is returned. Else zero is returned.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelint
29949e866e40b95795203f3ee46f44a197c946e4stevelprocess_fault_list(void)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel int fault = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel struct ft_link_list *ftlist; /* fault list pointer */
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bd_t *bdlist; /* board list pointer */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Note on locking. The bdlist mutex is always acquired and
29949e866e40b95795203f3ee46f44a197c946e4stevel * held around the ftlist mutex when both are needed for an
29949e866e40b95795203f3ee46f44a197c946e4stevel * operation. This is to avoid deadlock.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* First lock the board list */
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) fhc_bdlist_lock(-1);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Grab the fault list lock first */
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_enter(&ftlist_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* clear the board list of all faults first */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (bdlist = fhc_bd_first(); bdlist; bdlist = fhc_bd_next(bdlist))
29949e866e40b95795203f3ee46f44a197c946e4stevel bdlist->fault = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* walk the fault list here */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (ftlist = ft_list; ftlist != NULL; ftlist = ftlist->next) {
29949e866e40b95795203f3ee46f44a197c946e4stevel fault++;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * If this is a board level fault, find the board, The
29949e866e40b95795203f3ee46f44a197c946e4stevel * unit number for all board class faults must be the
29949e866e40b95795203f3ee46f44a197c946e4stevel * actual board number. The caller of reg_fault must
29949e866e40b95795203f3ee46f44a197c946e4stevel * ensure this for FT_BOARD class faults.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ftlist->f.fclass == FT_BOARD) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Sanity check the board first */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (fhc_bd_valid(ftlist->f.unit)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel bdlist = fhc_bd(ftlist->f.unit);
29949e866e40b95795203f3ee46f44a197c946e4stevel bdlist->fault = 1;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "No board %d list entry found",
193974072f41a843678abf5f61979c748687e66bSherry Moore ftlist->f.unit);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* now unlock the fault list */
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&ftlist_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* unlock the board list before leaving */
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bdlist_unlock();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel return (fault);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Add a new memloc to the database (and keep 'em sorted by PA)
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelvoid
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_add_memloc(int board, uint64_t pa, uint_t size)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct fhc_memloc *p, **pp;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t ipa = pa >> FHC_MEMLOC_SHIFT;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(fhc_bdlist_locked());
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT((size & (size-1)) == 0); /* size must be power of 2 */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* look for a comparable memloc (as long as new PA smaller) */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (p = fhc_base_memloc, pp = &fhc_base_memloc;
29949e866e40b95795203f3ee46f44a197c946e4stevel p != NULL; pp = &p->next, p = p->next) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* have we passed our place in the sort? */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ipa < p->pa) {
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel p = kmem_alloc(sizeof (struct fhc_memloc), KM_SLEEP);
29949e866e40b95795203f3ee46f44a197c946e4stevel p->next = *pp;
29949e866e40b95795203f3ee46f44a197c946e4stevel p->board = board;
29949e866e40b95795203f3ee46f44a197c946e4stevel p->pa = ipa;
29949e866e40b95795203f3ee46f44a197c946e4stevel p->size = size;
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef DEBUG_MEMDEC
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_NOTE, "fhc_add_memloc: adding %d 0x%x 0x%x",
193974072f41a843678abf5f61979c748687e66bSherry Moore p->board, p->pa, p->size);
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif /* DEBUG_MEMDEC */
29949e866e40b95795203f3ee46f44a197c946e4stevel *pp = p;
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Delete all memloc records for a board from the database
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelvoid
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_del_memloc(int board)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct fhc_memloc *p, **pp;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(fhc_bdlist_locked());
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* delete all entries that match board */
29949e866e40b95795203f3ee46f44a197c946e4stevel pp = &fhc_base_memloc;
29949e866e40b95795203f3ee46f44a197c946e4stevel while ((p = *pp) != NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if (p->board == board) {
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef DEBUG_MEMDEC
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_NOTE, "fhc_del_memloc: removing %d "
29949e866e40b95795203f3ee46f44a197c946e4stevel "0x%x 0x%x", board, p->pa, p->size);
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif /* DEBUG_MEMDEC */
29949e866e40b95795203f3ee46f44a197c946e4stevel *pp = p->next;
29949e866e40b95795203f3ee46f44a197c946e4stevel kmem_free(p, sizeof (struct fhc_memloc));
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel pp = &(p->next);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Find a physical address range of sufficient size and return a starting PA
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4steveluint64_t
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_find_memloc_gap(uint_t size)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct fhc_memloc *p;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t base_pa = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t mask = ~(size-1);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(fhc_bdlist_locked());
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT((size & (size-1)) == 0); /* size must be power of 2 */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * walk the list of known memlocs and measure the 'gaps'.
29949e866e40b95795203f3ee46f44a197c946e4stevel * we will need a hole that can align the 'size' requested.
29949e866e40b95795203f3ee46f44a197c946e4stevel * (e.g. a 256mb bank needs to be on a 256mb boundary).
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (p = fhc_base_memloc; p != NULL; p = p->next) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if (base_pa != (base_pa & mask))
29949e866e40b95795203f3ee46f44a197c946e4stevel base_pa = (base_pa + size) & mask;
29949e866e40b95795203f3ee46f44a197c946e4stevel if (base_pa + size <= p->pa)
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel base_pa = p->pa + p->size;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * At this point, we assume that base_pa is good enough.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT((base_pa + size) <= FHC_MEMLOC_MAX);
29949e866e40b95795203f3ee46f44a197c946e4stevel if (base_pa != (base_pa & mask))
29949e866e40b95795203f3ee46f44a197c946e4stevel base_pa = (base_pa + size) & mask; /* align */
29949e866e40b95795203f3ee46f44a197c946e4stevel return ((uint64_t)base_pa << FHC_MEMLOC_SHIFT);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * This simple function to write the MCRs can only be used when
29949e866e40b95795203f3ee46f44a197c946e4stevel * the contents of memory are not valid as there is a bug in the AC
29949e866e40b95795203f3ee46f44a197c946e4stevel * ASIC concerning refresh.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_write_mcrs(
29949e866e40b95795203f3ee46f44a197c946e4stevel uint64_t cpa,
29949e866e40b95795203f3ee46f44a197c946e4stevel uint64_t dpa0,
29949e866e40b95795203f3ee46f44a197c946e4stevel uint64_t dpa1,
29949e866e40b95795203f3ee46f44a197c946e4stevel uint64_t c,
29949e866e40b95795203f3ee46f44a197c946e4stevel uint64_t d0,
29949e866e40b95795203f3ee46f44a197c946e4stevel uint64_t d1)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel stdphysio(cpa, c & ~AC_CSR_REFEN);
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) lddphysio(cpa);
29949e866e40b95795203f3ee46f44a197c946e4stevel if (GRP_SIZE_IS_SET(d0)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel stdphysio(dpa0, d0);
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) lddphysio(dpa0);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel if (GRP_SIZE_IS_SET(d1)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel stdphysio(dpa1, d1);
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) lddphysio(dpa1);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel stdphysio(cpa, c);
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) lddphysio(cpa);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/* compute the appropriate RASIZE for bank size */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic uint_t
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_cvt_size(uint64_t bsz)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t csz;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel csz = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel bsz /= 64;
29949e866e40b95795203f3ee46f44a197c946e4stevel while (bsz) {
29949e866e40b95795203f3ee46f44a197c946e4stevel csz++;
29949e866e40b95795203f3ee46f44a197c946e4stevel bsz /= 2;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel csz /= 2;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel return (csz);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelvoid
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_program_memory(int board, uint64_t pa)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel uint64_t cpa, dpa0, dpa1;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint64_t c, d0, d1;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint64_t b0_pa, b1_pa;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint64_t memdec0, memdec1;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t b0_size, b1_size;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* XXX gross hack to get to board via board number */
29949e866e40b95795203f3ee46f44a197c946e4stevel cpa = 0x1c0f9000060ull + (board * 0x400000000ull);
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef DEBUG_MEMDEC
29949e866e40b95795203f3ee46f44a197c946e4stevel prom_printf("cpa = 0x%llx\n", cpa);
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif /* DEBUG_MEMDEC */
29949e866e40b95795203f3ee46f44a197c946e4stevel dpa0 = cpa + 0x10;
29949e866e40b95795203f3ee46f44a197c946e4stevel dpa1 = cpa + 0x20;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/* assume size is set by connect */
29949e866e40b95795203f3ee46f44a197c946e4stevel memdec0 = lddphysio(dpa0);
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef DEBUG_MEMDEC
29949e866e40b95795203f3ee46f44a197c946e4stevel prom_printf("memdec0 = 0x%llx\n", memdec0);
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif /* DEBUG_MEMDEC */
29949e866e40b95795203f3ee46f44a197c946e4stevel memdec1 = lddphysio(dpa1);
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef DEBUG_MEMDEC
29949e866e40b95795203f3ee46f44a197c946e4stevel prom_printf("memdec1 = 0x%llx\n", memdec1);
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif /* DEBUG_MEMDEC */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (GRP_SIZE_IS_SET(memdec0)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel b0_size = GRP_SPANMB(memdec0);
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel b0_size = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel if (GRP_SIZE_IS_SET(memdec1)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel b1_size = GRP_SPANMB(memdec1);
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel b1_size = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel c = lddphysio(cpa);
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef DEBUG_MEMDEC
29949e866e40b95795203f3ee46f44a197c946e4stevel prom_printf("c = 0x%llx\n", c);
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif /* DEBUG_MEMDEC */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (b0_size) {
29949e866e40b95795203f3ee46f44a197c946e4stevel b0_pa = pa;
29949e866e40b95795203f3ee46f44a197c946e4stevel d0 = SETUP_DECODE(b0_pa, b0_size, 0, 0);
29949e866e40b95795203f3ee46f44a197c946e4stevel d0 |= AC_MEM_VALID;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel c &= ~0x7;
29949e866e40b95795203f3ee46f44a197c946e4stevel c |= 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel c &= ~(0x7 << 8);
29949e866e40b95795203f3ee46f44a197c946e4stevel c |= (fhc_cvt_size(b0_size) << 8); /* match row size */
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel d0 = memdec0;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel if (b1_size) {
29949e866e40b95795203f3ee46f44a197c946e4stevel b1_pa = pa + 0x80000000ull; /* XXX 2gb */
29949e866e40b95795203f3ee46f44a197c946e4stevel d1 = SETUP_DECODE(b1_pa, b1_size, 0, 0);
29949e866e40b95795203f3ee46f44a197c946e4stevel d1 |= AC_MEM_VALID;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel c &= ~(0x7 << 3);
29949e866e40b95795203f3ee46f44a197c946e4stevel c |= (0 << 3);
29949e866e40b95795203f3ee46f44a197c946e4stevel c &= ~(0x7 << 11);
29949e866e40b95795203f3ee46f44a197c946e4stevel c |= (fhc_cvt_size(b1_size) << 11); /* match row size */
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel d1 = memdec1;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef DEBUG_MEMDEC
29949e866e40b95795203f3ee46f44a197c946e4stevel prom_printf("c 0x%llx, d0 0x%llx, d1 0x%llx\n", c, d0, d1);
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif /* DEBUG_MEMDEC */
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_write_mcrs(cpa, dpa0, dpa1, c, d0, d1);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Creates a variable sized virtual kstat with a snapshot routine in order
29949e866e40b95795203f3ee46f44a197c946e4stevel * to pass the linked list fault list up to userland. Also creates a
29949e866e40b95795203f3ee46f44a197c946e4stevel * virtual kstat to pass up the string table for faults.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelvoid
29949e866e40b95795203f3ee46f44a197c946e4stevelcreate_ft_kstats(int instance)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct kstat *ksp;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ksp = kstat_create("unix", instance, FT_LIST_KSTAT_NAME, "misc",
193974072f41a843678abf5f61979c748687e66bSherry Moore KSTAT_TYPE_RAW, 1, KSTAT_FLAG_VIRTUAL|KSTAT_FLAG_VAR_SIZE);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ksp != NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel ksp->ks_data = NULL;
29949e866e40b95795203f3ee46f44a197c946e4stevel ksp->ks_update = ft_ks_update;
29949e866e40b95795203f3ee46f44a197c946e4stevel ksp->ks_snapshot = ft_ks_snapshot;
29949e866e40b95795203f3ee46f44a197c946e4stevel ksp->ks_data_size = 1;
29949e866e40b95795203f3ee46f44a197c946e4stevel ksp->ks_lock = &ftlist_mutex;
29949e866e40b95795203f3ee46f44a197c946e4stevel kstat_install(ksp);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * This routine creates a snapshot of all the fault list data. It is
29949e866e40b95795203f3ee46f44a197c946e4stevel * called by the kstat framework when a kstat read is done.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int
29949e866e40b95795203f3ee46f44a197c946e4stevelft_ks_snapshot(struct kstat *ksp, void *buf, int rw)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct ft_link_list *ftlist;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (rw == KSTAT_WRITE) {
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EACCES);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ksp->ks_snaptime = gethrtime();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel for (ftlist = ft_list; ftlist != NULL; ftlist = ftlist->next) {
29949e866e40b95795203f3ee46f44a197c946e4stevel bcopy(&ftlist->f, buf, sizeof (struct ft_list));
29949e866e40b95795203f3ee46f44a197c946e4stevel buf = ((struct ft_list *)buf) + 1;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel return (0);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Setup the kstat data size for the kstat framework. This is used in
29949e866e40b95795203f3ee46f44a197c946e4stevel * conjunction with the ks_snapshot routine. This routine sets the size,
29949e866e40b95795203f3ee46f44a197c946e4stevel * the kstat framework allocates the memory, and ks_shapshot does the
29949e866e40b95795203f3ee46f44a197c946e4stevel * data transfer.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int
29949e866e40b95795203f3ee46f44a197c946e4stevelft_ks_update(struct kstat *ksp, int rw)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel if (rw == KSTAT_WRITE) {
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EACCES);
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ft_nfaults) {
29949e866e40b95795203f3ee46f44a197c946e4stevel ksp->ks_data_size = ft_nfaults *
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (struct ft_list);
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel ksp->ks_data_size = 1;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel return (0);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Power off any cpus on the board.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelint
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_board_poweroffcpus(int board, char *errbuf, int cpu_flags)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel cpu_t *cpa, *cpb;
29949e866e40b95795203f3ee46f44a197c946e4stevel enum board_type type;
29949e866e40b95795203f3ee46f44a197c946e4stevel int error = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(MUTEX_HELD(&cpu_lock));
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * what type of board are we dealing with?
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel type = fhc_bd_type(board);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel switch (type) {
29949e866e40b95795203f3ee46f44a197c946e4stevel case CPU_BOARD:
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * the shutdown sequence will be:
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * idle both cpus then shut them off.
29949e866e40b95795203f3ee46f44a197c946e4stevel * it looks like the hardware gets corrupted if one
29949e866e40b95795203f3ee46f44a197c946e4stevel * cpu is busy while the other is shutting down...
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((cpa = cpu_get(FHC_BOARD2CPU_A(board))) != NULL &&
29949e866e40b95795203f3ee46f44a197c946e4stevel cpu_is_active(cpa)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if (!cpu_intr_on(cpa)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cpu_intr_enable(cpa);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((error = cpu_offline(cpa, cpu_flags)) != 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN,
29949e866e40b95795203f3ee46f44a197c946e4stevel "Processor %d failed to offline.",
29949e866e40b95795203f3ee46f44a197c946e4stevel cpa->cpu_id);
29949e866e40b95795203f3ee46f44a197c946e4stevel if (errbuf != NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) snprintf(errbuf, SYSC_OUTPUT_LEN,
29949e866e40b95795203f3ee46f44a197c946e4stevel "processor %d failed to offline",
29949e866e40b95795203f3ee46f44a197c946e4stevel cpa->cpu_id);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (error == 0 &&
29949e866e40b95795203f3ee46f44a197c946e4stevel (cpb = cpu_get(FHC_BOARD2CPU_B(board))) != NULL &&
29949e866e40b95795203f3ee46f44a197c946e4stevel cpu_is_active(cpb)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if (!cpu_intr_on(cpb)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cpu_intr_enable(cpb);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((error = cpu_offline(cpb, cpu_flags)) != 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN,
29949e866e40b95795203f3ee46f44a197c946e4stevel "Processor %d failed to offline.",
29949e866e40b95795203f3ee46f44a197c946e4stevel cpb->cpu_id);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (errbuf != NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) snprintf(errbuf, SYSC_OUTPUT_LEN,
29949e866e40b95795203f3ee46f44a197c946e4stevel "processor %d failed to offline",
29949e866e40b95795203f3ee46f44a197c946e4stevel cpb->cpu_id);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (error == 0 && cpa != NULL && cpu_is_offline(cpa)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((error = cpu_poweroff(cpa)) != 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN,
29949e866e40b95795203f3ee46f44a197c946e4stevel "Processor %d failed to power off.",
29949e866e40b95795203f3ee46f44a197c946e4stevel cpa->cpu_id);
29949e866e40b95795203f3ee46f44a197c946e4stevel if (errbuf != NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) snprintf(errbuf, SYSC_OUTPUT_LEN,
29949e866e40b95795203f3ee46f44a197c946e4stevel "processor %d failed to power off",
29949e866e40b95795203f3ee46f44a197c946e4stevel cpa->cpu_id);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_NOTE, "Processor %d powered off.",
29949e866e40b95795203f3ee46f44a197c946e4stevel cpa->cpu_id);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (error == 0 && cpb != NULL && cpu_is_offline(cpb)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((error = cpu_poweroff(cpb)) != 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN,
29949e866e40b95795203f3ee46f44a197c946e4stevel "Processor %d failed to power off.",
29949e866e40b95795203f3ee46f44a197c946e4stevel cpb->cpu_id);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (errbuf != NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) snprintf(errbuf, SYSC_OUTPUT_LEN,
29949e866e40b95795203f3ee46f44a197c946e4stevel "processor %d failed to power off",
29949e866e40b95795203f3ee46f44a197c946e4stevel cpb->cpu_id);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_NOTE, "Processor %d powered off.",
29949e866e40b95795203f3ee46f44a197c946e4stevel cpb->cpu_id);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * If all the shutdowns completed, ONLY THEN, clear the
29949e866e40b95795203f3ee46f44a197c946e4stevel * incorrectly valid dtags...
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * IMPORTANT: it is an error to read or write dtags while
29949e866e40b95795203f3ee46f44a197c946e4stevel * they are 'active'
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (error == 0 && (cpa != NULL || cpb != NULL)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel u_longlong_t base = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel int i;
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef DEBUG
29949e866e40b95795203f3ee46f44a197c946e4stevel int nonz0 = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel int nonz1 = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif
29949e866e40b95795203f3ee46f44a197c946e4stevel if (cpa != NULL)
29949e866e40b95795203f3ee46f44a197c946e4stevel base = FHC_DTAG_BASE(cpa->cpu_id);
29949e866e40b95795203f3ee46f44a197c946e4stevel if (cpb != NULL)
29949e866e40b95795203f3ee46f44a197c946e4stevel base = FHC_DTAG_BASE(cpb->cpu_id);
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(base != 0);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < FHC_DTAG_SIZE; i += FHC_DTAG_SKIP) {
29949e866e40b95795203f3ee46f44a197c946e4stevel u_longlong_t value = lddphysio(base+i);
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef lint
29949e866e40b95795203f3ee46f44a197c946e4stevel value = value;
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef DEBUG
29949e866e40b95795203f3ee46f44a197c946e4stevel if (cpa != NULL && (value & FHC_DTAG_LOW))
29949e866e40b95795203f3ee46f44a197c946e4stevel nonz0++;
29949e866e40b95795203f3ee46f44a197c946e4stevel if (cpb != NULL && (value & FHC_DTAG_HIGH))
29949e866e40b95795203f3ee46f44a197c946e4stevel nonz1++;
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif
29949e866e40b95795203f3ee46f44a197c946e4stevel /* always clear the dtags */
29949e866e40b95795203f3ee46f44a197c946e4stevel stdphysio(base + i, 0ull);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef DEBUG
29949e866e40b95795203f3ee46f44a197c946e4stevel if (nonz0 || nonz1) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_NOTE, "!dtag results: "
29949e866e40b95795203f3ee46f44a197c946e4stevel "cpua valid %d, cpub valid %d",
29949e866e40b95795203f3ee46f44a197c946e4stevel nonz0, nonz1);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel default:
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel return (error);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * platform code for shutting down cpus.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelint
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_cpu_poweroff(struct cpu *cp)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel int board;
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bd_t *bd_list;
29949e866e40b95795203f3ee46f44a197c946e4stevel int delays;
29949e866e40b95795203f3ee46f44a197c946e4stevel extern void idle_stop_xcall(void);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(MUTEX_HELD(&cpu_lock));
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT((cp->cpu_flags & (CPU_EXISTS | CPU_OFFLINE | CPU_QUIESCED)) ==
193974072f41a843678abf5f61979c748687e66bSherry Moore (CPU_EXISTS | CPU_OFFLINE | CPU_QUIESCED));
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Lock the board so that we can safely access the
29949e866e40b95795203f3ee46f44a197c946e4stevel * registers. This cannot be done inside the pause_cpus().
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel board = FHC_CPU2BOARD(cp->cpu_id);
29949e866e40b95795203f3ee46f44a197c946e4stevel bd_list = fhc_bdlist_lock(board);
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(fhc_bd_valid(board) && (bd_list->sc.type == CPU_BOARD));
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Capture all CPUs (except for detaching proc) to prevent
29949e866e40b95795203f3ee46f44a197c946e4stevel * crosscalls to the detaching proc until it has cleared its
29949e866e40b95795203f3ee46f44a197c946e4stevel * bit in cpu_ready_set.
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * The CPU's remain paused and the prom_mutex is known to be free.
29949e866e40b95795203f3ee46f44a197c946e4stevel * This prevents the x-trap victim from blocking when doing prom
29949e866e40b95795203f3ee46f44a197c946e4stevel * IEEE-1275 calls at a high PIL level.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel promsafe_pause_cpus();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Quiesce interrupts on the target CPU. We do this by setting
29949e866e40b95795203f3ee46f44a197c946e4stevel * the CPU 'not ready'- (i.e. removing the CPU from cpu_ready_set) to
29949e866e40b95795203f3ee46f44a197c946e4stevel * prevent it from receiving cross calls and cross traps.
29949e866e40b95795203f3ee46f44a197c946e4stevel * This prevents the processor from receiving any new soft interrupts.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel mp_cpu_quiesce(cp);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel xt_one_unchecked(cp->cpu_id, (xcfunc_t *)idle_stop_xcall,
193974072f41a843678abf5f61979c748687e66bSherry Moore (uint64_t)fhc_cpu_shutdown_self, (uint64_t)NULL);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Wait for slave cpu to shutdown.
29949e866e40b95795203f3ee46f44a197c946e4stevel * Sense this by watching the hardware EPDx bit.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (delays = FHC_SHUTDOWN_WAIT_MSEC; delays != 0; delays--) {
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t temp;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel DELAY(1000);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* get the current cpu power status */
29949e866e40b95795203f3ee46f44a197c946e4stevel temp = *bd_list->softsp->ctrl;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* has the cpu actually signalled shutdown? */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (FHC_CPU_IS_A(cp->cpu_id)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if (temp & FHC_EPDA_OFF)
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel if (temp & FHC_EPDB_OFF)
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel start_cpus();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bdlist_unlock();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* A timeout means we've lost control of the cpu. */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (delays == 0)
29949e866e40b95795203f3ee46f44a197c946e4stevel panic("Processor %d failed during shutdown", cp->cpu_id);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel return (0);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * shutdown_self
29949e866e40b95795203f3ee46f44a197c946e4stevel * slave side shutdown. clean up and execute the shutdown sequence.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_cpu_shutdown_self(void)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel extern void flush_windows(void);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel flush_windows();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(CPU->cpu_intr_actv == 0);
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(CPU->cpu_thread == CPU->cpu_idle_thread ||
29949e866e40b95795203f3ee46f44a197c946e4stevel CPU->cpu_thread == CPU->cpu_startup_thread);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel CPU->cpu_flags = CPU_POWEROFF | CPU_OFFLINE | CPU_QUIESCED;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) prom_sunfire_cpu_off(); /* inform Ultra Enterprise prom */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel os_completes_shutdown();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel panic("fhc_cpu_shutdown_self: cannot return");
29949e866e40b95795203f3ee46f44a197c946e4stevel /*NOTREACHED*/
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Warm start CPU.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_cpu_start(struct cpu *cp)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel int rv;
29949e866e40b95795203f3ee46f44a197c946e4stevel int cpuid = cp->cpu_id;
29949e866e40b95795203f3ee46f44a197c946e4stevel pnode_t nodeid;
29949e866e40b95795203f3ee46f44a197c946e4stevel extern void restart_other_cpu(int);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(MUTEX_HELD(&cpu_lock));
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* power on cpu */
29949e866e40b95795203f3ee46f44a197c946e4stevel nodeid = cpunodes[cpuid].nodeid;
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(nodeid != (pnode_t)0);
29949e866e40b95795203f3ee46f44a197c946e4stevel rv = prom_wakeupcpu(nodeid);
29949e866e40b95795203f3ee46f44a197c946e4stevel if (rv != 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "Processor %d failed to power on.", cpuid);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EBUSY);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel cp->cpu_flags &= ~CPU_POWEROFF;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * NOTE: restart_other_cpu pauses cpus during the slave cpu start.
29949e866e40b95795203f3ee46f44a197c946e4stevel * This helps to quiesce the bus traffic a bit which makes
29949e866e40b95795203f3ee46f44a197c946e4stevel * the tick sync routine in the prom more robust.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel restart_other_cpu(cpuid);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel return (0);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Power on CPU.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelint
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_cpu_poweron(struct cpu *cp)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bd_t *bd_list;
29949e866e40b95795203f3ee46f44a197c946e4stevel enum temp_state state;
29949e866e40b95795203f3ee46f44a197c946e4stevel int board;
29949e866e40b95795203f3ee46f44a197c946e4stevel int status;
29949e866e40b95795203f3ee46f44a197c946e4stevel int status_other;
29949e866e40b95795203f3ee46f44a197c946e4stevel struct cpu *cp_other;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(MUTEX_HELD(&cpu_lock));
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(cpu_is_poweredoff(cp));
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* do not power on overtemperature cpu */
29949e866e40b95795203f3ee46f44a197c946e4stevel board = FHC_CPU2BOARD(cp->cpu_id);
29949e866e40b95795203f3ee46f44a197c946e4stevel bd_list = fhc_bdlist_lock(board);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(bd_list != NULL);
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(bd_list->sc.type == CPU_BOARD);
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(bd_list->dev_softsp != NULL);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel state = ((struct environ_soft_state *)
193974072f41a843678abf5f61979c748687e66bSherry Moore bd_list->dev_softsp)->tempstat.state;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bdlist_unlock();
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((state == TEMP_WARN) || (state == TEMP_DANGER))
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EBUSY);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel status = fhc_cpu_start(cp);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* policy for dual cpu boards */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((status == 0) &&
29949e866e40b95795203f3ee46f44a197c946e4stevel ((cp_other = cpu_get(FHC_OTHER_CPU_ID(cp->cpu_id))) != NULL)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Do not leave board's other cpu idling in the prom.
29949e866e40b95795203f3ee46f44a197c946e4stevel * Start the other cpu and set its state to P_OFFLINE.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel status_other = fhc_cpu_start(cp_other);
29949e866e40b95795203f3ee46f44a197c946e4stevel if (status_other != 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel panic("fhc: failed to start second CPU"
29949e866e40b95795203f3ee46f44a197c946e4stevel " in pair %d & %d, error %d",
29949e866e40b95795203f3ee46f44a197c946e4stevel cp->cpu_id, cp_other->cpu_id, status_other);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel return (status);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * complete the shutdown sequence in case the firmware doesn't.
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * If the firmware returns, then complete the shutdown code.
29949e866e40b95795203f3ee46f44a197c946e4stevel * (sunfire firmware presently only updates its status. the
29949e866e40b95795203f3ee46f44a197c946e4stevel * OS must flush the D-tags and execute the shutdown instruction.)
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void
29949e866e40b95795203f3ee46f44a197c946e4stevelos_completes_shutdown(void)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel pfn_t pfn;
29949e866e40b95795203f3ee46f44a197c946e4stevel tte_t tte;
29949e866e40b95795203f3ee46f44a197c946e4stevel volatile uint_t *src;
29949e866e40b95795203f3ee46f44a197c946e4stevel volatile uint_t *dst;
29949e866e40b95795203f3ee46f44a197c946e4stevel caddr_t copy_addr;
29949e866e40b95795203f3ee46f44a197c946e4stevel extern void fhc_shutdown_asm(u_longlong_t, int);
29949e866e40b95795203f3ee46f44a197c946e4stevel extern void fhc_shutdown_asm_end(void);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel copy_addr = shutdown_va + FHC_SRAM_OS_OFFSET;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* compute sram global address for this operation */
29949e866e40b95795203f3ee46f44a197c946e4stevel pfn = FHC_LOCAL_OS_PAGEBASE >> MMU_PAGESHIFT;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* force load i and d translations */
29949e866e40b95795203f3ee46f44a197c946e4stevel tte.tte_inthi = TTE_VALID_INT | TTE_SZ_INT(TTE8K) |
193974072f41a843678abf5f61979c748687e66bSherry Moore TTE_PFN_INTHI(pfn);
29949e866e40b95795203f3ee46f44a197c946e4stevel tte.tte_intlo = TTE_PFN_INTLO(pfn) |
193974072f41a843678abf5f61979c748687e66bSherry Moore TTE_HWWR_INT | TTE_PRIV_INT | TTE_LCK_INT; /* un$ */
1e2e7a75ddb1eedcefa449ce98fd5862749b72eehuah sfmmu_dtlb_ld_kva(shutdown_va, &tte); /* load dtlb */
1e2e7a75ddb1eedcefa449ce98fd5862749b72eehuah sfmmu_itlb_ld_kva(shutdown_va, &tte); /* load itlb */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * copy the special shutdown function to sram
29949e866e40b95795203f3ee46f44a197c946e4stevel * (this is a special integer copy that synchronizes with localspace
29949e866e40b95795203f3ee46f44a197c946e4stevel * accesses. we need special throttling to ensure copy integrity)
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (src = (uint_t *)fhc_shutdown_asm, dst = (uint_t *)copy_addr;
29949e866e40b95795203f3ee46f44a197c946e4stevel src < (uint_t *)fhc_shutdown_asm_end;
29949e866e40b95795203f3ee46f44a197c946e4stevel src++, dst++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel volatile uint_t dummy;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel *dst = *src;
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * ensure non corrupting single write operations to
29949e866e40b95795203f3ee46f44a197c946e4stevel * localspace sram by interleaving reads with writes.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel dummy = *dst;
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef lint
29949e866e40b95795203f3ee46f44a197c946e4stevel dummy = dummy;
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Call the shutdown sequencer.
29949e866e40b95795203f3ee46f44a197c946e4stevel * NOTE: the base flush address must be unique for each MID.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel ((void (*)(u_longlong_t, int))copy_addr)(
193974072f41a843678abf5f61979c748687e66bSherry Moore FHC_BASE_NOMEM + CPU->cpu_id * FHC_MAX_ECACHE_SIZE,
193974072f41a843678abf5f61979c748687e66bSherry Moore cpunodes[CPU->cpu_id].ecache_size);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelenum temp_state
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_env_temp_state(int board)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bd_t *bdp;
29949e866e40b95795203f3ee46f44a197c946e4stevel struct environ_soft_state *envp;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(fhc_bd_valid(board));
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel bdp = fhc_bd(board);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Due to asynchronous attach of environ, environ may
29949e866e40b95795203f3ee46f44a197c946e4stevel * not be attached by the time we start calling this routine
29949e866e40b95795203f3ee46f44a197c946e4stevel * to check the temperature state. Environ not attaching is
29949e866e40b95795203f3ee46f44a197c946e4stevel * pathological so this will only cover the time between
29949e866e40b95795203f3ee46f44a197c946e4stevel * board connect and environ attach.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (!bdp->dev_softsp) {
29949e866e40b95795203f3ee46f44a197c946e4stevel return (TEMP_OK);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel envp = (struct environ_soft_state *)bdp->dev_softsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel return (envp->tempstat.state);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_tod_fault(enum tod_fault_type tod_bad)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel int board_num = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel enum ft_class class = FT_SYSTEM;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint64_t addr;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel addr = (va_to_pa((void *)v_eeprom_addr)) >> BOARD_PHYADDR_SHIFT;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((addr & CLOCKBOARD_PHYADDR_BITS) != CLOCKBOARD_PHYADDR_BITS) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* if tod is not on clock board, */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* it'd be on one of io boards */
29949e866e40b95795203f3ee46f44a197c946e4stevel board_num = (addr >> IO_BOARD_NUMBER_SHIFT)
193974072f41a843678abf5f61979c748687e66bSherry Moore & IO_BOARD_NUMBER_MASK;
29949e866e40b95795203f3ee46f44a197c946e4stevel class = FT_BOARD;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel switch (tod_bad) {
29949e866e40b95795203f3ee46f44a197c946e4stevel case TOD_NOFAULT:
29949e866e40b95795203f3ee46f44a197c946e4stevel clear_fault(board_num, FT_TODFAULT, class);
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel case TOD_REVERSED:
29949e866e40b95795203f3ee46f44a197c946e4stevel case TOD_STALLED:
29949e866e40b95795203f3ee46f44a197c946e4stevel case TOD_JUMPED:
29949e866e40b95795203f3ee46f44a197c946e4stevel case TOD_RATECHANGED:
29949e866e40b95795203f3ee46f44a197c946e4stevel reg_fault(board_num, FT_TODFAULT, class);
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel default:
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel}