/*
* 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
* 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 (c) 2009, Intel Corporation.
* All rights reserved.
*/
/*
* PCI device ID for supported hardware.
* For memory controller devices in Intel 5000/7300 series chipset, PCI vendor
* id and PCI device id is read only, PCI subvendor id and PCI subsystem id is
* write-once. So we could only rely on PCI vendor id and PCI device id here.
* For all PCI functions (0,1,2,3) in device 0x10 on bus 0, they will have the
* same PCI (vendor_id, device_id, subvendor_id, subsystem_id, class_id).
* We only need to access PCI device (0, 0x10, 1), all other PCI functions will
* be filtered out by unit address.
*/
static struct fipe_pci_id {
char *unitaddr;
} fipe_mc_pciids[] = {
{ 0x8086, 0x25f0, 0xffff, 0xffff, "10,1" }, /* Intel 5000P/V/X/Z */
{ 0x8086, 0x360c, 0xffff, 0xffff, "10,1" } /* Intel 7300 NB */
};
/*ARGSUSED*/
static int
{
return (EINVAL);
}
return (0);
}
/*ARGSUSED*/
static int
{
return (0);
}
/*ARGSUSED*/
static int
int *rvalp)
{
int rc = 0;
/* First check permission. */
if (secpolicy_power_mgmt(credp) != 0) {
return (EPERM);
}
switch (cmd) {
case FIPE_IOCTL_START:
} else {
rc = fipe_start();
}
break;
case FIPE_IOCTL_STOP:
} else {
}
break;
case FIPE_IOCTL_GET_PMPOLICY:
} else {
policy = fipe_get_pmpolicy();
}
break;
case FIPE_IOCTL_SET_PMPOLICY:
} else {
}
break;
default:
break;
}
return (rc);
}
/*ARGSUSED*/
static int
{
switch (infocmd) {
case DDI_INFO_DEVT2DEVINFO:
if (fipe_drv_dip != NULL) {
*result = fipe_drv_dip;
return (DDI_SUCCESS);
} else {
return (DDI_FAILURE);
}
case DDI_INFO_DEVT2INSTANCE:
if (fipe_drv_dip != NULL) {
return (DDI_SUCCESS);
} else {
return (DDI_FAILURE);
}
default:
return (DDI_FAILURE);
}
}
/* Validate whether it's supported hardware. */
static int
{
char *unitaddr;
/* Get device unit address, it's "devid,funcid" in hexadecimal. */
return (-1);
}
return (-1);
}
/* Validate device. */
i < sizeof (fipe_mc_pciids) / sizeof (fipe_mc_pciids[0]);
i++, ip++) {
rc = 0;
break;
}
}
return (rc);
}
static int
{
char *ptr;
switch (cmd) {
case DDI_ATTACH:
/* Check whether it has been disabled by user. */
fipe_allow_attach = 0;
}
}
if (fipe_allow_attach == 0) {
"fipe: driver has been disabled by user.");
ignore = 1;
break;
}
/* Filter out unwanted PCI functions. */
break;
/* There should be only one MC device in system. */
} else if (fipe_drv_dip != NULL) {
"!fipe: more than one hardware instances found.");
break;
}
fipe_drv_dip = dip;
/* Initialize and start power management subsystem. */
if (fipe_init(fipe_drv_dip) != 0) {
fipe_drv_dip = NULL;
break;
} else if (fipe_start() != 0) {
(void) fipe_fini();
fipe_drv_dip = NULL;
break;
}
/* Ignore error from creating minor node. */
"ddi_mem_pm", 0) != DDI_SUCCESS) {
"?fipe: failed to create device minor node.\n");
}
rc = DDI_SUCCESS;
break;
case DDI_RESUME:
if (fipe_resume() == 0) {
rc = DDI_SUCCESS;
}
break;
default:
break;
}
}
return (rc);
}
/*ARGSUSED*/
static int
{
switch (cmd) {
case DDI_DETACH:
break;
}
if (fipe_stop() != 0) {
break;
} else if (fipe_fini() != 0) {
(void) fipe_start();
break;
}
fipe_drv_dip = NULL;
rc = DDI_SUCCESS;
break;
case DDI_SUSPEND:
if (fipe_suspend() == 0) {
rc = DDI_SUCCESS;
}
break;
default:
break;
}
if (rc != DDI_SUCCESS) {
}
return (rc);
}
static int
{
if (dip != fipe_drv_dip) {
return (DDI_SUCCESS);
}
/* Quiesce hardware by stopping power management subsystem. */
if (fipe_suspend() != 0) {
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
nodev, /* not a block driver */
nodev, /* no print routine */
nodev, /* no dump routine */
nodev, /* no read routine */
nodev, /* no write routine */
nodev, /* no devmap routine */
nodev, /* no mmap routine */
nodev, /* no segmap routine */
nochpoll, /* no chpoll routine */
0, /* not a STREAMS driver */
};
DEVO_REV, /* devo_rev */
0, /* devo_refcnt */
fipe_getinfo, /* devo_getinfo */
nulldev, /* devo_identify */
nulldev, /* devo_probe */
fipe_attach, /* devo_attach */
fipe_detach, /* devo_detach */
nodev, /* devo_reset */
&fipe_cb_ops, /* devo_cb_ops */
NULL, /* devo_bus_ops */
NULL, /* devo_power */
&fipe_quiesce, /* devo_quiesce */
};
"Intel 5000/7300 memory controller driver",
};
(void *)&modldrv,
};
int
_init(void)
{
fipe_drv_dip = NULL;
return (mod_install(&modlinkage));
}
int
{
}
int
_fini(void)
{
int err;
fipe_drv_dip = NULL;
}
return (err);
}