pcicfg.c revision a3282898e99eb4fd1912bf791254452bfd913d4b
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * CDDL HEADER START
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * The contents of this file are subject to the terms of the
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * Common Development and Distribution License, Version 1.0 only
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * (the "License"). You may not use this file except in compliance
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * with the License.
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * or http://www.opensolaris.org/os/licensing.
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * See the License for the specific language governing permissions
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * and limitations under the License.
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * When distributing Covered Code, include this CDDL HEADER in each
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * If applicable, add the following below this CDDL HEADER, with the
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * fields enclosed by brackets "[]" replaced with your own identifying
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * information: Portions Copyright [yyyy] [name of copyright owner]
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * CDDL HEADER END
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * Use is subject to license terms.
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#pragma ident "%Z%%M% %I% %E% SMI"
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * PCI configurator (pcicfg)
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * The following macro enables hack to differentiate QFE device from a
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * Freshchoice and hence assigned different drivers which are written
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * for the same silicon..Yikes.
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * ************************************************************************
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * *** Implementation specific local data structures/definitions. ***
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * ************************************************************************
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulknerstatic int pcicfg_start_devno = 0; /* for Debug only */
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#define PCICFG_HIADDR(n) ((uint32_t)(((uint64_t)(n) & 0xFFFFFFFF00000000)>> 32))
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#define PCICFG_LOADDR(n) ((uint32_t)((uint64_t)(n) & 0x00000000FFFFFFFF))
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#define PCICFG_LADDR(lo, hi) (((uint64_t)(hi) << 32) | (uint32_t)(lo))
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#define PCICFG_HIWORD(n) ((uint16_t)(((uint32_t)(n) & 0xFFFF0000)>> 16))
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#define PCICFG_LOWORD(n) ((uint16_t)((uint32_t)(n) & 0x0000FFFF))
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#define PCICFG_HIBYTE(n) ((uint8_t)(((uint16_t)(n) & 0xFF00)>> 8))
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#define PCICFG_LOBYTE(n) ((uint8_t)((uint16_t)(n) & 0x00FF))
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#define PCICFG_ROUND_UP(addr, gran) ((uintptr_t)((gran+addr-1)&(~(gran-1))))
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#define PCICFG_ROUND_DOWN(addr, gran) ((uintptr_t)((addr) & ~(gran-1)))
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#define PCICFG_RANGE_LEN 2 /* Number of range entries */
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * The following typedef is used to represent a
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * 1275 "bus-range" property of a PCI Bus node.
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * DAF - should be in generic include file...
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner dev_info_t *dip; /* Associated with the attach point */
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner uint64_t memory_base; /* Memory base for this attach point */
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner uint32_t io_base; /* I/O base for this attach point */
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner uint_t highest_bus; /* Highest bus seen on the probe */
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner hole_t mem_hole; /* Memory hole linked list. */
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner ndi_ra_request_t mem_req; /* allocator request for memory */
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner ndi_ra_request_t io_req; /* allocator request for I/O */
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * List of Indirect Config Map Devices. At least the intent of the
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner * design is to look for a device in this list during the configure
} pcicfg_indirect_map_devs[] = {
#if defined(DEBUG)
extern void prom_printf(const char *, ...);
int pcicfg_debug = 0;
#ifdef DEBUG
#ifdef _EFCODE_WORKAROUND
#ifndef _DONT_USE_1275_GENERIC_NAMES
#ifdef DEBUG
_init()
_fini(void)
int error;
if (error != 0) {
return (error);
int len;
int func;
int rv;
int circ;
return (PCICFG_FAILURE);
case PCICFG_FAILURE:
goto cleanup;
case PCICFG_NODEVICE:
goto cleanup;
goto cleanup;
int rc;
goto cleanup;
#ifdef _EFCODE_WORKAROUND
if (func == 0)
return (PCICFG_SUCCESS);
return (PCICFG_FAILURE);
static uint_t
int devno;
!= DDI_SUCCESS) {
return ((int)PCICFG_FAILURE);
return (rc);
return (rc);
return (rc);
return (rc);
max_devs = 0;
!= DDI_PROP_SUCCESS) {
!= DDI_SUCCESS) {
old_dev++;
&k) != DDI_PROP_SUCCESS) {
return (rc);
return (rc);
"pcicfg: cant unload ntbridge driver..children.\n");
return (rc);
return (PCICFG_FAILURE);
return (PCICFG_FAILURE);
return (PCICFG_SUCCESS);
return (PCICFG_FAILURE);
return (PCICFG_FAILURE);
#ifdef DEBUG
return (PCICFG_FAILURE);
#ifdef DEBUG
return (PCICFG_FAILURE);
return (PCICFG_SUCCESS);
return (PCICFG_FAILURE);
return (rc);
return (PCICFG_FAILURE);
!= DDI_PROP_SUCCESS) {
return (PCICFG_FAILURE);
!= DDI_SUCCESS) {
return (PCICFG_FAILURE);
return (PCICFG_NODEVICE);
static uint_t
&k) != DDI_PROP_SUCCESS) {
return (rc);
return (rc);
return (DDI_FAILURE);
rc);
return (rc);
static uint_t
return (rc);
len = sizeof (int);
return (rc);
return (DDI_SUCCESS);
#if defined(__sparc)
return (rc);
return (DDI_SUCCESS);
static uint_t
return (found);
return (found);
for (i = 0; i < acount; i++) {
return (found);
int func;
for (i = 0; i < func; i++) {
== NULL) {
return (PCICFG_FAILURE);
return (PCICFG_FAILURE);
return (PCICFG_FAILURE);
return (PCICFG_FAILURE);
return (PCICFG_SUCCESS);
return (PCICFG_FAILURE);
return (PCICFG_FAILURE);
return (PCICFG_SUCCESS);
static pcicfg_phdl_t *
return (entry);
static pcicfg_phdl_t *
KM_SLEEP);
return (new);
return (PCICFG_SUCCESS);
return (PCICFG_FAILURE);
return (PCICFG_FAILURE);
return (PCICFG_FAILURE);
return (PCICFG_FAILURE);
return (PCICFG_SUCCESS);
int length;
int rcount;
int offset;
int count;
return (DDI_WALK_TERMINATE);
!= DDI_SUCCESS) {
return (DDI_WALK_TERMINATE);
return (DDI_WALK_TERMINATE);
if (mem_residual > 0) {
if (io_residual > 0) {
return (DDI_WALK_TERMINATE);
return (DDI_WALK_TERMINATE);
return (DDI_WALK_PRUNECHILD);
return (DDI_WALK_TERMINATE);
for (i = 0; i < rcount; i++) {
return (DDI_WALK_TERMINATE);
return (DDI_WALK_TERMINATE);
return (DDI_WALK_CONTINUE);
int length;
int rcount;
int offset;
return (PCICFG_FAILURE);
return (PCICFG_FAILURE);
for (i = 0; i < rcount; i++) {
!= NDI_SUCCESS) {
return (PCICFG_FAILURE);
alen);
!= NDI_SUCCESS) {
return (PCICFG_FAILURE);
alen);
!= NDI_SUCCESS) {
return (PCICFG_FAILURE);
alen);
return (PCICFG_FAILURE);
return (PCICFG_FAILURE);
return (PCICFG_SUCCESS);
int circular;
if (parent)
if (mem_answer == 0) {
return (PCICFG_FAILURE);
return (PCICFG_FAILURE);
if (io_answer == 0) {
return (PCICFG_FAILURE);
return (PCICFG_FAILURE);
return (PCICFG_SUCCESS);
#ifdef DEBUG
* much memory was wasted/unallocated in bridge device's domain.
static uint64_t
count++;
} while (hole);
return (len);
while (hole) {
static uint64_t
KM_SLEEP);
actual_hole_start = 0;
} while (hole);
return (actual_hole_start);
length);
int length;
int rcount;
return (DDI_WALK_TERMINATE);
PCI_BCNF_SECBUS)) {
return (DDI_WALK_CONTINUE);
return (DDI_WALK_TERMINATE);
for (i = 0; i < rcount; i++) {
return (DDI_WALK_CONTINUE);
int length;
return (PCICFG_FAILURE);
case PCI_ADDR_IO:
!= NDI_SUCCESS) {
return (PCICFG_FAILURE);
case PCI_ADDR_MEM32:
case PCI_ADDR_MEM64:
!= NDI_SUCCESS) {
return (PCICFG_FAILURE);
&k) != DDI_PROP_SUCCESS) {
return (PCICFG_FAILURE);
return (PCICFG_FAILURE);
return (PCICFG_SUCCESS);
int length;
int acount;
return (PCICFG_FAILURE);
for (i = 0; i < acount; i++) {
return (PCICFG_FAILURE);
return (PCICFG_FAILURE);
return (PCICFG_FAILURE);
return (PCICFG_FAILURE);
return (PCICFG_SUCCESS);
return (PCICFG_FAILURE);
return (PCICFG_FAILURE);
return (PCICFG_FAILURE);
return (PCICFG_SUCCESS);
#ifndef _DONT_USE_1275_GENERIC_NAMES
return (NULL);
static dev_info_t *
int count;
int length;
int pci_dev;
int pci_func;
return (DDI_WALK_TERMINATE);
return (DDI_WALK_TERMINATE);
return (DDI_WALK_PRUNECHILD);
int alen;
switch (status) {
case DDI_PROP_SUCCESS:
case DDI_PROP_NO_MEMORY:
return (PCICFG_FAILURE);
sizeof (*newone)/sizeof (int));
return (PCICFG_SUCCESS);
return (PCICFG_SUCCESS);
int rlen;
switch (status) {
case DDI_PROP_SUCCESS:
case DDI_PROP_NO_MEMORY:
return (PCICFG_FAILURE);
sizeof (pcicfg_range_t)/sizeof (int))
!= DDI_SUCCESS) {
return (PCICFG_FAILURE);
return (PCICFG_SUCCESS);
return (PCICFG_SUCCESS);
int rlen;
switch (status) {
case DDI_PROP_SUCCESS:
case DDI_PROP_NO_MEMORY:
return (PCICFG_FAILURE);
return (PCICFG_FAILURE);
== PCI_BASE_TYPE_ALL) {
return (PCICFG_SUCCESS);
int ret;
return (ret);
return (ret);
return (ret);
return (ret);
return (ret);
return (ret);
return (ret);
return (ret);
return (ret);
return (ret);
PCI_CONF_SUBVENID)) != 0) {
return (ret);
PCI_CONF_SUBSYSID)) != 0) {
return (ret);
PCI_CONF_CACHE_LINESZ)) != 0) {
return (ret);
return (ret);
return (PCICFG_SUCCESS);
int ret;
return (ret);
return (ret);
return (ret);
return (PCICFG_SUCCESS);
int ret;
#ifndef _DONT_USE_1275_GENERIC_NAMES
char *name;
#ifdef _EFCODE_WORKAROUND
#ifndef _DONT_USE_1275_GENERIC_NAMES
#ifdef _DONT_USE_1275_GENERIC_NAMES
#ifdef _EFCODE_WORKAROUND
return (PCICFG_FAILURE);
#ifdef _EFCODE_WORKAROUND
DDI_SUCCESS) {
return (ret);
return (PCICFG_SUCCESS);
PCICFG_MEMGRAN))));
PCICFG_IOGRAN)))));
PCICFG_IOGRAN))));
int ret;
int circ;
goto failedchild;
!= PCICFG_SUCCESS) {
return (ret);
goto failedconfig;
goto failedchild;
goto failedchild;
return (PCICFG_NODEVICE);
goto failedchild;
goto failedchild;
for (i = 0; i < PCICFG_MAX_DEVICE; i++) {
for (j = 0; j < PCICFG_MAX_FUNCTION; j++) {
new_bus, i, j) ==
new_bus, i, j);
goto failedchild;
i = PCI_CONF_BASE0;
while (i <= PCI_CONF_BASE5) {
if (request != 0) {
goto failedchild;
i, request,
i, request,
if (request != 0) {
goto failedchild;
return (PCICFG_SUCCESS);
return (PCICFG_FAILURE);
int circ;
int status;
int rlen;
int flags = 0;
switch (status) {
case DDI_PROP_SUCCESS:
case DDI_PROP_NO_MEMORY:
return (PCICFG_FAILURE);
return (PCICFG_FAILURE);
return (PCICFG_FAILURE);
return (PCICFG_FAILURE);
return (PCICFG_FAILURE);
return (ret);
#ifdef DEBUG
#ifdef _EFCODE_WORKAROUND
int *vendor_id;
int *device_id;
return (DDI_WALK_TERMINATE);
return (DDI_WALK_TERMINATE);
return (DDI_WALK_CONTINUE);
int *vendor_id;
int *device_id;
length = 0;
*count = 0;
return (DDI_WALK_TERMINATE);
*count = 0;
return (DDI_WALK_TERMINATE);
return (DDI_WALK_CONTINUE);
int number;
int circular;
number = 0;
if (parent)
} else if (number) {
if (parent)
if (parent)
return (rc);
(ddi_root_node() !=
== DDI_SUCCESS) {
return (rc);
char *buffer)
return (rc);
(ddi_root_node() !=
return (rc);
return (DDI_FAILURE);
return (rc);
return (DDI_FAILURE);
return (DDI_SUCCESS);