03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CDDL HEADER START
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The contents of this file are subject to the terms of the
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * Common Development and Distribution License (the "License").
25cf1a301a396c38e8adf52c15f537b80d2483f7jl * You may not use this file except in compliance with the License.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
03831d35f7499c87d51205817c93e9a8d42c4baestevel * or http://www.opensolaris.org/os/licensing.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * See the License for the specific language governing permissions
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and limitations under the License.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * When distributing Covered Code, include this CDDL HEADER in each
03831d35f7499c87d51205817c93e9a8d42c4baestevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If applicable, add the following below this CDDL HEADER, with the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fields enclosed by brackets "[]" replaced with your own identifying
03831d35f7499c87d51205817c93e9a8d42c4baestevel * information: Portions Copyright [yyyy] [name of copyright owner]
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CDDL HEADER END
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Use is subject to license terms.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/note.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/debug.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/types.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/varargs.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/errno.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/cred.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/dditypes.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/devops.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/modctl.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/poll.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/conf.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/ddi.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sunddi.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sunndi.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/ndi_impldefs.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/stat.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/kmem.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/vmem.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/disp.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/processor.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/cheetahregs.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/cpuvar.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/mem_config.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/ddi_impldefs.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/systm.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/machsystm.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/autoconf.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/cmn_err.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sysmacros.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/x_call.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/promif.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/prom_plat.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/membar.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <vm/seg_kmem.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/mem_cage.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/stack.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/archsystm.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <vm/hat_sfmmu.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/pte.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/mmu.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/cpu_module.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/obpdefs.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/mboxsc.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/plat_ecc_dimm.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/hotplug/hpctrl.h> /* XXX should be included by schpc.h */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/schpc.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/pci.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/starcat.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/cpu_sgnblk_defs.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/drmach.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/dr_util.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/dr_mbx.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sc_gptwocfg.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/iosramreg.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/iosramio.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/iosramvar.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/axq.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/post/scat_dcd.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/kobj.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/taskq.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/cmp.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sbd_ioctl.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sysevent.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sysevent/dr.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sysevent/eventdefs.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/pci/pcisch.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/pci/pci_regs.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/ontrap.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* defined in ../ml/drmach.il.cpp */
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern void bcopy32_il(uint64_t, uint64_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern void flush_ecache_il(int64_t physaddr, int size, int linesz);
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern void flush_dcache_il(void);
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern void flush_icache_il(void);
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern void flush_pcache_il(void);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* defined in ../ml/drmach_asm.s */
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern uint64_t lddmcdecode(uint64_t physaddr);
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern uint64_t lddsafconfig(void);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* XXX here until provided by sys/dman.h */
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern int man_dr_attach(dev_info_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern int man_dr_detach(dev_info_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_BNUM2EXP(bnum) ((bnum) >> 1)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_BNUM2SLOT(bnum) ((bnum) & 1)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_EXPSLOT2BNUM(exp, slot) (((exp) << 1) + (slot))
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_SLICE_MASK 0x1Full
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_SLICE_TO_PA(s) (((s) & DRMACH_SLICE_MASK) << 37)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_PA_TO_SLICE(a) (((a) >> 37) & DRMACH_SLICE_MASK)
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DRMACH_MEM_SLICE_SIZE and DRMACH_MEM_USABLE_SLICE_SIZE define the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * available address space and the usable address space for every slice.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * There must be a distinction between the available and usable do to a
03831d35f7499c87d51205817c93e9a8d42c4baestevel * restriction imposed by CDC memory size.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_MEM_SLICE_SIZE (1ull << 37) /* 128GB */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_MEM_USABLE_SLICE_SIZE (1ull << 36) /* 64GB */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_MC_NBANKS 4
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_MC_ADDR(mp, bank) ((mp)->madr_pa + 16 + 8 * (bank))
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_MC_ASI_ADDR(mp, bank) (DRMACH_MC_ADDR(mp, bank) & 0xFF)
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_EMU_ACT_STATUS_OFFSET 0x50
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_EMU_ACT_STATUS_ADDR(mp) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((mp)->madr_pa + DRMACH_EMU_ACT_STATUS_OFFSET)
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The Cheetah's Safari Configuration Register and the Schizo's
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Safari Control/Status Register place the LPA base and bound fields in
03831d35f7499c87d51205817c93e9a8d42c4baestevel * same bit locations with in their register word. This source code takes
03831d35f7499c87d51205817c93e9a8d42c4baestevel * advantage of this by defining only one set of LPA encoding/decoding macros
03831d35f7499c87d51205817c93e9a8d42c4baestevel * which are shared by various Cheetah and Schizo drmach routines.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_LPA_BASE_MASK (0x3Full << 3)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_LPA_BND_MASK (0x3Full << 9)
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_LPA_BASE_TO_PA(scr) (((scr) & DRMACH_LPA_BASE_MASK) << 34)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_LPA_BND_TO_PA(scr) (((scr) & DRMACH_LPA_BND_MASK) << 28)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_PA_TO_LPA_BASE(pa) (((pa) >> 34) & DRMACH_LPA_BASE_MASK)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_PA_TO_LPA_BND(pa) (((pa) >> 28) & DRMACH_LPA_BND_MASK)
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_L1_SET_LPA(b) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel (((b)->flags & DRMACH_NULL_PROC_LPA) == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_CPU_SRAM_ADDR 0x7fff0900000ull
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_CPU_SRAM_SIZE 0x20000ull
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Name properties for frequently accessed device nodes.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_CPU_NAMEPROP "cpu"
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_CMP_NAMEPROP "cmp"
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_AXQ_NAMEPROP "address-extender-queue"
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_PCI_NAMEPROP "pci"
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Maximum value of processor Safari Timeout Log (TOL) field of
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Safari Config reg (7 secs).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_SAF_TOL_MAX 7 * 1000000
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * drmach_board_t flag definitions
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_NULL_PROC_LPA 0x1
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveltypedef struct {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t reg_addr_hi;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t reg_addr_lo;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t reg_size_hi;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t reg_size_lo;
03831d35f7499c87d51205817c93e9a8d42c4baestevel} drmach_reg_t;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveltypedef struct {
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct drmach_node *node;
03831d35f7499c87d51205817c93e9a8d42c4baestevel void *data;
03831d35f7499c87d51205817c93e9a8d42c4baestevel} drmach_node_walk_args_t;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveltypedef struct drmach_node {
03831d35f7499c87d51205817c93e9a8d42c4baestevel void *here;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel pnode_t (*get_dnode)(struct drmach_node *node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel int (*walk)(struct drmach_node *node, void *data,
03831d35f7499c87d51205817c93e9a8d42c4baestevel int (*cb)(drmach_node_walk_args_t *args));
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *(*n_getdip)(struct drmach_node *node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel int (*n_getproplen)(struct drmach_node *node, char *name,
03831d35f7499c87d51205817c93e9a8d42c4baestevel int *len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel int (*n_getprop)(struct drmach_node *node, char *name,
03831d35f7499c87d51205817c93e9a8d42c4baestevel void *buf, int len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel int (*get_parent)(struct drmach_node *node,
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct drmach_node *pnode);
03831d35f7499c87d51205817c93e9a8d42c4baestevel} drmach_node_t;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveltypedef struct {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int min_index;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int max_index;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int arr_sz;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmachid_t *arr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel} drmach_array_t;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveltypedef struct {
03831d35f7499c87d51205817c93e9a8d42c4baestevel void *isa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel void (*dispose)(drmachid_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *(*release)(drmachid_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *(*status)(drmachid_t, drmach_status_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel char name[MAXNAMELEN];
03831d35f7499c87d51205817c93e9a8d42c4baestevel} drmach_common_t;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstruct drmach_board;
03831d35f7499c87d51205817c93e9a8d42c4baesteveltypedef struct drmach_board drmach_board_t;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveltypedef struct {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_common_t cm;
03831d35f7499c87d51205817c93e9a8d42c4baestevel const char *type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_t *bp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_node_t *node;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int portid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int unum;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int busy;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int powered;
03831d35f7499c87d51205817c93e9a8d42c4baestevel} drmach_device_t;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveltypedef struct drmach_cpu {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_device_t dev;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t scr_pa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel processorid_t cpuid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int coreid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel} drmach_cpu_t;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveltypedef struct drmach_mem {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_device_t dev;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct drmach_mem *next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t nbytes;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t madr_pa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel} drmach_mem_t;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveltypedef struct drmach_io {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_device_t dev;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t scsr_pa; /* PA of Schizo Control/Status Register */
03831d35f7499c87d51205817c93e9a8d42c4baestevel} drmach_io_t;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstruct drmach_board {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_common_t cm;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int bnum;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int assigned;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int powered;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int connected;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int empty;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int cond;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint_t cpu_impl;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint_t flags;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_node_t *tree;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_array_t *devices;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mem_t *mem;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t stardrb_offset;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char type[BD_TYPELEN];
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveltypedef struct {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int flags;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_device_t *dp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *fdip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel} drmach_config_args_t;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveltypedef struct {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_t *obj;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int ndevs;
03831d35f7499c87d51205817c93e9a8d42c4baestevel void *a;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *(*found)(void *a, const char *, int, drmachid_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel} drmach_board_cb_data_t;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveltypedef struct drmach_casmslot {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int valid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int slice;
03831d35f7499c87d51205817c93e9a8d42c4baestevel} drmach_casmslot_t;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveltypedef enum {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_CR_OK,
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_CR_MC_IDLE_ERR,
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_CR_IOPAUSE_ERR,
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_CR_ONTRAP_ERR
03831d35f7499c87d51205817c93e9a8d42c4baestevel} drmach_cr_err_t;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveltypedef struct {
03831d35f7499c87d51205817c93e9a8d42c4baestevel void *isa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel caddr_t data;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mem_t *s_mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mem_t *t_mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct memlist *c_ml;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t s_copybasepa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t t_copybasepa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_cr_err_t ecode;
03831d35f7499c87d51205817c93e9a8d42c4baestevel void *earg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel} drmach_copy_rename_t;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The following global is read as a boolean value, non-zero is true.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If zero, DR copy-rename and cpu poweron will not set the processor
03831d35f7499c87d51205817c93e9a8d42c4baestevel * LPA settings (CBASE, CBND of Safari config register) to correspond
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to the current memory slice map. LPAs of processors present at boot
03831d35f7499c87d51205817c93e9a8d42c4baestevel * will remain as programmed by POST. LPAs of processors on boards added
03831d35f7499c87d51205817c93e9a8d42c4baestevel * by DR will remain NULL, as programmed by POST. This can be used to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to override the per-board L1SSFLG_THIS_L1_NULL_PROC_LPA flag set by
03831d35f7499c87d51205817c93e9a8d42c4baestevel * POST in the LDCD (and copied to the GDCD by SMS).
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * drmach_reprogram_lpa and L1SSFLG_THIS_L1_NULL_PROC_LPA do not apply
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to Schizo device LPAs. These are always set by DR.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int drmach_reprogram_lpa = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * There is a known HW bug where a Jaguar CPU in Safari port 0 (SBX/P0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * can fail to receive an XIR. To workaround this issue until a hardware
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fix is implemented, we will exclude the selection of these CPUs.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Setting this to 0 will allow their selection again.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int drmach_iocage_exclude_jaguar_port_zero = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int drmach_initialized;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic drmach_array_t *drmach_boards;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int drmach_cpu_delay = 1000;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int drmach_cpu_ntries = 50000;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uint32_t drmach_slice_table[AXQ_MAX_EXP];
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic kmutex_t drmach_slice_table_lock;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveltte_t drmach_cpu_sram_tte[NCPU];
03831d35f7499c87d51205817c93e9a8d42c4baestevelcaddr_t drmach_cpu_sram_va;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Setting to non-zero will enable delay before all disconnect ops.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int drmach_unclaim_delay_all;
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Default delay is slightly greater than the max processor Safari timeout.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This delay is intended to ensure the outstanding Safari activity has
03831d35f7499c87d51205817c93e9a8d42c4baestevel * retired on this board prior to a board disconnect.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic clock_t drmach_unclaim_usec_delay = DRMACH_SAF_TOL_MAX + 10;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * By default, DR of non-Panther procs is not allowed into a Panther
03831d35f7499c87d51205817c93e9a8d42c4baestevel * domain with large page sizes enabled. Setting this to 0 will remove
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the restriction.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int drmach_large_page_restriction = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Used to pass updated LPA values to procs.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Protocol is to clear the array before use.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvolatile uchar_t *drmach_xt_mb;
03831d35f7499c87d51205817c93e9a8d42c4baestevelvolatile uint64_t drmach_xt_ready;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic kmutex_t drmach_xt_mb_lock;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int drmach_xt_mb_size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveluint64_t drmach_bus_sync_list[18 * 4 * 4 + 1];
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic kmutex_t drmach_bus_sync_lock;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowestatic void drmach_fini(void);
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowe
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *drmach_device_new(drmach_node_t *,
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_t *, int, drmachid_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *drmach_cpu_new(drmach_device_t *, drmachid_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *drmach_mem_new(drmach_device_t *, drmachid_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *drmach_pci_new(drmach_device_t *, drmachid_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *drmach_io_new(drmach_device_t *, drmachid_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowestatic sbd_error_t *drmach_board_release(drmachid_t);
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowestatic sbd_error_t *drmach_board_status(drmachid_t, drmach_status_t *);
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowe
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowestatic void drmach_cpu_dispose(drmachid_t);
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowestatic sbd_error_t *drmach_cpu_release(drmachid_t);
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowestatic sbd_error_t *drmach_cpu_status(drmachid_t, drmach_status_t *);
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowe
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowestatic void drmach_mem_dispose(drmachid_t);
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowestatic sbd_error_t *drmach_mem_release(drmachid_t);
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowestatic sbd_error_t *drmach_mem_status(drmachid_t, drmach_status_t *);
8682d1ef2a0960ed5a9f05b9448eaa3e68ac931fRichard Lowe
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic dev_info_t *drmach_node_ddi_get_dip(drmach_node_t *np);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int drmach_node_ddi_get_prop(drmach_node_t *np,
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *name, void *buf, int len);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int drmach_node_ddi_get_proplen(drmach_node_t *np,
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *name, int *len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic dev_info_t *drmach_node_obp_get_dip(drmach_node_t *np);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int drmach_node_obp_get_prop(drmach_node_t *np,
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *name, void *buf, int len);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int drmach_node_obp_get_proplen(drmach_node_t *np,
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *name, int *len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *drmach_mbox_trans(uint8_t msgtype, int bnum,
03831d35f7499c87d51205817c93e9a8d42c4baestevel caddr_t obufp, int olen,
03831d35f7499c87d51205817c93e9a8d42c4baestevel caddr_t ibufp, int ilen);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *drmach_io_post_attach(drmachid_t id);
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *drmach_io_post_release(drmachid_t id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *drmach_iocage_setup(dr_testboard_req_t *,
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_device_t **dpp, cpu_flag_t *oflags);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int drmach_iocage_cpu_return(drmach_device_t *dp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpu_flag_t oflags);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *drmach_iocage_mem_return(dr_testboard_reply_t *tbr);
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid drmach_iocage_mem_scrub(uint64_t nbytes);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *drmach_i_status(drmachid_t id, drmach_status_t *stat);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void drmach_slot1_lpa_set(drmach_board_t *bp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void drmach_cpu_read(uint64_t arg1, uint64_t arg2);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int drmach_cpu_read_scr(drmach_cpu_t *cp, uint64_t *scr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void drmach_bus_sync_list_update(void);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void drmach_slice_table_update(drmach_board_t *, int);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int drmach_portid2bnum(int);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void drmach_msg_memslice_init(dr_memslice_t slice_arr[]);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void drmach_msg_memregs_init(dr_memregs_t regs_arr[]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int drmach_panther_boards(void);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int drmach_name2type_idx(char *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_PR if (drmach_debug) printf
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_MEMLIST_DUMP if (drmach_debug) MEMLIST_DUMP
03831d35f7499c87d51205817c93e9a8d42c4baestevelint drmach_debug = 0; /* set to non-zero to enable debug messages */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#else
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_PR _NOTE(CONSTANTCONDITION) if (0) printf
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_MEMLIST_DUMP _NOTE(CONSTANTCONDITION) if (0) MEMLIST_DUMP
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_OBJ(id) ((drmach_common_t *)id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_IS_BOARD_ID(id) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((id != 0) && \
03831d35f7499c87d51205817c93e9a8d42c4baestevel (DRMACH_OBJ(id)->isa == (void *)drmach_board_new))
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_IS_CPU_ID(id) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((id != 0) && \
03831d35f7499c87d51205817c93e9a8d42c4baestevel (DRMACH_OBJ(id)->isa == (void *)drmach_cpu_new))
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_IS_MEM_ID(id) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((id != 0) && \
03831d35f7499c87d51205817c93e9a8d42c4baestevel (DRMACH_OBJ(id)->isa == (void *)drmach_mem_new))
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_IS_IO_ID(id) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((id != 0) && \
03831d35f7499c87d51205817c93e9a8d42c4baestevel (DRMACH_OBJ(id)->isa == (void *)drmach_io_new))
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_IS_DEVICE_ID(id) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((id != 0) && \
03831d35f7499c87d51205817c93e9a8d42c4baestevel (DRMACH_OBJ(id)->isa == (void *)drmach_cpu_new || \
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_OBJ(id)->isa == (void *)drmach_mem_new || \
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_OBJ(id)->isa == (void *)drmach_io_new))
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_IS_ID(id) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((id != 0) && \
03831d35f7499c87d51205817c93e9a8d42c4baestevel (DRMACH_OBJ(id)->isa == (void *)drmach_board_new || \
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_OBJ(id)->isa == (void *)drmach_cpu_new || \
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_OBJ(id)->isa == (void *)drmach_mem_new || \
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_OBJ(id)->isa == (void *)drmach_io_new))
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_INTERNAL_ERROR() \
03831d35f7499c87d51205817c93e9a8d42c4baestevel drerr_new(1, ESTC_INTERNAL, drmach_ie_fmt, __LINE__)
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic char *drmach_ie_fmt = "drmach.c %d";
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct {
03831d35f7499c87d51205817c93e9a8d42c4baestevel const char *name;
03831d35f7499c87d51205817c93e9a8d42c4baestevel const char *type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *(*new)(drmach_device_t *, drmachid_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel} drmach_name2type[] = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel {"cmp", DRMACH_DEVTYPE_CMP, NULL },
03831d35f7499c87d51205817c93e9a8d42c4baestevel {"cpu", DRMACH_DEVTYPE_CPU, drmach_cpu_new },
03831d35f7499c87d51205817c93e9a8d42c4baestevel {"SUNW,UltraSPARC-III", DRMACH_DEVTYPE_CPU, drmach_cpu_new },
03831d35f7499c87d51205817c93e9a8d42c4baestevel {"SUNW,UltraSPARC-III+", DRMACH_DEVTYPE_CPU, drmach_cpu_new },
03831d35f7499c87d51205817c93e9a8d42c4baestevel {"memory-controller", DRMACH_DEVTYPE_MEM, drmach_mem_new },
03831d35f7499c87d51205817c93e9a8d42c4baestevel {"pci", DRMACH_DEVTYPE_PCI, drmach_pci_new },
03831d35f7499c87d51205817c93e9a8d42c4baestevel {"SUNW,wci", DRMACH_DEVTYPE_WCI, drmach_io_new },
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * drmach autoconfiguration data structures and interfaces
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern struct mod_ops mod_miscops;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct modlmisc modlmisc = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel &mod_miscops,
f500b19684bd0346ac05bec02a50af07f369da1aRichard Bean "Sun Fire 15000 DR"
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct modlinkage modlinkage = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel MODREV_1,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void *)&modlmisc,
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * drmach_boards_rwlock is used to synchronize read/write
03831d35f7499c87d51205817c93e9a8d42c4baestevel * access to drmach_boards array between status and board lookup
03831d35f7499c87d51205817c93e9a8d42c4baestevel * as READERS, and assign, and unassign threads as WRITERS.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic krwlock_t drmach_boards_rwlock;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic kmutex_t drmach_i_lock;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic kmutex_t drmach_iocage_lock;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic kcondvar_t drmach_iocage_cv;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int drmach_iocage_is_busy = 0;
03831d35f7499c87d51205817c93e9a8d42c4baesteveluint64_t drmach_iocage_paddr;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic caddr_t drmach_iocage_vaddr;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int drmach_iocage_size = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int drmach_is_cheetah = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevel_init(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(&drmach_i_lock, NULL, MUTEX_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_init(&drmach_boards_rwlock, NULL, RW_DEFAULT, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_xt_mb_size = NCPU * sizeof (uchar_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_xt_mb = (uchar_t *)vmem_alloc(static_alloc_arena,
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_xt_mb_size, VM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel bzero((void *)drmach_xt_mb, drmach_xt_mb_size);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((err = mod_install(&modlinkage)) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(&drmach_i_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_destroy(&drmach_boards_rwlock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel vmem_free(static_alloc_arena, (void *)drmach_xt_mb,
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_xt_mb_size);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevel_fini(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((err = mod_remove(&modlinkage)) == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_fini();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevel_info(struct modinfo *modinfop)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (mod_info(&modlinkage, modinfop));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * drmach_node_* routines serve the purpose of separating the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * rest of the code from the device tree and OBP. This is necessary
03831d35f7499c87d51205817c93e9a8d42c4baestevel * because of In-Kernel-Probing. Devices probed after stod, are probed
03831d35f7499c87d51205817c93e9a8d42c4baestevel * by the in-kernel-prober, not OBP. These devices, therefore, do not
03831d35f7499c87d51205817c93e9a8d42c4baestevel * have dnode ids.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_node_obp_get_parent(drmach_node_t *np, drmach_node_t *pp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel pnode_t nodeid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel static char *fn = "drmach_node_obp_get_parent";
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodeid = np->get_dnode(np);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (nodeid == OBP_NONODE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "%s: invalid dnode", fn);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy(np, pp, sizeof (drmach_node_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel pp->here = (void *)(uintptr_t)prom_parentnode(nodeid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (pp->here == OBP_NONODE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "%s: invalid parent dnode", fn);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic pnode_t
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_node_obp_get_dnode(drmach_node_t *np)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return ((pnode_t)(uintptr_t)np->here);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveltypedef struct {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_node_walk_args_t *nwargs;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int (*cb)(drmach_node_walk_args_t *args);
03831d35f7499c87d51205817c93e9a8d42c4baestevel int err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel} drmach_node_ddi_walk_args_t;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_node_ddi_walk_cb(dev_info_t *dip, void *arg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_node_ddi_walk_args_t *nargs;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel nargs = (drmach_node_ddi_walk_args_t *)arg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * dip doesn't have to be held here as we are called
03831d35f7499c87d51205817c93e9a8d42c4baestevel * from ddi_walk_devs() which holds the dip.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nargs->nwargs->node->here = (void *)dip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel nargs->err = nargs->cb(nargs->nwargs);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set "here" to NULL so that unheld dip is not accessible
03831d35f7499c87d51205817c93e9a8d42c4baestevel * outside ddi_walk_devs()
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nargs->nwargs->node->here = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (nargs->err)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_WALK_TERMINATE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_WALK_CONTINUE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_node_ddi_walk(drmach_node_t *np, void *data,
03831d35f7499c87d51205817c93e9a8d42c4baestevel int (*cb)(drmach_node_walk_args_t *args))
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_node_walk_args_t args;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_node_ddi_walk_args_t nargs;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* initialized args structure for callback */
03831d35f7499c87d51205817c93e9a8d42c4baestevel args.node = np;
03831d35f7499c87d51205817c93e9a8d42c4baestevel args.data = data;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel nargs.nwargs = &args;
03831d35f7499c87d51205817c93e9a8d42c4baestevel nargs.cb = cb;
03831d35f7499c87d51205817c93e9a8d42c4baestevel nargs.err = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Root node doesn't have to be held in any way.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni ddi_walk_devs(ddi_root_node(), drmach_node_ddi_walk_cb, (void *)&nargs);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (nargs.err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_node_obp_walk(drmach_node_t *np, void *data,
03831d35f7499c87d51205817c93e9a8d42c4baestevel int (*cb)(drmach_node_walk_args_t *args))
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel pnode_t nodeid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_node_walk_args_t args;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* initialized args structure for callback */
03831d35f7499c87d51205817c93e9a8d42c4baestevel args.node = np;
03831d35f7499c87d51205817c93e9a8d42c4baestevel args.data = data;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodeid = prom_childnode(prom_rootnode());
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* save our new position within the tree */
03831d35f7499c87d51205817c93e9a8d42c4baestevel np->here = (void *)(uintptr_t)nodeid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (nodeid != OBP_NONODE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel pnode_t child;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = (*cb)(&args);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel child = prom_childnode(nodeid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel np->here = (void *)(uintptr_t)child;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (child != OBP_NONODE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = (*cb)(&args);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel child = prom_nextnode(child);
03831d35f7499c87d51205817c93e9a8d42c4baestevel np->here = (void *)(uintptr_t)child;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodeid = prom_nextnode(nodeid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* save our new position within the tree */
03831d35f7499c87d51205817c93e9a8d42c4baestevel np->here = (void *)(uintptr_t)nodeid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (rv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_node_ddi_get_parent(drmach_node_t *np, drmach_node_t *pp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *ndip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel static char *fn = "drmach_node_ddi_get_parent";
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndip = np->n_getdip(np);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ndip == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "%s: NULL dip", fn);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy(np, pp, sizeof (drmach_node_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel pp->here = (void *)ddi_get_parent(ndip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (pp->here == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "%s: NULL parent dip", fn);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic pnode_t
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_node_ddi_get_dnode(drmach_node_t *np)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return ((pnode_t)NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic drmach_node_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_node_new(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_node_t *np;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel np = kmem_zalloc(sizeof (drmach_node_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_initialized) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel np->get_dnode = drmach_node_ddi_get_dnode;
03831d35f7499c87d51205817c93e9a8d42c4baestevel np->walk = drmach_node_ddi_walk;
03831d35f7499c87d51205817c93e9a8d42c4baestevel np->n_getdip = drmach_node_ddi_get_dip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel np->n_getproplen = drmach_node_ddi_get_proplen;
03831d35f7499c87d51205817c93e9a8d42c4baestevel np->n_getprop = drmach_node_ddi_get_prop;
03831d35f7499c87d51205817c93e9a8d42c4baestevel np->get_parent = drmach_node_ddi_get_parent;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel np->get_dnode = drmach_node_obp_get_dnode;
03831d35f7499c87d51205817c93e9a8d42c4baestevel np->walk = drmach_node_obp_walk;
03831d35f7499c87d51205817c93e9a8d42c4baestevel np->n_getdip = drmach_node_obp_get_dip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel np->n_getproplen = drmach_node_obp_get_proplen;
03831d35f7499c87d51205817c93e9a8d42c4baestevel np->n_getprop = drmach_node_obp_get_prop;
03831d35f7499c87d51205817c93e9a8d42c4baestevel np->get_parent = drmach_node_obp_get_parent;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (np);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_node_dispose(drmach_node_t *np)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(np, sizeof (*np));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check if a CPU node is part of a CMP.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_is_cmp_child(dev_info_t *dip)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *pdip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (strcmp(ddi_node_name(dip), DRMACH_CPU_NAMEPROP) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel pdip = ddi_get_parent(dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(pdip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (strcmp(ddi_node_name(pdip), DRMACH_CMP_NAMEPROP) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic dev_info_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_node_obp_get_dip(drmach_node_t *np)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel pnode_t nodeid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *dip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodeid = np->get_dnode(np);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (nodeid == OBP_NONODE)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dip = e_ddi_nodeid_to_dip(nodeid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dip) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The branch rooted at dip will have been previously
03831d35f7499c87d51205817c93e9a8d42c4baestevel * held, or it will be the child of a CMP. In either
03831d35f7499c87d51205817c93e9a8d42c4baestevel * case, the hold acquired in e_ddi_nodeid_to_dip()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * is not needed.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_release_devi(dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(drmach_is_cmp_child(dip) || e_ddi_branch_held(dip));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic dev_info_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_node_ddi_get_dip(drmach_node_t *np)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return ((dev_info_t *)np->here);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_node_walk(drmach_node_t *np, void *param,
03831d35f7499c87d51205817c93e9a8d42c4baestevel int (*cb)(drmach_node_walk_args_t *args))
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (np->walk(np, param, cb));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_node_ddi_get_prop(drmach_node_t *np, char *name, void *buf, int len)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *ndip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel static char *fn = "drmach_node_ddi_get_prop";
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndip = np->n_getdip(np);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ndip == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "%s: NULL dip", fn);
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (ddi_getlongprop_buf(DDI_DEV_T_ANY, ndip,
03831d35f7499c87d51205817c93e9a8d42c4baestevel DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, name,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (caddr_t)buf, &len) != DDI_PROP_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (rv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_node_obp_get_prop(drmach_node_t *np, char *name, void *buf, int len)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pnode_t nodeid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel static char *fn = "drmach_node_obp_get_prop";
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodeid = np->get_dnode(np);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (nodeid == OBP_NONODE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "%s: invalid dnode", fn);
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (prom_getproplen(nodeid, (caddr_t)name) < 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) prom_getprop(nodeid, (caddr_t)name, (caddr_t)buf);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (rv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_node_ddi_get_proplen(drmach_node_t *np, char *name, int *len)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *ndip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndip = np->n_getdip(np);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ndip == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (ddi_getproplen(DDI_DEV_T_ANY, ndip, DDI_PROP_DONTPASS,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni name, len) != DDI_PROP_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (rv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_node_obp_get_proplen(drmach_node_t *np, char *name, int *len)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel pnode_t nodeid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodeid = np->get_dnode(np);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (nodeid == OBP_NONODE)
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *len = prom_getproplen(nodeid, (caddr_t)name);
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = (*len < 0 ? -1 : 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (rv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic drmachid_t
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_node_dup(drmach_node_t *np)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_node_t *dup;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dup = drmach_node_new();
03831d35f7499c87d51205817c93e9a8d42c4baestevel dup->here = np->here;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dup->get_dnode = np->get_dnode;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dup->walk = np->walk;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dup->n_getdip = np->n_getdip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dup->n_getproplen = np->n_getproplen;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dup->n_getprop = np->n_getprop;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dup->get_parent = np->get_parent;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (dup);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * drmach_array provides convenient array construction, access,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * bounds checking and array destruction logic.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic drmach_array_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_array_new(int min_index, int max_index)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_array_t *arr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel arr = kmem_zalloc(sizeof (drmach_array_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel arr->arr_sz = (max_index - min_index + 1) * sizeof (void *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (arr->arr_sz > 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel arr->min_index = min_index;
03831d35f7499c87d51205817c93e9a8d42c4baestevel arr->max_index = max_index;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel arr->arr = kmem_zalloc(arr->arr_sz, KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (arr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(arr, sizeof (*arr));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_array_set(drmach_array_t *arr, int idx, drmachid_t val)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (idx < arr->min_index || idx > arr->max_index)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel arr->arr[idx - arr->min_index] = val;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*NOTREACHED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_array_get(drmach_array_t *arr, int idx, drmachid_t *val)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (idx < arr->min_index || idx > arr->max_index)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *val = arr->arr[idx - arr->min_index];
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*NOTREACHED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_array_first(drmach_array_t *arr, int *idx, drmachid_t *val)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *idx = arr->min_index;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while ((rv = drmach_array_get(arr, *idx, val)) == 0 && *val == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel *idx += 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (rv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_array_next(drmach_array_t *arr, int *idx, drmachid_t *val)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *idx += 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while ((rv = drmach_array_get(arr, *idx, val)) == 0 && *val == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel *idx += 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (rv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_array_dispose(drmach_array_t *arr, void (*disposer)(drmachid_t))
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmachid_t val;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int idx;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = drmach_array_first(arr, &idx, &val);
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (rv == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (*disposer)(val);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* clear the array entry */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = drmach_array_set(arr, idx, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(rv == 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = drmach_array_next(arr, &idx, &val);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(arr->arr, arr->arr_sz);
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(arr, sizeof (*arr));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic gdcd_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_gdcd_new()
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel gdcd_t *gdcd;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel gdcd = kmem_zalloc(sizeof (gdcd_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* read the gdcd, bail if magic or ver #s are not what is expected */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_rd(GDCD_MAGIC, 0, sizeof (gdcd_t), (caddr_t)gdcd)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevelbail:
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(gdcd, sizeof (gdcd_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (gdcd->h.dcd_magic != GDCD_MAGIC) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto bail;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (gdcd->h.dcd_version != DCD_VERSION) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto bail;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (gdcd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_gdcd_dispose(gdcd_t *gdcd)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(gdcd, sizeof (gdcd_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_configure(drmachid_t id, int flags)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_device_t *dp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *rdip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * On Starcat, there is no CPU driver, so it is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * not necessary to configure any CPU nodes.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (DRMACH_IS_CPU_ID(id)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (; id; ) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *fdip = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_DEVICE_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel dp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rdip = dp->node->n_getdip(dp->node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We held this branch earlier, so at a minimum its
03831d35f7499c87d51205817c93e9a8d42c4baestevel * root should still be present in the device tree.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(rdip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("drmach_configure: configuring DDI branch");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(e_ddi_branch_held(rdip));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (e_ddi_branch_configure(rdip, &fdip, 0) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Record first failure but don't stop
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *dip = (fdip != NULL) ? fdip : rdip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) ddi_pathname(dip, path);
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drerr_new(1, ESTC_DRVFAIL, path);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(path, MAXPATHLEN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If non-NULL, fdip is returned held and must be
03831d35f7499c87d51205817c93e9a8d42c4baestevel * released.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (fdip != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_release_devi(fdip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (DRMACH_IS_MEM_ID(id)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mem_t *mp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel id = mp->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel id = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_device_new(drmach_node_t *node,
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_t *bp, int portid, drmachid_t *idp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i, rv, device_id, unum;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char name[OBP_MAXDRVNAME];
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_device_t proto;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = node->n_getprop(node, "name", name, OBP_MAXDRVNAME);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* every node is expected to have a name */
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drerr_new(1, ESTC_GETPROP,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "dip: 0x%p: property %s",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni node->n_getdip(node), OBP_NAME);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = drmach_name2type_idx(name);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i < 0 || strcmp(name, "cmp") == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Not a node of interest to dr - including "cmp",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * but it is in drmach_name2type[], which lets gptwocfg
03831d35f7499c87d51205817c93e9a8d42c4baestevel * driver to check if node is OBP created.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel *idp = (drmachid_t)0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Derive a best-guess unit number from the portid value.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Some drmach_*_new constructors (drmach_pci_new, for example)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * will overwrite the prototype unum value with one that is more
03831d35f7499c87d51205817c93e9a8d42c4baestevel * appropriate for the device.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel device_id = portid & 0x1f;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (device_id < 4)
03831d35f7499c87d51205817c93e9a8d42c4baestevel unum = device_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else if (device_id == 8) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel unum = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (device_id == 9) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel unum = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (device_id == 0x1c) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel unum = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (device_id == 0x1d) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel unum = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DRMACH_INTERNAL_ERROR());
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel bzero(&proto, sizeof (proto));
03831d35f7499c87d51205817c93e9a8d42c4baestevel proto.type = drmach_name2type[i].type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel proto.bp = bp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel proto.node = node;
03831d35f7499c87d51205817c93e9a8d42c4baestevel proto.portid = portid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel proto.unum = unum;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drmach_name2type[i].new(&proto, idp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_device_dispose(drmachid_t id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_device_t *self = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel self->cm.dispose(id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic drmach_board_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_board_new(int bnum)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_t *bp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp = kmem_zalloc(sizeof (drmach_board_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->cm.isa = (void *)drmach_board_new;
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->cm.release = drmach_board_release;
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->cm.status = drmach_board_status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) drmach_board_name(bnum, bp->cm.name, sizeof (bp->cm.name));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->bnum = bnum;
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->devices = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->tree = drmach_node_new();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) drmach_array_set(drmach_boards, bnum, bp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (bp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_board_dispose(drmachid_t id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_t *bp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(DRMACH_IS_BOARD_ID(id));
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (bp->tree)
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_node_dispose(bp->tree);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (bp->devices)
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_array_dispose(bp->devices, drmach_device_dispose);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(bp, sizeof (*bp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_board_status(drmachid_t id, drmach_status_t *stat)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_t *bp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel caddr_t obufp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dr_showboard_t shb;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_BOARD_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * we need to know if the board's connected before
03831d35f7499c87d51205817c93e9a8d42c4baestevel * issuing a showboard message. If it's connected, we just
03831d35f7499c87d51205817c93e9a8d42c4baestevel * reply with status composed of cached info
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!bp->connected) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel obufp = kmem_zalloc(sizeof (dr_proto_hdr_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_mbox_trans(DRMSG_SHOWBOARD, bp->bnum, obufp,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni sizeof (dr_proto_hdr_t), (caddr_t)&shb,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni sizeof (dr_showboard_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(obufp, sizeof (dr_proto_hdr_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->connected = (shb.bd_assigned && shb.bd_active);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) strncpy(bp->type, shb.board_type, sizeof (bp->type));
03831d35f7499c87d51205817c93e9a8d42c4baestevel stat->assigned = bp->assigned = shb.bd_assigned;
03831d35f7499c87d51205817c93e9a8d42c4baestevel stat->powered = bp->powered = shb.power_on;
03831d35f7499c87d51205817c93e9a8d42c4baestevel stat->empty = bp->empty = shb.slot_empty;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (shb.test_status) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DR_TEST_STATUS_UNKNOWN:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DR_TEST_STATUS_IPOST:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DR_TEST_STATUS_ABORTED:
03831d35f7499c87d51205817c93e9a8d42c4baestevel stat->cond = bp->cond = SBD_COND_UNKNOWN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DR_TEST_STATUS_PASSED:
03831d35f7499c87d51205817c93e9a8d42c4baestevel stat->cond = bp->cond = SBD_COND_OK;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DR_TEST_STATUS_FAILED:
03831d35f7499c87d51205817c93e9a8d42c4baestevel stat->cond = bp->cond = SBD_COND_FAILED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel stat->cond = bp->cond = SBD_COND_UNKNOWN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("Unknown test status=0x%x from SC\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni shb.test_status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) strncpy(stat->type, shb.board_type, sizeof (stat->type));
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) snprintf(stat->info, sizeof (stat->info),
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki "Test Level=%d", shb.test_level);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel stat->assigned = bp->assigned;
03831d35f7499c87d51205817c93e9a8d42c4baestevel stat->powered = bp->powered;
03831d35f7499c87d51205817c93e9a8d42c4baestevel stat->empty = bp->empty;
03831d35f7499c87d51205817c93e9a8d42c4baestevel stat->cond = bp->cond;
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) strncpy(stat->type, bp->type, sizeof (stat->type));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel stat->busy = 0; /* assume not busy */
03831d35f7499c87d51205817c93e9a8d42c4baestevel stat->configured = 0; /* assume not configured */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (bp->devices) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int d_idx;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmachid_t d_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = drmach_array_first(bp->devices, &d_idx, &d_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (rv == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_status_t d_stat;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_i_status(d_id, &d_stat);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel stat->busy |= d_stat.busy;
03831d35f7499c87d51205817c93e9a8d42c4baestevel stat->configured |= d_stat.configured;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = drmach_array_next(bp->devices, &d_idx, &d_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveltypedef struct drmach_msglist {
03831d35f7499c87d51205817c93e9a8d42c4baestevel kcondvar_t s_cv; /* condvar for sending msg */
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmutex_t s_lock; /* mutex for sending */
03831d35f7499c87d51205817c93e9a8d42c4baestevel kcondvar_t g_cv; /* condvar for getting reply */
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmutex_t g_lock; /* mutex for getting reply */
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct drmach_msglist *prev; /* link to previous entry */
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct drmach_msglist *next; /* link to next entry */
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct drmach_msglist *link; /* link to related entry */
03831d35f7499c87d51205817c93e9a8d42c4baestevel caddr_t o_buf; /* address of output buffer */
03831d35f7499c87d51205817c93e9a8d42c4baestevel caddr_t i_buf; /* address of input buffer */
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t o_buflen; /* output buffer length */
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t i_buflen; /* input buffer length */
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t msgid; /* message identifier */
03831d35f7499c87d51205817c93e9a8d42c4baestevel int o_nretry; /* number of sending retries */
03831d35f7499c87d51205817c93e9a8d42c4baestevel int f_error; /* mailbox framework error */
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint8_t e_code; /* error code returned by SC */
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint8_t p_flag :1, /* successfully putmsg */
03831d35f7499c87d51205817c93e9a8d42c4baestevel m_reply :1, /* msg reply received */
03831d35f7499c87d51205817c93e9a8d42c4baestevel unused :6;
03831d35f7499c87d51205817c93e9a8d42c4baestevel} drmach_msglist_t;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelkmutex_t drmach_g_mbox_mutex; /* mutex for mailbox globals */
03831d35f7499c87d51205817c93e9a8d42c4baestevelkmutex_t drmach_ri_mbox_mutex; /* mutex for mailbox reinit */
03831d35f7499c87d51205817c93e9a8d42c4baestevelkmutex_t drmach_msglist_mutex; /* mutex for message list */
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_msglist_t *drmach_msglist_first; /* first entry in msg list */
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_msglist_t *drmach_msglist_last; /* last entry in msg list */
03831d35f7499c87d51205817c93e9a8d42c4baesteveluint32_t drmach_msgid; /* current message id */
03831d35f7499c87d51205817c93e9a8d42c4baestevelkthread_t *drmach_getmsg_thread; /* ptr to getmsg thread */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvolatile int drmach_getmsg_thread_run; /* run flag for getmsg thr */
03831d35f7499c87d51205817c93e9a8d42c4baestevelkmutex_t drmach_sendmsg_mutex; /* mutex for sendmsg cv */
03831d35f7499c87d51205817c93e9a8d42c4baestevelkcondvar_t drmach_sendmsg_cv; /* signaled to send new msg */
03831d35f7499c87d51205817c93e9a8d42c4baestevelkthread_t *drmach_sendmsg_thread; /* ptr to sendmsg thread */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvolatile int drmach_sendmsg_thread_run; /* run flag for sendmsg */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint drmach_mbox_istate; /* mailbox init state */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint drmach_mbox_iflag; /* set if init'd with SC */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint drmach_mbox_ipending; /* set if reinit scheduled */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Timeout values (in seconds) used when waiting for replies (from the SC) to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * requests that we sent. Since we only receive boardevent messages, and they
03831d35f7499c87d51205817c93e9a8d42c4baestevel * are events rather than replies, there is no boardevent timeout.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint drmach_to_mbxinit = 60; /* 1 minute */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint drmach_to_assign = 60; /* 1 minute */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint drmach_to_unassign = 60; /* 1 minute */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint drmach_to_claim = 3600; /* 1 hour */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint drmach_to_unclaim = 3600; /* 1 hour */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint drmach_to_poweron = 480; /* 8 minutes */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint drmach_to_poweroff = 480; /* 8 minutes */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint drmach_to_testboard = 43200; /* 12 hours */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint drmach_to_aborttest = 180; /* 3 minutes */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint drmach_to_showboard = 180; /* 3 minutes */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint drmach_to_unconfig = 180; /* 3 minutes */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Delay (in seconds) used after receiving a non-transient error indication from
03831d35f7499c87d51205817c93e9a8d42c4baestevel * an mboxsc_getmsg call in the thread that loops waiting for incoming messages.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint drmach_mbxerr_delay = 15; /* 15 seconds */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Timeout values (in milliseconds) for mboxsc_putmsg and mboxsc_getmsg calls.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelclock_t drmach_to_putmsg; /* set in drmach_mbox_init */
03831d35f7499c87d51205817c93e9a8d42c4baestevelclock_t drmach_to_getmsg = 31000; /* 31 seconds */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Normally, drmach_to_putmsg is set dynamically during initialization in
03831d35f7499c87d51205817c93e9a8d42c4baestevel * drmach_mbox_init. This has the potentially undesirable side effect of
03831d35f7499c87d51205817c93e9a8d42c4baestevel * clobbering any value that might have been set in /etc/system. To prevent
03831d35f7499c87d51205817c93e9a8d42c4baestevel * dynamic setting of drmach_to_putmsg (thereby allowing it to be tuned in
03831d35f7499c87d51205817c93e9a8d42c4baestevel * /etc/system), set drmach_use_tuned_putmsg_to to 1.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint drmach_use_tuned_putmsg_to = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* maximum conceivable message size for future mailbox protocol versions */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_MAX_MBOX_MSG_SIZE 4096
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_mbox_prmsg(dr_mbox_msg_t *mbp, int dir)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i, j;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dr_memregs_t *memregs;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dr_proto_hdr_t *php = &mbp->p_hdr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dr_msg_t *mp = &mbp->msgdata;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (php->command) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRMSG_BOARDEVENT:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dir) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("ERROR!! outgoing BOARDEVENT\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("BOARDEVENT received:\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("init=%d ins=%d rem=%d asgn=%d\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni mp->dm_be.initialized,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni mp->dm_be.board_insertion,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni mp->dm_be.board_removal,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni mp->dm_be.slot_assign);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("unasgn=%d avail=%d unavail=%d\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni mp->dm_be.slot_unassign,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni mp->dm_be.slot_avail,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni mp->dm_be.slot_unavail);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRMSG_MBOX_INIT:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dir) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("MBOX_INIT Request:\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("MBOX_INIT Reply:\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRMSG_ASSIGN:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dir) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("ASSIGN Request:\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("ASSIGN Reply:\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRMSG_UNASSIGN:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dir) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("UNASSIGN Request:\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("UNASSIGN Reply:\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRMSG_CLAIM:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!dir) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("CLAIM Reply:\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("CLAIM Request:\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < 18; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("exp%d: val=%d slice=0x%x\n", i,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni mp->dm_cr.mem_slice[i].valid,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni mp->dm_cr.mem_slice[i].slice);
03831d35f7499c87d51205817c93e9a8d42c4baestevel memregs = &(mp->dm_cr.mem_regs[i]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (j = 0; j < S0_LPORT_COUNT; j++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR(" MC %2d: "
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "MADR[%d] = 0x%lx, "
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "MADR[%d] = 0x%lx\n", j,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni 0, DRMACH_MCREG_TO_U64(
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni memregs->madr[j][0]),
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni 1, DRMACH_MCREG_TO_U64(
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni memregs->madr[j][1]));
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR(" : "
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "MADR[%d] = 0x%lx, "
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "MADR[%d] = 0x%lx\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni 2, DRMACH_MCREG_TO_U64(
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni memregs->madr[j][2]),
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni 3, DRMACH_MCREG_TO_U64(
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni memregs->madr[j][3]));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRMSG_UNCLAIM:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!dir) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("UNCLAIM Reply:\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("UNCLAIM Request:\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < 18; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("exp%d: val=%d slice=0x%x\n", i,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni mp->dm_ur.mem_slice[i].valid,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni mp->dm_ur.mem_slice[i].slice);
03831d35f7499c87d51205817c93e9a8d42c4baestevel memregs = &(mp->dm_ur.mem_regs[i]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (j = 0; j < S0_LPORT_COUNT; j++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR(" MC %2d: "
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "MADR[%d] = 0x%lx, "
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "MADR[%d] = 0x%lx\n", j,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni 0, DRMACH_MCREG_TO_U64(
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni memregs->madr[j][0]),
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni 1, DRMACH_MCREG_TO_U64(
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni memregs->madr[j][1]));
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR(" : "
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "MADR[%d] = 0x%lx, "
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "MADR[%d] = 0x%lx\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni 2, DRMACH_MCREG_TO_U64(
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni memregs->madr[j][2]),
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni 3, DRMACH_MCREG_TO_U64(
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni memregs->madr[j][3]));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR(" mem_clear=%d\n", mp->dm_ur.mem_clear);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRMSG_UNCONFIG:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!dir) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("UNCONFIG Reply:\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("UNCONFIG Request:\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < 18; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("exp%d: val=%d slice=0x%x\n", i,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni mp->dm_uc.mem_slice[i].valid,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni mp->dm_uc.mem_slice[i].slice);
03831d35f7499c87d51205817c93e9a8d42c4baestevel memregs = &(mp->dm_uc.mem_regs[i]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (j = 0; j < S0_LPORT_COUNT; j++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR(" MC %2d: "
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "MADR[%d] = 0x%lx, "
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "MADR[%d] = 0x%lx\n", j,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni 0, DRMACH_MCREG_TO_U64(
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni memregs->madr[j][0]),
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni 1, DRMACH_MCREG_TO_U64(
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni memregs->madr[j][1]));
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR(" : "
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "MADR[%d] = 0x%lx, "
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "MADR[%d] = 0x%lx\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni 2, DRMACH_MCREG_TO_U64(
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni memregs->madr[j][2]),
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni 3, DRMACH_MCREG_TO_U64(
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni memregs->madr[j][3]));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRMSG_POWERON:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dir) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("POWERON Request:\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("POWERON Reply:\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRMSG_POWEROFF:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dir) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("POWEROFF Request:\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("POWEROFF Reply:\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRMSG_TESTBOARD:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dir) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("TESTBOARD Request:\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("\tmemaddrhi=0x%x memaddrlo=0x%x ",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni mp->dm_tb.memaddrhi,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni mp->dm_tb.memaddrlo);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("memlen=0x%x cpu_portid=0x%x\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni mp->dm_tb.memlen, mp->dm_tb.cpu_portid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("\tforce=0x%x imm=0x%x\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni mp->dm_tb.force, mp->dm_tb.immediate);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("TESTBOARD Reply:\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("\tmemaddrhi=0x%x memaddrlo=0x%x ",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni mp->dm_tr.memaddrhi,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni mp->dm_tr.memaddrlo);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("memlen=0x%x cpu_portid=0x%x\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni mp->dm_tr.memlen, mp->dm_tr.cpu_portid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("\trecovered=0x%x test status=0x%x\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni mp->dm_tr.cpu_recovered,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni mp->dm_tr.test_status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRMSG_ABORT_TEST:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dir) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("ABORT_TEST Request:\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("ABORT_TEST Reply:\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("\tmemaddrhi=0x%x memaddrlo=0x%x ",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni mp->dm_ta.memaddrhi,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni mp->dm_ta.memaddrlo);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("memlen=0x%x cpu_portid=0x%x\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni mp->dm_ta.memlen, mp->dm_ta.cpu_portid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRMSG_SHOWBOARD:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dir) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("SHOWBOARD Request:\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("SHOWBOARD Reply:\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR(": empty=%d power=%d assigned=%d",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni mp->dm_sb.slot_empty,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni mp->dm_sb.power_on,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni mp->dm_sb.bd_assigned);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR(": active=%d t_status=%d t_level=%d ",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni mp->dm_sb.bd_active,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni mp->dm_sb.test_status,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni mp->dm_sb.test_level);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR(": type=%s ", mp->dm_sb.board_type);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("Unknown message type\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("dr hdr:\n\tid=0x%x vers=0x%x cmd=0x%x exp=0x%x slot=0x%x\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni php->message_id, php->drproto_version, php->command,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni php->expbrd, php->slot);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("\treply_status=0x%x error_code=0x%x\n", php->reply_status,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni php->error_code);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Callback function passed to taskq_dispatch when a mailbox reinitialization
03831d35f7499c87d51205817c93e9a8d42c4baestevel * handshake needs to be scheduled. The handshake can't be performed by the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * thread that determines it is needed, in most cases, so this function is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * dispatched on the system-wide taskq pool of threads. Failure is reported but
03831d35f7499c87d51205817c93e9a8d42c4baestevel * otherwise ignored, since any situation that requires a mailbox initialization
03831d35f7499c87d51205817c93e9a8d42c4baestevel * handshake will continue to request the handshake until it succeeds.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_mbox_reinit(void *unused)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel _NOTE(ARGUNUSED(unused))
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel caddr_t obufp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *serr = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("scheduled mailbox reinit running\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_ri_mbox_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_g_mbox_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_mbox_iflag == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* need to initialize the mailbox */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_g_mbox_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "!reinitializing DR mailbox");
03831d35f7499c87d51205817c93e9a8d42c4baestevel obufp = kmem_zalloc(sizeof (dr_proto_hdr_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel serr = drmach_mbox_trans(DRMSG_MBOX_INIT, 0, obufp,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni sizeof (dr_proto_hdr_t), (caddr_t)NULL, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(obufp, sizeof (dr_proto_hdr_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (serr) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "mbox_init: MBOX_INIT failed ecode=0x%x",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni serr->e_code);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_err_clear(&serr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_g_mbox_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!serr) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mbox_iflag = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mbox_ipending = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_g_mbox_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_ri_mbox_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * To ensure sufficient compatibility with future versions of the DR mailbox
03831d35f7499c87d51205817c93e9a8d42c4baestevel * protocol, we use a buffer that is large enough to receive the largest message
03831d35f7499c87d51205817c93e9a8d42c4baestevel * that could possibly be sent to us. However, since that ends up being fairly
03831d35f7499c87d51205817c93e9a8d42c4baestevel * large, allocating it on the stack is a bad idea. Fortunately, this function
03831d35f7499c87d51205817c93e9a8d42c4baestevel * does not need to be MT-safe since it is only invoked by the mailbox
03831d35f7499c87d51205817c93e9a8d42c4baestevel * framework, which will never invoke it multiple times concurrently. Since
03831d35f7499c87d51205817c93e9a8d42c4baestevel * that is the case, we can use a static buffer.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_mbox_event(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel static uint8_t buf[DRMACH_MAX_MBOX_MSG_SIZE];
03831d35f7499c87d51205817c93e9a8d42c4baestevel dr_mbox_msg_t *msg = (dr_mbox_msg_t *)buf;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t type = MBOXSC_MSG_EVENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t command = DRMSG_BOARDEVENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t transid = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t length = DRMACH_MAX_MBOX_MSG_SIZE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *hint = "";
03831d35f7499c87d51205817c93e9a8d42c4baestevel int logsys = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel do {
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni err = mboxsc_getmsg(KEY_SCDR, &type, &command, &transid,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni &length, (void *)msg, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } while (err == EAGAIN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* don't try to interpret anything with the wrong version number */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((err == 0) && (msg->p_hdr.drproto_version != DRMBX_VERSION)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "mailbox version mismatch 0x%x vs 0x%x",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni msg->p_hdr.drproto_version, DRMBX_VERSION);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_g_mbox_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mbox_iflag = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* schedule a reinit handshake if one isn't pending */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!drmach_mbox_ipending) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (taskq_dispatch(system_taskq, drmach_mbox_reinit,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni NULL, TQ_NOSLEEP) != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mbox_ipending = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "failed to schedule mailbox reinit");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_g_mbox_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((err != 0) || (msg->p_hdr.reply_status != DRMSG_REPLY_OK)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "Unsolicited mboxsc_getmsg failed: err=0x%x code=0x%x",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni err, msg->p_hdr.error_code);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dr_boardevent_t *be;
03831d35f7499c87d51205817c93e9a8d42c4baestevel be = (dr_boardevent_t *)&msg->msgdata;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* check for initialization event */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (be->initialized) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_g_mbox_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mbox_iflag = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* schedule a reinit handshake if one isn't pending */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!drmach_mbox_ipending) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (taskq_dispatch(system_taskq,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni drmach_mbox_reinit, NULL, TQ_NOSLEEP)
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mbox_ipending = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni cmn_err(CE_WARN, "failed to schedule "
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "mailbox reinit");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_g_mbox_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "!Mailbox Init event received");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* anything else will be a log_sysevent call */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (be->board_insertion) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("Board Insertion event received");
03831d35f7499c87d51205817c93e9a8d42c4baestevel hint = DR_HINT_INSERT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel logsys++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (be->board_removal) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("Board Removal event received");
03831d35f7499c87d51205817c93e9a8d42c4baestevel hint = DR_HINT_REMOVE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel logsys++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (be->slot_assign) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("Slot Assign event received");
03831d35f7499c87d51205817c93e9a8d42c4baestevel logsys++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (be->slot_unassign) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("Slot Unassign event received");
03831d35f7499c87d51205817c93e9a8d42c4baestevel logsys++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (be->slot_avail) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("Slot Available event received");
03831d35f7499c87d51205817c93e9a8d42c4baestevel logsys++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (be->slot_unavail) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("Slot Unavailable event received");
03831d35f7499c87d51205817c93e9a8d42c4baestevel logsys++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (be->power_on) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("Power ON event received");
03831d35f7499c87d51205817c93e9a8d42c4baestevel logsys++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (be->power_off) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("Power OFF event received");
03831d35f7499c87d51205817c93e9a8d42c4baestevel logsys++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (logsys)
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) drmach_log_sysevent(
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni DRMACH_EXPSLOT2BNUM(msg->p_hdr.expbrd,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni msg->p_hdr.slot), hint, SE_NOSLEEP, 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uint32_t
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_get_msgid()
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t rv;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_msglist_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(++drmach_msgid))
03831d35f7499c87d51205817c93e9a8d42c4baestevel ++drmach_msgid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = drmach_msgid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_msglist_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (rv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * unlink an entry from the message transaction list
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * caller must hold drmach_msglist_mutex
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_msglist_unlink(drmach_msglist_t *entry)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mutex_owned(&drmach_msglist_mutex));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (entry->prev) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel entry->prev->next = entry->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (entry->next)
03831d35f7499c87d51205817c93e9a8d42c4baestevel entry->next->prev = entry->prev;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_msglist_first = entry->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (entry->next)
03831d35f7499c87d51205817c93e9a8d42c4baestevel entry->next->prev = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (entry == drmach_msglist_last) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_msglist_last = entry->prev;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_msglist_link(drmach_msglist_t *entry)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_msglist_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_msglist_last) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel entry->prev = drmach_msglist_last;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_msglist_last->next = entry;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_msglist_last = entry;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_msglist_last = drmach_msglist_first = entry;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_msglist_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_mbox_getmsg()
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel register int msgid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel static uint8_t buf[DRMACH_MAX_MBOX_MSG_SIZE];
03831d35f7499c87d51205817c93e9a8d42c4baestevel dr_mbox_msg_t *msg = (dr_mbox_msg_t *)buf;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dr_proto_hdr_t *php;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_msglist_t *found, *entry;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t type = MBOXSC_MSG_REPLY;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t command;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t transid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t length;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel php = &msg->p_hdr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (drmach_getmsg_thread_run != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* get a reply message */
03831d35f7499c87d51205817c93e9a8d42c4baestevel command = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel transid = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel length = DRMACH_MAX_MBOX_MSG_SIZE;
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni err = mboxsc_getmsg(KEY_SCDR, &type, &command, &transid,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni &length, (void *)msg, drmach_to_getmsg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If mboxsc_getmsg returns ETIMEDOUT or EAGAIN, then
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the "error" is really just a normal, transient
03831d35f7499c87d51205817c93e9a8d42c4baestevel * condition and we can retry the operation right away.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Any other error suggests a more serious problem,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ranging from a message being too big for our buffer
03831d35f7499c87d51205817c93e9a8d42c4baestevel * (EMSGSIZE) to total failure of the mailbox layer.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This second class of errors is much less "transient",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * so rather than retrying over and over (and getting
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the same error over and over) as fast as we can,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * we'll sleep for a while before retrying.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((err != ETIMEDOUT) && (err != EAGAIN)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "mboxsc_getmsg failed, err=0x%x", err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel delay(drmach_mbxerr_delay * hz);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mbox_prmsg(msg, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (php->drproto_version != DRMBX_VERSION) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "mailbox version mismatch 0x%x vs 0x%x",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni php->drproto_version, DRMBX_VERSION);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_g_mbox_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mbox_iflag = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* schedule a reinit handshake if one isn't pending */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!drmach_mbox_ipending) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (taskq_dispatch(system_taskq,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni drmach_mbox_reinit, NULL, TQ_NOSLEEP)
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mbox_ipending = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni cmn_err(CE_WARN, "failed to schedule "
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "mailbox reinit");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_g_mbox_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgid = php->message_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel found = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_msglist_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel entry = drmach_msglist_first;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (entry != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (entry->msgid == msgid) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel found = entry;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_msglist_unlink(entry);
03831d35f7499c87d51205817c93e9a8d42c4baestevel entry = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else
03831d35f7499c87d51205817c93e9a8d42c4baestevel entry = entry->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (found) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&found->g_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel found->e_code = php->error_code;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (found->i_buflen > 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy((caddr_t)&msg->msgdata, found->i_buf,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni found->i_buflen);
03831d35f7499c87d51205817c93e9a8d42c4baestevel found->m_reply = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_signal(&found->g_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&found->g_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "!mbox_getmsg: no match for id 0x%x",
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "! cmd = 0x%x, exb = %d, slot = %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel php->command, php->expbrd, php->slot);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_msglist_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "mbox_getmsg: exiting");
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_msglist_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel entry = drmach_msglist_first;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (entry != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (entry->p_flag == 1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel entry->f_error = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&entry->g_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_signal(&entry->g_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&entry->g_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_msglist_unlink(entry);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel entry = entry->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_msglist_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_getmsg_thread_run = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel thread_exit();
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_mbox_sendmsg()
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int err, retry;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_msglist_t *entry;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dr_mbox_msg_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dr_proto_hdr_t *php;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (drmach_sendmsg_thread_run != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Search through the list to find entries awaiting
03831d35f7499c87d51205817c93e9a8d42c4baestevel * transmission to the SC
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_msglist_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel entry = drmach_msglist_first;
03831d35f7499c87d51205817c93e9a8d42c4baestevel retry = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (entry != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (entry->p_flag == 1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel entry = entry->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_msglist_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!retry)
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&entry->s_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = (dr_mbox_msg_t *)entry->o_buf;
03831d35f7499c87d51205817c93e9a8d42c4baestevel php = &mp->p_hdr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mbox_prmsg(mp, 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = mboxsc_putmsg(KEY_DRSC, MBOXSC_MSG_REQUEST,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni php->command, NULL, entry->o_buflen, (void *)mp,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni drmach_to_putmsg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (err) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case EAGAIN:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case EBUSY:
03831d35f7499c87d51205817c93e9a8d42c4baestevel ++retry;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_msglist_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case ETIMEDOUT:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (--entry->o_nretry <= 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni &drmach_msglist_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_msglist_unlink(entry);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni &drmach_msglist_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel entry->f_error = err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel entry->p_flag = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_signal(&entry->s_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ++retry;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni &drmach_msglist_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_msglist_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_msglist_unlink(entry);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_msglist_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel entry->f_error = err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel entry->p_flag = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_signal(&entry->s_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel entry->p_flag = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_signal(&entry->s_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&entry->s_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel retry = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_msglist_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel entry = drmach_msglist_first;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_msglist_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_sendmsg_mutex);
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (void) cv_reltimedwait(&drmach_sendmsg_cv,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni &drmach_sendmsg_mutex, (5 * hz), TR_CLOCK_TICK);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_sendmsg_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "mbox_sendmsg: exiting");
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_msglist_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel entry = drmach_msglist_first;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (entry != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (entry->p_flag == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel entry->f_error = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&entry->s_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_signal(&entry->s_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&entry->s_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_msglist_unlink(entry);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel entry = entry->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_msglist_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_destroy(&drmach_sendmsg_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(&drmach_sendmsg_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_sendmsg_thread_run = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel thread_exit();
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_msglist_destroy(drmach_msglist_t *listp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (listp != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_msglist_t *entry;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_msglist_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel entry = drmach_msglist_first;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (entry) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (listp == entry) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_msglist_unlink(listp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel entry = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else
03831d35f7499c87d51205817c93e9a8d42c4baestevel entry = entry->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(&listp->s_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_destroy(&listp->s_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(&listp->g_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_destroy(&listp->g_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(listp, sizeof (drmach_msglist_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_msglist_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic drmach_msglist_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_msglist_new(caddr_t ibufp, uint32_t ilen, dr_proto_hdr_t *hdrp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t olen, int nrtry)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_msglist_t *listp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel listp = kmem_zalloc(sizeof (drmach_msglist_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(&listp->s_lock, NULL, MUTEX_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_init(&listp->s_cv, NULL, CV_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(&listp->g_lock, NULL, MUTEX_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_init(&listp->g_cv, NULL, CV_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel listp->o_buf = (caddr_t)hdrp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel listp->o_buflen = olen;
03831d35f7499c87d51205817c93e9a8d42c4baestevel listp->i_buf = ibufp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel listp->i_buflen = ilen;
03831d35f7499c87d51205817c93e9a8d42c4baestevel listp->o_nretry = nrtry;
03831d35f7499c87d51205817c93e9a8d42c4baestevel listp->msgid = hdrp->message_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (listp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic drmach_msglist_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_mbox_req_rply(dr_proto_hdr_t *hdrp, uint32_t olen, caddr_t ibufp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t ilen, int timeout, int nrtry, int nosig,
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_msglist_t *link)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int crv;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_msglist_t *listp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel clock_t to_val;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dr_proto_hdr_t *php;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* setup transaction list entry */
03831d35f7499c87d51205817c93e9a8d42c4baestevel listp = drmach_msglist_new(ibufp, ilen, hdrp, olen, nrtry);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* send mailbox message, await reply */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&listp->s_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&listp->g_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel listp->link = link;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_msglist_link(listp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_sendmsg_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_signal(&drmach_sendmsg_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_sendmsg_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (listp->p_flag == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_wait(&listp->s_cv, &listp->s_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni to_val = ddi_get_lbolt() + (timeout * hz);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (listp->f_error) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel listp->p_flag = 0;
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni cmn_err(CE_WARN, "!mboxsc_putmsg failed: 0x%x", listp->f_error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel php = (dr_proto_hdr_t *)listp->o_buf;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "! cmd = 0x%x, exb = %d, slot = %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel php->command, php->expbrd, php->slot);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (listp->m_reply == 0 && listp->f_error == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (nosig)
03831d35f7499c87d51205817c93e9a8d42c4baestevel crv = cv_timedwait(&listp->g_cv, &listp->g_lock,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni to_val);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel crv = cv_timedwait_sig(&listp->g_cv,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni &listp->g_lock, to_val);
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (crv) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case -1: /* timed out */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "!msgid=0x%x reply timed out",
03831d35f7499c87d51205817c93e9a8d42c4baestevel hdrp->message_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel php = (dr_proto_hdr_t *)listp->o_buf;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "! cmd = 0x%x, "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "exb = %d, slot = %d", php->command,
03831d35f7499c87d51205817c93e9a8d42c4baestevel php->expbrd, php->slot);
03831d35f7499c87d51205817c93e9a8d42c4baestevel listp->f_error = ETIMEDOUT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case 0: /* signal received */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "operation interrupted by signal");
03831d35f7499c87d51205817c93e9a8d42c4baestevel listp->f_error = EINTR;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If link is set for this entry, check to see if
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the linked entry has been replied to. If not,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * wait for the response.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Currently, this is only used for ABORT_TEST functionality,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * wherein a check is made for the TESTBOARD reply when
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the ABORT_TEST reply is received.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (link) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&link->g_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the reply to the linked entry hasn't been
03831d35f7499c87d51205817c93e9a8d42c4baestevel * received, clear the existing link->f_error,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and await the reply.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (link->m_reply == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel link->f_error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel to_val = ddi_get_lbolt() + (timeout * hz);
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (link->m_reply == 0 && link->f_error == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel crv = cv_timedwait(&link->g_cv, &link->g_lock,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni to_val);
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (crv) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case -1: /* timed out */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "!link msgid=0x%x reply timed out",
03831d35f7499c87d51205817c93e9a8d42c4baestevel link->msgid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel link->f_error = ETIMEDOUT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&link->g_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&listp->g_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&listp->s_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (listp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_mbx2sbderr(drmach_msglist_t *mlp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel char a_pnt[MAXNAMELEN];
03831d35f7499c87d51205817c93e9a8d42c4baestevel dr_proto_hdr_t *php;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int bnum;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mlp->f_error) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If framework failure is due to signal, return "no error"
03831d35f7499c87d51205817c93e9a8d42c4baestevel * error.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mlp->f_error == EINTR)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_NONE, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_g_mbox_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mbox_iflag = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_g_mbox_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!mlp->p_flag)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(1, ESTC_MBXRQST, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(1, ESTC_MBXRPLY, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel php = (dr_proto_hdr_t *)mlp->o_buf;
03831d35f7499c87d51205817c93e9a8d42c4baestevel bnum = 2 * php->expbrd + php->slot;
03831d35f7499c87d51205817c93e9a8d42c4baestevel a_pnt[0] = '\0';
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) drmach_board_name(bnum, a_pnt, MAXNAMELEN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (mlp->e_code) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case 0:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRERR_NOACL:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_NOACL, "%s", a_pnt));
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRERR_NOT_ASSIGNED:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_NOT_ASSIGNED, "%s", a_pnt));
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRERR_NOT_ACTIVE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_NOT_ACTIVE, "%s", a_pnt));
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRERR_EMPTY_SLOT:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_EMPTY_SLOT, "%s", a_pnt));
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRERR_POWER_OFF:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_POWER_OFF, "%s", a_pnt));
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRERR_TEST_IN_PROGRESS:
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni return (drerr_new(0, ESTC_TEST_IN_PROGRESS, "%s",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni a_pnt));
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRERR_TESTING_BUSY:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_TESTING_BUSY, "%s", a_pnt));
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRERR_TEST_REQUIRED:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_TEST_REQUIRED, "%s", a_pnt));
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRERR_UNAVAILABLE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_UNAVAILABLE, "%s", a_pnt));
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRERR_RECOVERABLE:
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni return (drerr_new(0, ESTC_SMS_ERR_RECOVERABLE, "%s",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni a_pnt));
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRERR_UNRECOVERABLE:
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni return (drerr_new(1, ESTC_SMS_ERR_UNRECOVERABLE, "%s",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni a_pnt));
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(1, ESTC_MBOX_UNKNOWN, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_mbox_trans(uint8_t msgtype, int bnum, caddr_t obufp, int olen,
03831d35f7499c87d51205817c93e9a8d42c4baestevel caddr_t ibufp, int ilen)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int timeout = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int ntries = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int nosignals = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dr_proto_hdr_t *hdrp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_msglist_t *mlp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (msgtype != DRMSG_MBOX_INIT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_ri_mbox_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_g_mbox_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_mbox_iflag == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* need to initialize the mailbox */
03831d35f7499c87d51205817c93e9a8d42c4baestevel dr_proto_hdr_t imsg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_g_mbox_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel imsg.command = DRMSG_MBOX_INIT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel imsg.message_id = drmach_get_msgid();
03831d35f7499c87d51205817c93e9a8d42c4baestevel imsg.drproto_version = DRMBX_VERSION;
03831d35f7499c87d51205817c93e9a8d42c4baestevel imsg.expbrd = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel imsg.slot = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni cmn_err(CE_WARN, "!reinitializing DR mailbox");
03831d35f7499c87d51205817c93e9a8d42c4baestevel mlp = drmach_mbox_req_rply(&imsg, sizeof (imsg), 0, 0,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni 10, 5, 0, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_mbx2sbderr(mlp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If framework failure incoming is encountered on
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the MBOX_INIT [timeout on SMS reply], the error
03831d35f7499c87d51205817c93e9a8d42c4baestevel * type must be changed before returning to caller.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This is to prevent drmach_board_connect() and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * drmach_board_disconnect() from marking boards
03831d35f7499c87d51205817c93e9a8d42c4baestevel * UNUSABLE based on MBOX_INIT failures.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((err != NULL) && (err->e_code == ESTC_MBXRPLY)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "!Changed mbox incoming to outgoing"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " failure on reinit");
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_err_clear(&err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drerr_new(0, ESTC_MBXRQST, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_msglist_destroy(mlp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_ri_mbox_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_g_mbox_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mbox_iflag = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_g_mbox_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_ri_mbox_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel hdrp = (dr_proto_hdr_t *)obufp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* setup outgoing mailbox header */
03831d35f7499c87d51205817c93e9a8d42c4baestevel hdrp->command = msgtype;
03831d35f7499c87d51205817c93e9a8d42c4baestevel hdrp->message_id = drmach_get_msgid();
03831d35f7499c87d51205817c93e9a8d42c4baestevel hdrp->drproto_version = DRMBX_VERSION;
03831d35f7499c87d51205817c93e9a8d42c4baestevel hdrp->expbrd = DRMACH_BNUM2EXP(bnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel hdrp->slot = DRMACH_BNUM2SLOT(bnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (msgtype) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRMSG_MBOX_INIT:
03831d35f7499c87d51205817c93e9a8d42c4baestevel timeout = drmach_to_mbxinit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ntries = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel nosignals = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRMSG_ASSIGN:
03831d35f7499c87d51205817c93e9a8d42c4baestevel timeout = drmach_to_assign;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ntries = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel nosignals = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRMSG_UNASSIGN:
03831d35f7499c87d51205817c93e9a8d42c4baestevel timeout = drmach_to_unassign;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ntries = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel nosignals = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRMSG_POWERON:
03831d35f7499c87d51205817c93e9a8d42c4baestevel timeout = drmach_to_poweron;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ntries = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel nosignals = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRMSG_POWEROFF:
03831d35f7499c87d51205817c93e9a8d42c4baestevel timeout = drmach_to_poweroff;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ntries = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel nosignals = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRMSG_SHOWBOARD:
03831d35f7499c87d51205817c93e9a8d42c4baestevel timeout = drmach_to_showboard;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ntries = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel nosignals = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRMSG_CLAIM:
03831d35f7499c87d51205817c93e9a8d42c4baestevel timeout = drmach_to_claim;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ntries = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel nosignals = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRMSG_UNCLAIM:
03831d35f7499c87d51205817c93e9a8d42c4baestevel timeout = drmach_to_unclaim;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ntries = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel nosignals = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRMSG_UNCONFIG:
03831d35f7499c87d51205817c93e9a8d42c4baestevel timeout = drmach_to_unconfig;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ntries = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel nosignals = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRMSG_TESTBOARD:
03831d35f7499c87d51205817c93e9a8d42c4baestevel timeout = drmach_to_testboard;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ntries = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel nosignals = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni cmn_err(CE_WARN, "Unknown outgoing message type 0x%x",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni msgtype);
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = DRMACH_INTERNAL_ERROR();
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err == NULL) {
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni mlp = drmach_mbox_req_rply(hdrp, olen, ibufp, ilen, timeout,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni ntries, nosignals, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_mbx2sbderr(mlp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * For DRMSG_TESTBOARD attempts which have timed out, or
03831d35f7499c87d51205817c93e9a8d42c4baestevel * been aborted due to a signal received after mboxsc_putmsg()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * has succeeded in sending the message, a DRMSG_ABORT_TEST
03831d35f7499c87d51205817c93e9a8d42c4baestevel * must be sent.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((msgtype == DRMSG_TESTBOARD) && (err != NULL) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((mlp->f_error == EINTR) || ((mlp->f_error == ETIMEDOUT) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel (mlp->p_flag != 0)))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_msglist_t *abmlp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dr_abort_test_t abibuf;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel hdrp->command = DRMSG_ABORT_TEST;
03831d35f7499c87d51205817c93e9a8d42c4baestevel hdrp->message_id = drmach_get_msgid();
03831d35f7499c87d51205817c93e9a8d42c4baestevel abmlp = drmach_mbox_req_rply(hdrp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sizeof (dr_abort_test_t), (caddr_t)&abibuf,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sizeof (abibuf), drmach_to_aborttest, 5, 1, mlp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "test aborted");
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_msglist_destroy(abmlp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_msglist_destroy(mlp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_mbox_init()
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel caddr_t obufp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *serr = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_timeout_range_t mbxtoz;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mbox_istate = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* register the outgoing mailbox */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((err = mboxsc_init(KEY_DRSC, MBOXSC_MBOX_OUT,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni NULL)) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "DR - SC mboxsc_init failed: 0x%x", err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mbox_istate = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* setup the mboxsc_putmsg timeout value */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_use_tuned_putmsg_to) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "!using tuned drmach_to_putmsg = 0x%lx\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_to_putmsg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((err = mboxsc_ctrl(KEY_DRSC,
03831d35f7499c87d51205817c93e9a8d42c4baestevel MBOXSC_CMD_PUTMSG_TIMEOUT_RANGE, &mbxtoz)) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "mboxsc_ctrl failed: 0x%x", err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_to_putmsg = 60000;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_to_putmsg = mboxsc_putmsg_def_timeout() * 6;
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("putmsg range is 0x%lx - 0x%lx value"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " is 0x%lx\n", mbxtoz.min_timeout,
03831d35f7499c87d51205817c93e9a8d42c4baestevel mbxtoz.max_timeout, drmach_to_putmsg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* register the incoming mailbox */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((err = mboxsc_init(KEY_SCDR, MBOXSC_MBOX_IN,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni drmach_mbox_event)) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "SC - DR mboxsc_init failed: 0x%x", err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mbox_istate = 2;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* initialize mutex for mailbox globals */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(&drmach_g_mbox_mutex, NULL, MUTEX_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* initialize mutex for mailbox re-init */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(&drmach_ri_mbox_mutex, NULL, MUTEX_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* initialize mailbox message list elements */
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_msglist_first = drmach_msglist_last = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(&drmach_msglist_mutex, NULL, MUTEX_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(&drmach_sendmsg_mutex, NULL, MUTEX_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_init(&drmach_sendmsg_cv, NULL, CV_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mbox_istate = 3;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* start mailbox sendmsg thread */
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_sendmsg_thread_run = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_sendmsg_thread == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_sendmsg_thread = thread_create(NULL, 0,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void (*)())drmach_mbox_sendmsg, NULL, 0, &p0,
03831d35f7499c87d51205817c93e9a8d42c4baestevel TS_RUN, minclsyspri);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* start mailbox getmsg thread */
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_getmsg_thread_run = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_getmsg_thread == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_getmsg_thread = thread_create(NULL, 0,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void (*)())drmach_mbox_getmsg, NULL, 0, &p0,
03831d35f7499c87d51205817c93e9a8d42c4baestevel TS_RUN, minclsyspri);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel obufp = kmem_zalloc(sizeof (dr_proto_hdr_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel serr = drmach_mbox_trans(DRMSG_MBOX_INIT, 0, obufp,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni sizeof (dr_proto_hdr_t), (caddr_t)NULL, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(obufp, sizeof (dr_proto_hdr_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (serr) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "mbox_init: MBOX_INIT failed ecode=0x%x",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni serr->e_code);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_err_clear(&serr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_g_mbox_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mbox_iflag = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mbox_ipending = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_g_mbox_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_mbox_fini()
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int err, rv = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_mbox_istate > 2) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_getmsg_thread_run = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_sendmsg_thread_run = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "drmach_mbox_fini: waiting for mbox threads...");
03831d35f7499c87d51205817c93e9a8d42c4baestevel while ((drmach_getmsg_thread_run == 0) ||
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (drmach_sendmsg_thread_run == 0)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni cmn_err(CE_WARN, "drmach_mbox_fini: mbox threads done.");
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(&drmach_msglist_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_mbox_istate) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* de-register the outgoing mailbox */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((err = mboxsc_fini(KEY_DRSC)) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "DR - SC mboxsc_fini failed: 0x%x",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_mbox_istate > 1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* de-register the incoming mailbox */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((err = mboxsc_fini(KEY_SCDR)) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "SC - DR mboxsc_fini failed: 0x%x",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(&drmach_g_mbox_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(&drmach_ri_mbox_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (rv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_portid2bnum(int portid)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int slot;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (portid & 0x1f) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case 0: case 1: case 2: case 3: /* cpu/wci devices */
03831d35f7499c87d51205817c93e9a8d42c4baestevel case 0x1e: /* slot 0 axq registers */
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case 8: case 9: /* cpu devices */
03831d35f7499c87d51205817c93e9a8d42c4baestevel case 0x1c: case 0x1d: /* schizo/wci devices */
03831d35f7499c87d51205817c93e9a8d42c4baestevel case 0x1f: /* slot 1 axq registers */
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(0); /* catch in debug kernels */
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (((portid >> 4) & 0x7e) | slot);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern int axq_suspend_iopause;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelhold_rele_branch(dev_info_t *rdip, void *arg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int *holdp = (int *)arg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *name = ddi_node_name(rdip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * For Starcat, we must be children of the root devinfo node
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(ddi_get_parent(rdip) == ddi_root_node());
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = drmach_name2type_idx(name);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Only children of the root devinfo node need to be
03831d35f7499c87d51205817c93e9a8d42c4baestevel * held/released since they are the only valid targets
03831d35f7499c87d51205817c93e9a8d42c4baestevel * of tree operations. This corresponds to the node types
03831d35f7499c87d51205817c93e9a8d42c4baestevel * listed in the drmach_name2type array.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i < 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Not of interest to us */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_WALK_PRUNECHILD);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (*holdp) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(!e_ddi_branch_held(rdip));
03831d35f7499c87d51205817c93e9a8d42c4baestevel e_ddi_branch_hold(rdip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(e_ddi_branch_held(rdip));
03831d35f7499c87d51205817c93e9a8d42c4baestevel e_ddi_branch_rele(rdip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_WALK_PRUNECHILD);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_init(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel pnode_t nodeid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel gdcd_t *gdcd;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int bnum;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *rdip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int hold, circ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_i_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_initialized) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_i_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel gdcd = drmach_gdcd_new();
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (gdcd == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_i_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "drmach_init: failed to access GDCD\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_boards = drmach_array_new(0, MAX_BOARDS - 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodeid = prom_childnode(prom_rootnode());
03831d35f7499c87d51205817c93e9a8d42c4baestevel do {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int portid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmachid_t id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel len = prom_getproplen(nodeid, "portid");
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (len != sizeof (portid))
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel portid = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) prom_getprop(nodeid, "portid", (caddr_t)&portid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (portid == -1)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel bnum = drmach_portid2bnum(portid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_array_get(drmach_boards, bnum, &id) == -1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* portid translated to an invalid board number */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "OBP node 0x%x has"
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni " invalid property value, %s=%u",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni nodeid, "portid", portid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* clean up */
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_array_dispose(drmach_boards,
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_dispose);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_gdcd_dispose(gdcd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_i_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (id == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_t *bp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel l1_slot_stat_t *dcd;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int exp, slot;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp = drmach_board_new(bnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->assigned = !drmach_initialized;
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->powered = !drmach_initialized;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel exp = DRMACH_BNUM2EXP(bnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot = DRMACH_BNUM2SLOT(bnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel dcd = &gdcd->dcd_slot[exp][slot];
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->stardrb_offset =
03831d35f7499c87d51205817c93e9a8d42c4baestevel dcd->l1ss_cpu_drblock_xwd_offset << 3;
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("%s: stardrb_offset=0x%lx\n", bp->cm.name,
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->stardrb_offset);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (gdcd->dcd_slot[exp][slot].l1ss_flags &
03831d35f7499c87d51205817c93e9a8d42c4baestevel L1SSFLG_THIS_L1_NULL_PROC_LPA) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->flags |= DRMACH_NULL_PROC_LPA;
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("%s: NULL proc LPA\n", bp->cm.name);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } while ((nodeid = prom_nextnode(nodeid)) != OBP_NONODE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_cpu_sram_va = vmem_alloc(heap_arena, PAGESIZE, VM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (gdcd->dcd_testcage_log2_mbytes_size != DCD_DR_TESTCAGE_DISABLED) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(gdcd->dcd_testcage_log2_mbytes_size ==
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni gdcd->dcd_testcage_log2_mbytes_align);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_iocage_paddr =
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (uint64_t)gdcd->dcd_testcage_mbyte_PA << 20;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_iocage_size =
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni 1 << (gdcd->dcd_testcage_log2_mbytes_size + 20);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_iocage_vaddr = (caddr_t)vmem_alloc(heap_arena,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni drmach_iocage_size, VM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel hat_devload(kas.a_hat, drmach_iocage_vaddr, drmach_iocage_size,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni mmu_btop(drmach_iocage_paddr),
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni PROT_READ | PROT_WRITE,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni HAT_LOAD_LOCK | HAT_LOAD_NOCONSIST);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("gdcd size=0x%x align=0x%x PA=0x%x\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni gdcd->dcd_testcage_log2_mbytes_size,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni gdcd->dcd_testcage_log2_mbytes_align,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni gdcd->dcd_testcage_mbyte_PA);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("drmach size=0x%x PA=0x%lx VA=0x%p\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni drmach_iocage_size, drmach_iocage_paddr,
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void *)drmach_iocage_vaddr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_iocage_size == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_array_dispose(drmach_boards, drmach_board_dispose);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_boards = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel vmem_free(heap_arena, drmach_cpu_sram_va, PAGESIZE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_gdcd_dispose(gdcd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_i_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "drmach_init: iocage not available\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_gdcd_dispose(gdcd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(&drmach_iocage_lock, NULL, MUTEX_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_init(&drmach_iocage_cv, NULL, CV_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(&drmach_xt_mb_lock, NULL, MUTEX_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(&drmach_bus_sync_lock, NULL, MUTEX_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(&drmach_slice_table_lock, NULL, MUTEX_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&cpu_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_iocage_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(drmach_iocage_is_busy == 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_iocage_is_busy = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_iocage_mem_scrub(drmach_iocage_size);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_iocage_is_busy = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_signal(&drmach_iocage_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_iocage_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&cpu_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_mbox_init() == -1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "DR - SC mailbox initialization Failed");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Walk immediate children of devinfo root node and hold
03831d35f7499c87d51205817c93e9a8d42c4baestevel * all devinfo branches of interest.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel hold = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rdip = ddi_root_node();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_devi_enter(rdip, &circ);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_walk_devs(ddi_get_child(rdip), hold_rele_branch, &hold);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_devi_exit(rdip, circ);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_initialized = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * To avoid a circular patch dependency between DR and AXQ, the AXQ
03831d35f7499c87d51205817c93e9a8d42c4baestevel * rev introducing the axq_iopause_*_all interfaces should not regress
03831d35f7499c87d51205817c93e9a8d42c4baestevel * when installed without the DR rev using those interfaces. The default
03831d35f7499c87d51205817c93e9a8d42c4baestevel * is for iopause to be enabled/disabled during axq suspend/resume. By
03831d35f7499c87d51205817c93e9a8d42c4baestevel * setting the following axq flag to zero, axq will not enable iopause
03831d35f7499c87d51205817c93e9a8d42c4baestevel * during suspend/resume, instead DR will call the axq_iopause_*_all
03831d35f7499c87d51205817c93e9a8d42c4baestevel * interfaces during drmach_copy_rename.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel axq_suspend_iopause = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_i_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_fini(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *rdip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int hold, circ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_initialized) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_enter(&drmach_boards_rwlock, RW_WRITER);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_array_dispose(drmach_boards, drmach_board_dispose);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_boards = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_exit(&drmach_boards_rwlock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(&drmach_slice_table_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(&drmach_xt_mb_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(&drmach_bus_sync_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_destroy(&drmach_iocage_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(&drmach_iocage_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel vmem_free(heap_arena, drmach_cpu_sram_va, PAGESIZE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Walk immediate children of the root devinfo node
03831d35f7499c87d51205817c93e9a8d42c4baestevel * releasing holds acquired on branches in drmach_init()
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel hold = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rdip = ddi_root_node();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_devi_enter(rdip, &circ);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_walk_devs(ddi_get_child(rdip), hold_rele_branch, &hold);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_devi_exit(rdip, circ);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_initialized = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) drmach_mbox_fini();
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_xt_mb != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel vmem_free(static_alloc_arena, (void *)drmach_xt_mb,
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_xt_mb_size);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_destroy(&drmach_boards_rwlock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(&drmach_i_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_mem_read_madr(drmach_mem_t *mp, int bank, uint64_t *madr)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel kpreempt_disable();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* get register address, read madr value */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (STARCAT_CPUID_TO_PORTID(CPU->cpu_id) == mp->dev.portid) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *madr = lddmcdecode(DRMACH_MC_ASI_ADDR(mp, bank));
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *madr = lddphysio(DRMACH_MC_ADDR(mp, bank));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel kpreempt_enable();
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uint64_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_prep_mc_rename(uint64_t *p, int local,
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mem_t *mp, uint64_t current_basepa, uint64_t new_basepa)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int bank;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (bank = 0; bank < DRMACH_MC_NBANKS; bank++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t madr, bank_offset;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* fetch mc's bank madr register value */
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mem_read_madr(mp, bank, &madr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (madr & DRMACH_MC_VALID_MASK) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t bankpa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel bank_offset = (DRMACH_MC_UM_TO_PA(madr) |
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_MC_LM_TO_PA(madr)) - current_basepa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel bankpa = new_basepa + bank_offset;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* encode new base pa into madr */
03831d35f7499c87d51205817c93e9a8d42c4baestevel madr &= ~DRMACH_MC_UM_MASK;
03831d35f7499c87d51205817c93e9a8d42c4baestevel madr |= DRMACH_MC_PA_TO_UM(bankpa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel madr &= ~DRMACH_MC_LM_MASK;
03831d35f7499c87d51205817c93e9a8d42c4baestevel madr |= DRMACH_MC_PA_TO_LM(bankpa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (local)
03831d35f7499c87d51205817c93e9a8d42c4baestevel *p++ = DRMACH_MC_ASI_ADDR(mp, bank);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel *p++ = DRMACH_MC_ADDR(mp, bank);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *p++ = madr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (p);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uint64_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_prep_schizo_script(uint64_t *p, drmach_mem_t *mp, uint64_t new_basepa)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_t *bp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int idx;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmachid_t id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t last_scsr_pa = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* memory is always in slot 0 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(DRMACH_BNUM2SLOT(mp->dev.bp->bnum) == 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* look up slot 1 board on same expander */
03831d35f7499c87d51205817c93e9a8d42c4baestevel idx = DRMACH_EXPSLOT2BNUM(DRMACH_BNUM2EXP(mp->dev.bp->bnum), 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = drmach_array_get(drmach_boards, idx, &id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp = id; /* bp will be NULL if board not found */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* look up should never be out of bounds */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(rv == 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* nothing to do when board is not found or has no devices */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv == -1 || bp == NULL || bp->devices == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (p);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = drmach_array_first(bp->devices, &idx, &id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (rv == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (DRMACH_IS_IO_ID(id)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_io_t *io = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Skip all non-Schizo IO devices (only IO nodes
03831d35f7499c87d51205817c93e9a8d42c4baestevel * that are Schizo devices have non-zero scsr_pa).
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Filter out "other" leaf to avoid writing to the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * same Schizo Control/Status Register twice.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (io->scsr_pa && io->scsr_pa != last_scsr_pa) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t scsr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsr = lddphysio(io->scsr_pa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsr &= ~(DRMACH_LPA_BASE_MASK |
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni DRMACH_LPA_BND_MASK);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsr |= DRMACH_PA_TO_LPA_BASE(new_basepa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsr |= DRMACH_PA_TO_LPA_BND(
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni new_basepa + DRMACH_MEM_SLICE_SIZE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *p++ = io->scsr_pa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel *p++ = scsr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel last_scsr_pa = io->scsr_pa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = drmach_array_next(bp->devices, &idx, &id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (p);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * For Panther MCs, append the MC idle reg address and drmach_mem_t pointer.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The latter is returned when drmach_rename fails to idle a Panther MC and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * is used to identify the MC for error reporting.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uint64_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_prep_pn_mc_idle(uint64_t *p, drmach_mem_t *mp, int local)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* only slot 0 has memory */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(DRMACH_BNUM2SLOT(mp->dev.bp->bnum) == 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(IS_PANTHER(mp->dev.bp->cpu_impl));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (mp = mp->dev.bp->mem; mp != NULL; mp = mp->next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(DRMACH_IS_MEM_ID(mp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mp->dev.portid == STARCAT_CPUID_TO_PORTID(CPU->cpu_id)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (local) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *p++ = ASI_EMU_ACT_STATUS_VA; /* local ASI */
03831d35f7499c87d51205817c93e9a8d42c4baestevel *p++ = (uintptr_t)mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (!local) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *p++ = DRMACH_EMU_ACT_STATUS_ADDR(mp); /* PIO */
03831d35f7499c87d51205817c93e9a8d42c4baestevel *p++ = (uintptr_t)mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (p);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_prep_rename_script(drmach_mem_t *s_mp, drmach_mem_t *t_mp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t t_slice_offset, caddr_t buf, int buflen)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel _NOTE(ARGUNUSED(buflen))
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t *p = (uint64_t *)buf, *q;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mem_t *mp, *skip_mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t s_basepa, t_basepa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t s_new_basepa, t_new_basepa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* verify supplied buffer space is adequate */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(buflen >=
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni /* addr for all possible MC banks */
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (sizeof (uint64_t) * 4 * 4 * 18) +
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni /* list section terminator */
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (sizeof (uint64_t) * 1) +
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni /* addr/id tuple for local Panther MC idle reg */
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (sizeof (uint64_t) * 2) +
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni /* list section terminator */
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (sizeof (uint64_t) * 1) +
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni /* addr/id tuple for 2 boards with 4 Panther MC idle regs */
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (sizeof (uint64_t) * 2 * 2 * 4) +
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni /* list section terminator */
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (sizeof (uint64_t) * 1) +
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni /* addr/val tuple for 1 proc with 4 MC banks */
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (sizeof (uint64_t) * 2 * 4) +
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni /* list section terminator */
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (sizeof (uint64_t) * 1) +
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni /* addr/val tuple for 2 boards w/ 2 schizos each */
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (sizeof (uint64_t) * 2 * 2 * 2) +
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni /* addr/val tuple for 2 boards w/ 16 MC banks each */
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (sizeof (uint64_t) * 2 * 2 * 16) +
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni /* list section terminator */
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (sizeof (uint64_t) * 1) +
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni /* addr/val tuple for 18 AXQs w/ two slots each */
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (sizeof (uint64_t) * 2 * 2 * 18) +
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni /* list section terminator */
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (sizeof (uint64_t) * 1) +
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni /* list terminator */
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (sizeof (uint64_t) * 1));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* copy bank list to rename script */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_bus_sync_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (q = drmach_bus_sync_list; *q; q++, p++)
03831d35f7499c87d51205817c93e9a8d42c4baestevel *p = *q;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_bus_sync_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* list section terminator */
03831d35f7499c87d51205817c93e9a8d42c4baestevel *p++ = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Write idle script for MC on this processor. A script will be
03831d35f7499c87d51205817c93e9a8d42c4baestevel * produced only if this is a Panther processor on the source or
03831d35f7499c87d51205817c93e9a8d42c4baestevel * target board.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IS_PANTHER(s_mp->dev.bp->cpu_impl))
03831d35f7499c87d51205817c93e9a8d42c4baestevel p = drmach_prep_pn_mc_idle(p, s_mp, 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IS_PANTHER(t_mp->dev.bp->cpu_impl))
03831d35f7499c87d51205817c93e9a8d42c4baestevel p = drmach_prep_pn_mc_idle(p, t_mp, 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* list section terminator */
03831d35f7499c87d51205817c93e9a8d42c4baestevel *p++ = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Write idle script for all other MCs on source and target
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Panther boards.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IS_PANTHER(s_mp->dev.bp->cpu_impl))
03831d35f7499c87d51205817c93e9a8d42c4baestevel p = drmach_prep_pn_mc_idle(p, s_mp, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IS_PANTHER(t_mp->dev.bp->cpu_impl))
03831d35f7499c87d51205817c93e9a8d42c4baestevel p = drmach_prep_pn_mc_idle(p, t_mp, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* list section terminator */
03831d35f7499c87d51205817c93e9a8d42c4baestevel *p++ = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Step 1: Write source base address to target MC
03831d35f7499c87d51205817c93e9a8d42c4baestevel * with present bit off.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Step 2: Now rewrite target reg with present bit on.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_mem_get_base_physaddr(s_mp, &s_basepa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(err == NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_mem_get_base_physaddr(t_mp, &t_basepa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(err == NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* exchange base pa. include slice offset in new target base pa */
03831d35f7499c87d51205817c93e9a8d42c4baestevel s_new_basepa = t_basepa & ~ (DRMACH_MEM_SLICE_SIZE - 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel t_new_basepa = (s_basepa & ~ (DRMACH_MEM_SLICE_SIZE - 1)) +
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni t_slice_offset;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("s_new_basepa 0x%lx\n", s_new_basepa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("t_new_basepa 0x%lx\n", t_new_basepa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("preparing MC MADR rename script (master is CPU%d):\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni CPU->cpu_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Write rename script for MC on this processor. A script will
03831d35f7499c87d51205817c93e9a8d42c4baestevel * be produced only if this processor is on the source or target
03831d35f7499c87d51205817c93e9a8d42c4baestevel * board.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel skip_mp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = s_mp->dev.bp->mem;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (mp != NULL && skip_mp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mp->dev.portid == STARCAT_CPUID_TO_PORTID(CPU->cpu_id)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel skip_mp = mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel p = drmach_prep_mc_rename(p, 1, mp, s_basepa,
03831d35f7499c87d51205817c93e9a8d42c4baestevel s_new_basepa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = mp->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = t_mp->dev.bp->mem;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (mp != NULL && skip_mp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mp->dev.portid == STARCAT_CPUID_TO_PORTID(CPU->cpu_id)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel skip_mp = mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel p = drmach_prep_mc_rename(p, 1, mp, t_basepa,
03831d35f7499c87d51205817c93e9a8d42c4baestevel t_new_basepa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = mp->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* list section terminator */
03831d35f7499c87d51205817c93e9a8d42c4baestevel *p++ = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Write rename script for all other MCs on source and target
03831d35f7499c87d51205817c93e9a8d42c4baestevel * boards.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (mp = s_mp->dev.bp->mem; mp; mp = mp->next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mp == skip_mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel p = drmach_prep_mc_rename(p, 0, mp, s_basepa, s_new_basepa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (mp = t_mp->dev.bp->mem; mp; mp = mp->next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mp == skip_mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel p = drmach_prep_mc_rename(p, 0, mp, t_basepa, t_new_basepa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Write rename script for Schizo LPA_BASE/LPA_BND */
03831d35f7499c87d51205817c93e9a8d42c4baestevel p = drmach_prep_schizo_script(p, s_mp, s_new_basepa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel p = drmach_prep_schizo_script(p, t_mp, t_new_basepa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* list section terminator */
03831d35f7499c87d51205817c93e9a8d42c4baestevel *p++ = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("preparing AXQ CASM rename script (EXP%d <> EXP%d):\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni DRMACH_BNUM2EXP(s_mp->dev.bp->bnum),
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni DRMACH_BNUM2EXP(t_mp->dev.bp->bnum));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = axq_do_casm_rename_script(&p,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni DRMACH_PA_TO_SLICE(s_new_basepa),
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni DRMACH_PA_TO_SLICE(t_new_basepa));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv == DDI_FAILURE)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DRMACH_INTERNAL_ERROR());
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* list section & final terminator */
03831d35f7499c87d51205817c93e9a8d42c4baestevel *p++ = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel *p++ = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t *q = (uint64_t *)buf;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* paranoia */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT((caddr_t)p <= buf + buflen);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("MC bank base pa list:\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (*q) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t a = *q++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("0x%lx\n", a);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* skip terminator */
03831d35f7499c87d51205817c93e9a8d42c4baestevel q += 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("local Panther MC idle reg (via ASI 0x4a):\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (*q) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("addr=0x%lx, mp=0x%lx\n", *q, *(q + 1));
03831d35f7499c87d51205817c93e9a8d42c4baestevel q += 2;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* skip terminator */
03831d35f7499c87d51205817c93e9a8d42c4baestevel q += 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("non-local Panther MC idle reg (via ASI 0x15):\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (*q) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("addr=0x%lx, mp=0x%lx\n", *q, *(q + 1));
03831d35f7499c87d51205817c93e9a8d42c4baestevel q += 2;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* skip terminator */
03831d35f7499c87d51205817c93e9a8d42c4baestevel q += 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("MC reprogramming script (via ASI 0x72):\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (*q) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t r = *q++; /* register address */
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t v = *q++; /* new register value */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("0x%lx = 0x%lx, basepa 0x%lx\n",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki r, v, (long)(DRMACH_MC_UM_TO_PA(v)|
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DRMACH_MC_LM_TO_PA(v)));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* skip terminator */
03831d35f7499c87d51205817c93e9a8d42c4baestevel q += 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("MC/SCHIZO reprogramming script:\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (*q) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("0x%lx = 0x%lx\n", *q, *(q + 1));
03831d35f7499c87d51205817c93e9a8d42c4baestevel q += 2;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* skip terminator */
03831d35f7499c87d51205817c93e9a8d42c4baestevel q += 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("AXQ reprogramming script:\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (*q) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("0x%lx = 0x%lx\n", *q, *(q + 1));
03831d35f7499c87d51205817c93e9a8d42c4baestevel q += 2;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* verify final terminator is present */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(*(q + 1) == 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DRMACH_PR("copy-rename script 0x%p, len %d\n",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void *)buf, (int)((intptr_t)p - (intptr_t)buf));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_debug)
03831d35f7499c87d51205817c93e9a8d42c4baestevel DELAY(10000000);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_prep_xt_mb_for_slice_update(drmach_board_t *bp, uchar_t slice)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(MUTEX_HELD(&drmach_xt_mb_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (bp->devices) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int d_idx;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmachid_t d_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = drmach_array_first(bp->devices, &d_idx, &d_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (rv == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (DRMACH_IS_CPU_ID(d_id)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_cpu_t *cp = d_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel processorid_t cpuid = cp->cpuid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&cpu_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cpu[cpuid] && cpu[cpuid]->cpu_flags)
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_xt_mb[cpuid] = 0x80 | slice;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&cpu_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = drmach_array_next(bp->devices, &d_idx, &d_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (DRMACH_BNUM2SLOT(bp->bnum) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_t *s1bp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = drmach_array_get(drmach_boards, bp->bnum + 1,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void *) &s1bp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv == 0 && s1bp != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(DRMACH_IS_BOARD_ID(s1bp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(DRMACH_BNUM2SLOT(s1bp->bnum) == 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_prep_xt_mb_for_slice_update(s1bp, slice);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_copy_rename_init(drmachid_t t_id, uint64_t t_slice_offset,
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmachid_t s_id, struct memlist *c_ml, drmachid_t *cr_id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel extern void drmach_rename(uint64_t *, uint_t *, uint64_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel extern void drmach_rename_end(void);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mem_t *s_mp, *t_mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct memlist *x_ml;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t off_mask, s_copybasepa, t_copybasepa, t_basepa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel caddr_t bp, wp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint_t *p, *q;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel tte_t *tte;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_copy_rename_t *cr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_MEM_ID(s_id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_MEM_ID(t_id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel s_mp = s_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel t_mp = t_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* get starting physical address of target memory */
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_mem_get_base_physaddr(t_id, &t_basepa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* calculate slice offset mask from slice size */
03831d35f7499c87d51205817c93e9a8d42c4baestevel off_mask = DRMACH_MEM_SLICE_SIZE - 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* calculate source and target base pa */
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams s_copybasepa = c_ml->ml_address;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams t_copybasepa =
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams t_basepa + ((c_ml->ml_address & off_mask) - t_slice_offset);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* paranoia */
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams ASSERT((c_ml->ml_address & off_mask) >= t_slice_offset);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* adjust copy memlist addresses to be relative to copy base pa */
03831d35f7499c87d51205817c93e9a8d42c4baestevel x_ml = c_ml;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (x_ml != NULL) {
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams x_ml->ml_address -= s_copybasepa;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams x_ml = x_ml->ml_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t s_basepa, s_size, t_size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel x_ml = c_ml;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams while (x_ml->ml_next != NULL)
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams x_ml = x_ml->ml_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("source copy span: base pa 0x%lx, end pa 0x%lx\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni s_copybasepa,
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams s_copybasepa + x_ml->ml_address + x_ml->ml_size);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("target copy span: base pa 0x%lx, end pa 0x%lx\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni t_copybasepa,
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams t_copybasepa + x_ml->ml_address + x_ml->ml_size);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("copy memlist (relative to copy base pa):\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_MEMLIST_DUMP(c_ml);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_mem_get_base_physaddr(s_id, &s_basepa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(err == NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_mem_get_size(s_id, &s_size);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(err == NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_mem_get_size(t_id, &t_size);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(err == NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("current source base pa 0x%lx, size 0x%lx\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni s_basepa, s_size);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("current target base pa 0x%lx, size 0x%lx\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni t_basepa, t_size);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Map in appropriate cpu sram page */
03831d35f7499c87d51205817c93e9a8d42c4baestevel tte = &drmach_cpu_sram_tte[CPU->cpu_id];
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(TTE_IS_VALID(tte) && TTE_IS_8K(tte) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel TTE_IS_PRIVILEGED(tte) && TTE_IS_LOCKED(tte));
1e2e7a75ddb1eedcefa449ce98fd5862749b72eehuah sfmmu_dtlb_ld_kva(drmach_cpu_sram_va, tte);
1e2e7a75ddb1eedcefa449ce98fd5862749b72eehuah sfmmu_itlb_ld_kva(drmach_cpu_sram_va, tte);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp = wp = drmach_cpu_sram_va;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Make sure the rename routine will fit */
03831d35f7499c87d51205817c93e9a8d42c4baestevel len = (ptrdiff_t)drmach_rename_end - (ptrdiff_t)drmach_rename;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(wp + len < bp + PAGESIZE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* copy text. standard bcopy not designed to work in nc space */
03831d35f7499c87d51205817c93e9a8d42c4baestevel p = (uint_t *)wp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel q = (uint_t *)drmach_rename;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (q < (uint_t *)drmach_rename_end)
03831d35f7499c87d51205817c93e9a8d42c4baestevel *p++ = *q++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* zero remainder. standard bzero not designed to work in nc space */
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (p < (uint_t *)(bp + PAGESIZE))
03831d35f7499c87d51205817c93e9a8d42c4baestevel *p++ = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DRMACH_PR("drmach_rename function 0x%p, len %d\n", (void *)wp, len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp += (len + 15) & ~15;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni err = drmach_prep_rename_script(s_mp, t_mp, t_slice_offset, wp,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni PAGESIZE - (wp - bp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err) {
03831d35f7499c87d51205817c93e9a8d42c4baestevelcleanup:
03831d35f7499c87d51205817c93e9a8d42c4baestevel xt_one(CPU->cpu_id, vtag_flushpage_tl1,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (uint64_t)drmach_cpu_sram_va, (uint64_t)ksfmmup);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* disable and flush CDC */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (axq_cdc_disable_flush_all() != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel axq_cdc_enable_all(); /* paranoia */
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = DRMACH_INTERNAL_ERROR();
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto cleanup;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* mark both memory units busy */
03831d35f7499c87d51205817c93e9a8d42c4baestevel t_mp->dev.busy++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel s_mp->dev.busy++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cr = vmem_alloc(static_alloc_arena, sizeof (drmach_copy_rename_t),
03831d35f7499c87d51205817c93e9a8d42c4baestevel VM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cr->isa = (void *)drmach_copy_rename_init;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cr->data = wp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cr->c_ml = c_ml;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cr->s_mp = s_mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cr->t_mp = t_mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cr->s_copybasepa = s_copybasepa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cr->t_copybasepa = t_copybasepa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cr->ecode = DRMACH_CR_OK;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_slice_table_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_xt_mb_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel bzero((void *)drmach_xt_mb, drmach_xt_mb_size);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (DRMACH_L1_SET_LPA(s_mp->dev.bp) && drmach_reprogram_lpa) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_prep_xt_mb_for_slice_update(s_mp->dev.bp,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni DRMACH_PA_TO_SLICE(t_copybasepa));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (DRMACH_L1_SET_LPA(t_mp->dev.bp) && drmach_reprogram_lpa) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_prep_xt_mb_for_slice_update(t_mp->dev.bp,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni DRMACH_PA_TO_SLICE(s_copybasepa));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *cr_id = cr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint drmach_rename_count;
03831d35f7499c87d51205817c93e9a8d42c4baestevelint drmach_rename_ntries;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_copy_rename_fini(drmachid_t id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_copy_rename_t *cr = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dr_mbox_msg_t *obufp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(cr->isa == (void *)drmach_copy_rename_init);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel axq_cdc_enable_all();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel xt_one(CPU->cpu_id, vtag_flushpage_tl1,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (uint64_t)drmach_cpu_sram_va, (uint64_t)ksfmmup);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (cr->ecode) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRMACH_CR_OK:
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRMACH_CR_MC_IDLE_ERR: {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *dip = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mem_t *mp = (drmach_mem_t *)cr->earg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(DRMACH_IS_MEM_ID(mp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_get_dip(mp, &dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(err == NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(dip != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drerr_new(0, ESBD_MEMFAIL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) ddi_pathname(dip, path);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "failed to idle memory controller %s on %s: "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "copy-rename aborted", path, mp->dev.bp->cm.name);
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(path, MAXPATHLEN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRMACH_CR_IOPAUSE_ERR:
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT((uintptr_t)cr->earg >= 0 &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel (uintptr_t)cr->earg < AXQ_MAX_EXP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drerr_new(0, ESBD_SUSPEND, "EX%d", (uintptr_t)cr->earg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "failed to idle EX%ld AXQ slot1 activity prior"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " to copy-rename", (uintptr_t)cr->earg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DRMACH_CR_ONTRAP_ERR:
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drerr_new(0, ESBD_MEMFAIL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "copy-rename aborted due to uncorrectable "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "memory error");
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = DRMACH_INTERNAL_ERROR();
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "unknown copy-rename error code (%d)\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel cr->ecode);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((DRMACH_L1_SET_LPA(cr->s_mp->dev.bp) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_L1_SET_LPA(cr->t_mp->dev.bp)) && drmach_reprogram_lpa) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < NCPU; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_xt_mb[i])
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("cpu%d ignored drmach_xt_mb", i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_xt_mb_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cr->c_ml != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel memlist_delete(cr->c_ml);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cr->t_mp->dev.busy--;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cr->s_mp->dev.busy--;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_slice_table_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto done;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* update casm shadow for target and source board */
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_slice_table_update(cr->t_mp->dev.bp, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_slice_table_update(cr->s_mp->dev.bp, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_slice_table_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_bus_sync_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_bus_sync_list_update();
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_bus_sync_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Make a good-faith effort to notify the SC about the copy-rename, but
03831d35f7499c87d51205817c93e9a8d42c4baestevel * don't worry if it fails, since a subsequent claim/unconfig/unclaim
03831d35f7499c87d51205817c93e9a8d42c4baestevel * will duplicate the update.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel obufp = kmem_zalloc(sizeof (dr_mbox_msg_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_slice_table_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_msg_memslice_init(obufp->msgdata.dm_uc.mem_slice);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_msg_memregs_init(obufp->msgdata.dm_uc.mem_regs);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_slice_table_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) drmach_mbox_trans(DRMSG_UNCONFIG, cr->s_mp->dev.bp->bnum,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (caddr_t)obufp, sizeof (dr_mbox_msg_t), (caddr_t)NULL, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(obufp, sizeof (dr_mbox_msg_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveldone:
03831d35f7499c87d51205817c93e9a8d42c4baestevel vmem_free(static_alloc_arena, cr, sizeof (drmach_copy_rename_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("waited %d out of %d tries for drmach_rename_wait on %d cpus",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni drmach_rename_ntries, drmach_cpu_ntries, drmach_rename_count);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint drmach_slow_copy = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_copy_rename(drmachid_t id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel extern uint_t getpstate(void);
03831d35f7499c87d51205817c93e9a8d42c4baestevel extern void setpstate(uint_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel extern xcfunc_t drmach_rename_wait;
03831d35f7499c87d51205817c93e9a8d42c4baestevel extern xcfunc_t drmach_rename_done;
03831d35f7499c87d51205817c93e9a8d42c4baestevel extern xcfunc_t drmach_rename_abort;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_copy_rename_t *cr = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t neer;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct memlist *ml;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i, count;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int csize, lnsize;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t caddr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpuset_t cpuset;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint_t pstate;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t exp = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel on_trap_data_t otd;
03831d35f7499c87d51205817c93e9a8d42c4baestevel xcfunc_t *drmach_end_wait_xcall = drmach_rename_done;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(cr->isa == (void *)drmach_copy_rename_init);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(MUTEX_HELD(&cpu_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(cr->ecode == DRMACH_CR_OK);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Prevent slot1 IO from accessing Safari memory bus.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (axq_iopause_enable_all(&exp) != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(exp >= 0 && exp < AXQ_MAX_EXP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cr->ecode = DRMACH_CR_IOPAUSE_ERR;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cr->earg = (void *)(uintptr_t)exp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpuset = cpu_ready_set;
03831d35f7499c87d51205817c93e9a8d42c4baestevel CPUSET_DEL(cpuset, CPU->cpu_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel count = ncpus - 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_rename_count = count; /* for debug */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_xt_ready = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel xt_some(cpuset, drmach_rename_wait, NULL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < drmach_cpu_ntries; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_xt_ready == count)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel DELAY(drmach_cpu_delay);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_rename_ntries = i; /* for debug */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_xt_ready = 0; /* steal the line back */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < NCPU; i++) /* steal the line back, preserve data */
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_xt_mb[i] = drmach_xt_mb[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel caddr = drmach_iocage_paddr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel csize = cpunodes[CPU->cpu_id].ecache_size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel lnsize = cpunodes[CPU->cpu_id].ecache_linesize;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* disable CE reporting */
03831d35f7499c87d51205817c93e9a8d42c4baestevel neer = get_error_enable();
03831d35f7499c87d51205817c93e9a8d42c4baestevel set_error_enable(neer & ~EN_REG_CEEN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* disable interrupts (paranoia) */
03831d35f7499c87d51205817c93e9a8d42c4baestevel pstate = getpstate();
03831d35f7499c87d51205817c93e9a8d42c4baestevel setpstate(pstate & ~PSTATE_IE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Execute copy-rename under on_trap to protect against a panic due
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to an uncorrectable error. Instead, DR will abort the copy-rename
03831d35f7499c87d51205817c93e9a8d42c4baestevel * operation and rely on the OS to do the error reporting.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * In general, trap handling on any cpu once the copy begins
03831d35f7499c87d51205817c93e9a8d42c4baestevel * can result in an inconsistent memory image on the target.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (on_trap(&otd, OT_DATA_EC)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cr->ecode = DRMACH_CR_ONTRAP_ERR;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto copy_rename_end;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DO COPY.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams for (ml = cr->c_ml; ml; ml = ml->ml_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t s_pa, t_pa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t nbytes;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams s_pa = cr->s_copybasepa + ml->ml_address;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams t_pa = cr->t_copybasepa + ml->ml_address;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams nbytes = ml->ml_size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (nbytes != 0ull) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* copy 32 bytes at src_pa to dst_pa */
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy32_il(s_pa, t_pa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* increment by 32 bytes */
03831d35f7499c87d51205817c93e9a8d42c4baestevel s_pa += (4 * sizeof (uint64_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel t_pa += (4 * sizeof (uint64_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* decrement by 32 bytes */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nbytes -= (4 * sizeof (uint64_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_slow_copy) { /* for debug */
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t i = 13 * 50;
f500b19684bd0346ac05bec02a50af07f369da1aRichard Bean while (i--)
f500b19684bd0346ac05bec02a50af07f369da1aRichard Bean ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XXX CHEETAH SUPPORT
03831d35f7499c87d51205817c93e9a8d42c4baestevel * For cheetah, we need to grab the iocage lock since iocage
03831d35f7499c87d51205817c93e9a8d42c4baestevel * memory is used for e$ flush.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * NOTE: This code block is dangerous at this point in the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * copy-rename operation. It modifies memory after the copy
03831d35f7499c87d51205817c93e9a8d42c4baestevel * has taken place which means that any persistent state will
03831d35f7499c87d51205817c93e9a8d42c4baestevel * be abandoned after the rename operation. The code is also
03831d35f7499c87d51205817c93e9a8d42c4baestevel * performing thread synchronization at a time when all but
03831d35f7499c87d51205817c93e9a8d42c4baestevel * one processors are paused. This is a potential deadlock
03831d35f7499c87d51205817c93e9a8d42c4baestevel * situation.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This code block must be moved to drmach_copy_rename_init.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_is_cheetah) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_iocage_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (drmach_iocage_is_busy)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_wait(&drmach_iocage_cv, &drmach_iocage_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_iocage_is_busy = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_iocage_mem_scrub(ecache_size * 2);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_iocage_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * bcopy32_il is implemented as a series of ldxa/stxa via
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ASI_MEM instructions. Following the copy loop, the E$
03831d35f7499c87d51205817c93e9a8d42c4baestevel * of the master (this) processor will have lines in state
03831d35f7499c87d51205817c93e9a8d42c4baestevel * O that correspond to lines of home memory in state gI.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * An E$ flush is necessary to commit these lines before
03831d35f7499c87d51205817c93e9a8d42c4baestevel * proceeding with the rename operation.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Flushing the E$ will automatically flush the W$, but
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the D$ and I$ must be flushed separately and explicitly.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel flush_ecache_il(caddr, csize, lnsize); /* inline version */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Each line of home memory is now in state gM, except in
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the case of a cheetah processor when the E$ flush area
03831d35f7499c87d51205817c93e9a8d42c4baestevel * is included within the copied region. In such a case,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the lines of home memory for the upper half of the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * flush area are in state gS.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Each line of target memory is in state gM.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Each line of this processor's E$ is in state I, except
03831d35f7499c87d51205817c93e9a8d42c4baestevel * those of a cheetah processor. All lines of a cheetah
03831d35f7499c87d51205817c93e9a8d42c4baestevel * processor's E$ are in state S and correspond to the lines
03831d35f7499c87d51205817c93e9a8d42c4baestevel * in upper half of the E$ flush area.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * It is vital at this point that none of the lines in the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * home or target memories are in state gI and that none
03831d35f7499c87d51205817c93e9a8d42c4baestevel * of the lines in this processor's E$ are in state O or Os.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * A single instance of such a condition will cause loss of
03831d35f7499c87d51205817c93e9a8d42c4baestevel * coherency following the rename operation.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Rename
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel (*(void(*)())drmach_cpu_sram_va)(cr->data, &cr->ecode, &cr->earg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Rename operation complete. The physical address space
03831d35f7499c87d51205817c93e9a8d42c4baestevel * of the home and target memories have been swapped, the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * routing data in the respective CASM entries have been
03831d35f7499c87d51205817c93e9a8d42c4baestevel * swapped, and LPA settings in the processor and schizo
03831d35f7499c87d51205817c93e9a8d42c4baestevel * devices have been reprogrammed accordingly.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * In the case of a cheetah processor, the E$ remains
03831d35f7499c87d51205817c93e9a8d42c4baestevel * populated with lines in state S that correspond to the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * lines in the former home memory. Now that the physical
03831d35f7499c87d51205817c93e9a8d42c4baestevel * addresses have been swapped, these E$ lines correspond
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to lines in the new home memory which are in state gM.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This combination is invalid. An additional E$ flush is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * necessary to restore coherency. The E$ flush will cause
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the lines of the new home memory for the flush region
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to transition from state gM to gS. The former home memory
03831d35f7499c87d51205817c93e9a8d42c4baestevel * remains unmodified. This additional E$ flush has no effect
03831d35f7499c87d51205817c93e9a8d42c4baestevel * on a cheetah+ processor.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel flush_ecache_il(caddr, csize, lnsize); /* inline version */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The D$ and I$ must be flushed to ensure that coherency is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * maintained. Any line in a cache that is in the valid
03831d35f7499c87d51205817c93e9a8d42c4baestevel * state has its corresponding line of the new home memory
03831d35f7499c87d51205817c93e9a8d42c4baestevel * in the gM state. This is an invalid condition. When the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * flushes are complete the cache line states will be
03831d35f7499c87d51205817c93e9a8d42c4baestevel * resynchronized with those in the new home memory.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel flush_icache_il(); /* inline version */
03831d35f7499c87d51205817c93e9a8d42c4baestevel flush_dcache_il(); /* inline version */
03831d35f7499c87d51205817c93e9a8d42c4baestevel flush_pcache_il(); /* inline version */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelcopy_rename_end:
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel no_trap();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* enable interrupts */
03831d35f7499c87d51205817c93e9a8d42c4baestevel setpstate(pstate);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* enable CE reporting */
03831d35f7499c87d51205817c93e9a8d42c4baestevel set_error_enable(neer);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cr->ecode != DRMACH_CR_OK)
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_end_wait_xcall = drmach_rename_abort;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XXX CHEETAH SUPPORT
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_is_cheetah) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_iocage_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_iocage_mem_scrub(ecache_size * 2);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_iocage_is_busy = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_signal(&drmach_iocage_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_iocage_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel axq_iopause_disable_all();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel xt_some(cpuset, drmach_end_wait_xcall, NULL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void drmach_io_dispose(drmachid_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *drmach_io_release(drmachid_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *drmach_io_status(drmachid_t, drmach_status_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_pci_new(drmach_device_t *proto, drmachid_t *idp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_node_t *node = proto->node;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_reg_t regs[3];
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int len = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = node->n_getproplen(node, "reg", &len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv != 0 || len != sizeof (regs)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* pci nodes are expected to have regs */
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drerr_new(1, ESTC_GETPROP,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "Device Node 0x%x: property %s",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (uint_t)node->get_dnode(node), "reg");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = node->n_getprop(node, "reg", (void *)regs, sizeof (regs));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drerr_new(1, ESTC_GETPROP,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "Device Node 0x%x: property %s",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (uint_t)node->get_dnode(node), "reg");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Fix up unit number so that Leaf A has a lower unit number
03831d35f7499c87d51205817c93e9a8d42c4baestevel * than Leaf B.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((proto->portid % 2) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((regs[0].reg_addr_lo & 0x700000) == 0x700000)
03831d35f7499c87d51205817c93e9a8d42c4baestevel proto->unum = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel proto->unum = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((regs[0].reg_addr_lo & 0x700000) == 0x700000)
03831d35f7499c87d51205817c93e9a8d42c4baestevel proto->unum = 2;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel proto->unum = 3;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_io_new(proto, idp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_io_t *self = *idp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* reassemble 64-bit base address */
03831d35f7499c87d51205817c93e9a8d42c4baestevel self->scsr_pa = (uint64_t)regs[1].reg_addr_hi << 32;
03831d35f7499c87d51205817c93e9a8d42c4baestevel self->scsr_pa |= (uint64_t)regs[1].reg_addr_lo;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_io_new(drmach_device_t *proto, drmachid_t *idp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_io_t *ip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ip = kmem_zalloc(sizeof (drmach_io_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy(proto, &ip->dev, sizeof (ip->dev));
03831d35f7499c87d51205817c93e9a8d42c4baestevel ip->dev.node = drmach_node_dup(proto->node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ip->dev.cm.isa = (void *)drmach_io_new;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ip->dev.cm.dispose = drmach_io_dispose;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ip->dev.cm.release = drmach_io_release;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ip->dev.cm.status = drmach_io_status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) snprintf(ip->dev.cm.name, sizeof (ip->dev.cm.name), "%s%d",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni ip->dev.type, ip->dev.unum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *idp = (drmachid_t)ip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_io_dispose(drmachid_t id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_io_t *self;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(DRMACH_IS_IO_ID(id));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel self = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (self->dev.node)
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_node_dispose(self->dev.node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(self, sizeof (*self));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_pre_op(int cmd, drmachid_t id, drmach_opts_t *opts)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_t *bp = (drmach_board_t *)id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (id && DRMACH_IS_BOARD_ID(id)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (cmd) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SBD_CMD_TEST:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SBD_CMD_STATUS:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SBD_CMD_GETNCM:
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SBD_CMD_CONNECT:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (bp->connected)
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drerr_new(0, ESBD_STATE, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (bp->cond == SBD_COND_UNUSABLE)
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drerr_new(0,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni ESBD_FATAL_STATE, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SBD_CMD_DISCONNECT:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!bp->connected)
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drerr_new(0, ESBD_STATE, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (bp->cond == SBD_COND_UNUSABLE)
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drerr_new(0,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni ESBD_FATAL_STATE, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (bp->cond == SBD_COND_UNUSABLE)
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drerr_new(0,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni ESBD_FATAL_STATE, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_post_op(int cmd, drmachid_t id, drmach_opts_t *opts)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_board_assign(int bnum, drmachid_t *id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel caddr_t obufp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!drmach_initialized && drmach_init() == -1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = DRMACH_INTERNAL_ERROR();
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_enter(&drmach_boards_rwlock, RW_WRITER);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!err) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_array_get(drmach_boards, bnum, id) == -1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drerr_new(0, ESTC_BNUM, "%d", bnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_t *bp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (*id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_downgrade(&drmach_boards_rwlock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel obufp = kmem_zalloc(sizeof (dr_proto_hdr_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_mbox_trans(DRMSG_ASSIGN, bnum, obufp,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni sizeof (dr_proto_hdr_t), (caddr_t)NULL, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(obufp, sizeof (dr_proto_hdr_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!err) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp = *id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!*id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp = *id =
03831d35f7499c87d51205817c93e9a8d42c4baestevel (drmachid_t)drmach_board_new(bnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->assigned = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_exit(&drmach_boards_rwlock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uint_t
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_board_non_panther_cpus(gdcd_t *gdcd, uint_t exp, uint_t slot)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint_t port, port_start, port_end;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint_t non_panther_cpus = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint_t impl;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(gdcd != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Determine PRD port indices based on slot location.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (slot) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case 0:
03831d35f7499c87d51205817c93e9a8d42c4baestevel port_start = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel port_end = 3;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case 1:
03831d35f7499c87d51205817c93e9a8d42c4baestevel port_start = 4;
03831d35f7499c87d51205817c93e9a8d42c4baestevel port_end = 5;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* check all */
03831d35f7499c87d51205817c93e9a8d42c4baestevel port_start = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel port_end = 5;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (port = port_start; port <= port_end; port++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (gdcd->dcd_prd[exp][port].prd_ptype == SAFPTYPE_CPU &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel RSV_GOOD(gdcd->dcd_prd[exp][port].prd_prsv)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This Safari port passed POST and represents a
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cpu, so check the implementation.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel impl = (gdcd->dcd_prd[exp][port].prd_ver_reg >> 32)
03831d35f7499c87d51205817c93e9a8d42c4baestevel & 0xffff;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (impl) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case CHEETAH_IMPL:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case CHEETAH_PLUS_IMPL:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case JAGUAR_IMPL:
03831d35f7499c87d51205817c93e9a8d42c4baestevel non_panther_cpus++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case PANTHER_IMPL:
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel non_panther_cpus++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("drmach_board_non_panther_cpus: exp=%d, slot=%d, "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "non_panther_cpus=%d", exp, slot, non_panther_cpus);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (non_panther_cpus);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_board_connect(drmachid_t id, drmach_opts_t *opts)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel _NOTE(ARGUNUSED(opts))
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_t *bp = (drmach_board_t *)id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dr_mbox_msg_t *obufp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel gdcd_t *gdcd = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint_t exp, slot;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sc_gptwocfg_cookie_t scc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int panther_pages_enabled;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_BOARD_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Build the casm info portion of the CLAIM message.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel obufp = kmem_zalloc(sizeof (dr_mbox_msg_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_slice_table_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_msg_memslice_init(obufp->msgdata.dm_cr.mem_slice);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_msg_memregs_init(obufp->msgdata.dm_cr.mem_regs);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_slice_table_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_mbox_trans(DRMSG_CLAIM, bp->bnum, (caddr_t)obufp,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni sizeof (dr_mbox_msg_t), (caddr_t)NULL, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(obufp, sizeof (dr_mbox_msg_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if mailbox timeout or unrecoverable error from SC,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * board cannot be touched. Mark the status as
03831d35f7499c87d51205817c93e9a8d42c4baestevel * unusable.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((err->e_code == ESTC_SMS_ERR_UNRECOVERABLE) ||
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (err->e_code == ESTC_MBXRPLY))
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni bp->cond = SBD_COND_UNUSABLE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel gdcd = drmach_gdcd_new();
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (gdcd == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "failed to read GDCD info for %s\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->cm.name);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DRMACH_INTERNAL_ERROR());
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Read CPU SRAM DR buffer offset from GDCD.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel exp = DRMACH_BNUM2EXP(bp->bnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot = DRMACH_BNUM2SLOT(bp->bnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->stardrb_offset =
03831d35f7499c87d51205817c93e9a8d42c4baestevel gdcd->dcd_slot[exp][slot].l1ss_cpu_drblock_xwd_offset << 3;
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("%s: stardrb_offset=0x%lx\n", bp->cm.name,
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->stardrb_offset);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Read board LPA setting from GDCD.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->flags &= ~DRMACH_NULL_PROC_LPA;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (gdcd->dcd_slot[exp][slot].l1ss_flags &
03831d35f7499c87d51205817c93e9a8d42c4baestevel L1SSFLG_THIS_L1_NULL_PROC_LPA) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->flags |= DRMACH_NULL_PROC_LPA;
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("%s: NULL proc LPA\n", bp->cm.name);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XXX Until the Solaris large pages support heterogeneous cpu
03831d35f7499c87d51205817c93e9a8d42c4baestevel * domains, DR needs to prevent the addition of non-Panther cpus
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to an all-Panther domain with large pages enabled.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel panther_pages_enabled = (page_num_pagesizes() > DEFAULT_MMU_PAGE_SIZES);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_board_non_panther_cpus(gdcd, exp, slot) > 0 &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel panther_pages_enabled && drmach_large_page_restriction) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "Domain shutdown is required to add a non-"
03831d35f7499c87d51205817c93e9a8d42c4baestevel "UltraSPARC-IV+ board into an all UltraSPARC-IV+ domain");
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drerr_new(0, ESTC_SUPPORT, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* do saf configurator stuff */
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("calling sc_probe_board for bnum=%d\n", bp->bnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scc = sc_probe_board(bp->bnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scc == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drerr_new(0, ESTC_PROBE, bp->cm.name);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* flush CDC srams */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (axq_cdc_flush_all() != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto out;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Build the casm info portion of the UNCLAIM message.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel obufp = kmem_zalloc(sizeof (dr_mbox_msg_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_slice_table_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_msg_memslice_init(obufp->msgdata.dm_ur.mem_slice);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_msg_memregs_init(obufp->msgdata.dm_ur.mem_regs);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_slice_table_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) drmach_mbox_trans(DRMSG_UNCLAIM, bp->bnum,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (caddr_t)obufp, sizeof (dr_mbox_msg_t),
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (caddr_t)NULL, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(obufp, sizeof (dr_mbox_msg_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * we clear the connected flag just in case it would have
03831d35f7499c87d51205817c93e9a8d42c4baestevel * been set by a concurrent drmach_board_status() thread
03831d35f7499c87d51205817c93e9a8d42c4baestevel * before the UNCLAIM completed.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->connected = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto out;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Now that the board has been successfully attached, obtain
03831d35f7499c87d51205817c93e9a8d42c4baestevel * platform-specific DIMM serial id information for the board.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((DRMACH_BNUM2SLOT(bp->bnum) == 0) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel plat_ecc_capability_sc_get(PLAT_ECC_DIMM_SID_MESSAGE)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) plat_request_mem_sids(DRMACH_BNUM2EXP(bp->bnum));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelout:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (gdcd != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_gdcd_dispose(gdcd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_slice_table_update(drmach_board_t *bp, int invalidate)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel static char *axq_name = "address-extender-queue";
03831d35f7499c87d51205817c93e9a8d42c4baestevel static dev_info_t *axq_dip = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel static int axq_exp = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel static int axq_slot;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int e, s, slice;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(MUTEX_HELD(&drmach_slice_table_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel e = DRMACH_BNUM2EXP(bp->bnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (invalidate) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(DRMACH_BNUM2SLOT(bp->bnum) == 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* invalidate cached casm value */
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_slice_table[e] = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* invalidate cached axq info if for same exp */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (e == axq_exp && axq_dip) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_rele_devi(axq_dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel axq_dip = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (axq_dip == NULL || !i_ddi_devi_attached(axq_dip)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i, portid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* search for an attached slot0 axq instance */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < AXQ_MAX_EXP * AXQ_MAX_SLOT_PER_EXP; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (axq_dip)
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_rele_devi(axq_dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel axq_dip = ddi_find_devinfo(axq_name, i, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (axq_dip && DDI_CF2(axq_dip)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel portid = ddi_getprop(DDI_DEV_T_ANY, axq_dip,
03831d35f7499c87d51205817c93e9a8d42c4baestevel DDI_PROP_DONTPASS, "portid", -1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (portid == -1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("cant get portid of axq "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "instance %d\n", i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel axq_exp = (portid >> 5) & 0x1f;
03831d35f7499c87d51205817c93e9a8d42c4baestevel axq_slot = portid & 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (invalidate && axq_exp == e)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (axq_slot == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break; /* found */
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i == AXQ_MAX_EXP * AXQ_MAX_SLOT_PER_EXP) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (axq_dip) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_rele_devi(axq_dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel axq_dip = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("drmach_slice_table_update: failed to "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "update axq dip\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(axq_dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(axq_slot == 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (invalidate)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel s = DRMACH_BNUM2SLOT(bp->bnum);
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni DRMACH_PR("using AXQ casm %d.%d for slot%d.%d\n", axq_exp, axq_slot,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni e, s);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* invalidate entry */
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_slice_table[e] &= ~0x20;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * find a slice that routes to expander e. If no match
03831d35f7499c87d51205817c93e9a8d42c4baestevel * is found, drmach_slice_table[e] will remain invalid.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The CASM is a routing table indexed by slice number.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Each element in the table contains permission bits,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * a destination expander number and a valid bit. The
03831d35f7499c87d51205817c93e9a8d42c4baestevel * valid bit must true for the element to be meaningful.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CASM entry structure
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Bits 15..6 ignored
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Bit 5 valid
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Bits 0..4 expander number
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * NOTE: the for loop is really enumerating the range of slices,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * which is ALWAYS equal to the range of expanders. Hence,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * AXQ_MAX_EXP is okay to use in this loop.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (slice = 0; slice < AXQ_MAX_EXP; slice++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t casm = axq_casm_read(axq_exp, axq_slot, slice);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((casm & 0x20) && (casm & 0x1f) == e)
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_slice_table[e] = 0x20 | slice;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Get base and bound PAs for slot 1 board lpa programming
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If a cpu/mem board is present in the same expander, use slice
03831d35f7499c87d51205817c93e9a8d42c4baestevel * information corresponding to the CASM. Otherwise, set base and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * bound PAs to 0.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_lpa_bb_get(drmach_board_t *s1bp, uint64_t *basep, uint64_t *boundp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmachid_t s0id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mutex_owned(&drmach_slice_table_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(DRMACH_BNUM2SLOT(s1bp->bnum) == 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *basep = *boundp = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_array_get(drmach_boards, s1bp->bnum - 1, &s0id) == 0 &&
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni s0id != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t slice;
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni if ((slice = drmach_slice_table[DRMACH_BNUM2EXP(s1bp->bnum)])
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni & 0x20) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *basep = DRMACH_SLICE_TO_PA(slice & DRMACH_SLICE_MASK);
03831d35f7499c87d51205817c93e9a8d42c4baestevel *boundp = *basep + DRMACH_MEM_SLICE_SIZE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Reprogram slot 1 lpa's as required.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The purpose of this routine is maintain the LPA settings of the devices
03831d35f7499c87d51205817c93e9a8d42c4baestevel * in slot 1. To date we know Schizo and Cheetah are the only devices that
03831d35f7499c87d51205817c93e9a8d42c4baestevel * require this attention. The LPA setting must match the slice field in the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CASM element for the local expander. This field is guaranteed to be
03831d35f7499c87d51205817c93e9a8d42c4baestevel * programmed in accordance with the cacheable address space on the slot 0
03831d35f7499c87d51205817c93e9a8d42c4baestevel * board of the local expander. If no memory is present on the slot 0 board,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * there is no cacheable address space and, hence, the CASM slice field will
03831d35f7499c87d51205817c93e9a8d42c4baestevel * be zero or its valid bit will be false (or both).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_slot1_lpa_set(drmach_board_t *bp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmachid_t id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_t *s1bp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv, idx, is_maxcat = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t last_scsr_pa = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t new_basepa, new_boundpa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (DRMACH_BNUM2SLOT(bp->bnum)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel s1bp = bp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (s1bp->devices == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("drmach...lpa_set: slot1=%d not present",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni bp->bnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = drmach_array_get(drmach_boards, bp->bnum + 1, &id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* nothing to do when board is not found or has no devices */
03831d35f7499c87d51205817c93e9a8d42c4baestevel s1bp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv == -1 || s1bp == NULL || s1bp->devices == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("drmach...lpa_set: slot1=%d not present",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni bp->bnum + 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(DRMACH_IS_BOARD_ID(id));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_slice_table_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_lpa_bb_get(s1bp, &new_basepa, &new_boundpa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("drmach_...lpa_set: bnum=%d base=0x%lx bound=0x%lx\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni s1bp->bnum, new_basepa, new_boundpa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = drmach_array_first(s1bp->devices, &idx, &id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (rv == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (DRMACH_IS_IO_ID(id)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_io_t *io = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel is_maxcat = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Skip all non-Schizo IO devices (only IO nodes
03831d35f7499c87d51205817c93e9a8d42c4baestevel * that are Schizo devices have non-zero scsr_pa).
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Filter out "other" leaf to avoid writing to the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * same Schizo Control/Status Register twice.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (io->scsr_pa && io->scsr_pa != last_scsr_pa) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t scsr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsr = lddphysio(io->scsr_pa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("drmach...lpa_set: old scsr=0x%lx\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni scsr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsr &= ~(DRMACH_LPA_BASE_MASK |
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni DRMACH_LPA_BND_MASK);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsr |= DRMACH_PA_TO_LPA_BASE(new_basepa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsr |= DRMACH_PA_TO_LPA_BND(new_boundpa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel stdphysio(io->scsr_pa, scsr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("drmach...lpa_set: new scsr=0x%lx\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni scsr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel last_scsr_pa = io->scsr_pa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = drmach_array_next(s1bp->devices, &idx, &id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (is_maxcat && DRMACH_L1_SET_LPA(s1bp) && drmach_reprogram_lpa) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel extern xcfunc_t drmach_set_lpa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("reprogramming maxcat lpa's");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&cpu_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = drmach_array_first(s1bp->devices, &idx, &id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (rv == 0 && id != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (DRMACH_IS_CPU_ID(id)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int ntries;
03831d35f7499c87d51205817c93e9a8d42c4baestevel processorid_t cpuid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpuid = ((drmach_cpu_t *)id)->cpuid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check for unconfigured or powered-off
03831d35f7499c87d51205817c93e9a8d42c4baestevel * MCPUs. If CPU_READY flag is clear, the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * MCPU cannot be xcalled.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((cpu[cpuid] == NULL) ||
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (cpu[cpuid]->cpu_flags &
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni CPU_READY) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = drmach_array_next(s1bp->devices,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni &idx, &id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XXX CHEETAH SUPPORT
03831d35f7499c87d51205817c93e9a8d42c4baestevel * for cheetah, we need to clear iocage
03831d35f7499c87d51205817c93e9a8d42c4baestevel * memory since it will be used for e$ flush
03831d35f7499c87d51205817c93e9a8d42c4baestevel * in drmach_set_lpa.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_is_cheetah) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_iocage_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (drmach_iocage_is_busy)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_wait(&drmach_iocage_cv,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni &drmach_iocage_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_iocage_is_busy = 1;
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni drmach_iocage_mem_scrub(ecache_size *
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni 2);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_iocage_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * drmach_slice_table[*]
03831d35f7499c87d51205817c93e9a8d42c4baestevel * bit 5 valid
03831d35f7499c87d51205817c93e9a8d42c4baestevel * bit 0:4 slice number
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * drmach_xt_mb[*] format for drmach_set_lpa
03831d35f7499c87d51205817c93e9a8d42c4baestevel * bit 7 valid
03831d35f7499c87d51205817c93e9a8d42c4baestevel * bit 6 set null LPA
03831d35f7499c87d51205817c93e9a8d42c4baestevel * (overrides bits 0:4)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * bit 0:4 slice number
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * drmach_set_lpa derives processor CBASE and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CBND from bits 6 and 0:4 of drmach_xt_mb.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If bit 6 is set, then CBASE = CBND = 0.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Otherwise, CBASE = slice number;
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CBND = slice number + 1.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * No action is taken if bit 7 is zero.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_xt_mb_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel bzero((void *)drmach_xt_mb,
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_xt_mb_size);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (new_basepa == 0 && new_boundpa == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_xt_mb[cpuid] = 0x80 | 0x40;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_xt_mb[cpuid] = 0x80 |
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni DRMACH_PA_TO_SLICE(new_basepa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_xt_ready = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel xt_one(cpuid, drmach_set_lpa, NULL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ntries = drmach_cpu_ntries;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (!drmach_xt_ready && ntries) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DELAY(drmach_cpu_delay);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ntries--;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_xt_mb_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_xt_ready = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XXX CHEETAH SUPPORT
03831d35f7499c87d51205817c93e9a8d42c4baestevel * for cheetah, we need to clear iocage
03831d35f7499c87d51205817c93e9a8d42c4baestevel * memory since it was used for e$ flush
03831d35f7499c87d51205817c93e9a8d42c4baestevel * in performed drmach_set_lpa.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_is_cheetah) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_iocage_lock);
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni drmach_iocage_mem_scrub(ecache_size *
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni 2);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_iocage_is_busy = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_signal(&drmach_iocage_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_iocage_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = drmach_array_next(s1bp->devices, &idx, &id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&cpu_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_slice_table_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Return the number of connected Panther boards in the domain.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_panther_boards(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int b_idx;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmachid_t b_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_t *bp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int npanther = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = drmach_array_first(drmach_boards, &b_idx, &b_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (rv == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(DRMACH_IS_BOARD_ID(b_id));
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp = b_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IS_PANTHER(bp->cpu_impl))
03831d35f7499c87d51205817c93e9a8d42c4baestevel npanther++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = drmach_array_next(drmach_boards, &b_idx, &b_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (npanther);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_board_disconnect(drmachid_t id, drmach_opts_t *opts)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_t *bp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dr_mbox_msg_t *obufp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel sc_gptwocfg_cookie_t scc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_BOARD_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Build the casm info portion of the UNCLAIM message.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This must be done prior to calling for saf configurator
03831d35f7499c87d51205817c93e9a8d42c4baestevel * deprobe, to ensure that the associated axq instance
03831d35f7499c87d51205817c93e9a8d42c4baestevel * is not detached.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel obufp = kmem_zalloc(sizeof (dr_mbox_msg_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_slice_table_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_msg_memslice_init(obufp->msgdata.dm_ur.mem_slice);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If disconnecting slot 0 board, update the casm slice table
03831d35f7499c87d51205817c93e9a8d42c4baestevel * info now, for use by drmach_slot1_lpa_set()
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (DRMACH_BNUM2SLOT(bp->bnum) == 0)
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni drmach_slice_table_update(bp, 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_msg_memregs_init(obufp->msgdata.dm_ur.mem_regs);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_slice_table_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Update LPA information for slot1 board
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_slot1_lpa_set(bp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* disable and flush CDC */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (axq_cdc_disable_flush_all() != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel axq_cdc_enable_all(); /* paranoia */
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = DRMACH_INTERNAL_ERROR();
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * call saf configurator for deprobe
03831d35f7499c87d51205817c93e9a8d42c4baestevel * It's done now before sending an UNCLAIM message because
03831d35f7499c87d51205817c93e9a8d42c4baestevel * IKP will probe boards it doesn't know about <present at boot>
03831d35f7499c87d51205817c93e9a8d42c4baestevel * prior to unprobing them. If this happens after sending the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * UNCLAIM, it will cause a dstop for domain transgression error.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!err) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scc = sc_unprobe_board(bp->bnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel axq_cdc_enable_all();
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scc != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drerr_new(0, ESTC_DEPROBE, bp->cm.name);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If disconnecting a board from a Panther domain, wait a fixed-
03831d35f7499c87d51205817c93e9a8d42c4baestevel * time delay for pending Safari transactions to complete on the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * disconnecting board's processors. The bus sync list read used
03831d35f7499c87d51205817c93e9a8d42c4baestevel * in drmach_shutdown_asm to synchronize with outstanding Safari
03831d35f7499c87d51205817c93e9a8d42c4baestevel * transactions assumes no read-bypass-write mode for all memory
03831d35f7499c87d51205817c93e9a8d42c4baestevel * controllers. Since Panther supports read-bypass-write, a
03831d35f7499c87d51205817c93e9a8d42c4baestevel * delay is used that is slightly larger than the maximum Safari
03831d35f7499c87d51205817c93e9a8d42c4baestevel * timeout value in the Safari/Fireplane Config Reg.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_panther_boards() > 0 || drmach_unclaim_delay_all) {
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni clock_t stime = ddi_get_lbolt();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel delay(drv_usectohz(drmach_unclaim_usec_delay));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni stime = ddi_get_lbolt() - stime;
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("delayed %ld ticks (%ld secs) before disconnecting "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "board %s from domain\n", stime, stime / hz, bp->cm.name);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!err) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel obufp->msgdata.dm_ur.mem_clear = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_mbox_trans(DRMSG_UNCLAIM, bp->bnum, (caddr_t)obufp,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni sizeof (dr_mbox_msg_t), (caddr_t)NULL, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if mailbox timeout or unrecoverable error from SC,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * board cannot be touched. Mark the status as
03831d35f7499c87d51205817c93e9a8d42c4baestevel * unusable.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((err->e_code == ESTC_SMS_ERR_UNRECOVERABLE) ||
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (err->e_code == ESTC_MBXRPLY))
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni bp->cond = SBD_COND_UNUSABLE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("UNCLAIM failed for bnum=%d\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni bp->bnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("calling sc_probe_board: bnum=%d\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni bp->bnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scc = sc_probe_board(bp->bnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scc == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "sc_probe_board failed for bnum=%d",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni bp->bnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (DRMACH_BNUM2SLOT(bp->bnum) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(
03831d35f7499c87d51205817c93e9a8d42c4baestevel &drmach_slice_table_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_slice_table_update(bp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(
03831d35f7499c87d51205817c93e9a8d42c4baestevel &drmach_slice_table_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_slot1_lpa_set(bp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->connected = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Now that the board has been successfully detached,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * discard platform-specific DIMM serial id information
03831d35f7499c87d51205817c93e9a8d42c4baestevel * for the board.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((DRMACH_BNUM2SLOT(bp->bnum) == 0) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel plat_ecc_capability_sc_get(
03831d35f7499c87d51205817c93e9a8d42c4baestevel PLAT_ECC_DIMM_SID_MESSAGE)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) plat_discard_mem_sids(
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_BNUM2EXP(bp->bnum));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(obufp, sizeof (dr_mbox_msg_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_get_portid(drmach_node_t *np)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_node_t pp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int portid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char type[OBP_MAXPROPNAME];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (np->n_getprop(np, "portid", &portid, sizeof (portid)) == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (portid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Get the device_type property to see if we should
03831d35f7499c87d51205817c93e9a8d42c4baestevel * continue processing this node.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (np->n_getprop(np, "device_type", &type, sizeof (type)) != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the device is a CPU without a 'portid' property,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * it is a CMP core. For such cases, the parent node
03831d35f7499c87d51205817c93e9a8d42c4baestevel * has the portid.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (strcmp(type, DRMACH_CPU_NAMEPROP) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (np->get_parent(np, &pp) != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (pp.n_getprop(&pp, "portid", &portid, sizeof (portid)) == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (portid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This is a helper function to determine if a given
03831d35f7499c87d51205817c93e9a8d42c4baestevel * node should be considered for a dr operation according
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to predefined dr type nodes and the node's name.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Formal Parameter : The name of a device node.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Return Value: -1, name does not map to a valid dr type.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * A value greater or equal to 0, name is a valid dr type.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_name2type_idx(char *name)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int index, ntypes;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (name == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Determine how many possible types are currently supported
03831d35f7499c87d51205817c93e9a8d42c4baestevel * for dr.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ntypes = sizeof (drmach_name2type) / sizeof (drmach_name2type[0]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Determine if the node's name correspond to a predefined type. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (index = 0; index < ntypes; index++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (strcmp(drmach_name2type[index].name, name) == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* The node is an allowed type for dr. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (index);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the name of the node does not map to any of the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * types in the array drmach_name2type then the node is not of
03831d35f7499c87d51205817c93e9a8d42c4baestevel * interest to dr.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_board_find_devices_cb(drmach_node_walk_args_t *args)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_node_t *node = args->node;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_cb_data_t *data = args->data;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_t *obj = data->obj;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv, portid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmachid_t id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_device_t *device;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char name[OBP_MAXDRVNAME];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel portid = drmach_get_portid(node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (portid == -1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if the node does not have a portid property, then
03831d35f7499c87d51205817c93e9a8d42c4baestevel * by that information alone it is known that drmach
03831d35f7499c87d51205817c93e9a8d42c4baestevel * is not interested in it.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = node->n_getprop(node, "name", name, OBP_MAXDRVNAME);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* The node must have a name */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Ignore devices whose portid do not map to this board,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * or that their name property is not mapped to a valid
03831d35f7499c87d51205817c93e9a8d42c4baestevel * dr device name.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((drmach_portid2bnum(portid) != obj->bnum) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel (drmach_name2type_idx(name) < 0))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Create a device data structure from this node data.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The call may yield nothing if the node is not of interest
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to drmach.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel data->err = drmach_device_new(node, obj, portid, &id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (data->err)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else if (!id) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * drmach_device_new examined the node we passed in
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and determined that it was either one not of
03831d35f7499c87d51205817c93e9a8d42c4baestevel * interest to drmach or the PIM dr layer.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * So, it is skipped.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = drmach_array_set(obj->devices, data->ndevs++, id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel data->err = DRMACH_INTERNAL_ERROR();
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel device = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("%d %s %d %p\n", portid, device->type, device->unum, id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (DRMACH_IS_IO_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("ndevs = %d dip/node = %p", data->ndevs, node->here);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel data->err = (*data->found)(data->a, device->type, device->unum, id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (data->err == NULL ? 0 : -1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_board_find_devices(drmachid_t id, void *a,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *(*found)(void *a, const char *, int, drmachid_t))
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_t *bp = (drmach_board_t *)id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int max_devices;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_cb_data_t data;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_BOARD_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel max_devices = plat_max_cpu_units_per_board();
03831d35f7499c87d51205817c93e9a8d42c4baestevel max_devices += plat_max_mem_units_per_board();
03831d35f7499c87d51205817c93e9a8d42c4baestevel max_devices += plat_max_io_units_per_board();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->devices = drmach_array_new(0, max_devices);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (bp->tree == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->tree = drmach_node_new();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel data.obj = bp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel data.ndevs = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel data.found = found;
03831d35f7499c87d51205817c93e9a8d42c4baestevel data.a = a;
03831d35f7499c87d51205817c93e9a8d42c4baestevel data.err = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_slice_table_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_bus_sync_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = drmach_node_walk(bp->tree, &data, drmach_board_find_devices_cb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_slice_table_update(bp, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_bus_sync_list_update();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_bus_sync_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_slice_table_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_slot1_lpa_set(bp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_array_dispose(bp->devices, drmach_device_dispose);
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->devices = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (data.err)
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = data.err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = DRMACH_INTERNAL_ERROR();
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_board_lookup(int bnum, drmachid_t *id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!drmach_initialized && drmach_init() == -1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *id = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_enter(&drmach_boards_rwlock, RW_WRITER);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_array_get(drmach_boards, bnum, id)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *id = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel caddr_t obufp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dr_showboard_t shb;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_t *bp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp = *id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (bp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_downgrade(&drmach_boards_rwlock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel obufp = kmem_zalloc(sizeof (dr_proto_hdr_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_mbox_trans(DRMSG_SHOWBOARD, bnum, obufp,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni sizeof (dr_proto_hdr_t), (caddr_t)&shb,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni sizeof (dr_showboard_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(obufp, sizeof (dr_proto_hdr_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err->e_code == ESTC_UNAVAILABLE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *id = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_err_clear(&err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!bp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp = *id = (drmachid_t)drmach_board_new(bnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->connected = (shb.bd_assigned && shb.bd_active);
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->empty = shb.slot_empty;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (shb.test_status) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DR_TEST_STATUS_UNKNOWN:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DR_TEST_STATUS_IPOST:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DR_TEST_STATUS_ABORTED:
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->cond = SBD_COND_UNKNOWN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DR_TEST_STATUS_PASSED:
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->cond = SBD_COND_OK;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DR_TEST_STATUS_FAILED:
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->cond = SBD_COND_FAILED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->cond = SBD_COND_UNKNOWN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("Unknown test status=0x%x from SC\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni shb.test_status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) strncpy(bp->type, shb.board_type,
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki sizeof (bp->type));
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->assigned = shb.bd_assigned;
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->powered = shb.power_on;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_exit(&drmach_boards_rwlock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (rv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_board_name(int bnum, char *buf, int buflen)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) snprintf(buf, buflen, "%s%d", DRMACH_BNUM2SLOT(bnum) ?
03831d35f7499c87d51205817c93e9a8d42c4baestevel "IO" : "SB", DRMACH_BNUM2EXP(bnum));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_board_poweroff(drmachid_t id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_t *bp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_status_t stat;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_BOARD_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_board_status(id, &stat);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!err) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (stat.configured || stat.busy)
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drerr_new(0, ESTC_CONFIGBUSY, bp->cm.name);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel caddr_t obufp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel obufp = kmem_zalloc(sizeof (dr_proto_hdr_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_mbox_trans(DRMSG_POWEROFF, bp->bnum, obufp,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni sizeof (dr_proto_hdr_t), (caddr_t)NULL, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(obufp, sizeof (dr_proto_hdr_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!err)
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->powered = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_board_poweron(drmachid_t id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_t *bp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel caddr_t obufp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_BOARD_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel obufp = kmem_zalloc(sizeof (dr_proto_hdr_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_mbox_trans(DRMSG_POWERON, bp->bnum, obufp,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni sizeof (dr_proto_hdr_t), (caddr_t)NULL, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!err)
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->powered = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(obufp, sizeof (dr_proto_hdr_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_board_release(drmachid_t id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_BOARD_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_board_test(drmachid_t id, drmach_opts_t *opts, int force)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_t *bp;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl drmach_device_t *dp[MAX_CORES_PER_CMP];
03831d35f7499c87d51205817c93e9a8d42c4baestevel dr_mbox_msg_t *obufp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dr_testboard_reply_t tbr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int cpylen;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *copts;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int is_io;
25cf1a301a396c38e8adf52c15f537b80d2483f7jl cpu_flag_t oflags[MAX_CORES_PER_CMP];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_BOARD_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the board is an I/O or MAXCAT board, setup I/O cage for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * testing. Slot 1 indicates I/O or MAXCAT board.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel is_io = DRMACH_BNUM2SLOT(bp->bnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel obufp = kmem_zalloc(sizeof (dr_mbox_msg_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (force)
03831d35f7499c87d51205817c93e9a8d42c4baestevel obufp->msgdata.dm_tb.force = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel obufp->msgdata.dm_tb.immediate = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((opts->size > 0) && ((copts = opts->copts) != NULL)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpylen = (opts->size > DR_HPOPTLEN ? DR_HPOPTLEN : opts->size);
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy(copts, obufp->msgdata.dm_tb.hpost_opts, cpylen);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (is_io) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_iocage_setup(&obufp->msgdata.dm_tb, dp, oflags);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(obufp, sizeof (dr_mbox_msg_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_mbox_trans(DRMSG_TESTBOARD, bp->bnum, (caddr_t)obufp,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni sizeof (dr_mbox_msg_t), (caddr_t)&tbr, sizeof (tbr));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!err)
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->cond = SBD_COND_OK;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->cond = SBD_COND_UNKNOWN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((!err) && (tbr.test_status != DR_TEST_STATUS_PASSED)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* examine test status */
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (tbr.test_status) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DR_TEST_STATUS_IPOST:
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->cond = SBD_COND_UNKNOWN;
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni err = drerr_new(0, ESTC_TEST_IN_PROGRESS, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DR_TEST_STATUS_UNKNOWN:
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->cond = SBD_COND_UNKNOWN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drerr_new(1,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni ESTC_TEST_STATUS_UNKNOWN, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DR_TEST_STATUS_FAILED:
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->cond = SBD_COND_FAILED;
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni err = drerr_new(1, ESTC_TEST_FAILED, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DR_TEST_STATUS_ABORTED:
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->cond = SBD_COND_UNKNOWN;
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni err = drerr_new(1, ESTC_TEST_ABORTED, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->cond = SBD_COND_UNKNOWN;
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni err = drerr_new(1, ESTC_TEST_RESULT_UNKNOWN,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If I/O cage test was performed, check for availability of the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cpu used. If cpu has been returned, it's OK to proceed with
03831d35f7499c87d51205817c93e9a8d42c4baestevel * reconfiguring it for use.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (is_io) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("drmach_board_test: tbr.cpu_recovered: %d",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni tbr.cpu_recovered);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("drmach_board_test: port id: %d",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni tbr.cpu_portid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check the cpu_recovered flag in the testboard reply, or
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if the testboard request message was not sent to SMS due
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to an mboxsc_putmsg() failure, it's OK to recover the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cpu since hpost hasn't touched it.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((tbr.cpu_recovered && tbr.cpu_portid ==
03831d35f7499c87d51205817c93e9a8d42c4baestevel obufp->msgdata.dm_tb.cpu_portid) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((err) && (err->e_code == ESTC_MBXRQST))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&cpu_lock);
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (i = 0; i < MAX_CORES_PER_CMP; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dp[i] != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) drmach_iocage_cpu_return(dp[i],
03831d35f7499c87d51205817c93e9a8d42c4baestevel oflags[i]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&cpu_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "Unable to recover port id %d "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "after I/O cage test: cpu_recovered=%d, "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "returned portid=%d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel obufp->msgdata.dm_tb.cpu_portid,
03831d35f7499c87d51205817c93e9a8d42c4baestevel tbr.cpu_recovered, tbr.cpu_portid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) drmach_iocage_mem_return(&tbr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(obufp, sizeof (dr_mbox_msg_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_board_unassign(drmachid_t id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_t *bp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_status_t stat;
03831d35f7499c87d51205817c93e9a8d42c4baestevel caddr_t obufp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_enter(&drmach_boards_rwlock, RW_WRITER);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_BOARD_ID(id)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_exit(&drmach_boards_rwlock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_board_status(id, &stat);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_exit(&drmach_boards_rwlock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (stat.configured || stat.busy) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drerr_new(0, ESTC_CONFIGBUSY, bp->cm.name);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel obufp = kmem_zalloc(sizeof (dr_proto_hdr_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_mbox_trans(DRMSG_UNASSIGN, bp->bnum, obufp,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni sizeof (dr_proto_hdr_t), (caddr_t)NULL, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(obufp, sizeof (dr_proto_hdr_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!err) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_array_set(drmach_boards, bp->bnum, 0) != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = DRMACH_INTERNAL_ERROR();
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_dispose(bp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_exit(&drmach_boards_rwlock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_read_reg_addr(drmach_device_t *dp, uint64_t *p)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_reg_t reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_node_t pp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_node_t *np = dp->node;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the node does not have a portid property,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * it represents a CMP device. For a CMP, the reg
03831d35f7499c87d51205817c93e9a8d42c4baestevel * property of the parent holds the information of
03831d35f7499c87d51205817c93e9a8d42c4baestevel * interest.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dp->node->n_getproplen(dp->node, "portid", &len) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dp->node->get_parent(dp->node, &pp) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DRMACH_INTERNAL_ERROR());
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel np = &pp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (np->n_getproplen(np, "reg", &len) != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DRMACH_INTERNAL_ERROR());
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (len != sizeof (reg))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DRMACH_INTERNAL_ERROR());
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (np->n_getprop(np, "reg", &reg, sizeof (reg)) != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DRMACH_INTERNAL_ERROR());
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* reassemble 64-bit base address */
03831d35f7499c87d51205817c93e9a8d42c4baestevel *p = ((uint64_t)reg.reg_addr_hi << 32) | reg.reg_addr_lo;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_cpu_read(uint64_t arg1, uint64_t arg2)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t *saf_config_reg = (uint64_t *)arg1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint_t *reg_read = (uint_t *)arg2;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *saf_config_reg = lddsafconfig();
03831d35f7499c87d51205817c93e9a8d42c4baestevel *reg_read = 0x1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * A return value of 1 indicates success and 0 indicates a failure
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_cpu_read_scr(drmach_cpu_t *cp, uint64_t *scr)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv = 0x0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *scr = 0x0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Confirm cpu was in ready set when xc was issued.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This is done by verifying rv which is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * set to 0x1 when xc_one is successful.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel xc_one(cp->dev.portid, (xcfunc_t *)drmach_cpu_read,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (uint64_t)scr, (uint64_t)&rv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (rv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_cpu_read_cpuid(drmach_cpu_t *cp, processorid_t *cpuid)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_node_t *np;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel np = cp->dev.node;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If a CPU does not have a portid property, it must
03831d35f7499c87d51205817c93e9a8d42c4baestevel * be a CMP device with a cpuid property.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (np->n_getprop(np, "portid", cpuid, sizeof (*cpuid)) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (np->n_getprop(np, "cpuid", cpuid, sizeof (*cpuid)) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DRMACH_INTERNAL_ERROR());
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* Starcat CMP core id is bit 2 of the cpuid */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_COREID_MASK (1u << 2)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_CPUID2SRAM_IDX(id) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((id & DRMACH_COREID_MASK) >> 1 | (id & 0x1))
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_cpu_new(drmach_device_t *proto, drmachid_t *idp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t scr_pa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_cpu_t *cp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pfn_t pfn;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t cpu_stardrb_offset, cpu_sram_pa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int idx;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int impl;
03831d35f7499c87d51205817c93e9a8d42c4baestevel processorid_t cpuid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_read_reg_addr(proto, &scr_pa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto fail;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cp = kmem_zalloc(sizeof (drmach_cpu_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy(proto, &cp->dev, sizeof (cp->dev));
03831d35f7499c87d51205817c93e9a8d42c4baestevel cp->dev.node = drmach_node_dup(proto->node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cp->dev.cm.isa = (void *)drmach_cpu_new;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cp->dev.cm.dispose = drmach_cpu_dispose;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cp->dev.cm.release = drmach_cpu_release;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cp->dev.cm.status = drmach_cpu_status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cp->scr_pa = scr_pa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_cpu_read_cpuid(cp, &cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto fail;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_cpu_get_impl(cp, &impl);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto fail;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cp->cpuid = cpuid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cp->coreid = STARCAT_CPUID_TO_COREID(cp->cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cp->dev.unum = STARCAT_CPUID_TO_AGENT(cp->cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Init the board cpu type. Assumes all board cpus are the same type.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cp->dev.bp->cpu_impl == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cp->dev.bp->cpu_impl = impl;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(cp->dev.bp->cpu_impl == impl);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XXX CHEETAH SUPPORT
03831d35f7499c87d51205817c93e9a8d42c4baestevel * determine if the domain uses Cheetah procs
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_is_cheetah < 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_is_cheetah = IS_CHEETAH(impl);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Initialize TTE for mapping CPU SRAM STARDRB buffer.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The STARDRB buffer (16KB on Cheetah+ boards, 32KB on
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Jaguar/Panther boards) is shared by all cpus in a Safari port
03831d35f7499c87d51205817c93e9a8d42c4baestevel * pair. Each cpu uses 8KB according to the following layout:
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Page 0: even numbered Cheetah+'s and Panther/Jaguar core 0's
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Page 1: odd numbered Cheetah+'s and Panther/Jaguar core 0's
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Page 2: even numbered Panther/Jaguar core 1's
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Page 3: odd numbered Panther/Jaguar core 1's
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel idx = DRMACH_CPUID2SRAM_IDX(cp->cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpu_stardrb_offset = cp->dev.bp->stardrb_offset + (PAGESIZE * idx);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpu_sram_pa = DRMACH_CPU_SRAM_ADDR + cpu_stardrb_offset;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pfn = cpu_sram_pa >> PAGESHIFT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(drmach_cpu_sram_tte[cp->cpuid].tte_inthi == 0 &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_cpu_sram_tte[cp->cpuid].tte_intlo == 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_cpu_sram_tte[cp->cpuid].tte_inthi = TTE_PFN_INTHI(pfn) |
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni TTE_VALID_INT | TTE_SZ_INT(TTE8K);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_cpu_sram_tte[cp->cpuid].tte_intlo = TTE_PFN_INTLO(pfn) |
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni TTE_HWWR_INT | TTE_PRIV_INT | TTE_LCK_INT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("drmach_cpu_new: cpuid=%d, coreid=%d, stardrb_offset=0x%lx, "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "cpu_sram_offset=0x%lx, idx=%d\n", cp->cpuid, cp->coreid,
03831d35f7499c87d51205817c93e9a8d42c4baestevel cp->dev.bp->stardrb_offset, cpu_stardrb_offset, idx);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) snprintf(cp->dev.cm.name, sizeof (cp->dev.cm.name), "%s%d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel cp->dev.type, cp->dev.unum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *idp = (drmachid_t)cp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelfail:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cp) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_node_dispose(cp->dev.node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(cp, sizeof (*cp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *idp = (drmachid_t)0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_cpu_dispose(drmachid_t id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_cpu_t *self;
03831d35f7499c87d51205817c93e9a8d42c4baestevel processorid_t cpuid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(DRMACH_IS_CPU_ID(id));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel self = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (self->dev.node)
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_node_dispose(self->dev.node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpuid = self->cpuid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(TTE_IS_VALID(&drmach_cpu_sram_tte[cpuid]) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel TTE_IS_8K(&drmach_cpu_sram_tte[cpuid]) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel TTE_IS_PRIVILEGED(&drmach_cpu_sram_tte[cpuid]) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel TTE_IS_LOCKED(&drmach_cpu_sram_tte[cpuid]));
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_cpu_sram_tte[cpuid].tte_inthi = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_cpu_sram_tte[cpuid].tte_intlo = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(self, sizeof (*self));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_cpu_start(struct cpu *cp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel extern xcfunc_t drmach_set_lpa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel extern void restart_other_cpu(int);
03831d35f7499c87d51205817c93e9a8d42c4baestevel int cpuid = cp->cpu_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv, bnum;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_t *bp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(MUTEX_HELD(&cpu_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(cpunodes[cpuid].nodeid != (pnode_t)0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cp->cpu_flags &= ~CPU_POWEROFF;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * NOTE: restart_other_cpu pauses cpus during the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * slave cpu start. This helps to quiesce the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * bus traffic a bit which makes the tick sync
03831d35f7499c87d51205817c93e9a8d42c4baestevel * routine in the prom more robust.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("COLD START for cpu (%d)\n", cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (prom_hotaddcpu(cpuid) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_PANIC, "prom_hotaddcpu() for cpuid=%d failed.",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel restart_other_cpu(cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel bnum = drmach_portid2bnum(cpunodes[cpuid].portid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = drmach_array_get(drmach_boards, bnum, (drmachid_t)&bp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv == -1 || bp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("drmach_cpu_start: cannot read board info for "
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki "cpuid=%d: rv=%d, bp=%p\n", cpuid, rv, (void *)bp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (DRMACH_L1_SET_LPA(bp) && drmach_reprogram_lpa) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int exp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int ntries;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_xt_mb_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_slice_table_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel bzero((void *)drmach_xt_mb, drmach_xt_mb_size);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * drmach_slice_table[*]
03831d35f7499c87d51205817c93e9a8d42c4baestevel * bit 5 valid
03831d35f7499c87d51205817c93e9a8d42c4baestevel * bit 0:4 slice number
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * drmach_xt_mb[*] format for drmach_set_lpa
03831d35f7499c87d51205817c93e9a8d42c4baestevel * bit 7 valid
03831d35f7499c87d51205817c93e9a8d42c4baestevel * bit 6 set null LPA (overrides bits 0:4)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * bit 0:4 slice number
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * drmach_set_lpa derives processor CBASE and CBND
03831d35f7499c87d51205817c93e9a8d42c4baestevel * from bits 6 and 0:4 of drmach_xt_mb. If bit 6 is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * set, then CBASE = CBND = 0. Otherwise, CBASE = slice
03831d35f7499c87d51205817c93e9a8d42c4baestevel * number; CBND = slice number + 1.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * No action is taken if bit 7 is zero.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel exp = (cpuid >> 5) & 0x1f;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_slice_table[exp] & 0x20) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_xt_mb[cpuid] = 0x80 |
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (drmach_slice_table[exp] & 0x1f);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_xt_mb[cpuid] = 0x80 | 0x40;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_xt_ready = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel xt_one(cpuid, drmach_set_lpa, NULL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ntries = drmach_cpu_ntries;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (!drmach_xt_ready && ntries) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DELAY(drmach_cpu_delay);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ntries--;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_slice_table_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_xt_mb_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR(
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "waited %d out of %d tries for drmach_set_lpa on cpu%d",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni drmach_cpu_ntries - ntries, drmach_cpu_ntries,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni cp->cpu_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni xt_one(cpuid, vtag_flushpage_tl1, (uint64_t)drmach_cpu_sram_va,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (uint64_t)ksfmmup);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * A detaching CPU is xcalled with an xtrap to drmach_cpu_stop_self() after
03831d35f7499c87d51205817c93e9a8d42c4baestevel * it has been offlined. The function of this routine is to get the cpu
03831d35f7499c87d51205817c93e9a8d42c4baestevel * spinning in a safe place. The requirement is that the system will not
03831d35f7499c87d51205817c93e9a8d42c4baestevel * reference anything on the detaching board (memory and i/o is detached
03831d35f7499c87d51205817c93e9a8d42c4baestevel * elsewhere) and that the CPU not reference anything on any other board
03831d35f7499c87d51205817c93e9a8d42c4baestevel * in the system. This isolation is required during and after the writes
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to the domain masks to remove the board from the domain.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * To accomplish this isolation the following is done:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 1) Create a locked mapping to the STARDRB data buffer located
03831d35f7499c87d51205817c93e9a8d42c4baestevel * in this cpu's sram. There is one TTE per cpu, initialized in
03831d35f7499c87d51205817c93e9a8d42c4baestevel * drmach_cpu_new(). The cpuid is used to select which TTE to use.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Each Safari port pair shares the CPU SRAM on a Serengeti CPU/MEM
03831d35f7499c87d51205817c93e9a8d42c4baestevel * board. The STARDRB buffer is 16KB on Cheetah+ boards, 32KB on Jaguar
03831d35f7499c87d51205817c93e9a8d42c4baestevel * boards. Each STARDRB buffer is logically divided by DR into one
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 8KB page per cpu (or Jaguar core).
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 2) Copy the target function (drmach_shutdown_asm) into buffer.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 3) Jump to function now in the cpu sram.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Function will:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 3.1) Flush its Ecache (displacement).
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 3.2) Flush its Dcache with HW mechanism.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 3.3) Flush its Icache with HW mechanism.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 3.4) Flush all valid and _unlocked_ D-TLB and I-TLB entries.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 3.5) Set LPA to NULL
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 3.6) Clear xt_mb to signal completion. Note: cache line is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * recovered by drmach_cpu_poweroff().
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 4) Jump into an infinite loop.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_cpu_stop_self(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni extern void drmach_shutdown_asm(uint64_t, uint64_t, int, int, uint64_t);
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni extern void drmach_shutdown_asm_end(void);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel tte_t *tte;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint_t *p, *q;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t stack_pointer;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(((ptrdiff_t)drmach_shutdown_asm_end -
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (ptrdiff_t)drmach_shutdown_asm) < PAGESIZE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel tte = &drmach_cpu_sram_tte[CPU->cpu_id];
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni ASSERT(TTE_IS_VALID(tte) && TTE_IS_8K(tte) && TTE_IS_PRIVILEGED(tte) &&
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni TTE_IS_LOCKED(tte));
1e2e7a75ddb1eedcefa449ce98fd5862749b72eehuah sfmmu_dtlb_ld_kva(drmach_cpu_sram_va, tte);
1e2e7a75ddb1eedcefa449ce98fd5862749b72eehuah sfmmu_itlb_ld_kva(drmach_cpu_sram_va, tte);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* copy text. standard bcopy not designed to work in nc space */
03831d35f7499c87d51205817c93e9a8d42c4baestevel p = (uint_t *)drmach_cpu_sram_va;
03831d35f7499c87d51205817c93e9a8d42c4baestevel q = (uint_t *)drmach_shutdown_asm;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (q < (uint_t *)drmach_shutdown_asm_end)
03831d35f7499c87d51205817c93e9a8d42c4baestevel *p++ = *q++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* zero to assist debug */
03831d35f7499c87d51205817c93e9a8d42c4baestevel q = (uint_t *)(drmach_cpu_sram_va + PAGESIZE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (p < q)
03831d35f7499c87d51205817c93e9a8d42c4baestevel *p++ = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* a parking spot for the stack pointer */
03831d35f7499c87d51205817c93e9a8d42c4baestevel stack_pointer = (uint64_t)q;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* call copy of drmach_shutdown_asm */
03831d35f7499c87d51205817c93e9a8d42c4baestevel (*(void (*)())drmach_cpu_sram_va)(
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni stack_pointer,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni drmach_iocage_paddr,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni cpunodes[CPU->cpu_id].ecache_size,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni cpunodes[CPU->cpu_id].ecache_linesize,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni va_to_pa((void *)&drmach_xt_mb[CPU->cpu_id]));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_cpu_shutdown_self(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpu_t *cp = CPU;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int cpuid = cp->cpu_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel extern void flush_windows(void);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel flush_windows();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) spl8();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(cp->cpu_intr_actv == 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(cp->cpu_thread == cp->cpu_idle_thread ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel cp->cpu_thread == cp->cpu_startup_thread);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cp->cpu_flags = CPU_OFFLINE | CPU_QUIESCED | CPU_POWEROFF;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_cpu_stop_self();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_PANIC, "CPU %d FAILED TO SHUTDOWN", cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_cpu_release(drmachid_t id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_cpu_t *cp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct cpu *cpu;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_CPU_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel cp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(MUTEX_HELD(&cpu_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpu = cpu_get(cp->cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cpu == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = DRMACH_INTERNAL_ERROR();
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_cpu_status(drmachid_t id, drmach_status_t *stat)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_cpu_t *cp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_device_t *dp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(DRMACH_IS_CPU_ID(id));
03831d35f7499c87d51205817c93e9a8d42c4baestevel cp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dp = &cp->dev;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel stat->assigned = dp->bp->assigned;
03831d35f7499c87d51205817c93e9a8d42c4baestevel stat->powered = dp->bp->powered;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&cpu_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel stat->configured = (cpu_get(cp->cpuid) != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&cpu_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel stat->busy = dp->busy;
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) strncpy(stat->type, dp->type, sizeof (stat->type));
03831d35f7499c87d51205817c93e9a8d42c4baestevel stat->info[0] = '\0';
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_cpu_disconnect(drmachid_t id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_CPU_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_cpu_get_id(drmachid_t id, processorid_t *cpuid)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_cpu_t *cpu;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_CPU_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpu = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *cpuid = cpu->cpuid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_cpu_get_impl(drmachid_t id, int *ip)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_node_t *np;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int impl;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_CPU_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel np = ((drmach_device_t *)id)->node;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (np->n_getprop(np, "implementation#", &impl, sizeof (impl)) == -1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DRMACH_INTERNAL_ERROR());
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *ip = impl;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Flush this cpu's ecache, then ensure all outstanding safari
03831d35f7499c87d51205817c93e9a8d42c4baestevel * transactions have retired.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_cpu_flush_ecache_sync(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t *p;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(curthread->t_bound_cpu == CPU);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpu_flush_ecache();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_bus_sync_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (p = drmach_bus_sync_list; *p; p++)
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) ldphys(*p);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_bus_sync_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpu_flush_ecache();
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_get_dip(drmachid_t id, dev_info_t **dip)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_device_t *dp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_DEVICE_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel dp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *dip = dp->node->n_getdip(dp->node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_io_is_attached(drmachid_t id, int *yes)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_device_t *dp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *dip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int state;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_IO_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel dp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dip = dp->node->n_getdip(dp->node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dip == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *yes = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel state = ddi_get_devstate(dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel *yes = i_ddi_devi_attached(dip) || (state == DDI_DEVSTATE_UP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_dip_is_schizo_xmits_0_pci_b(dev_info_t *dip)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel char dtype[OBP_MAXPROPNAME];
03831d35f7499c87d51205817c93e9a8d42c4baestevel int portid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint_t pci_csr_base;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct pci_phys_spec *regbuf = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv, len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(dip != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = ddi_getproplen(DDI_DEV_T_ANY, dip, 0, "device_type", &len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((rv != DDI_PROP_SUCCESS) || (len > sizeof (dtype)))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 0, "device_type",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (caddr_t)dtype, &len) == DDI_PROP_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (strncmp(dtype, "pci", 3) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Get safari portid. All schizo/xmits 0
03831d35f7499c87d51205817c93e9a8d42c4baestevel * safari IDs end in 0x1C.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni rv = ddi_getproplen(DDI_DEV_T_ANY, dip, 0, "portid",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni &len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((rv != DDI_PROP_SUCCESS) ||
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (len > sizeof (portid)))
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 0,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "portid", (caddr_t)&portid, &len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv != DDI_PROP_SUCCESS)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((portid & 0x1F) != 0x1C)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni DDI_PROP_DONTPASS, "reg", (caddr_t)&regbuf,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni &len) == DDI_PROP_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel pci_csr_base = regbuf[0].pci_phys_mid &
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni PCI_CONF_ADDR_MASK;
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(regbuf, len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * All PCI B-Leafs are at configspace 0x70.0000.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (pci_csr_base == 0x700000)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCHIZO_BINDING_NAME "pci108e,8001"
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define XMITS_BINDING_NAME "pci108e,8002"
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Verify if the dip is an instance of MAN 'eri'.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_dip_is_man_eri(dev_info_t *dip)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct pci_phys_spec *regbuf = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *parent_dip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *name;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint_t pci_device;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint_t pci_function;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dip == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Verify if the parent is schizo(xmits)0 and pci B leaf.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (((parent_dip = ddi_get_parent(dip)) == NULL) ||
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni ((name = ddi_binding_name(parent_dip)) == NULL))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (strcmp(name, SCHIZO_BINDING_NAME) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This RIO could be on XMITS, so get the dip to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XMITS PCI Leaf.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((parent_dip = ddi_get_parent(parent_dip)) == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (((name = ddi_binding_name(parent_dip)) == NULL) ||
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (strcmp(name, XMITS_BINDING_NAME) != 0)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!drmach_dip_is_schizo_xmits_0_pci_b(parent_dip))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Finally make sure it is the MAN eri.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "reg", (caddr_t)&regbuf, &len) == DDI_PROP_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel pci_device = PCI_REG_DEV_G(regbuf->pci_phys_hi);
03831d35f7499c87d51205817c93e9a8d42c4baestevel pci_function = PCI_REG_FUNC_G(regbuf->pci_phys_hi);
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(regbuf, len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The network function of the RIO ASIC will always be
03831d35f7499c87d51205817c93e9a8d42c4baestevel * device 3 and function 1 ("network@3,1").
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((pci_device == 3) && (pci_function == 1))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveltypedef struct {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int iosram_inst;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *eri_dip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int bnum;
03831d35f7499c87d51205817c93e9a8d42c4baestevel} drmach_io_inst_t;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_board_find_io_insts(dev_info_t *dip, void *args)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_io_inst_t *ios = (drmach_io_inst_t *)args;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int portid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char name[OBP_MAXDRVNAME];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = ddi_getproplen(DDI_DEV_T_ANY, dip, 0, "portid", &len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((rv != DDI_PROP_SUCCESS) || (len > sizeof (portid))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_WALK_CONTINUE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 0,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "portid", (caddr_t)&portid, &len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv != DDI_PROP_SUCCESS)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_WALK_CONTINUE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* ignore devices that are not on this board */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_portid2bnum(portid) != ios->bnum)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_WALK_CONTINUE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((ios->iosram_inst < 0) || (ios->eri_dip == NULL)) {
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni rv = ddi_getproplen(DDI_DEV_T_ANY, dip, 0, "name", &len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv == DDI_PROP_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = ddi_getlongprop_buf(DDI_DEV_T_ANY, dip,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni 0, "name",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (caddr_t)name, &len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv != DDI_PROP_SUCCESS)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_WALK_CONTINUE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (strncmp("iosram", name, 6) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ios->iosram_inst = ddi_get_instance(dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ios->eri_dip == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_WALK_CONTINUE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_WALK_TERMINATE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_dip_is_man_eri(dip)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(ios->eri_dip == NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_hold_devi(dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ios->eri_dip = dip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ios->iosram_inst < 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_WALK_CONTINUE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_WALK_TERMINATE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_WALK_CONTINUE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_io_pre_release(drmachid_t id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_io_inst_t ios;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_t *bp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_device_t *dp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *rdip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int circ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_IO_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel dp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp = dp->bp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rdip = dp->node->n_getdip(dp->node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* walk device tree to find iosram instance for the board */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ios.iosram_inst = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ios.eri_dip = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ios.bnum = bp->bnum;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_devi_enter(rdip, &circ);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_walk_devs(ddi_get_child(rdip), drmach_board_find_io_insts,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (void *)&ios);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("drmach_io_pre_release: bnum=%d iosram=%d eri=0x%p\n",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki ios.bnum, ios.iosram_inst, (void *)ios.eri_dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_devi_exit(rdip, circ);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ios.eri_dip) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Release hold acquired in drmach_board_find_io_insts()
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_rele_devi(ios.eri_dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ios.iosram_inst >= 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* call for tunnel switch */
03831d35f7499c87d51205817c93e9a8d42c4baestevel do {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("calling iosram_switchfrom(%d)\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni ios.iosram_inst);
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = iosram_switchfrom(ios.iosram_inst);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv)
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("iosram_switchfrom returned %d\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni rv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } while (rv == EAGAIN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv)
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drerr_new(0, ESTC_IOSWITCH, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_io_unrelease(drmachid_t id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *dip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_device_t *dp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_IO_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel dp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dip = dp->node->n_getdip(dp->node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dip == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = DRMACH_INTERNAL_ERROR();
03831d35f7499c87d51205817c93e9a8d42c4baestevel else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int (*func)(dev_info_t *dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel func = (int (*)(dev_info_t *))kobj_getsymvalue("man_dr_attach",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (func) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_io_inst_t ios;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *pdip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int circ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Walk device tree to find rio dip for the board
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Since we are not interested in iosram instance here,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * initialize it to 0, so that the walk terminates as
03831d35f7499c87d51205817c93e9a8d42c4baestevel * soon as eri dip is found.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ios.iosram_inst = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ios.eri_dip = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ios.bnum = dp->bp->bnum;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (pdip = ddi_get_parent(dip)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_hold_devi(pdip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_devi_enter(pdip, &circ);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Root node doesn't have to be held in any way.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni ddi_walk_devs(dip, drmach_board_find_io_insts,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (void *)&ios);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (pdip) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_devi_exit(pdip, circ);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_rele_devi(pdip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("drmach_io_unrelease: bnum=%d eri=0x%p\n",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki ios.bnum, (void *)ios.eri_dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ios.eri_dip) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("calling man_dr_attach\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((*func)(ios.eri_dip))
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni err = drerr_new(0, ESTC_NWSWITCH, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Release hold acquired in
03831d35f7499c87d51205817c93e9a8d42c4baestevel * drmach_board_find_io_insts()
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_rele_devi(ios.eri_dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("man_dr_attach NOT present\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_io_release(drmachid_t id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *dip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_device_t *dp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_IO_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel dp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dip = dp->node->n_getdip(dp->node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dip == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = DRMACH_INTERNAL_ERROR();
03831d35f7499c87d51205817c93e9a8d42c4baestevel else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int (*func)(dev_info_t *dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel func = (int (*)(dev_info_t *))kobj_getsymvalue("man_dr_detach",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (func) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_io_inst_t ios;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *pdip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int circ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Walk device tree to find rio dip for the board
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Since we are not interested in iosram instance here,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * initialize it to 0, so that the walk terminates as
03831d35f7499c87d51205817c93e9a8d42c4baestevel * soon as eri dip is found.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ios.iosram_inst = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ios.eri_dip = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ios.bnum = dp->bp->bnum;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (pdip = ddi_get_parent(dip)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_hold_devi(pdip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_devi_enter(pdip, &circ);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Root node doesn't have to be held in any way.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni ddi_walk_devs(dip, drmach_board_find_io_insts,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (void *)&ios);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (pdip) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_devi_exit(pdip, circ);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_rele_devi(pdip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("drmach_io_release: bnum=%d eri=0x%p\n",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki ios.bnum, (void *)ios.eri_dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ios.eri_dip) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("calling man_dr_detach\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((*func)(ios.eri_dip))
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni err = drerr_new(0, ESTC_NWSWITCH, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Release hold acquired in
03831d35f7499c87d51205817c93e9a8d42c4baestevel * drmach_board_find_io_insts()
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_rele_devi(ios.eri_dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("man_dr_detach NOT present\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_io_post_release(drmachid_t id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *path;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *rdip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_device_t *dp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_DEVICE_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel dp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rdip = dp->node->n_getdip(dp->node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Always called after drmach_unconfigure() which on Starcat
03831d35f7499c87d51205817c93e9a8d42c4baestevel * unconfigures the branch but doesn't remove it so the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * dip must always exist.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(rdip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(e_ddi_branch_held(rdip));
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) ddi_pathname(rdip, path);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("post_release dip path is: %s\n", path);
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(path, MAXPATHLEN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (strcmp(dp->type, DRMACH_DEVTYPE_PCI) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (schpc_remove_pci(rdip)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("schpc_remove_pci failed\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESBD_OFFLINE, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("schpc_remove_pci succeeded\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_io_post_attach(drmachid_t id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int circ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *dip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *pdip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_device_t *dp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_io_inst_t ios;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_DEVICE_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel dp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dip = dp->node->n_getdip(dp->node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We held the branch rooted at dip earlier, so at a minimum the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * root i.e. dip must be present in the device tree.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (strcmp(dp->type, DRMACH_DEVTYPE_PCI) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (schpc_add_pci(dip)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("schpc_add_pci failed\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("schpc_add_pci succeeded\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Walk device tree to find rio dip for the board
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Since we are not interested in iosram instance here,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * initialize it to 0, so that the walk terminates as
03831d35f7499c87d51205817c93e9a8d42c4baestevel * soon as eri dip is found.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ios.iosram_inst = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ios.eri_dip = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ios.bnum = dp->bp->bnum;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (pdip = ddi_get_parent(dip)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_hold_devi(pdip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_devi_enter(pdip, &circ);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Root node doesn't have to be held in any way.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni ddi_walk_devs(dip, drmach_board_find_io_insts, (void *)&ios);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (pdip) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_devi_exit(pdip, circ);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_rele_devi(pdip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DRMACH_PR("drmach_io_post_attach: bnum=%d eri=0x%p\n",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki ios.bnum, (void *)ios.eri_dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ios.eri_dip) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int (*func)(dev_info_t *dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel func =
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (int (*)(dev_info_t *))kobj_getsymvalue("man_dr_attach", 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (func) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("calling man_dr_attach\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) (*func)(ios.eri_dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("man_dr_attach NOT present\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Release hold acquired in drmach_board_find_io_insts()
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_rele_devi(ios.eri_dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_io_status(drmachid_t id, drmach_status_t *stat)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_device_t *dp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int configured;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(DRMACH_IS_IO_ID(id));
03831d35f7499c87d51205817c93e9a8d42c4baestevel dp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_io_is_attached(id, &configured);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel stat->assigned = dp->bp->assigned;
03831d35f7499c87d51205817c93e9a8d42c4baestevel stat->powered = dp->bp->powered;
03831d35f7499c87d51205817c93e9a8d42c4baestevel stat->configured = (configured != 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel stat->busy = dp->busy;
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) strncpy(stat->type, dp->type, sizeof (stat->type));
03831d35f7499c87d51205817c93e9a8d42c4baestevel stat->info[0] = '\0';
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_mem_init_size(drmachid_t id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mem_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel gdcd_t *gdcd;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mem_chunk_t *chunk;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t chunks, pa, mask, sz;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_MEM_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_mem_get_base_physaddr(id, &pa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mask = ~ (DRMACH_MEM_SLICE_SIZE - 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel pa &= mask;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel gdcd = drmach_gdcd_new();
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (gdcd == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DRMACH_INTERNAL_ERROR());
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel sz = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunk = gdcd->dcd_chunk_list.dcl_chunk;
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunks = gdcd->dcd_chunk_list.dcl_chunks;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (chunks-- != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((chunk->mc_base_pa & mask) == pa) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sz += chunk->mc_mbytes * 1048576;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ++chunk;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->nbytes = sz;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_gdcd_dispose(gdcd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Hardware registers are organized into consecutively
03831d35f7499c87d51205817c93e9a8d42c4baestevel * addressed registers. The reg property's hi and lo fields
03831d35f7499c87d51205817c93e9a8d42c4baestevel * together describe the base address of the register set for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this memory-controller. Register descriptions and offsets
03831d35f7499c87d51205817c93e9a8d42c4baestevel * (from the base address) are as follows:
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Description Offset Size (bytes)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Memory Timing Control Register I 0x00 8
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Memory Timing Control Register II 0x08 8
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Memory Address Decoding Register I 0x10 8
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Memory Address Decoding Register II 0x18 8
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Memory Address Decoding Register III 0x20 8
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Memory Address Decoding Register IV 0x28 8
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Memory Address Control Register 0x30 8
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Memory Timing Control Register III 0x38 8
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Memory Timing Control Register IV 0x40 8
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Memory Timing Control Register V 0x48 8 (Jaguar, Panther only)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * EMU Activity Status Register 0x50 8 (Panther only)
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Only the Memory Address Decoding Register and EMU Activity Status
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Register addresses are needed for DRMACH.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_mem_new(drmach_device_t *proto, drmachid_t *idp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t madr_pa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mem_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int bank, count;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_read_reg_addr(proto, &madr_pa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = kmem_zalloc(sizeof (drmach_mem_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy(proto, &mp->dev, sizeof (mp->dev));
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->dev.node = drmach_node_dup(proto->node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->dev.cm.isa = (void *)drmach_mem_new;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->dev.cm.dispose = drmach_mem_dispose;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->dev.cm.release = drmach_mem_release;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->dev.cm.status = drmach_mem_status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->madr_pa = madr_pa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) snprintf(mp->dev.cm.name,
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki sizeof (mp->dev.cm.name), "%s", mp->dev.type);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (count = bank = 0; bank < DRMACH_MC_NBANKS; bank++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t madr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mem_read_madr(mp, bank, &madr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (madr & DRMACH_MC_VALID_MASK) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel count += 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If none of the banks had their valid bit set, that means
03831d35f7499c87d51205817c93e9a8d42c4baestevel * post did not configure this MC to participate in the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * domain. So, pretend this node does not exist by returning
03831d35f7499c87d51205817c93e9a8d42c4baestevel * a drmachid of zero.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (count == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* drmach_mem_dispose frees board mem list */
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_node_dispose(mp->dev.node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(mp, sizeof (*mp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel *idp = (drmachid_t)0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Only one mem unit per board is exposed to the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * PIM layer. The first mem unit encountered during
03831d35f7499c87d51205817c93e9a8d42c4baestevel * tree walk is used to represent all mem units on
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the same board.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mp->dev.bp->mem == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* start list of mem units on this board */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->dev.bp->mem = mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * force unum to zero since this is the only mem unit
03831d35f7499c87d51205817c93e9a8d42c4baestevel * that will be visible to the PIM layer.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->dev.unum = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * board memory size kept in this mem unit only
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_mem_init_size(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->dev.bp->mem = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* drmach_mem_dispose frees board mem list */
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_node_dispose(mp->dev.node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(mp, sizeof (*mp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel *idp = (drmachid_t)0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * allow this instance (the first encountered on this board)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to be visible to the PIM layer.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel *idp = (drmachid_t)mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mem_t *lp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* hide this mem instance behind the first. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (lp = mp->dev.bp->mem; lp->next; lp = lp->next)
03831d35f7499c87d51205817c93e9a8d42c4baestevel ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel lp->next = mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * hide this instance from the caller.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * See drmach_board_find_devices_cb() for details.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel *idp = (drmachid_t)0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_mem_dispose(drmachid_t id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mem_t *mp, *next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_t *bp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(DRMACH_IS_MEM_ID(id));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_bus_sync_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp = mp->dev.bp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel do {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mp->dev.node)
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_node_dispose(mp->dev.node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel next = mp->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(mp, sizeof (*mp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } while (mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->mem = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_bus_sync_list_update();
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_bus_sync_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_mem_add_span(drmachid_t id, uint64_t basepa, uint64_t size)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel pfn_t basepfn = (pfn_t)(basepa >> PAGESHIFT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel pgcnt_t npages = (pgcnt_t)(size >> PAGESHIFT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(size != 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_MEM_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
85f5803819bea86c07827a9544494e4ad327d95ddp rv = kcage_range_add(basepfn, npages, KCAGE_DOWN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv == ENOMEM) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "%lu megabytes not available"
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni " to kernel cage", size >> 20);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (rv != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* catch this in debug kernels */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "unexpected kcage_range_add"
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni " return value %d", rv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_mem_del_span(drmachid_t id, uint64_t basepa, uint64_t size)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel pfn_t basepfn = (pfn_t)(basepa >> PAGESHIFT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel pgcnt_t npages = (pgcnt_t)(size >> PAGESHIFT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_MEM_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (size > 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = kcage_range_delete_post_mem_del(basepfn, npages);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "unexpected kcage_range_delete_post_mem_del"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " return value %d", rv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DRMACH_INTERNAL_ERROR());
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_mem_disable(drmachid_t id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_MEM_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_mem_enable(drmachid_t id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_MEM_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_mem_get_alignment(drmachid_t id, uint64_t *mask)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define MB(mb) ((mb) * 1048576ull)
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel static struct {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint_t uk;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t segsz;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } uk2segsz[] = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel { 0x003, MB(256) },
03831d35f7499c87d51205817c93e9a8d42c4baestevel { 0x007, MB(512) },
03831d35f7499c87d51205817c93e9a8d42c4baestevel { 0x00f, MB(1024) },
03831d35f7499c87d51205817c93e9a8d42c4baestevel { 0x01f, MB(2048) },
03831d35f7499c87d51205817c93e9a8d42c4baestevel { 0x03f, MB(4096) },
03831d35f7499c87d51205817c93e9a8d42c4baestevel { 0x07f, MB(8192) },
03831d35f7499c87d51205817c93e9a8d42c4baestevel { 0x0ff, MB(16384) },
03831d35f7499c87d51205817c93e9a8d42c4baestevel { 0x1ff, MB(32768) },
03831d35f7499c87d51205817c93e9a8d42c4baestevel { 0x3ff, MB(65536) },
03831d35f7499c87d51205817c93e9a8d42c4baestevel { 0x7ff, MB(131072) }
03831d35f7499c87d51205817c93e9a8d42c4baestevel };
03831d35f7499c87d51205817c93e9a8d42c4baestevel static int len = sizeof (uk2segsz) / sizeof (uk2segsz[0]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#undef MB
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t largest_sz = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mem_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_MEM_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* prime the result with a default value */
03831d35f7499c87d51205817c93e9a8d42c4baestevel *mask = (DRMACH_MEM_SLICE_SIZE - 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (mp = id; mp; mp = mp->next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int bank;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (bank = 0; bank < DRMACH_MC_NBANKS; bank++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint_t uk;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t madr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* get register value, extract uk and normalize */
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mem_read_madr(mp, bank, &madr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(madr & DRMACH_MC_VALID_MASK))
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel uk = DRMACH_MC_UK(madr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* match uk value */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < len; i++)
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (uk == uk2segsz[i].uk)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i < len) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t sz = uk2segsz[i].segsz;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * remember largest segment size,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * update mask result
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sz > largest_sz) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel largest_sz = sz;
03831d35f7499c87d51205817c93e9a8d42c4baestevel *mask = sz - 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * uk not in table, punt using
03831d35f7499c87d51205817c93e9a8d42c4baestevel * entire slice size. no longer any
03831d35f7499c87d51205817c93e9a8d42c4baestevel * reason to check other banks.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel *mask = (DRMACH_MEM_SLICE_SIZE - 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_mem_get_base_physaddr(drmachid_t id, uint64_t *base_addr)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mem_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_MEM_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *base_addr = (uint64_t)-1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (mp = id; mp; mp = mp->next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int bank;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (bank = 0; bank < DRMACH_MC_NBANKS; bank++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t addr, madr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mem_read_madr(mp, bank, &madr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (madr & DRMACH_MC_VALID_MASK) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel addr = DRMACH_MC_UM_TO_PA(madr) |
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni DRMACH_MC_LM_TO_PA(madr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (addr < *base_addr)
03831d35f7499c87d51205817c93e9a8d42c4baestevel *base_addr = addr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* should not happen, but ... */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (*base_addr == (uint64_t)-1)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DRMACH_INTERNAL_ERROR());
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_bus_sync_list_update(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv, idx, cnt = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmachid_t id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(MUTEX_HELD(&drmach_bus_sync_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = drmach_array_first(drmach_boards, &idx, &id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (rv == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_t *bp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mem_t *mp = bp->mem;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (mp) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int bank;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (bank = 0; bank < DRMACH_MC_NBANKS; bank++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t madr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mem_read_madr(mp, bank, &madr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (madr & DRMACH_MC_VALID_MASK) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t pa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel pa = DRMACH_MC_UM_TO_PA(madr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel pa |= DRMACH_MC_LM_TO_PA(madr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The list is zero terminated.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Offset the pa by a doubleword
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to avoid confusing a pa value of
03831d35f7499c87d51205817c93e9a8d42c4baestevel * of zero with the terminator.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel pa += sizeof (uint64_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_bus_sync_list[cnt++] = pa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = mp->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = drmach_array_next(drmach_boards, &idx, &id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_bus_sync_list[cnt] = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_mem_get_memlist(drmachid_t id, struct memlist **ml)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct memlist *mlist;
03831d35f7499c87d51205817c93e9a8d42c4baestevel gdcd_t *gdcd;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mem_chunk_t *chunk;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t chunks, pa, mask;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_mem_get_base_physaddr(id, &pa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel gdcd = drmach_gdcd_new();
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (gdcd == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DRMACH_INTERNAL_ERROR());
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mask = ~ (DRMACH_MEM_SLICE_SIZE - 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel pa &= mask;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mlist = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunk = gdcd->dcd_chunk_list.dcl_chunk;
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunks = gdcd->dcd_chunk_list.dcl_chunks;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (chunks-- != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((chunk->mc_base_pa & mask) == pa) {
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni mlist = memlist_add_span(mlist, chunk->mc_base_pa,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni chunk->mc_mbytes * 1048576);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ++chunk;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_gdcd_dispose(gdcd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("GDCD derived memlist:");
03831d35f7499c87d51205817c93e9a8d42c4baestevel memlist_dump(mlist);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *ml = mlist;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_mem_get_size(drmachid_t id, uint64_t *bytes)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mem_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_MEM_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mp->nbytes != 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel *bytes = mp->nbytes;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_mem_get_slice_size(drmachid_t id, uint64_t *bytes)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_device_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_MEM_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (DRMACH_BNUM2SLOT(mp->bp->bnum)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case 0: *bytes = DRMACH_MEM_USABLE_SLICE_SIZE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case 1: *bytes = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = DRMACH_INTERNAL_ERROR();
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelprocessorid_t drmach_mem_cpu_affinity_nail;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelprocessorid_t
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_mem_cpu_affinity(drmachid_t id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_device_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_t *bp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel processorid_t cpuid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_MEM_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (CPU_CURRENT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_mem_cpu_affinity_nail) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpuid = drmach_mem_cpu_affinity_nail;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cpuid < 0 || cpuid > NCPU)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (CPU_CURRENT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&cpu_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cpu[cpuid] == NULL || !CPU_ACTIVE(cpu[cpuid]))
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpuid = CPU_CURRENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&cpu_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* try to choose a proc on the target board */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp = mp->bp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (bp->devices) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int d_idx;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmachid_t d_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = drmach_array_first(bp->devices, &d_idx, &d_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (rv == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (DRMACH_IS_CPU_ID(d_id)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_cpu_t *cp = d_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&cpu_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpuid = cp->cpuid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cpu[cpuid] && CPU_ACTIVE(cpu[cpuid])) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&cpu_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&cpu_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = drmach_array_next(bp->devices, &d_idx, &d_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* otherwise, this proc, wherever it is */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (CPU_CURRENT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_mem_release(drmachid_t id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_MEM_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_mem_status(drmachid_t id, drmach_status_t *stat)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mem_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t pa, slice_size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct memlist *ml;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(DRMACH_IS_MEM_ID(id));
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* get starting physical address of target memory */
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_mem_get_base_physaddr(id, &pa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* round down to slice boundary */
03831d35f7499c87d51205817c93e9a8d42c4baestevel slice_size = DRMACH_MEM_SLICE_SIZE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pa &= ~ (slice_size - 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* stop at first span that is in slice */
03831d35f7499c87d51205817c93e9a8d42c4baestevel memlist_read_lock();
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams for (ml = phys_install; ml; ml = ml->ml_next)
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams if (ml->ml_address >= pa && ml->ml_address < pa + slice_size)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel memlist_read_unlock();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel stat->assigned = mp->dev.bp->assigned;
03831d35f7499c87d51205817c93e9a8d42c4baestevel stat->powered = mp->dev.bp->powered;
03831d35f7499c87d51205817c93e9a8d42c4baestevel stat->configured = (ml != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel stat->busy = mp->dev.busy;
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) strncpy(stat->type, mp->dev.type, sizeof (stat->type));
03831d35f7499c87d51205817c93e9a8d42c4baestevel stat->info[0] = '\0';
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_board_deprobe(drmachid_t id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_t *bp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_BOARD_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (bp->tree) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_node_dispose(bp->tree);
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->tree = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (bp->devices) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_array_dispose(bp->devices, drmach_device_dispose);
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->devices = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp->mem = NULL; /* TODO: still needed? */
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED1*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_pt_showlpa(drmachid_t id, drmach_opts_t *opts)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_device_t *dp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t val;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int err = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (DRMACH_IS_CPU_ID(id)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_cpu_t *cp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_cpu_read_scr(cp, &val))
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (DRMACH_IS_IO_ID(id) && ((drmach_io_t *)id)->scsr_pa != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_io_t *io = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel val = lddphysio(io->scsr_pa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uprintf("showlpa %s::%s portid %d, base pa %lx, bound pa %lx\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni dp->bp->cm.name,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni dp->cm.name,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni dp->portid,
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (long)(DRMACH_LPA_BASE_TO_PA(val)),
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (long)(DRMACH_LPA_BND_TO_PA(val)));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_pt_ikprobe(drmachid_t id, drmach_opts_t *opts)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_t *bp = (drmach_board_t *)id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sc_gptwocfg_cookie_t scc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_BOARD_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* do saf configurator stuff */
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("calling sc_probe_board for bnum=%d\n", bp->bnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scc = sc_probe_board(bp->bnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scc == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drerr_new(0, ESTC_PROBE, bp->cm.name);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_pt_ikdeprobe(drmachid_t id, drmach_opts_t *opts)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_t *bp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sc_gptwocfg_cookie_t scc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_BOARD_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "DR: in-kernel unprobe board %d\n", bp->bnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scc = sc_unprobe_board(bp->bnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scc != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drerr_new(0, ESTC_DEPROBE, bp->cm.name);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_board_deprobe(id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_pt_readmem(drmachid_t id, drmach_opts_t *opts)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel _NOTE(ARGUNUSED(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel _NOTE(ARGUNUSED(opts))
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct memlist *ml;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t src_pa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t dst_pa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t dst;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dst_pa = va_to_pa(&dst);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel memlist_read_lock();
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams for (ml = phys_install; ml; ml = ml->ml_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t nbytes;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams src_pa = ml->ml_address;
56f33205c9ed776c3c909e07d52e94610a675740Jonathan Adams nbytes = ml->ml_size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (nbytes != 0ull) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* copy 32 bytes at src_pa to dst_pa */
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy32_il(src_pa, dst_pa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* increment by 32 bytes */
03831d35f7499c87d51205817c93e9a8d42c4baestevel src_pa += (4 * sizeof (uint64_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* decrement by 32 bytes */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nbytes -= (4 * sizeof (uint64_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel memlist_read_unlock();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_pt_recovercpu(drmachid_t id, drmach_opts_t *opts)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel _NOTE(ARGUNUSED(opts))
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_cpu_t *cp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_CPU_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel cp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&cpu_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) drmach_iocage_cpu_return(&(cp->dev),
03831d35f7499c87d51205817c93e9a8d42c4baestevel CPU_ENABLE | CPU_EXISTS | CPU_READY | CPU_RUNNING);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&cpu_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Starcat DR passthrus are for debugging purposes only.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct {
03831d35f7499c87d51205817c93e9a8d42c4baestevel const char *name;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *(*handler)(drmachid_t id, drmach_opts_t *opts);
03831d35f7499c87d51205817c93e9a8d42c4baestevel} drmach_pt_arr[] = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel { "showlpa", drmach_pt_showlpa },
03831d35f7499c87d51205817c93e9a8d42c4baestevel { "ikprobe", drmach_pt_ikprobe },
03831d35f7499c87d51205817c93e9a8d42c4baestevel { "ikdeprobe", drmach_pt_ikdeprobe },
03831d35f7499c87d51205817c93e9a8d42c4baestevel { "readmem", drmach_pt_readmem },
03831d35f7499c87d51205817c93e9a8d42c4baestevel { "recovercpu", drmach_pt_recovercpu },
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* the following line must always be last */
03831d35f7499c87d51205817c93e9a8d42c4baestevel { NULL, NULL }
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_passthru(drmachid_t id, drmach_opts_t *opts)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (drmach_pt_arr[i].name != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int len = strlen(drmach_pt_arr[i].name);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (strncmp(drmach_pt_arr[i].name, opts->copts, len) == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel i += 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_pt_arr[i].name == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drerr_new(0, ESTC_UNKPTCMD, opts->copts);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = (*drmach_pt_arr[i].handler)(id, opts);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_release(drmachid_t id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_common_t *cp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_DEVICE_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel cp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (cp->release(id));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_status(drmachid_t id, drmach_status_t *stat)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_common_t *cp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_enter(&drmach_boards_rwlock, RW_READER);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_ID(id)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_exit(&drmach_boards_rwlock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_NOTID, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = cp->status(id, stat);
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_exit(&drmach_boards_rwlock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_i_status(drmachid_t id, drmach_status_t *stat)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_common_t *cp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_NOTID, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel cp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (cp->status(id, stat));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_unconfigure(drmachid_t id, int flags)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_device_t *dp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *rdip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel char name[OBP_MAXDRVNAME];
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Since CPU nodes are not configured, it is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * necessary to skip the unconfigure step as
03831d35f7499c87d51205817c93e9a8d42c4baestevel * well.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (DRMACH_IS_CPU_ID(id)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (; id; ) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *fdip = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_DEVICE_ID(id))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(0, ESTC_INAPPROP, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel dp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rdip = dp->node->n_getdip(dp->node);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * drmach_unconfigure() is always called on a configured branch.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * So the root of the branch was held earlier and must exist.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(rdip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("drmach_unconfigure: unconfiguring DDI branch");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = dp->node->n_getprop(dp->node,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "name", name, OBP_MAXDRVNAME);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* The node must have a name */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_name2type_idx(name) < 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (DRMACH_IS_MEM_ID(id)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mem_t *mp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel id = mp->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel id = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * NOTE: FORCE flag is no longer needed under devfs
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(e_ddi_branch_held(rdip));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (e_ddi_branch_unconfigure(rdip, &fdip, 0) != 0) {
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni sbd_error_t *err = NULL;
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni char *path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If non-NULL, fdip is returned held and must be
03831d35f7499c87d51205817c93e9a8d42c4baestevel * released.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (fdip != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) ddi_pathname(fdip, path);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_release_devi(fdip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) ddi_pathname(rdip, path);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drerr_new(1, ESTC_DRVFAIL, path);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(path, MAXPATHLEN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If we were unconfiguring an IO board, a call was
03831d35f7499c87d51205817c93e9a8d42c4baestevel * made to man_dr_detach. We now need to call
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_dr_attach to regain man use of the eri.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (DRMACH_IS_IO_ID(id)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int (*func)(dev_info_t *dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel func = (int (*)(dev_info_t *))kobj_getsymvalue\
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni ("man_dr_attach", 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (func) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_io_inst_t ios;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *pdip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int circ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Walk device tree to find rio dip for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the board
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Since we are not interested in iosram
03831d35f7499c87d51205817c93e9a8d42c4baestevel * instance here, initialize it to 0, so
03831d35f7499c87d51205817c93e9a8d42c4baestevel * that the walk terminates as soon as
03831d35f7499c87d51205817c93e9a8d42c4baestevel * eri dip is found.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ios.iosram_inst = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ios.eri_dip = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ios.bnum = dp->bp->bnum;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (pdip = ddi_get_parent(rdip)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_hold_devi(pdip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_devi_enter(pdip, &circ);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Root node doesn't have to be held in
03831d35f7499c87d51205817c93e9a8d42c4baestevel * any way.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(e_ddi_branch_held(rdip));
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_walk_devs(rdip,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni drmach_board_find_io_insts,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (void *)&ios);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("drmach_unconfigure: bnum=%d"
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni " eri=0x%p\n",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki ios.bnum, (void *)ios.eri_dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (pdip) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_devi_exit(pdip, circ);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_rele_devi(pdip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ios.eri_dip) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("calling"
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni " man_dr_attach\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) (*func)(ios.eri_dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Release hold acquired in
03831d35f7499c87d51205817c93e9a8d42c4baestevel * drmach_board_find_io_insts()
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_rele_devi(ios.eri_dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (DRMACH_IS_MEM_ID(id)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mem_t *mp = id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel id = mp->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel id = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * drmach interfaces to legacy Starfire platmod logic
03831d35f7499c87d51205817c93e9a8d42c4baestevel * linkage via runtime symbol look up, called from plat_cpu_power*
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Start up a cpu. It is possible that we're attempting to restart
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the cpu after an UNCONFIGURE in which case the cpu will be
03831d35f7499c87d51205817c93e9a8d42c4baestevel * spinning in its cache. So, all we have to do is wakeup him up.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Under normal circumstances the cpu will be coming from a previous
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CONNECT and thus will be spinning in OBP. In both cases, the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * startup sequence is the same.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_cpu_poweron(struct cpu *cp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("drmach_cpu_poweron: starting cpuid %d\n", cp->cpu_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(MUTEX_HELD(&cpu_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_cpu_start(cp) != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EBUSY);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_cpu_poweroff(struct cpu *cp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int ntries;
03831d35f7499c87d51205817c93e9a8d42c4baestevel processorid_t cpuid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel void drmach_cpu_shutdown_self(void);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("drmach_cpu_poweroff: stopping cpuid %d\n", cp->cpu_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(MUTEX_HELD(&cpu_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XXX CHEETAH SUPPORT
03831d35f7499c87d51205817c93e9a8d42c4baestevel * for cheetah, we need to grab the iocage lock since iocage
03831d35f7499c87d51205817c93e9a8d42c4baestevel * memory is used for e$ flush.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_is_cheetah) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_iocage_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (drmach_iocage_is_busy)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_wait(&drmach_iocage_cv, &drmach_iocage_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_iocage_is_busy = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_iocage_mem_scrub(ecache_size * 2);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_iocage_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpuid = cp->cpu_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set affinity to ensure consistent reading and writing of
03831d35f7499c87d51205817c93e9a8d42c4baestevel * drmach_xt_mb[cpuid] by one "master" CPU directing
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the shutdown of the target CPU.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel affinity_set(CPU->cpu_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Capture all CPUs (except for detaching proc) to prevent
03831d35f7499c87d51205817c93e9a8d42c4baestevel * crosscalls to the detaching proc until it has cleared its
03831d35f7499c87d51205817c93e9a8d42c4baestevel * bit in cpu_ready_set.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The CPUs remain paused and the prom_mutex is known to be free.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This prevents blocking when doing prom IEEE-1275 calls at a
03831d35f7499c87d51205817c93e9a8d42c4baestevel * high PIL level.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel promsafe_pause_cpus();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Quiesce interrupts on the target CPU. We do this by setting
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the CPU 'not ready'- (i.e. removing the CPU from cpu_ready_set) to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * prevent it from receiving cross calls and cross traps.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This prevents the processor from receiving any new soft interrupts.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp_cpu_quiesce(cp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) prom_hotremovecpu(cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel start_cpus();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* setup xt_mb, will be cleared by drmach_shutdown_asm when ready */
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_xt_mb[cpuid] = 0x80;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel xt_one_unchecked(cp->cpu_id, (xcfunc_t *)idle_stop_xcall,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (uint64_t)drmach_cpu_shutdown_self, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ntries = drmach_cpu_ntries;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (drmach_xt_mb[cpuid] && ntries) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DELAY(drmach_cpu_delay);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ntries--;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_xt_mb[cpuid] = 0; /* steal the cache line back */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel membar_sync(); /* make sure copy-back retires */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel affinity_clear();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XXX CHEETAH SUPPORT
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_is_cheetah) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_iocage_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_iocage_mem_scrub(ecache_size * 2);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_iocage_is_busy = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_signal(&drmach_iocage_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_iocage_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("waited %d out of %d tries for "
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "drmach_cpu_shutdown_self on cpu%d",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni drmach_cpu_ntries - ntries, drmach_cpu_ntries, cp->cpu_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Do this here instead of drmach_cpu_shutdown_self() to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * avoid an assertion failure panic in turnstile.c.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel CPU_SIGNATURE(OS_SIG, SIGST_DETACHED, SIGSUBST_NULL, cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_iocage_mem_scrub(uint64_t nbytes)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki extern uint32_t drmach_bc_bzero(void*, size_t);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki uint32_t rv;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(MUTEX_HELD(&cpu_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel affinity_set(CPU->cpu_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = drmach_bc_bzero(drmach_iocage_vaddr, nbytes);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR(
03831d35f7499c87d51205817c93e9a8d42c4baestevel "iocage scrub failed, drmach_bc_bzero returned %d\n", rv);
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni rv = drmach_bc_bzero(drmach_iocage_vaddr, drmach_iocage_size);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_PANIC,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "iocage scrub failed, drmach_bc_bzero rv=%d\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpu_flush_ecache();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel affinity_clear();
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define ALIGN(x, a) ((a) == 0 ? (uintptr_t)(x) : \
03831d35f7499c87d51205817c93e9a8d42c4baestevel (((uintptr_t)(x) + (uintptr_t)(a) - 1l) & ~((uintptr_t)(a) - 1l)))
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_iocage_mem_get(dr_testboard_req_t *tbrq)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel pfn_t basepfn;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pgcnt_t npages;
03831d35f7499c87d51205817c93e9a8d42c4baestevel extern int memscrub_delete_span(pfn_t, pgcnt_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t drmach_iocage_paddr_mbytes;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(drmach_iocage_paddr != -1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel basepfn = (pfn_t)(drmach_iocage_paddr >> PAGESHIFT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel npages = (pgcnt_t)(drmach_iocage_size >> PAGESHIFT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) memscrub_delete_span(basepfn, npages);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&cpu_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_iocage_mem_scrub(drmach_iocage_size);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&cpu_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * HPOST wants the address of the cage to be 64 megabyte-aligned
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and in megabyte units.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The size of the cage is also in megabyte units.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(drmach_iocage_paddr == ALIGN(drmach_iocage_paddr, 0x4000000));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_iocage_paddr_mbytes = drmach_iocage_paddr / 0x100000;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel tbrq->memaddrhi = (uint32_t)(drmach_iocage_paddr_mbytes >> 32);
03831d35f7499c87d51205817c93e9a8d42c4baestevel tbrq->memaddrlo = (uint32_t)drmach_iocage_paddr_mbytes;
03831d35f7499c87d51205817c93e9a8d42c4baestevel tbrq->memlen = drmach_iocage_size / 0x100000;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("drmach_iocage_mem_get: hi: 0x%x", tbrq->memaddrhi);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("drmach_iocage_mem_get: lo: 0x%x", tbrq->memaddrlo);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("drmach_iocage_mem_get: size: 0x%x", tbrq->memlen);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_iocage_mem_return(dr_testboard_reply_t *tbr)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel _NOTE(ARGUNUSED(tbr))
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel pfn_t basepfn;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pgcnt_t npages;
03831d35f7499c87d51205817c93e9a8d42c4baestevel extern int memscrub_add_span(pfn_t, pgcnt_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(drmach_iocage_paddr != -1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel basepfn = (pfn_t)(drmach_iocage_paddr >> PAGESHIFT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel npages = (pgcnt_t)(drmach_iocage_size >> PAGESHIFT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) memscrub_add_span(basepfn, npages);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&cpu_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_iocage_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_iocage_mem_scrub(drmach_iocage_size);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_iocage_is_busy = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_signal(&drmach_iocage_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_iocage_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&cpu_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_cpu_intr_disable(cpu_t *cp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cpu_intr_disable(cp) != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_iocage_cpu_acquire(drmach_device_t *dp, cpu_flag_t *oflags)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct cpu *cp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel processorid_t cpuid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel static char *fn = "drmach_iocage_cpu_acquire";
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int impl;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(DRMACH_IS_CPU_ID(dp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(MUTEX_HELD(&cpu_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpuid = ((drmach_cpu_t *)dp)->cpuid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("%s: attempting to acquire CPU id %d", fn, cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dp->busy)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((cp = cpu_get(cpuid)) == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("%s: cpu_get(%d) returned NULL", fn, cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!CPU_ACTIVE(cp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("%s: skipping offlined CPU id %d", fn, cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * There is a known HW bug where a Jaguar CPU in Safari port 0 (SBX/P0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * can fail to receive an XIR. To workaround this issue until a hardware
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fix is implemented, we will exclude the selection of these CPUs.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Once a fix is implemented in hardware, this code should be updated
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to allow Jaguar CPUs that have the fix to be used. However, support
03831d35f7499c87d51205817c93e9a8d42c4baestevel * must be retained to skip revisions that do not have this fix.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_cpu_get_impl(dp, &impl);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("%s: error getting impl. of CPU id %d", fn, cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_err_clear(&err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IS_JAGUAR(impl) && (STARCAT_CPUID_TO_LPORT(cpuid) == 0) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_iocage_exclude_jaguar_port_zero) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("%s: excluding CPU id %d: port 0 on jaguar",
03831d35f7499c87d51205817c93e9a8d42c4baestevel fn, cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(oflags);
03831d35f7499c87d51205817c93e9a8d42c4baestevel *oflags = cp->cpu_flags;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cpu_offline(cp, 0)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("%s: cpu_offline failed for CPU id %d", fn, cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cpu_poweroff(cp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("%s: cpu_poweroff failed for CPU id %d", fn, cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cpu_online(cp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "failed to online CPU id %d "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "during I/O cage test selection", cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (CPU_ACTIVE(cp) && cpu_flagged_nointr(*oflags) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_cpu_intr_disable(cp) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "failed to restore CPU id %d "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "no-intr during I/O cage test selection", cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cpu_unconfigure(cpuid)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("%s: cpu_unconfigure failed for CPU id %d", fn,
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) cpu_configure(cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((cp = cpu_get(cpuid)) == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "failed to reconfigure CPU id %d "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "during I/O cage test selection", cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel dp->busy = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cpu_poweron(cp) || cpu_online(cp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "failed to %s CPU id %d "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "during I/O cage test selection",
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpu_is_poweredoff(cp) ?
03831d35f7499c87d51205817c93e9a8d42c4baestevel "poweron" : "online", cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (CPU_ACTIVE(cp) && cpu_flagged_nointr(*oflags) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_cpu_intr_disable(cp) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "failed to restore CPU id %d "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "no-intr during I/O cage test selection", cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dp->busy = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("%s: acquired CPU id %d", fn, cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Attempt to acquire all the CPU devices passed in. It is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * assumed that all the devices in the list are the cores of
03831d35f7499c87d51205817c93e9a8d42c4baestevel * a single CMP device. Non CMP devices can be handled as a
03831d35f7499c87d51205817c93e9a8d42c4baestevel * single core CMP by passing in a one element list.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Success is only returned if *all* the devices in the list
03831d35f7499c87d51205817c93e9a8d42c4baestevel * can be acquired. In the failure case, none of the devices
03831d35f7499c87d51205817c93e9a8d42c4baestevel * in the list will be held as acquired.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_iocage_cmp_acquire(drmach_device_t **dpp, cpu_flag_t *oflags)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int curr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT((dpp != NULL) && (*dpp != NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Walk the list of CPU devices (cores of a CMP)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and attempt to acquire them. Bail out if an
03831d35f7499c87d51205817c93e9a8d42c4baestevel * error is encountered.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
25cf1a301a396c38e8adf52c15f537b80d2483f7jl for (curr = 0; curr < MAX_CORES_PER_CMP; curr++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* check for the end of the list */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dpp[curr] == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(DRMACH_IS_CPU_ID(dpp[curr]));
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(dpp[curr]->portid == (*dpp)->portid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = drmach_iocage_cpu_acquire(dpp[curr], &oflags[curr]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check for an error.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Make a best effort attempt to return any cores
03831d35f7499c87d51205817c93e9a8d42c4baestevel * that were already acquired before the error was
03831d35f7499c87d51205817c93e9a8d42c4baestevel * encountered.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < curr; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) drmach_iocage_cpu_return(dpp[i], oflags[i]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (rv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_iocage_cpu_return(drmach_device_t *dp, cpu_flag_t oflags)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel processorid_t cpuid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct cpu *cp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel static char *fn = "drmach_iocage_cpu_return";
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(DRMACH_IS_CPU_ID(dp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(MUTEX_HELD(&cpu_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpuid = ((drmach_cpu_t *)dp)->cpuid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("%s: attempting to return CPU id: %d", fn, cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cpu_configure(cpuid)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "failed to reconfigure CPU id %d "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "after I/O cage test", cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The component was never set to unconfigured during the IO
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cage test, so we need to leave marked as busy to prevent
03831d35f7499c87d51205817c93e9a8d42c4baestevel * further DR operations involving this component.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((cp = cpu_get(cpuid)) == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "cpu_get failed on CPU id %d after "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "I/O cage test", cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel dp->busy = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cpu_poweron(cp) || cpu_online(cp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "failed to %s CPU id %d after I/O "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "cage test", cpu_is_poweredoff(cp) ?
03831d35f7499c87d51205817c93e9a8d42c4baestevel "poweron" : "online", cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * drmach_iocage_cpu_acquire will accept cpus in state P_ONLINE or
03831d35f7499c87d51205817c93e9a8d42c4baestevel * P_NOINTR. Need to return to previous user-visible state.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (CPU_ACTIVE(cp) && cpu_flagged_nointr(oflags) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_cpu_intr_disable(cp) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "failed to restore CPU id %d "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "no-intr after I/O cage test", cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dp->busy = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("%s: returned CPU id: %d", fn, cpuid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (rv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_iocage_cpu_get(dr_testboard_req_t *tbrq, drmach_device_t **dpp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpu_flag_t *oflags)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_t *bp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int b_rv;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int b_idx;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmachid_t b_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int found;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&cpu_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(drmach_boards != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel found = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Walk the board list.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel b_rv = drmach_array_first(drmach_boards, &b_idx, &b_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (b_rv == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel int d_rv;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int d_idx;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmachid_t d_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp = b_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (bp->connected == 0 || bp->devices == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel b_rv = drmach_array_next(drmach_boards, &b_idx, &b_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* An AXQ restriction disqualifies MCPU's as candidates. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (DRMACH_BNUM2SLOT(bp->bnum) == 1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel b_rv = drmach_array_next(drmach_boards, &b_idx, &b_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Walk the device list of this board.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel d_rv = drmach_array_first(bp->devices, &d_idx, &d_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (d_rv == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_device_t *ndp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* only interested in CPU devices */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!DRMACH_IS_CPU_ID(d_id)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel d_rv = drmach_array_next(bp->devices, &d_idx,
03831d35f7499c87d51205817c93e9a8d42c4baestevel &d_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The following code assumes two properties
03831d35f7499c87d51205817c93e9a8d42c4baestevel * of a CMP device:
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 1. All cores of a CMP are grouped together
03831d35f7499c87d51205817c93e9a8d42c4baestevel * in the device list.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 2. There will only be a maximum of two cores
03831d35f7499c87d51205817c93e9a8d42c4baestevel * present in the CMP.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If either of these two properties change,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this code will have to be revisited.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dpp[0] = d_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dpp[1] = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Get the next device. It may or may not be used.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel d_rv = drmach_array_next(bp->devices, &d_idx, &d_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndp = d_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((d_rv == 0) && DRMACH_IS_CPU_ID(d_id)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The second device is only interesting for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this pass if it has the same portid as the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * first device. This implies that both are
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cores of the same CMP.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dpp[0]->portid == ndp->portid) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dpp[1] = d_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Attempt to acquire all cores of the CMP.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_iocage_cmp_acquire(dpp, oflags) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel found = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check if the search for the second core was
03831d35f7499c87d51205817c93e9a8d42c4baestevel * successful. If not, the next iteration should
03831d35f7499c87d51205817c93e9a8d42c4baestevel * use that device.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dpp[1] == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel d_rv = drmach_array_next(bp->devices, &d_idx, &d_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (found)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel b_rv = drmach_array_next(drmach_boards, &b_idx, &b_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&cpu_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!found) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drerr_new(1, ESTC_IOCAGE_NO_CPU_AVAIL, NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel tbrq->cpu_portid = (*dpp)->portid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Setup an iocage by acquiring a cpu and memory.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbd_error_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_iocage_setup(dr_testboard_req_t *tbrq, drmach_device_t **dpp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpu_flag_t *oflags)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_error_t *err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_iocage_cpu_get(tbrq, dpp, oflags);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!err) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_iocage_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (drmach_iocage_is_busy)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_wait(&drmach_iocage_cv, &drmach_iocage_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_iocage_is_busy = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_iocage_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drmach_iocage_mem_get(tbrq);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&drmach_iocage_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_iocage_is_busy = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_signal(&drmach_iocage_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&drmach_iocage_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_SCHIZO_PCI_LEAF_MAX 2
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_SCHIZO_PCI_SLOT_MAX 8
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_S1P_SAMPLE_MAX 2
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveltypedef enum {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_POST_SUSPEND = 0,
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PRE_RESUME
03831d35f7499c87d51205817c93e9a8d42c4baestevel} drmach_sr_iter_t;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveltypedef struct {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *dip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t portid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t pcr_sel_save;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t pic_l2_io_q[DRMACH_S1P_SAMPLE_MAX];
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t reg_basepa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel} drmach_s1p_axq_t;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveltypedef struct {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *dip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t portid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t csr_basepa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t slot_intr_state_diag;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t obio_intr_state_diag;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint_t nmap_regs;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t *intr_map_regs;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } regs[DRMACH_S1P_SAMPLE_MAX];
03831d35f7499c87d51205817c93e9a8d42c4baestevel} drmach_s1p_pci_t;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveltypedef struct {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t csr_basepa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t csr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t errctrl;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t errlog;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } regs[DRMACH_S1P_SAMPLE_MAX];
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_s1p_pci_t pci[DRMACH_SCHIZO_PCI_LEAF_MAX];
03831d35f7499c87d51205817c93e9a8d42c4baestevel} drmach_s1p_schizo_t;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveltypedef struct {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_s1p_axq_t axq;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_s1p_schizo_t schizo[STARCAT_SLOT1_IO_MAX];
03831d35f7499c87d51205817c93e9a8d42c4baestevel} drmach_slot1_pause_t;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Table of saved state for paused slot1 devices.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic drmach_slot1_pause_t *drmach_slot1_paused[STARCAT_BDSET_MAX];
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int drmach_slot1_pause_init = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevelint drmach_slot1_pause_debug = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#else
03831d35f7499c87d51205817c93e9a8d42c4baestevelint drmach_slot1_pause_debug = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_is_slot1_pause_axq(dev_info_t *dip, char *name, int *id, uint64_t *reg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int portid, exp, slot, i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_reg_t regs[2];
03831d35f7499c87d51205817c93e9a8d42c4baestevel int reglen = sizeof (regs);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((portid = ddi_getprop(DDI_DEV_T_ANY, dip,
03831d35f7499c87d51205817c93e9a8d42c4baestevel DDI_PROP_DONTPASS, "portid", -1)) == -1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel exp = (portid >> 5) & 0x1f;
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot = portid & 0x1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (slot == 0 || strncmp(name, DRMACH_AXQ_NAMEPROP,
03831d35f7499c87d51205817c93e9a8d42c4baestevel strlen(DRMACH_AXQ_NAMEPROP))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&cpu_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < STARCAT_SLOT1_CPU_MAX; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cpu[MAKE_CPUID(exp, slot, i)]) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* maxcat cpu present */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&cpu_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&cpu_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "reg", (caddr_t)regs, &reglen) != DDI_PROP_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("drmach_is_slot1_pause_axq: no reg prop for "
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki "axq dip=%p\n", (void *)dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(id && reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel *reg = (uint64_t)regs[0].reg_addr_hi << 32;
03831d35f7499c87d51205817c93e9a8d42c4baestevel *reg |= (uint64_t)regs[0].reg_addr_lo;
03831d35f7499c87d51205817c93e9a8d42c4baestevel *id = portid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Allocate an entry in the slot1_paused state table.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_slot1_pause_add_axq(dev_info_t *axq_dip, char *axq_name, int axq_portid,
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t reg, drmach_slot1_pause_t **slot1_paused)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int axq_exp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_slot1_pause_t *slot1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel axq_exp = (axq_portid >> 5) & 0x1f;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(axq_portid & 0x1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(slot1_paused[axq_exp] == NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(strncmp(axq_name, DRMACH_AXQ_NAMEPROP,
03831d35f7499c87d51205817c93e9a8d42c4baestevel strlen(DRMACH_AXQ_NAMEPROP)) == 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot1 = kmem_zalloc(sizeof (*slot1), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XXX This dip should really be held (via ndi_hold_devi())
03831d35f7499c87d51205817c93e9a8d42c4baestevel * before saving it in the axq pause structure. However that
03831d35f7499c87d51205817c93e9a8d42c4baestevel * would prevent DR as the pause data structures persist until
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the next suspend. drmach code should be modified to free the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the slot 1 pause data structures for a boardset when its
03831d35f7499c87d51205817c93e9a8d42c4baestevel * slot 1 board is DRed out. The dip can then be released via
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ndi_rele_devi() when the pause data structure is freed
03831d35f7499c87d51205817c93e9a8d42c4baestevel * allowing DR to proceed. Until this change is made, drmach
03831d35f7499c87d51205817c93e9a8d42c4baestevel * code should be careful about dereferencing the saved dip
03831d35f7499c87d51205817c93e9a8d42c4baestevel * as it may no longer exist.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot1->axq.dip = axq_dip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot1->axq.portid = axq_portid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot1->axq.reg_basepa = reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot1_paused[axq_exp] = slot1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_s1p_pci_free(drmach_s1p_pci_t *pci)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < DRMACH_S1P_SAMPLE_MAX; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (pci->regs[i].intr_map_regs != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(pci->regs[i].nmap_regs > 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(pci->regs[i].intr_map_regs,
03831d35f7499c87d51205817c93e9a8d42c4baestevel pci->regs[i].nmap_regs * sizeof (uint64_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_slot1_pause_free(drmach_slot1_pause_t **slot1_paused)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i, j, k;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_slot1_pause_t *slot1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < STARCAT_BDSET_MAX; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((slot1 = slot1_paused[i]) == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (j = 0; j < STARCAT_SLOT1_IO_MAX; j++)
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (k = 0; k < DRMACH_SCHIZO_PCI_LEAF_MAX; k++)
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_s1p_pci_free(&slot1->schizo[j].pci[k]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(slot1, sizeof (*slot1));
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot1_paused[i] = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Tree walk callback routine. If dip represents a Schizo PCI leaf,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fill in the appropriate info in the slot1_paused state table.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_find_slot1_io(dev_info_t *dip, void *arg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int portid, exp, ioc_unum, leaf_unum;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char buf[OBP_MAXDRVNAME];
03831d35f7499c87d51205817c93e9a8d42c4baestevel int buflen = sizeof (buf);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_reg_t regs[3];
03831d35f7499c87d51205817c93e9a8d42c4baestevel int reglen = sizeof (regs);
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t leaf_offset;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t schizo_csr_pa, pci_csr_pa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_s1p_pci_t *pci;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_slot1_pause_t **slot1_paused = (drmach_slot1_pause_t **)arg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "name", (caddr_t)buf, &buflen) != DDI_PROP_SUCCESS ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel strncmp(buf, DRMACH_PCI_NAMEPROP, strlen(DRMACH_PCI_NAMEPROP))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_WALK_CONTINUE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((portid = ddi_getprop(DDI_DEV_T_ANY, dip,
03831d35f7499c87d51205817c93e9a8d42c4baestevel DDI_PROP_DONTPASS, "portid", -1)) == -1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_WALK_CONTINUE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "reg", (caddr_t)regs, &reglen) != DDI_PROP_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("drmach_find_slot1_io: no reg prop for pci "
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki "dip=%p\n", (void *)dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_WALK_CONTINUE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel exp = portid >> 5;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ioc_unum = portid & 0x1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel leaf_offset = regs[0].reg_addr_lo & 0x7fffff;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pci_csr_pa = (uint64_t)regs[0].reg_addr_hi << 32;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pci_csr_pa |= (uint64_t)regs[0].reg_addr_lo;
03831d35f7499c87d51205817c93e9a8d42c4baestevel schizo_csr_pa = (uint64_t)regs[1].reg_addr_hi << 32;
03831d35f7499c87d51205817c93e9a8d42c4baestevel schizo_csr_pa |= (uint64_t)regs[1].reg_addr_lo;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(exp >= 0 && exp < STARCAT_BDSET_MAX);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(slot1_paused[exp] != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(leaf_offset == 0x600000 || leaf_offset == 0x700000);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(slot1_paused[exp]->schizo[ioc_unum].csr_basepa == 0x0UL ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot1_paused[exp]->schizo[ioc_unum].csr_basepa == schizo_csr_pa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel leaf_unum = (leaf_offset == 0x600000) ? 0 : 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot1_paused[exp]->schizo[ioc_unum].csr_basepa = schizo_csr_pa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pci = &slot1_paused[exp]->schizo[ioc_unum].pci[leaf_unum];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XXX This dip should really be held (via ndi_hold_devi())
03831d35f7499c87d51205817c93e9a8d42c4baestevel * before saving it in the pci pause structure. However that
03831d35f7499c87d51205817c93e9a8d42c4baestevel * would prevent DR as the pause data structures persist until
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the next suspend. drmach code should be modified to free the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the slot 1 pause data structures for a boardset when its
03831d35f7499c87d51205817c93e9a8d42c4baestevel * slot 1 board is DRed out. The dip can then be released via
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ndi_rele_devi() when the pause data structure is freed
03831d35f7499c87d51205817c93e9a8d42c4baestevel * allowing DR to proceed. Until this change is made, drmach
03831d35f7499c87d51205817c93e9a8d42c4baestevel * code should be careful about dereferencing the saved dip as
03831d35f7499c87d51205817c93e9a8d42c4baestevel * it may no longer exist.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel pci->dip = dip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pci->portid = portid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pci->csr_basepa = pci_csr_pa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("drmach_find_slot1_io: name=%s, portid=0x%x, dip=%p\n",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki buf, portid, (void *)dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_WALK_PRUNECHILD);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_slot1_pause_add_io(drmach_slot1_pause_t **slot1_paused)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Root node doesn't have to be held
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_walk_devs(ddi_root_node(), drmach_find_slot1_io,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void *)slot1_paused);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Save the interrupt mapping registers for each non-idle interrupt
03831d35f7499c87d51205817c93e9a8d42c4baestevel * represented by the bit pairs in the saved interrupt state
03831d35f7499c87d51205817c93e9a8d42c4baestevel * diagnostic registers for this PCI leaf.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_s1p_intr_map_reg_save(drmach_s1p_pci_t *pci, drmach_sr_iter_t iter)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i, cnt, ino;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *dname;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t Xmits;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dname = ddi_binding_name(pci->dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel Xmits = (strcmp(dname, XMITS_BINDING_NAME) == 0) ? 1 : 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 1st pass allocates, 2nd pass populates.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < 2; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cnt = ino = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * PCI slot interrupts
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = pci->regs[iter].slot_intr_state_diag;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (reg) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Xmits Interrupt Number Offset(ino) Assignments
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 00-17 PCI Slot Interrupts
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 18-1f Not Used
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((Xmits) && (ino > 0x17))
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((reg & COMMON_CLEAR_INTR_REG_MASK) !=
03831d35f7499c87d51205817c93e9a8d42c4baestevel COMMON_CLEAR_INTR_REG_IDLE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel pci->regs[iter].intr_map_regs[cnt] =
03831d35f7499c87d51205817c93e9a8d42c4baestevel lddphysio(pci->csr_basepa +
03831d35f7499c87d51205817c93e9a8d42c4baestevel SCHIZO_IB_INTR_MAP_REG_OFFSET +
03831d35f7499c87d51205817c93e9a8d42c4baestevel ino * sizeof (reg));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel ++cnt;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel ++ino;
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg >>= 2;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Xmits Interrupt Number Offset(ino) Assignments
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 20-2f Not Used
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 30-37 Internal interrupts
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 38-3e Not Used
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ino = (Xmits) ? 0x30 : 0x20;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * OBIO and internal schizo interrupts
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Each PCI leaf has a set of mapping registers for all
03831d35f7499c87d51205817c93e9a8d42c4baestevel * possible interrupt sources except the NewLink interrupts.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = pci->regs[iter].obio_intr_state_diag;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (reg && ino <= 0x38) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((reg & COMMON_CLEAR_INTR_REG_MASK) !=
03831d35f7499c87d51205817c93e9a8d42c4baestevel COMMON_CLEAR_INTR_REG_IDLE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel pci->regs[iter].intr_map_regs[cnt] =
03831d35f7499c87d51205817c93e9a8d42c4baestevel lddphysio(pci->csr_basepa +
03831d35f7499c87d51205817c93e9a8d42c4baestevel SCHIZO_IB_INTR_MAP_REG_OFFSET +
03831d35f7499c87d51205817c93e9a8d42c4baestevel ino * sizeof (reg));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel ++cnt;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel ++ino;
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg >>= 2;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel pci->regs[iter].nmap_regs = cnt;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pci->regs[iter].intr_map_regs =
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_zalloc(cnt * sizeof (reg), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_s1p_axq_update(drmach_s1p_axq_t *axq, drmach_sr_iter_t iter)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (axq->reg_basepa == 0x0UL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iter == DRMACH_POST_SUSPEND) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel axq->pcr_sel_save = ldphysio(axq->reg_basepa +
03831d35f7499c87d51205817c93e9a8d42c4baestevel AXQ_SLOT1_PERFCNT_SEL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Select l2_io_queue counter by writing L2_IO_Q mux
03831d35f7499c87d51205817c93e9a8d42c4baestevel * input to bits 0-6 of perf cntr select reg.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = axq->pcr_sel_save;
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg &= ~AXQ_PIC_CLEAR_MASK;
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg |= L2_IO_Q;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel stphysio(axq->reg_basepa + AXQ_SLOT1_PERFCNT_SEL, reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel axq->pic_l2_io_q[iter] = ldphysio(axq->reg_basepa + AXQ_SLOT1_PERFCNT0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iter == DRMACH_PRE_RESUME) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel stphysio(axq->reg_basepa + AXQ_SLOT1_PERFCNT_SEL,
03831d35f7499c87d51205817c93e9a8d42c4baestevel axq->pcr_sel_save);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("drmach_s1p_axq_update: axq #%d pic_l2_io_q[%d]=%d\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_get_instance(axq->dip), iter, axq->pic_l2_io_q[iter]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_s1p_schizo_update(drmach_s1p_schizo_t *schizo, drmach_sr_iter_t iter)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_s1p_pci_t *pci;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (schizo->csr_basepa == 0x0UL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel schizo->regs[iter].csr =
03831d35f7499c87d51205817c93e9a8d42c4baestevel lddphysio(schizo->csr_basepa + SCHIZO_CB_CSR_OFFSET);
03831d35f7499c87d51205817c93e9a8d42c4baestevel schizo->regs[iter].errctrl =
03831d35f7499c87d51205817c93e9a8d42c4baestevel lddphysio(schizo->csr_basepa + SCHIZO_CB_ERRCTRL_OFFSET);
03831d35f7499c87d51205817c93e9a8d42c4baestevel schizo->regs[iter].errlog =
03831d35f7499c87d51205817c93e9a8d42c4baestevel lddphysio(schizo->csr_basepa + SCHIZO_CB_ERRLOG_OFFSET);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < DRMACH_SCHIZO_PCI_LEAF_MAX; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel pci = &schizo->pci[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (pci->dip != NULL && pci->csr_basepa != 0x0UL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel pci->regs[iter].slot_intr_state_diag =
03831d35f7499c87d51205817c93e9a8d42c4baestevel lddphysio(pci->csr_basepa +
03831d35f7499c87d51205817c93e9a8d42c4baestevel COMMON_IB_SLOT_INTR_STATE_DIAG_REG);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel pci->regs[iter].obio_intr_state_diag =
03831d35f7499c87d51205817c93e9a8d42c4baestevel lddphysio(pci->csr_basepa +
03831d35f7499c87d51205817c93e9a8d42c4baestevel COMMON_IB_OBIO_INTR_STATE_DIAG_REG);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_s1p_intr_map_reg_save(pci, iter);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Called post-suspend and pre-resume to snapshot the suspend state
03831d35f7499c87d51205817c93e9a8d42c4baestevel * of slot1 AXQs and Schizos.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_slot1_pause_update(drmach_slot1_pause_t **slot1_paused,
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_sr_iter_t iter)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i, j;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_slot1_pause_t *slot1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < STARCAT_BDSET_MAX; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((slot1 = slot1_paused[i]) == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_s1p_axq_update(&slot1->axq, iter);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (j = 0; j < STARCAT_SLOT1_IO_MAX; j++)
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_s1p_schizo_update(&slot1->schizo[j], iter);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Starcat hPCI Schizo devices.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The name field is overloaded. NULL means the slot (interrupt concentrator
03831d35f7499c87d51205817c93e9a8d42c4baestevel * bus) is not used. intr_mask is a bit mask representing the 4 possible
03831d35f7499c87d51205817c93e9a8d42c4baestevel * interrupts per slot, on if valid (rio does not use interrupt lines 0, 1).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct {
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *name;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint8_t intr_mask;
03831d35f7499c87d51205817c93e9a8d42c4baestevel} drmach_schz_slot_intr[][DRMACH_SCHIZO_PCI_LEAF_MAX] = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Schizo 0 */ /* Schizo 1 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel {{"C3V0", 0xf}, {"C3V1", 0xf}}, /* slot 0 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel {{"C5V0", 0xf}, {"C5V1", 0xf}}, /* slot 1 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel {{"rio", 0xc}, {NULL, 0x0}}, /* slot 2 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel {{NULL, 0x0}, {NULL, 0x0}}, /* slot 3 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel {{"sbbc", 0xf}, {NULL, 0x0}}, /* slot 4 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel {{NULL, 0x0}, {NULL, 0x0}}, /* slot 5 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel {{NULL, 0x0}, {NULL, 0x0}}, /* slot 6 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel {{NULL, 0x0}, {NULL, 0x0}} /* slot 7 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * See Schizo Specification, Revision 51 (May 23, 2001), Section 22.4.4
03831d35f7499c87d51205817c93e9a8d42c4baestevel * "Interrupt Registers", Table 22-69, page 306.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic char *
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_schz_internal_ino2str(int ino)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int intr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(ino >= 0x30 && ino <= 0x37);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel intr = ino & 0x7;
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (intr) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case (0x0): return ("Uncorrectable ECC error");
03831d35f7499c87d51205817c93e9a8d42c4baestevel case (0x1): return ("Correctable ECC error");
03831d35f7499c87d51205817c93e9a8d42c4baestevel case (0x2): return ("PCI Bus A Error");
03831d35f7499c87d51205817c93e9a8d42c4baestevel case (0x3): return ("PCI Bus B Error");
03831d35f7499c87d51205817c93e9a8d42c4baestevel case (0x4): return ("Safari Bus Error");
03831d35f7499c87d51205817c93e9a8d42c4baestevel default: return ("Reserved");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_INTR_MASK_SHIFT(ino) ((ino) << 1)
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_s1p_decode_slot_intr(int exp, int unum, drmach_s1p_pci_t *pci,
03831d35f7499c87d51205817c93e9a8d42c4baestevel int ino, drmach_sr_iter_t iter)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint8_t intr_mask;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *slot_devname;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char namebuf[OBP_MAXDRVNAME];
03831d35f7499c87d51205817c93e9a8d42c4baestevel int slot, intr_line, slot_valid, intr_valid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(ino >= 0 && ino <= 0x1f);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT((pci->regs[iter].slot_intr_state_diag &
03831d35f7499c87d51205817c93e9a8d42c4baestevel (COMMON_CLEAR_INTR_REG_MASK << DRMACH_INTR_MASK_SHIFT(ino))) !=
03831d35f7499c87d51205817c93e9a8d42c4baestevel COMMON_CLEAR_INTR_REG_IDLE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot = (ino >> 2) & 0x7;
03831d35f7499c87d51205817c93e9a8d42c4baestevel intr_line = ino & 0x3;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot_devname = drmach_schz_slot_intr[slot][unum].name;
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot_valid = (slot_devname == NULL) ? 0 : 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!slot_valid) {
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) snprintf(namebuf, sizeof (namebuf), "slot %d (INVALID)",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki slot);
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot_devname = namebuf;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel intr_mask = drmach_schz_slot_intr[slot][unum].intr_mask;
03831d35f7499c87d51205817c93e9a8d42c4baestevel intr_valid = (1 << intr_line) & intr_mask;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel prom_printf("IO%d/P%d PCI slot interrupt: ino=0x%x, source device=%s, "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "interrupt line=%d%s\n", exp, unum, ino, slot_devname, intr_line,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (slot_valid && !intr_valid) ? " (INVALID)" : "");
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Log interrupt source device info for all valid, pending interrupts
03831d35f7499c87d51205817c93e9a8d42c4baestevel * on each Schizo PCI leaf. Called if Schizo has logged a Safari bus
03831d35f7499c87d51205817c93e9a8d42c4baestevel * error in the error ctrl reg.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_s1p_schizo_log_intr(drmach_s1p_schizo_t *schizo, int exp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel int unum, drmach_sr_iter_t iter)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i, n, ino;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_s1p_pci_t *pci;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(exp >= 0 && exp < STARCAT_BDSET_MAX);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(unum < STARCAT_SLOT1_IO_MAX);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check the saved interrupt mapping registers. If interrupt is valid,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * map the ino to the Schizo source device and check that the pci
03831d35f7499c87d51205817c93e9a8d42c4baestevel * slot and interrupt line are valid.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < DRMACH_SCHIZO_PCI_LEAF_MAX; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel pci = &schizo->pci[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (n = 0; n < pci->regs[iter].nmap_regs; n++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = pci->regs[iter].intr_map_regs[n];
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (reg & COMMON_INTR_MAP_REG_VALID) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ino = reg & COMMON_INTR_MAP_REG_INO;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ino <= 0x1f) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * PCI slot interrupt
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_s1p_decode_slot_intr(exp, unum,
03831d35f7499c87d51205817c93e9a8d42c4baestevel pci, ino, iter);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (ino <= 0x2f) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * OBIO interrupt
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel prom_printf("IO%d/P%d OBIO interrupt: "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "ino=0x%x\n", exp, unum, ino);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (ino <= 0x37) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Internal interrupt
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel prom_printf("IO%d/P%d Internal "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "interrupt: ino=0x%x (%s)\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel exp, unum, ino,
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_schz_internal_ino2str(ino));
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * NewLink interrupt
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel prom_printf("IO%d/P%d NewLink "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "interrupt: ino=0x%x\n", exp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel unum, ino);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("drmach_s1p_schizo_log_intr: "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "exp=%d, schizo=%d, pci_leaf=%c, "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "ino=0x%x, intr_map_reg=0x%lx\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel exp, unum, (i == 0) ? 'A' : 'B', ino, reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * See Schizo Specification, Revision 51 (May 23, 2001), Section 22.2.4
03831d35f7499c87d51205817c93e9a8d42c4baestevel * "Safari Error Control/Log Registers", Table 22-11, page 248.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DRMACH_SCHIZO_SAFARI_UNMAPPED_ERR (0x1ull << 4)
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check for possible error indicators prior to resuming the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * AXQ driver, which will de-assert slot1 AXQ_DOMCTRL_PAUSE.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_slot1_pause_verify(drmach_slot1_pause_t **slot1_paused,
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_sr_iter_t iter)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i, j;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int errflag = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_slot1_pause_t *slot1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check for logged schizo bus error and pending interrupts.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < STARCAT_BDSET_MAX; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((slot1 = slot1_paused[i]) == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (j = 0; j < STARCAT_SLOT1_IO_MAX; j++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (slot1->schizo[j].csr_basepa == 0x0UL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (slot1->schizo[j].regs[iter].errlog &
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_SCHIZO_SAFARI_UNMAPPED_ERR) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!errflag) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel prom_printf("DR WARNING: interrupt "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "attempt detected during "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "copy-rename (%s):\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel (iter == DRMACH_POST_SUSPEND) ?
03831d35f7499c87d51205817c93e9a8d42c4baestevel "post suspend" : "pre resume");
03831d35f7499c87d51205817c93e9a8d42c4baestevel ++errflag;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_s1p_schizo_log_intr(&slot1->schizo[j],
03831d35f7499c87d51205817c93e9a8d42c4baestevel i, j, iter);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check for changes in axq l2_io_q performance counters (2nd pass only)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iter == DRMACH_PRE_RESUME) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < STARCAT_BDSET_MAX; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((slot1 = slot1_paused[i]) == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (slot1->axq.pic_l2_io_q[DRMACH_POST_SUSPEND] !=
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot1->axq.pic_l2_io_q[DRMACH_PRE_RESUME]) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel prom_printf("DR WARNING: IO transactions "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "detected on IO%d during copy-rename: "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "AXQ l2_io_q performance counter "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "start=%d, end=%d\n", i,
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot1->axq.pic_l2_io_q[DRMACH_POST_SUSPEND],
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot1->axq.pic_l2_io_q[DRMACH_PRE_RESUME]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstruct drmach_sr_list {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *dip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct drmach_sr_list *next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct drmach_sr_list *prev;
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct drmach_sr_ordered {
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *name;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct drmach_sr_list *ring;
03831d35f7499c87d51205817c93e9a8d42c4baestevel} drmach_sr_ordered[] = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel { "iosram", NULL },
03831d35f7499c87d51205817c93e9a8d42c4baestevel { "address-extender-queue", NULL },
03831d35f7499c87d51205817c93e9a8d42c4baestevel { NULL, NULL }, /* terminator -- required */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_sr_insert(struct drmach_sr_list **lp, dev_info_t *dip)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct drmach_sr_list *np;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DRMACH_PR("drmach_sr_insert: adding dip %p\n", (void *)dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel np = (struct drmach_sr_list *)kmem_alloc(
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni sizeof (struct drmach_sr_list), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_hold_devi(dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel np->dip = dip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (*lp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* establish list */
03831d35f7499c87d51205817c93e9a8d42c4baestevel *lp = np->next = np->prev = np;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* place new node behind head node on ring list */
03831d35f7499c87d51205817c93e9a8d42c4baestevel np->prev = (*lp)->prev;
03831d35f7499c87d51205817c93e9a8d42c4baestevel np->next = *lp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel np->prev->next = np;
03831d35f7499c87d51205817c93e9a8d42c4baestevel np->next->prev = np;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_sr_delete(struct drmach_sr_list **lp, dev_info_t *dip)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DRMACH_PR("drmach_sr_delete: searching for dip %p\n", (void *)dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (*lp) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct drmach_sr_list *xp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* start search with mostly likely node */
03831d35f7499c87d51205817c93e9a8d42c4baestevel xp = (*lp)->prev;
03831d35f7499c87d51205817c93e9a8d42c4baestevel do {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (xp->dip == dip) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel xp->prev->next = xp->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel xp->next->prev = xp->prev;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (xp == *lp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel *lp = xp->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (xp == *lp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel *lp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel xp->dip = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_rele_devi(dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(xp, sizeof (*xp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("drmach_sr_delete:"
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki " disposed sr node for dip %p",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void *)dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("drmach_sr_delete: still searching\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel xp = xp->prev;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } while (xp != (*lp)->prev);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* every dip should be found during resume */
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DRMACH_PR("ERROR: drmach_sr_delete: can't find dip %p", (void *)dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_verify_sr(dev_info_t *dip, int sflag)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char name[OBP_MAXDRVNAME];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_slot1_pause_debug) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sflag && drmach_slot1_pause_init) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_slot1_pause_free(drmach_slot1_paused);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_slot1_pause_init = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (!sflag && !drmach_slot1_pause_init) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* schedule init for next suspend */
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_slot1_pause_init = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = ddi_getproplen(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "name", &len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv == DDI_PROP_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int portid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct drmach_sr_ordered *op;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = ddi_getlongprop_buf(DDI_DEV_T_ANY, dip,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni DDI_PROP_DONTPASS, "name", (caddr_t)name, &len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv != DDI_PROP_SUCCESS)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_slot1_pause_debug && sflag &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_is_slot1_pause_axq(dip, name, &portid, &reg)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_slot1_pause_add_axq(dip, name, portid, reg,
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_slot1_paused);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (op = drmach_sr_ordered; op->name; op++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (strncmp(op->name, name, strlen(op->name)) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sflag)
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_sr_insert(&op->ring, dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_sr_delete(&op->ring, dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_sr_dip(dev_info_t *dip, int suspend)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv;
03831d35f7499c87d51205817c93e9a8d42c4baestevel major_t maj;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *name, *name_addr, *aka;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((name = ddi_get_name(dip)) == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel name = "<null name>";
03831d35f7499c87d51205817c93e9a8d42c4baestevel else if ((maj = ddi_name_to_major(name)) != -1)
03831d35f7499c87d51205817c93e9a8d42c4baestevel aka = ddi_major_to_name(maj);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel aka = "<unknown>";
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((name_addr = ddi_get_name_addr(dip)) == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel name_addr = "<null>";
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel prom_printf("\t%s %s@%s (aka %s)\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni suspend ? "suspending" : "resuming",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni name, name_addr, aka);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (suspend) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = devi_detach(dip, DDI_SUSPEND);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = devi_attach(dip, DDI_RESUME);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel prom_printf("\tFAILED to %s %s@%s\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni suspend ? "suspend" : "resume",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni name, name_addr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_suspend_last()
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct drmach_sr_ordered *op;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_slot1_pause_debug)
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_slot1_pause_add_io(drmach_slot1_paused);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The ordering array declares the strict sequence in which
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the named drivers are to suspended. Each element in
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the array may have a double-linked ring list of driver
03831d35f7499c87d51205817c93e9a8d42c4baestevel * instances (dip) in the order in which they were presented
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to drmach_verify_sr. If present, walk the list in the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * forward direction to suspend each instance.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (op = drmach_sr_ordered; op->name; op++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (op->ring) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct drmach_sr_list *rp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rp = op->ring;
03831d35f7499c87d51205817c93e9a8d42c4baestevel do {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_sr_dip(rp->dip, 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel rp = rp->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } while (rp != op->ring);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_slot1_pause_debug) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_slot1_pause_update(drmach_slot1_paused,
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_POST_SUSPEND);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_slot1_pause_verify(drmach_slot1_paused,
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_POST_SUSPEND);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_resume_first()
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct drmach_sr_ordered *op = drmach_sr_ordered +
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (sizeof (drmach_sr_ordered) / sizeof (drmach_sr_ordered[0]));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_slot1_pause_debug) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_slot1_pause_update(drmach_slot1_paused,
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PRE_RESUME);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_slot1_pause_verify(drmach_slot1_paused,
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PRE_RESUME);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel op -= 1; /* point at terminating element */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * walk ordering array and rings backwards to resume dips
03831d35f7499c87d51205817c93e9a8d42c4baestevel * in reverse order in which they were suspended
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (--op >= drmach_sr_ordered) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (op->ring) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct drmach_sr_list *rp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rp = op->ring->prev;
03831d35f7499c87d51205817c93e9a8d42c4baestevel do {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_sr_dip(rp->dip, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel rp = rp->prev;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } while (rp != op->ring->prev);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Log a DR sysevent.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Return value: 0 success, non-zero failure.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_log_sysevent(int board, char *hint, int flag, int verbose)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel sysevent_t *ev;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sysevent_id_t eid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv, km_flag;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sysevent_value_t evnt_val;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sysevent_attr_list_t *evnt_attr_list = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char attach_pnt[MAXNAMELEN];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel km_flag = (flag == SE_SLEEP) ? KM_SLEEP : KM_NOSLEEP;
03831d35f7499c87d51205817c93e9a8d42c4baestevel attach_pnt[0] = '\0';
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drmach_board_name(board, attach_pnt, MAXNAMELEN)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto logexit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (verbose)
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("drmach_log_sysevent: %s %s, flag: %d, verbose: %d\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni attach_pnt, hint, flag, verbose);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((ev = sysevent_alloc(EC_DR, ESC_DR_AP_STATE_CHANGE,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni SUNW_KERN_PUB"dr", km_flag)) == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = -2;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto logexit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel evnt_val.value_type = SE_DATA_TYPE_STRING;
03831d35f7499c87d51205817c93e9a8d42c4baestevel evnt_val.value.sv_string = attach_pnt;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((rv = sysevent_add_attr(&evnt_attr_list, DR_AP_ID,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni &evnt_val, km_flag)) != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto logexit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel evnt_val.value_type = SE_DATA_TYPE_STRING;
03831d35f7499c87d51205817c93e9a8d42c4baestevel evnt_val.value.sv_string = hint;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((rv = sysevent_add_attr(&evnt_attr_list, DR_HINT,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni &evnt_val, km_flag)) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sysevent_free_attr(evnt_attr_list);
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto logexit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) sysevent_attach_attributes(ev, evnt_attr_list);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Log the event but do not sleep waiting for its
03831d35f7499c87d51205817c93e9a8d42c4baestevel * delivery. This provides insulation from syseventd.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = log_sysevent(ev, SE_NOSLEEP, &eid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevellogexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ev)
03831d35f7499c87d51205817c93e9a8d42c4baestevel sysevent_free(ev);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((rv != 0) && verbose)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "drmach_log_sysevent failed (rv %d) for %s %s\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni rv, attach_pnt, hint);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (rv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Initialize the mem_slice portion of a claim/unconfig/unclaim mailbox message.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Only the valid entries are modified, so the array should be zeroed out
03831d35f7499c87d51205817c93e9a8d42c4baestevel * initially.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_msg_memslice_init(dr_memslice_t slice_arr[]) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char c;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mutex_owned(&drmach_slice_table_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < AXQ_MAX_EXP; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel c = drmach_slice_table[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (c & 0x20) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel slice_arr[i].valid = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel slice_arr[i].slice = c & 0x1f;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Initialize the mem_regs portion of a claim/unconfig/unclaim mailbox message.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Only the valid entries are modified, so the array should be zeroed out
03831d35f7499c87d51205817c93e9a8d42c4baestevel * initially.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_msg_memregs_init(dr_memregs_t regs_arr[]) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv, exp, mcnum, bank;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t madr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmachid_t id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_t *bp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mem_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dr_memregs_t *memregs;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* CONSTCOND */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(DRMACH_MC_NBANKS == (PMBANKS_PER_PORT * LMBANKS_PER_PMBANK));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (exp = 0; exp < 18; exp++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = drmach_array_get(drmach_boards,
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_EXPSLOT2BNUM(exp, 0), &id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(rv == 0); /* should never be out of bounds */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (id == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel memregs = &regs_arr[exp];
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp = (drmach_board_t *)id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (mp = bp->mem; mp != NULL; mp = mp->next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mcnum = mp->dev.portid & 0x3;
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (bank = 0; bank < DRMACH_MC_NBANKS; bank++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_mem_read_madr(mp, bank, &madr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (madr & DRMACH_MC_VALID_MASK) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_PR("%d.%d.%d.madr = 0x%lx\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni exp, mcnum, bank, madr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel memregs->madr[mcnum][bank].hi =
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_U64_TO_MCREGHI(madr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel memregs->madr[mcnum][bank].lo =
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_U64_TO_MCREGLO(madr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Do not allow physical address range modification if either board on this
03831d35f7499c87d51205817c93e9a8d42c4baestevel * expander has processors in NULL LPA mode (CBASE=CBND=NULL).
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * A side effect of NULL proc LPA mode in Starcat SSM is that local reads will
03831d35f7499c87d51205817c93e9a8d42c4baestevel * install the cache line as owned/dirty as a result of the RTSR transaction.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * See section 5.2.3 of the Safari spec. All processors will read the bus sync
03831d35f7499c87d51205817c93e9a8d42c4baestevel * list before the rename after flushing local caches. When copy-rename
03831d35f7499c87d51205817c93e9a8d42c4baestevel * requires changing the physical address ranges (i.e. smaller memory target),
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the bus sync list contains physical addresses that will not exist after the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * rename. If these cache lines are owned due to a RTSR, a system error can
03831d35f7499c87d51205817c93e9a8d42c4baestevel * occur following the rename when these cache lines are evicted and a writeback
03831d35f7499c87d51205817c93e9a8d42c4baestevel * is attempted.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Incoming parameter represents either the copy-rename source or a candidate
03831d35f7499c87d51205817c93e9a8d42c4baestevel * target memory board. On Starcat, only slot0 boards may have memory.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baesteveldrmach_allow_memrange_modify(drmachid_t s0id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmach_board_t *s0bp, *s1bp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmachid_t s1id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel s0bp = s0id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(DRMACH_IS_BOARD_ID(s0id));
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(DRMACH_BNUM2SLOT(s0bp->bnum) == 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (s0bp->flags & DRMACH_NULL_PROC_LPA) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This is reason enough to fail the request, no need
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to check the device list for cpus.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check for MCPU board on the same expander.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The board flag DRMACH_NULL_PROC_LPA can be set for all board
03831d35f7499c87d51205817c93e9a8d42c4baestevel * types, as it is derived at from the POST gdcd board flag
03831d35f7499c87d51205817c93e9a8d42c4baestevel * L1SSFLG_THIS_L1_NULL_PROC_LPA, which can be set (and should be
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ignored) for boards with no processors. Since NULL proc LPA
03831d35f7499c87d51205817c93e9a8d42c4baestevel * applies only to processors, we walk the devices array to detect
03831d35f7499c87d51205817c93e9a8d42c4baestevel * MCPUs.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = drmach_array_get(drmach_boards, s0bp->bnum + 1, &s1id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel s1bp = s1id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv == 0 && s1bp != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(DRMACH_IS_BOARD_ID(s1id));
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(DRMACH_BNUM2SLOT(s1bp->bnum) == 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(DRMACH_BNUM2EXP(s0bp->bnum) ==
03831d35f7499c87d51205817c93e9a8d42c4baestevel DRMACH_BNUM2EXP(s1bp->bnum));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((s1bp->flags & DRMACH_NULL_PROC_LPA) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel s1bp->devices != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int d_idx;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drmachid_t d_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = drmach_array_first(s1bp->devices, &d_idx, &d_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (rv == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (DRMACH_IS_CPU_ID(d_id)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Fail MCPU in NULL LPA mode.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = drmach_array_next(s1bp->devices, &d_idx,
03831d35f7499c87d51205817c93e9a8d42c4baestevel &d_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}