xref: /netbsd-src/sys/arch/ia64/acpi/madt.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
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