pci_resource.c revision 56f33205c9ed776c3c909e07d52e94610a675740
/*
* 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 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* pci_resource.c -- routines to retrieve available bus resources from
* the MP Spec. Table and Hotplug Resource Table
*/
#include <sys/pci_impl.h>
#include "mps_table.h"
#include "pcihrt.h"
extern int pci_boot_debug;
extern int pci_bios_maxbus;
static int tbl_init = 0;
static int hrt_entry_cnt = 0;
static int acpi_cb_cnt = 0;
static void mps_probe(void);
static void acpi_pci_probe(void);
static int mps_find_bus_res(int, int, struct memlist **);
static void hrt_probe(void);
static int hrt_find_bus_res(int, int, struct memlist **);
static int acpi_find_bus_res(int, int, struct memlist **);
void bus_res_fini(void);
static void acpi_trim_bus_ranges(void);
/*
* -1 = attempt ACPI resource discovery
* 0 = don't attempt ACPI resource discovery
* 1 = ACPI resource discovery successful
*/
volatile int acpi_resource_discovery = -1;
struct memlist *
{
if (tbl_init == 0) {
tbl_init = 1;
hrt_probe();
mps_probe();
}
return (res);
return (res);
return (res);
}
static void
acpi_pci_probe(void)
{
int bus;
if (acpi_resource_discovery == 0)
return;
/* if no dip or no ACPI handle, no resources to discover */
continue;
}
if (acpi_cb_cnt > 0) {
}
}
/*
* Trim overlapping bus ranges in acpi_bus_res[]
* Some BIOSes report root-bridges with bus ranges that
* overlap, for example:"0..255" and "8..255". Lower-numbered
* ranges are trimmed by upper-numbered ranges (so "0..255" would
* be trimmed to "0..7", in the example).
*/
static void
{
int bus;
/*
* Assumptions:
* - there exists at most 1 bus range entry for each bus number
* - there are no (broken) ranges that start at the same bus number
*/
/* skip buses with no range entry */
continue;
/*
* create copy of existing range and overload
* 'prev' pointer to link existing to new copy
*/
new = memlist_alloc();
/* sorted insertion of 'new' into ranges list */
break;
/* place at beginning of (possibly) empty list */
} else {
/* place in list (possibly at end) */
}
}
/* scan the list, perform trimming */
/* done when no range above current */
break;
/*
* trim size in original range element
* (current->ml_prev points to the original range)
*/
}
/* discard the list */
}
static int
{
switch (type) {
case IO_TYPE:
break;
case MEM_TYPE:
break;
case PREFETCH_TYPE:
break;
case BUSRANGE_TYPE:
break;
default:
break;
}
/* memlist_count() treats NULL head as zero-length */
return (memlist_count(*res));
}
void
bus_res_fini(void)
{
int bus;
}
}
struct memlist **
{
switch (t) {
case ACPI_MEMORY_RANGE:
/* is this really the best we've got? */
return (&acpi_pmem_res[bus]);
else
return (&acpi_mem_res[bus]);
}
}
{
/* ignore consumed resources */
return (AE_OK);
case ACPI_RESOURCE_TYPE_IRQ:
/* never expect to see a PCI bus produce an Interrupt */
break;
case ACPI_RESOURCE_TYPE_DMA:
/* never expect to see a PCI bus produce DMA */
break;
break;
break;
case ACPI_RESOURCE_TYPE_IO:
break;
acpi_cb_cnt++;
break;
/* only expect to see this as a consumer */
break;
break;
break;
/* only expect to see this as a consumer */
break;
/* only expect to see this as a consumer */
break;
/* only expect to see this as a consumer */
break;
break;
acpi_cb_cnt++;
break;
break;
acpi_cb_cnt++;
break;
/*
* We comment out this block because we currently cannot deal with
* PCI 64-bit addresses. Will revisit this when we add PCI 64-bit MMIO
* support.
*/
#if 0
break;
acpi_cb_cnt++;
#endif
break;
#if 0 /* Will revisit this when we add PCI 64-bit MMIO support */
break;
acpi_cb_cnt++;
#endif
break;
/* never expect to see a PCI bus produce an Interrupt */
break;
/* never expect to see a PCI bus produce an GAS */
break;
}
return (AE_OK);
}
static void
{
struct mps_ct_hdr *ctp;
if (ebda_seg != 0) {
}
if (base_end_seg != ebda_seg) {
}
}
}
dprintf("MP Spec table doesn't exist");
return;
} else {
dprintf("Found MP Floating Pointer Structure at %p\n",
(void *)fpp);
}
dprintf("MP Floating Pointer Structure checksum error");
return;
}
dprintf("MP Configuration Table signature is wrong");
return;
}
dprintf("MP Configuration Table checksum error");
return;
}
dprintf("MP Spec 1.1 found - extended table doesn't exist");
return;
}
dprintf("MP Spec 1.4 found - extended table doesn't exist");
return;
}
dprintf("MP Extended Table checksum error");
return;
}
}
static int
{
int res_cnt;
return (0);
res_cnt = 0;
while (extp < mps_ext_endp) {
switch (*extp) {
case SYS_AS_MAPPING:
if (sasmp->sasm_as_base_hi != 0 ||
sasmp->sasm_as_len_hi != 0) {
printf("64 bits address space\n");
break;
}
sasmp->sasm_as_len);
res_cnt++;
}
break;
case BUS_HIERARCHY_DESC:
break;
case COMP_BUS_AS_MODIFIER:
break;
default:
" in BIOS Multiprocessor Spec table.",
*extp);
while (*res) {
}
return (0);
}
}
return (res_cnt);
}
static void
{
dprintf("search PCI Hot-Plug Resource Table starting at 0xF0000\n");
dprintf("NO PCI Hot-Plug Resource Table");
return;
}
dprintf("PCI Hot-Plug Resource Table version no. <> 1\n");
return;
}
}
static int
{
int res_cnt, i;
return (0);
res_cnt = 0;
for (i = 0; i < hrt_entry_cnt; i++, hpep++) {
continue;
continue;
res_cnt++;
continue;
res_cnt++;
} else if (type == PREFETCH_TYPE) {
if (hpep->php_pfmem_start == 0 ||
hpep->php_pfmem_size == 0)
continue;
res_cnt++;
}
}
return (res_cnt);
}
static uchar_t *
{
long i;
/* Search for the "_MP_" or "$HRT" signature */
for (i = 0; i < len; i += 16) {
return (cp);
cp += 16;
}
return (NULL);
}
static int
{
int i;
unsigned int cksum;
return ((int)(cksum & 0xFF));
}
#ifdef UNUSED_BUS_HIERARY_INFO
/*
* At this point, the bus hierarchy entries do not appear to
* provide anything we can't find out from PCI config space.
* The only interesting bit is the ISA bus number, which we
* don't care.
*/
int
mps_find_parent_bus(int bus)
{
return (-1);
while (extp < mps_ext_endp) {
switch (*extp) {
case SYS_AS_MAPPING:
break;
case BUS_HIERARCHY_DESC:
return (bhdp->bhd_parent);
break;
case COMP_BUS_AS_MODIFIER:
break;
default:
" in BIOS Multiprocessor Spec table.",
*extp);
return (-1);
}
}
return (-1);
}
int
hrt_find_bus_range(int bus)
{
return (-1);
}
max_bus = -1;
for (i = 0; i < hrt_entry_cnt; i++, hpep++) {
continue;
}
return (max_bus);
}
#endif /* UNUSED_BUS_HIERARY_INFO */