root/usr/src/uts/sun4v/io/iospc/rfios_iospc.c
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */
#include <sys/types.h>
#include <sys/ddi.h>
#include <sys/modctl.h>
#include <sys/kmem.h>
#include <sys/sunddi.h>
#include <sys/sunndi.h>
#include <sys/disp.h>
#include <sys/stat.h>
#include <sys/pci.h>
#include <sys/hsvc.h>
#include "iospc.h"
#include "rfios_acc.h"
#include "rfios_tables.h"

extern iospc_grp_t *rfios_leaf_grps[];

#define RF_REQ_MAJOR_VER        1
#define RF_REQ_MINOR_VER        0

static hsvc_info_t rfios_hsvc = {
        HSVC_REV_1,
        NULL,
        RF_PERF_COUNTER_GROUP_ID,
        RF_REQ_MAJOR_VER,
        RF_REQ_MINOR_VER,
        MODULE_NAME     /* Passed in as a #define from Makefile */
};

static uint64_t rfios_sup_minor;

iospc_grp_t **
rfios_bind_group(void)
{
        int rval;

        if ((rval = hsvc_register(&rfios_hsvc, &rfios_sup_minor)) !=
            DDI_SUCCESS) {
                IOSPC_DBG1("%s: Could not hsvc_register: %d\n",
                    MODULE_NAME, rval);

                return (NULL);
        }

        return ((iospc_grp_t **)&rfios_leaf_grps);
}

void
rfios_unbind_group(void)
{
        (void) hsvc_unregister(&rfios_hsvc);
}

int
rfios_access_init(iospc_t *iospc_p, iospc_ksinfo_t *ksinfo_p)
{
        uint32_t regprop[4];
        int len;
        cntr_handle_t   iospc_handle;

        IOSPC_DBG2("rfios_access_init: iospc_p=%p\n", (void *)iospc_p);

        len = sizeof (regprop);
        if (ddi_getlongprop_buf(DDI_DEV_T_ANY, iospc_p->iospc_dip,
            DDI_PROP_DONTPASS, "reg", (caddr_t)regprop, &len) !=
            DDI_SUCCESS) {
                return (FAILURE);
        }

        iospc_handle = (regprop[0] & 0xfffffff);
        ksinfo_p->arg = (void *)iospc_handle;

        return (SUCCESS);

}

int
rfios_access_fini(iospc_t *iospc_p, iospc_ksinfo_t *ksinfo_p)
{
        IOSPC_DBG2("rfios_access_fini: iospc_p=%p ksinfo_p=%p\n",
            (void *)iospc_p, (void *)ksinfo_p);
        return (SUCCESS);
}

int
rfios_access_hv(iospc_t *iospc_p, void *arg, int op, int regid, uint64_t *data)
{
        cntr_handle_t   iospc_handle = (cntr_handle_t)arg;

        if (op == IOSPC_REG_READ) {
                if (rfiospc_get_perfreg(iospc_handle, regid, data) != H_EOK) {
                        IOSPC_DBG2("rfios_access_hv: READ handle=%p regid=%x "
                            "- Failed\n", (void *)iospc_p, regid);
                        return (FAILURE);
                }

                IOSPC_DBG2("rfios_access_hv: READ handle=%p regid=%x "
                    "data=%lx\n", (void *)iospc_p, regid, *data);

        } else { /* IOSPC_REG_WRITE */
                if (rfiospc_set_perfreg(iospc_handle, regid, *data) != H_EOK) {
                        IOSPC_DBG2("rfios_access_hv: READ handle=%p regid=%x "
                            "- Failed\n", (void *)iospc_p, regid);
                        return (FAILURE);
                }

                IOSPC_DBG2("rfios_access_hv: WRITE  handle=%p regid=%x "
                    "data=%lx\n", (void *)iospc_p, regid, *data);
        }

        return (SUCCESS);
}