madt.c revision 85399
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: head/sys/ia64/acpica/madt.c 85399 2001-10-24 04:48:05Z marcel $
27 */
28
29#include "acpi.h"
30
31#pragma pack(1)
32
33#define APIC_INTERRUPT_SOURCE_OVERRIDE 2
34#define APIC_NMI		3
35#define APIC_LOCAL_APIC_NMI	4
36#define APIC_LOCAL_APIC_OVERRIDE 5
37#define APIC_IO_SAPIC		6
38#define APIC_LOCAL_SAPIC	7
39#define APIC_PLATFORM_INTERRUPT	8
40
41
42typedef struct  /* Interrupt Source Override */
43{
44    APIC_HEADER             header;
45    UINT8                   Bus;
46    UINT8                   Source;
47    UINT32                  GlobalSystemInterrupt;
48    UINT16                  Flags;
49} INTERRUPT_SOURCE_OVERRIDE;
50
51typedef struct  /* IO SAPIC */
52{
53    APIC_HEADER             header;
54    UINT8                   IoSapicId;              /* I/O SAPIC ID */
55    UINT8                   Reserved;               /* reserved - must be zero */
56    UINT32                  Vector;                 /* interrupt vector index where INTI
57                                                     * lines start */
58    UINT64                  IoSapicAddress;         /* SAPIC's physical address */
59
60} IO_SAPIC;
61
62
63typedef struct  /* LOCAL SAPIC */
64{
65    APIC_HEADER             header;
66    UINT16                  ProcessorId;            /* ACPI processor id */
67    UINT16                  ProcessorEnabled: 1;    /* Processor is usable if set */
68    UINT16                  Reserved1       : 15;
69    UINT8                   LocalSapicId;           /* processor's local SAPIC id */
70    UINT8                   LocalSapicEid;          /* processor's local SAPIC eid */
71
72} LOCAL_SAPIC;
73
74
75typedef struct  /* PLATFORM INTERRUPT SOURCE */
76{
77    APIC_HEADER             header;
78    UINT16                  Polarity   : 2;         /* Polarity of input signal */
79    UINT16                  TriggerMode: 2;         /* Trigger mode of input signal */
80    UINT16                  Reserved1  : 12;
81    UINT8                   InterruptType;          /* 1-PMI, 2-INIT, 3-Error */
82    UINT8                   ProcessorId;            /* Processor ID of destination */
83    UINT8                   ProcessorEid;           /* Processor EID of destination */
84    UINT8                   IoSapicVector;          /* Value for redirection table */
85    UINT32                  GlobalSystemInterrupt;  /* Global System Interrupt */
86    UINT32                  Reserved2;
87
88} PLATFORM_INTERRUPT_SOURCE;
89
90
91#pragma pack()
92
93static void
94parse_local_apic(PROCESSOR_APIC *apic)
95{
96	if (bootverbose) {
97		printf("\t\tProcessorId=0x%x, APIC Id=0x%x",
98		    apic->ProcessorApicId, apic->LocalApicId);
99		if (!apic->ProcessorEnabled)
100			printf(" (disabled)");
101		printf("\n");
102	}
103}
104
105static void
106parse_io_apic(IO_APIC *apic)
107{
108	if (bootverbose)
109		printf("\t\tId=0x%x, Vector=0x%x, Address=0x%lx\n",
110		    apic->IoApicId, apic->Vector, apic->IoApicAddress);
111}
112
113static void
114parse_interrupt_override(INTERRUPT_SOURCE_OVERRIDE *override)
115{
116	if (bootverbose)
117		printf("\t\tBus=%d, Source=%d, Irq=0x%x\n",
118		       override->Bus,
119		       override->Source,
120		       override->GlobalSystemInterrupt);
121}
122
123static void
124parse_io_sapic(IO_SAPIC *sapic)
125{
126	if (bootverbose)
127		printf("\t\tId=0x%x, Vector=0x%x, Address=0x%lx\n",
128		       sapic->IoSapicId,
129		       sapic->Vector,
130		       sapic->IoSapicAddress);
131	sapic_create(sapic->IoSapicId, sapic->Vector, sapic->IoSapicAddress);
132}
133
134static void
135parse_local_sapic(LOCAL_SAPIC *sapic)
136{
137	if (bootverbose) {
138		printf("\t\tProcessorId=0x%x, Id=0x%x, Eid=0x%x",
139		    sapic->ProcessorId, sapic->LocalSapicId,
140		    sapic->LocalSapicEid);
141		if (!sapic->ProcessorEnabled)
142			printf(" (disabled)");
143		printf("\n");
144	}
145}
146
147static void
148parse_platform_interrupt(PLATFORM_INTERRUPT_SOURCE *source)
149{
150	if (bootverbose)
151		printf("\t\tPolarity=%d, TriggerMode=%d, Id=0x%x, "
152		       "Eid=0x%x, Vector=0x%x, Irq=%d\n",
153		       source->Polarity,
154		       source->TriggerMode,
155		       source->ProcessorId,
156		       source->ProcessorEid,
157		       source->IoSapicVector,
158		       source->GlobalSystemInterrupt);
159}
160
161static void
162parse_madt(APIC_TABLE *madt)
163{
164	char			*p, *end;
165
166	/*
167	 * MADT header is followed by a number of variable length
168	 * structures.
169	 */
170	end = (char *) madt + madt->header.Length;
171	for (p = (char *) (madt + 1); p < end; ) {
172		APIC_HEADER *head = (APIC_HEADER *) p;
173
174		if (bootverbose)
175			printf("\t");
176		switch (head->Type) {
177		case APIC_PROC:
178			if (bootverbose)
179				printf("Local APIC entry\n");
180			parse_local_apic((PROCESSOR_APIC *) head);
181			break;
182
183		case APIC_IO:
184			if (bootverbose)
185				printf("I/O APIC entry\n");
186			parse_io_apic((IO_APIC *) head);
187			break;
188
189		case APIC_INTERRUPT_SOURCE_OVERRIDE:
190			if (bootverbose)
191				printf("Interrupt source override entry\n");
192			parse_interrupt_override
193				((INTERRUPT_SOURCE_OVERRIDE *) head);
194			break;
195
196		case APIC_NMI:
197			if (bootverbose)
198				printf("NMI entry\n");
199			break;
200
201		case APIC_LOCAL_APIC_NMI:
202			if (bootverbose)
203				printf("Local APIC NMI entry\n");
204			break;
205
206		case APIC_LOCAL_APIC_OVERRIDE:
207			if (bootverbose)
208				printf("Local APIC override entry\n");
209			break;
210
211		case APIC_IO_SAPIC:
212			if (bootverbose)
213				printf("I/O SAPIC entry\n");
214			parse_io_sapic((IO_SAPIC *) head);
215			break;
216
217		case APIC_LOCAL_SAPIC:
218			if (bootverbose)
219				printf("Local SAPIC entry\n");
220			parse_local_sapic((LOCAL_SAPIC *) head);
221			break;
222
223		case APIC_PLATFORM_INTERRUPT:
224			if (bootverbose)
225				printf("Platform interrupt entry\n");
226			parse_platform_interrupt
227				((PLATFORM_INTERRUPT_SOURCE *) head);
228			break;
229
230		default:
231			if (bootverbose)
232				printf("Unknown type %d entry\n", head->Type);
233			break;
234		}
235
236		p = p + head->Length;
237	}
238}
239
240void
241ia64_parse_xsdt(XSDT_DESCRIPTOR *xsdt)
242{
243	int			i, count;
244	ACPI_TABLE_HEADER	*table;
245
246	/*
247	 * First find the MADT.
248	 */
249	count = (UINT64 *) ((char *) xsdt + xsdt->Header.Length)
250		- &xsdt->TableOffsetEntry[0];
251	for (i = 0; i < count; i++) {
252		table = (ACPI_TABLE_HEADER *)
253			IA64_PHYS_TO_RR7(xsdt->TableOffsetEntry[i]);
254		if (bootverbose)
255			printf("Table '%c%c%c%c' at %p\n",
256			       table->Signature[0],
257			       table->Signature[1],
258			       table->Signature[2],
259			       table->Signature[3],
260			       table);
261		if (!strncmp(table->Signature, APIC_SIG, 4)) {
262			parse_madt((APIC_TABLE *) table);
263		}
264	}
265}
266