pci_cap.c revision cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0
27255037bba8df933008f7bd2112201bef2e2429pjha/*
27255037bba8df933008f7bd2112201bef2e2429pjha * CDDL HEADER START
27255037bba8df933008f7bd2112201bef2e2429pjha *
27255037bba8df933008f7bd2112201bef2e2429pjha * The contents of this file are subject to the terms of the
27255037bba8df933008f7bd2112201bef2e2429pjha * Common Development and Distribution License (the "License").
27255037bba8df933008f7bd2112201bef2e2429pjha * You may not use this file except in compliance with the License.
27255037bba8df933008f7bd2112201bef2e2429pjha *
27255037bba8df933008f7bd2112201bef2e2429pjha * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
27255037bba8df933008f7bd2112201bef2e2429pjha * or http://www.opensolaris.org/os/licensing.
27255037bba8df933008f7bd2112201bef2e2429pjha * See the License for the specific language governing permissions
27255037bba8df933008f7bd2112201bef2e2429pjha * and limitations under the License.
27255037bba8df933008f7bd2112201bef2e2429pjha *
27255037bba8df933008f7bd2112201bef2e2429pjha * When distributing Covered Code, include this CDDL HEADER in each
27255037bba8df933008f7bd2112201bef2e2429pjha * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
27255037bba8df933008f7bd2112201bef2e2429pjha * If applicable, add the following below this CDDL HEADER, with the
27255037bba8df933008f7bd2112201bef2e2429pjha * fields enclosed by brackets "[]" replaced with your own identifying
27255037bba8df933008f7bd2112201bef2e2429pjha * information: Portions Copyright [yyyy] [name of copyright owner]
27255037bba8df933008f7bd2112201bef2e2429pjha *
27255037bba8df933008f7bd2112201bef2e2429pjha * CDDL HEADER END
27255037bba8df933008f7bd2112201bef2e2429pjha */
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha#include <sys/note.h>
27255037bba8df933008f7bd2112201bef2e2429pjha#include <sys/conf.h>
27255037bba8df933008f7bd2112201bef2e2429pjha#include <sys/debug.h>
27255037bba8df933008f7bd2112201bef2e2429pjha#include <sys/sunddi.h>
27255037bba8df933008f7bd2112201bef2e2429pjha#include <sys/pci.h>
27255037bba8df933008f7bd2112201bef2e2429pjha#include <sys/pcie.h>
27255037bba8df933008f7bd2112201bef2e2429pjha#include <sys/bitmap.h>
27255037bba8df933008f7bd2112201bef2e2429pjha#include <sys/autoconf.h>
27255037bba8df933008f7bd2112201bef2e2429pjha#include <sys/sysmacros.h>
27255037bba8df933008f7bd2112201bef2e2429pjha#include <sys/pci_cap.h>
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha/*
fb66942fa6213bb169b433e06b0ed5dcced34b0dCasper H.S. Dik * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
27255037bba8df933008f7bd2112201bef2e2429pjha * Use is subject to license terms.
27255037bba8df933008f7bd2112201bef2e2429pjha */
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha/*
27255037bba8df933008f7bd2112201bef2e2429pjha * Generic PCI Capabilites Interface for all pci platforms
27255037bba8df933008f7bd2112201bef2e2429pjha */
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha#ifdef DEBUG
27255037bba8df933008f7bd2112201bef2e2429pjhauint_t pci_cap_debug = 0;
27255037bba8df933008f7bd2112201bef2e2429pjha#endif
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha/* Cap Base Macro */
27255037bba8df933008f7bd2112201bef2e2429pjha#define PCI_CAP_BASE(h, id, base_p) (*base_p ? DDI_SUCCESS : \
27255037bba8df933008f7bd2112201bef2e2429pjha (id ? PCI_CAP_LOCATE(h, id, base_p) : DDI_FAILURE))
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha/*
27255037bba8df933008f7bd2112201bef2e2429pjha * pci_cap_probe: returns the capid and base based upon a given index
27255037bba8df933008f7bd2112201bef2e2429pjha */
27255037bba8df933008f7bd2112201bef2e2429pjhaint
27255037bba8df933008f7bd2112201bef2e2429pjhapci_cap_probe(ddi_acc_handle_t h, uint16_t index,
27255037bba8df933008f7bd2112201bef2e2429pjha uint32_t *id_p, uint16_t *base_p)
27255037bba8df933008f7bd2112201bef2e2429pjha{
27255037bba8df933008f7bd2112201bef2e2429pjha int i, search_ext = 0;
27255037bba8df933008f7bd2112201bef2e2429pjha uint16_t base, pcix_cmd, status;
27255037bba8df933008f7bd2112201bef2e2429pjha uint32_t id, xcaps_hdr; /* Extended Caps Header Word */
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha status = pci_config_get16(h, PCI_CONF_STAT);
27255037bba8df933008f7bd2112201bef2e2429pjha
dc5d169b4bfc1a6993578ef34dae678076fd19fbpjha if (status == PCI_CAP_EINVAL16 || !(status & PCI_STAT_CAP))
27255037bba8df933008f7bd2112201bef2e2429pjha return (DDI_FAILURE);
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha /* PCIE and PCIX Version 2 contain Extended Config Space */
27255037bba8df933008f7bd2112201bef2e2429pjha for (i = 0, base = pci_config_get8(h, PCI_CONF_CAP_PTR);
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases base && i < index; base = pci_config_get8(h, base
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases + PCI_CAP_NEXT_PTR), i++) {
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha if ((id = pci_config_get8(h, base)) == 0xff)
27255037bba8df933008f7bd2112201bef2e2429pjha break;
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha if (id == PCI_CAP_ID_PCI_E)
27255037bba8df933008f7bd2112201bef2e2429pjha search_ext = 1;
27255037bba8df933008f7bd2112201bef2e2429pjha else if (id == PCI_CAP_ID_PCIX) {
27255037bba8df933008f7bd2112201bef2e2429pjha if ((pcix_cmd = pci_config_get16(h, base +
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases PCI_PCIX_COMMAND)) != PCI_CAP_EINVAL16)
27255037bba8df933008f7bd2112201bef2e2429pjha continue;
27255037bba8df933008f7bd2112201bef2e2429pjha if ((pcix_cmd & PCI_PCIX_VER_MASK) == PCI_PCIX_VER_2)
27255037bba8df933008f7bd2112201bef2e2429pjha search_ext = 1;
27255037bba8df933008f7bd2112201bef2e2429pjha }
27255037bba8df933008f7bd2112201bef2e2429pjha }
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha if (base && i == index) {
27255037bba8df933008f7bd2112201bef2e2429pjha if ((id = pci_config_get8(h, base)) != 0xff)
27255037bba8df933008f7bd2112201bef2e2429pjha goto found;
27255037bba8df933008f7bd2112201bef2e2429pjha }
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha if (!search_ext)
27255037bba8df933008f7bd2112201bef2e2429pjha return (DDI_FAILURE);
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha for (base = PCIE_EXT_CAP; base && i < index; i++) {
dc5d169b4bfc1a6993578ef34dae678076fd19fbpjha if ((xcaps_hdr = pci_config_get32(h, base)) == PCI_CAP_EINVAL32)
27255037bba8df933008f7bd2112201bef2e2429pjha break;
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha id = (xcaps_hdr >> PCIE_EXT_CAP_ID_SHIFT)
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases & PCIE_EXT_CAP_ID_MASK;
27255037bba8df933008f7bd2112201bef2e2429pjha base = (xcaps_hdr >> PCIE_EXT_CAP_NEXT_PTR_SHIFT)
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases & PCIE_EXT_CAP_NEXT_PTR_MASK;
27255037bba8df933008f7bd2112201bef2e2429pjha }
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha if (!base || i < index)
27255037bba8df933008f7bd2112201bef2e2429pjha return (DDI_FAILURE);
27255037bba8df933008f7bd2112201bef2e2429pjha
dc5d169b4bfc1a6993578ef34dae678076fd19fbpjha if ((xcaps_hdr = pci_config_get32(h, base)) == PCI_CAP_EINVAL32)
27255037bba8df933008f7bd2112201bef2e2429pjha return (DDI_FAILURE);
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha id = ((xcaps_hdr >> PCIE_EXT_CAP_ID_SHIFT) & PCIE_EXT_CAP_ID_MASK) |
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases PCI_CAP_XCFG_FLAG;
27255037bba8df933008f7bd2112201bef2e2429pjhafound:
27255037bba8df933008f7bd2112201bef2e2429pjha PCI_CAP_DBG("pci_cap_probe: index=%x, id=%x, base=%x\n",
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases index, id, base);
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha *id_p = id;
27255037bba8df933008f7bd2112201bef2e2429pjha *base_p = base;
27255037bba8df933008f7bd2112201bef2e2429pjha return (DDI_SUCCESS);
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha}
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha/*
27255037bba8df933008f7bd2112201bef2e2429pjha * pci_lcap_locate: Helper function locates a base in conventional config space.
27255037bba8df933008f7bd2112201bef2e2429pjha */
27255037bba8df933008f7bd2112201bef2e2429pjhaint
27255037bba8df933008f7bd2112201bef2e2429pjhapci_lcap_locate(ddi_acc_handle_t h, uint8_t id, uint16_t *base_p)
27255037bba8df933008f7bd2112201bef2e2429pjha{
fb66942fa6213bb169b433e06b0ed5dcced34b0dCasper H.S. Dik uint8_t header;
27255037bba8df933008f7bd2112201bef2e2429pjha uint16_t status, base;
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha status = pci_config_get16(h, PCI_CONF_STAT);
27255037bba8df933008f7bd2112201bef2e2429pjha
dc5d169b4bfc1a6993578ef34dae678076fd19fbpjha if (status == PCI_CAP_EINVAL16 || !(status & PCI_STAT_CAP))
27255037bba8df933008f7bd2112201bef2e2429pjha return (DDI_FAILURE);
27255037bba8df933008f7bd2112201bef2e2429pjha
fb66942fa6213bb169b433e06b0ed5dcced34b0dCasper H.S. Dik header = pci_config_get8(h, PCI_CONF_HEADER);
fb66942fa6213bb169b433e06b0ed5dcced34b0dCasper H.S. Dik switch (header & PCI_HEADER_TYPE_M) {
fb66942fa6213bb169b433e06b0ed5dcced34b0dCasper H.S. Dik case PCI_HEADER_ZERO:
fb66942fa6213bb169b433e06b0ed5dcced34b0dCasper H.S. Dik base = PCI_CONF_CAP_PTR;
fb66942fa6213bb169b433e06b0ed5dcced34b0dCasper H.S. Dik break;
fb66942fa6213bb169b433e06b0ed5dcced34b0dCasper H.S. Dik case PCI_HEADER_PPB:
fb66942fa6213bb169b433e06b0ed5dcced34b0dCasper H.S. Dik base = PCI_BCNF_CAP_PTR;
fb66942fa6213bb169b433e06b0ed5dcced34b0dCasper H.S. Dik break;
fb66942fa6213bb169b433e06b0ed5dcced34b0dCasper H.S. Dik case PCI_HEADER_CARDBUS:
fb66942fa6213bb169b433e06b0ed5dcced34b0dCasper H.S. Dik base = PCI_CBUS_CAP_PTR;
fb66942fa6213bb169b433e06b0ed5dcced34b0dCasper H.S. Dik break;
fb66942fa6213bb169b433e06b0ed5dcced34b0dCasper H.S. Dik default:
fb66942fa6213bb169b433e06b0ed5dcced34b0dCasper H.S. Dik cmn_err(CE_WARN, "%s: unexpected pci header type:%x",
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases __func__, header);
fb66942fa6213bb169b433e06b0ed5dcced34b0dCasper H.S. Dik return (DDI_FAILURE);
fb66942fa6213bb169b433e06b0ed5dcced34b0dCasper H.S. Dik }
fb66942fa6213bb169b433e06b0ed5dcced34b0dCasper H.S. Dik
fb66942fa6213bb169b433e06b0ed5dcced34b0dCasper H.S. Dik for (base = pci_config_get8(h, base); base;
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases base = pci_config_get8(h, base + PCI_CAP_NEXT_PTR)) {
27255037bba8df933008f7bd2112201bef2e2429pjha if (pci_config_get8(h, base) == id) {
27255037bba8df933008f7bd2112201bef2e2429pjha *base_p = base;
27255037bba8df933008f7bd2112201bef2e2429pjha return (DDI_SUCCESS);
27255037bba8df933008f7bd2112201bef2e2429pjha }
27255037bba8df933008f7bd2112201bef2e2429pjha }
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha *base_p = PCI_CAP_NEXT_PTR_NULL;
27255037bba8df933008f7bd2112201bef2e2429pjha return (DDI_FAILURE);
27255037bba8df933008f7bd2112201bef2e2429pjha}
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha/*
27255037bba8df933008f7bd2112201bef2e2429pjha * pci_xcap_locate: Helper function locates a base in extended config space.
27255037bba8df933008f7bd2112201bef2e2429pjha */
27255037bba8df933008f7bd2112201bef2e2429pjhaint
27255037bba8df933008f7bd2112201bef2e2429pjhapci_xcap_locate(ddi_acc_handle_t h, uint16_t id, uint16_t *base_p)
27255037bba8df933008f7bd2112201bef2e2429pjha{
27255037bba8df933008f7bd2112201bef2e2429pjha uint16_t status, base;
27255037bba8df933008f7bd2112201bef2e2429pjha uint32_t xcaps_hdr;
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha status = pci_config_get16(h, PCI_CONF_STAT);
27255037bba8df933008f7bd2112201bef2e2429pjha
dc5d169b4bfc1a6993578ef34dae678076fd19fbpjha if (status == PCI_CAP_EINVAL16 || !(status & PCI_STAT_CAP))
27255037bba8df933008f7bd2112201bef2e2429pjha return (DDI_FAILURE);
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha for (base = PCIE_EXT_CAP; base; base = (xcaps_hdr >>
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases PCIE_EXT_CAP_NEXT_PTR_SHIFT) & PCIE_EXT_CAP_NEXT_PTR_MASK) {
27255037bba8df933008f7bd2112201bef2e2429pjha
dc5d169b4bfc1a6993578ef34dae678076fd19fbpjha if ((xcaps_hdr = pci_config_get32(h, base)) == PCI_CAP_EINVAL32)
27255037bba8df933008f7bd2112201bef2e2429pjha break;
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha if (((xcaps_hdr >> PCIE_EXT_CAP_ID_SHIFT) &
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases PCIE_EXT_CAP_ID_MASK) == id) {
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases *base_p = base;
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases return (DDI_SUCCESS);
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases }
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases }
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases *base_p = PCI_CAP_NEXT_PTR_NULL;
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases return (DDI_FAILURE);
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases}
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases/*
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases * There can be multiple pci caps with a Hypertransport technology cap ID
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases * Each is distiguished by a type register in the upper half of the cap
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases * header (the "command" register part).
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases *
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases * This returns the location of a hypertransport capability whose upper
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases * 16-bits of the cap header matches <reg_val> after masking the value
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases * with <reg_mask>; if both <reg_mask> and <reg_val> are 0, it will return
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases * the first HT cap found
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases */
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayasesint
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayasespci_htcap_locate(ddi_acc_handle_t h, uint16_t reg_mask, uint16_t reg_val,
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases uint16_t *base_p)
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases{
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases uint8_t header;
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases uint16_t status, base;
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases status = pci_config_get16(h, PCI_CONF_STAT);
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases if (status == PCI_CAP_EINVAL16 || !(status & PCI_STAT_CAP))
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases return (DDI_FAILURE);
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases header = pci_config_get8(h, PCI_CONF_HEADER);
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases switch (header & PCI_HEADER_TYPE_M) {
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases case PCI_HEADER_ZERO:
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases base = PCI_CONF_CAP_PTR;
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases break;
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases case PCI_HEADER_PPB:
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases base = PCI_BCNF_CAP_PTR;
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases break;
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases default:
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases cmn_err(CE_WARN, "%s: unexpected pci header type:%x",
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases __func__, header);
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases return (DDI_FAILURE);
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases }
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases for (base = pci_config_get8(h, base); base;
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases base = pci_config_get8(h, base + PCI_CAP_NEXT_PTR)) {
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases if (pci_config_get8(h, base) == PCI_CAP_ID_HT &&
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases (pci_config_get16(h, base + PCI_CAP_ID_REGS_OFF) &
cb7ea99db394f3bd5f4a6c6bf58c8c52df3508f0Jimmy Vetayases reg_mask) == reg_val) {
27255037bba8df933008f7bd2112201bef2e2429pjha *base_p = base;
27255037bba8df933008f7bd2112201bef2e2429pjha return (DDI_SUCCESS);
27255037bba8df933008f7bd2112201bef2e2429pjha }
27255037bba8df933008f7bd2112201bef2e2429pjha }
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha *base_p = PCI_CAP_NEXT_PTR_NULL;
27255037bba8df933008f7bd2112201bef2e2429pjha return (DDI_FAILURE);
27255037bba8df933008f7bd2112201bef2e2429pjha}
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha/*
27255037bba8df933008f7bd2112201bef2e2429pjha * pci_cap_get: This function uses the base or capid to get a byte, word,
27255037bba8df933008f7bd2112201bef2e2429pjha * or dword. If access by capid is requested, the function uses the capid to
27255037bba8df933008f7bd2112201bef2e2429pjha * locate the base. Access by a base results in better performance
27255037bba8df933008f7bd2112201bef2e2429pjha * because no cap list traversal is required.
27255037bba8df933008f7bd2112201bef2e2429pjha */
27255037bba8df933008f7bd2112201bef2e2429pjhauint32_t
3c4226f98775d47a05fa88f9f72479f1a250eaa5pjhapci_cap_get(ddi_acc_handle_t h, pci_cap_config_size_t size,
27255037bba8df933008f7bd2112201bef2e2429pjha uint32_t id, uint16_t base, uint16_t offset)
27255037bba8df933008f7bd2112201bef2e2429pjha{
27255037bba8df933008f7bd2112201bef2e2429pjha uint32_t data;
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha if (PCI_CAP_BASE(h, id, &base) != DDI_SUCCESS)
dc5d169b4bfc1a6993578ef34dae678076fd19fbpjha return (PCI_CAP_EINVAL32);
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha /*
911fc2e57de04c6f6a4da8afebbafbcc3e3c4ee5pjha * Each access to a PCI Configuration Space should be checked
911fc2e57de04c6f6a4da8afebbafbcc3e3c4ee5pjha * by the calling function. A returned value of the 2's complement
911fc2e57de04c6f6a4da8afebbafbcc3e3c4ee5pjha * of -1 indicates that either the device is offlined or it does not
911fc2e57de04c6f6a4da8afebbafbcc3e3c4ee5pjha * exist.
27255037bba8df933008f7bd2112201bef2e2429pjha */
27255037bba8df933008f7bd2112201bef2e2429pjha offset += base;
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha switch (size) {
27255037bba8df933008f7bd2112201bef2e2429pjha case PCI_CAP_CFGSZ_8:
911fc2e57de04c6f6a4da8afebbafbcc3e3c4ee5pjha data = pci_config_get8(h, offset);
27255037bba8df933008f7bd2112201bef2e2429pjha break;
27255037bba8df933008f7bd2112201bef2e2429pjha case PCI_CAP_CFGSZ_16:
911fc2e57de04c6f6a4da8afebbafbcc3e3c4ee5pjha data = pci_config_get16(h, offset);
27255037bba8df933008f7bd2112201bef2e2429pjha break;
27255037bba8df933008f7bd2112201bef2e2429pjha case PCI_CAP_CFGSZ_32:
911fc2e57de04c6f6a4da8afebbafbcc3e3c4ee5pjha data = pci_config_get32(h, offset);
27255037bba8df933008f7bd2112201bef2e2429pjha break;
27255037bba8df933008f7bd2112201bef2e2429pjha default:
dc5d169b4bfc1a6993578ef34dae678076fd19fbpjha data = PCI_CAP_EINVAL32;
27255037bba8df933008f7bd2112201bef2e2429pjha }
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha PCI_CAP_DBG("pci_cap_get: %p[x%x]=x%x\n", (void *)h, offset, data);
27255037bba8df933008f7bd2112201bef2e2429pjha return (data);
27255037bba8df933008f7bd2112201bef2e2429pjha}
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha/*
27255037bba8df933008f7bd2112201bef2e2429pjha * pci_cap_put: This function uses the caps ptr or capid to put a byte, word,
27255037bba8df933008f7bd2112201bef2e2429pjha * or dword. If access by capid is requested, the function uses the capid to
27255037bba8df933008f7bd2112201bef2e2429pjha * locate the base. Access by base results in better performance
27255037bba8df933008f7bd2112201bef2e2429pjha * because no cap list traversal is required.
27255037bba8df933008f7bd2112201bef2e2429pjha */
27255037bba8df933008f7bd2112201bef2e2429pjhaint
3c4226f98775d47a05fa88f9f72479f1a250eaa5pjhapci_cap_put(ddi_acc_handle_t h, pci_cap_config_size_t size,
27255037bba8df933008f7bd2112201bef2e2429pjha uint32_t id, uint16_t base, uint16_t offset,
27255037bba8df933008f7bd2112201bef2e2429pjha uint32_t data)
27255037bba8df933008f7bd2112201bef2e2429pjha{
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha /*
27255037bba8df933008f7bd2112201bef2e2429pjha * use the pci_config_size_t to switch for the appropriate read
27255037bba8df933008f7bd2112201bef2e2429pjha */
27255037bba8df933008f7bd2112201bef2e2429pjha if (PCI_CAP_BASE(h, id, &base) != DDI_SUCCESS)
27255037bba8df933008f7bd2112201bef2e2429pjha return (DDI_FAILURE);
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha offset += base;
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha switch (size) {
27255037bba8df933008f7bd2112201bef2e2429pjha case PCI_CAP_CFGSZ_8:
27255037bba8df933008f7bd2112201bef2e2429pjha pci_config_put8(h, offset, data);
27255037bba8df933008f7bd2112201bef2e2429pjha break;
27255037bba8df933008f7bd2112201bef2e2429pjha case PCI_CAP_CFGSZ_16:
27255037bba8df933008f7bd2112201bef2e2429pjha pci_config_put16(h, offset, data);
27255037bba8df933008f7bd2112201bef2e2429pjha break;
27255037bba8df933008f7bd2112201bef2e2429pjha case PCI_CAP_CFGSZ_32:
27255037bba8df933008f7bd2112201bef2e2429pjha pci_config_put32(h, offset, data);
27255037bba8df933008f7bd2112201bef2e2429pjha break;
27255037bba8df933008f7bd2112201bef2e2429pjha default:
27255037bba8df933008f7bd2112201bef2e2429pjha return (DDI_FAILURE);
27255037bba8df933008f7bd2112201bef2e2429pjha }
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha PCI_CAP_DBG("pci_cap_put: data=%x\n", data);
27255037bba8df933008f7bd2112201bef2e2429pjha return (DDI_SUCCESS);
27255037bba8df933008f7bd2112201bef2e2429pjha}
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha/*
27255037bba8df933008f7bd2112201bef2e2429pjha * Cache the entire Cap Structure. The caller is required to allocate and free
27255037bba8df933008f7bd2112201bef2e2429pjha * buffer.
27255037bba8df933008f7bd2112201bef2e2429pjha */
27255037bba8df933008f7bd2112201bef2e2429pjhaint
27255037bba8df933008f7bd2112201bef2e2429pjhapci_cap_read(ddi_acc_handle_t h, uint32_t id, uint16_t base,
27255037bba8df933008f7bd2112201bef2e2429pjha uint32_t *buf_p, uint32_t nwords)
27255037bba8df933008f7bd2112201bef2e2429pjha{
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha int i;
27255037bba8df933008f7bd2112201bef2e2429pjha uint32_t *ptr;
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha ASSERT(nwords < 1024);
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha if (PCI_CAP_BASE(h, id, &base) != DDI_SUCCESS)
27255037bba8df933008f7bd2112201bef2e2429pjha return (DDI_FAILURE);
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha for (ptr = buf_p, i = 0; i < nwords; i++, base += 4) {
dc5d169b4bfc1a6993578ef34dae678076fd19fbpjha if ((*ptr++ = pci_config_get32(h, base)) == PCI_CAP_EINVAL32)
27255037bba8df933008f7bd2112201bef2e2429pjha return (DDI_FAILURE);
27255037bba8df933008f7bd2112201bef2e2429pjha }
27255037bba8df933008f7bd2112201bef2e2429pjha
27255037bba8df933008f7bd2112201bef2e2429pjha return (DDI_SUCCESS);
27255037bba8df933008f7bd2112201bef2e2429pjha}