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/ivintr.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/intr.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/intreg.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/autoconf.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/modctl.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/spl.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/fhc.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/simmstat.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/* Useful debugging Stuff */
29949e866e40b95795203f3ee46f44a197c946e4stevel#include <sys/nexusdebug.h>
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Function prototypes
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int simmstat_attach(dev_info_t *, ddi_attach_cmd_t);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int simmstat_detach(dev_info_t *, ddi_detach_cmd_t);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void simmstat_add_kstats(struct simmstat_soft_state *);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int simmstat_kstat_update(kstat_t *, int);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Configuration data structures
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic struct cb_ops simmstat_cb_ops = {
29949e866e40b95795203f3ee46f44a197c946e4stevel nulldev, /* open */
29949e866e40b95795203f3ee46f44a197c946e4stevel nulldev, /* close */
29949e866e40b95795203f3ee46f44a197c946e4stevel nulldev, /* strategy */
29949e866e40b95795203f3ee46f44a197c946e4stevel nulldev, /* print */
29949e866e40b95795203f3ee46f44a197c946e4stevel nodev, /* dump */
29949e866e40b95795203f3ee46f44a197c946e4stevel nulldev, /* read */
29949e866e40b95795203f3ee46f44a197c946e4stevel nulldev, /* write */
29949e866e40b95795203f3ee46f44a197c946e4stevel nulldev, /* ioctl */
29949e866e40b95795203f3ee46f44a197c946e4stevel nodev, /* devmap */
29949e866e40b95795203f3ee46f44a197c946e4stevel nodev, /* mmap */
29949e866e40b95795203f3ee46f44a197c946e4stevel nodev, /* segmap */
29949e866e40b95795203f3ee46f44a197c946e4stevel nochpoll, /* poll */
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_prop_op, /* cb_prop_op */
29949e866e40b95795203f3ee46f44a197c946e4stevel 0, /* streamtab */
29949e866e40b95795203f3ee46f44a197c946e4stevel D_MP | D_NEW | D_HOTPLUG, /* Driver compatibility flag */
29949e866e40b95795203f3ee46f44a197c946e4stevel CB_REV, /* rev */
29949e866e40b95795203f3ee46f44a197c946e4stevel nodev, /* cb_aread */
29949e866e40b95795203f3ee46f44a197c946e4stevel nodev /* cb_awrite */
29949e866e40b95795203f3ee46f44a197c946e4stevel};
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic struct dev_ops simmstat_ops = {
29949e866e40b95795203f3ee46f44a197c946e4stevel DEVO_REV, /* rev */
29949e866e40b95795203f3ee46f44a197c946e4stevel 0, /* refcnt */
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_no_info, /* getinfo */
29949e866e40b95795203f3ee46f44a197c946e4stevel nulldev, /* identify */
29949e866e40b95795203f3ee46f44a197c946e4stevel nulldev, /* probe */
29949e866e40b95795203f3ee46f44a197c946e4stevel simmstat_attach, /* attach */
29949e866e40b95795203f3ee46f44a197c946e4stevel simmstat_detach, /* detach */
29949e866e40b95795203f3ee46f44a197c946e4stevel nulldev, /* reset */
29949e866e40b95795203f3ee46f44a197c946e4stevel &simmstat_cb_ops, /* cb_ops */
29949e866e40b95795203f3ee46f44a197c946e4stevel (struct bus_ops *)0, /* bus_ops */
193974072f41a843678abf5f61979c748687e66bSherry Moore nulldev, /* power */
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_quiesce_not_needed, /* quiesce */
29949e866e40b95795203f3ee46f44a197c946e4stevel};
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic uint_t simmstat_reg_read_delay_us = 10;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Driver globals
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevelvoid *simmstatp;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelextern struct mod_ops mod_driverops;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic struct modldrv modldrv = {
29949e866e40b95795203f3ee46f44a197c946e4stevel &mod_driverops, /* module type, this one is a driver */
193974072f41a843678abf5f61979c748687e66bSherry Moore "SIMM-status Leaf", /* module name */
29949e866e40b95795203f3ee46f44a197c946e4stevel &simmstat_ops, /* driver ops */
29949e866e40b95795203f3ee46f44a197c946e4stevel};
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic struct modlinkage modlinkage = {
29949e866e40b95795203f3ee46f44a197c946e4stevel MODREV_1, /* rev */
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(&simmstatp,
29949e866e40b95795203f3ee46f44a197c946e4stevel sizeof (struct simmstat_soft_state), 1)) != 0)
29949e866e40b95795203f3ee46f44a197c946e4stevel return (error);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel return (mod_install(&modlinkage));
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelint
29949e866e40b95795203f3ee46f44a197c946e4stevel_fini(void)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel int error;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((error = mod_remove(&modlinkage)) != 0)
29949e866e40b95795203f3ee46f44a197c946e4stevel return (error);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_soft_state_fini(&simmstatp);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (0);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelint
29949e866e40b95795203f3ee46f44a197c946e4stevel_info(struct modinfo *modinfop)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel return (mod_info(&modlinkage, modinfop));
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int
29949e866e40b95795203f3ee46f44a197c946e4stevelsimmstat_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct simmstat_soft_state *softsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel int instance;
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(simmstatp, instance) != DDI_SUCCESS)
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_FAILURE);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp = ddi_get_soft_state(simmstatp, instance);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Set the dip in the soft state */
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->dip = devi;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* Get the board number from this nodes parent device. */
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, "simmstat%d: unable to retrieve %s property",
193974072f41a843678abf5f61979c748687e66bSherry Moore instance, OBP_BOARDNUM);
29949e866e40b95795203f3ee46f44a197c946e4stevel goto bad;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel DPRINTF(SIMMSTAT_ATTACH_DEBUG, ("simmstat%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,
29949e866e40b95795203f3ee46f44a197c946e4stevel (caddr_t *)&softsp->simmstat_base, 0, 0)) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "simmstat%d: unable to map registers",
193974072f41a843678abf5f61979c748687e66bSherry Moore instance);
29949e866e40b95795203f3ee46f44a197c946e4stevel goto bad;
29949e866e40b95795203f3ee46f44a197c946e4stevel }
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 /* create the kstats for this device */
29949e866e40b95795203f3ee46f44a197c946e4stevel simmstat_add_kstats(softsp);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_report_dev(devi);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_SUCCESS);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelbad:
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_soft_state_free(simmstatp, instance);
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_FAILURE);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/* ARGSUSED */
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int
29949e866e40b95795203f3ee46f44a197c946e4stevelsimmstat_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel int instance;
29949e866e40b95795203f3ee46f44a197c946e4stevel struct simmstat_soft_state *softsp;
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(simmstatp, instance);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel switch (cmd) {
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_SUSPEND:
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_SUCCESS);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel case DDI_DETACH:
29949e866e40b95795203f3ee46f44a197c946e4stevel (void) fhc_bdlist_lock(softsp->board);
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 fhc_bdlist_unlock();
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* remove the kstat for this board */
29949e866e40b95795203f3ee46f44a197c946e4stevel kstat_delete(softsp->simmstat_ksp);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* unmap the registers */
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_unmap_regs(softsp->dip, 0,
193974072f41a843678abf5f61979c748687e66bSherry Moore (caddr_t *)&softsp->simmstat_base, 0, 0);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel /* free up the soft state */
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_soft_state_free(simmstatp, instance);
29949e866e40b95795203f3ee46f44a197c946e4stevel ddi_prop_remove_all(devi);
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel return (DDI_SUCCESS);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic void
29949e866e40b95795203f3ee46f44a197c946e4stevelsimmstat_add_kstats(struct simmstat_soft_state *softsp)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct kstat *simmstat_ksp;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel if ((simmstat_ksp = kstat_create("unix", softsp->board,
29949e866e40b95795203f3ee46f44a197c946e4stevel SIMMSTAT_KSTAT_NAME, "misc", KSTAT_TYPE_RAW,
29949e866e40b95795203f3ee46f44a197c946e4stevel SIMM_COUNT, KSTAT_FLAG_PERSISTENT)) == NULL) {
29949e866e40b95795203f3ee46f44a197c946e4stevel cmn_err(CE_WARN, "simmstat%d: kstat_create failed",
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_get_instance(softsp->dip));
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel simmstat_ksp->ks_update = simmstat_kstat_update;
29949e866e40b95795203f3ee46f44a197c946e4stevel simmstat_ksp->ks_private = (void *)softsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp->simmstat_ksp = simmstat_ksp;
29949e866e40b95795203f3ee46f44a197c946e4stevel kstat_install(simmstat_ksp);
29949e866e40b95795203f3ee46f44a197c946e4stevel}
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel/*
29949e866e40b95795203f3ee46f44a197c946e4stevel * Kstats only need ks_update functions when they change dynamically
29949e866e40b95795203f3ee46f44a197c946e4stevel * at run time.
29949e866e40b95795203f3ee46f44a197c946e4stevel * In the case of the simmstat registers, they contain battery
29949e866e40b95795203f3ee46f44a197c946e4stevel * information for NVSIMMs. These need to be updated whenever a
29949e866e40b95795203f3ee46f44a197c946e4stevel * kstat_read asks for the data. There is currently no plan to
29949e866e40b95795203f3ee46f44a197c946e4stevel * ship NVSIMMs on this platform, but this support must be present.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevelstatic int
29949e866e40b95795203f3ee46f44a197c946e4stevelsimmstat_kstat_update(kstat_t *ksp, int rw)
29949e866e40b95795203f3ee46f44a197c946e4stevel{
29949e866e40b95795203f3ee46f44a197c946e4stevel struct simmstat_soft_state *softsp;
29949e866e40b95795203f3ee46f44a197c946e4stevel volatile char *statp; /* pointer to hardware register */
29949e866e40b95795203f3ee46f44a197c946e4stevel char *kstatp; /* pointer to kstat data buffer */
29949e866e40b95795203f3ee46f44a197c946e4stevel int i;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel kstatp = (char *)ksp->ks_data;
29949e866e40b95795203f3ee46f44a197c946e4stevel softsp = (struct simmstat_soft_state *)ksp->ks_private;
29949e866e40b95795203f3ee46f44a197c946e4stevel
29949e866e40b95795203f3ee46f44a197c946e4stevel statp = (char *)softsp->simmstat_base;
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 /*
29949e866e40b95795203f3ee46f44a197c946e4stevel * copy current status of hardware into the kstat
29949e866e40b95795203f3ee46f44a197c946e4stevel * structure.
29949e866e40b95795203f3ee46f44a197c946e4stevel */
29949e866e40b95795203f3ee46f44a197c946e4stevel for (i = 0; i < SIMM_COUNT; i++, statp++, kstatp++) {
29949e866e40b95795203f3ee46f44a197c946e4stevel *kstatp = *statp;
29949e866e40b95795203f3ee46f44a197c946e4stevel DELAY(simmstat_reg_read_delay_us);
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel }
29949e866e40b95795203f3ee46f44a197c946e4stevel return (0);
29949e866e40b95795203f3ee46f44a197c946e4stevel}