sunpci.c revision 00d0963faf2e861a4aef6b1bf28f99a5b2b20755
/*
* 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 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/sysmacros.h>
#include <sys/pci_impl.h>
int
{
/* Check for fault management capabilities */
}
}
void
{
}
{
}
{
}
{
}
{
}
void
{
}
void
{
}
void
{
}
void
{
}
/*
* We need to separate the old interfaces from the new ones and leave them
* in here for a while. Previous versions of the OS defined the new interfaces
* to the old interfaces. This way we can fix things up so that we can
* eventually remove these interfaces.
* or earlier will actually have a reference to pci_config_getb in the binary.
*/
#ifdef _ILP32
{
}
{
}
{
}
{
}
void
{
}
void
{
}
void
{
}
void
{
}
#endif /* _ILP32 */
/*ARGSUSED*/
int
{
return (DDI_SUCCESS);
}
/*
* Note about saving and restoring config space.
* PCI devices have only upto 256 bytes of config space while PCI Express
* devices can have upto 4k config space. In case of PCI Express device,
* we save all 4k config space and restore it even if it doesn't make use
* of all 4k. But some devices don't respond to reads to non-existent
* registers within the config space. To avoid any panics, we use ddi_peek
* to do the reads. A bit mask is used to indicate which words of the
* config space are accessible. While restoring the config space, only those
* readable words are restored. We do all this in 32 bit size words.
*/
#define INDEX_SHIFT 3
#define BITMASK 0x7
/*
* Table below specifies the number of registers to be saved for each PCI
* capability. pci_generic_save saves the number of words specified in the
* table. Any special considerations will be taken care by the capability
* specific save function e.g. use pci_msi_save to save registers associated
* with MSI capability. PCI_UNKNOWN_SIZE indicates that number of registers
* to be saved is variable and will be determined by the specific save function.
* including read only registers. Regsiters are saved and restored in 32 bit
* size words.
*/
static pci_cap_entry_t pci_cap_table[] = {
/*
* {PCI_CAP_ID_cPCI_CRC, 0, NULL},
* {PCI_CAP_ID_VPD, 0, NULL},
* {PCI_CAP_ID_cPCI_HS, 0, NULL},
* {PCI_CAP_ID_PCI_HOTPLUG, 0, NULL},
* {PCI_CAP_ID_AGP_8X, 0, NULL},
* {PCI_CAP_ID_SECURE_DEV, 0, NULL},
*/
{PCI_CAP_NEXT_PTR_NULL, 0, NULL}
};
/*
* Save the configuration registers for cdip as a property
* so that it persists after detach/uninitchild.
*/
int
{
int ret;
int pcie = 0;
return (DDI_FAILURE);
}
/*
* Determine if it is a pci express device. If it is, save entire
* 4k config space treating it as a array of 32 bit integers.
* If it is not, do it in a usual PCI way.
*/
/*
* Walk the capabilities searching for pci express capability
*/
while (cap_ptr != PCI_CAP_NEXT_PTR_NULL) {
cap_ptr + PCI_CAP_ID);
if (cap_id == PCI_CAP_ID_PCI_E) {
pcie = 1;
break;
}
}
if (pcie) {
/* PCI express device. Can have data in all 4k space */
KM_SLEEP);
p = regbuf;
/*
* Allocate space for mask.
* mask size is 128 bytes (4096 / 4 / 8 )
*/
for (i = 0; i < (PCIE_CONF_HDR_SIZE / sizeof (uint32_t)); i++) {
(int32_t *)p) == DDI_SUCCESS) {
/* it is readable register. set the bit */
maskbuf[i >> INDEX_SHIFT] |=
}
p++;
}
maskbufsz)) != DDI_PROP_SUCCESS) {
"saving config space for %s@%d\n",
}
} else {
KM_SLEEP);
}
/*
* Allocate maximum space required for capability descriptions.
* The maximum number of capabilties saved is the number of
* capabilities listed in the pci_cap_table.
*/
sizeof (pci_config_header_state_t));
regbufsz = sizeof (pci_config_header_state_t) +
} else if (ncaps) {
ncaps * sizeof (pci_cap_save_desc_t));
if (ret != DDI_PROP_SUCCESS)
}
}
if (ret != DDI_PROP_SUCCESS)
return (DDI_FAILURE);
return (DDI_SUCCESS);
}
/*
* Saves registers associated with PCI capabilities.
* Returns number of 32 bit words saved.
* Number of capabilities saved is returned in ncapsp.
*/
static uint32_t
{
}
static uint32_t
{
*ncapsp = 0;
if (!xspace)
/*
* Walk the capabilities
*/
while (cap_ptr != PCI_CAP_NEXT_PTR_NULL) {
/* Search for this cap id in our table */
if (!xspace)
pci_cap_entp++;
/*
* If this cap id is not found in the table, there is nothing
* to save.
*/
continue;
if (pci_cap_entp->cap_save_func) {
cap_descp++;
words_saved += nwords;
(*ncapsp)++;
}
}
}
return (words_saved);
}
static void
{
int i;
for (i = 0; i < nwords; i++) {
regbuf++;
cap_ptr += 4;
}
}
static uint32_t
{
return (nwords);
}
/*ARGSUSED*/
static uint32_t
{
/* Figure out how many registers to be saved */
/* If 64 bit address capable add one word */
if (msi_ctrl & PCI_MSI_64BIT_MASK)
nwords++;
/* If per vector masking capable, add two more words */
if (msi_ctrl & PCI_MSI_PVM_MASK)
nwords += 2;
return (nwords);
}
/*ARGSUSED*/
static uint32_t
{
/* Figure out how many registers to be saved */
/* If it is version 1 or version 2, add 4 words */
nwords += 4;
return (nwords);
}
/*ARGSUSED*/
static uint32_t
{
return (0);
}
static void
{
/*
* Copy the power state bits from the PMCSR to our saved copy.
* This is to make sure that we don't change the D state when
* we restore config space of the device.
*/
(*saved_pmcsrp) &= ~PCI_PMCSR_STATE_MASK;
}
static void
{
int i, j;
for (i = 0; i < (elements / sizeof (pci_cap_save_desc_t)); i++) {
regbuf++;
offset += 4;
}
cap_descp++;
}
}
/*
* Restore config_regs from a single devinfo node.
*/
int
{
return (DDI_FAILURE);
}
goto restoreconfig_err;
}
/* pcie device and has 4k config space saved */
p = regbuf;
for (i = 0; i < PCIE_CONF_HDR_SIZE / sizeof (uint32_t); i++) {
/* If the word is readable then restore it */
if (maskbuf[i >> INDEX_SHIFT] &
p++;
}
}
} else {
return (DDI_FAILURE);
}
chs_p->chs_command);
}
/*
* PCI capability related regsiters are saved.
* Restore them based on the description.
*/
sizeof (pci_config_header_state_t));
}
}
/*
* Make sure registers are flushed
*/
}
return (DDI_SUCCESS);
}
return (DDI_FAILURE);
}