madt.c revision 84541
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 84541 2001-10-05 10:30:09Z dfr $
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
93
94static void
95parse_interrupt_override(INTERRUPT_SOURCE_OVERRIDE *override)
96{
97	if (bootverbose)
98		printf("\t\tBus=%d, Source=%d, Irq=0x%x\n",
99		       override->Bus,
100		       override->Source,
101		       override->GlobalSystemInterrupt);
102}
103
104static void
105parse_io_sapic(IO_SAPIC *sapic)
106{
107	if (bootverbose)
108		printf("\t\tId=0x%x, Vector=0x%x, Address=0x%lx\n",
109		       sapic->IoSapicId,
110		       sapic->Vector,
111		       sapic->IoSapicAddress);
112	sapic_create(sapic->IoSapicId, sapic->Vector, sapic->IoSapicAddress);
113}
114
115static void
116parse_local_sapic(LOCAL_SAPIC *sapic)
117{
118	if (bootverbose)
119		printf("\t\tProcessorId=0x%x, Id=0x%x, Eid=0x%x\n",
120		       sapic->ProcessorId,
121		       sapic->LocalSapicId,
122		       sapic->LocalSapicEid);
123}
124
125static void
126parse_platform_interrupt(PLATFORM_INTERRUPT_SOURCE *source)
127{
128	if (bootverbose)
129		printf("\t\tPolarity=%d, TriggerMode=%d, Id=0x%x, "
130		       "Eid=0x%x, Vector=0x%x, Irq=%d\n",
131		       source->Polarity,
132		       source->TriggerMode,
133		       source->ProcessorId,
134		       source->ProcessorEid,
135		       source->IoSapicVector,
136		       source->GlobalSystemInterrupt);
137}
138
139static void
140parse_madt(APIC_TABLE *madt)
141{
142	char			*p, *end;
143
144	/*
145	 * MADT header is followed by a number of variable length
146	 * structures.
147	 */
148	end = (char *) madt + madt->header.Length;
149	for (p = (char *) (madt + 1); p < end; ) {
150		APIC_HEADER *head = (APIC_HEADER *) p;
151
152		if (bootverbose)
153			printf("\t");
154		switch (head->Type) {
155		case APIC_PROC:
156			if (bootverbose)
157				printf("Processor APIC entry\n");
158			break;
159
160		case APIC_IO:
161			if (bootverbose)
162				printf("I/O APIC entry\n");
163			break;
164
165		case APIC_INTERRUPT_SOURCE_OVERRIDE:
166			if (bootverbose)
167				printf("Interrupt source override entry\n");
168			parse_interrupt_override
169				((INTERRUPT_SOURCE_OVERRIDE *) head);
170			break;
171
172		case APIC_NMI:
173			if (bootverbose)
174				printf("NMI entry\n");
175			break;
176
177		case APIC_LOCAL_APIC_NMI:
178			if (bootverbose)
179				printf("Local APIC NMI entry\n");
180			break;
181
182		case APIC_LOCAL_APIC_OVERRIDE:
183			if (bootverbose)
184				printf("Local APIC override entry\n");
185			break;
186
187		case APIC_IO_SAPIC:
188			if (bootverbose)
189				printf("I/O SAPIC entry\n");
190			parse_io_sapic((IO_SAPIC *) head);
191			break;
192
193		case APIC_LOCAL_SAPIC:
194			if (bootverbose)
195				printf("Local SAPIC entry\n");
196			parse_local_sapic((LOCAL_SAPIC *) head);
197			break;
198
199		case APIC_PLATFORM_INTERRUPT:
200			if (bootverbose)
201				printf("Platform interrupt entry\n");
202			parse_platform_interrupt
203				((PLATFORM_INTERRUPT_SOURCE *) head);
204			break;
205
206		default:
207			if (bootverbose)
208				printf("Unknown type %d entry\n", head->Type);
209			break;
210		}
211
212		p = p + head->Length;
213	}
214}
215
216void
217ia64_parse_xsdt(XSDT_DESCRIPTOR *xsdt)
218{
219	int			i, count;
220	ACPI_TABLE_HEADER	*table;
221
222	/*
223	 * First find the MADT.
224	 */
225	count = (UINT64 *) ((char *) xsdt + xsdt->Header.Length)
226		- &xsdt->TableOffsetEntry[0];
227	for (i = 0; i < count; i++) {
228		table = (ACPI_TABLE_HEADER *)
229			IA64_PHYS_TO_RR7(xsdt->TableOffsetEntry[i]);
230		if (bootverbose)
231			printf("Table '%c%c%c%c' at %p\n",
232			       table->Signature[0],
233			       table->Signature[1],
234			       table->Signature[2],
235			       table->Signature[3],
236			       table);
237		if (!strncmp(table->Signature, APIC_SIG, 4)) {
238			parse_madt((APIC_TABLE *) table);
239		}
240	}
241}
242