Sun Sep 23 00:26:26 2012 UTC ()
re-enable the code to disable link devices at startup, ie. revert rev 1.3.
this fixes PCI interrupts on some systems (eg. HP XW9400) and we suspect that
the problems which led to the original change were caused by buggy early
implementations of ACPI, which are now ignored by date.


(chs)
diff -r1.18 -r1.19 src/sys/dev/acpi/acpi_pci_link.c

cvs diff -r1.18 -r1.19 src/sys/dev/acpi/acpi_pci_link.c (switch to unified diff)

--- src/sys/dev/acpi/acpi_pci_link.c 2010/04/23 15:52:26 1.18
+++ src/sys/dev/acpi/acpi_pci_link.c 2012/09/23 00:26:25 1.19
@@ -1,1271 +1,1269 @@ @@ -1,1271 +1,1269 @@
1/* $NetBSD: acpi_pci_link.c,v 1.18 2010/04/23 15:52:26 jruoho Exp $ */ 1/* $NetBSD: acpi_pci_link.c,v 1.19 2012/09/23 00:26:25 chs Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2002 Mitsuru IWASAKI <iwasaki@jp.freebsd.org> 4 * Copyright (c) 2002 Mitsuru IWASAKI <iwasaki@jp.freebsd.org>
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE. 26 * SUCH DAMAGE.
27 */ 27 */
28 28
29#include <sys/cdefs.h> 29#include <sys/cdefs.h>
30__KERNEL_RCSID(0, "$NetBSD: acpi_pci_link.c,v 1.18 2010/04/23 15:52:26 jruoho Exp $"); 30__KERNEL_RCSID(0, "$NetBSD: acpi_pci_link.c,v 1.19 2012/09/23 00:26:25 chs Exp $");
31 31
32#include <sys/param.h> 32#include <sys/param.h>
33#include <sys/malloc.h> 33#include <sys/malloc.h>
34#include <sys/queue.h> 34#include <sys/queue.h>
35#include <sys/reboot.h> 35#include <sys/reboot.h>
36#include <sys/systm.h> 36#include <sys/systm.h>
37 37
38#include <dev/acpi/acpireg.h> 38#include <dev/acpi/acpireg.h>
39#include <dev/acpi/acpivar.h> 39#include <dev/acpi/acpivar.h>
40 40
41#include <dev/pci/pcireg.h> 41#include <dev/pci/pcireg.h>
42 42
43#include "opt_acpi.h" 43#include "opt_acpi.h"
44 44
45 45
46#define _COMPONENT ACPI_BUS_COMPONENT 46#define _COMPONENT ACPI_BUS_COMPONENT
47ACPI_MODULE_NAME ("acpi_pci_link") 47ACPI_MODULE_NAME ("acpi_pci_link")
48 48
49MALLOC_DECLARE(M_ACPI); 49MALLOC_DECLARE(M_ACPI);
50 50
51#define NUM_ISA_INTERRUPTS 16 51#define NUM_ISA_INTERRUPTS 16
52#define NUM_ACPI_INTERRUPTS 256 52#define NUM_ACPI_INTERRUPTS 256
53 53
54#define PCI_INVALID_IRQ 255 54#define PCI_INVALID_IRQ 255
55#define PCI_INTERRUPT_VALID(x) ((x) != PCI_INVALID_IRQ && (x) != 0) 55#define PCI_INTERRUPT_VALID(x) ((x) != PCI_INVALID_IRQ && (x) != 0)
56 56
57#define ACPI_SERIAL_BEGIN(x) 57#define ACPI_SERIAL_BEGIN(x)
58#define ACPI_SERIAL_END(x) 58#define ACPI_SERIAL_END(x)
59 59
60/* 60/*
61 * An ACPI PCI link device may contain multiple links. Each link has its 61 * An ACPI PCI link device may contain multiple links. Each link has its
62 * own ACPI resource. _PRT entries specify which link is being used via 62 * own ACPI resource. _PRT entries specify which link is being used via
63 * the Source Index. 63 * the Source Index.
64 * 64 *
65 * XXX: A note about Source Indices and DPFs: Currently we assume that 65 * XXX: A note about Source Indices and DPFs: Currently we assume that
66 * the DPF start and end tags are not counted towards the index that 66 * the DPF start and end tags are not counted towards the index that
67 * Source Index corresponds to. Also, we assume that when DPFs are in use 67 * Source Index corresponds to. Also, we assume that when DPFs are in use
68 * they various sets overlap in terms of Indices. Here's an example 68 * they various sets overlap in terms of Indices. Here's an example
69 * resource list indicating these assumptions: 69 * resource list indicating these assumptions:
70 * 70 *
71 * Resource Index 71 * Resource Index
72 * -------- ----- 72 * -------- -----
73 * I/O Port 0 73 * I/O Port 0
74 * Start DPF - 74 * Start DPF -
75 * IRQ 1 75 * IRQ 1
76 * MemIO 2 76 * MemIO 2
77 * Start DPF - 77 * Start DPF -
78 * IRQ 1 78 * IRQ 1
79 * MemIO 2 79 * MemIO 2
80 * End DPF - 80 * End DPF -
81 * DMA Channel 3 81 * DMA Channel 3
82 * 82 *
83 * The XXX is because I'm not sure if this is a valid assumption to make. 83 * The XXX is because I'm not sure if this is a valid assumption to make.
84 */ 84 */
85 85
86/* States during DPF processing. */ 86/* States during DPF processing. */
87#define DPF_OUTSIDE 0 87#define DPF_OUTSIDE 0
88#define DPF_FIRST 1 88#define DPF_FIRST 1
89#define DPF_IGNORE 2 89#define DPF_IGNORE 2
90 90
91struct link; 91struct link;
92 92
93struct acpi_pci_link_softc { 93struct acpi_pci_link_softc {
94 int pl_num_links; 94 int pl_num_links;
95 int pl_crs_bad; 95 int pl_crs_bad;
96 struct link *pl_links; 96 struct link *pl_links;
97 char pl_name[32]; 97 char pl_name[32];
98 ACPI_HANDLE pl_handle; 98 ACPI_HANDLE pl_handle;
99 TAILQ_ENTRY(acpi_pci_link_softc) pl_list; 99 TAILQ_ENTRY(acpi_pci_link_softc) pl_list;
100}; 100};
101 101
102static TAILQ_HEAD(, acpi_pci_link_softc) acpi_pci_linkdevs = 102static TAILQ_HEAD(, acpi_pci_link_softc) acpi_pci_linkdevs =
103 TAILQ_HEAD_INITIALIZER(acpi_pci_linkdevs); 103 TAILQ_HEAD_INITIALIZER(acpi_pci_linkdevs);
104 104
105 105
106struct link { 106struct link {
107 struct acpi_pci_link_softc *l_sc; 107 struct acpi_pci_link_softc *l_sc;
108 uint8_t l_bios_irq; 108 uint8_t l_bios_irq;
109 uint8_t l_irq; 109 uint8_t l_irq;
110 uint8_t l_trig; 110 uint8_t l_trig;
111 uint8_t l_pol; 111 uint8_t l_pol;
112 uint8_t l_initial_irq; 112 uint8_t l_initial_irq;
113 int l_res_index; 113 int l_res_index;
114 int l_num_irqs; 114 int l_num_irqs;
115 int *l_irqs; 115 int *l_irqs;
116 int l_references; 116 int l_references;
117 int l_dev_count; 117 int l_dev_count;
118 pcitag_t *l_devices; 118 pcitag_t *l_devices;
119 int l_routed:1; 119 int l_routed:1;
120 int l_isa_irq:1; 120 int l_isa_irq:1;
121 ACPI_RESOURCE l_prs_template; 121 ACPI_RESOURCE l_prs_template;
122}; 122};
123 123
124struct link_count_request { 124struct link_count_request {
125 int in_dpf; 125 int in_dpf;
126 int count; 126 int count;
127}; 127};
128 128
129struct link_res_request { 129struct link_res_request {
130 struct acpi_pci_link_softc *sc; 130 struct acpi_pci_link_softc *sc;
131 int in_dpf; 131 int in_dpf;
132 int res_index; 132 int res_index;
133 int link_index; 133 int link_index;
134}; 134};
135 135
136static int pci_link_interrupt_weights[NUM_ACPI_INTERRUPTS]; 136static int pci_link_interrupt_weights[NUM_ACPI_INTERRUPTS];
137static int pci_link_bios_isa_irqs; 137static int pci_link_bios_isa_irqs;
138 138
139static ACPI_STATUS acpi_count_irq_resources(ACPI_RESOURCE *, void *); 139static ACPI_STATUS acpi_count_irq_resources(ACPI_RESOURCE *, void *);
140static ACPI_STATUS link_add_crs(ACPI_RESOURCE *, void *); 140static ACPI_STATUS link_add_crs(ACPI_RESOURCE *, void *);
141static ACPI_STATUS link_add_prs(ACPI_RESOURCE *, void *); 141static ACPI_STATUS link_add_prs(ACPI_RESOURCE *, void *);
142static int link_valid_irq(struct link *, int); 142static int link_valid_irq(struct link *, int);
143static void acpi_pci_link_dump(struct acpi_pci_link_softc *); 143static void acpi_pci_link_dump(struct acpi_pci_link_softc *);
144static int acpi_pci_link_attach(struct acpi_pci_link_softc *); 144static int acpi_pci_link_attach(struct acpi_pci_link_softc *);
145static uint8_t acpi_pci_link_search_irq(struct acpi_pci_link_softc *, int, int, 145static uint8_t acpi_pci_link_search_irq(struct acpi_pci_link_softc *, int, int,
146 int); 146 int);
147static struct link *acpi_pci_link_lookup(struct acpi_pci_link_softc *, int); 147static struct link *acpi_pci_link_lookup(struct acpi_pci_link_softc *, int);
148static ACPI_STATUS acpi_pci_link_srs(struct acpi_pci_link_softc *, 148static ACPI_STATUS acpi_pci_link_srs(struct acpi_pci_link_softc *,
149 ACPI_BUFFER *); 149 ACPI_BUFFER *);
150static ACPI_STATUS acpi_AppendBufferResource(ACPI_BUFFER *, ACPI_RESOURCE *); 150static ACPI_STATUS acpi_AppendBufferResource(ACPI_BUFFER *, ACPI_RESOURCE *);
151 151
152static ACPI_STATUS 152static ACPI_STATUS
153acpi_count_irq_resources(ACPI_RESOURCE *res, void *context) 153acpi_count_irq_resources(ACPI_RESOURCE *res, void *context)
154{ 154{
155 struct link_count_request *req; 155 struct link_count_request *req;
156 156
157 req = (struct link_count_request *)context; 157 req = (struct link_count_request *)context;
158 switch (res->Type) { 158 switch (res->Type) {
159 case ACPI_RESOURCE_TYPE_START_DEPENDENT: 159 case ACPI_RESOURCE_TYPE_START_DEPENDENT:
160 switch (req->in_dpf) { 160 switch (req->in_dpf) {
161 case DPF_OUTSIDE: 161 case DPF_OUTSIDE:
162 /* We've started the first DPF. */ 162 /* We've started the first DPF. */
163 req->in_dpf = DPF_FIRST; 163 req->in_dpf = DPF_FIRST;
164 break; 164 break;
165 case DPF_FIRST: 165 case DPF_FIRST:
166 /* We've started the second DPF. */ 166 /* We've started the second DPF. */
167 req->in_dpf = DPF_IGNORE; 167 req->in_dpf = DPF_IGNORE;
168 break; 168 break;
169 } 169 }
170 break; 170 break;
171 case ACPI_RESOURCE_TYPE_END_DEPENDENT: 171 case ACPI_RESOURCE_TYPE_END_DEPENDENT:
172 /* We are finished with DPF parsing. */ 172 /* We are finished with DPF parsing. */
173 KASSERT(req->in_dpf != DPF_OUTSIDE); 173 KASSERT(req->in_dpf != DPF_OUTSIDE);
174 req->in_dpf = DPF_OUTSIDE; 174 req->in_dpf = DPF_OUTSIDE;
175 break; 175 break;
176 case ACPI_RESOURCE_TYPE_IRQ: 176 case ACPI_RESOURCE_TYPE_IRQ:
177 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: 177 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
178 /* 178 /*
179 * Don't count resources if we are in a DPF set that we are 179 * Don't count resources if we are in a DPF set that we are
180 * ignoring. 180 * ignoring.
181 */ 181 */
182 if (req->in_dpf != DPF_IGNORE) 182 if (req->in_dpf != DPF_IGNORE)
183 req->count++; 183 req->count++;
184 } 184 }
185 return (AE_OK); 185 return (AE_OK);
186} 186}
187 187
188static ACPI_STATUS 188static ACPI_STATUS
189link_add_crs(ACPI_RESOURCE *res, void *context) 189link_add_crs(ACPI_RESOURCE *res, void *context)
190{ 190{
191 struct link_res_request *req; 191 struct link_res_request *req;
192 struct link *link; 192 struct link *link;
193 193
194 req = (struct link_res_request *)context; 194 req = (struct link_res_request *)context;
195 switch (res->Type) { 195 switch (res->Type) {
196 case ACPI_RESOURCE_TYPE_START_DEPENDENT: 196 case ACPI_RESOURCE_TYPE_START_DEPENDENT:
197 switch (req->in_dpf) { 197 switch (req->in_dpf) {
198 case DPF_OUTSIDE: 198 case DPF_OUTSIDE:
199 /* We've started the first DPF. */ 199 /* We've started the first DPF. */
200 req->in_dpf = DPF_FIRST; 200 req->in_dpf = DPF_FIRST;
201 break; 201 break;
202 case DPF_FIRST: 202 case DPF_FIRST:
203 /* We've started the second DPF. */ 203 /* We've started the second DPF. */
204 panic( 204 panic(
205 "%s: Multiple dependent functions within a current resource", 205 "%s: Multiple dependent functions within a current resource",
206 __func__); 206 __func__);
207 break; 207 break;
208 } 208 }
209 break; 209 break;
210 case ACPI_RESOURCE_TYPE_END_DEPENDENT: 210 case ACPI_RESOURCE_TYPE_END_DEPENDENT:
211 /* We are finished with DPF parsing. */ 211 /* We are finished with DPF parsing. */
212 KASSERT(req->in_dpf != DPF_OUTSIDE); 212 KASSERT(req->in_dpf != DPF_OUTSIDE);
213 req->in_dpf = DPF_OUTSIDE; 213 req->in_dpf = DPF_OUTSIDE;
214 break; 214 break;
215 case ACPI_RESOURCE_TYPE_IRQ: 215 case ACPI_RESOURCE_TYPE_IRQ:
216 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: 216 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
217 KASSERT(req->link_index < req->sc->pl_num_links); 217 KASSERT(req->link_index < req->sc->pl_num_links);
218 link = &req->sc->pl_links[req->link_index]; 218 link = &req->sc->pl_links[req->link_index];
219 link->l_res_index = req->res_index; 219 link->l_res_index = req->res_index;
220 req->link_index++; 220 req->link_index++;
221 req->res_index++; 221 req->res_index++;
222 222
223 /* 223 /*
224 * Only use the current value if there's one IRQ. Some 224 * Only use the current value if there's one IRQ. Some
225 * systems return multiple IRQs (which is nonsense for _CRS) 225 * systems return multiple IRQs (which is nonsense for _CRS)
226 * when the link hasn't been programmed. 226 * when the link hasn't been programmed.
227 */ 227 */
228 if (res->Type == ACPI_RESOURCE_TYPE_IRQ) { 228 if (res->Type == ACPI_RESOURCE_TYPE_IRQ) {
229 if (res->Data.Irq.InterruptCount == 1) { 229 if (res->Data.Irq.InterruptCount == 1) {
230 link->l_irq = res->Data.Irq.Interrupts[0]; 230 link->l_irq = res->Data.Irq.Interrupts[0];
231 link->l_trig = res->Data.Irq.Triggering; 231 link->l_trig = res->Data.Irq.Triggering;
232 link->l_pol = res->Data.Irq.Polarity; 232 link->l_pol = res->Data.Irq.Polarity;
233 } 233 }
234 } else if (res->Data.ExtendedIrq.InterruptCount == 1) { 234 } else if (res->Data.ExtendedIrq.InterruptCount == 1) {
235 link->l_irq = res->Data.ExtendedIrq.Interrupts[0]; 235 link->l_irq = res->Data.ExtendedIrq.Interrupts[0];
236 link->l_trig = res->Data.ExtendedIrq.Triggering; 236 link->l_trig = res->Data.ExtendedIrq.Triggering;
237 link->l_pol = res->Data.ExtendedIrq.Polarity; 237 link->l_pol = res->Data.ExtendedIrq.Polarity;
238 } 238 }
239 239
240 /* 240 /*
241 * An IRQ of zero means that the link isn't routed. 241 * An IRQ of zero means that the link isn't routed.
242 */ 242 */
243 if (link->l_irq == 0) 243 if (link->l_irq == 0)
244 link->l_irq = PCI_INVALID_IRQ; 244 link->l_irq = PCI_INVALID_IRQ;
245 break; 245 break;
246 default: 246 default:
247 req->res_index++; 247 req->res_index++;
248 } 248 }
249 return (AE_OK); 249 return (AE_OK);
250} 250}
251 251
252/* 252/*
253 * Populate the set of possible IRQs for each device. 253 * Populate the set of possible IRQs for each device.
254 */ 254 */
255static ACPI_STATUS 255static ACPI_STATUS
256link_add_prs(ACPI_RESOURCE *res, void *context) 256link_add_prs(ACPI_RESOURCE *res, void *context)
257{ 257{
258 struct link_res_request *req; 258 struct link_res_request *req;
259 struct link *link; 259 struct link *link;
260 uint8_t *irqs = NULL; 260 uint8_t *irqs = NULL;
261 uint32_t *ext_irqs = NULL; 261 uint32_t *ext_irqs = NULL;
262 int i, is_ext_irq = 1; 262 int i, is_ext_irq = 1;
263 263
264 req = (struct link_res_request *)context; 264 req = (struct link_res_request *)context;
265 switch (res->Type) { 265 switch (res->Type) {
266 case ACPI_RESOURCE_TYPE_START_DEPENDENT: 266 case ACPI_RESOURCE_TYPE_START_DEPENDENT:
267 switch (req->in_dpf) { 267 switch (req->in_dpf) {
268 case DPF_OUTSIDE: 268 case DPF_OUTSIDE:
269 /* We've started the first DPF. */ 269 /* We've started the first DPF. */
270 req->in_dpf = DPF_FIRST; 270 req->in_dpf = DPF_FIRST;
271 break; 271 break;
272 case DPF_FIRST: 272 case DPF_FIRST:
273 /* We've started the second DPF. */ 273 /* We've started the second DPF. */
274 req->in_dpf = DPF_IGNORE; 274 req->in_dpf = DPF_IGNORE;
275 break; 275 break;
276 } 276 }
277 break; 277 break;
278 case ACPI_RESOURCE_TYPE_END_DEPENDENT: 278 case ACPI_RESOURCE_TYPE_END_DEPENDENT:
279 /* We are finished with DPF parsing. */ 279 /* We are finished with DPF parsing. */
280 KASSERT(req->in_dpf != DPF_OUTSIDE); 280 KASSERT(req->in_dpf != DPF_OUTSIDE);
281 req->in_dpf = DPF_OUTSIDE; 281 req->in_dpf = DPF_OUTSIDE;
282 break; 282 break;
283 case ACPI_RESOURCE_TYPE_IRQ: 283 case ACPI_RESOURCE_TYPE_IRQ:
284 is_ext_irq = 0; 284 is_ext_irq = 0;
285 /* fall through */ 285 /* fall through */
286 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: 286 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
287 /* 287 /*
288 * Don't parse resources if we are in a DPF set that we are 288 * Don't parse resources if we are in a DPF set that we are
289 * ignoring. 289 * ignoring.
290 */ 290 */
291 if (req->in_dpf == DPF_IGNORE) 291 if (req->in_dpf == DPF_IGNORE)
292 break; 292 break;
293 293
294 KASSERT(req->link_index < req->sc->pl_num_links); 294 KASSERT(req->link_index < req->sc->pl_num_links);
295 link = &req->sc->pl_links[req->link_index]; 295 link = &req->sc->pl_links[req->link_index];
296 if (link->l_res_index == -1) { 296 if (link->l_res_index == -1) {
297 KASSERT(req->sc->pl_crs_bad); 297 KASSERT(req->sc->pl_crs_bad);
298 link->l_res_index = req->res_index; 298 link->l_res_index = req->res_index;
299 } 299 }
300 req->link_index++; 300 req->link_index++;
301 req->res_index++; 301 req->res_index++;
302 302
303 /* 303 /*
304 * Stash a copy of the resource for later use when 304 * Stash a copy of the resource for later use when
305 * doing _SRS. 305 * doing _SRS.
306 * 306 *
307 * Note that in theory res->Length may exceed the size 307 * Note that in theory res->Length may exceed the size
308 * of ACPI_RESOURCE, due to variable length lists in 308 * of ACPI_RESOURCE, due to variable length lists in
309 * subtypes. However, all uses of l_prs_template only 309 * subtypes. However, all uses of l_prs_template only
310 * rely on lists lengths of zero or one, for which 310 * rely on lists lengths of zero or one, for which
311 * sizeof(ACPI_RESOURCE) is sufficient space anyway. 311 * sizeof(ACPI_RESOURCE) is sufficient space anyway.
312 * We cannot read longer than Length bytes, in case we 312 * We cannot read longer than Length bytes, in case we
313 * read off the end of mapped memory. So we read 313 * read off the end of mapped memory. So we read
314 * whichever length is shortest, Length or 314 * whichever length is shortest, Length or
315 * sizeof(ACPI_RESOURCE). 315 * sizeof(ACPI_RESOURCE).
316 */ 316 */
317 KASSERT(res->Length >= ACPI_RS_SIZE_MIN); 317 KASSERT(res->Length >= ACPI_RS_SIZE_MIN);
318 318
319 memset(&link->l_prs_template, 0, sizeof(link->l_prs_template)); 319 memset(&link->l_prs_template, 0, sizeof(link->l_prs_template));
320 memcpy(&link->l_prs_template, res, 320 memcpy(&link->l_prs_template, res,
321 MIN(res->Length, sizeof(link->l_prs_template))); 321 MIN(res->Length, sizeof(link->l_prs_template)));
322 322
323 if (is_ext_irq) { 323 if (is_ext_irq) {
324 link->l_num_irqs = 324 link->l_num_irqs =
325 res->Data.ExtendedIrq.InterruptCount; 325 res->Data.ExtendedIrq.InterruptCount;
326 link->l_trig = res->Data.ExtendedIrq.Triggering; 326 link->l_trig = res->Data.ExtendedIrq.Triggering;
327 link->l_pol = res->Data.ExtendedIrq.Polarity; 327 link->l_pol = res->Data.ExtendedIrq.Polarity;
328 ext_irqs = res->Data.ExtendedIrq.Interrupts; 328 ext_irqs = res->Data.ExtendedIrq.Interrupts;
329 } else { 329 } else {
330 link->l_num_irqs = res->Data.Irq.InterruptCount; 330 link->l_num_irqs = res->Data.Irq.InterruptCount;
331 link->l_trig = res->Data.Irq.Triggering; 331 link->l_trig = res->Data.Irq.Triggering;
332 link->l_pol = res->Data.Irq.Polarity; 332 link->l_pol = res->Data.Irq.Polarity;
333 irqs = res->Data.Irq.Interrupts; 333 irqs = res->Data.Irq.Interrupts;
334 } 334 }
335 if (link->l_num_irqs == 0) 335 if (link->l_num_irqs == 0)
336 break; 336 break;
337 337
338 /* 338 /*
339 * Save a list of the valid IRQs. Also, if all of the 339 * Save a list of the valid IRQs. Also, if all of the
340 * valid IRQs are ISA IRQs, then mark this link as 340 * valid IRQs are ISA IRQs, then mark this link as
341 * routed via an ISA interrupt. 341 * routed via an ISA interrupt.
342 */ 342 */
343 link->l_isa_irq = TRUE; 343 link->l_isa_irq = TRUE;
344 link->l_irqs = malloc(sizeof(int) * link->l_num_irqs, 344 link->l_irqs = malloc(sizeof(int) * link->l_num_irqs,
345 M_ACPI, M_WAITOK | M_ZERO); 345 M_ACPI, M_WAITOK | M_ZERO);
346 for (i = 0; i < link->l_num_irqs; i++) { 346 for (i = 0; i < link->l_num_irqs; i++) {
347 if (is_ext_irq) { 347 if (is_ext_irq) {
348 link->l_irqs[i] = ext_irqs[i]; 348 link->l_irqs[i] = ext_irqs[i];
349 if (ext_irqs[i] >= NUM_ISA_INTERRUPTS) 349 if (ext_irqs[i] >= NUM_ISA_INTERRUPTS)
350 link->l_isa_irq = FALSE; 350 link->l_isa_irq = FALSE;
351 } else { 351 } else {
352 link->l_irqs[i] = irqs[i]; 352 link->l_irqs[i] = irqs[i];
353 if (irqs[i] >= NUM_ISA_INTERRUPTS) 353 if (irqs[i] >= NUM_ISA_INTERRUPTS)
354 link->l_isa_irq = FALSE; 354 link->l_isa_irq = FALSE;
355 } 355 }
356 } 356 }
357 break; 357 break;
358 default: 358 default:
359 if (req->in_dpf == DPF_IGNORE) 359 if (req->in_dpf == DPF_IGNORE)
360 break; 360 break;
361 if (req->sc->pl_crs_bad) 361 if (req->sc->pl_crs_bad)
362 aprint_normal("%s: Warning: possible resource %d " 362 aprint_normal("%s: Warning: possible resource %d "
363 "will be lost during _SRS\n", req->sc->pl_name, 363 "will be lost during _SRS\n", req->sc->pl_name,
364 req->res_index); 364 req->res_index);
365 req->res_index++; 365 req->res_index++;
366 } 366 }
367 return (AE_OK); 367 return (AE_OK);
368} 368}
369 369
370static int 370static int
371link_valid_irq(struct link *link, int irq) 371link_valid_irq(struct link *link, int irq)
372{ 372{
373 int i; 373 int i;
374 374
375 /* Invalid interrupts are never valid. */ 375 /* Invalid interrupts are never valid. */
376 if (!PCI_INTERRUPT_VALID(irq)) 376 if (!PCI_INTERRUPT_VALID(irq))
377 return (FALSE); 377 return (FALSE);
378 378
379 /* Any interrupt in the list of possible interrupts is valid. */ 379 /* Any interrupt in the list of possible interrupts is valid. */
380 for (i = 0; i < link->l_num_irqs; i++) 380 for (i = 0; i < link->l_num_irqs; i++)
381 if (link->l_irqs[i] == irq) 381 if (link->l_irqs[i] == irq)
382 return (TRUE); 382 return (TRUE);
383 383
384 /* 384 /*
385 * For links routed via an ISA interrupt, if the SCI is routed via 385 * For links routed via an ISA interrupt, if the SCI is routed via
386 * an ISA interrupt, the SCI is always treated as a valid IRQ. 386 * an ISA interrupt, the SCI is always treated as a valid IRQ.
387 */ 387 */
388 if (link->l_isa_irq && AcpiGbl_FADT.SciInterrupt == irq && 388 if (link->l_isa_irq && AcpiGbl_FADT.SciInterrupt == irq &&
389 irq < NUM_ISA_INTERRUPTS) 389 irq < NUM_ISA_INTERRUPTS)
390 return (TRUE); 390 return (TRUE);
391 391
392 /* If the interrupt wasn't found in the list it is not valid. */ 392 /* If the interrupt wasn't found in the list it is not valid. */
393 return (FALSE); 393 return (FALSE);
394} 394}
395 395
396void 396void
397acpi_pci_link_state(void) 397acpi_pci_link_state(void)
398{ 398{
399 struct acpi_pci_link_softc *sc; 399 struct acpi_pci_link_softc *sc;
400 400
401 TAILQ_FOREACH(sc, &acpi_pci_linkdevs, pl_list) { 401 TAILQ_FOREACH(sc, &acpi_pci_linkdevs, pl_list) {
402 acpi_pci_link_dump(sc); 402 acpi_pci_link_dump(sc);
403 } 403 }
404} 404}
405 405
406static void 406static void
407acpi_pci_link_dump(struct acpi_pci_link_softc *sc) 407acpi_pci_link_dump(struct acpi_pci_link_softc *sc)
408{ 408{
409 struct link *link; 409 struct link *link;
410 int i, j; 410 int i, j;
411 411
412 printf("Link Device %s:\n", sc->pl_name); 412 printf("Link Device %s:\n", sc->pl_name);
413 printf("Index IRQ Rtd Ref IRQs\n"); 413 printf("Index IRQ Rtd Ref IRQs\n");
414 for (i = 0; i < sc->pl_num_links; i++) { 414 for (i = 0; i < sc->pl_num_links; i++) {
415 link = &sc->pl_links[i]; 415 link = &sc->pl_links[i];
416 printf("%5d %3d %c %3d ", i, link->l_irq, 416 printf("%5d %3d %c %3d ", i, link->l_irq,
417 link->l_routed ? 'Y' : 'N', link->l_references); 417 link->l_routed ? 'Y' : 'N', link->l_references);
418 if (link->l_num_irqs == 0) 418 if (link->l_num_irqs == 0)
419 printf(" none"); 419 printf(" none");
420 else for (j = 0; j < link->l_num_irqs; j++) 420 else for (j = 0; j < link->l_num_irqs; j++)
421 printf(" %d", link->l_irqs[j]); 421 printf(" %d", link->l_irqs[j]);
422 printf(" polarity %u trigger %u\n", link->l_pol, link->l_trig); 422 printf(" polarity %u trigger %u\n", link->l_pol, link->l_trig);
423 } 423 }
424 printf("\n"); 424 printf("\n");
425} 425}
426 426
427static int 427static int
428acpi_pci_link_attach(struct acpi_pci_link_softc *sc) 428acpi_pci_link_attach(struct acpi_pci_link_softc *sc)
429{ 429{
430 struct link_count_request creq; 430 struct link_count_request creq;
431 struct link_res_request rreq; 431 struct link_res_request rreq;
432 ACPI_STATUS status; 432 ACPI_STATUS status;
433 int i; 433 int i;
434 434
435 ACPI_SERIAL_BEGIN(pci_link); 435 ACPI_SERIAL_BEGIN(pci_link);
436 436
437 /* 437 /*
438 * Count the number of current resources so we know how big of 438 * Count the number of current resources so we know how big of
439 * a link array to allocate. On some systems, _CRS is broken, 439 * a link array to allocate. On some systems, _CRS is broken,
440 * so for those systems try to derive the count from _PRS instead. 440 * so for those systems try to derive the count from _PRS instead.
441 */ 441 */
442 creq.in_dpf = DPF_OUTSIDE; 442 creq.in_dpf = DPF_OUTSIDE;
443 creq.count = 0; 443 creq.count = 0;
444 status = AcpiWalkResources(sc->pl_handle, "_CRS", 444 status = AcpiWalkResources(sc->pl_handle, "_CRS",
445 acpi_count_irq_resources, &creq); 445 acpi_count_irq_resources, &creq);
446 sc->pl_crs_bad = ACPI_FAILURE(status); 446 sc->pl_crs_bad = ACPI_FAILURE(status);
447 if (sc->pl_crs_bad) { 447 if (sc->pl_crs_bad) {
448 creq.in_dpf = DPF_OUTSIDE; 448 creq.in_dpf = DPF_OUTSIDE;
449 creq.count = 0; 449 creq.count = 0;
450 status = AcpiWalkResources(sc->pl_handle, "_PRS", 450 status = AcpiWalkResources(sc->pl_handle, "_PRS",
451 acpi_count_irq_resources, &creq); 451 acpi_count_irq_resources, &creq);
452 if (ACPI_FAILURE(status)) { 452 if (ACPI_FAILURE(status)) {
453 aprint_error("%s: Unable to parse _CRS or _PRS: %s\n", 453 aprint_error("%s: Unable to parse _CRS or _PRS: %s\n",
454 sc->pl_name, AcpiFormatException(status)); 454 sc->pl_name, AcpiFormatException(status));
455 ACPI_SERIAL_END(pci_link); 455 ACPI_SERIAL_END(pci_link);
456 return (ENXIO); 456 return (ENXIO);
457 } 457 }
458 } 458 }
459 sc->pl_num_links = creq.count; 459 sc->pl_num_links = creq.count;
460 if (creq.count == 0) { 460 if (creq.count == 0) {
461 ACPI_SERIAL_END(pci_link); 461 ACPI_SERIAL_END(pci_link);
462 return (0); 462 return (0);
463 } 463 }
464 sc->pl_links = malloc(sizeof(struct link) * sc->pl_num_links, 464 sc->pl_links = malloc(sizeof(struct link) * sc->pl_num_links,
465 M_ACPI, M_WAITOK | M_ZERO); 465 M_ACPI, M_WAITOK | M_ZERO);
466 466
467 /* Initialize the child links. */ 467 /* Initialize the child links. */
468 for (i = 0; i < sc->pl_num_links; i++) { 468 for (i = 0; i < sc->pl_num_links; i++) {
469 sc->pl_links[i].l_irq = PCI_INVALID_IRQ; 469 sc->pl_links[i].l_irq = PCI_INVALID_IRQ;
470 sc->pl_links[i].l_bios_irq = PCI_INVALID_IRQ; 470 sc->pl_links[i].l_bios_irq = PCI_INVALID_IRQ;
471 sc->pl_links[i].l_sc = sc; 471 sc->pl_links[i].l_sc = sc;
472 sc->pl_links[i].l_isa_irq = FALSE; 472 sc->pl_links[i].l_isa_irq = FALSE;
473 sc->pl_links[i].l_res_index = -1; 473 sc->pl_links[i].l_res_index = -1;
474 sc->pl_links[i].l_dev_count = 0; 474 sc->pl_links[i].l_dev_count = 0;
475 sc->pl_links[i].l_devices = NULL; 475 sc->pl_links[i].l_devices = NULL;
476 } 476 }
477 477
478 /* Try to read the current settings from _CRS if it is valid. */ 478 /* Try to read the current settings from _CRS if it is valid. */
479 if (!sc->pl_crs_bad) { 479 if (!sc->pl_crs_bad) {
480 rreq.in_dpf = DPF_OUTSIDE; 480 rreq.in_dpf = DPF_OUTSIDE;
481 rreq.link_index = 0; 481 rreq.link_index = 0;
482 rreq.res_index = 0; 482 rreq.res_index = 0;
483 rreq.sc = sc; 483 rreq.sc = sc;
484 status = AcpiWalkResources(sc->pl_handle, "_CRS", 484 status = AcpiWalkResources(sc->pl_handle, "_CRS",
485 link_add_crs, &rreq); 485 link_add_crs, &rreq);
486 if (ACPI_FAILURE(status)) { 486 if (ACPI_FAILURE(status)) {
487 aprint_error("%s: Unable to parse _CRS: %s\n", 487 aprint_error("%s: Unable to parse _CRS: %s\n",
488 sc->pl_name, AcpiFormatException(status)); 488 sc->pl_name, AcpiFormatException(status));
489 goto fail; 489 goto fail;
490 } 490 }
491 } 491 }
492 492
493 /* 493 /*
494 * Try to read the possible settings from _PRS. Note that if the 494 * Try to read the possible settings from _PRS. Note that if the
495 * _CRS is toast, we depend on having a working _PRS. However, if 495 * _CRS is toast, we depend on having a working _PRS. However, if
496 * _CRS works, then it is ok for _PRS to be missing. 496 * _CRS works, then it is ok for _PRS to be missing.
497 */ 497 */
498 rreq.in_dpf = DPF_OUTSIDE; 498 rreq.in_dpf = DPF_OUTSIDE;
499 rreq.link_index = 0; 499 rreq.link_index = 0;
500 rreq.res_index = 0; 500 rreq.res_index = 0;
501 rreq.sc = sc; 501 rreq.sc = sc;
502 status = AcpiWalkResources(sc->pl_handle, "_PRS", 502 status = AcpiWalkResources(sc->pl_handle, "_PRS",
503 link_add_prs, &rreq); 503 link_add_prs, &rreq);
504 if (ACPI_FAILURE(status) && 504 if (ACPI_FAILURE(status) &&
505 (status != AE_NOT_FOUND || sc->pl_crs_bad)) { 505 (status != AE_NOT_FOUND || sc->pl_crs_bad)) {
506 aprint_error("%s: Unable to parse _PRS: %s\n", 506 aprint_error("%s: Unable to parse _PRS: %s\n",
507 sc->pl_name, AcpiFormatException(status)); 507 sc->pl_name, AcpiFormatException(status));
508 goto fail; 508 goto fail;
509 } 509 }
510 if (boothowto & AB_VERBOSE) { 510 if (boothowto & AB_VERBOSE) {
511 aprint_normal("%s: Links after initial probe:\n", sc->pl_name); 511 aprint_normal("%s: Links after initial probe:\n", sc->pl_name);
512 acpi_pci_link_dump(sc); 512 acpi_pci_link_dump(sc);
513 } 513 }
514 514
515 /* Verify initial IRQs if we have _PRS. */ 515 /* Verify initial IRQs if we have _PRS. */
516 if (status != AE_NOT_FOUND) 516 if (status != AE_NOT_FOUND)
517 for (i = 0; i < sc->pl_num_links; i++) 517 for (i = 0; i < sc->pl_num_links; i++)
518 if (!link_valid_irq(&sc->pl_links[i], 518 if (!link_valid_irq(&sc->pl_links[i],
519 sc->pl_links[i].l_irq)) 519 sc->pl_links[i].l_irq))
520 sc->pl_links[i].l_irq = PCI_INVALID_IRQ; 520 sc->pl_links[i].l_irq = PCI_INVALID_IRQ;
521 if (boothowto & AB_VERBOSE) { 521 if (boothowto & AB_VERBOSE) {
522 printf("%s: Links after initial validation:\n", sc->pl_name); 522 printf("%s: Links after initial validation:\n", sc->pl_name);
523 acpi_pci_link_dump(sc); 523 acpi_pci_link_dump(sc);
524 } 524 }
525 525
526 /* Save initial IRQs. */ 526 /* Save initial IRQs. */
527 for (i = 0; i < sc->pl_num_links; i++) 527 for (i = 0; i < sc->pl_num_links; i++)
528 sc->pl_links[i].l_initial_irq = sc->pl_links[i].l_irq; 528 sc->pl_links[i].l_initial_irq = sc->pl_links[i].l_irq;
529 529
530 /* 530 /*
531 * Try to disable this link. If successful, set the current IRQ to 531 * Try to disable this link. If successful, set the current IRQ to
532 * zero and flags to indicate this link is not routed. If we can't 532 * zero and flags to indicate this link is not routed. If we can't
533 * run _DIS (i.e., the method doesn't exist), assume the initial 533 * run _DIS (i.e., the method doesn't exist), assume the initial
534 * IRQ was routed by the BIOS. 534 * IRQ was routed by the BIOS.
535 */ 535 */
536#if 0 /* XXX causes spontaneaous resets on some systems. Disabled for now. */ 
537 if (ACPI_SUCCESS(AcpiEvaluateObject(sc->pl_handle, "_DIS", NULL, 536 if (ACPI_SUCCESS(AcpiEvaluateObject(sc->pl_handle, "_DIS", NULL,
538 NULL))) 537 NULL)))
539 for (i = 0; i < sc->pl_num_links; i++) 538 for (i = 0; i < sc->pl_num_links; i++)
540 sc->pl_links[i].l_irq = PCI_INVALID_IRQ; 539 sc->pl_links[i].l_irq = PCI_INVALID_IRQ;
541 else 540 else
542#endif 
543 for (i = 0; i < sc->pl_num_links; i++) 541 for (i = 0; i < sc->pl_num_links; i++)
544 if (PCI_INTERRUPT_VALID(sc->pl_links[i].l_irq)) 542 if (PCI_INTERRUPT_VALID(sc->pl_links[i].l_irq))
545 sc->pl_links[i].l_routed = TRUE; 543 sc->pl_links[i].l_routed = TRUE;
546 if (boothowto & AB_VERBOSE) { 544 if (boothowto & AB_VERBOSE) {
547 printf("%s: Links after disable:\n", sc->pl_name); 545 printf("%s: Links after disable:\n", sc->pl_name);
548 acpi_pci_link_dump(sc); 546 acpi_pci_link_dump(sc);
549 } 547 }
550 ACPI_SERIAL_END(pci_link); 548 ACPI_SERIAL_END(pci_link);
551 return (0); 549 return (0);
552fail: 550fail:
553 ACPI_SERIAL_END(pci_link); 551 ACPI_SERIAL_END(pci_link);
554 for (i = 0; i < sc->pl_num_links; i++) { 552 for (i = 0; i < sc->pl_num_links; i++) {
555 if (sc->pl_links[i].l_irqs != NULL) 553 if (sc->pl_links[i].l_irqs != NULL)
556 free(sc->pl_links[i].l_irqs, M_ACPI); 554 free(sc->pl_links[i].l_irqs, M_ACPI);
557 if (sc->pl_links[i].l_devices != NULL) 555 if (sc->pl_links[i].l_devices != NULL)
558 free(sc->pl_links[i].l_devices, M_ACPI); 556 free(sc->pl_links[i].l_devices, M_ACPI);
559 } 557 }
560 free(sc->pl_links, M_ACPI); 558 free(sc->pl_links, M_ACPI);
561 return (ENXIO); 559 return (ENXIO);
562} 560}
563 561
564static void 562static void
565acpi_pci_link_add_functions(struct acpi_pci_link_softc *sc, struct link *link, 563acpi_pci_link_add_functions(struct acpi_pci_link_softc *sc, struct link *link,
566 int bus, int device, int pin) 564 int bus, int device, int pin)
567{ 565{
568 uint32_t value; 566 uint32_t value;
569 uint8_t func, maxfunc, ipin; 567 uint8_t func, maxfunc, ipin;
570 pcitag_t tag; 568 pcitag_t tag;
571 569
572 tag = pci_make_tag(acpi_softc->sc_pc, bus, device, 0); 570 tag = pci_make_tag(acpi_softc->sc_pc, bus, device, 0);
573 /* See if we have a valid device at function 0. */ 571 /* See if we have a valid device at function 0. */
574 value = pci_conf_read(acpi_softc->sc_pc, tag, PCI_BHLC_REG); 572 value = pci_conf_read(acpi_softc->sc_pc, tag, PCI_BHLC_REG);
575 if (PCI_HDRTYPE_TYPE(value) > PCI_HDRTYPE_PCB) 573 if (PCI_HDRTYPE_TYPE(value) > PCI_HDRTYPE_PCB)
576 return; 574 return;
577 if (PCI_HDRTYPE_MULTIFN(value)) 575 if (PCI_HDRTYPE_MULTIFN(value))
578 maxfunc = 7; 576 maxfunc = 7;
579 else 577 else
580 maxfunc = 0; 578 maxfunc = 0;
581 579
582 /* Scan all possible functions at this device. */ 580 /* Scan all possible functions at this device. */
583 for (func = 0; func <= maxfunc; func++) { 581 for (func = 0; func <= maxfunc; func++) {
584 tag = pci_make_tag(acpi_softc->sc_pc, bus, device, func); 582 tag = pci_make_tag(acpi_softc->sc_pc, bus, device, func);
585 value = pci_conf_read(acpi_softc->sc_pc, tag, PCI_ID_REG); 583 value = pci_conf_read(acpi_softc->sc_pc, tag, PCI_ID_REG);
586 if (PCI_VENDOR(value) == 0xffff) 584 if (PCI_VENDOR(value) == 0xffff)
587 continue; 585 continue;
588 value = pci_conf_read(acpi_softc->sc_pc, tag, 586 value = pci_conf_read(acpi_softc->sc_pc, tag,
589 PCI_INTERRUPT_REG); 587 PCI_INTERRUPT_REG);
590 ipin = PCI_INTERRUPT_PIN(value); 588 ipin = PCI_INTERRUPT_PIN(value);
591 /* 589 /*
592 * See if it uses the pin in question. Note that the passed 590 * See if it uses the pin in question. Note that the passed
593 * in pin uses 0 for A, .. 3 for D whereas the intpin 591 * in pin uses 0 for A, .. 3 for D whereas the intpin
594 * register uses 0 for no interrupt, 1 for A, .. 4 for D. 592 * register uses 0 for no interrupt, 1 for A, .. 4 for D.
595 */ 593 */
596 if (ipin != pin + 1) 594 if (ipin != pin + 1)
597 continue; 595 continue;
598 596
599 link->l_devices = realloc(link->l_devices, 597 link->l_devices = realloc(link->l_devices,
600 sizeof(pcitag_t) * (link->l_dev_count + 1), 598 sizeof(pcitag_t) * (link->l_dev_count + 1),
601 M_ACPI, M_WAITOK); 599 M_ACPI, M_WAITOK);
602 link->l_devices[link->l_dev_count] = tag; 600 link->l_devices[link->l_dev_count] = tag;
603 ++link->l_dev_count; 601 ++link->l_dev_count;
604 } 602 }
605} 603}
606 604
607static uint8_t 605static uint8_t
608acpi_pci_link_search_irq(struct acpi_pci_link_softc *sc, int bus, int device, 606acpi_pci_link_search_irq(struct acpi_pci_link_softc *sc, int bus, int device,
609 int pin) 607 int pin)
610{ 608{
611 uint32_t value; 609 uint32_t value;
612 uint8_t func, maxfunc, ipin, iline; 610 uint8_t func, maxfunc, ipin, iline;
613 pcitag_t tag; 611 pcitag_t tag;
614 612
615 tag = pci_make_tag(acpi_softc->sc_pc, bus, device, 0); 613 tag = pci_make_tag(acpi_softc->sc_pc, bus, device, 0);
616 /* See if we have a valid device at function 0. */ 614 /* See if we have a valid device at function 0. */
617 value = pci_conf_read(acpi_softc->sc_pc, tag, PCI_BHLC_REG); 615 value = pci_conf_read(acpi_softc->sc_pc, tag, PCI_BHLC_REG);
618 if (PCI_HDRTYPE_TYPE(value) > PCI_HDRTYPE_PCB) 616 if (PCI_HDRTYPE_TYPE(value) > PCI_HDRTYPE_PCB)
619 return (PCI_INVALID_IRQ); 617 return (PCI_INVALID_IRQ);
620 if (PCI_HDRTYPE_MULTIFN(value)) 618 if (PCI_HDRTYPE_MULTIFN(value))
621 maxfunc = 7; 619 maxfunc = 7;
622 else 620 else
623 maxfunc = 0; 621 maxfunc = 0;
624 622
625 /* Scan all possible functions at this device. */ 623 /* Scan all possible functions at this device. */
626 for (func = 0; func <= maxfunc; func++) { 624 for (func = 0; func <= maxfunc; func++) {
627 tag = pci_make_tag(acpi_softc->sc_pc, bus, device, func); 625 tag = pci_make_tag(acpi_softc->sc_pc, bus, device, func);
628 value = pci_conf_read(acpi_softc->sc_pc, tag, PCI_ID_REG); 626 value = pci_conf_read(acpi_softc->sc_pc, tag, PCI_ID_REG);
629 if (PCI_VENDOR(value) == 0xffff) 627 if (PCI_VENDOR(value) == 0xffff)
630 continue; 628 continue;
631 value = pci_conf_read(acpi_softc->sc_pc, tag, 629 value = pci_conf_read(acpi_softc->sc_pc, tag,
632 PCI_INTERRUPT_REG); 630 PCI_INTERRUPT_REG);
633 ipin = PCI_INTERRUPT_PIN(value); 631 ipin = PCI_INTERRUPT_PIN(value);
634 iline = PCI_INTERRUPT_LINE(value); 632 iline = PCI_INTERRUPT_LINE(value);
635 633
636 /* 634 /*
637 * See if it uses the pin in question. Note that the passed 635 * See if it uses the pin in question. Note that the passed
638 * in pin uses 0 for A, .. 3 for D whereas the intpin 636 * in pin uses 0 for A, .. 3 for D whereas the intpin
639 * register uses 0 for no interrupt, 1 for A, .. 4 for D. 637 * register uses 0 for no interrupt, 1 for A, .. 4 for D.
640 */ 638 */
641 if (ipin != pin + 1) 639 if (ipin != pin + 1)
642 continue; 640 continue;
643 aprint_verbose( 641 aprint_verbose(
644 "%s: ACPI: Found matching pin for %d.%d.INT%c" 642 "%s: ACPI: Found matching pin for %d.%d.INT%c"
645 " at func %d: %d\n", 643 " at func %d: %d\n",
646 sc->pl_name, bus, device, pin + 'A', func, iline); 644 sc->pl_name, bus, device, pin + 'A', func, iline);
647 if (PCI_INTERRUPT_VALID(iline)) 645 if (PCI_INTERRUPT_VALID(iline))
648 return (iline); 646 return (iline);
649 } 647 }
650 return (PCI_INVALID_IRQ); 648 return (PCI_INVALID_IRQ);
651} 649}
652 650
653/* 651/*
654 * Find the link structure that corresponds to the resource index passed in 652 * Find the link structure that corresponds to the resource index passed in
655 * via 'source_index'. 653 * via 'source_index'.
656 */ 654 */
657static struct link * 655static struct link *
658acpi_pci_link_lookup(struct acpi_pci_link_softc *sc, int source_index) 656acpi_pci_link_lookup(struct acpi_pci_link_softc *sc, int source_index)
659{ 657{
660 int i; 658 int i;
661 659
662 for (i = 0; i < sc->pl_num_links; i++) 660 for (i = 0; i < sc->pl_num_links; i++)
663 if (sc->pl_links[i].l_res_index == source_index) 661 if (sc->pl_links[i].l_res_index == source_index)
664 return (&sc->pl_links[i]); 662 return (&sc->pl_links[i]);
665 return (NULL); 663 return (NULL);
666} 664}
667 665
668void 666void
669acpi_pci_link_add_reference(void *v, int index, int bus, int slot, int pin) 667acpi_pci_link_add_reference(void *v, int index, int bus, int slot, int pin)
670{ 668{
671 struct acpi_pci_link_softc *sc = v; 669 struct acpi_pci_link_softc *sc = v;
672 struct link *link; 670 struct link *link;
673 uint8_t bios_irq; 671 uint8_t bios_irq;
674 672
675 /* Bump the reference count. */ 673 /* Bump the reference count. */
676 ACPI_SERIAL_BEGIN(pci_link); 674 ACPI_SERIAL_BEGIN(pci_link);
677 link = acpi_pci_link_lookup(sc, index); 675 link = acpi_pci_link_lookup(sc, index);
678 if (link == NULL) { 676 if (link == NULL) {
679 printf("%s: apparently invalid index %d\n", sc->pl_name, index); 677 printf("%s: apparently invalid index %d\n", sc->pl_name, index);
680 ACPI_SERIAL_END(pci_link); 678 ACPI_SERIAL_END(pci_link);
681 return; 679 return;
682 } 680 }
683 link->l_references++; 681 link->l_references++;
684 acpi_pci_link_add_functions(sc, link, bus, slot, pin); 682 acpi_pci_link_add_functions(sc, link, bus, slot, pin);
685 if (link->l_routed) 683 if (link->l_routed)
686 pci_link_interrupt_weights[link->l_irq]++; 684 pci_link_interrupt_weights[link->l_irq]++;
687 685
688 /* 686 /*
689 * The BIOS only routes interrupts via ISA IRQs using the ATPICs 687 * The BIOS only routes interrupts via ISA IRQs using the ATPICs
690 * (8259As). Thus, if this link is routed via an ISA IRQ, go 688 * (8259As). Thus, if this link is routed via an ISA IRQ, go
691 * look to see if the BIOS routed an IRQ for this link at the 689 * look to see if the BIOS routed an IRQ for this link at the
692 * indicated (bus, slot, pin). If so, we prefer that IRQ for 690 * indicated (bus, slot, pin). If so, we prefer that IRQ for
693 * this link and add that IRQ to our list of known-good IRQs. 691 * this link and add that IRQ to our list of known-good IRQs.
694 * This provides a good work-around for link devices whose _CRS 692 * This provides a good work-around for link devices whose _CRS
695 * method is either broken or bogus. We only use the value 693 * method is either broken or bogus. We only use the value
696 * returned by _CRS if we can't find a valid IRQ via this method 694 * returned by _CRS if we can't find a valid IRQ via this method
697 * in fact. 695 * in fact.
698 * 696 *
699 * If this link is not routed via an ISA IRQ (because we are using 697 * If this link is not routed via an ISA IRQ (because we are using
700 * APIC for example), then don't bother looking up the BIOS IRQ 698 * APIC for example), then don't bother looking up the BIOS IRQ
701 * as if we find one it won't be valid anyway. 699 * as if we find one it won't be valid anyway.
702 */ 700 */
703 if (!link->l_isa_irq) { 701 if (!link->l_isa_irq) {
704 ACPI_SERIAL_END(pci_link); 702 ACPI_SERIAL_END(pci_link);
705 return; 703 return;
706 } 704 }
707 705
708 /* Try to find a BIOS IRQ setting from any matching devices. */ 706 /* Try to find a BIOS IRQ setting from any matching devices. */
709 bios_irq = acpi_pci_link_search_irq(sc, bus, slot, pin); 707 bios_irq = acpi_pci_link_search_irq(sc, bus, slot, pin);
710 if (!PCI_INTERRUPT_VALID(bios_irq)) { 708 if (!PCI_INTERRUPT_VALID(bios_irq)) {
711 ACPI_SERIAL_END(pci_link); 709 ACPI_SERIAL_END(pci_link);
712 return; 710 return;
713 } 711 }
714 712
715 /* Validate the BIOS IRQ. */ 713 /* Validate the BIOS IRQ. */
716 if (!link_valid_irq(link, bios_irq)) { 714 if (!link_valid_irq(link, bios_irq)) {
717 printf("%s: BIOS IRQ %u for %d.%d.INT%c is invalid\n", 715 printf("%s: BIOS IRQ %u for %d.%d.INT%c is invalid\n",
718 sc->pl_name, bios_irq, (int)bus, slot, pin + 'A'); 716 sc->pl_name, bios_irq, (int)bus, slot, pin + 'A');
719 } else if (!PCI_INTERRUPT_VALID(link->l_bios_irq)) { 717 } else if (!PCI_INTERRUPT_VALID(link->l_bios_irq)) {
720 link->l_bios_irq = bios_irq; 718 link->l_bios_irq = bios_irq;
721 if (bios_irq < NUM_ISA_INTERRUPTS) 719 if (bios_irq < NUM_ISA_INTERRUPTS)
722 pci_link_bios_isa_irqs |= (1 << bios_irq); 720 pci_link_bios_isa_irqs |= (1 << bios_irq);
723 if (bios_irq != link->l_initial_irq && 721 if (bios_irq != link->l_initial_irq &&
724 PCI_INTERRUPT_VALID(link->l_initial_irq)) 722 PCI_INTERRUPT_VALID(link->l_initial_irq))
725 printf( 723 printf(
726 "%s: BIOS IRQ %u does not match initial IRQ %u\n", 724 "%s: BIOS IRQ %u does not match initial IRQ %u\n",
727 sc->pl_name, bios_irq, link->l_initial_irq); 725 sc->pl_name, bios_irq, link->l_initial_irq);
728 } else if (bios_irq != link->l_bios_irq) 726 } else if (bios_irq != link->l_bios_irq)
729 printf( 727 printf(
730 "%s: BIOS IRQ %u for %d.%d.INT%c does not match " 728 "%s: BIOS IRQ %u for %d.%d.INT%c does not match "
731 "previous BIOS IRQ %u\n", 729 "previous BIOS IRQ %u\n",
732 sc->pl_name, bios_irq, (int)bus, slot, pin + 'A', 730 sc->pl_name, bios_irq, (int)bus, slot, pin + 'A',
733 link->l_bios_irq); 731 link->l_bios_irq);
734 ACPI_SERIAL_END(pci_link); 732 ACPI_SERIAL_END(pci_link);
735} 733}
736 734
737static ACPI_STATUS 735static ACPI_STATUS
738acpi_pci_link_srs_from_crs(struct acpi_pci_link_softc *sc, ACPI_BUFFER *srsbuf) 736acpi_pci_link_srs_from_crs(struct acpi_pci_link_softc *sc, ACPI_BUFFER *srsbuf)
739{ 737{
740 ACPI_RESOURCE *resource, *end, newres, *resptr; 738 ACPI_RESOURCE *resource, *end, newres, *resptr;
741 ACPI_BUFFER crsbuf; 739 ACPI_BUFFER crsbuf;
742 ACPI_STATUS status; 740 ACPI_STATUS status;
743 struct link *link; 741 struct link *link;
744 int i, in_dpf; 742 int i, in_dpf;
745 743
746 /* Fetch the _CRS. */ 744 /* Fetch the _CRS. */
747 crsbuf.Pointer = NULL; 745 crsbuf.Pointer = NULL;
748 crsbuf.Length = ACPI_ALLOCATE_LOCAL_BUFFER; 746 crsbuf.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
749 status = AcpiGetCurrentResources(sc->pl_handle, &crsbuf); 747 status = AcpiGetCurrentResources(sc->pl_handle, &crsbuf);
750 if (ACPI_SUCCESS(status) && crsbuf.Pointer == NULL) 748 if (ACPI_SUCCESS(status) && crsbuf.Pointer == NULL)
751 status = AE_NO_MEMORY; 749 status = AE_NO_MEMORY;
752 if (ACPI_FAILURE(status)) { 750 if (ACPI_FAILURE(status)) {
753 aprint_verbose("%s: Unable to fetch current resources: %s\n", 751 aprint_verbose("%s: Unable to fetch current resources: %s\n",
754 sc->pl_name, AcpiFormatException(status)); 752 sc->pl_name, AcpiFormatException(status));
755 return (status); 753 return (status);
756 } 754 }
757 755
758 /* Fill in IRQ resources via link structures. */ 756 /* Fill in IRQ resources via link structures. */
759 srsbuf->Pointer = NULL; 757 srsbuf->Pointer = NULL;
760 link = sc->pl_links; 758 link = sc->pl_links;
761 i = 0; 759 i = 0;
762 in_dpf = DPF_OUTSIDE; 760 in_dpf = DPF_OUTSIDE;
763 resource = (ACPI_RESOURCE *)crsbuf.Pointer; 761 resource = (ACPI_RESOURCE *)crsbuf.Pointer;
764 end = (ACPI_RESOURCE *)((char *)crsbuf.Pointer + crsbuf.Length); 762 end = (ACPI_RESOURCE *)((char *)crsbuf.Pointer + crsbuf.Length);
765 for (;;) { 763 for (;;) {
766 switch (resource->Type) { 764 switch (resource->Type) {
767 case ACPI_RESOURCE_TYPE_START_DEPENDENT: 765 case ACPI_RESOURCE_TYPE_START_DEPENDENT:
768 switch (in_dpf) { 766 switch (in_dpf) {
769 case DPF_OUTSIDE: 767 case DPF_OUTSIDE:
770 /* We've started the first DPF. */ 768 /* We've started the first DPF. */
771 in_dpf = DPF_FIRST; 769 in_dpf = DPF_FIRST;
772 break; 770 break;
773 case DPF_FIRST: 771 case DPF_FIRST:
774 /* We've started the second DPF. */ 772 /* We've started the second DPF. */
775 panic( 773 panic(
776 "%s: Multiple dependent functions within a current resource", 774 "%s: Multiple dependent functions within a current resource",
777 __func__); 775 __func__);
778 break; 776 break;
779 } 777 }
780 resptr = NULL; 778 resptr = NULL;
781 break; 779 break;
782 case ACPI_RESOURCE_TYPE_END_DEPENDENT: 780 case ACPI_RESOURCE_TYPE_END_DEPENDENT:
783 /* We are finished with DPF parsing. */ 781 /* We are finished with DPF parsing. */
784 KASSERT(in_dpf != DPF_OUTSIDE); 782 KASSERT(in_dpf != DPF_OUTSIDE);
785 in_dpf = DPF_OUTSIDE; 783 in_dpf = DPF_OUTSIDE;
786 resptr = NULL; 784 resptr = NULL;
787 break; 785 break;
788 case ACPI_RESOURCE_TYPE_IRQ: 786 case ACPI_RESOURCE_TYPE_IRQ:
789 newres = link->l_prs_template; 787 newres = link->l_prs_template;
790 resptr = &newres; 788 resptr = &newres;
791 resptr->Data.Irq.InterruptCount = 1; 789 resptr->Data.Irq.InterruptCount = 1;
792 if (PCI_INTERRUPT_VALID(link->l_irq)) { 790 if (PCI_INTERRUPT_VALID(link->l_irq)) {
793 KASSERT(link->l_irq < NUM_ISA_INTERRUPTS); 791 KASSERT(link->l_irq < NUM_ISA_INTERRUPTS);
794 resptr->Data.Irq.Interrupts[0] = link->l_irq; 792 resptr->Data.Irq.Interrupts[0] = link->l_irq;
795 resptr->Data.Irq.Triggering = link->l_trig; 793 resptr->Data.Irq.Triggering = link->l_trig;
796 resptr->Data.Irq.Polarity = link->l_pol; 794 resptr->Data.Irq.Polarity = link->l_pol;
797 } else 795 } else
798 resptr->Data.Irq.Interrupts[0] = 0; 796 resptr->Data.Irq.Interrupts[0] = 0;
799 link++; 797 link++;
800 i++; 798 i++;
801 break; 799 break;
802 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: 800 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
803 newres = link->l_prs_template; 801 newres = link->l_prs_template;
804 resptr = &newres; 802 resptr = &newres;
805 resptr->Data.ExtendedIrq.InterruptCount = 1; 803 resptr->Data.ExtendedIrq.InterruptCount = 1;
806 if (PCI_INTERRUPT_VALID(link->l_irq)) { 804 if (PCI_INTERRUPT_VALID(link->l_irq)) {
807 resptr->Data.ExtendedIrq.Interrupts[0] = 805 resptr->Data.ExtendedIrq.Interrupts[0] =
808 link->l_irq; 806 link->l_irq;
809 resptr->Data.ExtendedIrq.Triggering = 807 resptr->Data.ExtendedIrq.Triggering =
810 link->l_trig; 808 link->l_trig;
811 resptr->Data.ExtendedIrq.Polarity = link->l_pol; 809 resptr->Data.ExtendedIrq.Polarity = link->l_pol;
812 } else 810 } else
813 resptr->Data.ExtendedIrq.Interrupts[0] = 0; 811 resptr->Data.ExtendedIrq.Interrupts[0] = 0;
814 link++; 812 link++;
815 i++; 813 i++;
816 break; 814 break;
817 default: 815 default:
818 resptr = resource; 816 resptr = resource;
819 } 817 }
820 if (resptr != NULL) { 818 if (resptr != NULL) {
821 status = acpi_AppendBufferResource(srsbuf, resptr); 819 status = acpi_AppendBufferResource(srsbuf, resptr);
822 if (ACPI_FAILURE(status)) { 820 if (ACPI_FAILURE(status)) {
823 printf("%s: Unable to build resources: %s\n", 821 printf("%s: Unable to build resources: %s\n",
824 sc->pl_name, AcpiFormatException(status)); 822 sc->pl_name, AcpiFormatException(status));
825 if (srsbuf->Pointer != NULL) 823 if (srsbuf->Pointer != NULL)
826 ACPI_FREE(srsbuf->Pointer); 824 ACPI_FREE(srsbuf->Pointer);
827 ACPI_FREE(crsbuf.Pointer); 825 ACPI_FREE(crsbuf.Pointer);
828 return (status); 826 return (status);
829 } 827 }
830 } 828 }
831 if (resource->Type == ACPI_RESOURCE_TYPE_END_TAG) 829 if (resource->Type == ACPI_RESOURCE_TYPE_END_TAG)
832 break; 830 break;
833 resource = ACPI_NEXT_RESOURCE(resource); 831 resource = ACPI_NEXT_RESOURCE(resource);
834 if (resource >= end) 832 if (resource >= end)
835 break; 833 break;
836 } 834 }
837 ACPI_FREE(crsbuf.Pointer); 835 ACPI_FREE(crsbuf.Pointer);
838 return (AE_OK); 836 return (AE_OK);
839} 837}
840 838
841static ACPI_STATUS 839static ACPI_STATUS
842acpi_pci_link_srs_from_links(struct acpi_pci_link_softc *sc, 840acpi_pci_link_srs_from_links(struct acpi_pci_link_softc *sc,
843 ACPI_BUFFER *srsbuf) 841 ACPI_BUFFER *srsbuf)
844{ 842{
845 ACPI_RESOURCE newres; 843 ACPI_RESOURCE newres;
846 ACPI_STATUS status; 844 ACPI_STATUS status;
847 struct link *link; 845 struct link *link;
848 int i; 846 int i;
849 847
850 /* Start off with an empty buffer. */ 848 /* Start off with an empty buffer. */
851 srsbuf->Pointer = NULL; 849 srsbuf->Pointer = NULL;
852 link = sc->pl_links; 850 link = sc->pl_links;
853 for (i = 0; i < sc->pl_num_links; i++) { 851 for (i = 0; i < sc->pl_num_links; i++) {
854 852
855 /* Add a new IRQ resource from each link. */ 853 /* Add a new IRQ resource from each link. */
856 link = &sc->pl_links[i]; 854 link = &sc->pl_links[i];
857 newres = link->l_prs_template; 855 newres = link->l_prs_template;
858 if (newres.Type == ACPI_RESOURCE_TYPE_IRQ) { 856 if (newres.Type == ACPI_RESOURCE_TYPE_IRQ) {
859 857
860 /* Build an IRQ resource. */ 858 /* Build an IRQ resource. */
861 newres.Data.Irq.InterruptCount = 1; 859 newres.Data.Irq.InterruptCount = 1;
862 if (PCI_INTERRUPT_VALID(link->l_irq)) { 860 if (PCI_INTERRUPT_VALID(link->l_irq)) {
863 KASSERT(link->l_irq < NUM_ISA_INTERRUPTS); 861 KASSERT(link->l_irq < NUM_ISA_INTERRUPTS);
864 newres.Data.Irq.Interrupts[0] = link->l_irq; 862 newres.Data.Irq.Interrupts[0] = link->l_irq;
865 newres.Data.Irq.Triggering = link->l_trig; 863 newres.Data.Irq.Triggering = link->l_trig;
866 newres.Data.Irq.Polarity = link->l_pol; 864 newres.Data.Irq.Polarity = link->l_pol;
867 } else 865 } else
868 newres.Data.Irq.Interrupts[0] = 0; 866 newres.Data.Irq.Interrupts[0] = 0;
869 } else { 867 } else {
870 868
871 /* Build an ExtIRQ resuorce. */ 869 /* Build an ExtIRQ resuorce. */
872 newres.Data.ExtendedIrq.InterruptCount = 1; 870 newres.Data.ExtendedIrq.InterruptCount = 1;
873 if (PCI_INTERRUPT_VALID(link->l_irq)) { 871 if (PCI_INTERRUPT_VALID(link->l_irq)) {
874 newres.Data.ExtendedIrq.Interrupts[0] = 872 newres.Data.ExtendedIrq.Interrupts[0] =
875 link->l_irq; 873 link->l_irq;
876 newres.Data.ExtendedIrq.Triggering = 874 newres.Data.ExtendedIrq.Triggering =
877 link->l_trig; 875 link->l_trig;
878 newres.Data.ExtendedIrq.Polarity = 876 newres.Data.ExtendedIrq.Polarity =
879 link->l_pol; 877 link->l_pol;
880 } else { 878 } else {
881 newres.Data.ExtendedIrq.Interrupts[0] = 0; 879 newres.Data.ExtendedIrq.Interrupts[0] = 0;
882 } 880 }
883 } 881 }
884 882
885 /* Add the new resource to the end of the _SRS buffer. */ 883 /* Add the new resource to the end of the _SRS buffer. */
886 status = acpi_AppendBufferResource(srsbuf, &newres); 884 status = acpi_AppendBufferResource(srsbuf, &newres);
887 if (ACPI_FAILURE(status)) { 885 if (ACPI_FAILURE(status)) {
888 printf("%s: Unable to build resources: %s\n", 886 printf("%s: Unable to build resources: %s\n",
889 sc->pl_name, AcpiFormatException(status)); 887 sc->pl_name, AcpiFormatException(status));
890 if (srsbuf->Pointer != NULL) 888 if (srsbuf->Pointer != NULL)
891 ACPI_FREE(srsbuf->Pointer); 889 ACPI_FREE(srsbuf->Pointer);
892 return (status); 890 return (status);
893 } 891 }
894 } 892 }
895 return (AE_OK); 893 return (AE_OK);
896} 894}
897 895
898static ACPI_STATUS 896static ACPI_STATUS
899acpi_pci_link_srs(struct acpi_pci_link_softc *sc, ACPI_BUFFER *srsbuf) 897acpi_pci_link_srs(struct acpi_pci_link_softc *sc, ACPI_BUFFER *srsbuf)
900{ 898{
901 ACPI_STATUS status; 899 ACPI_STATUS status;
902 900
903 if (sc->pl_crs_bad) 901 if (sc->pl_crs_bad)
904 status = acpi_pci_link_srs_from_links(sc, srsbuf); 902 status = acpi_pci_link_srs_from_links(sc, srsbuf);
905 else 903 else
906 status = acpi_pci_link_srs_from_crs(sc, srsbuf); 904 status = acpi_pci_link_srs_from_crs(sc, srsbuf);
907 905
908 /* Write out new resources via _SRS. */ 906 /* Write out new resources via _SRS. */
909 return AcpiSetCurrentResources(sc->pl_handle, srsbuf); 907 return AcpiSetCurrentResources(sc->pl_handle, srsbuf);
910} 908}
911 909
912static ACPI_STATUS 910static ACPI_STATUS
913acpi_pci_link_route_irqs(struct acpi_pci_link_softc *sc, int *irq, int *pol, 911acpi_pci_link_route_irqs(struct acpi_pci_link_softc *sc, int *irq, int *pol,
914 int *trig) 912 int *trig)
915{ 913{
916 ACPI_RESOURCE *resource, *end; 914 ACPI_RESOURCE *resource, *end;
917 ACPI_BUFFER srsbuf; 915 ACPI_BUFFER srsbuf;
918 ACPI_STATUS status; 916 ACPI_STATUS status;
919 struct link *link; 917 struct link *link;
920 int i, is_ext = 0; 918 int i, is_ext = 0;
921 919
922 status = acpi_pci_link_srs(sc, &srsbuf); 920 status = acpi_pci_link_srs(sc, &srsbuf);
923 if (ACPI_FAILURE(status)) { 921 if (ACPI_FAILURE(status)) {
924 printf("%s: _SRS failed: %s\n", 922 printf("%s: _SRS failed: %s\n",
925 sc->pl_name, AcpiFormatException(status)); 923 sc->pl_name, AcpiFormatException(status));
926 return (status); 924 return (status);
927 } 925 }
928 /* 926 /*
929 * Perform acpi_config_intr() on each IRQ resource if it was just 927 * Perform acpi_config_intr() on each IRQ resource if it was just
930 * routed for the first time. 928 * routed for the first time.
931 */ 929 */
932 link = sc->pl_links; 930 link = sc->pl_links;
933 i = 0; 931 i = 0;
934 resource = (ACPI_RESOURCE *)srsbuf.Pointer; 932 resource = (ACPI_RESOURCE *)srsbuf.Pointer;
935 end = (ACPI_RESOURCE *)((char *)srsbuf.Pointer + srsbuf.Length); 933 end = (ACPI_RESOURCE *)((char *)srsbuf.Pointer + srsbuf.Length);
936 for (;;) { 934 for (;;) {
937 if (resource->Type == ACPI_RESOURCE_TYPE_END_TAG) 935 if (resource->Type == ACPI_RESOURCE_TYPE_END_TAG)
938 break; 936 break;
939 switch (resource->Type) { 937 switch (resource->Type) {
940 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: 938 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
941 is_ext = 1; 939 is_ext = 1;
942 /* FALLTHROUGH */ 940 /* FALLTHROUGH */
943 case ACPI_RESOURCE_TYPE_IRQ: 941 case ACPI_RESOURCE_TYPE_IRQ:
944 /* 942 /*
945 * Only configure the interrupt and update the 943 * Only configure the interrupt and update the
946 * weights if this link has a valid IRQ and was 944 * weights if this link has a valid IRQ and was
947 * previously unrouted. 945 * previously unrouted.
948 */ 946 */
949 if (!link->l_routed && 947 if (!link->l_routed &&
950 PCI_INTERRUPT_VALID(link->l_irq)) { 948 PCI_INTERRUPT_VALID(link->l_irq)) {
951 *trig = is_ext ? 949 *trig = is_ext ?
952 resource->Data.ExtendedIrq.Triggering : 950 resource->Data.ExtendedIrq.Triggering :
953 resource->Data.Irq.Triggering; 951 resource->Data.Irq.Triggering;
954 *pol = is_ext ? 952 *pol = is_ext ?
955 resource->Data.ExtendedIrq.Polarity : 953 resource->Data.ExtendedIrq.Polarity :
956 resource->Data.Irq.Polarity; 954 resource->Data.Irq.Polarity;
957 *irq = is_ext ? 955 *irq = is_ext ?
958 resource->Data.ExtendedIrq.Interrupts[0] : 956 resource->Data.ExtendedIrq.Interrupts[0] :
959 resource->Data.Irq.Interrupts[0]; 957 resource->Data.Irq.Interrupts[0];
960 link->l_routed = TRUE; 958 link->l_routed = TRUE;
961 pci_link_interrupt_weights[link->l_irq] += 959 pci_link_interrupt_weights[link->l_irq] +=
962 link->l_references; 960 link->l_references;
963 } 961 }
964 link++; 962 link++;
965 i++; 963 i++;
966 break; 964 break;
967 } 965 }
968 resource = ACPI_NEXT_RESOURCE(resource); 966 resource = ACPI_NEXT_RESOURCE(resource);
969 if (resource >= end) 967 if (resource >= end)
970 break; 968 break;
971 } 969 }
972 ACPI_FREE(srsbuf.Pointer); 970 ACPI_FREE(srsbuf.Pointer);
973 return (AE_OK); 971 return (AE_OK);
974} 972}
975 973
976/* 974/*
977 * Pick an IRQ to use for this unrouted link. 975 * Pick an IRQ to use for this unrouted link.
978 */ 976 */
979static uint8_t 977static uint8_t
980acpi_pci_link_choose_irq(struct acpi_pci_link_softc *sc, struct link *link) 978acpi_pci_link_choose_irq(struct acpi_pci_link_softc *sc, struct link *link)
981{ 979{
982 u_int8_t best_irq, pos_irq; 980 u_int8_t best_irq, pos_irq;
983 int best_weight, pos_weight, i; 981 int best_weight, pos_weight, i;
984 982
985 KASSERT(!link->l_routed); 983 KASSERT(!link->l_routed);
986 KASSERT(!PCI_INTERRUPT_VALID(link->l_irq)); 984 KASSERT(!PCI_INTERRUPT_VALID(link->l_irq));
987 985
988 /* 986 /*
989 * If we have a valid BIOS IRQ, use that. We trust what the BIOS 987 * If we have a valid BIOS IRQ, use that. We trust what the BIOS
990 * says it routed over what _CRS says the link thinks is routed. 988 * says it routed over what _CRS says the link thinks is routed.
991 */ 989 */
992 if (PCI_INTERRUPT_VALID(link->l_bios_irq)) 990 if (PCI_INTERRUPT_VALID(link->l_bios_irq))
993 return (link->l_bios_irq); 991 return (link->l_bios_irq);
994 992
995 /* 993 /*
996 * If we don't have a BIOS IRQ but do have a valid IRQ from _CRS, 994 * If we don't have a BIOS IRQ but do have a valid IRQ from _CRS,
997 * then use that. 995 * then use that.
998 */ 996 */
999 if (PCI_INTERRUPT_VALID(link->l_initial_irq)) 997 if (PCI_INTERRUPT_VALID(link->l_initial_irq))
1000 return (link->l_initial_irq); 998 return (link->l_initial_irq);
1001 999
1002 /* 1000 /*
1003 * Ok, we have no useful hints, so we have to pick from the 1001 * Ok, we have no useful hints, so we have to pick from the
1004 * possible IRQs. For ISA IRQs we only use interrupts that 1002 * possible IRQs. For ISA IRQs we only use interrupts that
1005 * have already been used by the BIOS. 1003 * have already been used by the BIOS.
1006 */ 1004 */
1007 best_irq = PCI_INVALID_IRQ; 1005 best_irq = PCI_INVALID_IRQ;
1008 best_weight = INT_MAX; 1006 best_weight = INT_MAX;
1009 for (i = 0; i < link->l_num_irqs; i++) { 1007 for (i = 0; i < link->l_num_irqs; i++) {
1010 pos_irq = link->l_irqs[i]; 1008 pos_irq = link->l_irqs[i];
1011 if (pos_irq < NUM_ISA_INTERRUPTS && 1009 if (pos_irq < NUM_ISA_INTERRUPTS &&
1012 (pci_link_bios_isa_irqs & 1 << pos_irq) == 0) 1010 (pci_link_bios_isa_irqs & 1 << pos_irq) == 0)
1013 continue; 1011 continue;
1014 pos_weight = pci_link_interrupt_weights[pos_irq]; 1012 pos_weight = pci_link_interrupt_weights[pos_irq];
1015 if (pos_weight < best_weight) { 1013 if (pos_weight < best_weight) {
1016 best_weight = pos_weight; 1014 best_weight = pos_weight;
1017 best_irq = pos_irq; 1015 best_irq = pos_irq;
1018 } 1016 }
1019 } 1017 }
1020 1018
1021 /* 1019 /*
1022 * If this is an ISA IRQ, try using the SCI if it is also an ISA 1020 * If this is an ISA IRQ, try using the SCI if it is also an ISA
1023 * interrupt as a fallback. 1021 * interrupt as a fallback.
1024 */ 1022 */
1025 if (link->l_isa_irq && !PCI_INTERRUPT_VALID(best_irq)) { 1023 if (link->l_isa_irq && !PCI_INTERRUPT_VALID(best_irq)) {
1026 pos_irq = AcpiGbl_FADT.SciInterrupt; 1024 pos_irq = AcpiGbl_FADT.SciInterrupt;
1027 pos_weight = pci_link_interrupt_weights[pos_irq]; 1025 pos_weight = pci_link_interrupt_weights[pos_irq];
1028 if (pos_weight < best_weight) { 1026 if (pos_weight < best_weight) {
1029 best_weight = pos_weight; 1027 best_weight = pos_weight;
1030 best_irq = pos_irq; 1028 best_irq = pos_irq;
1031 } 1029 }
1032 } 1030 }
1033 1031
1034 if (PCI_INTERRUPT_VALID(best_irq)) { 1032 if (PCI_INTERRUPT_VALID(best_irq)) {
1035 aprint_verbose("%s: Picked IRQ %u with weight %d\n", 1033 aprint_verbose("%s: Picked IRQ %u with weight %d\n",
1036 sc->pl_name, best_irq, best_weight); 1034 sc->pl_name, best_irq, best_weight);
1037 } else 1035 } else
1038 printf("%s: Unable to choose an IRQ\n", sc->pl_name); 1036 printf("%s: Unable to choose an IRQ\n", sc->pl_name);
1039 return (best_irq); 1037 return (best_irq);
1040} 1038}
1041 1039
1042int 1040int
1043acpi_pci_link_route_interrupt(void *v, int index, int *irq, int *pol, int *trig) 1041acpi_pci_link_route_interrupt(void *v, int index, int *irq, int *pol, int *trig)
1044{ 1042{
1045 struct acpi_pci_link_softc *sc = v; 1043 struct acpi_pci_link_softc *sc = v;
1046 struct link *link; 1044 struct link *link;
1047 int i; 1045 int i;
1048 pcireg_t reg; 1046 pcireg_t reg;
1049 1047
1050 ACPI_SERIAL_BEGIN(pci_link); 1048 ACPI_SERIAL_BEGIN(pci_link);
1051 link = acpi_pci_link_lookup(sc, index); 1049 link = acpi_pci_link_lookup(sc, index);
1052 if (link == NULL) 1050 if (link == NULL)
1053 panic("%s: apparently invalid index %d", __func__, index); 1051 panic("%s: apparently invalid index %d", __func__, index);
1054 1052
1055 /* 1053 /*
1056 * If this link device is already routed to an interrupt, just return 1054 * If this link device is already routed to an interrupt, just return
1057 * the interrupt it is routed to. 1055 * the interrupt it is routed to.
1058 */ 1056 */
1059 if (link->l_routed) { 1057 if (link->l_routed) {
1060 KASSERT(PCI_INTERRUPT_VALID(link->l_irq)); 1058 KASSERT(PCI_INTERRUPT_VALID(link->l_irq));
1061 ACPI_SERIAL_END(pci_link); 1059 ACPI_SERIAL_END(pci_link);
1062 *irq = link->l_irq; 1060 *irq = link->l_irq;
1063 *pol = link->l_pol; 1061 *pol = link->l_pol;
1064 *trig = link->l_trig; 1062 *trig = link->l_trig;
1065 return (link->l_irq); 1063 return (link->l_irq);
1066 } 1064 }
1067 1065
1068 /* Choose an IRQ if we need one. */ 1066 /* Choose an IRQ if we need one. */
1069 if (PCI_INTERRUPT_VALID(link->l_irq)) { 1067 if (PCI_INTERRUPT_VALID(link->l_irq)) {
1070 *irq = link->l_irq; 1068 *irq = link->l_irq;
1071 *pol = link->l_pol; 1069 *pol = link->l_pol;
1072 *trig = link->l_trig; 1070 *trig = link->l_trig;
1073 goto done; 1071 goto done;
1074 } 1072 }
1075 1073
1076 link->l_irq = acpi_pci_link_choose_irq(sc, link); 1074 link->l_irq = acpi_pci_link_choose_irq(sc, link);
1077 1075
1078 /* 1076 /*
1079 * Try to route the interrupt we picked. If it fails, then 1077 * Try to route the interrupt we picked. If it fails, then
1080 * assume the interrupt is not routed. 1078 * assume the interrupt is not routed.
1081 */ 1079 */
1082 if (!PCI_INTERRUPT_VALID(link->l_irq)) 1080 if (!PCI_INTERRUPT_VALID(link->l_irq))
1083 goto done; 1081 goto done;
1084 1082
1085 acpi_pci_link_route_irqs(sc, irq, pol, trig); 1083 acpi_pci_link_route_irqs(sc, irq, pol, trig);
1086 if (!link->l_routed) { 1084 if (!link->l_routed) {
1087 link->l_irq = PCI_INVALID_IRQ; 1085 link->l_irq = PCI_INVALID_IRQ;
1088 goto done; 1086 goto done;
1089 } 1087 }
1090 1088
1091 link->l_pol = *pol; 1089 link->l_pol = *pol;
1092 link->l_trig = *trig; 1090 link->l_trig = *trig;
1093 for (i = 0; i < link->l_dev_count; ++i) { 1091 for (i = 0; i < link->l_dev_count; ++i) {
1094 reg = pci_conf_read(acpi_softc->sc_pc, link->l_devices[i], 1092 reg = pci_conf_read(acpi_softc->sc_pc, link->l_devices[i],
1095 PCI_INTERRUPT_REG); 1093 PCI_INTERRUPT_REG);
1096 reg &= ~(PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT); 1094 reg &= ~(PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT);
1097 reg |= link->l_irq << PCI_INTERRUPT_LINE_SHIFT; 1095 reg |= link->l_irq << PCI_INTERRUPT_LINE_SHIFT;
1098 pci_conf_write(acpi_softc->sc_pc, link->l_devices[i], 1096 pci_conf_write(acpi_softc->sc_pc, link->l_devices[i],
1099 PCI_INTERRUPT_REG, reg); 1097 PCI_INTERRUPT_REG, reg);
1100 } 1098 }
1101 1099
1102done: 1100done:
1103 ACPI_SERIAL_END(pci_link); 1101 ACPI_SERIAL_END(pci_link);
1104 1102
1105 return (link->l_irq); 1103 return (link->l_irq);
1106} 1104}
1107 1105
1108/* 1106/*
1109 * This is gross, but we abuse the identify routine to perform one-time 1107 * This is gross, but we abuse the identify routine to perform one-time
1110 * SYSINIT() style initialization for the driver. 1108 * SYSINIT() style initialization for the driver.
1111 */ 1109 */
1112static void 1110static void
1113acpi_pci_link_init(struct acpi_pci_link_softc *sc) 1111acpi_pci_link_init(struct acpi_pci_link_softc *sc)
1114{ 1112{
1115 ACPI_BUFFER buf; 1113 ACPI_BUFFER buf;
1116 1114
1117 /* 1115 /*
1118 * If the SCI is an ISA IRQ, add it to the bitmask of known good 1116 * If the SCI is an ISA IRQ, add it to the bitmask of known good
1119 * ISA IRQs. 1117 * ISA IRQs.
1120 * 1118 *
1121 * XXX: If we are using the APIC, the SCI might have been 1119 * XXX: If we are using the APIC, the SCI might have been
1122 * rerouted to an APIC pin in which case this is invalid. However, 1120 * rerouted to an APIC pin in which case this is invalid. However,
1123 * if we are using the APIC, we also shouldn't be having any PCI 1121 * if we are using the APIC, we also shouldn't be having any PCI
1124 * interrupts routed via ISA IRQs, so this is probably ok. 1122 * interrupts routed via ISA IRQs, so this is probably ok.
1125 */ 1123 */
1126 if (AcpiGbl_FADT.SciInterrupt < NUM_ISA_INTERRUPTS) 1124 if (AcpiGbl_FADT.SciInterrupt < NUM_ISA_INTERRUPTS)
1127 pci_link_bios_isa_irqs |= (1 << AcpiGbl_FADT.SciInterrupt); 1125 pci_link_bios_isa_irqs |= (1 << AcpiGbl_FADT.SciInterrupt);
1128 1126
1129 buf.Length = sizeof (sc->pl_name); 1127 buf.Length = sizeof (sc->pl_name);
1130 buf.Pointer = sc->pl_name; 1128 buf.Pointer = sc->pl_name;
1131 1129
1132 if (ACPI_FAILURE(AcpiGetName(sc->pl_handle, ACPI_SINGLE_NAME, &buf))) 1130 if (ACPI_FAILURE(AcpiGetName(sc->pl_handle, ACPI_SINGLE_NAME, &buf)))
1133 snprintf(sc->pl_name, sizeof (sc->pl_name), "%s", 1131 snprintf(sc->pl_name, sizeof (sc->pl_name), "%s",
1134 "ACPI link device"); 1132 "ACPI link device");
1135 1133
1136 acpi_pci_link_attach(sc); 1134 acpi_pci_link_attach(sc);
1137} 1135}
1138 1136
1139void * 1137void *
1140acpi_pci_link_devbyhandle(ACPI_HANDLE handle) 1138acpi_pci_link_devbyhandle(ACPI_HANDLE handle)
1141{ 1139{
1142 struct acpi_pci_link_softc *sc; 1140 struct acpi_pci_link_softc *sc;
1143 1141
1144 TAILQ_FOREACH(sc, &acpi_pci_linkdevs, pl_list) { 1142 TAILQ_FOREACH(sc, &acpi_pci_linkdevs, pl_list) {
1145 if (sc->pl_handle == handle) 1143 if (sc->pl_handle == handle)
1146 return sc; 1144 return sc;
1147 } 1145 }
1148 1146
1149 sc = malloc(sizeof (*sc), M_ACPI, M_NOWAIT | M_ZERO); 1147 sc = malloc(sizeof (*sc), M_ACPI, M_NOWAIT | M_ZERO);
1150 if (sc == NULL) 1148 if (sc == NULL)
1151 return NULL; 1149 return NULL;
1152 1150
1153 sc->pl_handle = handle; 1151 sc->pl_handle = handle;
1154 1152
1155 acpi_pci_link_init(sc); 1153 acpi_pci_link_init(sc);
1156 1154
1157 TAILQ_INSERT_TAIL(&acpi_pci_linkdevs, sc, pl_list); 1155 TAILQ_INSERT_TAIL(&acpi_pci_linkdevs, sc, pl_list);
1158 1156
1159 return (void *)sc; 1157 return (void *)sc;
1160} 1158}
1161 1159
1162void 1160void
1163acpi_pci_link_resume(void) 1161acpi_pci_link_resume(void)
1164{ 1162{
1165 struct acpi_pci_link_softc *sc; 1163 struct acpi_pci_link_softc *sc;
1166 ACPI_BUFFER srsbuf; 1164 ACPI_BUFFER srsbuf;
1167 1165
1168 TAILQ_FOREACH(sc, &acpi_pci_linkdevs, pl_list) { 1166 TAILQ_FOREACH(sc, &acpi_pci_linkdevs, pl_list) {
1169 ACPI_SERIAL_BEGIN(pci_link); 1167 ACPI_SERIAL_BEGIN(pci_link);
1170 if (ACPI_SUCCESS(acpi_pci_link_srs(sc, &srsbuf))) 1168 if (ACPI_SUCCESS(acpi_pci_link_srs(sc, &srsbuf)))
1171 ACPI_FREE(srsbuf.Pointer); 1169 ACPI_FREE(srsbuf.Pointer);
1172 ACPI_SERIAL_END(pci_link); 1170 ACPI_SERIAL_END(pci_link);
1173 } 1171 }
1174} 1172}
1175 1173
1176ACPI_HANDLE 1174ACPI_HANDLE
1177acpi_pci_link_handle(void *v) 1175acpi_pci_link_handle(void *v)
1178{ 1176{
1179 struct acpi_pci_link_softc *sc = v; 1177 struct acpi_pci_link_softc *sc = v;
1180 1178
1181 return sc->pl_handle; 1179 return sc->pl_handle;
1182} 1180}
1183 1181
1184char * 1182char *
1185acpi_pci_link_name(void *v) 1183acpi_pci_link_name(void *v)
1186{ 1184{
1187 struct acpi_pci_link_softc *sc = v; 1185 struct acpi_pci_link_softc *sc = v;
1188 1186
1189 return sc->pl_name; 1187 return sc->pl_name;
1190} 1188}
1191 1189
1192 1190
1193/* 1191/*
1194 * Append an ACPI_RESOURCE to an ACPI_BUFFER. 1192 * Append an ACPI_RESOURCE to an ACPI_BUFFER.
1195 * 1193 *
1196 * Given a pointer to an ACPI_RESOURCE structure, expand the ACPI_BUFFER 1194 * Given a pointer to an ACPI_RESOURCE structure, expand the ACPI_BUFFER
1197 * provided to contain it. If the ACPI_BUFFER is empty, allocate a sensible 1195 * provided to contain it. If the ACPI_BUFFER is empty, allocate a sensible
1198 * backing block. If the ACPI_RESOURCE is NULL, return an empty set of 1196 * backing block. If the ACPI_RESOURCE is NULL, return an empty set of
1199 * resources. 1197 * resources.
1200 */ 1198 */
1201#define ACPI_INITIAL_RESOURCE_BUFFER_SIZE 512 1199#define ACPI_INITIAL_RESOURCE_BUFFER_SIZE 512
1202 1200
1203static ACPI_STATUS 1201static ACPI_STATUS
1204acpi_AppendBufferResource(ACPI_BUFFER *buf, ACPI_RESOURCE *res) 1202acpi_AppendBufferResource(ACPI_BUFFER *buf, ACPI_RESOURCE *res)
1205{ 1203{
1206 ACPI_RESOURCE *rp; 1204 ACPI_RESOURCE *rp;
1207 void *newp; 1205 void *newp;
1208 1206
1209 /* Initialise the buffer if necessary. */ 1207 /* Initialise the buffer if necessary. */
1210 if (buf->Pointer == NULL) { 1208 if (buf->Pointer == NULL) {
1211 buf->Length = ACPI_INITIAL_RESOURCE_BUFFER_SIZE; 1209 buf->Length = ACPI_INITIAL_RESOURCE_BUFFER_SIZE;
1212 if ((buf->Pointer = ACPI_ALLOCATE(buf->Length)) == NULL) 1210 if ((buf->Pointer = ACPI_ALLOCATE(buf->Length)) == NULL)
1213 return (AE_NO_MEMORY); 1211 return (AE_NO_MEMORY);
1214 rp = (ACPI_RESOURCE *)buf->Pointer; 1212 rp = (ACPI_RESOURCE *)buf->Pointer;
1215 rp->Type = ACPI_RESOURCE_TYPE_END_TAG; 1213 rp->Type = ACPI_RESOURCE_TYPE_END_TAG;
1216 rp->Length = 0; 1214 rp->Length = 0;
1217 } 1215 }
1218 1216
1219 if (res == NULL) 1217 if (res == NULL)
1220 return (AE_OK); 1218 return (AE_OK);
1221 1219
1222 /* 1220 /*
1223 * Scan the current buffer looking for the terminator. 1221 * Scan the current buffer looking for the terminator.
1224 * This will either find the terminator or hit the end 1222 * This will either find the terminator or hit the end
1225 * of the buffer and return an error. 1223 * of the buffer and return an error.
1226 */ 1224 */
1227 rp = (ACPI_RESOURCE *)buf->Pointer; 1225 rp = (ACPI_RESOURCE *)buf->Pointer;
1228 for (;;) { 1226 for (;;) {
1229 /* Range check, don't go outside the buffer */ 1227 /* Range check, don't go outside the buffer */
1230 if (rp >= (ACPI_RESOURCE *)((u_int8_t *)buf->Pointer + 1228 if (rp >= (ACPI_RESOURCE *)((u_int8_t *)buf->Pointer +
1231 buf->Length)) 1229 buf->Length))
1232 return (AE_BAD_PARAMETER); 1230 return (AE_BAD_PARAMETER);
1233 if (rp->Type == ACPI_RESOURCE_TYPE_END_TAG || rp->Length == 0) 1231 if (rp->Type == ACPI_RESOURCE_TYPE_END_TAG || rp->Length == 0)
1234 break; 1232 break;
1235 rp = ACPI_NEXT_RESOURCE(rp); 1233 rp = ACPI_NEXT_RESOURCE(rp);
1236 } 1234 }
1237 1235
1238 /* 1236 /*
1239 * Check the size of the buffer and expand if required. 1237 * Check the size of the buffer and expand if required.
1240 * 1238 *
1241 * Required size is: 1239 * Required size is:
1242 * size of existing resources before terminator +  1240 * size of existing resources before terminator +
1243 * size of new resource and header + 1241 * size of new resource and header +
1244 * size of terminator. 1242 * size of terminator.
1245 * 1243 *
1246 * Note that this loop should really only run once, unless 1244 * Note that this loop should really only run once, unless
1247 * for some reason we are stuffing a *really* huge resource. 1245 * for some reason we are stuffing a *really* huge resource.
1248 */ 1246 */
1249 while ((((u_int8_t *)rp - (u_int8_t *)buf->Pointer) +  1247 while ((((u_int8_t *)rp - (u_int8_t *)buf->Pointer) +
1250 res->Length + ACPI_RS_SIZE_NO_DATA + 1248 res->Length + ACPI_RS_SIZE_NO_DATA +
1251 ACPI_RS_SIZE_MIN) >= buf->Length) { 1249 ACPI_RS_SIZE_MIN) >= buf->Length) {
1252 if ((newp = ACPI_ALLOCATE(buf->Length * 2)) == NULL) 1250 if ((newp = ACPI_ALLOCATE(buf->Length * 2)) == NULL)
1253 return (AE_NO_MEMORY); 1251 return (AE_NO_MEMORY);
1254 memcpy(newp, buf->Pointer, buf->Length); 1252 memcpy(newp, buf->Pointer, buf->Length);
1255 rp = (ACPI_RESOURCE *)((u_int8_t *)newp + 1253 rp = (ACPI_RESOURCE *)((u_int8_t *)newp +
1256 ((u_int8_t *)rp - (u_int8_t *)buf->Pointer)); 1254 ((u_int8_t *)rp - (u_int8_t *)buf->Pointer));
1257 ACPI_FREE(buf->Pointer); 1255 ACPI_FREE(buf->Pointer);
1258 buf->Pointer = newp; 1256 buf->Pointer = newp;
1259 buf->Length += buf->Length; 1257 buf->Length += buf->Length;
1260 } 1258 }
1261 1259
1262 /* Insert the new resource. */ 1260 /* Insert the new resource. */
1263 memcpy(rp, res, res->Length + ACPI_RS_SIZE_NO_DATA); 1261 memcpy(rp, res, res->Length + ACPI_RS_SIZE_NO_DATA);
1264 1262
1265 /* And add the terminator. */ 1263 /* And add the terminator. */
1266 rp = ACPI_NEXT_RESOURCE(rp); 1264 rp = ACPI_NEXT_RESOURCE(rp);
1267 rp->Type = ACPI_RESOURCE_TYPE_END_TAG; 1265 rp->Type = ACPI_RESOURCE_TYPE_END_TAG;
1268 rp->Length = 0; 1266 rp->Length = 0;
1269 1267
1270 return (AE_OK); 1268 return (AE_OK);
1271} 1269}