29949e866e40b95795203f3ee46f44a197c946e4stevel * CDDL HEADER START
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 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
29949e866e40b95795203f3ee46f44a197c946e4stevel * See the License for the specific language governing permissions
29949e866e40b95795203f3ee46f44a197c946e4stevel * and limitations under the License.
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 * CDDL HEADER END
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
29949e866e40b95795203f3ee46f44a197c946e4stevel * Use is subject to license terms.
29949e866e40b95795203f3ee46f44a197c946e4stevel * Function to register and deregister callbacks, for sunfire only.
29949e866e40b95795203f3ee46f44a197c946e4stevelextern void plat_register_tod_fault(void (*func)(enum tod_fault_type));
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.
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 * 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/* Only one processor should powerdown the system. */
29949e866e40b95795203f3ee46f44a197c946e4stevel/* Let user disable overtemp powerdown. */
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#define CPU_MX_CNT (sizeof (cpu_table)/sizeof (short))
29949e866e40b95795203f3ee46f44a197c946e4stevel#define CPU2_MX_CNT (sizeof (cpu2_table)/sizeof (short))
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, 0, 0, 0, 0, 0, 0, 0, /* 0-7 */
29949e866e40b95795203f3ee46f44a197c946e4stevel#define CLK_MX_CNT (sizeof (clock_table)/sizeof (short))
29949e866e40b95795203f3ee46f44a197c946e4stevel * System temperature limits.
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 * 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 * These values can be tuned via /etc/system or boot -h.
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 */
29949e866e40b95795203f3ee46f44a197c946e4stevelshort dft_warn_temp = 60; /* default warning temp value */
29949e866e40b95795203f3ee46f44a197c946e4stevelshort dft_danger_temp = 68; /* default danger temp value */
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 * 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 * The fhc memloc structure is protected under the bdlist lock
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 * 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.
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int ft_max_index = (sizeof (ft_str_table) / sizeof (char *));
29949e866e40b95795203f3ee46f44a197c946e4stevel * Function prototypes
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);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int fhc_add_intr_impl(dev_info_t *dip, dev_info_t *rdip,
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void fhc_remove_intr_impl(dev_info_t *dip, dev_info_t *rdip,
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 void fhc_unmap_regs(struct fhc_soft_state *softsp);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic enum board_type fhc_board_type(struct fhc_soft_state *, int);
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_xlate_intrs(ddi_intr_handle_impl_t *hdlp, uint32_t ign);
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_ctlops_peekpoke(ddi_ctl_enum_t, peekpoke_ctlops_t *, void *result);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int check_for_chamber(void);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int ft_ks_snapshot(struct kstat *, void *, int);
29949e866e40b95795203f3ee46f44a197c946e4stevel * board type and A/D convertor output passed in and real temperature
29949e866e40b95795203f3ee46f44a197c946e4stevel * is returned.
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic short calibrate_temp(enum board_type, uchar_t, uint_t);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic enum temp_state get_temp_state(enum board_type, short, int);
29949e866e40b95795203f3ee46f44a197c946e4stevel/* Routine to determine if there are CPUs on this board. */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int cpu_on_board(int);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void build_bd_display_str(char *, enum board_type, int);
29949e866e40b95795203f3ee46f44a197c946e4stevel/* Interrupt distribution callback function. */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void fhc_intrdist(void *);
29949e866e40b95795203f3ee46f44a197c946e4stevel/* CPU power control */
29949e866e40b95795203f3ee46f44a197c946e4stevelint fhc_cpu_poweroff(struct cpu *); /* cpu_poweroff()->platform */
29949e866e40b95795203f3ee46f44a197c946e4stevelint fhc_cpu_poweron(struct cpu *); /* cpu_poweron()->platform */
29949e866e40b95795203f3ee46f44a197c946e4stevelextern void halt(char *);
29949e866e40b95795203f3ee46f44a197c946e4stevel * Configuration data structures
29949e866e40b95795203f3ee46f44a197c946e4stevel 0, /* get_intrspec */
29949e866e40b95795203f3ee46f44a197c946e4stevel 0, /* add_intrspec */
29949e866e40b95795203f3ee46f44a197c946e4stevel 0, /* remove_intrspec */
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 0, /* streamtab */
29949e866e40b95795203f3ee46f44a197c946e4stevel D_MP|D_NEW|D_HOTPLUG, /* Driver compatibility flag */
29949e866e40b95795203f3ee46f44a197c946e4stevel 0, /* refcnt */
29949e866e40b95795203f3ee46f44a197c946e4stevel * Driver globals
29949e866e40b95795203f3ee46f44a197c946e4stevel * TODO - We need to investigate what locking needs to be done here.
29949e866e40b95795203f3ee46f44a197c946e4stevel &mod_driverops, /* Type of module. This one is a driver */
29949e866e40b95795203f3ee46f44a197c946e4stevel * These are the module initialization routines.
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_init(&ftlist_mutex, NULL, MUTEX_DEFAULT, NULL);
29949e866e40b95795203f3ee46f44a197c946e4stevel shutdown_va = vmem_alloc(heap_arena, PAGESIZE, VM_SLEEP);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (0);
29949e866e40b95795203f3ee46f44a197c946e4stevel * Reset the interrupt mapping registers.
29949e866e40b95795203f3ee46f44a197c946e4stevel * This function resets the values during DDI_RESUME.
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 * 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 /* We must now re-issue any pending interrupts. */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < FHC_MAX_INO; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(softsp->list->sc.board == FHC_BSR_TO_BD(*(softsp->bsr)));
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Loop through all 4 FHC interrupt mapping registers */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < FHC_MAX_INO; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel "found lost system interrupt, resetting..");
29949e866e40b95795203f3ee46f44a197c946e4stevel * ensure atomic write with this read.
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 * ensure atomic write with this read.
29949e866e40b95795203f3ee46f44a197c946e4stevel * This is the value of AC configuration and status reg
29949e866e40b95795203f3ee46f44a197c946e4stevel * in the Local Devices space. We access it as a physical
29949e866e40b95795203f3ee46f44a197c946e4stevel /* IGR, NOT_BRD_PRES handled by prom */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* reset interrupt mapping registers */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ddi_soft_state_zalloc(fhcp, instance) != DDI_SUCCESS)
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Set the dip in the soft state */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* get the instance of this devi */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* get the soft state pointer for this device node */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* grab the lock on the board list */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* FALLTHROUGH */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Remove the interrupt redistribution callback. */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* remove the soft state pointer from the board list */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* clear inherited faults from the PROM. */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* remove the kstat for this board */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* destroy the mutexes in this soft state structure */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* unmap all the register sets */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* release the board list lock now */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* free the soft state structure */
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_board_type(struct fhc_soft_state *softsp, int board)
29949e866e40b95795203f3ee46f44a197c946e4stevel DDI_PROP_DONTPASS, "board-type", (caddr_t)&board_type,
29949e866e40b95795203f3ee46f44a197c946e4stevel /* match the board-type string */
29949e866e40b95795203f3ee46f44a197c946e4stevel } else if (strcmp(IO_2SBUS_BD_NAME, board_type) == 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel } else if (strcmp(IO_SBUS_FFB_BD_NAME, board_type) == 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel } else if (strcmp(IO_2SBUS_SOCPLUS_BD_NAME, board_type) == 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel } else if (strcmp(IO_SBUS_FFB_SOCPLUS_BD_NAME, board_type)
29949e866e40b95795203f3ee46f44a197c946e4stevel } else if (strcmp(IO_PCI_BD_NAME, board_type) == 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel * if the board type is indeterminate, it must be determined.
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 ddi_unmap_regs(dip, 0, (caddr_t *)&softsp->id, 0, 0);
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_unmap_regs(dip, 1, (caddr_t *)&softsp->igr, 0, 0);
29949e866e40b95795203f3ee46f44a197c946e4stevel if (softsp->intr_regs[FHC_FANFAIL_INO].mapping_reg) {
193974072f41a843678abf5f61979c748687e66bSherry Moore (caddr_t *)&softsp->intr_regs[FHC_FANFAIL_INO].mapping_reg,
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->intr_regs[FHC_FANFAIL_INO].mapping_reg = NULL;
193974072f41a843678abf5f61979c748687e66bSherry Moore (caddr_t *)&softsp->intr_regs[FHC_SYS_INO].mapping_reg,
193974072f41a843678abf5f61979c748687e66bSherry Moore (caddr_t *)&softsp->intr_regs[FHC_UART_INO].mapping_reg,
193974072f41a843678abf5f61979c748687e66bSherry Moore (caddr_t *)&softsp->intr_regs[FHC_TOD_INO].mapping_reg,
29949e866e40b95795203f3ee46f44a197c946e4stevel * Map in the FHC registers. Specifying length and offset of
29949e866e40b95795203f3ee46f44a197c946e4stevel * zero maps in the entire OBP register set.
29949e866e40b95795203f3ee46f44a197c946e4stevel /* map in register set 0 */
29949e866e40b95795203f3ee46f44a197c946e4stevel * Fill in the virtual addresses of the registers in the
29949e866e40b95795203f3ee46f44a197c946e4stevel * fhc_soft_state structure.
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->jtag_ctrl = (uint_t *)((char *)(softsp->id) +
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->jt_master.jtag_cmd = (uint_t *)((char *)(softsp->id) +
29949e866e40b95795203f3ee46f44a197c946e4stevel /* map in register set 1 */
29949e866e40b95795203f3ee46f44a197c946e4stevel * map in register set 2
29949e866e40b95795203f3ee46f44a197c946e4stevel * XXX this can never be used as an interrupt generator
29949e866e40b95795203f3ee46f44a197c946e4stevel * (hardware queue overflow in fhc)
29949e866e40b95795203f3ee46f44a197c946e4stevel (caddr_t *)&softsp->intr_regs[FHC_FANFAIL_INO].mapping_reg,
193974072f41a843678abf5f61979c748687e66bSherry Moore "IMR register", ddi_get_instance(softsp->dip));
29949e866e40b95795203f3ee46f44a197c946e4stevel /* map in register set 3 */
29949e866e40b95795203f3ee46f44a197c946e4stevel (caddr_t *)&softsp->intr_regs[FHC_SYS_INO].mapping_reg,
193974072f41a843678abf5f61979c748687e66bSherry Moore "IMR register\n", ddi_get_instance(softsp->dip));
29949e866e40b95795203f3ee46f44a197c946e4stevel /* map in register set 4 */
29949e866e40b95795203f3ee46f44a197c946e4stevel (caddr_t *)&softsp->intr_regs[FHC_UART_INO].mapping_reg,
193974072f41a843678abf5f61979c748687e66bSherry Moore "IMR register\n", ddi_get_instance(softsp->dip));
29949e866e40b95795203f3ee46f44a197c946e4stevel /* map in register set 5 */
29949e866e40b95795203f3ee46f44a197c946e4stevel (caddr_t *)&softsp->intr_regs[FHC_TOD_INO].mapping_reg,
193974072f41a843678abf5f61979c748687e66bSherry Moore "IMR register", ddi_get_instance(softsp->dip));
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++) {
193974072f41a843678abf5f61979c748687e66bSherry Moore (uint_t *)((char *)(softsp->intr_regs[i].mapping_reg) +
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Now clear the state machines to idle */
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 if ((board = (int)ddi_getprop(DDI_DEV_T_ANY, softsp->dip,
29949e866e40b95795203f3ee46f44a197c946e4stevel * Now determine the board number by reading the
29949e866e40b95795203f3ee46f44a197c946e4stevel * hardware register.
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 if ((*(softsp->jtag_ctrl) & JTAG_MASTER_EN) && !softsp->is_central) {
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_init(&(softsp->jt_master.lock), NULL, MUTEX_DEFAULT,
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bd_init(softsp, board, fhc_board_type(softsp, board));
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Initialize the mutex guarding the poll_list. */
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_init(&softsp->poll_list_lock, NULL, MUTEX_DRIVER, NULL);
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Initialize the mutex guarding the FHC CSR */
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_init(&softsp->ctrl_lock, NULL, MUTEX_DRIVER, NULL);
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Initialize the poll_list to be empty */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < MAX_ZS_CNT; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Modify the various registers in the FHC now */
29949e866e40b95795203f3ee46f44a197c946e4stevel * We know this board to be present now, record that state and
29949e866e40b95795203f3ee46f44a197c946e4stevel * remove the NOT_BRD_PRES condition
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Now flush the hardware store buffers. */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* XXX record the board state in global space */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Add kstats for all non-central instances of the FHC. */
29949e866e40b95795203f3ee46f44a197c946e4stevel * Read the device tree to see if this system is in an environmental
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Check for inherited faults from the PROM. */
29949e866e40b95795203f3ee46f44a197c946e4stevel reg_fault(softsp->list->sc.board, FT_PROM, FT_BOARD);
29949e866e40b95795203f3ee46f44a197c946e4stevel * setup the IGR. Shift the board number over by one to get
29949e866e40b95795203f3ee46f44a197c946e4stevel * the UPA MID.
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Now flush the hardware store buffers. */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Add the interrupt redistribution callback. */
29949e866e40b95795203f3ee46f44a197c946e4stevel struct fhc_wrapper_arg *intr_info = (struct fhc_wrapper_arg *)arg;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t (*funcp)(caddr_t, caddr_t) = intr_info->funcp;
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Idle the state machine. */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Flush the hardware store buffers. */
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif /* lint */
29949e866e40b95795203f3ee46f44a197c946e4stevel * fhc_zs_intr_wrapper
29949e866e40b95795203f3ee46f44a197c946e4stevel * This function handles intrerrupts where more than one device may interupt
29949e866e40b95795203f3ee46f44a197c946e4stevel * the fhc with the same mondo.
29949e866e40b95795203f3ee46f44a197c946e4stevel struct fhc_soft_state *softsp = (struct fhc_soft_state *)arg;
29949e866e40b95795203f3ee46f44a197c946e4stevel caddr_t funcp0_arg1, funcp0_arg2, funcp1_arg1, funcp1_arg2;
29949e866e40b95795203f3ee46f44a197c946e4stevel clear_reg = softsp->intr_regs[FHC_UART_INO].clear_reg;
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((funcp0)(funcp0_arg1, funcp0_arg2) == DDI_INTR_CLAIMED) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((funcp1)(funcp1_arg1, funcp1_arg2) == DDI_INTR_CLAIMED) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Idle the state machine. */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* flush the store buffers. */
29949e866e40b95795203f3ee46f44a197c946e4stevel * add_intrspec - Add an interrupt specification.
29949e866e40b95795203f3ee46f44a197c946e4stevel struct fhc_soft_state *softsp = (struct fhc_soft_state *)
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Xlate the interrupt */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* get the mondo number */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* We don't use the two spare interrupts. */
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "fhc%d: Spare interrupt %d not usable",
29949e866e40b95795203f3ee46f44a197c946e4stevel /* TOD and Fan Fail interrupts are not usable */
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "fhc%d: Fan fail interrupt not usable",
29949e866e40b95795203f3ee46f44a197c946e4stevel * If the interrupt is for the zs chips, use the vector
29949e866e40b95795203f3ee46f44a197c946e4stevel * polling lists. Otherwise use a straight handler.
29949e866e40b95795203f3ee46f44a197c946e4stevel /* First lock the mutex for this poll_list */
29949e866e40b95795203f3ee46f44a197c946e4stevel * Add this interrupt to the polling list.
29949e866e40b95795203f3ee46f44a197c946e4stevel /* figure out where to add this item in the list */
29949e866e40b95795203f3ee46f44a197c946e4stevel "fhc%d: poll list overflow",
29949e866e40b95795203f3ee46f44a197c946e4stevel * If polling list is empty, then install handler
29949e866e40b95795203f3ee46f44a197c946e4stevel * and enable interrupts for this ino.
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 /* now release the mutex and return */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* just release the mutex */
29949e866e40b95795203f3ee46f44a197c946e4stevel } else { /* normal interrupt installation */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Allocate a nexus interrupt data structure */
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_arg = kmem_alloc(sizeof (struct fhc_wrapper_arg), KM_SLEEP);
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_arg->clear_reg = (softsp->intr_regs[ino].clear_reg);
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < FHC_MAX_INO; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel * Save the fhc_arg in the ispec so we can use this info
29949e866e40b95795203f3ee46f44a197c946e4stevel * later to uninstall this interrupt spec.
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 * Since all FHC interrupts are level interrupts, any
29949e866e40b95795203f3ee46f44a197c946e4stevel * real interrupting condition will immediately transition
29949e866e40b95795203f3ee46f44a197c946e4stevel * the ISM back to pending.
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 /* don't do this for fan because fan has a special control */
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki ("Mondo 0x%x mapping reg: 0x%p", hdlp->ih_vector,
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Store it in the hardware reg. */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Read a FHC register to flush store buffers */
29949e866e40b95795203f3ee46f44a197c946e4stevel * remove_intrspec - Remove an interrupt specification.
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_remove_intr_impl(dev_info_t *dip, dev_info_t *rdip,
29949e866e40b95795203f3ee46f44a197c946e4stevel struct fhc_soft_state *softsp = (struct fhc_soft_state *)
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_get_soft_state(fhcp, ddi_get_instance(dip));
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Xlate the interrupt */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* get the mondo number */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Lock the poll_list first */
29949e866e40b95795203f3ee46f44a197c946e4stevel * Find which entry in the poll list belongs to this
29949e866e40b95795203f3ee46f44a197c946e4stevel * intrspec.
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < MAX_ZS_CNT; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* If we did not find an entry, then we have a problem */
29949e866e40b95795203f3ee46f44a197c946e4stevel * If we have removed all active entries for the poll
29949e866e40b95795203f3ee46f44a197c946e4stevel * list, then we have to disable interupts at this point.
29949e866e40b95795203f3ee46f44a197c946e4stevel /* flush the hardware buffers */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Eliminate the particular handler from the system. */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < FHC_MAX_INO; i++)
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Turn off the valid bit in the mapping register. */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* XXX what about FHC_FANFAIL owned imr? */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* flush the hardware store buffers */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Eliminate the particular handler from the system. */
29949e866e40b95795203f3ee46f44a197c946e4stevel sizeof (struct fhc_wrapper_arg));
29949e866e40b95795203f3ee46f44a197c946e4stevel/* new intr_ops structure */
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op,
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Xlate the interrupt */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* only support fixed interrupts */
29949e866e40b95795203f3ee46f44a197c946e4stevel ret = i_ddi_intr_ops(dip, rdip, intr_op, hdlp, result);
29949e866e40b95795203f3ee46f44a197c946e4stevel * FHC Control Ops routine
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 switch (op) {
29949e866e40b95795203f3ee46f44a197c946e4stevel DPRINTF(FHC_CTLOPS_DEBUG, ("DDI_CTLOPS_INITCHILD\n"));
29949e866e40b95795203f3ee46f44a197c946e4stevel return (impl_ddi_sunbus_initchild((dev_info_t *)arg));
29949e866e40b95795203f3ee46f44a197c946e4stevel * TODO - Figure out what makes sense to report here.
29949e866e40b95795203f3ee46f44a197c946e4stevel return (fhc_ctlops_peekpoke(op, (peekpoke_ctlops_t *)arg,
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/* ARGSUSED */
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_xlate_intrs(ddi_intr_handle_impl_t *hdlp, uint32_t ign)
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_ctlops_peekpoke(ddi_ctl_enum_t cmd, peekpoke_ctlops_t *in_args,
29949e866e40b95795203f3ee46f44a197c946e4stevel /* No safe access except for peek/poke is supported. */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Set up protected environment. */
29949e866e40b95795203f3ee46f44a197c946e4stevel err = do_poke(in_args->size, (void *)in_args->dev_addr,
29949e866e40b95795203f3ee46f44a197c946e4stevel err = do_peek(in_args->size, (void *)in_args->dev_addr,
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Take down protected environment. */
29949e866e40b95795203f3ee46f44a197c946e4stevel * This function initializes the temperature arrays for use. All
29949e866e40b95795203f3ee46f44a197c946e4stevel * temperatures are set in to invalid value to start.
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < L1_SZ; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < L2_SZ; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < L3_SZ; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < L4_SZ; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < L5_SZ; i++) {
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 * 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.
29949e866e40b95795203f3ee46f44a197c946e4stevelupdate_temp(dev_info_t *pdip, struct temp_stats *envstat, uchar_t value)
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t tmp_index; /* temp index into upper level array */
29949e866e40b95795203f3ee46f44a197c946e4stevel int total; /* sum total of non-zero values in array */
29949e866e40b95795203f3ee46f44a197c946e4stevel char buffer[256]; /* buffer for warning of overtemp */
29949e866e40b95795203f3ee46f44a197c946e4stevel * NOTE: This global counter is not protected since we're called
29949e866e40b95795203f3ee46f44a197c946e4stevel * serially for each board.
29949e866e40b95795203f3ee46f44a197c946e4stevel static int shutdown_msg = 0; /* Flag if shutdown warning issued */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* determine soft state pointer of parent */
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp = ddi_get_soft_state(fhcp, ddi_get_instance(pdip));
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 /* 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 /* take an average of the level 4 array */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Do not include zero values in average */
29949e866e40b95795203f3ee46f44a197c946e4stevel * If there were any level 4 data points to average,
29949e866e40b95795203f3ee46f44a197c946e4stevel if (count != 0) {
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 /* take an average of the level 3 array */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Do not include zero values in average */
29949e866e40b95795203f3ee46f44a197c946e4stevel * If there were any level 3 data points to average,
29949e866e40b95795203f3ee46f44a197c946e4stevel if (count != 0) {
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 /* take an average of the level 2 array */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Do not include zero values in average */
29949e866e40b95795203f3ee46f44a197c946e4stevel * If there were any level 2 data points to average,
29949e866e40b95795203f3ee46f44a197c946e4stevel if (count != 0) {
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 /* take an average of the level 1 array */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Do not include zero values in average */
29949e866e40b95795203f3ee46f44a197c946e4stevel * If there were any level 1 data points to average,
29949e866e40b95795203f3ee46f44a197c946e4stevel if (count != 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* determine the current temperature in degrees Celcius */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* use override temperature for this board */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Run the calibration function using this board type */
29949e866e40b95795203f3ee46f44a197c946e4stevel real_temp = calibrate_temp(softsp->list->sc.type, value,
29949e866e40b95795203f3ee46f44a197c946e4stevel /* check if the temperature state for this device needs to change */
29949e866e40b95795203f3ee46f44a197c946e4stevel temp_state = get_temp_state(softsp->list->sc.type, real_temp,
29949e866e40b95795203f3ee46f44a197c946e4stevel /* has the state changed? Then get the board string ready */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* heating up, change state now */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* now warn the user of the problem */
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s is warm (temperature: %dC). "
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s is very hot (temperature: %dC)",
29949e866e40b95795203f3ee46f44a197c946e4stevel * NOTE: The "%d seconds" is not
29949e866e40b95795203f3ee46f44a197c946e4stevel * necessarily accurate in the case
29949e866e40b95795203f3ee46f44a197c946e4stevel * where we have multiple boards
29949e866e40b95795203f3ee46f44a197c946e4stevel * overheating and subsequently cooling
193974072f41a843678abf5f61979c748687e66bSherry Moore "shutdown scheduled "
193974072f41a843678abf5f61979c748687e66bSherry Moore "in %d seconds due to "
193974072f41a843678abf5f61979c748687e66bSherry Moore "over-temperature "
193974072f41a843678abf5f61979c748687e66bSherry Moore "condition on %s",
29949e866e40b95795203f3ee46f44a197c946e4stevel * If this is a cpu board, power them off.
29949e866e40b95795203f3ee46f44a197c946e4stevel * Avert the sigpower that would
29949e866e40b95795203f3ee46f44a197c946e4stevel * otherwise be sent to init.
29949e866e40b95795203f3ee46f44a197c946e4stevel /* cooling down, use state counter */
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s is cooling "
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s has cooled down "
193974072f41a843678abf5f61979c748687e66bSherry Moore "(temperature: %dC), system OK",
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
193974072f41a843678abf5f61979c748687e66bSherry Moore "shutdown due to over-"
193974072f41a843678abf5f61979c748687e66bSherry Moore "temperature "
193974072f41a843678abf5f61979c748687e66bSherry Moore "condition cancelled");
29949e866e40b95795203f3ee46f44a197c946e4stevel /* the system is still too hot */
193974072f41a843678abf5f61979c748687e66bSherry Moore "(temperature: %dC)."
29949e866e40b95795203f3ee46f44a197c946e4stevel /* update the maximum and minimum temperatures if necessary */
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((envstat->max == NA_TEMP) || (real_temp > envstat->max)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((envstat->min == NA_TEMP) || (real_temp < envstat->min)) {
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 if (((tmp_index = L2_INDEX(index)) > 0) && (L2_REM(index) == 0)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Issue a warning if the temperature is rising rapidly. */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* For CPU boards, don't warn if CPUs just powered on. */
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "%s temperature is rising rapidly! "
29949e866e40b95795203f3ee46f44a197c946e4stevel#define PREV_L2_INDEX(x) ((x) ? ((x) - 1) : (L2_SZ - 1))
29949e866e40b95795203f3ee46f44a197c946e4stevel * This routine determines if the temp of the device passed in is heating
29949e866e40b95795203f3ee46f44a197c946e4stevel * up, cooling down, or staying stable.
29949e866e40b95795203f3ee46f44a197c946e4stevel curr_index = (L2_INDEX(tempstat->index) - 1) % L2_SZ;
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Count how many temperature readings are available */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (read_cnt = 0; read_cnt < L2_SZ - 1; read_cnt++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel delta = curr_temp - tempstat->l2[PREV_L2_INDEX(curr_index)];
29949e866e40b95795203f3ee46f44a197c946e4stevel } else if (delta <= -RAPID_FALL_THRESH) { /* rapid fall? */
29949e866e40b95795203f3ee46f44a197c946e4stevel * Reboot the system if we can, otherwise attempt a power down
29949e866e40b95795203f3ee46f44a197c946e4stevel /* send a SIGPWR to init process */
29949e866e40b95795203f3ee46f44a197c946e4stevel * If we're still booting and init(1) isn't
29949e866e40b95795203f3ee46f44a197c946e4stevel * set up yet, simply halt.
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 * 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 /* Pull the max and min from Level 1 array */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < L1_SZ; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Pull the max and min from Level 2 array */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < L2_SZ; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Pull the max and min from Level 3 array */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < L3_SZ; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Pull the max and min from Level 4 array */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < L4_SZ; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Pull the max and min from Level 5 array */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < L5_SZ; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel * copy the temperature history buffer into the
29949e866e40b95795203f3ee46f44a197c946e4stevel * kstat structure.
29949e866e40b95795203f3ee46f44a197c946e4stevel return (0);
29949e866e40b95795203f3ee46f44a197c946e4stevel * Kstat reads are used to get the temperature override setting.
29949e866e40b95795203f3ee46f44a197c946e4stevel * Kstat writes are used to set the temperature override setting.
29949e866e40b95795203f3ee46f44a197c946e4stevel return (0);
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.
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic short
29949e866e40b95795203f3ee46f44a197c946e4stevelcalibrate_temp(enum board_type type, uchar_t temp, uint_t ac_comp)
29949e866e40b95795203f3ee46f44a197c946e4stevel return ((short)temp);
29949e866e40b95795203f3ee46f44a197c946e4stevel * If AC chip revision is >= 4 or if it is unitialized,
29949e866e40b95795203f3ee46f44a197c946e4stevel * then use the new calibration tables.
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((CHIP_REV(ac_comp) >= 4) || (CHIP_REV(ac_comp) == 0)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel * Determine the temperature state of this board based on its type and
29949e866e40b95795203f3ee46f44a197c946e4stevel * the actual temperature in degrees Celcius.
29949e866e40b95795203f3ee46f44a197c946e4stevelget_temp_state(enum board_type type, short temp, int board)
29949e866e40b95795203f3ee46f44a197c946e4stevel * For CPU boards with frequency >= 400 MHZ,
29949e866e40b95795203f3ee46f44a197c946e4stevel * temperature zones are different.
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((cpa = cpu_get(FHC_BOARD2CPU_A(board))) != NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((cpb = cpu_get(FHC_BOARD2CPU_B(board))) != NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((fhc_ksp = kstat_create("unix", softsp->list->sc.board,
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_named_ksp = (struct fhc_kstat *)(fhc_ksp->ks_data);
29949e866e40b95795203f3ee46f44a197c946e4stevel /* initialize the named kstats */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* this is a read-only kstat. Bail out on a write */
29949e866e40b95795203f3ee46f44a197c946e4stevel * copy the current state of the hardware into the
29949e866e40b95795203f3ee46f44a197c946e4stevel * kstat structure.
29949e866e40b95795203f3ee46f44a197c946e4stevel return (0);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (1);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (0);
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.
29949e866e40b95795203f3ee46f44a197c946e4stevelupdate_board_leds(fhc_bd_t *board, uint_t mask, uint_t value)
29949e866e40b95795203f3ee46f44a197c946e4stevel /* mask off mask and value for only the LED bits */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* read the current register state */
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 temp &= ~(FHC_CSR_SYNC | FHC_EPDA_OFF | FHC_EPDB_OFF);
29949e866e40b95795203f3ee46f44a197c946e4stevel /* mask off the bits to change */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* or in the new values of the bits. */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* update the register */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* flush the hardware registers */
29949e866e40b95795203f3ee46f44a197c946e4stevel * The operator can disable overtemp powerdown from /etc/system or
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "Operator has disabled overtemp powerdown");
29949e866e40b95795203f3ee46f44a197c946e4stevel return (1);
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 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 retval = prom_getprop(options_node_id, "mfg-mode", mfgmode);
193974072f41a843678abf5f61979c748687e66bSherry Moore " Chamber Mode. Overtemperature"
193974072f41a843678abf5f61979c748687e66bSherry Moore " Shutdown disabled");
29949e866e40b95795203f3ee46f44a197c946e4stevelbuild_bd_display_str(char *buffer, enum board_type type, int board)
29949e866e40b95795203f3ee46f44a197c946e4stevel /* fill in board type to display */
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) sprintf(buffer, "Uninitialized Board type board %d",
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) sprintf(buffer, "Unknown Board type board %d", board);
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) sprintf(buffer, "CPU/Memory board %d", board);
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) sprintf(buffer, "SBus FFB IO board %d", board);
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) sprintf(buffer, "2 SBus SOC+ IO board %d", board);
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) sprintf(buffer, "SBus FFB SOC+ IO board %d", board);
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) sprintf(buffer, "Unrecognized board type board %d",
29949e866e40b95795203f3ee46f44a197c946e4stevel /* extract the soft state pointer */
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp = ddi_get_soft_state(fhcp, ddi_get_instance(dip));
29949e866e40b95795203f3ee46f44a197c946e4stevel * Loop through all the interrupt mapping registers and reprogram
29949e866e40b95795203f3ee46f44a197c946e4stevel * the target CPU for all valid registers.
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < FHC_MAX_INO; i++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Check the current target of the mondo */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (((*mondo_vec_reg & INR_PID_MASK) >> INR_PID_SHIFT) ==
29949e866e40b95795203f3ee46f44a197c946e4stevel /* It is the same, don't reprogram */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* So it's OK to reprogram the CPU target */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* turn off the valid bit */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* flush the hardware registers */
29949e866e40b95795203f3ee46f44a197c946e4stevel * wait for the state machine to idle. Do not loop on panic, so
29949e866e40b95795203f3ee46f44a197c946e4stevel * that system does not hang.
29949e866e40b95795203f3ee46f44a197c946e4stevel while (((*intr_state_reg & INT_PENDING) == INT_PENDING) &&
29949e866e40b95795203f3ee46f44a197c946e4stevel /* re-target the mondo and turn it on */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* write it back to the hardware. */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* flush the hardware buffers. */
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif /* lint */
29949e866e40b95795203f3ee46f44a197c946e4stevel * reg_fault
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.
29949e866e40b95795203f3ee46f44a197c946e4stevelreg_fault(int unit, enum ft_type type, enum ft_class fclass)
29949e866e40b95795203f3ee46f44a197c946e4stevel struct ft_link_list *list; /* temporary list pointer */
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 /* Allocate a new fault structure. */
29949e866e40b95795203f3ee46f44a197c946e4stevel list = kmem_zalloc(sizeof (struct ft_link_list), KM_SLEEP);
29949e866e40b95795203f3ee46f44a197c946e4stevel /* fill in the fault list elements */
29949e866e40b95795203f3ee46f44a197c946e4stevel list->f.create_time = (time32_t)gethrestime_sec(); /* XX64 */
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) strncpy(list->f.msg, ft_str_table[type], MAX_FT_DESC);
29949e866e40b95795203f3ee46f44a197c946e4stevel /* link it into the list. */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Update the total fault count */
29949e866e40b95795203f3ee46f44a197c946e4stevel * clear_fault
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.
29949e866e40b95795203f3ee46f44a197c946e4stevelclear_fault(int unit, enum ft_type type, enum ft_class fclass)
29949e866e40b95795203f3ee46f44a197c946e4stevel struct ft_link_list *list; /* temporary list pointer */
29949e866e40b95795203f3ee46f44a197c946e4stevel * Search for the requested fault. If it exists, delete it
29949e866e40b95795203f3ee46f44a197c946e4stevel * and relink the fault list.
29949e866e40b95795203f3ee46f44a197c946e4stevel for (; list != NULL; vect = &list->next, list = list->next) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((list->f.unit == unit) && (list->f.type == type) &&
29949e866e40b95795203f3ee46f44a197c946e4stevel /* remove the item from the list */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* free the memory allocated */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Update the total fault count */
29949e866e40b95795203f3ee46f44a197c946e4stevel * process_fault_list
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 struct ft_link_list *ftlist; /* fault list pointer */
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 /* First lock the board list */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Grab the fault list lock first */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* clear the board list of all faults first */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (bdlist = fhc_bd_first(); bdlist; bdlist = fhc_bd_next(bdlist))
29949e866e40b95795203f3ee46f44a197c946e4stevel /* walk the fault list here */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (ftlist = ft_list; ftlist != NULL; ftlist = ftlist->next) {
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 /* Sanity check the board first */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* now unlock the fault list */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* unlock the board list before leaving */
29949e866e40b95795203f3ee46f44a197c946e4stevel * Add a new memloc to the database (and keep 'em sorted by PA)
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT((size & (size-1)) == 0); /* size must be power of 2 */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* look for a comparable memloc (as long as new PA smaller) */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* have we passed our place in the sort? */
29949e866e40b95795203f3ee46f44a197c946e4stevel p = kmem_alloc(sizeof (struct fhc_memloc), KM_SLEEP);
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_NOTE, "fhc_add_memloc: adding %d 0x%x 0x%x",
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif /* DEBUG_MEMDEC */
29949e866e40b95795203f3ee46f44a197c946e4stevel * Delete all memloc records for a board from the database
29949e866e40b95795203f3ee46f44a197c946e4stevel /* delete all entries that match board */
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif /* DEBUG_MEMDEC */
29949e866e40b95795203f3ee46f44a197c946e4stevel * Find a physical address range of sufficient size and return a starting PA
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT((size & (size-1)) == 0); /* size must be power of 2 */
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 * At this point, we assume that base_pa is good enough.
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/* compute the appropriate RASIZE for bank size */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* XXX gross hack to get to board via board number */
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif /* DEBUG_MEMDEC */
29949e866e40b95795203f3ee46f44a197c946e4stevel/* assume size is set by connect */
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif /* DEBUG_MEMDEC */
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif /* DEBUG_MEMDEC */
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif /* DEBUG_MEMDEC */
29949e866e40b95795203f3ee46f44a197c946e4stevel c |= (fhc_cvt_size(b0_size) << 8); /* match row size */
29949e866e40b95795203f3ee46f44a197c946e4stevel c |= (0 << 3);
29949e866e40b95795203f3ee46f44a197c946e4stevel c |= (fhc_cvt_size(b1_size) << 11); /* match row size */
29949e866e40b95795203f3ee46f44a197c946e4stevel prom_printf("c 0x%llx, d0 0x%llx, d1 0x%llx\n", c, d0, d1);
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif /* DEBUG_MEMDEC */
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 ksp = kstat_create("unix", instance, FT_LIST_KSTAT_NAME, "misc",
193974072f41a843678abf5f61979c748687e66bSherry Moore KSTAT_TYPE_RAW, 1, KSTAT_FLAG_VIRTUAL|KSTAT_FLAG_VAR_SIZE);
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 for (ftlist = ft_list; ftlist != NULL; ftlist = ftlist->next) {
29949e866e40b95795203f3ee46f44a197c946e4stevel return (0);
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.
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (struct ft_list);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (0);
29949e866e40b95795203f3ee46f44a197c946e4stevel * Power off any cpus on the board.
29949e866e40b95795203f3ee46f44a197c946e4stevelfhc_board_poweroffcpus(int board, char *errbuf, int cpu_flags)
29949e866e40b95795203f3ee46f44a197c946e4stevel * what type of board are we dealing with?
29949e866e40b95795203f3ee46f44a197c946e4stevel * the shutdown sequence will be:
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 if ((cpa = cpu_get(FHC_BOARD2CPU_A(board))) != NULL &&
29949e866e40b95795203f3ee46f44a197c946e4stevel "Processor %d failed to offline.",
29949e866e40b95795203f3ee46f44a197c946e4stevel "processor %d failed to offline",
29949e866e40b95795203f3ee46f44a197c946e4stevel if (error == 0 &&
29949e866e40b95795203f3ee46f44a197c946e4stevel "Processor %d failed to offline.",
29949e866e40b95795203f3ee46f44a197c946e4stevel "processor %d failed to offline",
29949e866e40b95795203f3ee46f44a197c946e4stevel if (error == 0 && cpa != NULL && cpu_is_offline(cpa)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel "Processor %d failed to power off.",
29949e866e40b95795203f3ee46f44a197c946e4stevel "processor %d failed to power off",
29949e866e40b95795203f3ee46f44a197c946e4stevel if (error == 0 && cpb != NULL && cpu_is_offline(cpb)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel "Processor %d failed to power off.",
29949e866e40b95795203f3ee46f44a197c946e4stevel "processor %d failed to power off",
29949e866e40b95795203f3ee46f44a197c946e4stevel * If all the shutdowns completed, ONLY THEN, clear the
29949e866e40b95795203f3ee46f44a197c946e4stevel * incorrectly valid dtags...
29949e866e40b95795203f3ee46f44a197c946e4stevel * IMPORTANT: it is an error to read or write dtags while
29949e866e40b95795203f3ee46f44a197c946e4stevel * they are 'active'
29949e866e40b95795203f3ee46f44a197c946e4stevel /* always clear the dtags */
29949e866e40b95795203f3ee46f44a197c946e4stevel "cpua valid %d, cpub valid %d",
29949e866e40b95795203f3ee46f44a197c946e4stevel * platform code for shutting down cpus.
29949e866e40b95795203f3ee46f44a197c946e4stevel extern void idle_stop_xcall(void);
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT((cp->cpu_flags & (CPU_EXISTS | CPU_OFFLINE | CPU_QUIESCED)) ==
29949e866e40b95795203f3ee46f44a197c946e4stevel * Lock the board so that we can safely access the
29949e866e40b95795203f3ee46f44a197c946e4stevel * registers. This cannot be done inside the pause_cpus().
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(fhc_bd_valid(board) && (bd_list->sc.type == CPU_BOARD));
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 * 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 * 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 xt_one_unchecked(cp->cpu_id, (xcfunc_t *)idle_stop_xcall,
193974072f41a843678abf5f61979c748687e66bSherry Moore (uint64_t)fhc_cpu_shutdown_self, (uint64_t)NULL);
29949e866e40b95795203f3ee46f44a197c946e4stevel * Wait for slave cpu to shutdown.
29949e866e40b95795203f3ee46f44a197c946e4stevel * Sense this by watching the hardware EPDx bit.
29949e866e40b95795203f3ee46f44a197c946e4stevel for (delays = FHC_SHUTDOWN_WAIT_MSEC; delays != 0; delays--) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* get the current cpu power status */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* has the cpu actually signalled shutdown? */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* A timeout means we've lost control of the cpu. */
29949e866e40b95795203f3ee46f44a197c946e4stevel panic("Processor %d failed during shutdown", cp->cpu_id);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (0);
29949e866e40b95795203f3ee46f44a197c946e4stevel * shutdown_self
29949e866e40b95795203f3ee46f44a197c946e4stevel * slave side shutdown. clean up and execute the shutdown sequence.
29949e866e40b95795203f3ee46f44a197c946e4stevel extern void flush_windows(void);
29949e866e40b95795203f3ee46f44a197c946e4stevel CPU->cpu_flags = CPU_POWEROFF | CPU_OFFLINE | CPU_QUIESCED;
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) prom_sunfire_cpu_off(); /* inform Ultra Enterprise prom */
29949e866e40b95795203f3ee46f44a197c946e4stevel /*NOTREACHED*/
29949e866e40b95795203f3ee46f44a197c946e4stevel * Warm start CPU.
29949e866e40b95795203f3ee46f44a197c946e4stevel extern void restart_other_cpu(int);
29949e866e40b95795203f3ee46f44a197c946e4stevel /* power on cpu */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (rv != 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "Processor %d failed to power on.", cpuid);
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 return (0);
29949e866e40b95795203f3ee46f44a197c946e4stevel * Power on CPU.
29949e866e40b95795203f3ee46f44a197c946e4stevel /* do not power on overtemperature cpu */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* policy for dual cpu boards */
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((status == 0) &&
29949e866e40b95795203f3ee46f44a197c946e4stevel ((cp_other = cpu_get(FHC_OTHER_CPU_ID(cp->cpu_id))) != NULL)) {
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 " in pair %d & %d, error %d",
29949e866e40b95795203f3ee46f44a197c946e4stevel * complete the shutdown sequence in case the firmware doesn't.
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 extern void fhc_shutdown_asm_end(void);
29949e866e40b95795203f3ee46f44a197c946e4stevel /* compute sram global address for this operation */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* force load i and d translations */
193974072f41a843678abf5f61979c748687e66bSherry Moore TTE_HWWR_INT | TTE_PRIV_INT | TTE_LCK_INT; /* un$ */
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 for (src = (uint_t *)fhc_shutdown_asm, dst = (uint_t *)copy_addr;
29949e866e40b95795203f3ee46f44a197c946e4stevel * ensure non corrupting single write operations to
29949e866e40b95795203f3ee46f44a197c946e4stevel * localspace sram by interleaving reads with writes.
29949e866e40b95795203f3ee46f44a197c946e4stevel * Call the shutdown sequencer.
29949e866e40b95795203f3ee46f44a197c946e4stevel * NOTE: the base flush address must be unique for each MID.
193974072f41a843678abf5f61979c748687e66bSherry Moore FHC_BASE_NOMEM + CPU->cpu_id * FHC_MAX_ECACHE_SIZE,
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 addr = (va_to_pa((void *)v_eeprom_addr)) >> BOARD_PHYADDR_SHIFT;
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 */