13446Smrj /* 23446Smrj * CDDL HEADER START 33446Smrj * 43446Smrj * The contents of this file are subject to the terms of the 5*8420SDana.Myers@Sun.COM * Common Development and Distribution License (the "License"). 6*8420SDana.Myers@Sun.COM * You may not use this file except in compliance with the License. 73446Smrj * 83446Smrj * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 93446Smrj * or http://www.opensolaris.org/os/licensing. 103446Smrj * See the License for the specific language governing permissions 113446Smrj * and limitations under the License. 123446Smrj * 133446Smrj * When distributing Covered Code, include this CDDL HEADER in each 143446Smrj * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 153446Smrj * If applicable, add the following below this CDDL HEADER, with the 163446Smrj * fields enclosed by brackets "[]" replaced with your own identifying 173446Smrj * information: Portions Copyright [yyyy] [name of copyright owner] 183446Smrj * 193446Smrj * CDDL HEADER END 203446Smrj */ 213446Smrj /* 22*8420SDana.Myers@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 233446Smrj * Use is subject to license terms. 243446Smrj * 253446Smrj * pci_resource.c -- routines to retrieve available bus resources from 263446Smrj * the MP Spec. Table and Hotplug Resource Table 273446Smrj */ 283446Smrj 293446Smrj #include <sys/types.h> 303446Smrj #include <sys/memlist.h> 313446Smrj #include <sys/pci_impl.h> 323446Smrj #include <sys/systm.h> 333446Smrj #include <sys/cmn_err.h> 34*8420SDana.Myers@Sun.COM #include <sys/acpi/acpi.h> 35*8420SDana.Myers@Sun.COM #include <sys/acpica.h> 363446Smrj #include "mps_table.h" 373446Smrj #include "pcihrt.h" 383446Smrj 393446Smrj extern int pci_boot_debug; 40*8420SDana.Myers@Sun.COM extern int pci_bios_nbus; 413446Smrj #define dprintf if (pci_boot_debug) printf 423446Smrj 433446Smrj static int tbl_init = 0; 443446Smrj static uchar_t *mps_extp = NULL; 453446Smrj static uchar_t *mps_ext_endp = NULL; 463446Smrj static struct php_entry *hrt_hpep; 473446Smrj static int hrt_entry_cnt = 0; 48*8420SDana.Myers@Sun.COM static int acpi_cb_cnt = 0; 493446Smrj 503446Smrj static void mps_probe(void); 51*8420SDana.Myers@Sun.COM static void acpi_pci_probe(void); 523446Smrj static int mps_find_bus_res(int, int, struct memlist **); 533446Smrj static void hrt_probe(void); 543446Smrj static int hrt_find_bus_res(int, int, struct memlist **); 55*8420SDana.Myers@Sun.COM static int acpi_find_bus_res(int, int, struct memlist **); 563446Smrj static uchar_t *find_sig(uchar_t *cp, int len, char *sig); 573446Smrj static int checksum(unsigned char *cp, int len); 58*8420SDana.Myers@Sun.COM static ACPI_STATUS acpi_wr_cb(ACPI_RESOURCE *rp, void *context); 59*8420SDana.Myers@Sun.COM void bus_res_fini(void); 60*8420SDana.Myers@Sun.COM 61*8420SDana.Myers@Sun.COM struct memlist *acpi_io_res[256]; 62*8420SDana.Myers@Sun.COM struct memlist *acpi_mem_res[256]; 63*8420SDana.Myers@Sun.COM struct memlist *acpi_pmem_res[256]; 64*8420SDana.Myers@Sun.COM struct memlist *acpi_bus_res[256]; 65*8420SDana.Myers@Sun.COM 66*8420SDana.Myers@Sun.COM /* 67*8420SDana.Myers@Sun.COM * -1 = attempt ACPI resource discovery 68*8420SDana.Myers@Sun.COM * 0 = don't attempt ACPI resource discovery 69*8420SDana.Myers@Sun.COM * 1 = ACPI resource discovery successful 70*8420SDana.Myers@Sun.COM */ 71*8420SDana.Myers@Sun.COM volatile int acpi_resource_discovery = -1; 723446Smrj 733446Smrj struct memlist * 743446Smrj find_bus_res(int bus, int type) 753446Smrj { 763446Smrj struct memlist *res = NULL; 773446Smrj 783446Smrj if (tbl_init == 0) { 793446Smrj tbl_init = 1; 80*8420SDana.Myers@Sun.COM acpi_pci_probe(); 813446Smrj hrt_probe(); 823446Smrj mps_probe(); 833446Smrj } 843446Smrj 85*8420SDana.Myers@Sun.COM if (acpi_find_bus_res(bus, type, &res) > 0) 86*8420SDana.Myers@Sun.COM return (res); 87*8420SDana.Myers@Sun.COM 883446Smrj if (hrt_find_bus_res(bus, type, &res) > 0) 893446Smrj return (res); 903446Smrj 913446Smrj (void) mps_find_bus_res(bus, type, &res); 923446Smrj return (res); 933446Smrj } 943446Smrj 95*8420SDana.Myers@Sun.COM 96*8420SDana.Myers@Sun.COM static void 97*8420SDana.Myers@Sun.COM acpi_pci_probe(void) 98*8420SDana.Myers@Sun.COM { 99*8420SDana.Myers@Sun.COM ACPI_HANDLE ah; 100*8420SDana.Myers@Sun.COM dev_info_t *dip; 101*8420SDana.Myers@Sun.COM int bus; 102*8420SDana.Myers@Sun.COM 103*8420SDana.Myers@Sun.COM if (acpi_resource_discovery == 0) 104*8420SDana.Myers@Sun.COM return; 105*8420SDana.Myers@Sun.COM 106*8420SDana.Myers@Sun.COM for (bus = 0; bus < pci_bios_nbus; bus++) { 107*8420SDana.Myers@Sun.COM /* if no dip or no ACPI handle, no resources to discover */ 108*8420SDana.Myers@Sun.COM dip = pci_bus_res[bus].dip; 109*8420SDana.Myers@Sun.COM if ((dip == NULL) || 110*8420SDana.Myers@Sun.COM (ACPI_FAILURE(acpica_get_handle(dip, &ah)))) 111*8420SDana.Myers@Sun.COM continue; 112*8420SDana.Myers@Sun.COM 113*8420SDana.Myers@Sun.COM (void) AcpiWalkResources(ah, "_CRS", acpi_wr_cb, 114*8420SDana.Myers@Sun.COM (void *)(uintptr_t)bus); 115*8420SDana.Myers@Sun.COM } 116*8420SDana.Myers@Sun.COM 117*8420SDana.Myers@Sun.COM if (acpi_cb_cnt > 0) 118*8420SDana.Myers@Sun.COM acpi_resource_discovery = 1; 119*8420SDana.Myers@Sun.COM } 120*8420SDana.Myers@Sun.COM 121*8420SDana.Myers@Sun.COM static int 122*8420SDana.Myers@Sun.COM acpi_find_bus_res(int bus, int type, struct memlist **res) 123*8420SDana.Myers@Sun.COM { 124*8420SDana.Myers@Sun.COM 125*8420SDana.Myers@Sun.COM switch (type) { 126*8420SDana.Myers@Sun.COM case IO_TYPE: 127*8420SDana.Myers@Sun.COM *res = acpi_io_res[bus]; 128*8420SDana.Myers@Sun.COM break; 129*8420SDana.Myers@Sun.COM case MEM_TYPE: 130*8420SDana.Myers@Sun.COM *res = acpi_mem_res[bus]; 131*8420SDana.Myers@Sun.COM break; 132*8420SDana.Myers@Sun.COM case PREFETCH_TYPE: 133*8420SDana.Myers@Sun.COM *res = acpi_pmem_res[bus]; 134*8420SDana.Myers@Sun.COM break; 135*8420SDana.Myers@Sun.COM case BUSRANGE_TYPE: 136*8420SDana.Myers@Sun.COM *res = acpi_bus_res[bus]; 137*8420SDana.Myers@Sun.COM break; 138*8420SDana.Myers@Sun.COM default: 139*8420SDana.Myers@Sun.COM *res = NULL; 140*8420SDana.Myers@Sun.COM break; 141*8420SDana.Myers@Sun.COM } 142*8420SDana.Myers@Sun.COM 143*8420SDana.Myers@Sun.COM /* memlist_count() treats NULL head as zero-length */ 144*8420SDana.Myers@Sun.COM return (memlist_count(*res)); 145*8420SDana.Myers@Sun.COM } 146*8420SDana.Myers@Sun.COM 147*8420SDana.Myers@Sun.COM void 148*8420SDana.Myers@Sun.COM bus_res_fini(void) 149*8420SDana.Myers@Sun.COM { 150*8420SDana.Myers@Sun.COM int bus; 151*8420SDana.Myers@Sun.COM 152*8420SDana.Myers@Sun.COM for (bus = 0; bus < pci_bios_nbus; bus++) { 153*8420SDana.Myers@Sun.COM memlist_free_all(&acpi_io_res[bus]); 154*8420SDana.Myers@Sun.COM memlist_free_all(&acpi_mem_res[bus]); 155*8420SDana.Myers@Sun.COM memlist_free_all(&acpi_pmem_res[bus]); 156*8420SDana.Myers@Sun.COM memlist_free_all(&acpi_bus_res[bus]); 157*8420SDana.Myers@Sun.COM } 158*8420SDana.Myers@Sun.COM } 159*8420SDana.Myers@Sun.COM 160*8420SDana.Myers@Sun.COM 161*8420SDana.Myers@Sun.COM struct memlist ** 162*8420SDana.Myers@Sun.COM rlistpp(UINT8 t, UINT8 flags, int bus) 163*8420SDana.Myers@Sun.COM { 164*8420SDana.Myers@Sun.COM switch (t) { 165*8420SDana.Myers@Sun.COM 166*8420SDana.Myers@Sun.COM case ACPI_MEMORY_RANGE: 167*8420SDana.Myers@Sun.COM /* is this really the best we've got? */ 168*8420SDana.Myers@Sun.COM if (((flags >> 1) & 0x3) == ACPI_PREFETCHABLE_MEMORY) 169*8420SDana.Myers@Sun.COM return (&acpi_pmem_res[bus]); 170*8420SDana.Myers@Sun.COM else 171*8420SDana.Myers@Sun.COM return (&acpi_mem_res[bus]); 172*8420SDana.Myers@Sun.COM 173*8420SDana.Myers@Sun.COM case ACPI_IO_RANGE: return &acpi_io_res[bus]; 174*8420SDana.Myers@Sun.COM case ACPI_BUS_NUMBER_RANGE: return &acpi_bus_res[bus]; 175*8420SDana.Myers@Sun.COM } 176*8420SDana.Myers@Sun.COM return ((struct memlist **)NULL); 177*8420SDana.Myers@Sun.COM } 178*8420SDana.Myers@Sun.COM 179*8420SDana.Myers@Sun.COM 180*8420SDana.Myers@Sun.COM ACPI_STATUS 181*8420SDana.Myers@Sun.COM acpi_wr_cb(ACPI_RESOURCE *rp, void *context) 182*8420SDana.Myers@Sun.COM { 183*8420SDana.Myers@Sun.COM int bus = (intptr_t)context; 184*8420SDana.Myers@Sun.COM 185*8420SDana.Myers@Sun.COM /* ignore consumed resources */ 186*8420SDana.Myers@Sun.COM if (rp->Data.Address.ProducerConsumer == 1) 187*8420SDana.Myers@Sun.COM return (AE_OK); 188*8420SDana.Myers@Sun.COM 189*8420SDana.Myers@Sun.COM switch (rp->Type) { 190*8420SDana.Myers@Sun.COM case ACPI_RESOURCE_TYPE_IRQ: 191*8420SDana.Myers@Sun.COM /* never expect to see a PCI bus produce an Interrupt */ 192*8420SDana.Myers@Sun.COM dprintf("%s\n", "IRQ"); 193*8420SDana.Myers@Sun.COM break; 194*8420SDana.Myers@Sun.COM 195*8420SDana.Myers@Sun.COM case ACPI_RESOURCE_TYPE_DMA: 196*8420SDana.Myers@Sun.COM /* never expect to see a PCI bus produce DMA */ 197*8420SDana.Myers@Sun.COM dprintf("%s\n", "DMA"); 198*8420SDana.Myers@Sun.COM break; 199*8420SDana.Myers@Sun.COM 200*8420SDana.Myers@Sun.COM case ACPI_RESOURCE_TYPE_START_DEPENDENT: 201*8420SDana.Myers@Sun.COM dprintf("%s\n", "START_DEPENDENT"); 202*8420SDana.Myers@Sun.COM break; 203*8420SDana.Myers@Sun.COM 204*8420SDana.Myers@Sun.COM case ACPI_RESOURCE_TYPE_END_DEPENDENT: 205*8420SDana.Myers@Sun.COM dprintf("%s\n", "END_DEPENDENT"); 206*8420SDana.Myers@Sun.COM break; 207*8420SDana.Myers@Sun.COM 208*8420SDana.Myers@Sun.COM case ACPI_RESOURCE_TYPE_IO: 209*8420SDana.Myers@Sun.COM if (rp->Data.Io.AddressLength == 0) 210*8420SDana.Myers@Sun.COM break; 211*8420SDana.Myers@Sun.COM acpi_cb_cnt++; 212*8420SDana.Myers@Sun.COM memlist_insert(&acpi_io_res[bus], rp->Data.Io.Minimum, 213*8420SDana.Myers@Sun.COM rp->Data.Io.AddressLength); 214*8420SDana.Myers@Sun.COM break; 215*8420SDana.Myers@Sun.COM 216*8420SDana.Myers@Sun.COM case ACPI_RESOURCE_TYPE_FIXED_IO: 217*8420SDana.Myers@Sun.COM /* only expect to see this as a consumer */ 218*8420SDana.Myers@Sun.COM dprintf("%s\n", "FIXED_IO"); 219*8420SDana.Myers@Sun.COM break; 220*8420SDana.Myers@Sun.COM 221*8420SDana.Myers@Sun.COM case ACPI_RESOURCE_TYPE_VENDOR: 222*8420SDana.Myers@Sun.COM dprintf("%s\n", "VENDOR"); 223*8420SDana.Myers@Sun.COM break; 224*8420SDana.Myers@Sun.COM 225*8420SDana.Myers@Sun.COM case ACPI_RESOURCE_TYPE_END_TAG: 226*8420SDana.Myers@Sun.COM dprintf("%s\n", "END_TAG"); 227*8420SDana.Myers@Sun.COM break; 228*8420SDana.Myers@Sun.COM 229*8420SDana.Myers@Sun.COM case ACPI_RESOURCE_TYPE_MEMORY24: 230*8420SDana.Myers@Sun.COM /* only expect to see this as a consumer */ 231*8420SDana.Myers@Sun.COM dprintf("%s\n", "MEMORY24"); 232*8420SDana.Myers@Sun.COM break; 233*8420SDana.Myers@Sun.COM 234*8420SDana.Myers@Sun.COM case ACPI_RESOURCE_TYPE_MEMORY32: 235*8420SDana.Myers@Sun.COM /* only expect to see this as a consumer */ 236*8420SDana.Myers@Sun.COM dprintf("%s\n", "MEMORY32"); 237*8420SDana.Myers@Sun.COM break; 238*8420SDana.Myers@Sun.COM 239*8420SDana.Myers@Sun.COM case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: 240*8420SDana.Myers@Sun.COM /* only expect to see this as a consumer */ 241*8420SDana.Myers@Sun.COM dprintf("%s\n", "FIXED_MEMORY32"); 242*8420SDana.Myers@Sun.COM break; 243*8420SDana.Myers@Sun.COM 244*8420SDana.Myers@Sun.COM case ACPI_RESOURCE_TYPE_ADDRESS16: 245*8420SDana.Myers@Sun.COM if (rp->Data.Address16.AddressLength == 0) 246*8420SDana.Myers@Sun.COM break; 247*8420SDana.Myers@Sun.COM acpi_cb_cnt++; 248*8420SDana.Myers@Sun.COM memlist_insert(rlistpp(rp->Data.Address16.ResourceType, 249*8420SDana.Myers@Sun.COM rp->Data.Address16.Info.TypeSpecific, bus), 250*8420SDana.Myers@Sun.COM rp->Data.Address16.Minimum, 251*8420SDana.Myers@Sun.COM rp->Data.Address16.AddressLength); 252*8420SDana.Myers@Sun.COM break; 253*8420SDana.Myers@Sun.COM 254*8420SDana.Myers@Sun.COM case ACPI_RESOURCE_TYPE_ADDRESS32: 255*8420SDana.Myers@Sun.COM if (rp->Data.Address32.AddressLength == 0) 256*8420SDana.Myers@Sun.COM break; 257*8420SDana.Myers@Sun.COM acpi_cb_cnt++; 258*8420SDana.Myers@Sun.COM memlist_insert(rlistpp(rp->Data.Address32.ResourceType, 259*8420SDana.Myers@Sun.COM rp->Data.Address32.Info.TypeSpecific, bus), 260*8420SDana.Myers@Sun.COM rp->Data.Address32.Minimum, 261*8420SDana.Myers@Sun.COM rp->Data.Address32.AddressLength); 262*8420SDana.Myers@Sun.COM break; 263*8420SDana.Myers@Sun.COM 264*8420SDana.Myers@Sun.COM case ACPI_RESOURCE_TYPE_ADDRESS64: 265*8420SDana.Myers@Sun.COM if (rp->Data.Address64.AddressLength == 0) 266*8420SDana.Myers@Sun.COM break; 267*8420SDana.Myers@Sun.COM acpi_cb_cnt++; 268*8420SDana.Myers@Sun.COM memlist_insert(rlistpp(rp->Data.Address64.ResourceType, 269*8420SDana.Myers@Sun.COM rp->Data.Address64.Info.TypeSpecific, bus), 270*8420SDana.Myers@Sun.COM rp->Data.Address64.Minimum, 271*8420SDana.Myers@Sun.COM rp->Data.Address64.AddressLength); 272*8420SDana.Myers@Sun.COM break; 273*8420SDana.Myers@Sun.COM 274*8420SDana.Myers@Sun.COM case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: 275*8420SDana.Myers@Sun.COM if (rp->Data.ExtAddress64.AddressLength == 0) 276*8420SDana.Myers@Sun.COM break; 277*8420SDana.Myers@Sun.COM acpi_cb_cnt++; 278*8420SDana.Myers@Sun.COM memlist_insert(rlistpp(rp->Data.ExtAddress64.ResourceType, 279*8420SDana.Myers@Sun.COM rp->Data.ExtAddress64.Info.TypeSpecific, bus), 280*8420SDana.Myers@Sun.COM rp->Data.ExtAddress64.Minimum, 281*8420SDana.Myers@Sun.COM rp->Data.ExtAddress64.AddressLength); 282*8420SDana.Myers@Sun.COM break; 283*8420SDana.Myers@Sun.COM 284*8420SDana.Myers@Sun.COM case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: 285*8420SDana.Myers@Sun.COM /* never expect to see a PCI bus produce an Interrupt */ 286*8420SDana.Myers@Sun.COM dprintf("%s\n", "EXTENDED_IRQ"); 287*8420SDana.Myers@Sun.COM break; 288*8420SDana.Myers@Sun.COM 289*8420SDana.Myers@Sun.COM case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: 290*8420SDana.Myers@Sun.COM /* never expect to see a PCI bus produce an GAS */ 291*8420SDana.Myers@Sun.COM dprintf("%s\n", "GENERIC_REGISTER"); 292*8420SDana.Myers@Sun.COM break; 293*8420SDana.Myers@Sun.COM } 294*8420SDana.Myers@Sun.COM 295*8420SDana.Myers@Sun.COM return (AE_OK); 296*8420SDana.Myers@Sun.COM } 297*8420SDana.Myers@Sun.COM 2983446Smrj static void 2993446Smrj mps_probe() 3003446Smrj { 3013446Smrj uchar_t *extp; 3023446Smrj struct mps_fps_hdr *fpp = NULL; 3033446Smrj struct mps_ct_hdr *ctp; 3043446Smrj uintptr_t ebda_start, base_end; 3053446Smrj ushort_t ebda_seg, base_size, ext_len, base_len, base_end_seg; 3063446Smrj 3073446Smrj base_size = *((ushort_t *)(0x413)); 3083446Smrj ebda_seg = *((ushort_t *)(0x40e)); 3093446Smrj ebda_start = ((uint32_t)ebda_seg) << 4; 3103446Smrj if (ebda_seg != 0) { 3113446Smrj fpp = (struct mps_fps_hdr *)find_sig( 3123446Smrj (uchar_t *)ebda_start, 1024, "_MP_"); 3133446Smrj } 3143446Smrj if (fpp == NULL) { 3153446Smrj base_end_seg = (base_size > 512) ? 0x9FC0 : 0x7FC0; 3163446Smrj if (base_end_seg != ebda_seg) { 3173446Smrj base_end = ((uintptr_t)base_end_seg) << 4; 3183446Smrj fpp = (struct mps_fps_hdr *)find_sig( 319*8420SDana.Myers@Sun.COM (uchar_t *)base_end, 1024, "_MP_"); 3203446Smrj } 3213446Smrj } 3223446Smrj if (fpp == NULL) { 3233446Smrj fpp = (struct mps_fps_hdr *)find_sig( 3243446Smrj (uchar_t *)0xF0000, 0x10000, "_MP_"); 3253446Smrj } 3263446Smrj 3273446Smrj if (fpp == NULL) { 3283446Smrj dprintf("MP Spec table doesn't exist"); 3293446Smrj return; 3303446Smrj } else { 3313446Smrj dprintf("Found MP Floating Pointer Structure at %p\n", 3323446Smrj (void *)fpp); 3333446Smrj } 3343446Smrj 3353446Smrj if (checksum((uchar_t *)fpp, fpp->fps_len * 16) != 0) { 3363446Smrj dprintf("MP Floating Pointer Structure checksum error"); 3373446Smrj return; 3383446Smrj } 3393446Smrj 3403446Smrj ctp = (struct mps_ct_hdr *)(uintptr_t)fpp->fps_mpct_paddr; 3413446Smrj if (ctp->ct_sig != 0x504d4350) { /* check "PCMP" signature */ 3423446Smrj dprintf("MP Configuration Table signature is wrong"); 3433446Smrj return; 3443446Smrj } 3453446Smrj 3463446Smrj base_len = ctp->ct_len; 3473446Smrj if (checksum((uchar_t *)ctp, base_len) != 0) { 3483446Smrj dprintf("MP Configuration Table checksum error"); 3493446Smrj return; 3503446Smrj } 3513446Smrj if (ctp->ct_spec_rev != 4) { /* not MPSpec rev 1.4 */ 3523446Smrj dprintf("MP Spec 1.1 found - extended table doesn't exist"); 3533446Smrj return; 3543446Smrj } 3553446Smrj if ((ext_len = ctp->ct_ext_tbl_len) == 0) { 3563446Smrj dprintf("MP Spec 1.4 found - extended table doesn't exist"); 3573446Smrj return; 3583446Smrj } 3593446Smrj extp = (uchar_t *)ctp + base_len; 3603446Smrj if (((checksum(extp, ext_len) + ctp->ct_ext_cksum) & 0xFF) != 0) { 3613446Smrj dprintf("MP Extended Table checksum error"); 3623446Smrj return; 3633446Smrj } 3643446Smrj mps_extp = extp; 3653446Smrj mps_ext_endp = mps_extp + ext_len; 3663446Smrj } 3673446Smrj 3683446Smrj 3693446Smrj static int 3703446Smrj mps_find_bus_res(int bus, int type, struct memlist **res) 3713446Smrj { 3723446Smrj struct sasm *sasmp; 3733446Smrj uchar_t *extp; 3743446Smrj int res_cnt; 3753446Smrj 3763446Smrj if (mps_extp == NULL) 3773446Smrj return (0); 3783446Smrj extp = mps_extp; 3793446Smrj res_cnt = 0; 3803446Smrj while (extp < mps_ext_endp) { 3813446Smrj switch (*extp) { 3823446Smrj case SYS_AS_MAPPING: 3833446Smrj sasmp = (struct sasm *)extp; 3843446Smrj if (((int)sasmp->sasm_as_type) == type && 3853446Smrj ((int)sasmp->sasm_bus_id) == bus) { 3863446Smrj if (sasmp->sasm_as_base_hi != 0 || 387*8420SDana.Myers@Sun.COM sasmp->sasm_as_len_hi != 0) { 3883446Smrj printf("64 bits address space\n"); 3893446Smrj extp += SYS_AS_MAPPING_SIZE; 3903446Smrj break; 3913446Smrj } 3923446Smrj memlist_insert(res, 3933446Smrj (uint64_t)sasmp->sasm_as_base, 3943446Smrj sasmp->sasm_as_len); 3953446Smrj res_cnt++; 3963446Smrj } 3973446Smrj extp += SYS_AS_MAPPING_SIZE; 3983446Smrj break; 3993446Smrj case BUS_HIERARCHY_DESC: 4003446Smrj extp += BUS_HIERARCHY_DESC_SIZE; 4013446Smrj break; 4023446Smrj case COMP_BUS_AS_MODIFIER: 4033446Smrj extp += COMP_BUS_AS_MODIFIER_SIZE; 4043446Smrj break; 4053446Smrj default: 4063446Smrj cmn_err(CE_WARN, "Unknown descriptor type %d" 4073446Smrj " in BIOS Multiprocessor Spec table.", 4083446Smrj *extp); 4093446Smrj while (*res) { 4103446Smrj struct memlist *tmp = *res; 4113446Smrj *res = tmp->next; 4123446Smrj memlist_free(tmp); 4133446Smrj } 4143446Smrj return (0); 4153446Smrj } 4163446Smrj } 4173446Smrj return (res_cnt); 4183446Smrj } 4193446Smrj 4203446Smrj static void 4213446Smrj hrt_probe() 4223446Smrj { 4233446Smrj struct hrt_hdr *hrtp; 4243446Smrj 4253446Smrj dprintf("search PCI Hot-Plug Resource Table starting at 0xF0000\n"); 4263446Smrj if ((hrtp = (struct hrt_hdr *)find_sig((uchar_t *)0xF0000, 4273446Smrj 0x10000, "$HRT")) == NULL) { 4283446Smrj dprintf("NO PCI Hot-Plug Resource Table"); 4293446Smrj return; 4303446Smrj } 4313446Smrj dprintf("Found PCI Hot-Plug Resource Table at %p\n", (void *)hrtp); 4323446Smrj if (hrtp->hrt_ver != 1) { 4333446Smrj dprintf("PCI Hot-Plug Resource Table version no. <> 1\n"); 4343446Smrj return; 4353446Smrj } 4363446Smrj hrt_entry_cnt = (int)hrtp->hrt_entry_cnt; 4373446Smrj dprintf("No. of PCI hot-plug slot entries = 0x%x\n", hrt_entry_cnt); 4383446Smrj hrt_hpep = (struct php_entry *)(hrtp + 1); 4393446Smrj } 4403446Smrj 4413446Smrj static int 4423446Smrj hrt_find_bus_res(int bus, int type, struct memlist **res) 4433446Smrj { 4443446Smrj int res_cnt, i; 4453446Smrj struct php_entry *hpep; 4463446Smrj 4473446Smrj if (hrt_hpep == NULL || hrt_entry_cnt == 0) 4483446Smrj return (0); 4493446Smrj hpep = hrt_hpep; 4503446Smrj res_cnt = 0; 4513446Smrj for (i = 0; i < hrt_entry_cnt; i++, hpep++) { 4523446Smrj if (hpep->php_pri_bus != bus) 4533446Smrj continue; 4543446Smrj if (type == IO_TYPE) { 4553446Smrj if (hpep->php_io_start == 0 || hpep->php_io_size == 0) 4563446Smrj continue; 4573446Smrj memlist_insert(res, (uint64_t)hpep->php_io_start, 4583446Smrj (uint64_t)hpep->php_io_size); 4593446Smrj res_cnt++; 4603446Smrj } else if (type == MEM_TYPE) { 4613446Smrj if (hpep->php_mem_start == 0 || hpep->php_mem_size == 0) 4623446Smrj continue; 4633446Smrj memlist_insert(res, 4643446Smrj (uint64_t)(((int)hpep->php_mem_start) << 16), 4653446Smrj (uint64_t)(((int)hpep->php_mem_size) << 16)); 4663446Smrj res_cnt++; 4673446Smrj } else if (type == PREFETCH_TYPE) { 4683446Smrj if (hpep->php_pfmem_start == 0 || 4693446Smrj hpep->php_pfmem_size == 0) 4703446Smrj continue; 4713446Smrj memlist_insert(res, 4723446Smrj (uint64_t)(((int)hpep->php_pfmem_start) << 16), 4733446Smrj (uint64_t)(((int)hpep->php_pfmem_size) << 16)); 4743446Smrj res_cnt++; 4753446Smrj } 4763446Smrj } 4773446Smrj return (res_cnt); 4783446Smrj } 4793446Smrj 4803446Smrj static uchar_t * 4813446Smrj find_sig(uchar_t *cp, int len, char *sig) 4823446Smrj { 4833446Smrj long i; 4843446Smrj 4853446Smrj /* Search for the "_MP_" or "$HRT" signature */ 4863446Smrj for (i = 0; i < len; i += 16) { 4873446Smrj if (cp[0] == sig[0] && cp[1] == sig[1] && 4883446Smrj cp[2] == sig[2] && cp[3] == sig[3]) 4893446Smrj return (cp); 4903446Smrj cp += 16; 4913446Smrj } 4923446Smrj return (NULL); 4933446Smrj } 4943446Smrj 4953446Smrj static int 4963446Smrj checksum(unsigned char *cp, int len) 4973446Smrj { 4983446Smrj int i; 4993446Smrj unsigned int cksum; 5003446Smrj 5013446Smrj for (i = cksum = 0; i < len; i++) 5023446Smrj cksum += (unsigned int) *cp++; 5033446Smrj 5043446Smrj return ((int)(cksum & 0xFF)); 5053446Smrj } 5063446Smrj 5073446Smrj #ifdef UNUSED_BUS_HIERARY_INFO 5083446Smrj 5093446Smrj /* 5103446Smrj * At this point, the bus hierarchy entries do not appear to 5113446Smrj * provide anything we can't find out from PCI config space. 5123446Smrj * The only interesting bit is the ISA bus number, which we 5133446Smrj * don't care. 5143446Smrj */ 5153446Smrj int 5163446Smrj mps_find_parent_bus(int bus) 5173446Smrj { 5183446Smrj struct sasm *sasmp; 5193446Smrj uchar_t *extp; 5203446Smrj 5213446Smrj if (mps_extp == NULL) 5223446Smrj return (-1); 5233446Smrj 5243446Smrj extp = mps_extp; 5253446Smrj while (extp < mps_ext_endp) { 5263446Smrj bhdp = (struct bhd *)extp; 5273446Smrj switch (*extp) { 5283446Smrj case SYS_AS_MAPPING: 5293446Smrj extp += SYS_AS_MAPPING_SIZE; 5303446Smrj break; 5313446Smrj case BUS_HIERARCHY_DESC: 5323446Smrj if (bhdp->bhd_bus_id == bus) 5333446Smrj return (bhdp->bhd_parent); 5343446Smrj extp += BUS_HIERARCHY_DESC_SIZE; 5353446Smrj break; 5363446Smrj case COMP_BUS_AS_MODIFIER: 5373446Smrj extp += COMP_BUS_AS_MODIFIER_SIZE; 5383446Smrj break; 5393446Smrj default: 5403446Smrj cmn_err(CE_WARN, "Unknown descriptor type %d" 5413446Smrj " in BIOS Multiprocessor Spec table.", 5423446Smrj *extp); 5433446Smrj return (-1); 5443446Smrj } 5453446Smrj } 5463446Smrj return (-1); 5473446Smrj } 5483446Smrj 5493446Smrj int 5503446Smrj hrt_find_bus_range(int bus) 5513446Smrj { 5523446Smrj int i, max_bus, sub_bus; 5533446Smrj struct php_entry *hpep; 5543446Smrj 5553446Smrj if (hrt_hpep == NULL || hrt_entry_cnt == 0) { 5563446Smrj return (-1); 5573446Smrj } 5583446Smrj hpep = hrt_hpep; 5593446Smrj max_bus = -1; 5603446Smrj for (i = 0; i < hrt_entry_cnt; i++, hpep++) { 5613446Smrj if (hpep->php_pri_bus != bus) 5623446Smrj continue; 5633446Smrj sub_bus = (int)hpep->php_subord_bus; 5643446Smrj if (sub_bus > max_bus) 5653446Smrj max_bus = sub_bus; 5663446Smrj } 5673446Smrj return (max_bus); 5683446Smrj } 5693446Smrj 5703446Smrj #endif /* UNUSED_BUS_HIERARY_INFO */ 571