vnex.c revision f3307d205c2ca89621e738ce08dfc06d4b121134
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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
* 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 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI" /* SVr4 5.0 */
#include <sys/ddi_impldefs.h>
#include <sys/autoconf.h>
#include <sys/ddi_subrdefs.h>
#include <sys/nexusintr_impl.h>
#include <sys/machsystm.h>
#include <sys/ddi_intr_impl.h>
#include <sys/hypervisor_api.h>
static kmutex_t vnex_id_lock;
/*
* Vnex name to pil map
*/
typedef struct vnex_regspec {
struct vnex_pil_map {
};
/* vnex interrupt descriptor */
typedef struct vnex_id {
uint_t (*vid_handler)();
} vnex_id_t;
/* vnex interrupt descriptor list */
static vnex_id_t *vnex_id_list;
/*
* vnex interrupt descriptor list manipulation functions
*/
static struct vnex_pil_map vnex_name_to_pil[] = {
{"console", PIL_12},
{"fma", PIL_5},
{"echo", PIL_3},
{"loop", PIL_3},
{"sunmc", PIL_3},
{"sunvts", PIL_3},
{"explorer", PIL_3}
};
#define VNEX_MAX_DEVS (sizeof (vnex_name_to_pil) / \
sizeof (struct vnex_pil_map))
/*
* Config information
*/
static int
static struct bus_ops vnex_bus_ops = {
NULL, /* NO OP */
NULL, /* NO OP */
NULL, /* NO OP */
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL, /* (*bus_get_eventcookie)(); */
NULL, /* (*bus_add_eventcall)(); */
NULL, /* (*bus_remove_eventcall)(); */
NULL, /* (*bus_post_event)(); */
NULL, /* (*bus_intr_ctl)(); */
NULL, /* (*bus_config)(); */
NULL, /* (*bus_unconfig)(); */
NULL, /* (*bus_fm_init)(); */
NULL, /* (*bus_fm_fini)(); */
NULL, /* (*bus_fm_access_enter)(); */
NULL, /* (*bus_fm_access_fini)(); */
NULL, /* (*bus_power)(); */
vnex_intr_ops /* (*bus_intr_op)(); */
};
static struct dev_ops pseudo_ops = {
DEVO_REV, /* devo_rev, */
0, /* refcnt */
ddi_no_info, /* info */
nulldev, /* identify */
nulldev, /* probe */
vnex_attach, /* attach */
vnex_detach, /* detach */
nodev, /* reset */
(struct cb_ops *)0, /* driver operations */
&vnex_bus_ops, /* bus operations */
nulldev /* power */
};
/*
* Module linkage information for the kernel.
*/
&mod_driverops, /* Type of module. This one is a pseudo driver */
"sun4v virtual-devices nexus driver v%I%",
&pseudo_ops, /* driver ops */
};
static struct modlinkage modlinkage = {
};
int
_init(void)
{
return (mod_install(&modlinkage));
}
int
_fini(void)
{
return (mod_remove(&modlinkage));
}
int
{
}
/*ARGSUSED*/
void
vnex_intr_dist(void *arg)
{
int intr_state;
/*
* Don't do anything for disabled interrupts.
* vnex_enable_intr takes care of redistributing interrupts.
*/
continue;
cpuid = intr_dist_cpuid();
/*
* Make a best effort to wait for pending interrupts to finish.
* There is not much we can do if we timeout.
*/
while (!panicstr &&
"ino 0x%x pending: timedout\n",
break;
}
}
}
}
static int
{
switch (cmd) {
case DDI_ATTACH:
/*
* Intitialize interrupt descriptor list
* and mutex.
*/
vnex_id_list = NULL;
/*
* Add interrupt redistribution callback.
*/
return (DDI_SUCCESS);
case DDI_RESUME:
return (DDI_SUCCESS);
default:
return (DDI_FAILURE);
}
}
/*ARGSUSED*/
static int
{
switch (cmd) {
case DDI_DETACH:
return (DDI_FAILURE);
case DDI_SUSPEND:
return (DDI_SUCCESS);
default:
return (DDI_FAILURE);
}
}
static int
{
int reglen;
switch (ctlop) {
case DDI_CTLOPS_REPORTDEV:
return (DDI_FAILURE);
return (DDI_SUCCESS);
case DDI_CTLOPS_INITCHILD:
{
return (DDI_FAILURE);
return (DDI_SUCCESS);
}
case DDI_CTLOPS_UNINITCHILD:
{
return (DDI_SUCCESS);
}
/*
* These ops correspond to functions that "shouldn't" be called
* by a pseudo driver. So we whinge when we're called.
*/
case DDI_CTLOPS_DMAPMAPC:
case DDI_CTLOPS_REPORTINT:
case DDI_CTLOPS_REGSIZE:
{
return (DDI_SUCCESS);
}
case DDI_CTLOPS_NREGS:
{
return (DDI_FAILURE);
return (DDI_SUCCESS);
}
case DDI_CTLOPS_NINTRS:
case DDI_CTLOPS_SIDDEV:
case DDI_CTLOPS_SLAVEONLY:
case DDI_CTLOPS_AFFINITY:
case DDI_CTLOPS_IOMIN:
case DDI_CTLOPS_POKE:
case DDI_CTLOPS_PEEK:
case DDI_CTLOPS_INTR_HILEVEL:
case DDI_CTLOPS_XLATE_INTRS:
return (DDI_FAILURE);
/*
*/
default:
}
}
static int
{
int i;
for (i = 0; i < VNEX_MAX_DEVS; i++) {
name) == 0) {
return (vnex_name_to_pil[i].pil);
}
}
/*
* if not found pil is 0
*/
return (0);
}
static int
{
cpuid = intr_dist_cpuid();
return (DDI_FAILURE);
}
return (DDI_FAILURE);
}
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
static int
{
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
static int
{
®len) != DDI_SUCCESS) {
return (DDI_FAILURE);
}
/*
* get the sun4v config handle for this device
*/
/*
* call hv to get vihdl
*/
return (DDI_FAILURE);
/*
* Allocate a interrupt descriptor (id) with the
* the interrupt handler and append it to
* the id list.
*/
}
if (ret != DDI_SUCCESS) {
return (ret);
}
return (ret);
}
static int
{
int ret = DDI_SUCCESS;
return (ret);
}
static int
{
int ret = DDI_SUCCESS;
switch (intr_op) {
case DDI_INTROP_GETCAP:
*(int *)result = 0;
break;
case DDI_INTROP_ALLOC:
break;
case DDI_INTROP_GETPRI:
break;
case DDI_INTROP_FREE:
break;
case DDI_INTROP_SETPRI:
break;
case DDI_INTROP_ADDISR:
break;
case DDI_INTROP_REMISR:
break;
case DDI_INTROP_ENABLE:
break;
case DDI_INTROP_DISABLE:
break;
case DDI_INTROP_NINTRS:
case DDI_INTROP_NAVAIL:
break;
DDI_INTR_TYPE_FIXED : 0;
break;
default:
ret = DDI_ENOTSUP;
break;
}
return (ret);
}
{
return (vid_p);
}
{
return (vid_p);
}
}
return (NULL);
}
static void
{
}
static void
{
} else {
}
}
static void
{
if (vnex_id_list == NULL) {
return;
}
/*
* We always just add to the front of the list
*/
}
{
int res;
return (res);
}