29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * CDDL HEADER START
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * The contents of this file are subject to the terms of the
29949e866e40b95795203f3ee46f44a197c946e4stevel * Common Development and Distribution License (the "License").
29949e866e40b95795203f3ee46f44a197c946e4stevel * You may not use this file except in compliance with the License.
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
29949e866e40b95795203f3ee46f44a197c946e4stevel * or http://www.opensolaris.org/os/licensing.
29949e866e40b95795203f3ee46f44a197c946e4stevel * See the License for the specific language governing permissions
29949e866e40b95795203f3ee46f44a197c946e4stevel * and limitations under the License.
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * When distributing Covered Code, include this CDDL HEADER in each
29949e866e40b95795203f3ee46f44a197c946e4stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
29949e866e40b95795203f3ee46f44a197c946e4stevel * If applicable, add the following below this CDDL HEADER, with the
29949e866e40b95795203f3ee46f44a197c946e4stevel * fields enclosed by brackets "[]" replaced with your own identifying
29949e866e40b95795203f3ee46f44a197c946e4stevel * information: Portions Copyright [yyyy] [name of copyright owner]
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * CDDL HEADER END
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
29949e866e40b95795203f3ee46f44a197c946e4stevel * Use is subject to license terms.
89b43686db1fe9681d80a7cf5662730cb9378caeBayard Bell * Copyright (c) 2011 Bayard G. Bell. All rights reserved.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/types.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/conf.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/ddi.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/sunddi.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/ddi_impldefs.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/obpdefs.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/cmn_err.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/errno.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/kmem.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/debug.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/sysmacros.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/machsystm.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <vm/hat_sfmmu.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/autoconf.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/open.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/stat.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/modctl.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/fhc.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/ac.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/cpu_module.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/x_call.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/fpu/fpusystm.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/lgrp.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/* Useful debugging Stuff */
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/nexusdebug.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Function prototypes
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int ac_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
29949e866e40b95795203f3ee46f44a197c946e4stevel void **result);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int ac_attach(dev_info_t *, ddi_attach_cmd_t);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int ac_detach(dev_info_t *, ddi_detach_cmd_t);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int ac_open(dev_t *, int, int, cred_t *);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int ac_close(dev_t, int, int, cred_t *);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int ac_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void ac_add_kstats(struct ac_soft_state *);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void ac_del_kstats(struct ac_soft_state *);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int ac_misc_kstat_update(kstat_t *, int);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void ac_add_picN_kstats(dev_info_t *dip);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int ac_counters_kstat_update(kstat_t *, int);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void ac_get_memory_status(struct ac_soft_state *, enum ac_bank_id);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void ac_eval_memory_status(struct ac_soft_state *, enum ac_bank_id);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void ac_ecache_flush(uint64_t, uint64_t);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int ac_pkt_init(ac_cfga_pkt_t *pkt, intptr_t arg, int flag);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int ac_pkt_fini(ac_cfga_pkt_t *pkt, intptr_t arg, int flag);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int ac_reset_timeout(int rw);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void ac_timeout(void *);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int ac_enter_transition(void);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void ac_exit_transition(void);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelint ac_add_memory(ac_cfga_pkt_t *);
29949e866e40b95795203f3ee46f44a197c946e4stevelint ac_del_memory(ac_cfga_pkt_t *);
29949e866e40b95795203f3ee46f44a197c946e4stevelint ac_mem_stat(ac_cfga_pkt_t *, int);
29949e866e40b95795203f3ee46f44a197c946e4stevelint ac_mem_test_start(ac_cfga_pkt_t *, int);
29949e866e40b95795203f3ee46f44a197c946e4stevelint ac_mem_test_stop(ac_cfga_pkt_t *, int);
29949e866e40b95795203f3ee46f44a197c946e4stevelint ac_mem_test_read(ac_cfga_pkt_t *, int);
29949e866e40b95795203f3ee46f44a197c946e4stevelint ac_mem_test_write(ac_cfga_pkt_t *, int);
29949e866e40b95795203f3ee46f44a197c946e4stevelvoid ac_mem_test_stop_on_close(uint_t, uint_t);
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * ac audit message events
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4steveltypedef enum {
29949e866e40b95795203f3ee46f44a197c946e4stevel AC_AUDIT_OSTATE_CONFIGURE,
29949e866e40b95795203f3ee46f44a197c946e4stevel AC_AUDIT_OSTATE_UNCONFIGURE,
29949e866e40b95795203f3ee46f44a197c946e4stevel AC_AUDIT_OSTATE_SUCCEEDED,
29949e866e40b95795203f3ee46f44a197c946e4stevel AC_AUDIT_OSTATE_CONFIGURE_FAILED,
29949e866e40b95795203f3ee46f44a197c946e4stevel AC_AUDIT_OSTATE_UNCONFIGURE_FAILED
29949e866e40b95795203f3ee46f44a197c946e4stevel} ac_audit_evt_t;
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void ac_policy_audit_messages(ac_audit_evt_t event, ac_cfga_pkt_t *pkt);
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic char *ac_ostate_typestr(sysc_cfga_ostate_t ostate, ac_audit_evt_t event);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/* The memory ioctl interface version of this driver. */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic ac_mem_version_t ac_mem_version = AC_MEM_ADMIN_VERSION;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int ac_mem_exercise(ac_cfga_pkt_t *, int);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Configuration data structures
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic struct cb_ops ac_cb_ops = {
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_open, /* open */
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_close, /* close */
29949e866e40b95795203f3ee46f44a197c946e4stevel nulldev, /* strategy */
29949e866e40b95795203f3ee46f44a197c946e4stevel nulldev, /* print */
29949e866e40b95795203f3ee46f44a197c946e4stevel nodev, /* dump */
29949e866e40b95795203f3ee46f44a197c946e4stevel nulldev, /* read */
29949e866e40b95795203f3ee46f44a197c946e4stevel nulldev, /* write */
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_ioctl, /* ioctl */
29949e866e40b95795203f3ee46f44a197c946e4stevel nodev, /* devmap */
29949e866e40b95795203f3ee46f44a197c946e4stevel nodev, /* mmap */
29949e866e40b95795203f3ee46f44a197c946e4stevel nodev, /* segmap */
29949e866e40b95795203f3ee46f44a197c946e4stevel nochpoll, /* poll */
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_prop_op, /* cb_prop_op */
29949e866e40b95795203f3ee46f44a197c946e4stevel 0, /* streamtab */
29949e866e40b95795203f3ee46f44a197c946e4stevel D_MP | D_NEW | D_HOTPLUG, /* Driver compatibility flag */
29949e866e40b95795203f3ee46f44a197c946e4stevel CB_REV, /* rev */
29949e866e40b95795203f3ee46f44a197c946e4stevel nodev, /* cb_aread */
29949e866e40b95795203f3ee46f44a197c946e4stevel nodev /* cb_awrite */
29949e866e40b95795203f3ee46f44a197c946e4stevel};
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic struct dev_ops ac_ops = {
29949e866e40b95795203f3ee46f44a197c946e4stevel DEVO_REV, /* devo_rev, */
29949e866e40b95795203f3ee46f44a197c946e4stevel 0, /* refcnt */
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_info, /* getinfo */
29949e866e40b95795203f3ee46f44a197c946e4stevel nulldev, /* identify */
29949e866e40b95795203f3ee46f44a197c946e4stevel nulldev, /* probe */
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_attach, /* attach */
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_detach, /* detach */
29949e866e40b95795203f3ee46f44a197c946e4stevel nulldev, /* reset */
29949e866e40b95795203f3ee46f44a197c946e4stevel &ac_cb_ops, /* cb_ops */
29949e866e40b95795203f3ee46f44a197c946e4stevel (struct bus_ops *)0, /* bus_ops */
193974072f41a843678abf5f61979c748687e66bSherry Moore nulldev, /* power */
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_quiesce_not_needed, /* quiesce */
29949e866e40b95795203f3ee46f44a197c946e4stevel};
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Driver globals
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelvoid *acp; /* ac soft state hook */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic kstat_t *ac_picN_ksp[AC_NUM_PICS]; /* performance picN kstats */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int ac_attachcnt = 0; /* number of instances attached */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic kmutex_t ac_attachcnt_mutex; /* ac_attachcnt lock - attach/detach */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic kmutex_t ac_hot_plug_mode_mutex;
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic timeout_id_t ac_hot_plug_timeout;
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int ac_hot_plug_timeout_interval = 10;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel#define AC_GETSOFTC(I) \
29949e866e40b95795203f3ee46f44a197c946e4stevel ((struct ac_soft_state *)ddi_get_soft_state(acp, (I)))
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelextern struct mod_ops mod_driverops;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic struct modldrv modldrv = {
29949e866e40b95795203f3ee46f44a197c946e4stevel &mod_driverops, /* Type of module. This one is a driver */
193974072f41a843678abf5f61979c748687e66bSherry Moore "AC Leaf", /* name of module */
29949e866e40b95795203f3ee46f44a197c946e4stevel &ac_ops, /* driver ops */
29949e866e40b95795203f3ee46f44a197c946e4stevel};
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic struct modlinkage modlinkage = {
29949e866e40b95795203f3ee46f44a197c946e4stevel MODREV_1,
29949e866e40b95795203f3ee46f44a197c946e4stevel (void *)&modldrv,
29949e866e40b95795203f3ee46f44a197c946e4stevel NULL
29949e866e40b95795203f3ee46f44a197c946e4stevel};
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * These are the module initialization routines.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelint
29949e866e40b95795203f3ee46f44a197c946e4stevel_init(void)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel int error;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((error = ddi_soft_state_init(&acp, sizeof (struct ac_soft_state),
29949e866e40b95795203f3ee46f44a197c946e4stevel 1)) != 0)
29949e866e40b95795203f3ee46f44a197c946e4stevel return (error);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((error = mod_install(&modlinkage)) != 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_soft_state_fini(&acp);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (error);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Initialize global mutex */
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_init(&ac_attachcnt_mutex, NULL, MUTEX_DRIVER, NULL);
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_init(&ac_hot_plug_mode_mutex, NULL, MUTEX_DRIVER, NULL);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (0);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelint
29949e866e40b95795203f3ee46f44a197c946e4stevel_fini(void)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel int error;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((error = mod_remove(&modlinkage)) == 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_soft_state_fini(&acp);
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_destroy(&ac_attachcnt_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_destroy(&ac_hot_plug_mode_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel return (error);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelint
29949e866e40b95795203f3ee46f44a197c946e4stevel_info(struct modinfo *modinfop)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel return (mod_info(&modlinkage, modinfop));
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/* ARGSUSED */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int
29949e866e40b95795203f3ee46f44a197c946e4stevelac_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel dev_t dev;
29949e866e40b95795203f3ee46f44a197c946e4stevel int instance;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (infocmd == DDI_INFO_DEVT2INSTANCE) {
29949e866e40b95795203f3ee46f44a197c946e4stevel dev = (dev_t)arg;
29949e866e40b95795203f3ee46f44a197c946e4stevel instance = AC_GETINSTANCE(getminor(dev));
29949e866e40b95795203f3ee46f44a197c946e4stevel *result = (void *)(uintptr_t)instance;
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_SUCCESS);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_FAILURE);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int
29949e866e40b95795203f3ee46f44a197c946e4stevelac_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel int instance;
29949e866e40b95795203f3ee46f44a197c946e4stevel struct ac_soft_state *softsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel struct bd_list *list = NULL;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel switch (cmd) {
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_ATTACH:
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_RESUME:
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_SUCCESS);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel default:
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_FAILURE);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel instance = ddi_get_instance(devi);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ddi_soft_state_zalloc(acp, instance) != DDI_SUCCESS) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "ddi_soft_state_zalloc failed for ac%d",
193974072f41a843678abf5f61979c748687e66bSherry Moore instance);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_FAILURE);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp = ddi_get_soft_state(acp, instance);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Set the dip in the soft state */
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->dip = devi;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Get the board number from this nodes parent */
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->pdip = ddi_get_parent(softsp->dip);
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((softsp->board = (int)ddi_getprop(DDI_DEV_T_ANY, softsp->pdip,
29949e866e40b95795203f3ee46f44a197c946e4stevel DDI_PROP_DONTPASS, OBP_BOARDNUM, -1)) == -1) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "ac%d: unable to retrieve %s property",
193974072f41a843678abf5f61979c748687e66bSherry Moore instance, OBP_BOARDNUM);
29949e866e40b95795203f3ee46f44a197c946e4stevel goto bad;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel DPRINTF(AC_ATTACH_DEBUG, ("ac%d: devi= 0x%p\n,"
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki " softsp=0x%p\n", instance, (void *)devi, (void *)softsp));
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* map in the registers for this device. */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ddi_map_regs(softsp->dip, 0, (caddr_t *)&softsp->ac_base, 0, 0)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "ac%d: unable to map registers", instance);
29949e866e40b95795203f3ee46f44a197c946e4stevel goto bad;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Setup the pointers to the hardware registers */
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->ac_id = (uint32_t *)softsp->ac_base;
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->ac_memctl = (uint64_t *)((char *)softsp->ac_base +
193974072f41a843678abf5f61979c748687e66bSherry Moore AC_OFF_MEMCTL);
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->ac_memdecode0 = (uint64_t *)((char *)softsp->ac_base +
193974072f41a843678abf5f61979c748687e66bSherry Moore AC_OFF_MEMDEC0);
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->ac_memdecode1 = (uint64_t *)((char *)softsp->ac_base +
193974072f41a843678abf5f61979c748687e66bSherry Moore AC_OFF_MEMDEC1);
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->ac_counter = (uint64_t *)((char *)softsp->ac_base +
193974072f41a843678abf5f61979c748687e66bSherry Moore AC_OFF_CNTR);
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->ac_mccr = (uint32_t *)((char *)softsp->ac_base +
193974072f41a843678abf5f61979c748687e66bSherry Moore AC_OFF_MCCR);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* nothing to suspend/resume here */
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) ddi_prop_update_string(DDI_DEV_T_NONE, devi,
193974072f41a843678abf5f61979c748687e66bSherry Moore "pm-hardware-state", "no-suspend-resume");
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* setup the the AC counter registers to allow for hotplug. */
29949e866e40b95795203f3ee46f44a197c946e4stevel list = fhc_bdlist_lock(softsp->board);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (list == NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_PANIC, "ac%d: Board %d not found in database",
193974072f41a843678abf5f61979c748687e66bSherry Moore instance, softsp->board);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* set the AC rev into the bd list structure */
29949e866e40b95795203f3ee46f44a197c946e4stevel list->sc.ac_compid = *softsp->ac_id;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel list->ac_softsp = softsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (list->sc.type == CPU_BOARD || list->sc.type == MEM_BOARD) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Create the minor nodes */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ddi_create_minor_node(devi, NAME_BANK0, S_IFCHR,
29949e866e40b95795203f3ee46f44a197c946e4stevel (AC_PUTINSTANCE(instance) | 0),
29949e866e40b95795203f3ee46f44a197c946e4stevel DDI_NT_ATTACHMENT_POINT, 0) == DDI_FAILURE) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "ac%d: \"%s\" "
29949e866e40b95795203f3ee46f44a197c946e4stevel "ddi_create_minor_node failed", instance,
29949e866e40b95795203f3ee46f44a197c946e4stevel NAME_BANK0);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ddi_create_minor_node(devi, NAME_BANK1, S_IFCHR,
29949e866e40b95795203f3ee46f44a197c946e4stevel (AC_PUTINSTANCE(instance) | 1),
29949e866e40b95795203f3ee46f44a197c946e4stevel DDI_NT_ATTACHMENT_POINT, 0) == DDI_FAILURE) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "ac%d: \"%s\" "
29949e866e40b95795203f3ee46f44a197c946e4stevel "ddi_create_minor_node failed", instance,
29949e866e40b95795203f3ee46f44a197c946e4stevel NAME_BANK0);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* purge previous fhc pa database entries */
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_del_memloc(softsp->board);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Inherit Memory Bank Status */
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_get_memory_status(softsp, Bank0);
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_get_memory_status(softsp, Bank1);
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Final Memory Bank Status evaluation and messaging */
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_eval_memory_status(softsp, Bank0);
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_eval_memory_status(softsp, Bank1);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bdlist_unlock();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* create the kstats for this device. */
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_add_kstats(softsp);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_report_dev(devi);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_SUCCESS);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelbad:
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_soft_state_free(acp, instance);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_FAILURE);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/* ARGSUSED */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int
29949e866e40b95795203f3ee46f44a197c946e4stevelac_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel int instance;
29949e866e40b95795203f3ee46f44a197c946e4stevel struct ac_soft_state *softsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel struct bd_list *list;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* get the instance of this devi */
29949e866e40b95795203f3ee46f44a197c946e4stevel instance = ddi_get_instance(devi);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* get the soft state pointer for this device node */
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp = ddi_get_soft_state(acp, instance);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel switch (cmd) {
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_SUSPEND:
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_SUCCESS);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_DETACH:
29949e866e40b95795203f3ee46f44a197c946e4stevel list = fhc_bdlist_lock(softsp->board);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (fhc_bd_detachable(softsp->board))
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel else
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bdlist_unlock();
29949e866e40b95795203f3ee46f44a197c946e4stevel /* FALLTHROUGH */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel default:
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_FAILURE);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(list->ac_softsp == softsp);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (list->sc.type == CPU_BOARD || list->sc.type == MEM_BOARD) {
29949e866e40b95795203f3ee46f44a197c946e4stevel int cpui;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Test to see if memory is in use on a CPU/MEM board.
29949e866e40b95795203f3ee46f44a197c946e4stevel * In the case of a DR operation this condition
29949e866e40b95795203f3ee46f44a197c946e4stevel * will have been assured when the board was unconfigured.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (softsp->bank[Bank0].busy != 0 ||
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[Bank0].ostate == SYSC_CFGA_OSTATE_CONFIGURED ||
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[Bank1].busy != 0 ||
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[Bank1].ostate == SYSC_CFGA_OSTATE_CONFIGURED) {
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bdlist_unlock();
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_FAILURE);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * CPU busy test is done by the DR sequencer before
29949e866e40b95795203f3ee46f44a197c946e4stevel * device detach called.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Flush all E-caches to remove references to this
29949e866e40b95795203f3ee46f44a197c946e4stevel * board's memory.
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * Do this one CPU at a time to avoid stalls and timeouts
29949e866e40b95795203f3ee46f44a197c946e4stevel * due to all CPUs flushing concurrently.
29949e866e40b95795203f3ee46f44a197c946e4stevel * xc_one returns silently for non-existant CPUs.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (cpui = 0; cpui < NCPU; cpui++)
29949e866e40b95795203f3ee46f44a197c946e4stevel xc_one(cpui, ac_ecache_flush, 0, 0);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel list->ac_softsp = NULL;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* delete the kstat for this driver. */
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_del_kstats(softsp);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* unmap the registers */
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_unmap_regs(softsp->dip, 0, (caddr_t *)&softsp->ac_base, 0, 0);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bdlist_unlock();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Remove the minor nodes. */
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_remove_minor_node(devi, NULL);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* free the soft state structure */
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_soft_state_free(acp, instance);
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_prop_remove_all(devi);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_SUCCESS);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/* ARGSUSED */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int
29949e866e40b95795203f3ee46f44a197c946e4stevelac_open(dev_t *devp, int flag, int otyp, cred_t *credp)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel int instance;
29949e866e40b95795203f3ee46f44a197c946e4stevel dev_t dev;
29949e866e40b95795203f3ee46f44a197c946e4stevel struct ac_soft_state *softsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel struct bd_list *board;
29949e866e40b95795203f3ee46f44a197c946e4stevel int vis;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel dev = *devp;
29949e866e40b95795203f3ee46f44a197c946e4stevel instance = AC_GETINSTANCE(getminor(dev));
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp = AC_GETSOFTC(instance);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Is the instance attached? */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (softsp == NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef DEBUG
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "ac%d device not attached", instance);
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif /* DEBUG */
29949e866e40b95795203f3ee46f44a197c946e4stevel return (ENXIO);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * If the board is not configured, hide the memory APs
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel board = fhc_bdlist_lock(softsp->board);
29949e866e40b95795203f3ee46f44a197c946e4stevel vis = (board != NULL) && MEM_BOARD_VISIBLE(board);
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bdlist_unlock();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (!vis)
29949e866e40b95795203f3ee46f44a197c946e4stevel return (ENXIO);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* verify that otyp is appropriate */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (otyp != OTYP_CHR) {
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EINVAL);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_SUCCESS);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/* ARGSUSED */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int
29949e866e40b95795203f3ee46f44a197c946e4stevelac_close(dev_t devt, int flag, int otyp, cred_t *credp)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct ac_soft_state *softsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel int instance;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel instance = AC_GETINSTANCE(getminor(devt));
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp = AC_GETSOFTC(instance);
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(softsp != NULL);
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_mem_test_stop_on_close(softsp->board, AC_GETBANK(getminor(devt)));
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_SUCCESS);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int
29949e866e40b95795203f3ee46f44a197c946e4stevelac_pkt_init(ac_cfga_pkt_t *pkt, intptr_t arg, int flag)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef _MULTI_DATAMODEL
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ddi_model_convert_from(flag & FMODELS) == DDI_MODEL_ILP32) {
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_cfga_cmd32_t ac_cmd32;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ddi_copyin((void *)arg, &ac_cmd32,
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (ac_cfga_cmd32_t), flag) != 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EFAULT);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel pkt->cmd_cfga.force = ac_cmd32.force;
29949e866e40b95795203f3ee46f44a197c946e4stevel pkt->cmd_cfga.test = ac_cmd32.test;
29949e866e40b95795203f3ee46f44a197c946e4stevel pkt->cmd_cfga.arg = ac_cmd32.arg;
29949e866e40b95795203f3ee46f44a197c946e4stevel pkt->cmd_cfga.errtype = ac_cmd32.errtype;
29949e866e40b95795203f3ee46f44a197c946e4stevel pkt->cmd_cfga.outputstr =
193974072f41a843678abf5f61979c748687e66bSherry Moore (char *)(uintptr_t)ac_cmd32.outputstr;
29949e866e40b95795203f3ee46f44a197c946e4stevel pkt->cmd_cfga.private =
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)(uintptr_t)ac_cmd32.private;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif /* _MULTI_DATAMODEL */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ddi_copyin((void *)arg, &(pkt->cmd_cfga),
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (ac_cfga_cmd_t), flag) != 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EFAULT);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel pkt->errbuf = kmem_zalloc(SYSC_OUTPUT_LEN, KM_SLEEP);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (0);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int
29949e866e40b95795203f3ee46f44a197c946e4stevelac_pkt_fini(ac_cfga_pkt_t *pkt, intptr_t arg, int flag)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel int ret = TRUE;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef _MULTI_DATAMODEL
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ddi_model_convert_from(flag & FMODELS) == DDI_MODEL_ILP32) {
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ddi_copyout(&(pkt->cmd_cfga.errtype),
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)&(((ac_cfga_cmd32_t *)arg)->errtype),
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (ac_err_t), flag) != 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel ret = FALSE;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel } else
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ddi_copyout(&(pkt->cmd_cfga.errtype),
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)&(((ac_cfga_cmd_t *)arg)->errtype),
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (ac_err_t), flag) != 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel ret = FALSE;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((ret != FALSE) && ((pkt->cmd_cfga.outputstr != NULL) &&
193974072f41a843678abf5f61979c748687e66bSherry Moore (ddi_copyout(pkt->errbuf, pkt->cmd_cfga.outputstr,
193974072f41a843678abf5f61979c748687e66bSherry Moore SYSC_OUTPUT_LEN, flag) != 0))) {
29949e866e40b95795203f3ee46f44a197c946e4stevel ret = FALSE;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel kmem_free(pkt->errbuf, SYSC_OUTPUT_LEN);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (ret);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/* ARGSUSED */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int
29949e866e40b95795203f3ee46f44a197c946e4stevelac_ioctl(
29949e866e40b95795203f3ee46f44a197c946e4stevel dev_t devt,
29949e866e40b95795203f3ee46f44a197c946e4stevel int cmd,
29949e866e40b95795203f3ee46f44a197c946e4stevel intptr_t arg,
29949e866e40b95795203f3ee46f44a197c946e4stevel int flag,
29949e866e40b95795203f3ee46f44a197c946e4stevel cred_t *cred_p,
29949e866e40b95795203f3ee46f44a197c946e4stevel int *rval_p)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct ac_soft_state *softsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_cfga_pkt_t cfga_pkt, *pkt;
29949e866e40b95795203f3ee46f44a197c946e4stevel int instance;
29949e866e40b95795203f3ee46f44a197c946e4stevel int retval;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel instance = AC_GETINSTANCE(getminor(devt));
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp = AC_GETSOFTC(instance);
29949e866e40b95795203f3ee46f44a197c946e4stevel if (softsp == NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef DEBUG
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_NOTE, "ac%d device not attached", instance);
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif /* DEBUG */
29949e866e40b95795203f3ee46f44a197c946e4stevel return (ENXIO);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Dispose of the easy ones first.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel switch (cmd) {
29949e866e40b95795203f3ee46f44a197c946e4stevel case AC_MEM_ADMIN_VER:
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Specify the revision of this ioctl interface driver.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ddi_copyout(&ac_mem_version, (void *)arg,
29949e866e40b95795203f3ee46f44a197c946e4stevel sizeof (ac_mem_version_t), flag) != 0)
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EFAULT);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_SUCCESS);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel case AC_MEM_CONFIGURE:
29949e866e40b95795203f3ee46f44a197c946e4stevel case AC_MEM_UNCONFIGURE:
29949e866e40b95795203f3ee46f44a197c946e4stevel case AC_MEM_STAT:
29949e866e40b95795203f3ee46f44a197c946e4stevel case AC_MEM_TEST_START:
29949e866e40b95795203f3ee46f44a197c946e4stevel case AC_MEM_TEST_STOP:
29949e866e40b95795203f3ee46f44a197c946e4stevel case AC_MEM_TEST_READ:
29949e866e40b95795203f3ee46f44a197c946e4stevel case AC_MEM_TEST_WRITE:
29949e866e40b95795203f3ee46f44a197c946e4stevel case AC_MEM_EXERCISE:
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel default:
29949e866e40b95795203f3ee46f44a197c946e4stevel return (ENOTTY);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel if (cmd != AC_MEM_STAT && !fpu_exists) {
29949e866e40b95795203f3ee46f44a197c946e4stevel return (ENOTSUP);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel pkt = &cfga_pkt;
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((retval = ac_pkt_init(pkt, arg, flag)) != 0)
29949e866e40b95795203f3ee46f44a197c946e4stevel return (retval);
29949e866e40b95795203f3ee46f44a197c946e4stevel pkt->softsp = softsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel pkt->bank = AC_GETBANK(getminor(devt));
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel switch (cmd) {
29949e866e40b95795203f3ee46f44a197c946e4stevel case AC_MEM_CONFIGURE:
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((flag & FWRITE) == 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel retval = EBADF;
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (pkt->cmd_cfga.private != NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel retval = EINVAL;
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_policy_audit_messages(AC_AUDIT_OSTATE_CONFIGURE, pkt);
29949e866e40b95795203f3ee46f44a197c946e4stevel retval = ac_add_memory(pkt);
29949e866e40b95795203f3ee46f44a197c946e4stevel if (!retval)
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_policy_audit_messages(
193974072f41a843678abf5f61979c748687e66bSherry Moore AC_AUDIT_OSTATE_SUCCEEDED, pkt);
29949e866e40b95795203f3ee46f44a197c946e4stevel else
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_policy_audit_messages(
193974072f41a843678abf5f61979c748687e66bSherry Moore AC_AUDIT_OSTATE_CONFIGURE_FAILED, pkt);
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel case AC_MEM_UNCONFIGURE:
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((flag & FWRITE) == 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel retval = EBADF;
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (pkt->cmd_cfga.private != NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel retval = EINVAL;
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_policy_audit_messages(AC_AUDIT_OSTATE_UNCONFIGURE, pkt);
29949e866e40b95795203f3ee46f44a197c946e4stevel retval = ac_del_memory(pkt);
29949e866e40b95795203f3ee46f44a197c946e4stevel if (!retval) {
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_policy_audit_messages(
193974072f41a843678abf5f61979c748687e66bSherry Moore AC_AUDIT_OSTATE_SUCCEEDED, pkt);
29949e866e40b95795203f3ee46f44a197c946e4stevel } else
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_policy_audit_messages(
193974072f41a843678abf5f61979c748687e66bSherry Moore AC_AUDIT_OSTATE_UNCONFIGURE_FAILED, pkt);
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel case AC_MEM_STAT:
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Query usage of a bank of memory.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel retval = ac_mem_stat(pkt, flag);
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel case AC_MEM_TEST_START:
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((flag & FWRITE) == 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel retval = EBADF;
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel retval = ac_mem_test_start(pkt, flag);
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel case AC_MEM_TEST_STOP:
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((flag & FWRITE) == 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel retval = EBADF;
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel retval = ac_mem_test_stop(pkt, flag);
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel case AC_MEM_TEST_READ:
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * read a 'page' (or less) of memory safely.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((flag & FWRITE) == 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel retval = EBADF;
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel retval = ac_mem_test_read(pkt, flag);
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel case AC_MEM_TEST_WRITE:
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * write a 'page' (or less) of memory safely.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((flag & FWRITE) == 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel retval = EBADF;
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel retval = ac_mem_test_write(pkt, flag);
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel case AC_MEM_EXERCISE:
29949e866e40b95795203f3ee46f44a197c946e4stevel retval = ac_mem_exercise(pkt, flag);
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel default:
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(0);
29949e866e40b95795203f3ee46f44a197c946e4stevel retval = ENOTTY;
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ac_pkt_fini(pkt, arg, flag) != TRUE)
29949e866e40b95795203f3ee46f44a197c946e4stevel retval = EFAULT;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel return (retval);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void
29949e866e40b95795203f3ee46f44a197c946e4stevelac_add_kstats(struct ac_soft_state *softsp)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct kstat *ac_ksp, *ac_counters_ksp;
29949e866e40b95795203f3ee46f44a197c946e4stevel struct ac_kstat *ac_named_ksp;
29949e866e40b95795203f3ee46f44a197c946e4stevel struct kstat_named *ac_counters_named_data;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * create the unix-misc kstat for address controller
29949e866e40b95795203f3ee46f44a197c946e4stevel * using the board number as the instance.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((ac_ksp = kstat_create("unix", softsp->board,
29949e866e40b95795203f3ee46f44a197c946e4stevel AC_KSTAT_NAME, "misc", KSTAT_TYPE_NAMED,
29949e866e40b95795203f3ee46f44a197c946e4stevel sizeof (struct ac_kstat) / sizeof (kstat_named_t),
29949e866e40b95795203f3ee46f44a197c946e4stevel KSTAT_FLAG_PERSISTENT)) == NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "ac%d: kstat_create failed",
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_get_instance(softsp->dip));
29949e866e40b95795203f3ee46f44a197c946e4stevel return;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_named_ksp = (struct ac_kstat *)(ac_ksp->ks_data);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* initialize the named kstats */
29949e866e40b95795203f3ee46f44a197c946e4stevel kstat_named_init(&ac_named_ksp->ac_memctl,
193974072f41a843678abf5f61979c748687e66bSherry Moore MEMCTL_KSTAT_NAMED,
193974072f41a843678abf5f61979c748687e66bSherry Moore KSTAT_DATA_UINT64);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel kstat_named_init(&ac_named_ksp->ac_memdecode0,
193974072f41a843678abf5f61979c748687e66bSherry Moore MEMDECODE0_KSTAT_NAMED,
193974072f41a843678abf5f61979c748687e66bSherry Moore KSTAT_DATA_UINT64);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel kstat_named_init(&ac_named_ksp->ac_memdecode1,
193974072f41a843678abf5f61979c748687e66bSherry Moore MEMDECODE1_KSTAT_NAMED,
193974072f41a843678abf5f61979c748687e66bSherry Moore KSTAT_DATA_UINT64);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel kstat_named_init(&ac_named_ksp->ac_mccr,
193974072f41a843678abf5f61979c748687e66bSherry Moore MCCR_KSTAT_NAMED,
193974072f41a843678abf5f61979c748687e66bSherry Moore KSTAT_DATA_UINT32);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel kstat_named_init(&ac_named_ksp->ac_counter,
193974072f41a843678abf5f61979c748687e66bSherry Moore CNTR_KSTAT_NAMED,
193974072f41a843678abf5f61979c748687e66bSherry Moore KSTAT_DATA_UINT64);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel kstat_named_init(&ac_named_ksp->ac_bank0_status,
193974072f41a843678abf5f61979c748687e66bSherry Moore BANK_0_KSTAT_NAMED,
193974072f41a843678abf5f61979c748687e66bSherry Moore KSTAT_DATA_CHAR);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel kstat_named_init(&ac_named_ksp->ac_bank1_status,
193974072f41a843678abf5f61979c748687e66bSherry Moore BANK_1_KSTAT_NAMED,
193974072f41a843678abf5f61979c748687e66bSherry Moore KSTAT_DATA_CHAR);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_ksp->ks_update = ac_misc_kstat_update;
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_ksp->ks_private = (void *)softsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->ac_ksp = ac_ksp;
29949e866e40b95795203f3ee46f44a197c946e4stevel kstat_install(ac_ksp);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Create the picN kstats if we are the first instance
29949e866e40b95795203f3ee46f44a197c946e4stevel * to attach. We use ac_attachcnt as a count of how
29949e866e40b95795203f3ee46f44a197c946e4stevel * many instances have attached. This is protected by
29949e866e40b95795203f3ee46f44a197c946e4stevel * a mutex.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_enter(&ac_attachcnt_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ac_attachcnt == 0)
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_add_picN_kstats(softsp->dip);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_attachcnt ++;
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&ac_attachcnt_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Create the "counter" kstat for each AC instance.
29949e866e40b95795203f3ee46f44a197c946e4stevel * This provides access to the %pcr and %pic
29949e866e40b95795203f3ee46f44a197c946e4stevel * registers for that instance.
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * The size of this kstat is AC_NUM_PICS + 1 for %pcr
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((ac_counters_ksp = kstat_create("ac",
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_get_instance(softsp->dip), "counters",
193974072f41a843678abf5f61979c748687e66bSherry Moore "bus", KSTAT_TYPE_NAMED, AC_NUM_PICS + 1,
193974072f41a843678abf5f61979c748687e66bSherry Moore KSTAT_FLAG_WRITABLE)) == NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "ac%d counters: kstat_create failed",
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_get_instance(softsp->dip));
29949e866e40b95795203f3ee46f44a197c946e4stevel return;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_counters_named_data =
193974072f41a843678abf5f61979c748687e66bSherry Moore (struct kstat_named *)(ac_counters_ksp->ks_data);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* initialize the named kstats */
29949e866e40b95795203f3ee46f44a197c946e4stevel kstat_named_init(&ac_counters_named_data[0],
193974072f41a843678abf5f61979c748687e66bSherry Moore "pcr", KSTAT_DATA_UINT64);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel kstat_named_init(&ac_counters_named_data[1],
193974072f41a843678abf5f61979c748687e66bSherry Moore "pic0", KSTAT_DATA_UINT64);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel kstat_named_init(&ac_counters_named_data[2],
193974072f41a843678abf5f61979c748687e66bSherry Moore "pic1", KSTAT_DATA_UINT64);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_counters_ksp->ks_update = ac_counters_kstat_update;
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_counters_ksp->ks_private = (void *)softsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel kstat_install(ac_counters_ksp);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* update the sofstate */
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->ac_counters_ksp = ac_counters_ksp;
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * called from ac_add_kstats() to create a kstat for each %pic
29949e866e40b95795203f3ee46f44a197c946e4stevel * that the AC supports. These (read-only) kstats export the
29949e866e40b95795203f3ee46f44a197c946e4stevel * event names and %pcr masks that each %pic supports.
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * if we fail to create any of these kstats we must remove any
29949e866e40b95795203f3ee46f44a197c946e4stevel * that we have already created and return;
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * NOTE: because all AC's use the same events we only need to
29949e866e40b95795203f3ee46f44a197c946e4stevel * create the picN kstats once. All instances can use
29949e866e40b95795203f3ee46f44a197c946e4stevel * the same picN kstats.
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * The flexibility exists to allow each device specify it's
29949e866e40b95795203f3ee46f44a197c946e4stevel * own events by creating picN kstats with the instance number
29949e866e40b95795203f3ee46f44a197c946e4stevel * set to ddi_get_instance(softsp->dip).
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * When searching for a picN kstat for a device you should
29949e866e40b95795203f3ee46f44a197c946e4stevel * first search for a picN kstat using the instance number
29949e866e40b95795203f3ee46f44a197c946e4stevel * of the device you are interested in. If that fails you
29949e866e40b95795203f3ee46f44a197c946e4stevel * should use the first picN kstat found for that device.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void
29949e866e40b95795203f3ee46f44a197c946e4stevelac_add_picN_kstats(dev_info_t *dip)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel typedef struct ac_event_mask {
29949e866e40b95795203f3ee46f44a197c946e4stevel char *event_name;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint64_t pcr_mask;
29949e866e40b95795203f3ee46f44a197c946e4stevel } ac_event_mask_t;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * AC Performance Events.
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * We declare an array of event-names and event-masks.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_event_mask_t ac_events_arr[] = {
29949e866e40b95795203f3ee46f44a197c946e4stevel {"mem_bank0_rds", 0x1}, {"mem_bank0_wrs", 0x2},
29949e866e40b95795203f3ee46f44a197c946e4stevel {"mem_bank0_stall", 0x3}, {"mem_bank1_rds", 0x4},
29949e866e40b95795203f3ee46f44a197c946e4stevel {"mem_bank1_wrs", 0x5}, {"mem_bank1_stall", 0x6},
29949e866e40b95795203f3ee46f44a197c946e4stevel {"clock_cycles", 0x7}, {"addr_pkts", 0x8},
29949e866e40b95795203f3ee46f44a197c946e4stevel {"data_pkts", 0x9}, {"flow_ctl_cyc", 0xa},
29949e866e40b95795203f3ee46f44a197c946e4stevel {"fast_arb_pkts", 0xb}, {"bus_cont_cyc", 0xc},
29949e866e40b95795203f3ee46f44a197c946e4stevel {"data_bus_can", 0xd}, {"ac_addr_pkts", 0xe},
29949e866e40b95795203f3ee46f44a197c946e4stevel {"ac_data_pkts", 0xf}, {"rts_pkts", 0x10},
29949e866e40b95795203f3ee46f44a197c946e4stevel {"rtsa_pkts", 0x11}, {"rto_pkts", 0x12},
29949e866e40b95795203f3ee46f44a197c946e4stevel {"rs_pkts", 0x13}, {"wb_pkts", 0x14},
29949e866e40b95795203f3ee46f44a197c946e4stevel {"ws_pkts", 0x15}, {"rio_pkts", 0x16},
29949e866e40b95795203f3ee46f44a197c946e4stevel {"rbio_pkts", 0x17}, {"wio_pkts", 0x18},
29949e866e40b95795203f3ee46f44a197c946e4stevel {"wbio_pkts", 0x19}, {"upa_a_rds_m", 0x1a},
29949e866e40b95795203f3ee46f44a197c946e4stevel {"upa_a_rdo_v", 0x1b}, {"upa_b_rds_m", 0x1c},
29949e866e40b95795203f3ee46f44a197c946e4stevel {"upa_b_rdo_v", 0x1d}, {"upa_a_preqs_fr", 0x20},
29949e866e40b95795203f3ee46f44a197c946e4stevel {"upa_a_sreqs_to", 0x21}, {"upa_a_preqs_to", 0x22},
29949e866e40b95795203f3ee46f44a197c946e4stevel {"upa_a_rds_fr", 0x23}, {"upa_a_rdsa_fr", 0x24},
29949e866e40b95795203f3ee46f44a197c946e4stevel {"upa_a_rdo_fr", 0x25}, {"upa_a_rdd_fr", 0x26},
29949e866e40b95795203f3ee46f44a197c946e4stevel {"upa_a_rio_rbio", 0x27}, {"upa_a_wio_wbio", 0x28},
29949e866e40b95795203f3ee46f44a197c946e4stevel {"upa_a_cpb_to", 0x29}, {"upa_a_inv_to", 0x2a},
29949e866e40b95795203f3ee46f44a197c946e4stevel {"upa_a_hits_buff", 0x2b}, {"upa_a_wb", 0x2c},
29949e866e40b95795203f3ee46f44a197c946e4stevel {"upa_a_wi", 0x2d}, {"upa_b_preqs_fr", 0x30},
29949e866e40b95795203f3ee46f44a197c946e4stevel {"upa_b_sreqs_to", 0x31}, {"upa_b_preqs_to", 0x32},
29949e866e40b95795203f3ee46f44a197c946e4stevel {"upa_b_rds_fr", 0x33}, {"upa_b_rdsa_fr", 0x34},
29949e866e40b95795203f3ee46f44a197c946e4stevel {"upa_b_rdo_fr", 0x35}, {"upa_b_rdd_fr", 0x36},
29949e866e40b95795203f3ee46f44a197c946e4stevel {"upa_b_rio_rbio", 0x37}, {"upa_b_wio_wbio", 0x38},
29949e866e40b95795203f3ee46f44a197c946e4stevel {"upa_b_cpb_to", 0x39}, {"upa_b_inv_to", 0x3a},
29949e866e40b95795203f3ee46f44a197c946e4stevel {"upa_b_hits_buff", 0x3b}, {"upa_b_wb", 0x3c},
29949e866e40b95795203f3ee46f44a197c946e4stevel {"upa_b_wi", 0x3d}
29949e866e40b95795203f3ee46f44a197c946e4stevel };
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel#define AC_NUM_EVENTS sizeof (ac_events_arr) / sizeof (ac_events_arr[0])
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * array of clear masks for each pic.
29949e866e40b95795203f3ee46f44a197c946e4stevel * These masks are used to clear the %pcr bits for
29949e866e40b95795203f3ee46f44a197c946e4stevel * each pic.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_event_mask_t ac_clear_pic[AC_NUM_PICS] = {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* pic0 */
29949e866e40b95795203f3ee46f44a197c946e4stevel {"clear_pic", (uint64_t)~(0x3f)},
29949e866e40b95795203f3ee46f44a197c946e4stevel /* pic1 */
29949e866e40b95795203f3ee46f44a197c946e4stevel {"clear_pic", (uint64_t)~(0x3f << 8)}
29949e866e40b95795203f3ee46f44a197c946e4stevel };
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel struct kstat_named *ac_pic_named_data;
29949e866e40b95795203f3ee46f44a197c946e4stevel int event, pic;
29949e866e40b95795203f3ee46f44a197c946e4stevel char pic_name[30];
29949e866e40b95795203f3ee46f44a197c946e4stevel int instance = ddi_get_instance(dip);
29949e866e40b95795203f3ee46f44a197c946e4stevel int pic_shift = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel for (pic = 0; pic < AC_NUM_PICS; pic++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * create the picN kstat. The size of this kstat is
29949e866e40b95795203f3ee46f44a197c946e4stevel * AC_NUM_EVENTS + 1 for the clear_event_mask
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) sprintf(pic_name, "pic%d", pic); /* pic0, pic1 ... */
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((ac_picN_ksp[pic] = kstat_create("ac",
193974072f41a843678abf5f61979c748687e66bSherry Moore instance, pic_name, "bus", KSTAT_TYPE_NAMED,
193974072f41a843678abf5f61979c748687e66bSherry Moore AC_NUM_EVENTS + 1, NULL)) == NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "ac %s: kstat_create failed",
193974072f41a843678abf5f61979c748687e66bSherry Moore pic_name);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* remove pic0 kstat if pic1 create fails */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (pic == 1) {
29949e866e40b95795203f3ee46f44a197c946e4stevel kstat_delete(ac_picN_ksp[0]);
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_picN_ksp[0] = NULL;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel return;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_pic_named_data =
193974072f41a843678abf5f61979c748687e66bSherry Moore (struct kstat_named *)(ac_picN_ksp[pic]->ks_data);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * when we are storing pcr_masks we need to shift bits
29949e866e40b95795203f3ee46f44a197c946e4stevel * left by 8 for pic1 events.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (pic == 1)
29949e866e40b95795203f3ee46f44a197c946e4stevel pic_shift = 8;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * for each picN event we need to write a kstat record
29949e866e40b95795203f3ee46f44a197c946e4stevel * (name = EVENT, value.ui64 = PCR_MASK)
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (event = 0; event < AC_NUM_EVENTS; event ++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* pcr_mask */
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_pic_named_data[event].value.ui64 =
193974072f41a843678abf5f61979c748687e66bSherry Moore ac_events_arr[event].pcr_mask << pic_shift;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* event-name */
29949e866e40b95795203f3ee46f44a197c946e4stevel kstat_named_init(&ac_pic_named_data[event],
193974072f41a843678abf5f61979c748687e66bSherry Moore ac_events_arr[event].event_name,
193974072f41a843678abf5f61979c748687e66bSherry Moore KSTAT_DATA_UINT64);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * we add the clear_pic event and mask as the last
29949e866e40b95795203f3ee46f44a197c946e4stevel * record in the kstat
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel /* pcr mask */
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_pic_named_data[AC_NUM_EVENTS].value.ui64 =
193974072f41a843678abf5f61979c748687e66bSherry Moore ac_clear_pic[pic].pcr_mask;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* event-name */
29949e866e40b95795203f3ee46f44a197c946e4stevel kstat_named_init(&ac_pic_named_data[AC_NUM_EVENTS],
193974072f41a843678abf5f61979c748687e66bSherry Moore ac_clear_pic[pic].event_name,
193974072f41a843678abf5f61979c748687e66bSherry Moore KSTAT_DATA_UINT64);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel kstat_install(ac_picN_ksp[pic]);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void
29949e866e40b95795203f3ee46f44a197c946e4stevelac_del_kstats(struct ac_soft_state *softsp)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct kstat *ac_ksp;
29949e866e40b95795203f3ee46f44a197c946e4stevel int pic;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* remove "misc" kstat */
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_ksp = softsp->ac_ksp;
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->ac_ksp = NULL;
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ac_ksp != NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(ac_ksp->ks_private == (void *)softsp);
29949e866e40b95795203f3ee46f44a197c946e4stevel kstat_delete(ac_ksp);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* remove "bus" kstat */
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_ksp = softsp->ac_counters_ksp;
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->ac_counters_ksp = NULL;
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ac_ksp != NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(ac_ksp->ks_private == (void *)softsp);
29949e866e40b95795203f3ee46f44a197c946e4stevel kstat_delete(ac_ksp);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * if we are the last instance to detach we need to
29949e866e40b95795203f3ee46f44a197c946e4stevel * remove the picN kstats. We use ac_attachcnt as a
29949e866e40b95795203f3ee46f44a197c946e4stevel * count of how many instances are still attached. This
29949e866e40b95795203f3ee46f44a197c946e4stevel * is protected by a mutex.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_enter(&ac_attachcnt_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_attachcnt --;
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ac_attachcnt == 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel for (pic = 0; pic < AC_NUM_PICS; pic++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ac_picN_ksp[pic] != (kstat_t *)NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel kstat_delete(ac_picN_ksp[pic]);
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_picN_ksp[pic] = NULL;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&ac_attachcnt_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic enum ac_bank_status
29949e866e40b95795203f3ee46f44a197c946e4stevelac_kstat_stat(sysc_cfga_rstate_t rst, sysc_cfga_ostate_t ost)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel switch (rst) {
29949e866e40b95795203f3ee46f44a197c946e4stevel case SYSC_CFGA_RSTATE_EMPTY:
29949e866e40b95795203f3ee46f44a197c946e4stevel return (StNoMem);
29949e866e40b95795203f3ee46f44a197c946e4stevel case SYSC_CFGA_RSTATE_DISCONNECTED:
29949e866e40b95795203f3ee46f44a197c946e4stevel return (StBad);
29949e866e40b95795203f3ee46f44a197c946e4stevel case SYSC_CFGA_RSTATE_CONNECTED:
29949e866e40b95795203f3ee46f44a197c946e4stevel switch (ost) {
29949e866e40b95795203f3ee46f44a197c946e4stevel case SYSC_CFGA_OSTATE_UNCONFIGURED:
29949e866e40b95795203f3ee46f44a197c946e4stevel return (StSpare);
29949e866e40b95795203f3ee46f44a197c946e4stevel case SYSC_CFGA_OSTATE_CONFIGURED:
29949e866e40b95795203f3ee46f44a197c946e4stevel return (StActive);
29949e866e40b95795203f3ee46f44a197c946e4stevel default:
29949e866e40b95795203f3ee46f44a197c946e4stevel return (StUnknown);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel default:
29949e866e40b95795203f3ee46f44a197c946e4stevel return (StUnknown);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic enum ac_bank_condition
29949e866e40b95795203f3ee46f44a197c946e4stevelac_kstat_cond(sysc_cfga_cond_t cond)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel switch (cond) {
29949e866e40b95795203f3ee46f44a197c946e4stevel case SYSC_CFGA_COND_UNKNOWN:
29949e866e40b95795203f3ee46f44a197c946e4stevel return (ConUnknown);
29949e866e40b95795203f3ee46f44a197c946e4stevel case SYSC_CFGA_COND_OK:
29949e866e40b95795203f3ee46f44a197c946e4stevel return (ConOK);
29949e866e40b95795203f3ee46f44a197c946e4stevel case SYSC_CFGA_COND_FAILING:
29949e866e40b95795203f3ee46f44a197c946e4stevel return (ConFailing);
29949e866e40b95795203f3ee46f44a197c946e4stevel case SYSC_CFGA_COND_FAILED:
29949e866e40b95795203f3ee46f44a197c946e4stevel return (ConFailed);
29949e866e40b95795203f3ee46f44a197c946e4stevel case SYSC_CFGA_COND_UNUSABLE:
29949e866e40b95795203f3ee46f44a197c946e4stevel return (ConBad);
29949e866e40b95795203f3ee46f44a197c946e4stevel default:
29949e866e40b95795203f3ee46f44a197c946e4stevel return (ConUnknown);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int
29949e866e40b95795203f3ee46f44a197c946e4stevelac_misc_kstat_update(kstat_t *ksp, int rw)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct ac_kstat *acksp;
29949e866e40b95795203f3ee46f44a197c946e4stevel struct ac_soft_state *softsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel acksp = (struct ac_kstat *)ksp->ks_data;
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp = (struct ac_soft_state *)ksp->ks_private;
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Need the NULL check in case kstat is about to be deleted. */
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(softsp->ac_ksp == NULL || ksp == softsp->ac_ksp);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* this is a read-only kstat. Bail out on a write */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (rw == KSTAT_WRITE) {
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EACCES);
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * copy the current state of the hardware into the
29949e866e40b95795203f3ee46f44a197c946e4stevel * kstat structure.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel acksp->ac_memctl.value.ui64 = *softsp->ac_memctl;
29949e866e40b95795203f3ee46f44a197c946e4stevel acksp->ac_memdecode0.value.ui64 = *softsp->ac_memdecode0;
29949e866e40b95795203f3ee46f44a197c946e4stevel acksp->ac_memdecode1.value.ui64 = *softsp->ac_memdecode1;
29949e866e40b95795203f3ee46f44a197c946e4stevel acksp->ac_mccr.value.ui32 = *softsp->ac_mccr;
29949e866e40b95795203f3ee46f44a197c946e4stevel acksp->ac_counter.value.ui64 = *softsp->ac_counter;
29949e866e40b95795203f3ee46f44a197c946e4stevel acksp->ac_bank0_status.value.c[0] =
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_kstat_stat(softsp->bank[0].rstate,
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[0].ostate);
29949e866e40b95795203f3ee46f44a197c946e4stevel acksp->ac_bank0_status.value.c[1] =
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_kstat_cond(softsp->bank[0].condition);
29949e866e40b95795203f3ee46f44a197c946e4stevel acksp->ac_bank1_status.value.c[0] =
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_kstat_stat(softsp->bank[1].rstate,
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[1].ostate);
29949e866e40b95795203f3ee46f44a197c946e4stevel acksp->ac_bank1_status.value.c[1] =
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_kstat_cond(softsp->bank[1].condition);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel return (0);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int
29949e866e40b95795203f3ee46f44a197c946e4stevelac_counters_kstat_update(kstat_t *ksp, int rw)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct kstat_named *ac_counters_data;
29949e866e40b95795203f3ee46f44a197c946e4stevel struct ac_soft_state *softsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint64_t pic_register;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_counters_data = (struct kstat_named *)ksp->ks_data;
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp = (struct ac_soft_state *)ksp->ks_private;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * We need to start/restart the ac_timeout that will
29949e866e40b95795203f3ee46f44a197c946e4stevel * return the AC counters to hot-plug mode after the
29949e866e40b95795203f3ee46f44a197c946e4stevel * ac_hot_plug_timeout_interval has expired. We tell
29949e866e40b95795203f3ee46f44a197c946e4stevel * ac_reset_timeout() whether this is a kstat_read or a
29949e866e40b95795203f3ee46f44a197c946e4stevel * kstat_write call. If this fails we reject the kstat
29949e866e40b95795203f3ee46f44a197c946e4stevel * operation.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ac_reset_timeout(rw) != 0)
29949e866e40b95795203f3ee46f44a197c946e4stevel return (-1);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (rw == KSTAT_WRITE) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Write the %pcr value to the softsp->ac_mccr.
29949e866e40b95795203f3ee46f44a197c946e4stevel * This interface does not support writing to the
29949e866e40b95795203f3ee46f44a197c946e4stevel * %pic.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel *softsp->ac_mccr =
193974072f41a843678abf5f61979c748687e66bSherry Moore (uint32_t)ac_counters_data[0].value.ui64;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Read %pcr and %pic register values and write them
29949e866e40b95795203f3ee46f44a197c946e4stevel * into counters kstat.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* pcr */
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_counters_data[0].value.ui64 = *softsp->ac_mccr;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel pic_register = *softsp->ac_counter;
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * ac pic register:
29949e866e40b95795203f3ee46f44a197c946e4stevel * (63:32) = pic1
29949e866e40b95795203f3ee46f44a197c946e4stevel * (31:00) = pic0
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* pic0 */
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_counters_data[1].value.ui64 =
193974072f41a843678abf5f61979c748687e66bSherry Moore AC_COUNTER_TO_PIC0(pic_register);
29949e866e40b95795203f3ee46f44a197c946e4stevel /* pic1 */
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_counters_data[2].value.ui64 =
193974072f41a843678abf5f61979c748687e66bSherry Moore AC_COUNTER_TO_PIC1(pic_register);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel return (0);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Decode the memory state given to us and plug it into the soft state
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void
29949e866e40b95795203f3ee46f44a197c946e4stevelac_get_memory_status(struct ac_soft_state *softsp, enum ac_bank_id id)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel char *property = (id == Bank0) ? AC_BANK0_STATUS : AC_BANK1_STATUS;
29949e866e40b95795203f3ee46f44a197c946e4stevel char *propval;
29949e866e40b95795203f3ee46f44a197c946e4stevel int proplen;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint64_t memdec = (id == Bank0) ?
193974072f41a843678abf5f61979c748687e66bSherry Moore *(softsp->ac_memdecode0) : *(softsp->ac_memdecode1);
29949e866e40b95795203f3ee46f44a197c946e4stevel uint_t grp_size;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[id].busy = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[id].status_change = ddi_get_time();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (GRP_SIZE_IS_SET(memdec)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel grp_size = GRP_SPANMB(memdec);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* determine the memory bank size (in MB) */
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[id].real_size = softsp->bank[id].use_size =
29949e866e40b95795203f3ee46f44a197c946e4stevel (id == Bank0) ? (grp_size / INTLV0(*softsp->ac_memctl)) :
29949e866e40b95795203f3ee46f44a197c946e4stevel (grp_size / INTLV1(*softsp->ac_memctl));
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[id].real_size = softsp->bank[id].use_size = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * decode the memory bank property. set condition based
29949e866e40b95795203f3ee46f44a197c946e4stevel * on the values.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ddi_prop_op(DDI_DEV_T_ANY, softsp->dip, PROP_LEN_AND_VAL_ALLOC,
29949e866e40b95795203f3ee46f44a197c946e4stevel DDI_PROP_DONTPASS, property, (caddr_t)&propval, &proplen) ==
29949e866e40b95795203f3ee46f44a197c946e4stevel DDI_PROP_SUCCESS) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if (strcmp(propval, AC_BANK_NOMEM) == 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[id].rstate = SYSC_CFGA_RSTATE_EMPTY;
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[id].ostate = SYSC_CFGA_OSTATE_UNCONFIGURED;
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[id].condition = SYSC_CFGA_COND_UNKNOWN;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else if (strcmp(propval, AC_BANK_OK) == 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[id].rstate = SYSC_CFGA_RSTATE_CONNECTED;
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[id].ostate = SYSC_CFGA_OSTATE_CONFIGURED;
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[id].condition = SYSC_CFGA_COND_OK;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else if (strcmp(propval, AC_BANK_SPARE) == 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[id].rstate = SYSC_CFGA_RSTATE_CONNECTED;
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[id].ostate = SYSC_CFGA_OSTATE_UNCONFIGURED;
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[id].condition = SYSC_CFGA_COND_UNKNOWN;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else if (strcmp(propval, AC_BANK_FAILED) == 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[id].rstate = SYSC_CFGA_RSTATE_DISCONNECTED;
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[id].ostate = SYSC_CFGA_OSTATE_UNCONFIGURED;
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[id].condition = SYSC_CFGA_COND_UNUSABLE;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "ac%d: board %d, bank %d: "
29949e866e40b95795203f3ee46f44a197c946e4stevel "unknown %smemory state [%s]",
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_get_instance(softsp->dip), softsp->board, id,
29949e866e40b95795203f3ee46f44a197c946e4stevel (memdec & AC_MEM_VALID) ? "connected " : "",
29949e866e40b95795203f3ee46f44a197c946e4stevel propval);
29949e866e40b95795203f3ee46f44a197c946e4stevel if (memdec & AC_MEM_VALID) {
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[id].rstate =
29949e866e40b95795203f3ee46f44a197c946e4stevel SYSC_CFGA_RSTATE_CONNECTED;
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[id].ostate =
29949e866e40b95795203f3ee46f44a197c946e4stevel SYSC_CFGA_OSTATE_CONFIGURED;
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[id].condition =
29949e866e40b95795203f3ee46f44a197c946e4stevel SYSC_CFGA_COND_OK;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[id].rstate =
29949e866e40b95795203f3ee46f44a197c946e4stevel SYSC_CFGA_RSTATE_DISCONNECTED;
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[id].ostate =
29949e866e40b95795203f3ee46f44a197c946e4stevel SYSC_CFGA_OSTATE_UNCONFIGURED;
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[id].condition =
29949e866e40b95795203f3ee46f44a197c946e4stevel SYSC_CFGA_COND_UNUSABLE;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel kmem_free(propval, proplen);
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* we don't have the property, deduce the state of memory */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (memdec & AC_MEM_VALID) {
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[id].rstate = SYSC_CFGA_RSTATE_CONNECTED;
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[id].ostate = SYSC_CFGA_OSTATE_CONFIGURED;
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[id].condition = SYSC_CFGA_COND_OK;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* could be an i/o board... */
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[id].rstate = SYSC_CFGA_RSTATE_EMPTY;
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[id].ostate = SYSC_CFGA_OSTATE_UNCONFIGURED;
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[id].condition = SYSC_CFGA_COND_UNKNOWN;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* we assume that all other bank statuses are NOT valid */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (softsp->bank[id].rstate == SYSC_CFGA_RSTATE_CONNECTED) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((memdec & AC_MEM_VALID) != 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel uint64_t base_pa;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT((*softsp->ac_memctl & AC_CSR_REFEN) != 0);
29949e866e40b95795203f3ee46f44a197c946e4stevel /* register existence in the memloc database */
29949e866e40b95795203f3ee46f44a197c946e4stevel base_pa = GRP_REALBASE(memdec);
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_add_memloc(softsp->board, base_pa, grp_size);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void
29949e866e40b95795203f3ee46f44a197c946e4stevelac_eval_memory_status(struct ac_soft_state *softsp, enum ac_bank_id id)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel uint64_t memdec = (id == Bank0) ?
193974072f41a843678abf5f61979c748687e66bSherry Moore *(softsp->ac_memdecode0) : *(softsp->ac_memdecode1);
29949e866e40b95795203f3ee46f44a197c946e4stevel uint64_t base_pa;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Downgrade the status of any bank that did not get
29949e866e40b95795203f3ee46f44a197c946e4stevel * programmed.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (softsp->bank[id].rstate == SYSC_CFGA_RSTATE_CONNECTED &&
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[id].ostate == SYSC_CFGA_OSTATE_UNCONFIGURED &&
29949e866e40b95795203f3ee46f44a197c946e4stevel (memdec & AC_MEM_VALID) == 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "ac%d: board %d, bank %d: "
29949e866e40b95795203f3ee46f44a197c946e4stevel "spare memory bank not valid - it was ",
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_get_instance(softsp->dip), softsp->board, id);
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "misconfigured by the system "
29949e866e40b95795203f3ee46f44a197c946e4stevel "firmware. Disabling...");
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[id].rstate = SYSC_CFGA_RSTATE_DISCONNECTED;
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[id].ostate = SYSC_CFGA_OSTATE_UNCONFIGURED;
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[id].condition = SYSC_CFGA_COND_UNUSABLE;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Log a message about good banks.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (softsp->bank[id].rstate == SYSC_CFGA_RSTATE_CONNECTED) {
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT((memdec & AC_MEM_VALID) != 0);
29949e866e40b95795203f3ee46f44a197c946e4stevel base_pa = GRP_REALBASE(memdec);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_CONT, "?ac%d board %d bank %d: "
29949e866e40b95795203f3ee46f44a197c946e4stevel "base 0x%" PRIx64 " size %dmb rstate %d "
29949e866e40b95795203f3ee46f44a197c946e4stevel "ostate %d condition %d\n",
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_get_instance(softsp->dip),
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->board, id, base_pa, softsp->bank[id].real_size,
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[id].rstate, softsp->bank[id].ostate,
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->bank[id].condition);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*ARGSUSED*/
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void
29949e866e40b95795203f3ee46f44a197c946e4stevelac_ecache_flush(uint64_t a, uint64_t b)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel cpu_flush_ecache();
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic char *
29949e866e40b95795203f3ee46f44a197c946e4stevelac_ostate_typestr(sysc_cfga_ostate_t ostate, ac_audit_evt_t event)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel char *type_str;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel switch (ostate) {
29949e866e40b95795203f3ee46f44a197c946e4stevel case SYSC_CFGA_OSTATE_UNCONFIGURED:
29949e866e40b95795203f3ee46f44a197c946e4stevel switch (event) {
29949e866e40b95795203f3ee46f44a197c946e4stevel case AC_AUDIT_OSTATE_UNCONFIGURE:
29949e866e40b95795203f3ee46f44a197c946e4stevel type_str = "unconfiguring";
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel case AC_AUDIT_OSTATE_SUCCEEDED:
29949e866e40b95795203f3ee46f44a197c946e4stevel case AC_AUDIT_OSTATE_UNCONFIGURE_FAILED:
29949e866e40b95795203f3ee46f44a197c946e4stevel type_str = "unconfigured";
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel default:
29949e866e40b95795203f3ee46f44a197c946e4stevel type_str = "unconfigure?";
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel case SYSC_CFGA_OSTATE_CONFIGURED:
29949e866e40b95795203f3ee46f44a197c946e4stevel switch (event) {
29949e866e40b95795203f3ee46f44a197c946e4stevel case AC_AUDIT_OSTATE_CONFIGURE:
29949e866e40b95795203f3ee46f44a197c946e4stevel type_str = "configuring";
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel case AC_AUDIT_OSTATE_SUCCEEDED:
29949e866e40b95795203f3ee46f44a197c946e4stevel case AC_AUDIT_OSTATE_CONFIGURE_FAILED:
29949e866e40b95795203f3ee46f44a197c946e4stevel type_str = "configured";
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel default:
29949e866e40b95795203f3ee46f44a197c946e4stevel type_str = "configure?";
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel default:
29949e866e40b95795203f3ee46f44a197c946e4stevel type_str = "undefined occupant state";
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel return (type_str);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void
29949e866e40b95795203f3ee46f44a197c946e4stevelac_policy_audit_messages(ac_audit_evt_t event, ac_cfga_pkt_t *pkt)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct ac_soft_state *softsp = pkt->softsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel switch (event) {
29949e866e40b95795203f3ee46f44a197c946e4stevel case AC_AUDIT_OSTATE_CONFIGURE:
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s memory bank %d in slot %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore ac_ostate_typestr(SYSC_CFGA_OSTATE_CONFIGURED,
193974072f41a843678abf5f61979c748687e66bSherry Moore event), pkt->bank,
193974072f41a843678abf5f61979c748687e66bSherry Moore softsp->board);
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel case AC_AUDIT_OSTATE_UNCONFIGURE:
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s memory bank %d in slot %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore ac_ostate_typestr(
193974072f41a843678abf5f61979c748687e66bSherry Moore SYSC_CFGA_OSTATE_UNCONFIGURED,
193974072f41a843678abf5f61979c748687e66bSherry Moore event), pkt->bank,
193974072f41a843678abf5f61979c748687e66bSherry Moore softsp->board);
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel case AC_AUDIT_OSTATE_SUCCEEDED:
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "memory bank %d in slot %d is %s",
193974072f41a843678abf5f61979c748687e66bSherry Moore pkt->bank, softsp->board,
193974072f41a843678abf5f61979c748687e66bSherry Moore ac_ostate_typestr(
193974072f41a843678abf5f61979c748687e66bSherry Moore softsp->bank[pkt->bank].ostate,
193974072f41a843678abf5f61979c748687e66bSherry Moore event));
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel case AC_AUDIT_OSTATE_CONFIGURE_FAILED:
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_NOTE,
29949e866e40b95795203f3ee46f44a197c946e4stevel "memory bank %d in slot %d not %s",
193974072f41a843678abf5f61979c748687e66bSherry Moore pkt->bank,
193974072f41a843678abf5f61979c748687e66bSherry Moore softsp->board,
193974072f41a843678abf5f61979c748687e66bSherry Moore ac_ostate_typestr(
193974072f41a843678abf5f61979c748687e66bSherry Moore SYSC_CFGA_OSTATE_CONFIGURED,
193974072f41a843678abf5f61979c748687e66bSherry Moore event));
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel case AC_AUDIT_OSTATE_UNCONFIGURE_FAILED:
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "memory bank %d in slot %d not %s",
193974072f41a843678abf5f61979c748687e66bSherry Moore pkt->bank,
193974072f41a843678abf5f61979c748687e66bSherry Moore softsp->board,
193974072f41a843678abf5f61979c748687e66bSherry Moore ac_ostate_typestr(
193974072f41a843678abf5f61979c748687e66bSherry Moore SYSC_CFGA_OSTATE_UNCONFIGURED,
193974072f41a843678abf5f61979c748687e66bSherry Moore event));
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel default:
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "unknown audit of memory bank %d in slot %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore pkt->bank, softsp->board);
29949e866e40b95795203f3ee46f44a197c946e4stevel break;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <vm/page.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <vm/hat.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int
29949e866e40b95795203f3ee46f44a197c946e4stevelac_mem_exercise(ac_cfga_pkt_t *pkt, int flag)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct ac_mem_info *mem_info;
29949e866e40b95795203f3ee46f44a197c946e4stevel pfn_t base;
29949e866e40b95795203f3ee46f44a197c946e4stevel pgcnt_t npgs;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel mem_info = &pkt->softsp->bank[pkt->bank];
29949e866e40b95795203f3ee46f44a197c946e4stevel if (mem_info->rstate == SYSC_CFGA_RSTATE_CONNECTED) {
29949e866e40b95795203f3ee46f44a197c946e4stevel uint64_t base_pa, bank_size;
29949e866e40b95795203f3ee46f44a197c946e4stevel uint64_t decode;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel decode = (pkt->bank == Bank0) ?
29949e866e40b95795203f3ee46f44a197c946e4stevel *pkt->softsp->ac_memdecode0 : *pkt->softsp->ac_memdecode1;
29949e866e40b95795203f3ee46f44a197c946e4stevel base_pa = GRP_REALBASE(decode);
29949e866e40b95795203f3ee46f44a197c946e4stevel bank_size = GRP_UK2SPAN(decode);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel base = base_pa >> PAGESHIFT;
29949e866e40b95795203f3ee46f44a197c946e4stevel npgs = bank_size >> PAGESHIFT;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel base = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel npgs = 0;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel switch (pkt->cmd_cfga.arg) {
29949e866e40b95795203f3ee46f44a197c946e4stevel case AC_MEMX_RELOCATE_ALL: {
29949e866e40b95795203f3ee46f44a197c946e4stevel pfn_t pfn, pglim;
29949e866e40b95795203f3ee46f44a197c946e4stevel struct ac_memx_relocate_stats rstat;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if (npgs == 0 ||
29949e866e40b95795203f3ee46f44a197c946e4stevel mem_info->ostate != SYSC_CFGA_OSTATE_CONFIGURED) {
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EINVAL);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel if (mem_info->busy != FALSE) {
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EBUSY);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel bzero(&rstat, sizeof (rstat));
29949e866e40b95795203f3ee46f44a197c946e4stevel rstat.base = (uint_t)base;
29949e866e40b95795203f3ee46f44a197c946e4stevel rstat.npgs = (uint_t)npgs;
29949e866e40b95795203f3ee46f44a197c946e4stevel pglim = base + npgs;
29949e866e40b95795203f3ee46f44a197c946e4stevel for (pfn = base; pfn < pglim; pfn++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel page_t *pp, *pp_repl;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel retry:
29949e866e40b95795203f3ee46f44a197c946e4stevel pp = page_numtopp_nolock(pfn);
29949e866e40b95795203f3ee46f44a197c946e4stevel if (pp != NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel if (!page_trylock(pp, SE_EXCL)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel pp = NULL;
29949e866e40b95795203f3ee46f44a197c946e4stevel rstat.nolock++;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel if (pp != NULL && page_pptonum(pp) != pfn) {
29949e866e40b95795203f3ee46f44a197c946e4stevel page_unlock(pp);
29949e866e40b95795203f3ee46f44a197c946e4stevel goto retry;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel rstat.nopaget++;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel if (pp != NULL && PP_ISFREE(pp)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel page_unlock(pp);
29949e866e40b95795203f3ee46f44a197c946e4stevel rstat.isfree++;
29949e866e40b95795203f3ee46f44a197c946e4stevel pp = NULL;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel if (pp != NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel spgcnt_t npgs;
29949e866e40b95795203f3ee46f44a197c946e4stevel int result;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel pp_repl = NULL;
29949e866e40b95795203f3ee46f44a197c946e4stevel result = page_relocate(&pp, &pp_repl, 1, 1,
29949e866e40b95795203f3ee46f44a197c946e4stevel &npgs, NULL);
29949e866e40b95795203f3ee46f44a197c946e4stevel if (result == 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel while (npgs-- > 0) {
29949e866e40b95795203f3ee46f44a197c946e4stevel page_t *tpp;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(pp_repl != NULL);
29949e866e40b95795203f3ee46f44a197c946e4stevel tpp = pp_repl;
29949e866e40b95795203f3ee46f44a197c946e4stevel page_sub(&pp_repl, tpp);
29949e866e40b95795203f3ee46f44a197c946e4stevel page_unlock(tpp);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel rstat.reloc++;
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel page_unlock(pp);
29949e866e40b95795203f3ee46f44a197c946e4stevel rstat.noreloc++;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel if (pkt->cmd_cfga.private != NULL && ddi_copyout(&rstat,
29949e866e40b95795203f3ee46f44a197c946e4stevel pkt->cmd_cfga.private, sizeof (rstat), flag) != 0)
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EFAULT);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_SUCCESS);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel default:
29949e866e40b95795203f3ee46f44a197c946e4stevel return (EINVAL);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int
29949e866e40b95795203f3ee46f44a197c946e4stevelac_reset_timeout(int rw)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_enter(&ac_hot_plug_mode_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((ac_hot_plug_timeout == (timeout_id_t)NULL) &&
29949e866e40b95795203f3ee46f44a197c946e4stevel (rw == KSTAT_READ)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * We are in hot-plug mode. A kstat_read is not
29949e866e40b95795203f3ee46f44a197c946e4stevel * going to affect this. return 0 to allow the
29949e866e40b95795203f3ee46f44a197c946e4stevel * kstat_read to continue.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&ac_hot_plug_mode_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (0);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel } else if ((ac_hot_plug_timeout == (timeout_id_t)NULL) &&
29949e866e40b95795203f3ee46f44a197c946e4stevel (rw == KSTAT_WRITE)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * There are no pending timeouts and we have received a
29949e866e40b95795203f3ee46f44a197c946e4stevel * kstat_write request so we must be transitioning
29949e866e40b95795203f3ee46f44a197c946e4stevel * from "hot-plug" mode to non "hot-plug" mode.
29949e866e40b95795203f3ee46f44a197c946e4stevel * Try to lock all boards before allowing the kstat_write.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel if (ac_enter_transition() == TRUE)
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bdlist_unlock();
29949e866e40b95795203f3ee46f44a197c946e4stevel else {
29949e866e40b95795203f3ee46f44a197c946e4stevel /* cannot lock boards so fail */
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&ac_hot_plug_mode_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (-1);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * We need to display a Warning about hot-plugging any
29949e866e40b95795203f3ee46f44a197c946e4stevel * boards. This message is only needed when we are
29949e866e40b95795203f3ee46f44a197c946e4stevel * transitioning out of "hot-plug" mode.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "This machine is being taken out of "
29949e866e40b95795203f3ee46f44a197c946e4stevel "hot-plug mode.");
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_CONT, "Do not attempt to hot-plug boards "
29949e866e40b95795203f3ee46f44a197c946e4stevel "or power supplies in this system until further notice.");
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel } else if (ac_hot_plug_timeout != (timeout_id_t)NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * There is a pending timeout so we must already be
29949e866e40b95795203f3ee46f44a197c946e4stevel * in non "hot-plug" mode. It doesn't matter if the
29949e866e40b95795203f3ee46f44a197c946e4stevel * kstat request is a read or a write.
29949e866e40b95795203f3ee46f44a197c946e4stevel *
29949e866e40b95795203f3ee46f44a197c946e4stevel * We need to cancel the existing timeout.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) untimeout(ac_hot_plug_timeout);
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_hot_plug_timeout = NULL;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * create a new timeout.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_hot_plug_timeout = timeout(ac_timeout, NULL,
29949e866e40b95795203f3ee46f44a197c946e4stevel drv_usectohz(ac_hot_plug_timeout_interval * 1000000));
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel mutex_exit(&ac_hot_plug_mode_mutex);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (0);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void
29949e866e40b95795203f3ee46f44a197c946e4stevelac_timeout(void *arg)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct ac_soft_state *softsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bd_t *board;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel#ifdef lint
29949e866e40b95795203f3ee46f44a197c946e4stevel arg = arg;
29949e866e40b95795203f3ee46f44a197c946e4stevel#endif /* lint */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_hot_plug_timeout = (timeout_id_t)NULL;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) fhc_bdlist_lock(-1);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Foreach ac in the board list we need to
29949e866e40b95795203f3ee46f44a197c946e4stevel * re-program the pcr into "hot-plug" mode.
29949e866e40b95795203f3ee46f44a197c946e4stevel * We also program the pic register with the
29949e866e40b95795203f3ee46f44a197c946e4stevel * bus pause timing
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel board = fhc_bd_first();
29949e866e40b95795203f3ee46f44a197c946e4stevel while (board != NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp = board->ac_softsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel if (softsp == NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * This board must not have an AC.
29949e866e40b95795203f3ee46f44a197c946e4stevel * Skip it and move on.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel board = fhc_bd_next(board);
29949e866e40b95795203f3ee46f44a197c946e4stevel continue;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel /* program the pcr into hot-plug mode */
29949e866e40b95795203f3ee46f44a197c946e4stevel *softsp->ac_mccr = AC_CLEAR_PCR(*softsp->ac_mccr);
29949e866e40b95795203f3ee46f44a197c946e4stevel *softsp->ac_mccr = AC_SET_HOT_PLUG(*softsp->ac_mccr);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* program the pic with the bus pause time value */
29949e866e40b95795203f3ee46f44a197c946e4stevel *softsp->ac_counter = AC_SET_PIC_BUS_PAUSE(softsp->board);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* get the next board */
29949e866e40b95795203f3ee46f44a197c946e4stevel board = fhc_bd_next(board);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ac_exit_transition();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bdlist_unlock();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * It is now safe to start hot-plugging again. We need
29949e866e40b95795203f3ee46f44a197c946e4stevel * to display a message.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_NOTE, "This machine is now in hot-plug mode.");
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_CONT, "Board and power supply hot-plug operations "
29949e866e40b95795203f3ee46f44a197c946e4stevel "can be resumed.");
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * This function will acquire the lock and set the in_transition
29949e866e40b95795203f3ee46f44a197c946e4stevel * bit for all the slots. If the slots are being used,
29949e866e40b95795203f3ee46f44a197c946e4stevel * we return FALSE; else set in_transition and return TRUE.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int
29949e866e40b95795203f3ee46f44a197c946e4stevelac_enter_transition(void)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bd_t *list;
29949e866e40b95795203f3ee46f44a197c946e4stevel sysc_cfga_stat_t *sysc_stat_lk;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* mutex lock the structure */
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) fhc_bdlist_lock(-1);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel list = fhc_bd_clock();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* change the in_transition bit */
29949e866e40b95795203f3ee46f44a197c946e4stevel sysc_stat_lk = &list->sc;
29949e866e40b95795203f3ee46f44a197c946e4stevel if (sysc_stat_lk->in_transition == TRUE) {
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bdlist_unlock();
29949e866e40b95795203f3ee46f44a197c946e4stevel return (FALSE);
29949e866e40b95795203f3ee46f44a197c946e4stevel } else {
29949e866e40b95795203f3ee46f44a197c946e4stevel sysc_stat_lk->in_transition = TRUE;
29949e866e40b95795203f3ee46f44a197c946e4stevel return (TRUE);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * clear the in_transition bit for all the slots.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void
29949e866e40b95795203f3ee46f44a197c946e4stevelac_exit_transition(void)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel fhc_bd_t *list;
29949e866e40b95795203f3ee46f44a197c946e4stevel sysc_cfga_stat_t *sysc_stat_lk;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(fhc_bdlist_locked());
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel list = fhc_bd_clock();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel sysc_stat_lk = &list->sc;
29949e866e40b95795203f3ee46f44a197c946e4stevel ASSERT(sysc_stat_lk->in_transition == TRUE);
29949e866e40b95795203f3ee46f44a197c946e4stevel sysc_stat_lk->in_transition = FALSE;
29949e866e40b95795203f3ee46f44a197c946e4stevel}