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