1 /*-
2 * Copyright (c) 2000 Michael Smith
3 * Copyright (c) 2000 BSDi
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD: releng/5.2/sys/dev/acpica/acpi_resource.c 120453 2003-09-26 05:24:55Z njl $");
30
31 #include "opt_acpi.h"
32 #include <sys/param.h>
33 #include <sys/kernel.h>
34 #include <sys/bus.h>
35
36 #include <machine/bus.h>
37 #include <machine/resource.h>
38 #include <sys/rman.h>
39
40 #include "acpi.h"
41 #include <dev/acpica/acpivar.h>
42
43 /* Hooks for the ACPI CA debugging infrastructure */
44 #define _COMPONENT ACPI_BUS
45 ACPI_MODULE_NAME("RESOURCE")
46
47 /*
48 * Fetch a device's resources and associate them with the device.
49 *
50 * Note that it might be nice to also locate ACPI-specific resource items, such
51 * as GPE bits.
52 *
53 * We really need to split the resource-fetching code out from the
54 * resource-parsing code, since we may want to use the parsing
55 * code for _PRS someday.
56 */
57 ACPI_STATUS
58 acpi_parse_resources(device_t dev, ACPI_HANDLE handle,
59 struct acpi_parse_resource_set *set)
60 {
61 ACPI_BUFFER buf;
62 ACPI_RESOURCE *res;
63 char *curr, *last;
64 ACPI_STATUS status;
65 void *context;
66
67 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
68
69 /*
70 * Special-case some devices that abuse _PRS/_CRS to mean
71 * something other than "I consume this resource".
72 *
73 * XXX do we really need this? It's only relevant once
74 * we start always-allocating these resources, and even
75 * then, the only special-cased device is likely to be
76 * the PCI interrupt link.
77 */
78
79 /* Fetch the device's current resources. */
80 buf.Length = ACPI_ALLOCATE_BUFFER;
81 if (ACPI_FAILURE((status = AcpiGetCurrentResources(handle, &buf)))) {
82 if (status != AE_NOT_FOUND)
83 printf("can't fetch resources for %s - %s\n",
84 acpi_name(handle), AcpiFormatException(status));
85 return_ACPI_STATUS (status);
86 }
87 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s - got %ld bytes of resources\n",
88 acpi_name(handle), (long)buf.Length));
89 set->set_init(dev, &context);
90
91 /* Iterate through the resources */
92 curr = buf.Pointer;
93 last = (char *)buf.Pointer + buf.Length;
94 while (curr < last) {
95 res = (ACPI_RESOURCE *)curr;
96 curr += res->Length;
97
98 /* Handle the individual resource types */
99 switch(res->Id) {
100 case ACPI_RSTYPE_END_TAG:
101 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "EndTag\n"));
102 curr = last;
103 break;
104 case ACPI_RSTYPE_FIXED_IO:
105 if (res->Data.FixedIo.RangeLength <= 0)
106 break;
107 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedIo 0x%x/%d\n",
108 res->Data.FixedIo.BaseAddress,
109 res->Data.FixedIo.RangeLength));
110 set->set_ioport(dev, context,
111 res->Data.FixedIo.BaseAddress,
112 res->Data.FixedIo.RangeLength);
113 break;
114 case ACPI_RSTYPE_IO:
115 if (res->Data.Io.RangeLength <= 0)
116 break;
117 if (res->Data.Io.MinBaseAddress == res->Data.Io.MaxBaseAddress) {
118 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x/%d\n",
119 res->Data.Io.MinBaseAddress,
120 res->Data.Io.RangeLength));
121 set->set_ioport(dev, context,
122 res->Data.Io.MinBaseAddress,
123 res->Data.Io.RangeLength);
124 } else {
125 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x-0x%x/%d\n",
126 res->Data.Io.MinBaseAddress,
127 res->Data.Io.MaxBaseAddress,
128 res->Data.Io.RangeLength));
129 set->set_iorange(dev, context,
130 res->Data.Io.MinBaseAddress,
131 res->Data.Io.MaxBaseAddress,
132 res->Data.Io.RangeLength,
133 res->Data.Io.Alignment);
134 }
135 break;
136 case ACPI_RSTYPE_FIXED_MEM32:
137 if (res->Data.FixedMemory32.RangeLength <= 0)
138 break;
139 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedMemory32 0x%x/%d\n",
140 res->Data.FixedMemory32.RangeBaseAddress,
141 res->Data.FixedMemory32.RangeLength));
142 set->set_memory(dev, context,
143 res->Data.FixedMemory32.RangeBaseAddress,
144 res->Data.FixedMemory32.RangeLength);
145 break;
146 case ACPI_RSTYPE_MEM32:
147 if (res->Data.Memory32.RangeLength <= 0)
148 break;
149 if (res->Data.Memory32.MinBaseAddress ==
150 res->Data.Memory32.MaxBaseAddress) {
151
152 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x/%d\n",
153 res->Data.Memory32.MinBaseAddress,
154 res->Data.Memory32.RangeLength));
155 set->set_memory(dev, context,
156 res->Data.Memory32.MinBaseAddress,
157 res->Data.Memory32.RangeLength);
158 } else {
159 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x-0x%x/%d\n",
160 res->Data.Memory32.MinBaseAddress,
161 res->Data.Memory32.MaxBaseAddress,
162 res->Data.Memory32.RangeLength));
163 set->set_memoryrange(dev, context,
164 res->Data.Memory32.MinBaseAddress,
165 res->Data.Memory32.MaxBaseAddress,
166 res->Data.Memory32.RangeLength,
167 res->Data.Memory32.Alignment);
168 }
169 break;
170 case ACPI_RSTYPE_MEM24:
171 if (res->Data.Memory24.RangeLength <= 0)
172 break;
173 if (res->Data.Memory24.MinBaseAddress ==
174 res->Data.Memory24.MaxBaseAddress) {
175
176 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x/%d\n",
177 res->Data.Memory24.MinBaseAddress,
178 res->Data.Memory24.RangeLength));
179 set->set_memory(dev, context, res->Data.Memory24.MinBaseAddress,
180 res->Data.Memory24.RangeLength);
181 } else {
182 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x-0x%x/%d\n",
183 res->Data.Memory24.MinBaseAddress,
184 res->Data.Memory24.MaxBaseAddress,
185 res->Data.Memory24.RangeLength));
186 set->set_memoryrange(dev, context,
187 res->Data.Memory24.MinBaseAddress,
188 res->Data.Memory24.MaxBaseAddress,
189 res->Data.Memory24.RangeLength,
190 res->Data.Memory24.Alignment);
191 }
192 break;
193 case ACPI_RSTYPE_IRQ:
194 /*
195 * from 1.0b 6.4.2
196 * "This structure is repeated for each separate interrupt
197 * required"
198 */
199 set->set_irq(dev, context, res->Data.Irq.Interrupts,
200 res->Data.Irq.NumberOfInterrupts, res->Data.Irq.EdgeLevel,
201 res->Data.Irq.ActiveHighLow);
202 break;
203 case ACPI_RSTYPE_DMA:
204 /*
205 * from 1.0b 6.4.3
206 * "This structure is repeated for each separate dma channel
207 * required"
208 */
209 set->set_drq(dev, context, res->Data.Dma.Channels,
210 res->Data.Dma.NumberOfChannels);
211 break;
212 case ACPI_RSTYPE_START_DPF:
213 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "start dependant functions\n"));
214 set->set_start_dependant(dev, context,
215 res->Data.StartDpf.CompatibilityPriority);
216 break;
217 case ACPI_RSTYPE_END_DPF:
218 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "end dependant functions\n"));
219 set->set_end_dependant(dev, context);
220 break;
221 case ACPI_RSTYPE_ADDRESS32:
222 if (res->Data.Address32.AddressLength <= 0)
223 break;
224 if (res->Data.Address32.ProducerConsumer != ACPI_CONSUMER) {
225 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
226 "ignored Address32 %s producer\n",
227 res->Data.Address32.ResourceType == ACPI_IO_RANGE ?
228 "IO" : "Memory"));
229 break;
230 }
231 if (res->Data.Address32.ResourceType != ACPI_MEMORY_RANGE &&
232 res->Data.Address32.ResourceType != ACPI_IO_RANGE) {
233 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
234 "ignored Address32 for non-memory, non-I/O\n"));
235 break;
236 }
237
238 if (res->Data.Address32.MinAddressFixed == ACPI_ADDRESS_FIXED &&
239 res->Data.Address32.MaxAddressFixed == ACPI_ADDRESS_FIXED) {
240
241 if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) {
242 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
243 "Address32/Memory 0x%x/%d\n",
244 res->Data.Address32.MinAddressRange,
245 res->Data.Address32.AddressLength));
246 set->set_memory(dev, context,
247 res->Data.Address32.MinAddressRange,
248 res->Data.Address32.AddressLength);
249 } else {
250 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
251 "Address32/IO 0x%x/%d\n",
252 res->Data.Address32.MinAddressRange,
253 res->Data.Address32.AddressLength));
254 set->set_ioport(dev, context,
255 res->Data.Address32.MinAddressRange,
256 res->Data.Address32.AddressLength);
257 }
258 } else {
259 if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) {
260 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
261 "Address32/Memory 0x%x-0x%x/%d\n",
262 res->Data.Address32.MinAddressRange,
263 res->Data.Address32.MaxAddressRange,
264 res->Data.Address32.AddressLength));
265 set->set_memoryrange(dev, context,
266 res->Data.Address32.MinAddressRange,
267 res->Data.Address32.MaxAddressRange,
268 res->Data.Address32.AddressLength,
269 res->Data.Address32.Granularity);
270 } else {
271 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
272 "Address32/IO 0x%x-0x%x/%d\n",
273 res->Data.Address32.MinAddressRange,
274 res->Data.Address32.MaxAddressRange,
275 res->Data.Address32.AddressLength));
276 set->set_iorange(dev, context,
277 res->Data.Address32.MinAddressRange,
278 res->Data.Address32.MaxAddressRange,
279 res->Data.Address32.AddressLength,
280 res->Data.Address32.Granularity);
281 }
282 }
283 break;
284 case ACPI_RSTYPE_ADDRESS16:
285 if (res->Data.Address16.AddressLength <= 0)
286 break;
287 if (res->Data.Address16.ProducerConsumer != ACPI_CONSUMER) {
288 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
289 "ignored Address16 %s producer\n",
290 res->Data.Address16.ResourceType == ACPI_IO_RANGE ?
291 "IO" : "Memory"));
292 break;
293 }
294 if (res->Data.Address16.ResourceType != ACPI_MEMORY_RANGE &&
295 res->Data.Address16.ResourceType != ACPI_IO_RANGE) {
296 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
297 "ignored Address16 for non-memory, non-I/O\n"));
298 break;
299 }
300
301 if (res->Data.Address16.MinAddressFixed == ACPI_ADDRESS_FIXED &&
302 res->Data.Address16.MaxAddressFixed == ACPI_ADDRESS_FIXED) {
303
304 if (res->Data.Address16.ResourceType == ACPI_MEMORY_RANGE) {
305 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
306 "Address16/Memory 0x%x/%d\n",
307 res->Data.Address16.MinAddressRange,
308 res->Data.Address16.AddressLength));
309 set->set_memory(dev, context,
310 res->Data.Address16.MinAddressRange,
311 res->Data.Address16.AddressLength);
312 } else {
313 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
314 "Address16/IO 0x%x/%d\n",
315 res->Data.Address16.MinAddressRange,
316 res->Data.Address16.AddressLength));
317 set->set_ioport(dev, context,
318 res->Data.Address16.MinAddressRange,
319 res->Data.Address16.AddressLength);
320 }
321 } else {
322 if (res->Data.Address16.ResourceType == ACPI_MEMORY_RANGE) {
323 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
324 "Address16/Memory 0x%x-0x%x/%d\n",
325 res->Data.Address16.MinAddressRange,
326 res->Data.Address16.MaxAddressRange,
327 res->Data.Address16.AddressLength));
328 set->set_memoryrange(dev, context,
329 res->Data.Address16.MinAddressRange,
330 res->Data.Address16.MaxAddressRange,
331 res->Data.Address16.AddressLength,
332 res->Data.Address16.Granularity);
333 } else {
334 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
335 "Address16/IO 0x%x-0x%x/%d\n",
336 res->Data.Address16.MinAddressRange,
337 res->Data.Address16.MaxAddressRange,
338 res->Data.Address16.AddressLength));
339 set->set_iorange(dev, context,
340 res->Data.Address16.MinAddressRange,
341 res->Data.Address16.MaxAddressRange,
342 res->Data.Address16.AddressLength,
343 res->Data.Address16.Granularity);
344 }
345 }
346 break;
347 case ACPI_RSTYPE_ADDRESS64:
348 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
349 "unimplemented Address64 resource\n"));
350 break;
351 case ACPI_RSTYPE_EXT_IRQ:
352 /* XXX special handling? */
353 set->set_irq(dev, context,res->Data.ExtendedIrq.Interrupts,
354 res->Data.ExtendedIrq.NumberOfInterrupts,
355 res->Data.ExtendedIrq.EdgeLevel,
356 res->Data.ExtendedIrq.ActiveHighLow);
357 break;
358 case ACPI_RSTYPE_VENDOR:
359 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
360 "unimplemented VendorSpecific resource\n"));
361 break;
362 default:
363 break;
364 }
365 }
366
367 AcpiOsFree(buf.Pointer);
368 set->set_done(dev, context);
369 return_ACPI_STATUS (AE_OK);
370 }
371
372 /*
373 * Resource-set vectors used to attach _CRS-derived resources
374 * to an ACPI device.
375 */
376 static void acpi_res_set_init(device_t dev, void **context);
377 static void acpi_res_set_done(device_t dev, void *context);
378 static void acpi_res_set_ioport(device_t dev, void *context,
379 u_int32_t base, u_int32_t length);
380 static void acpi_res_set_iorange(device_t dev, void *context,
381 u_int32_t low, u_int32_t high,
382 u_int32_t length, u_int32_t align);
383 static void acpi_res_set_memory(device_t dev, void *context,
384 u_int32_t base, u_int32_t length);
385 static void acpi_res_set_memoryrange(device_t dev, void *context,
386 u_int32_t low, u_int32_t high,
387 u_int32_t length, u_int32_t align);
388 static void acpi_res_set_irq(device_t dev, void *context, u_int32_t *irq,
389 int count, int trig, int pol);
390 static void acpi_res_set_drq(device_t dev, void *context, u_int32_t *drq,
391 int count);
392 static void acpi_res_set_start_dependant(device_t dev, void *context,
393 int preference);
394 static void acpi_res_set_end_dependant(device_t dev, void *context);
395
396 struct acpi_parse_resource_set acpi_res_parse_set = {
397 acpi_res_set_init,
398 acpi_res_set_done,
399 acpi_res_set_ioport,
400 acpi_res_set_iorange,
401 acpi_res_set_memory,
402 acpi_res_set_memoryrange,
403 acpi_res_set_irq,
404 acpi_res_set_drq,
405 acpi_res_set_start_dependant,
406 acpi_res_set_end_dependant
407 };
408
409 struct acpi_res_context {
410 int ar_nio;
411 int ar_nmem;
412 int ar_nirq;
413 int ar_ndrq;
414 };
415
416 static void
417 acpi_res_set_init(device_t dev, void **context)
418 {
419 struct acpi_res_context *cp;
420
421 if ((cp = AcpiOsAllocate(sizeof(*cp))) != NULL) {
422 bzero(cp, sizeof(*cp));
423 *context = cp;
424 }
425 }
426
427 static void
428 acpi_res_set_done(device_t dev, void *context)
429 {
430 struct acpi_res_context *cp = (struct acpi_res_context *)context;
431
432 if (cp == NULL)
433 return;
434 AcpiOsFree(cp);
435 }
436
437 static void
438 acpi_res_set_ioport(device_t dev, void *context, u_int32_t base,
439 u_int32_t length)
440 {
441 struct acpi_res_context *cp = (struct acpi_res_context *)context;
442
443 if (cp == NULL)
444 return;
445 bus_set_resource(dev, SYS_RES_IOPORT, cp->ar_nio++, base, length);
446 }
447
448 static void
449 acpi_res_set_iorange(device_t dev, void *context, u_int32_t low,
450 u_int32_t high, u_int32_t length, u_int32_t align)
451 {
452 struct acpi_res_context *cp = (struct acpi_res_context *)context;
453
454 if (cp == NULL)
455 return;
456 device_printf(dev, "I/O range not supported\n");
457 }
458
459 static void
460 acpi_res_set_memory(device_t dev, void *context, u_int32_t base,
461 u_int32_t length)
462 {
463 struct acpi_res_context *cp = (struct acpi_res_context *)context;
464
465 if (cp == NULL)
466 return;
467
468 bus_set_resource(dev, SYS_RES_MEMORY, cp->ar_nmem++, base, length);
469 }
470
471 static void
472 acpi_res_set_memoryrange(device_t dev, void *context, u_int32_t low,
473 u_int32_t high, u_int32_t length, u_int32_t align)
474 {
475 struct acpi_res_context *cp = (struct acpi_res_context *)context;
476
477 if (cp == NULL)
478 return;
479 device_printf(dev, "memory range not supported\n");
480 }
481
482 static void
483 acpi_res_set_irq(device_t dev, void *context, u_int32_t *irq, int count,
484 int trig, int pol)
485 {
486 struct acpi_res_context *cp = (struct acpi_res_context *)context;
487
488 if (cp == NULL || irq == NULL)
489 return;
490
491 /* This implements no resource relocation. */
492 if (count != 1)
493 return;
494
495 bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, *irq, 1);
496 BUS_CONFIG_INTR(dev, *irq, (trig == ACPI_EDGE_SENSITIVE) ?
497 INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL, (pol == ACPI_ACTIVE_HIGH) ?
498 INTR_POLARITY_HIGH : INTR_POLARITY_LOW);
499 }
500
501 static void
502 acpi_res_set_drq(device_t dev, void *context, u_int32_t *drq, int count)
503 {
504 struct acpi_res_context *cp = (struct acpi_res_context *)context;
505
506 if (cp == NULL || drq == NULL)
507 return;
508
509 /* This implements no resource relocation. */
510 if (count != 1)
511 return;
512
513 bus_set_resource(dev, SYS_RES_DRQ, cp->ar_ndrq++, *drq, 1);
514 }
515
516 static void
517 acpi_res_set_start_dependant(device_t dev, void *context, int preference)
518 {
519 struct acpi_res_context *cp = (struct acpi_res_context *)context;
520
521 if (cp == NULL)
522 return;
523 device_printf(dev, "dependant functions not supported\n");
524 }
525
526 static void
527 acpi_res_set_end_dependant(device_t dev, void *context)
528 {
529 struct acpi_res_context *cp = (struct acpi_res_context *)context;
530
531 if (cp == NULL)
532 return;
533 device_printf(dev, "dependant functions not supported\n");
534 }
535
536 /*
537 * Resource-owning placeholders.
538 *
539 * This code "owns" system resource objects that aren't
540 * otherwise useful to devices, and which shouldn't be
541 * considered "free".
542 *
543 * Note that some systems claim *all* of the physical address space
544 * with a PNP0C01 device, so we cannot correctly "own" system memory
545 * here (must be done in the SMAP handler on x86 systems, for
546 * example).
547 */
548
549 static int acpi_sysresource_probe(device_t dev);
550 static int acpi_sysresource_attach(device_t dev);
551
552 static device_method_t acpi_sysresource_methods[] = {
553 /* Device interface */
554 DEVMETHOD(device_probe, acpi_sysresource_probe),
555 DEVMETHOD(device_attach, acpi_sysresource_attach),
556
557 {0, 0}
558 };
559
560 static driver_t acpi_sysresource_driver = {
561 "acpi_sysresource",
562 acpi_sysresource_methods,
563 0,
564 };
565
566 static devclass_t acpi_sysresource_devclass;
567 DRIVER_MODULE(acpi_sysresource, acpi, acpi_sysresource_driver,
568 acpi_sysresource_devclass, 0, 0);
569
570 static int
571 acpi_sysresource_probe(device_t dev)
572 {
573 if (!acpi_disabled("sysresource") && acpi_MatchHid(dev, "PNP0C02"))
574 device_set_desc(dev, "System Resource");
575 else
576 return (ENXIO);
577
578 device_quiet(dev);
579 return (-100);
580 }
581
582 static int
583 acpi_sysresource_attach(device_t dev)
584 {
585 struct resource *res;
586 int i, rid;
587
588 /*
589 * Suck up all the resources that might have been assigned to us.
590 * Note that it's impossible to tell the difference between a
591 * resource that someone else has claimed, and one that doesn't
592 * exist.
593 */
594 for (i = 0; i < 100; i++) {
595 rid = i;
596 res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, 0);
597 rid = i;
598 res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, ~0, 1, 0);
599 rid = i;
600 res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
601 RF_SHAREABLE);
602 }
603
604 return (0);
605 }
Cache object: 5a310cc0565b2808068c18f64f1910b1
|