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