1 /* $NetBSD: madt.c,v 1.3 2013/04/07 07:37:51 kiyohara Exp $ */ 2 /*- 3 * Copyright (c) 2001 Doug Rabson 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * $FreeBSD: src/sys/ia64/acpica/madt.c,v 1.20 2007/03/22 18:16:42 jkim Exp $ 28 */ 29 30 #include <sys/param.h> 31 #include <sys/reboot.h> 32 33 #include <machine/md_var.h> 34 #include <machine/sapicvar.h> 35 36 #include <dev/acpi/acpica.h> 37 #include <dev/acpi/acpivar.h> 38 #include <actables.h> 39 40 41 extern uint64_t ia64_lapic_address; 42 43 static void 44 print_entry(ACPI_SUBTABLE_HEADER *entry) 45 { 46 47 switch (entry->Type) { 48 case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE: { 49 ACPI_MADT_INTERRUPT_OVERRIDE *iso = 50 (ACPI_MADT_INTERRUPT_OVERRIDE *)entry; 51 printf("\tInterrupt source override entry\n"); 52 printf("\t\tBus=%u, Source=%u, Irq=0x%x\n", iso->Bus, 53 iso->SourceIrq, iso->GlobalIrq); 54 break; 55 } 56 57 case ACPI_MADT_TYPE_IO_APIC: 58 printf("\tI/O APIC entry\n"); 59 break; 60 61 case ACPI_MADT_TYPE_IO_SAPIC: { 62 ACPI_MADT_IO_SAPIC *sapic = (ACPI_MADT_IO_SAPIC *)entry; 63 printf("\tI/O SAPIC entry\n"); 64 printf("\t\tId=0x%x, InterruptBase=0x%x, Address=0x%lx\n", 65 sapic->Id, sapic->GlobalIrqBase, sapic->Address); 66 break; 67 } 68 69 case ACPI_MADT_TYPE_LOCAL_APIC_NMI: 70 printf("\tLocal APIC NMI entry\n"); 71 break; 72 73 case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE: { 74 ACPI_MADT_LOCAL_APIC_OVERRIDE *lapic = 75 (ACPI_MADT_LOCAL_APIC_OVERRIDE *)entry; 76 printf("\tLocal APIC override entry\n"); 77 printf("\t\tLocal APIC address=0x%jx\n", lapic->Address); 78 break; 79 } 80 81 case ACPI_MADT_TYPE_LOCAL_SAPIC: { 82 ACPI_MADT_LOCAL_SAPIC *sapic = (ACPI_MADT_LOCAL_SAPIC *)entry; 83 printf("\tLocal SAPIC entry\n"); 84 printf("\t\tProcessorId=0x%x, Id=0x%x, Eid=0x%x", 85 sapic->ProcessorId, sapic->Id, sapic->Eid); 86 if (!(sapic->LapicFlags & ACPI_MADT_ENABLED)) 87 printf(" (disabled)"); 88 printf("\n"); 89 break; 90 } 91 92 case ACPI_MADT_TYPE_NMI_SOURCE: 93 printf("\tNMI entry\n"); 94 break; 95 96 case ACPI_MADT_TYPE_INTERRUPT_SOURCE: { 97 ACPI_MADT_INTERRUPT_SOURCE *pis = 98 (ACPI_MADT_INTERRUPT_SOURCE *)entry; 99 printf("\tPlatform interrupt entry\n"); 100 printf("\t\tPolarity=%u, TriggerMode=%u, Id=0x%x, " 101 "Eid=0x%x, Vector=0x%x, Irq=%d\n", 102 pis->IntiFlags & ACPI_MADT_POLARITY_MASK, 103 (pis->IntiFlags & ACPI_MADT_TRIGGER_MASK) >> 2, 104 pis->Id, pis->Eid, pis->IoSapicVector, pis->GlobalIrq); 105 break; 106 } 107 108 case ACPI_MADT_TYPE_LOCAL_APIC: 109 printf("\tLocal APIC entry\n"); 110 break; 111 112 default: 113 printf("\tUnknown type %d entry\n", entry->Type); 114 break; 115 } 116 } 117 118 void 119 ia64_probe_sapics(void) 120 { 121 ACPI_PHYSICAL_ADDRESS rsdp_ptr; 122 ACPI_SUBTABLE_HEADER *entry; 123 ACPI_TABLE_MADT *table; 124 ACPI_TABLE_RSDP *rsdp; 125 ACPI_TABLE_XSDT *xsdt; 126 char *end, *p; 127 int t, tables; 128 extern int has_i8259; 129 130 if ((rsdp_ptr = AcpiOsGetRootPointer()) == 0) 131 return; 132 133 rsdp = (ACPI_TABLE_RSDP *)IA64_PHYS_TO_RR7(rsdp_ptr); 134 xsdt = (ACPI_TABLE_XSDT *)IA64_PHYS_TO_RR7(rsdp->XsdtPhysicalAddress); 135 136 tables = (UINT64 *)((char *)xsdt + xsdt->Header.Length) - 137 xsdt->TableOffsetEntry; 138 139 for (t = 0; t < tables; t++) { 140 table = (ACPI_TABLE_MADT *) 141 IA64_PHYS_TO_RR7(xsdt->TableOffsetEntry[t]); 142 143 if (bootverbose) 144 printf("Table '%c%c%c%c' at %p\n", 145 table->Header.Signature[0], 146 table->Header.Signature[1], 147 table->Header.Signature[2], 148 table->Header.Signature[3], table); 149 150 if (strncmp(table->Header.Signature, ACPI_SIG_MADT, 151 ACPI_NAME_SIZE) != 0 || 152 ACPI_FAILURE(AcpiTbChecksum((void *)table, 153 table->Header.Length))) 154 continue; 155 156 /* Save the address of the processor interrupt block. */ 157 if (bootverbose) 158 printf("\tLocal APIC address=0x%x\n", table->Address); 159 ia64_lapic_address = table->Address; 160 161 if (table->Flags & ACPI_MADT_PCAT_COMPAT) 162 has_i8259 = 1; 163 164 end = (char *)table + table->Header.Length; 165 p = (char *)(table + 1); 166 while (p < end) { 167 entry = (ACPI_SUBTABLE_HEADER *)p; 168 169 if (bootverbose) 170 print_entry(entry); 171 172 switch (entry->Type) { 173 case ACPI_MADT_TYPE_IO_SAPIC: 174 { 175 ACPI_MADT_IO_SAPIC *sapic = 176 (ACPI_MADT_IO_SAPIC *)entry; 177 178 sapic_create(sapic->Id, sapic->GlobalIrqBase, 179 sapic->Address); 180 break; 181 } 182 183 case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE: 184 { 185 ACPI_MADT_LOCAL_APIC_OVERRIDE *lapic = 186 (ACPI_MADT_LOCAL_APIC_OVERRIDE *)entry; 187 188 ia64_lapic_address = lapic->Address; 189 break; 190 } 191 192 #ifdef MULTIPROCESSOR 193 case ACPI_MADT_TYPE_LOCAL_SAPIC: 194 { 195 ACPI_MADT_LOCAL_SAPIC *sapic = 196 (ACPI_MADT_LOCAL_SAPIC *)entry; 197 198 if (sapic->LapicFlags & ACPI_MADT_ENABLED) 199 cpu_mp_add(sapic->ProcessorId, 200 sapic->Id, sapic->Eid); 201 break; 202 } 203 #endif 204 205 default: 206 break; 207 } 208 209 p += entry->Length; 210 } 211 } 212 } 213 214 /* 215 * Count the number of local SAPIC entries in the APIC table. Every enabled 216 * entry corresponds to a processor. 217 */ 218 int 219 ia64_count_cpus(void) 220 { 221 ACPI_PHYSICAL_ADDRESS rsdp_ptr; 222 ACPI_MADT_LOCAL_SAPIC *entry; 223 ACPI_TABLE_MADT *table; 224 ACPI_TABLE_RSDP *rsdp; 225 ACPI_TABLE_XSDT *xsdt; 226 char *end, *p; 227 int cpus, t, tables; 228 229 if ((rsdp_ptr = AcpiOsGetRootPointer()) == 0) 230 return 0; 231 232 rsdp = (ACPI_TABLE_RSDP *)IA64_PHYS_TO_RR7(rsdp_ptr); 233 xsdt = (ACPI_TABLE_XSDT *)IA64_PHYS_TO_RR7(rsdp->XsdtPhysicalAddress); 234 235 tables = (UINT64 *)((char *)xsdt + xsdt->Header.Length) - 236 xsdt->TableOffsetEntry; 237 238 cpus = 0; 239 240 for (t = 0; t < tables; t++) { 241 table = (ACPI_TABLE_MADT *) 242 IA64_PHYS_TO_RR7(xsdt->TableOffsetEntry[t]); 243 244 if (strncmp(table->Header.Signature, ACPI_SIG_MADT, 245 ACPI_NAME_SIZE) != 0 || 246 ACPI_FAILURE(AcpiTbChecksum((void *)table, 247 table->Header.Length))) 248 continue; 249 250 end = (char *)table + table->Header.Length; 251 p = (char *)(table + 1); 252 while (p < end) { 253 entry = (ACPI_MADT_LOCAL_SAPIC *)p; 254 255 if (entry->Header.Type == ACPI_MADT_TYPE_LOCAL_SAPIC && 256 (entry->LapicFlags & ACPI_MADT_ENABLED)) 257 cpus++; 258 259 p += entry->Header.Length; 260 } 261 } 262 263 return cpus; 264 } 265