xref: /illumos-gate/usr/src/cmd/bhyve/pci_irq.c (revision 32640292)
1bf21cd93STycho Nightingale /*-
2*32640292SAndy Fiddaman  * SPDX-License-Identifier: BSD-2-Clause
34c87aefeSPatrick Mooney  *
44c87aefeSPatrick Mooney  * Copyright (c) 2014 Hudson River Trading LLC
5bf21cd93STycho Nightingale  * Written by: John H. Baldwin <jhb@FreeBSD.org>
6bf21cd93STycho Nightingale  * All rights reserved.
7bf21cd93STycho Nightingale  *
8bf21cd93STycho Nightingale  * Redistribution and use in source and binary forms, with or without
9bf21cd93STycho Nightingale  * modification, are permitted provided that the following conditions
10bf21cd93STycho Nightingale  * are met:
11bf21cd93STycho Nightingale  * 1. Redistributions of source code must retain the above copyright
12bf21cd93STycho Nightingale  *    notice, this list of conditions and the following disclaimer.
13bf21cd93STycho Nightingale  * 2. Redistributions in binary form must reproduce the above copyright
14bf21cd93STycho Nightingale  *    notice, this list of conditions and the following disclaimer in the
15bf21cd93STycho Nightingale  *    documentation and/or other materials provided with the distribution.
16bf21cd93STycho Nightingale  *
17bf21cd93STycho Nightingale  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18bf21cd93STycho Nightingale  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19bf21cd93STycho Nightingale  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20bf21cd93STycho Nightingale  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21bf21cd93STycho Nightingale  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22bf21cd93STycho Nightingale  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23bf21cd93STycho Nightingale  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24bf21cd93STycho Nightingale  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25bf21cd93STycho Nightingale  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26bf21cd93STycho Nightingale  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27bf21cd93STycho Nightingale  * SUCH DAMAGE.
28bf21cd93STycho Nightingale  */
29bf21cd93STycho Nightingale 
30bf21cd93STycho Nightingale 
31bf21cd93STycho Nightingale #include <sys/cdefs.h>
32bf21cd93STycho Nightingale 
33bf21cd93STycho Nightingale #include <sys/param.h>
34bf21cd93STycho Nightingale #include <machine/vmm.h>
35bf21cd93STycho Nightingale 
36bf21cd93STycho Nightingale #include <assert.h>
37bf21cd93STycho Nightingale #include <pthread.h>
38bf21cd93STycho Nightingale #include <stdbool.h>
39bf21cd93STycho Nightingale #include <stdio.h>
40bf21cd93STycho Nightingale #include <stdlib.h>
41bf21cd93STycho Nightingale #include <vmmapi.h>
42bf21cd93STycho Nightingale 
43bf21cd93STycho Nightingale #include "acpi.h"
44bf21cd93STycho Nightingale #include "inout.h"
45bf21cd93STycho Nightingale #include "pci_emul.h"
46bf21cd93STycho Nightingale #include "pci_irq.h"
47bf21cd93STycho Nightingale #include "pci_lpc.h"
48bf21cd93STycho Nightingale 
49bf21cd93STycho Nightingale /*
50bf21cd93STycho Nightingale  * Implement an 8 pin PCI interrupt router compatible with the router
51bf21cd93STycho Nightingale  * present on Intel's ICH10 chip.
52bf21cd93STycho Nightingale  */
53bf21cd93STycho Nightingale 
54bf21cd93STycho Nightingale /* Fields in each PIRQ register. */
55bf21cd93STycho Nightingale #define	PIRQ_DIS	0x80
56bf21cd93STycho Nightingale #define	PIRQ_IRQ	0x0f
57bf21cd93STycho Nightingale 
58bf21cd93STycho Nightingale /* Only IRQs 3-7, 9-12, and 14-15 are permitted. */
59bf21cd93STycho Nightingale #define	PERMITTED_IRQS	0xdef8
60bf21cd93STycho Nightingale #define	IRQ_PERMITTED(irq)	(((1U << (irq)) & PERMITTED_IRQS) != 0)
61bf21cd93STycho Nightingale 
62bf21cd93STycho Nightingale /* IRQ count to disable an IRQ. */
63bf21cd93STycho Nightingale #define	IRQ_DISABLED	0xff
64bf21cd93STycho Nightingale 
6559d65d31SAndy Fiddaman #define	NPIRQS		8
66bf21cd93STycho Nightingale static struct pirq {
67bf21cd93STycho Nightingale 	uint8_t	reg;
68bf21cd93STycho Nightingale 	int	use_count;
69bf21cd93STycho Nightingale 	int	active_count;
70bf21cd93STycho Nightingale 	pthread_mutex_t lock;
7159d65d31SAndy Fiddaman } pirqs[NPIRQS];
72bf21cd93STycho Nightingale 
7359d65d31SAndy Fiddaman #define	NIRQ_COUNTS	16
7459d65d31SAndy Fiddaman static u_char irq_counts[NIRQ_COUNTS];
75bf21cd93STycho Nightingale static int pirq_cold = 1;
76bf21cd93STycho Nightingale 
77bf21cd93STycho Nightingale /*
78bf21cd93STycho Nightingale  * Returns true if this pin is enabled with a valid IRQ.  Setting the
79bf21cd93STycho Nightingale  * register to a reserved IRQ causes interrupts to not be asserted as
80bf21cd93STycho Nightingale  * if the pin was disabled.
81bf21cd93STycho Nightingale  */
82bf21cd93STycho Nightingale static bool
pirq_valid_irq(int reg)83bf21cd93STycho Nightingale pirq_valid_irq(int reg)
84bf21cd93STycho Nightingale {
85bf21cd93STycho Nightingale 
86bf21cd93STycho Nightingale 	if (reg & PIRQ_DIS)
87bf21cd93STycho Nightingale 		return (false);
88bf21cd93STycho Nightingale 	return (IRQ_PERMITTED(reg & PIRQ_IRQ));
89bf21cd93STycho Nightingale }
90bf21cd93STycho Nightingale 
91bf21cd93STycho Nightingale uint8_t
pirq_read(int pin)92bf21cd93STycho Nightingale pirq_read(int pin)
93bf21cd93STycho Nightingale {
94bf21cd93STycho Nightingale 
9559d65d31SAndy Fiddaman 	assert(pin > 0 && pin <= NPIRQS);
96bf21cd93STycho Nightingale 	return (pirqs[pin - 1].reg);
97bf21cd93STycho Nightingale }
98bf21cd93STycho Nightingale 
99bf21cd93STycho Nightingale void
pirq_write(struct vmctx * ctx,int pin,uint8_t val)100bf21cd93STycho Nightingale pirq_write(struct vmctx *ctx, int pin, uint8_t val)
101bf21cd93STycho Nightingale {
102bf21cd93STycho Nightingale 	struct pirq *pirq;
103bf21cd93STycho Nightingale 
10459d65d31SAndy Fiddaman 	assert(pin > 0 && pin <= NPIRQS);
105bf21cd93STycho Nightingale 	pirq = &pirqs[pin - 1];
106bf21cd93STycho Nightingale 	pthread_mutex_lock(&pirq->lock);
107bf21cd93STycho Nightingale 	if (pirq->reg != (val & (PIRQ_DIS | PIRQ_IRQ))) {
108bf21cd93STycho Nightingale 		if (pirq->active_count != 0 && pirq_valid_irq(pirq->reg))
109bf21cd93STycho Nightingale 			vm_isa_deassert_irq(ctx, pirq->reg & PIRQ_IRQ, -1);
110bf21cd93STycho Nightingale 		pirq->reg = val & (PIRQ_DIS | PIRQ_IRQ);
111bf21cd93STycho Nightingale 		if (pirq->active_count != 0 && pirq_valid_irq(pirq->reg))
112bf21cd93STycho Nightingale 			vm_isa_assert_irq(ctx, pirq->reg & PIRQ_IRQ, -1);
113bf21cd93STycho Nightingale 	}
114bf21cd93STycho Nightingale 	pthread_mutex_unlock(&pirq->lock);
115bf21cd93STycho Nightingale }
116bf21cd93STycho Nightingale 
117bf21cd93STycho Nightingale void
pci_irq_reserve(int irq)118bf21cd93STycho Nightingale pci_irq_reserve(int irq)
119bf21cd93STycho Nightingale {
120bf21cd93STycho Nightingale 
12159d65d31SAndy Fiddaman 	assert(irq >= 0 && irq < NIRQ_COUNTS);
122bf21cd93STycho Nightingale 	assert(pirq_cold);
123bf21cd93STycho Nightingale 	assert(irq_counts[irq] == 0 || irq_counts[irq] == IRQ_DISABLED);
124bf21cd93STycho Nightingale 	irq_counts[irq] = IRQ_DISABLED;
125bf21cd93STycho Nightingale }
126bf21cd93STycho Nightingale 
127bf21cd93STycho Nightingale void
pci_irq_use(int irq)128bf21cd93STycho Nightingale pci_irq_use(int irq)
129bf21cd93STycho Nightingale {
130bf21cd93STycho Nightingale 
13159d65d31SAndy Fiddaman 	assert(irq >= 0 && irq < NIRQ_COUNTS);
132bf21cd93STycho Nightingale 	assert(pirq_cold);
1334c87aefeSPatrick Mooney 	assert(irq_counts[irq] != IRQ_DISABLED);
1344c87aefeSPatrick Mooney 	irq_counts[irq]++;
135bf21cd93STycho Nightingale }
136bf21cd93STycho Nightingale 
137bf21cd93STycho Nightingale void
pci_irq_init(struct vmctx * ctx __unused)13859d65d31SAndy Fiddaman pci_irq_init(struct vmctx *ctx __unused)
139bf21cd93STycho Nightingale {
140bf21cd93STycho Nightingale 	int i;
141bf21cd93STycho Nightingale 
14259d65d31SAndy Fiddaman 	for (i = 0; i < NPIRQS; i++) {
143bf21cd93STycho Nightingale 		pirqs[i].reg = PIRQ_DIS;
144bf21cd93STycho Nightingale 		pirqs[i].use_count = 0;
145bf21cd93STycho Nightingale 		pirqs[i].active_count = 0;
146bf21cd93STycho Nightingale 		pthread_mutex_init(&pirqs[i].lock, NULL);
147bf21cd93STycho Nightingale 	}
14859d65d31SAndy Fiddaman 	for (i = 0; i < NIRQ_COUNTS; i++) {
149bf21cd93STycho Nightingale 		if (IRQ_PERMITTED(i))
150bf21cd93STycho Nightingale 			irq_counts[i] = 0;
151bf21cd93STycho Nightingale 		else
152bf21cd93STycho Nightingale 			irq_counts[i] = IRQ_DISABLED;
153bf21cd93STycho Nightingale 	}
154bf21cd93STycho Nightingale }
155bf21cd93STycho Nightingale 
156bf21cd93STycho Nightingale void
pci_irq_assert(struct pci_devinst * pi)157bf21cd93STycho Nightingale pci_irq_assert(struct pci_devinst *pi)
158bf21cd93STycho Nightingale {
159bf21cd93STycho Nightingale 	struct pirq *pirq;
16059d65d31SAndy Fiddaman 	int pin;
161bf21cd93STycho Nightingale 
16259d65d31SAndy Fiddaman 	pin = pi->pi_lintr.pirq_pin;
16359d65d31SAndy Fiddaman 	if (pin > 0) {
16459d65d31SAndy Fiddaman 		assert(pin <= NPIRQS);
16559d65d31SAndy Fiddaman 		pirq = &pirqs[pin - 1];
166bf21cd93STycho Nightingale 		pthread_mutex_lock(&pirq->lock);
167bf21cd93STycho Nightingale 		pirq->active_count++;
168bf21cd93STycho Nightingale 		if (pirq->active_count == 1 && pirq_valid_irq(pirq->reg)) {
169bf21cd93STycho Nightingale 			vm_isa_assert_irq(pi->pi_vmctx, pirq->reg & PIRQ_IRQ,
170bf21cd93STycho Nightingale 			    pi->pi_lintr.ioapic_irq);
171bf21cd93STycho Nightingale 			pthread_mutex_unlock(&pirq->lock);
172bf21cd93STycho Nightingale 			return;
173bf21cd93STycho Nightingale 		}
174bf21cd93STycho Nightingale 		pthread_mutex_unlock(&pirq->lock);
175bf21cd93STycho Nightingale 	}
176bf21cd93STycho Nightingale 	vm_ioapic_assert_irq(pi->pi_vmctx, pi->pi_lintr.ioapic_irq);
177bf21cd93STycho Nightingale }
178bf21cd93STycho Nightingale 
179bf21cd93STycho Nightingale void
pci_irq_deassert(struct pci_devinst * pi)180bf21cd93STycho Nightingale pci_irq_deassert(struct pci_devinst *pi)
181bf21cd93STycho Nightingale {
182bf21cd93STycho Nightingale 	struct pirq *pirq;
18359d65d31SAndy Fiddaman 	int pin;
184bf21cd93STycho Nightingale 
18559d65d31SAndy Fiddaman 	pin = pi->pi_lintr.pirq_pin;
18659d65d31SAndy Fiddaman 	if (pin > 0) {
18759d65d31SAndy Fiddaman 		assert(pin <= NPIRQS);
18859d65d31SAndy Fiddaman 		pirq = &pirqs[pin - 1];
189bf21cd93STycho Nightingale 		pthread_mutex_lock(&pirq->lock);
190bf21cd93STycho Nightingale 		pirq->active_count--;
191bf21cd93STycho Nightingale 		if (pirq->active_count == 0 && pirq_valid_irq(pirq->reg)) {
192bf21cd93STycho Nightingale 			vm_isa_deassert_irq(pi->pi_vmctx, pirq->reg & PIRQ_IRQ,
193bf21cd93STycho Nightingale 			    pi->pi_lintr.ioapic_irq);
194bf21cd93STycho Nightingale 			pthread_mutex_unlock(&pirq->lock);
195bf21cd93STycho Nightingale 			return;
196bf21cd93STycho Nightingale 		}
197bf21cd93STycho Nightingale 		pthread_mutex_unlock(&pirq->lock);
198bf21cd93STycho Nightingale 	}
199bf21cd93STycho Nightingale 	vm_ioapic_deassert_irq(pi->pi_vmctx, pi->pi_lintr.ioapic_irq);
200bf21cd93STycho Nightingale }
201bf21cd93STycho Nightingale 
202bf21cd93STycho Nightingale int
pirq_alloc_pin(struct pci_devinst * pi)2034c87aefeSPatrick Mooney pirq_alloc_pin(struct pci_devinst *pi)
204bf21cd93STycho Nightingale {
2054c87aefeSPatrick Mooney 	struct vmctx *ctx = pi->pi_vmctx;
206bf21cd93STycho Nightingale 	int best_count, best_irq, best_pin, irq, pin;
207bf21cd93STycho Nightingale 
2084c87aefeSPatrick Mooney 	pirq_cold = 0;
2094c87aefeSPatrick Mooney 
2104c87aefeSPatrick Mooney 	if (lpc_bootrom()) {
2114c87aefeSPatrick Mooney 		/* For external bootrom use fixed mapping. */
2124c87aefeSPatrick Mooney 		best_pin = (4 + pi->pi_slot + pi->pi_lintr.pin) % 8;
2134c87aefeSPatrick Mooney 	} else {
2144c87aefeSPatrick Mooney 		/* Find the least-used PIRQ pin. */
2154c87aefeSPatrick Mooney 		best_pin = 0;
2164c87aefeSPatrick Mooney 		best_count = pirqs[0].use_count;
21759d65d31SAndy Fiddaman 		for (pin = 1; pin < NPIRQS; pin++) {
2184c87aefeSPatrick Mooney 			if (pirqs[pin].use_count < best_count) {
2194c87aefeSPatrick Mooney 				best_pin = pin;
2204c87aefeSPatrick Mooney 				best_count = pirqs[pin].use_count;
2214c87aefeSPatrick Mooney 			}
222bf21cd93STycho Nightingale 		}
223bf21cd93STycho Nightingale 	}
224bf21cd93STycho Nightingale 	pirqs[best_pin].use_count++;
225bf21cd93STycho Nightingale 
226bf21cd93STycho Nightingale 	/* Second, route this pin to an IRQ. */
227bf21cd93STycho Nightingale 	if (pirqs[best_pin].reg == PIRQ_DIS) {
228bf21cd93STycho Nightingale 		best_irq = -1;
229bf21cd93STycho Nightingale 		best_count = 0;
23059d65d31SAndy Fiddaman 		for (irq = 0; irq < NIRQ_COUNTS; irq++) {
231bf21cd93STycho Nightingale 			if (irq_counts[irq] == IRQ_DISABLED)
232bf21cd93STycho Nightingale 				continue;
233bf21cd93STycho Nightingale 			if (best_irq == -1 || irq_counts[irq] < best_count) {
234bf21cd93STycho Nightingale 				best_irq = irq;
235bf21cd93STycho Nightingale 				best_count = irq_counts[irq];
236bf21cd93STycho Nightingale 			}
237bf21cd93STycho Nightingale 		}
2384c87aefeSPatrick Mooney 		assert(best_irq >= 0);
239bf21cd93STycho Nightingale 		irq_counts[best_irq]++;
240bf21cd93STycho Nightingale 		pirqs[best_pin].reg = best_irq;
241bf21cd93STycho Nightingale 		vm_isa_set_irq_trigger(ctx, best_irq, LEVEL_TRIGGER);
242bf21cd93STycho Nightingale 	}
243bf21cd93STycho Nightingale 
244bf21cd93STycho Nightingale 	return (best_pin + 1);
245bf21cd93STycho Nightingale }
246bf21cd93STycho Nightingale 
247bf21cd93STycho Nightingale int
pirq_irq(int pin)248bf21cd93STycho Nightingale pirq_irq(int pin)
249bf21cd93STycho Nightingale {
25059d65d31SAndy Fiddaman 	assert(pin > 0 && pin <= NPIRQS);
251bf21cd93STycho Nightingale 	return (pirqs[pin - 1].reg & PIRQ_IRQ);
252bf21cd93STycho Nightingale }
253bf21cd93STycho Nightingale 
254bf21cd93STycho Nightingale /* XXX: Generate $PIR table. */
255bf21cd93STycho Nightingale 
256bf21cd93STycho Nightingale static void
pirq_dsdt(void)257bf21cd93STycho Nightingale pirq_dsdt(void)
258bf21cd93STycho Nightingale {
259bf21cd93STycho Nightingale 	char *irq_prs, *old;
260bf21cd93STycho Nightingale 	int irq, pin;
261bf21cd93STycho Nightingale 
262bf21cd93STycho Nightingale 	irq_prs = NULL;
26359d65d31SAndy Fiddaman 	for (irq = 0; irq < NIRQ_COUNTS; irq++) {
264bf21cd93STycho Nightingale 		if (!IRQ_PERMITTED(irq))
265bf21cd93STycho Nightingale 			continue;
266bf21cd93STycho Nightingale 		if (irq_prs == NULL)
267bf21cd93STycho Nightingale 			asprintf(&irq_prs, "%d", irq);
268bf21cd93STycho Nightingale 		else {
269bf21cd93STycho Nightingale 			old = irq_prs;
270bf21cd93STycho Nightingale 			asprintf(&irq_prs, "%s,%d", old, irq);
271bf21cd93STycho Nightingale 			free(old);
272bf21cd93STycho Nightingale 		}
273bf21cd93STycho Nightingale 	}
274bf21cd93STycho Nightingale 
275bf21cd93STycho Nightingale 	/*
276bf21cd93STycho Nightingale 	 * A helper method to validate a link register's value.  This
277bf21cd93STycho Nightingale 	 * duplicates pirq_valid_irq().
278bf21cd93STycho Nightingale 	 */
279bf21cd93STycho Nightingale 	dsdt_line("");
280bf21cd93STycho Nightingale 	dsdt_line("Method (PIRV, 1, NotSerialized)");
281bf21cd93STycho Nightingale 	dsdt_line("{");
282bf21cd93STycho Nightingale 	dsdt_line("  If (And (Arg0, 0x%02X))", PIRQ_DIS);
283bf21cd93STycho Nightingale 	dsdt_line("  {");
284bf21cd93STycho Nightingale 	dsdt_line("    Return (0x00)");
285bf21cd93STycho Nightingale 	dsdt_line("  }");
286bf21cd93STycho Nightingale 	dsdt_line("  And (Arg0, 0x%02X, Local0)", PIRQ_IRQ);
287bf21cd93STycho Nightingale 	dsdt_line("  If (LLess (Local0, 0x03))");
288bf21cd93STycho Nightingale 	dsdt_line("  {");
289bf21cd93STycho Nightingale 	dsdt_line("    Return (0x00)");
290bf21cd93STycho Nightingale 	dsdt_line("  }");
291bf21cd93STycho Nightingale 	dsdt_line("  If (LEqual (Local0, 0x08))");
292bf21cd93STycho Nightingale 	dsdt_line("  {");
293bf21cd93STycho Nightingale 	dsdt_line("    Return (0x00)");
294bf21cd93STycho Nightingale 	dsdt_line("  }");
295bf21cd93STycho Nightingale 	dsdt_line("  If (LEqual (Local0, 0x0D))");
296bf21cd93STycho Nightingale 	dsdt_line("  {");
297bf21cd93STycho Nightingale 	dsdt_line("    Return (0x00)");
298bf21cd93STycho Nightingale 	dsdt_line("  }");
299bf21cd93STycho Nightingale 	dsdt_line("  Return (0x01)");
300bf21cd93STycho Nightingale 	dsdt_line("}");
301bf21cd93STycho Nightingale 
30259d65d31SAndy Fiddaman 	for (pin = 0; pin < NPIRQS; pin++) {
303bf21cd93STycho Nightingale 		dsdt_line("");
304bf21cd93STycho Nightingale 		dsdt_line("Device (LNK%c)", 'A' + pin);
305bf21cd93STycho Nightingale 		dsdt_line("{");
306bf21cd93STycho Nightingale 		dsdt_line("  Name (_HID, EisaId (\"PNP0C0F\"))");
307bf21cd93STycho Nightingale 		dsdt_line("  Name (_UID, 0x%02X)", pin + 1);
308bf21cd93STycho Nightingale 		dsdt_line("  Method (_STA, 0, NotSerialized)");
309bf21cd93STycho Nightingale 		dsdt_line("  {");
310bf21cd93STycho Nightingale 		dsdt_line("    If (PIRV (PIR%c))", 'A' + pin);
311bf21cd93STycho Nightingale 		dsdt_line("    {");
312bf21cd93STycho Nightingale 		dsdt_line("       Return (0x0B)");
313bf21cd93STycho Nightingale 		dsdt_line("    }");
314bf21cd93STycho Nightingale 		dsdt_line("    Else");
315bf21cd93STycho Nightingale 		dsdt_line("    {");
316bf21cd93STycho Nightingale 		dsdt_line("       Return (0x09)");
317bf21cd93STycho Nightingale 		dsdt_line("    }");
318bf21cd93STycho Nightingale 		dsdt_line("  }");
319bf21cd93STycho Nightingale 		dsdt_line("  Name (_PRS, ResourceTemplate ()");
320bf21cd93STycho Nightingale 		dsdt_line("  {");
321bf21cd93STycho Nightingale 		dsdt_line("    IRQ (Level, ActiveLow, Shared, )");
322bf21cd93STycho Nightingale 		dsdt_line("      {%s}", irq_prs);
323bf21cd93STycho Nightingale 		dsdt_line("  })");
324bf21cd93STycho Nightingale 		dsdt_line("  Name (CB%02X, ResourceTemplate ()", pin + 1);
325bf21cd93STycho Nightingale 		dsdt_line("  {");
326bf21cd93STycho Nightingale 		dsdt_line("    IRQ (Level, ActiveLow, Shared, )");
327bf21cd93STycho Nightingale 		dsdt_line("      {}");
328bf21cd93STycho Nightingale 		dsdt_line("  })");
329bf21cd93STycho Nightingale 		dsdt_line("  CreateWordField (CB%02X, 0x01, CIR%c)",
330bf21cd93STycho Nightingale 		    pin + 1, 'A' + pin);
331bf21cd93STycho Nightingale 		dsdt_line("  Method (_CRS, 0, NotSerialized)");
332bf21cd93STycho Nightingale 		dsdt_line("  {");
333bf21cd93STycho Nightingale 		dsdt_line("    And (PIR%c, 0x%02X, Local0)", 'A' + pin,
334bf21cd93STycho Nightingale 		    PIRQ_DIS | PIRQ_IRQ);
335bf21cd93STycho Nightingale 		dsdt_line("    If (PIRV (Local0))");
336bf21cd93STycho Nightingale 		dsdt_line("    {");
337bf21cd93STycho Nightingale 		dsdt_line("      ShiftLeft (0x01, Local0, CIR%c)", 'A' + pin);
338bf21cd93STycho Nightingale 		dsdt_line("    }");
339bf21cd93STycho Nightingale 		dsdt_line("    Else");
340bf21cd93STycho Nightingale 		dsdt_line("    {");
341bf21cd93STycho Nightingale 		dsdt_line("      Store (0x00, CIR%c)", 'A' + pin);
342bf21cd93STycho Nightingale 		dsdt_line("    }");
343bf21cd93STycho Nightingale 		dsdt_line("    Return (CB%02X)", pin + 1);
344bf21cd93STycho Nightingale 		dsdt_line("  }");
345bf21cd93STycho Nightingale 		dsdt_line("  Method (_DIS, 0, NotSerialized)");
346bf21cd93STycho Nightingale 		dsdt_line("  {");
347bf21cd93STycho Nightingale 		dsdt_line("    Store (0x80, PIR%c)", 'A' + pin);
348bf21cd93STycho Nightingale 		dsdt_line("  }");
349bf21cd93STycho Nightingale 		dsdt_line("  Method (_SRS, 1, NotSerialized)");
350bf21cd93STycho Nightingale 		dsdt_line("  {");
351bf21cd93STycho Nightingale 		dsdt_line("    CreateWordField (Arg0, 0x01, SIR%c)", 'A' + pin);
352bf21cd93STycho Nightingale 		dsdt_line("    FindSetRightBit (SIR%c, Local0)", 'A' + pin);
353bf21cd93STycho Nightingale 		dsdt_line("    Store (Decrement (Local0), PIR%c)", 'A' + pin);
354bf21cd93STycho Nightingale 		dsdt_line("  }");
355bf21cd93STycho Nightingale 		dsdt_line("}");
356bf21cd93STycho Nightingale 	}
357bf21cd93STycho Nightingale 	free(irq_prs);
358bf21cd93STycho Nightingale }
359bf21cd93STycho Nightingale LPC_DSDT(pirq_dsdt);
360