pcix.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* 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
* 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 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/types.h>
#include <sys/kmem.h>
#include <sys/async.h>
#include <sys/sysmacros.h>
#include <sys/sunddi.h>
#include <sys/sunndi.h>
#include <sys/ddi_impldefs.h>
#include <sys/ddi_implfuncs.h>
#include <sys/pci/pci_obj.h>
#include <sys/pci.h>
/*LINTLIBRARY*/
static uint16_t
pcix_get_pcix_cap(ddi_acc_handle_t handle)
{
ushort_t caps_ptr, cap;
/*
* Walk the Capabilities List and locate
* the PCI-X Capability.
*/
if (pci_config_get16(handle, PCI_CONF_STAT) & PCI_STAT_CAP)
caps_ptr = pci_config_get8(handle, PCI_CONF_CAP_PTR);
else
caps_ptr = PCI_CAP_NEXT_PTR_NULL;
while (caps_ptr != PCI_CAP_NEXT_PTR_NULL) {
cap = pci_config_get8(handle, caps_ptr);
if (cap == PCI_CAP_ID_PCIX)
return (caps_ptr);
caps_ptr = pci_config_get8(handle, caps_ptr + PCI_CAP_NEXT_PTR);
}
return (0);
}
void
pcix_set_cmd_reg(dev_info_t *child, uint16_t value)
{
uint16_t pcix_cap_offset, pcix_cmd;
ddi_acc_handle_t handle;
if (pci_config_setup(child, &handle) != DDI_SUCCESS)
return;
/*
* Only modify the Command Register of non-bridge functions.
*/
if ((pci_config_get8(handle, PCI_CONF_HEADER) &
PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) {
pci_config_teardown(&handle);
return;
}
pcix_cap_offset = pcix_get_pcix_cap(handle);
DEBUG1(DBG_INIT_CLD, child,
"pcix_set_cmd_reg: pcix_cap_offset = %x\n", pcix_cap_offset);
if (pcix_cap_offset) {
/*
* Read the PCI-X Command Register.
*/
pcix_cmd = pci_config_get16(handle, (pcix_cap_offset + 2));
DEBUG1(DBG_INIT_CLD, child,
"pcix_set_cmd_reg: PCI-X CMD "
"Register (Before) %x\n", pcix_cmd);
pcix_cmd &= ~(0x1f << 2); /* clear bits 6-2 */
pcix_cmd |= value;
DEBUG1(DBG_INIT_CLD, child,
"pcix_set_cmd_reg: PCI-X CMD "
"Register (After) %x\n", pcix_cmd);
pci_config_put16(handle, (pcix_cap_offset + 2), pcix_cmd);
}
pci_config_teardown(&handle);
}