Print this page
PANKOVs restructure
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/i86pc/io/acpi/acpidev/acpidev_resource.c
+++ new/usr/src/uts/i86pc/io/acpi/acpidev/acpidev_resource.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
↓ open down ↓ |
24 lines elided |
↑ open up ↑ |
25 25 /*
26 26 * Copyright (c) 2009-2010, Intel Corporation.
27 27 * All rights reserved.
28 28 */
29 29
30 30 #include <sys/types.h>
31 31 #include <sys/cmn_err.h>
32 32 #include <sys/sysmacros.h>
33 33 #include <sys/sunddi.h>
34 34 #include <sys/sunndi.h>
35 -#include <sys/acpi/acpi.h>
35 +#include <acpica/include/acpi.h>
36 36 #include <sys/acpica.h>
37 37 #include <sys/acpidev.h>
38 38 #include <sys/acpidev_rsc.h>
39 39 #include <sys/acpidev_impl.h>
40 40
41 41 #define ACPIDEV_RES_INIT_ITEMS 8
42 42 #define ACPIDEV_RES_INCR_ITEMS 8
43 43
44 44 /* Data structure to hold parsed resources during walking. */
45 45 struct acpidev_resource_handle {
46 46 boolean_t acpidev_consumer;
47 47 int acpidev_reg_count;
48 48 int acpidev_reg_max;
49 49 acpidev_phys_spec_t *acpidev_regp;
50 50 acpidev_phys_spec_t acpidev_regs[ACPIDEV_RES_INIT_ITEMS];
51 51 int acpidev_range_count;
52 52 int acpidev_range_max;
53 53 acpidev_ranges_t *acpidev_rangep;
54 54 acpidev_ranges_t acpidev_ranges[ACPIDEV_RES_INIT_ITEMS];
55 55 int acpidev_bus_count;
56 56 int acpidev_bus_max;
57 57 acpidev_bus_range_t *acpidev_busp;
58 58 acpidev_bus_range_t acpidev_buses[ACPIDEV_RES_INIT_ITEMS];
59 59 int acpidev_irq_count;
60 60 int acpidev_irqp[ACPIDEV_RES_IRQ_MAX];
61 61 int acpidev_dma_count;
62 62 int acpidev_dmap[ACPIDEV_RES_DMA_MAX];
63 63 };
64 64
65 65 acpidev_resource_handle_t
66 66 acpidev_resource_handle_alloc(boolean_t consumer)
67 67 {
68 68 acpidev_resource_handle_t rhdl;
69 69
70 70 rhdl = kmem_zalloc(sizeof (*rhdl), KM_SLEEP);
71 71 rhdl->acpidev_consumer = consumer;
72 72 rhdl->acpidev_reg_max = ACPIDEV_RES_INIT_ITEMS;
73 73 rhdl->acpidev_regp = rhdl->acpidev_regs;
74 74 rhdl->acpidev_range_max = ACPIDEV_RES_INIT_ITEMS;
75 75 rhdl->acpidev_rangep = rhdl->acpidev_ranges;
76 76 rhdl->acpidev_bus_max = ACPIDEV_RES_INIT_ITEMS;
77 77 rhdl->acpidev_busp = rhdl->acpidev_buses;
78 78
79 79 return (rhdl);
80 80 }
81 81
82 82 void
83 83 acpidev_resource_handle_free(acpidev_resource_handle_t rhdl)
84 84 {
85 85 size_t sz;
86 86
87 87 ASSERT(rhdl != NULL);
88 88 if (rhdl != NULL) {
89 89 if (rhdl->acpidev_regp != rhdl->acpidev_regs) {
90 90 sz = sizeof (acpidev_phys_spec_t) *
91 91 rhdl->acpidev_reg_max;
92 92 kmem_free(rhdl->acpidev_regp, sz);
93 93 }
94 94 if (rhdl->acpidev_rangep != rhdl->acpidev_ranges) {
95 95 sz = sizeof (acpidev_ranges_t) *
96 96 rhdl->acpidev_range_max;
97 97 kmem_free(rhdl->acpidev_rangep, sz);
98 98 }
99 99 if (rhdl->acpidev_busp != rhdl->acpidev_buses) {
100 100 sz = sizeof (acpidev_bus_range_t) *
101 101 rhdl->acpidev_bus_max;
102 102 kmem_free(rhdl->acpidev_busp, sz);
103 103 }
104 104 kmem_free(rhdl, sizeof (struct acpidev_resource_handle));
105 105 }
106 106 }
107 107
108 108 static void
109 109 acpidev_resource_handle_grow(acpidev_resource_handle_t rhdl)
110 110 {
111 111 size_t sz;
112 112
113 113 if (rhdl->acpidev_reg_count == rhdl->acpidev_reg_max) {
114 114 acpidev_phys_spec_t *regp;
115 115
116 116 /* Prefer linear incremental here. */
117 117 rhdl->acpidev_reg_max += ACPIDEV_RES_INCR_ITEMS;
118 118 sz = sizeof (*regp) * rhdl->acpidev_reg_max;
119 119 regp = kmem_zalloc(sz, KM_SLEEP);
120 120 sz = sizeof (*regp) * rhdl->acpidev_reg_count;
121 121 bcopy(rhdl->acpidev_regp, regp, sz);
122 122 if (rhdl->acpidev_regp != rhdl->acpidev_regs) {
123 123 kmem_free(rhdl->acpidev_regp, sz);
124 124 }
125 125 rhdl->acpidev_regp = regp;
126 126 }
127 127
128 128 if (rhdl->acpidev_range_count == rhdl->acpidev_range_max) {
129 129 acpidev_ranges_t *rngp;
130 130
131 131 /* Prefer linear incremental here. */
132 132 rhdl->acpidev_range_max += ACPIDEV_RES_INCR_ITEMS;
133 133 sz = sizeof (*rngp) * rhdl->acpidev_range_max;
134 134 rngp = kmem_zalloc(sz, KM_SLEEP);
135 135 sz = sizeof (*rngp) * rhdl->acpidev_range_count;
136 136 bcopy(rhdl->acpidev_rangep, rngp, sz);
137 137 if (rhdl->acpidev_rangep != rhdl->acpidev_ranges) {
138 138 kmem_free(rhdl->acpidev_rangep, sz);
139 139 }
140 140 rhdl->acpidev_rangep = rngp;
141 141 }
142 142
143 143 if (rhdl->acpidev_bus_count == rhdl->acpidev_bus_max) {
144 144 acpidev_bus_range_t *busp;
145 145
146 146 /* Prefer linear incremental here. */
147 147 rhdl->acpidev_bus_max += ACPIDEV_RES_INCR_ITEMS;
148 148 sz = sizeof (*busp) * rhdl->acpidev_bus_max;
149 149 busp = kmem_zalloc(sz, KM_SLEEP);
150 150 sz = sizeof (*busp) * rhdl->acpidev_bus_count;
151 151 bcopy(rhdl->acpidev_busp, busp, sz);
152 152 if (rhdl->acpidev_busp != rhdl->acpidev_buses) {
153 153 kmem_free(rhdl->acpidev_busp, sz);
154 154 }
155 155 rhdl->acpidev_busp = busp;
156 156 }
157 157 }
158 158
159 159 ACPI_STATUS
160 160 acpidev_resource_insert_reg(acpidev_resource_handle_t rhdl,
161 161 acpidev_regspec_t *regp)
162 162 {
163 163 ASSERT(rhdl != NULL);
164 164 ASSERT(regp != NULL);
165 165 if (rhdl->acpidev_reg_count >= rhdl->acpidev_reg_max) {
166 166 acpidev_resource_handle_grow(rhdl);
167 167 }
168 168 ASSERT(rhdl->acpidev_reg_count < rhdl->acpidev_reg_max);
169 169 rhdl->acpidev_regp[rhdl->acpidev_reg_count] = *regp;
170 170 rhdl->acpidev_reg_count++;
171 171
172 172 return (AE_OK);
173 173 }
174 174
175 175 ACPI_STATUS
176 176 acpidev_resource_get_regs(acpidev_resource_handle_t rhdl,
177 177 uint_t mask, uint_t value, acpidev_regspec_t *regp, uint_t *cntp)
178 178 {
179 179 uint_t i, j;
180 180
181 181 ASSERT(rhdl != NULL);
182 182 ASSERT(cntp != NULL);
183 183 if (rhdl == NULL || cntp == NULL || (regp == NULL && *cntp != 0)) {
184 184 return (AE_BAD_PARAMETER);
185 185 }
186 186 for (i = 0, j = 0; i < rhdl->acpidev_reg_count; i++) {
187 187 if ((rhdl->acpidev_regp[i].phys_hi & mask) == value) {
188 188 if (j < *cntp) {
189 189 regp[j] = rhdl->acpidev_regp[i];
190 190 }
191 191 j++;
192 192 }
193 193 }
194 194 if (j >= *cntp) {
195 195 *cntp = j;
196 196 return (AE_LIMIT);
197 197 } else {
198 198 *cntp = j;
199 199 return (AE_OK);
200 200 }
201 201 }
202 202
203 203 uint_t
204 204 acpidev_resource_get_reg_count(acpidev_resource_handle_t rhdl,
205 205 uint_t mask, uint_t value)
206 206 {
207 207 uint_t i, j;
208 208
209 209 ASSERT(rhdl != NULL);
210 210 for (i = 0, j = 0; i < rhdl->acpidev_reg_count; i++) {
211 211 if ((rhdl->acpidev_regp[i].phys_hi & mask) == value) {
212 212 j++;
213 213 }
214 214 }
215 215
216 216 return (j);
217 217 }
218 218
219 219 ACPI_STATUS
220 220 acpidev_resource_insert_range(acpidev_resource_handle_t rhdl,
221 221 acpidev_ranges_t *rangep)
222 222 {
223 223 ASSERT(rhdl != NULL);
224 224 ASSERT(rangep != NULL);
225 225 if (rhdl->acpidev_range_count >= rhdl->acpidev_range_max) {
226 226 acpidev_resource_handle_grow(rhdl);
227 227 }
228 228 ASSERT(rhdl->acpidev_range_count < rhdl->acpidev_range_max);
229 229 rhdl->acpidev_rangep[rhdl->acpidev_range_count] = *rangep;
230 230 rhdl->acpidev_range_count++;
231 231
232 232 return (AE_OK);
233 233 }
234 234
235 235 ACPI_STATUS
236 236 acpidev_resource_get_ranges(acpidev_resource_handle_t rhdl,
237 237 uint_t mask, uint_t value, acpidev_ranges_t *rangep, uint_t *cntp)
238 238 {
239 239 uint_t i, j;
240 240
241 241 ASSERT(rhdl != NULL);
242 242 ASSERT(cntp != NULL);
243 243 if (rhdl == NULL || cntp == NULL || (rangep == NULL && *cntp != 0)) {
244 244 return (AE_BAD_PARAMETER);
245 245 }
246 246 for (i = 0, j = 0; i < rhdl->acpidev_range_count; i++) {
247 247 if ((rhdl->acpidev_rangep[i].child_hi & mask) == value) {
248 248 if (j < *cntp) {
249 249 rangep[j] = rhdl->acpidev_rangep[i];
250 250 }
251 251 j++;
252 252 }
253 253 }
254 254 if (j >= *cntp) {
255 255 *cntp = j;
256 256 return (AE_LIMIT);
257 257 } else {
258 258 *cntp = j;
259 259 return (AE_OK);
260 260 }
261 261 }
262 262
263 263 uint_t
264 264 acpidev_resource_get_range_count(acpidev_resource_handle_t rhdl,
265 265 uint_t mask, uint_t value)
266 266 {
267 267 uint_t i, j;
268 268
269 269 ASSERT(rhdl != NULL);
270 270 for (i = 0, j = 0; i < rhdl->acpidev_range_count; i++) {
271 271 if ((rhdl->acpidev_rangep[i].child_hi & mask) == value) {
272 272 j++;
273 273 }
274 274 }
275 275
276 276 return (j);
277 277 }
278 278
279 279 ACPI_STATUS
280 280 acpidev_resource_insert_bus(acpidev_resource_handle_t rhdl,
281 281 acpidev_bus_range_t *busp)
282 282 {
283 283 ASSERT(rhdl != NULL);
284 284 ASSERT(busp != NULL);
285 285 if (rhdl->acpidev_bus_count >= rhdl->acpidev_bus_max) {
286 286 acpidev_resource_handle_grow(rhdl);
287 287 }
288 288 ASSERT(rhdl->acpidev_bus_count < rhdl->acpidev_bus_max);
289 289 rhdl->acpidev_busp[rhdl->acpidev_bus_count] = *busp;
290 290 rhdl->acpidev_bus_count++;
291 291
292 292 return (AE_OK);
293 293 }
294 294
295 295 ACPI_STATUS
296 296 acpidev_resource_get_buses(acpidev_resource_handle_t rhdl,
297 297 acpidev_bus_range_t *busp, uint_t *cntp)
298 298 {
299 299 uint_t i, j;
300 300
301 301 ASSERT(rhdl != NULL);
302 302 ASSERT(cntp != NULL);
303 303 if (rhdl == NULL || cntp == NULL || (busp == NULL && *cntp != 0)) {
304 304 return (AE_BAD_PARAMETER);
305 305 }
306 306 for (i = 0, j = 0; i < rhdl->acpidev_bus_count; i++) {
307 307 if (j < *cntp) {
308 308 busp[j] = rhdl->acpidev_busp[i];
309 309 }
310 310 j++;
311 311 }
312 312 if (j >= *cntp) {
313 313 *cntp = j;
314 314 return (AE_LIMIT);
315 315 } else {
316 316 *cntp = j;
317 317 return (AE_OK);
318 318 }
319 319 }
320 320
321 321 uint_t
322 322 acpidev_resource_get_bus_count(acpidev_resource_handle_t rhdl)
323 323 {
324 324 ASSERT(rhdl != NULL);
325 325 return (rhdl->acpidev_bus_count);
326 326 }
327 327
328 328 ACPI_STATUS
329 329 acpidev_resource_insert_dma(acpidev_resource_handle_t rhdl, int dma)
330 330 {
331 331 ASSERT(rhdl != NULL);
332 332 if (rhdl->acpidev_dma_count >= ACPIDEV_RES_DMA_MAX) {
333 333 ACPIDEV_DEBUG(CE_WARN,
334 334 "!acpidev: too many DMA resources, max %u.",
335 335 ACPIDEV_RES_DMA_MAX);
336 336 return (AE_LIMIT);
337 337 }
338 338 rhdl->acpidev_dmap[rhdl->acpidev_dma_count] = dma;
339 339 rhdl->acpidev_dma_count++;
340 340
341 341 return (AE_OK);
342 342 }
343 343
344 344 ACPI_STATUS
345 345 acpidev_resource_get_dmas(acpidev_resource_handle_t rhdl,
346 346 uint_t *dmap, uint_t *cntp)
347 347 {
348 348 uint_t i, j;
349 349
350 350 ASSERT(rhdl != NULL);
351 351 ASSERT(cntp != NULL);
352 352 if (rhdl == NULL || cntp == NULL || (dmap == NULL && *cntp != 0)) {
353 353 return (AE_BAD_PARAMETER);
354 354 }
355 355 for (i = 0, j = 0; i < rhdl->acpidev_dma_count; i++) {
356 356 if (j < *cntp) {
357 357 dmap[j] = rhdl->acpidev_dmap[i];
358 358 }
359 359 j++;
360 360 }
361 361 if (j >= *cntp) {
362 362 *cntp = j;
363 363 return (AE_LIMIT);
364 364 } else {
365 365 *cntp = j;
366 366 return (AE_OK);
367 367 }
368 368 }
369 369
370 370 uint_t
371 371 acpidev_resource_get_dma_count(acpidev_resource_handle_t rhdl)
372 372 {
373 373 ASSERT(rhdl != NULL);
374 374 return (rhdl->acpidev_dma_count);
375 375 }
376 376
377 377 ACPI_STATUS
378 378 acpidev_resource_insert_irq(acpidev_resource_handle_t rhdl, int irq)
379 379 {
380 380 ASSERT(rhdl != NULL);
381 381 if (rhdl->acpidev_irq_count >= ACPIDEV_RES_IRQ_MAX) {
382 382 ACPIDEV_DEBUG(CE_WARN,
383 383 "!acpidev: too many IRQ resources, max %u.",
384 384 ACPIDEV_RES_IRQ_MAX);
385 385 return (AE_LIMIT);
386 386 }
387 387 rhdl->acpidev_irqp[rhdl->acpidev_irq_count] = irq;
388 388 rhdl->acpidev_irq_count++;
389 389
390 390 return (AE_OK);
391 391 }
392 392
393 393 ACPI_STATUS
394 394 acpidev_resource_get_irqs(acpidev_resource_handle_t rhdl,
395 395 uint_t *irqp, uint_t *cntp)
396 396 {
397 397 uint_t i, j;
398 398
399 399 ASSERT(rhdl != NULL);
400 400 ASSERT(cntp != NULL);
401 401 if (rhdl == NULL || cntp == NULL || (irqp == NULL && *cntp != 0)) {
402 402 return (AE_BAD_PARAMETER);
403 403 }
404 404 for (i = 0, j = 0; i < rhdl->acpidev_irq_count; i++) {
405 405 if (j < *cntp) {
406 406 irqp[j] = rhdl->acpidev_irqp[i];
407 407 }
408 408 j++;
409 409 }
410 410 if (j >= *cntp) {
411 411 *cntp = j;
412 412 return (AE_LIMIT);
413 413 } else {
414 414 *cntp = j;
415 415 return (AE_OK);
416 416 }
417 417 }
418 418
419 419 uint_t
420 420 acpidev_resource_get_irq_count(acpidev_resource_handle_t rhdl)
421 421 {
422 422 ASSERT(rhdl != NULL);
423 423 return (rhdl->acpidev_irq_count);
424 424 }
425 425
426 426 static ACPI_STATUS
427 427 acpidev_resource_address64(acpidev_resource_handle_t rhdl,
428 428 ACPI_RESOURCE_ADDRESS64 *addrp)
429 429 {
430 430 ACPI_STATUS rc = AE_OK;
431 431 uint_t high;
432 432
433 433 ASSERT(addrp != NULL && rhdl != NULL);
434 434 if (addrp->AddressLength == 0) {
435 435 return (AE_OK);
436 436 }
437 437
438 438 switch (addrp->ResourceType) {
439 439 case ACPI_MEMORY_RANGE:
440 440 high = ACPIDEV_REG_TYPE_MEMORY;
441 441 if (addrp->Decode == ACPI_SUB_DECODE) {
442 442 high |= ACPIDEV_REG_SUB_DEC;
443 443 }
444 444 if (addrp->Info.Mem.Translation) {
445 445 high |= ACPIDEV_REG_TRANSLATED;
446 446 }
447 447 if (addrp->Info.Mem.Caching == ACPI_NON_CACHEABLE_MEMORY) {
448 448 high |= ACPIDEV_REG_MEM_COHERENT_NC;
449 449 } else if (addrp->Info.Mem.Caching == ACPI_CACHABLE_MEMORY) {
450 450 high |= ACPIDEV_REG_MEM_COHERENT_CA;
451 451 } else if (addrp->Info.Mem.Caching ==
452 452 ACPI_WRITE_COMBINING_MEMORY) {
453 453 high |= ACPIDEV_REG_MEM_COHERENT_WC;
454 454 } else if (addrp->Info.Mem.Caching ==
455 455 ACPI_PREFETCHABLE_MEMORY) {
456 456 high |= ACPIDEV_REG_MEM_COHERENT_PF;
457 457 } else {
458 458 ACPIDEV_DEBUG(CE_WARN,
459 459 "!acpidev: unknown memory caching type %u.",
460 460 addrp->Info.Mem.Caching);
461 461 rc = AE_ERROR;
462 462 break;
463 463 }
464 464 if (addrp->Info.Mem.WriteProtect == ACPI_READ_WRITE_MEMORY) {
465 465 high |= ACPIDEV_REG_MEM_WRITABLE;
466 466 }
467 467
468 468 /* Generate 'reg' for producer. */
469 469 if (addrp->ProducerConsumer == ACPI_CONSUMER &&
470 470 rhdl->acpidev_consumer == B_TRUE) {
471 471 acpidev_regspec_t reg;
472 472
473 473 reg.phys_hi = high;
474 474 reg.phys_mid = addrp->Minimum >> 32;
475 475 reg.phys_low = addrp->Minimum & 0xFFFFFFFF;
476 476 reg.size_hi = addrp->AddressLength >> 32;
477 477 reg.size_low = addrp->AddressLength & 0xFFFFFFFF;
478 478 rc = acpidev_resource_insert_reg(rhdl, ®);
479 479 if (ACPI_FAILURE(rc)) {
480 480 ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to "
481 481 "insert regspec into resource handle.");
482 482 }
483 483 /* Generate 'ranges' for producer. */
484 484 } else if (addrp->ProducerConsumer == ACPI_PRODUCER &&
485 485 rhdl->acpidev_consumer == B_FALSE) {
486 486 uint64_t paddr;
487 487 acpidev_ranges_t range;
488 488
489 489 range.child_hi = high;
490 490 range.child_mid = addrp->Minimum >> 32;
491 491 range.child_low = addrp->Minimum & 0xFFFFFFFF;
492 492 /* It's IO on parent side if Translation is true. */
493 493 if (addrp->Info.Mem.Translation) {
494 494 range.parent_hi = ACPIDEV_REG_TYPE_IO;
495 495 } else {
496 496 range.parent_hi = high;
497 497 }
498 498 paddr = addrp->Minimum + addrp->TranslationOffset;
499 499 range.parent_mid = paddr >> 32;
500 500 range.parent_low = paddr & 0xFFFFFFFF;
501 501 range.size_hi = addrp->AddressLength >> 32;
502 502 range.size_low = addrp->AddressLength & 0xFFFFFFFF;
503 503 rc = acpidev_resource_insert_range(rhdl, &range);
504 504 if (ACPI_FAILURE(rc)) {
505 505 ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to "
506 506 "insert range into resource handle.");
507 507 }
508 508 }
509 509 break;
510 510
511 511 case ACPI_IO_RANGE:
512 512 high = ACPIDEV_REG_TYPE_IO;
513 513 if (addrp->Decode == ACPI_SUB_DECODE) {
514 514 high |= ACPIDEV_REG_SUB_DEC;
515 515 }
516 516 if (addrp->Info.Io.Translation) {
517 517 high |= ACPIDEV_REG_TRANSLATED;
518 518 }
519 519 if (addrp->Info.Io.RangeType == ACPI_NON_ISA_ONLY_RANGES) {
520 520 high |= ACPIDEV_REG_IO_RANGE_NONISA;
521 521 } else if (addrp->Info.Io.RangeType == ACPI_ISA_ONLY_RANGES) {
522 522 high |= ACPIDEV_REG_IO_RANGE_ISA;
523 523 } else if (addrp->Info.Io.RangeType == ACPI_ENTIRE_RANGE) {
524 524 high |= ACPIDEV_REG_IO_RANGE_FULL;
525 525 } else {
526 526 ACPIDEV_DEBUG(CE_WARN,
527 527 "!acpidev: unknown IO range type %u.",
528 528 addrp->Info.Io.RangeType);
529 529 rc = AE_ERROR;
530 530 break;
531 531 }
532 532 if (addrp->Info.Io.TranslationType == ACPI_SPARSE_TRANSLATION) {
533 533 high |= ACPIDEV_REG_IO_SPARSE;
534 534 }
535 535
536 536 /* Generate 'reg' for producer. */
537 537 if (addrp->ProducerConsumer == ACPI_CONSUMER &&
538 538 rhdl->acpidev_consumer == B_TRUE) {
539 539 acpidev_regspec_t reg;
540 540
541 541 reg.phys_hi = high;
542 542 reg.phys_mid = addrp->Minimum >> 32;
543 543 reg.phys_low = addrp->Minimum & 0xFFFFFFFF;
544 544 reg.size_hi = addrp->AddressLength >> 32;
545 545 reg.size_low = addrp->AddressLength & 0xFFFFFFFF;
546 546 rc = acpidev_resource_insert_reg(rhdl, ®);
547 547 if (ACPI_FAILURE(rc)) {
548 548 ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to "
549 549 "insert regspec into resource handle.");
550 550 }
551 551 /* Generate 'ranges' for producer. */
552 552 } else if (addrp->ProducerConsumer == ACPI_PRODUCER &&
553 553 rhdl->acpidev_consumer == B_FALSE) {
554 554 uint64_t paddr;
555 555 acpidev_ranges_t range;
556 556
557 557 range.child_hi = high;
558 558 range.child_mid = addrp->Minimum >> 32;
559 559 range.child_low = addrp->Minimum & 0xFFFFFFFF;
560 560 /* It's Memory on parent side if Translation is true. */
561 561 if (addrp->Info.Io.Translation) {
562 562 range.parent_hi = ACPIDEV_REG_TYPE_MEMORY;
563 563 } else {
564 564 range.parent_hi = high;
565 565 }
566 566 paddr = addrp->Minimum + addrp->TranslationOffset;
567 567 range.parent_mid = paddr >> 32;
568 568 range.parent_low = paddr & 0xFFFFFFFF;
569 569 range.size_hi = addrp->AddressLength >> 32;
570 570 range.size_low = addrp->AddressLength & 0xFFFFFFFF;
571 571 rc = acpidev_resource_insert_range(rhdl, &range);
572 572 if (ACPI_FAILURE(rc)) {
573 573 ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to "
574 574 "insert range into resource handle.");
575 575 }
576 576 }
577 577 break;
578 578
579 579 case ACPI_BUS_NUMBER_RANGE:
580 580 /* Only support producer of BUS. */
581 581 if (addrp->ProducerConsumer == ACPI_PRODUCER &&
582 582 rhdl->acpidev_consumer == B_FALSE) {
583 583 uint64_t end;
584 584 acpidev_bus_range_t bus;
585 585
586 586 end = addrp->Minimum + addrp->AddressLength;
587 587 if (end < addrp->Minimum || end > UINT_MAX) {
588 588 ACPIDEV_DEBUG(CE_WARN, "!acpidev: bus range "
589 589 "in ADDRESS64 is invalid.");
590 590 rc = AE_ERROR;
591 591 break;
592 592 }
593 593 bus.bus_start = addrp->Minimum & 0xFFFFFFFF;
594 594 bus.bus_end = end & 0xFFFFFFFF;
595 595 ASSERT(bus.bus_start <= bus.bus_end);
596 596 rc = acpidev_resource_insert_bus(rhdl, &bus);
597 597 if (ACPI_FAILURE(rc)) {
598 598 ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to "
599 599 "insert bus range into resource handle.");
600 600 }
601 601 }
602 602 break;
603 603
604 604 default:
605 605 ACPIDEV_DEBUG(CE_WARN,
606 606 "!acpidev: unknown resource type %u in ADDRESS64.",
607 607 addrp->ResourceType);
608 608 rc = AE_BAD_PARAMETER;
609 609 }
610 610
611 611 return (rc);
612 612 }
613 613
614 614 static ACPI_STATUS
615 615 acpidev_resource_walk_producer(ACPI_RESOURCE *rscp, void *ctxp)
616 616 {
617 617 ACPI_STATUS rc = AE_OK;
618 618 acpidev_resource_handle_t rhdl;
619 619
620 620 ASSERT(ctxp != NULL);
621 621 rhdl = (acpidev_resource_handle_t)ctxp;
622 622 ASSERT(rhdl->acpidev_consumer == B_FALSE);
623 623
624 624 switch (rscp->Type) {
625 625 case ACPI_RESOURCE_TYPE_DMA:
626 626 case ACPI_RESOURCE_TYPE_IRQ:
627 627 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
628 628 case ACPI_RESOURCE_TYPE_FIXED_IO:
629 629 case ACPI_RESOURCE_TYPE_MEMORY24:
630 630 case ACPI_RESOURCE_TYPE_MEMORY32:
631 631 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
632 632 case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
633 633 case ACPI_RESOURCE_TYPE_VENDOR:
634 634 ACPIDEV_DEBUG(CE_NOTE,
635 635 "!acpidev: unsupported producer resource type %u, ignored.",
636 636 rscp->Type);
637 637 break;
638 638
639 639 case ACPI_RESOURCE_TYPE_IO:
640 640 {
641 641 acpidev_ranges_t range;
642 642
643 643 range.child_hi = ACPIDEV_REG_TYPE_IO;
644 644 range.child_hi |= ACPIDEV_REG_IO_RANGE_FULL;
645 645 if (rscp->Data.Io.IoDecode == ACPI_DECODE_16) {
646 646 range.child_hi |= ACPIDEV_REG_IO_DECODE16;
647 647 }
648 648 range.parent_hi = range.child_hi;
649 649 range.parent_mid = range.child_mid = 0;
650 650 range.parent_low = range.child_low = rscp->Data.Io.Minimum;
651 651 range.size_hi = 0;
652 652 range.size_low = rscp->Data.Io.AddressLength;
653 653 if ((uint64_t)range.child_low + range.size_low > UINT16_MAX) {
654 654 ACPIDEV_DEBUG(CE_WARN, "!acpidev: invalid IO record, "
655 655 "IO max is out of range.");
656 656 rc = AE_ERROR;
657 657 } else if (range.size_low != 0) {
658 658 rc = acpidev_resource_insert_range(rhdl, &range);
659 659 if (ACPI_FAILURE(rc)) {
660 660 ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to "
661 661 "insert range into resource handle.");
662 662 }
663 663 }
664 664 break;
665 665 }
666 666
667 667 case ACPI_RESOURCE_TYPE_ADDRESS16:
668 668 case ACPI_RESOURCE_TYPE_ADDRESS32:
669 669 case ACPI_RESOURCE_TYPE_ADDRESS64:
670 670 {
671 671 ACPI_RESOURCE_ADDRESS64 addr64;
672 672
673 673 if (rscp->Data.Address.ProducerConsumer != ACPI_PRODUCER) {
674 674 ACPIDEV_DEBUG(CE_NOTE, "!acpidev: producer encountered "
675 675 "a CONSUMER resource, ignored.");
676 676 } else if (ACPI_FAILURE(AcpiResourceToAddress64(rscp,
677 677 &addr64))) {
678 678 ACPIDEV_DEBUG(CE_WARN,
679 679 "!acpidev: failed to convert resource to ADDR64.");
680 680 } else if (ACPI_FAILURE(rc = acpidev_resource_address64(rhdl,
681 681 &addr64))) {
682 682 ACPIDEV_DEBUG(CE_WARN,
683 683 "!acpidev: failed to handle ADDRESS resource.");
684 684 }
685 685 break;
686 686 }
687 687
688 688 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
689 689 {
690 690 ACPI_RESOURCE_ADDRESS64 addr64;
691 691
692 692 if (rscp->Data.ExtAddress64.ProducerConsumer != ACPI_PRODUCER) {
693 693 ACPIDEV_DEBUG(CE_NOTE, "!acpidev: producer encountered "
694 694 "a CONSUMER resource, ignored.");
695 695 break;
696 696 }
697 697
698 698 *(ACPI_RESOURCE_ADDRESS *)&addr64 = rscp->Data.Address;
699 699 addr64.Granularity = rscp->Data.ExtAddress64.Granularity;
700 700 addr64.Minimum = rscp->Data.ExtAddress64.Minimum;
701 701 addr64.Maximum = rscp->Data.ExtAddress64.Maximum;
702 702 addr64.TranslationOffset =
703 703 rscp->Data.ExtAddress64.TranslationOffset;
704 704 addr64.AddressLength = rscp->Data.ExtAddress64.AddressLength;
705 705 if (ACPI_FAILURE(rc = acpidev_resource_address64(rhdl,
706 706 &addr64))) {
707 707 ACPIDEV_DEBUG(CE_WARN,
708 708 "!acpidev: failed to handle EXTADDRESS resource.");
709 709 }
710 710 break;
711 711 }
712 712
713 713 case ACPI_RESOURCE_TYPE_START_DEPENDENT:
714 714 case ACPI_RESOURCE_TYPE_END_DEPENDENT:
715 715 ACPIDEV_DEBUG(CE_NOTE, "!acpidev: producer encountered "
716 716 "START_DEPENDENT or END_DEPENDENT tag, ignored.");
717 717 break;
718 718
719 719 case ACPI_RESOURCE_TYPE_END_TAG:
720 720 /* Finish walking when we encounter END_TAG. */
721 721 rc = AE_CTRL_TERMINATE;
722 722 break;
723 723
724 724 default:
725 725 ACPIDEV_DEBUG(CE_NOTE,
726 726 "!acpidev: unknown ACPI resource type %u, ignored.",
727 727 rscp->Type);
728 728 break;
729 729 }
730 730
731 731 return (rc);
732 732 }
733 733
734 734 static ACPI_STATUS
735 735 acpidev_resource_walk_consumer(ACPI_RESOURCE *rscp, void *ctxp)
736 736 {
737 737 ACPI_STATUS rc = AE_OK;
738 738 acpidev_resource_handle_t rhdl;
739 739
740 740 ASSERT(ctxp != NULL);
741 741 rhdl = (acpidev_resource_handle_t)ctxp;
742 742 ASSERT(rhdl->acpidev_consumer == B_TRUE);
743 743
744 744 switch (rscp->Type) {
745 745 case ACPI_RESOURCE_TYPE_MEMORY24:
746 746 case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
747 747 case ACPI_RESOURCE_TYPE_VENDOR:
748 748 ACPIDEV_DEBUG(CE_NOTE,
749 749 "!acpidev: unsupported consumer resource type %u, ignored.",
750 750 rscp->Type);
751 751 break;
752 752
753 753 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
754 754 {
755 755 int i;
756 756
757 757 if (rscp->Data.ExtendedIrq.ProducerConsumer != ACPI_CONSUMER) {
758 758 ACPIDEV_DEBUG(CE_NOTE, "!acpidev: consumer encountered "
759 759 "a PRODUCER resource, ignored.");
760 760 break;
761 761 }
762 762 for (i = 0; i < rscp->Data.ExtendedIrq.InterruptCount; i++) {
763 763 if (ACPI_SUCCESS(acpidev_resource_insert_irq(rhdl,
764 764 rscp->Data.ExtendedIrq.Interrupts[i]))) {
765 765 continue;
766 766 }
767 767 ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to insert"
768 768 "Extended IRQ into resource handle.");
769 769 rc = AE_ERROR;
770 770 break;
771 771 }
772 772 break;
773 773 }
774 774
775 775 case ACPI_RESOURCE_TYPE_IRQ:
776 776 {
777 777 int i;
778 778
779 779 for (i = 0; i < rscp->Data.Irq.InterruptCount; i++) {
780 780 if (ACPI_SUCCESS(acpidev_resource_insert_irq(rhdl,
781 781 rscp->Data.Irq.Interrupts[i]))) {
782 782 continue;
783 783 }
784 784 ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to insert"
785 785 "IRQ into resource handle.");
786 786 rc = AE_ERROR;
787 787 break;
788 788 }
789 789 break;
790 790 }
791 791
792 792 case ACPI_RESOURCE_TYPE_DMA:
793 793 {
794 794 int i;
795 795
796 796 for (i = 0; i < rscp->Data.Dma.ChannelCount; i++) {
797 797 if (ACPI_SUCCESS(acpidev_resource_insert_dma(rhdl,
798 798 rscp->Data.Dma.Channels[i]))) {
799 799 continue;
800 800 }
801 801 ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to insert"
802 802 "dma into resource handle.");
803 803 rc = AE_ERROR;
804 804 break;
805 805 }
806 806 break;
807 807 }
808 808
809 809 case ACPI_RESOURCE_TYPE_IO:
810 810 case ACPI_RESOURCE_TYPE_FIXED_IO:
811 811 {
812 812 acpidev_regspec_t reg;
813 813
814 814 reg.phys_hi = ACPIDEV_REG_TYPE_IO;
815 815 reg.phys_hi |= ACPIDEV_REG_IO_RANGE_FULL;
816 816 if (rscp->Type == ACPI_RESOURCE_TYPE_IO) {
817 817 if (rscp->Data.Io.IoDecode == ACPI_DECODE_16) {
818 818 reg.phys_hi |= ACPIDEV_REG_IO_DECODE16;
819 819 }
820 820 reg.phys_low = rscp->Data.Io.Minimum;
821 821 reg.size_low = rscp->Data.Io.AddressLength;
822 822 } else {
823 823 reg.phys_hi |= ACPIDEV_REG_IO_DECODE16;
824 824 reg.phys_low = rscp->Data.FixedIo.Address;
825 825 reg.size_low = rscp->Data.FixedIo.AddressLength;
826 826 }
827 827 reg.phys_mid = 0;
828 828 reg.size_hi = 0;
829 829 if ((uint64_t)reg.phys_low + reg.size_low > UINT16_MAX) {
830 830 ACPIDEV_DEBUG(CE_WARN, "!acpidev: invalid IO/FIXEDIO "
831 831 "record, IO max is out of range.");
832 832 rc = AE_ERROR;
833 833 } else if (reg.size_low != 0) {
834 834 rc = acpidev_resource_insert_reg(rhdl, ®);
835 835 if (ACPI_FAILURE(rc)) {
836 836 ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to "
837 837 "insert reg into resource handle.");
838 838 }
839 839 }
840 840 break;
841 841 }
842 842
843 843 case ACPI_RESOURCE_TYPE_MEMORY32:
844 844 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
845 845 {
846 846 acpidev_regspec_t reg;
847 847
848 848 reg.phys_hi = ACPIDEV_REG_TYPE_MEMORY;
849 849 reg.phys_hi |= ACPIDEV_REG_MEM_COHERENT_CA;
850 850 if (rscp->Type == ACPI_RESOURCE_TYPE_MEMORY32) {
851 851 if (rscp->Data.Memory32.WriteProtect ==
852 852 ACPI_READ_WRITE_MEMORY) {
853 853 reg.phys_hi |= ACPIDEV_REG_MEM_WRITABLE;
854 854 }
855 855 reg.phys_low = rscp->Data.Memory32.Minimum;
856 856 reg.size_low = rscp->Data.Memory32.AddressLength;
857 857 } else {
858 858 if (rscp->Data.FixedMemory32.WriteProtect ==
859 859 ACPI_READ_WRITE_MEMORY) {
860 860 reg.phys_hi |= ACPIDEV_REG_MEM_WRITABLE;
861 861 }
862 862 reg.phys_low = rscp->Data.FixedMemory32.Address;
863 863 reg.size_low = rscp->Data.FixedMemory32.AddressLength;
864 864 }
865 865 reg.phys_mid = 0;
866 866 reg.size_hi = 0;
867 867 if ((uint64_t)reg.phys_low + reg.size_low > UINT32_MAX) {
868 868 ACPIDEV_DEBUG(CE_WARN,
869 869 "!acpidev: invalid MEMORY32/FIXEDMEMORY32 record, "
870 870 "memory max is out of range.");
871 871 rc = AE_ERROR;
872 872 } else if (reg.size_low != 0) {
873 873 rc = acpidev_resource_insert_reg(rhdl, ®);
874 874 if (ACPI_FAILURE(rc)) {
875 875 ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to "
876 876 "insert reg into resource handle.");
877 877 }
878 878 }
879 879 break;
880 880 }
881 881
882 882 case ACPI_RESOURCE_TYPE_ADDRESS16:
883 883 case ACPI_RESOURCE_TYPE_ADDRESS32:
884 884 case ACPI_RESOURCE_TYPE_ADDRESS64:
885 885 {
886 886 ACPI_RESOURCE_ADDRESS64 addr64;
887 887
888 888 if (rscp->Data.Address.ProducerConsumer != ACPI_CONSUMER) {
889 889 ACPIDEV_DEBUG(CE_NOTE, "!acpidev: consumer encountered "
890 890 "a PRODUCER resource, ignored.");
891 891 } else if (ACPI_FAILURE(AcpiResourceToAddress64(rscp,
892 892 &addr64))) {
893 893 ACPIDEV_DEBUG(CE_WARN,
894 894 "!acpidev: failed to convert resource to ADDR64.");
895 895 } else if (ACPI_FAILURE(rc = acpidev_resource_address64(rhdl,
896 896 &addr64))) {
897 897 ACPIDEV_DEBUG(CE_WARN,
898 898 "!acpidev: failed to handle ADDRESS resource.");
899 899 }
900 900 break;
901 901 }
902 902
903 903 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
904 904 {
905 905 ACPI_RESOURCE_ADDRESS64 addr64;
906 906
907 907 if (rscp->Data.ExtAddress64.ProducerConsumer != ACPI_CONSUMER) {
908 908 ACPIDEV_DEBUG(CE_NOTE, "!acpidev: consumer encountered "
909 909 "a PRODUCER resource, ignored.");
910 910 break;
911 911 }
912 912
913 913 *(ACPI_RESOURCE_ADDRESS *)&addr64 = rscp->Data.Address;
914 914 addr64.Granularity = rscp->Data.ExtAddress64.Granularity;
915 915 addr64.Minimum = rscp->Data.ExtAddress64.Minimum;
916 916 addr64.Maximum = rscp->Data.ExtAddress64.Maximum;
917 917 addr64.TranslationOffset =
918 918 rscp->Data.ExtAddress64.TranslationOffset;
919 919 addr64.AddressLength = rscp->Data.ExtAddress64.AddressLength;
920 920 if (ACPI_FAILURE(rc = acpidev_resource_address64(rhdl,
921 921 &addr64))) {
922 922 ACPIDEV_DEBUG(CE_WARN,
923 923 "!acpidev: failed to handle EXTADDRESS resource.");
924 924 }
925 925 break;
926 926 }
927 927
928 928 case ACPI_RESOURCE_TYPE_START_DEPENDENT:
929 929 case ACPI_RESOURCE_TYPE_END_DEPENDENT:
930 930 ACPIDEV_DEBUG(CE_NOTE, "!acpidev: consumer encountered "
931 931 "START_DEPENDENT or END_DEPENDENT tag, ignored.");
932 932 break;
933 933
934 934 case ACPI_RESOURCE_TYPE_END_TAG:
935 935 /* Finish walking when we encounter END_TAG. */
936 936 rc = AE_CTRL_TERMINATE;
937 937 break;
938 938
939 939 default:
940 940 ACPIDEV_DEBUG(CE_NOTE,
941 941 "!acpidev: unknown ACPI resource type %u, ignored.",
942 942 rscp->Type);
943 943 break;
944 944 }
945 945
946 946 return (rc);
947 947 }
948 948
949 949 ACPI_STATUS
950 950 acpidev_resource_walk(ACPI_HANDLE hdl, char *method,
951 951 boolean_t consumer, acpidev_resource_handle_t *rhdlp)
952 952 {
953 953 ACPI_STATUS rc = AE_OK;
954 954 ACPI_HANDLE mhdl = NULL;
955 955 acpidev_resource_handle_t rhdl = NULL;
956 956
957 957 ASSERT(hdl != NULL);
958 958 ASSERT(method != NULL);
959 959 ASSERT(rhdlp != NULL);
960 960 if (hdl == NULL) {
961 961 ACPIDEV_DEBUG(CE_WARN,
962 962 "!acpidev: hdl is NULL in acpidev_resource_walk().");
963 963 return (AE_BAD_PARAMETER);
964 964 } else if (method == NULL) {
965 965 ACPIDEV_DEBUG(CE_WARN,
966 966 "!acpidev: method is NULL in acpidev_resource_walk().");
967 967 return (AE_BAD_PARAMETER);
968 968 } else if (rhdlp == NULL) {
969 969 ACPIDEV_DEBUG(CE_WARN, "!acpidev: resource handle ptr is NULL "
970 970 "in acpidev_resource_walk().");
971 971 return (AE_BAD_PARAMETER);
972 972 }
973 973
974 974 /* Check whether method exists under object. */
975 975 if (ACPI_FAILURE(AcpiGetHandle(hdl, method, &mhdl))) {
976 976 char *objname = acpidev_get_object_name(hdl);
977 977 ACPIDEV_DEBUG(CE_NOTE,
978 978 "!acpidev: method %s doesn't exist under %s",
979 979 method, objname);
980 980 acpidev_free_object_name(objname);
981 981 return (AE_NOT_FOUND);
982 982 }
983 983
984 984 /* Walk all resources. */
985 985 rhdl = acpidev_resource_handle_alloc(consumer);
986 986 if (consumer) {
987 987 rc = AcpiWalkResources(hdl, method,
988 988 acpidev_resource_walk_consumer, rhdl);
989 989 } else {
990 990 rc = AcpiWalkResources(hdl, method,
991 991 acpidev_resource_walk_producer, rhdl);
992 992 }
993 993 if (ACPI_SUCCESS(rc)) {
994 994 *rhdlp = rhdl;
995 995 } else {
996 996 acpidev_resource_handle_free(rhdl);
997 997 }
998 998 if (ACPI_FAILURE(rc)) {
999 999 char *objname = acpidev_get_object_name(hdl);
1000 1000 ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to walk resource from "
1001 1001 "method %s under %s.", method, objname);
1002 1002 acpidev_free_object_name(objname);
1003 1003 }
1004 1004
1005 1005 return (rc);
1006 1006 }
1007 1007
1008 1008 ACPI_STATUS
1009 1009 acpidev_resource_process(acpidev_walk_info_t *infop, boolean_t consumer)
1010 1010 {
1011 1011 ACPI_STATUS rc;
1012 1012 char path[MAXPATHLEN];
1013 1013 acpidev_resource_handle_t rhdl = NULL;
1014 1014
1015 1015 ASSERT(infop != NULL);
1016 1016 if (infop == NULL) {
1017 1017 ACPIDEV_DEBUG(CE_WARN, "!acpidev: invalid parameter "
1018 1018 "in acpidev_resource_process().");
1019 1019 return (AE_BAD_PARAMETER);
1020 1020 }
1021 1021
1022 1022 /* Walk all resources. */
1023 1023 (void) ddi_pathname(infop->awi_dip, path);
1024 1024 rc = acpidev_resource_walk(infop->awi_hdl, METHOD_NAME__CRS,
1025 1025 consumer, &rhdl);
1026 1026 if (ACPI_FAILURE(rc)) {
1027 1027 ACPIDEV_DEBUG(CE_WARN,
1028 1028 "!acpidev: failed to walk ACPI resources of %s(%s).",
1029 1029 path, infop->awi_name);
1030 1030 return (rc);
1031 1031 }
1032 1032
1033 1033 if (consumer) {
1034 1034 /* Create device properties for consumer. */
1035 1035
1036 1036 /* Create 'reg' and 'assigned-addresses' properties. */
1037 1037 if (rhdl->acpidev_reg_count > 0 &&
1038 1038 ndi_prop_update_int_array(DDI_DEV_T_NONE, infop->awi_dip,
1039 1039 "reg", (int *)rhdl->acpidev_regp,
1040 1040 rhdl->acpidev_reg_count * sizeof (acpidev_regspec_t) /
1041 1041 sizeof (int)) != NDI_SUCCESS) {
1042 1042 ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to set "
1043 1043 "'reg' property for %s.", path);
1044 1044 rc = AE_ERROR;
1045 1045 goto out;
1046 1046 }
1047 1047 if (rhdl->acpidev_reg_count > 0 &&
1048 1048 ndi_prop_update_int_array(DDI_DEV_T_NONE, infop->awi_dip,
1049 1049 "assigned-addresses", (int *)rhdl->acpidev_regp,
1050 1050 rhdl->acpidev_reg_count * sizeof (acpidev_regspec_t) /
1051 1051 sizeof (int)) != NDI_SUCCESS) {
1052 1052 ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to set "
1053 1053 "'assigned-addresses' property for %s.", path);
1054 1054 rc = AE_ERROR;
1055 1055 goto out;
1056 1056 }
1057 1057
1058 1058 /* Create 'interrupts' property. */
1059 1059 if (rhdl->acpidev_irq_count > 0 &&
1060 1060 ndi_prop_update_int_array(DDI_DEV_T_NONE, infop->awi_dip,
1061 1061 "interrupts", (int *)rhdl->acpidev_irqp,
1062 1062 rhdl->acpidev_irq_count) != NDI_SUCCESS) {
1063 1063 ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to set "
1064 1064 "'interrupts' property for %s.", path);
1065 1065 rc = AE_ERROR;
1066 1066 goto out;
1067 1067 }
1068 1068
1069 1069 /* Create 'dma-channels' property. */
1070 1070 if (rhdl->acpidev_dma_count > 0 &&
1071 1071 ndi_prop_update_int_array(DDI_DEV_T_NONE, infop->awi_dip,
1072 1072 "dma-channels", (int *)rhdl->acpidev_dmap,
1073 1073 rhdl->acpidev_dma_count) != NDI_SUCCESS) {
1074 1074 ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to set "
1075 1075 "'dma-channels' property for %s.", path);
1076 1076 rc = AE_ERROR;
1077 1077 goto out;
1078 1078 }
1079 1079
1080 1080 } else {
1081 1081 /* Create device properties for producer. */
1082 1082
1083 1083 /* Create 'ranges' property. */
1084 1084 if (rhdl->acpidev_range_count > 0 &&
1085 1085 ndi_prop_update_int_array(DDI_DEV_T_NONE, infop->awi_dip,
1086 1086 "ranges", (int *)rhdl->acpidev_rangep,
1087 1087 rhdl->acpidev_range_count * sizeof (acpidev_ranges_t) /
1088 1088 sizeof (int)) != NDI_SUCCESS) {
1089 1089 ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to set "
1090 1090 "'ranges' property for %s.", path);
1091 1091 rc = AE_ERROR;
1092 1092 goto out;
1093 1093 }
1094 1094
1095 1095 /* Create 'bus-range' property. */
1096 1096 if (rhdl->acpidev_bus_count > 0 &&
1097 1097 ndi_prop_update_int_array(DDI_DEV_T_NONE, infop->awi_dip,
1098 1098 "bus-range", (int *)rhdl->acpidev_busp,
1099 1099 rhdl->acpidev_bus_count * sizeof (acpidev_bus_range_t) /
1100 1100 sizeof (int)) != NDI_SUCCESS) {
1101 1101 ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to set "
1102 1102 "'bus-range' property for %s.", path);
1103 1103 rc = AE_ERROR;
1104 1104 goto out;
1105 1105 }
1106 1106 }
1107 1107
1108 1108 out:
1109 1109 /* Free resources allocated by acpidev_resource_walk. */
1110 1110 acpidev_resource_handle_free(rhdl);
1111 1111
1112 1112 return (rc);
1113 1113 }
↓ open down ↓ |
1068 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX