xref: /freebsd/sys/dev/acpica/acpi_resource.c (revision 3273b0052350a01f85ee60a6a2e31adb31d4a5a6)
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  *	$FreeBSD$
28  */
29 
30 #include "opt_acpi.h"
31 #include <sys/param.h>
32 #include <sys/kernel.h>
33 #include <sys/bus.h>
34 
35 #include <machine/bus.h>
36 #include <machine/resource.h>
37 #include <sys/rman.h>
38 
39 #include "acpi.h"
40 
41 #include <dev/acpica/acpivar.h>
42 
43 /*
44  * Hooks for the ACPI CA debugging infrastructure
45  */
46 #define _COMPONENT	ACPI_BUS
47 MODULE_NAME("RESOURCE")
48 
49 /*
50  * Fetch a device's resources and associate them with the device.
51  *
52  * Note that it might be nice to also locate ACPI-specific resource items, such
53  * as GPE bits.
54  *
55  * We really need to split the resource-fetching code out from the
56  * resource-parsing code, since we may want to use the parsing
57  * code for _PRS someday.
58  */
59 ACPI_STATUS
60 acpi_parse_resources(device_t dev, ACPI_HANDLE handle, struct acpi_parse_resource_set *set)
61 {
62     ACPI_BUFFER		buf;
63     ACPI_RESOURCE	*res;
64     char		*curr, *last;
65     ACPI_STATUS		status;
66     int			i;
67     void		*context;
68 
69     FUNCTION_TRACE(__func__);
70 
71     /*
72      * Special-case some devices that abuse _PRS/_CRS to mean
73      * something other than "I consume this resource".
74      *
75      * XXX do we really need this?  It's only relevant once
76      *     we start always-allocating these resources, and even
77      *     then, the only special-cased device is likely to be
78      *     the PCI interrupt link.
79      */
80 
81     /*
82      * Fetch the device's current resources.
83      */
84     if (((status = acpi_GetIntoBuffer(handle, AcpiGetCurrentResources, &buf)) != AE_OK)) {
85 	if (status != AE_NOT_FOUND)
86 	    printf("can't fetch resources for %s - %s\n",
87 		   acpi_name(handle), AcpiFormatException(status));
88 	return_ACPI_STATUS(status);
89     }
90     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s - got %d bytes of resources\n",
91 		      acpi_name(handle), buf.Length));
92     set->set_init(dev, &context);
93 
94     /*
95      * Iterate through the resources
96      */
97     curr = buf.Pointer;
98     last = (char *)buf.Pointer + buf.Length;
99     while (curr < last) {
100 	res = (ACPI_RESOURCE *)curr;
101 	curr += res->Length;
102 
103 	/*
104 	 * Handle the individual resource types
105 	 */
106 	switch(res->Id) {
107 	case ACPI_RSTYPE_END_TAG:
108 	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "EndTag\n"));
109 	    curr = last;
110 	    break;
111 
112 	case ACPI_RSTYPE_FIXED_IO:
113 	    if (res->Data.FixedIo.RangeLength <= 0)
114 		break;
115 	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedIo 0x%x/%d\n",
116 			      res->Data.FixedIo.BaseAddress,
117 			      res->Data.FixedIo.RangeLength));
118 	    set->set_ioport(dev, context,
119 			    res->Data.FixedIo.BaseAddress,
120 			    res->Data.FixedIo.RangeLength);
121 	    break;
122 
123 	case ACPI_RSTYPE_IO:
124 	    if (res->Data.Io.RangeLength <= 0)
125 		break;
126 	    if (res->Data.Io.MinBaseAddress == res->Data.Io.MaxBaseAddress) {
127 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x/%d\n",
128 				  res->Data.Io.MinBaseAddress,
129 				  res->Data.Io.RangeLength));
130 		set->set_ioport(dev, context,
131 				res->Data.Io.MinBaseAddress,
132 				res->Data.Io.RangeLength);
133 	    } else {
134 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x-0x%x/%d\n",
135 				  res->Data.Io.MinBaseAddress,
136 				  res->Data.Io.MaxBaseAddress,
137 				  res->Data.Io.RangeLength));
138 		set->set_iorange(dev, context,
139 				 res->Data.Io.MinBaseAddress,
140 				 res->Data.Io.MaxBaseAddress,
141 				 res->Data.Io.RangeLength, res->Data.Io.Alignment);
142 	    }
143 	    break;
144 
145 	case ACPI_RSTYPE_FIXED_MEM32:
146 	    if (res->Data.FixedMemory32.RangeLength <= 0)
147 		break;
148 	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedMemory32 0x%x/%d\n",
149 			      res->Data.FixedMemory32.RangeBaseAddress,
150 			      res->Data.FixedMemory32.RangeLength));
151 	    set->set_memory(dev, context, res->Data.FixedMemory32.RangeBaseAddress,
152 			    res->Data.FixedMemory32.RangeLength);
153 	    break;
154 
155 	case ACPI_RSTYPE_MEM32:
156 	    if (res->Data.Memory32.RangeLength <= 0)
157 		break;
158 	    if (res->Data.Memory32.MinBaseAddress == res->Data.Memory32.MaxBaseAddress) {
159 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x/%d\n",
160 				  res->Data.Memory32.MinBaseAddress,
161 				  res->Data.Memory32.RangeLength));
162 		set->set_memory(dev, context,
163 				res->Data.Memory32.MinBaseAddress,
164 				res->Data.Memory32.RangeLength);
165 	    } else {
166 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x-0x%x/%d\n",
167 				  res->Data.Memory32.MinBaseAddress,
168 				  res->Data.Memory32.MaxBaseAddress,
169 				  res->Data.Memory32.RangeLength));
170 		set->set_memoryrange(dev, context,
171 				     res->Data.Memory32.MinBaseAddress,
172 				     res->Data.Memory32.MaxBaseAddress,
173 				     res->Data.Memory32.RangeLength,
174 				     res->Data.Memory32.Alignment);
175 	    }
176 	    break;
177 
178 	case ACPI_RSTYPE_MEM24:
179 	    if (res->Data.Memory24.RangeLength <= 0)
180 		break;
181 	    if (res->Data.Memory24.MinBaseAddress == res->Data.Memory24.MaxBaseAddress) {
182 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x/%d\n",
183 				  res->Data.Memory24.MinBaseAddress,
184 				  res->Data.Memory24.RangeLength));
185 		set->set_memory(dev, context, res->Data.Memory24.MinBaseAddress,
186 				res->Data.Memory24.RangeLength);
187 	    } else {
188 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x-0x%x/%d\n",
189 				  res->Data.Memory24.MinBaseAddress,
190 				  res->Data.Memory24.MaxBaseAddress,
191 				  res->Data.Memory24.RangeLength));
192 		set->set_memoryrange(dev, context,
193 				     res->Data.Memory24.MinBaseAddress,
194 				     res->Data.Memory24.MaxBaseAddress,
195 				     res->Data.Memory24.RangeLength,
196 				     res->Data.Memory24.Alignment);
197 	    }
198 	    break;
199 
200 	case ACPI_RSTYPE_IRQ:
201 	    for (i = 0; i < res->Data.Irq.NumberOfInterrupts; i++) {
202 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Irq %d\n",
203 				  res->Data.Irq.Interrupts[i]));
204 		set->set_irq(dev, context,
205 			     res->Data.Irq.Interrupts[i]);
206 	    }
207 	    break;
208 
209 	case ACPI_RSTYPE_DMA:
210 	    for (i = 0; i < res->Data.Dma.NumberOfChannels; i++) {
211 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Drq %d\n",
212 				  res->Data.Dma.Channels[i]));
213 		set->set_drq(dev, context,
214 			     res->Data.Dma.Channels[i]);
215 	    }
216 	    break;
217 
218 	case ACPI_RSTYPE_START_DPF:
219 	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "start dependant functions\n"));
220 	    set->set_start_dependant(dev, context,
221 				     res->Data.StartDpf.CompatibilityPriority);
222 	    break;
223 
224 	case ACPI_RSTYPE_END_DPF:
225 	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "end dependant functions\n"));
226 	    set->set_end_dependant(dev, context);
227 	    break;
228 
229 	case ACPI_RSTYPE_ADDRESS32:
230 	    if (res->Data.Address32.AddressLength <= 0)
231 		break;
232 	    if (res->Data.Address32.ProducerConsumer != CONSUMER) {
233 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "ignored Address32 %s producer\n",
234 				  (res->Data.Address32.ResourceType == IO_RANGE) ?
235 				     "IO" : "Memory"));
236 		break;
237 	    }
238 	    if ((res->Data.Address32.ResourceType != MEMORY_RANGE) ||
239 		(res->Data.Address32.ResourceType != IO_RANGE)) {
240 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
241 				  "ignored Address32 for non-memory, non-I/O\n"));
242 		break;
243 	    }
244 
245 	    if ((res->Data.Address32.MinAddressFixed == ADDRESS_FIXED) &&
246 		(res->Data.Address32.MaxAddressFixed == ADDRESS_FIXED)) {
247 		if (res->Data.Address32.ResourceType == MEMORY_RANGE) {
248 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address32/Memory 0x%x/%d\n",
249 				      res->Data.Address32.MinAddressRange,
250 				      res->Data.Address32.AddressLength));
251 		    set->set_memory(dev, context,
252 				    res->Data.Address32.MinAddressRange,
253 				    res->Data.Address32.AddressLength);
254 		} else {
255 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address32/IO 0x%x/%d\n",
256 				      res->Data.Address32.MinAddressRange,
257 				      res->Data.Address32.AddressLength));
258 		    set->set_ioport(dev, context,
259 				    res->Data.Address32.MinAddressRange,
260 				    res->Data.Address32.AddressLength);
261 		}
262 	    } else {
263 		if (res->Data.Address32.ResourceType == MEMORY_RANGE) {
264 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address32/Memory 0x%x-0x%x/%d\n",
265 				      res->Data.Address32.MinAddressRange,
266 				      res->Data.Address32.MaxAddressRange,
267 				      res->Data.Address32.AddressLength));
268 		    set->set_memoryrange(dev, context,
269 					  res->Data.Address32.MinAddressRange,
270 					  res->Data.Address32.MaxAddressRange,
271 					  res->Data.Address32.AddressLength,
272 					  res->Data.Address32.Granularity);
273 		} else {
274 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address32/IO 0x%x-0x%x/%d\n",
275 				      res->Data.Address32.MinAddressRange,
276 				      res->Data.Address32.MaxAddressRange,
277 				      res->Data.Address32.AddressLength));
278 		    set->set_iorange(dev, context,
279 				     res->Data.Address32.MinAddressRange,
280 				     res->Data.Address32.MaxAddressRange,
281 				     res->Data.Address32.AddressLength,
282 				     res->Data.Address32.Granularity);
283 		}
284 	    }
285 	    break;
286 
287 	case ACPI_RSTYPE_ADDRESS16:
288 	    if (res->Data.Address16.AddressLength <= 0)
289 		break;
290 	    if (res->Data.Address16.ProducerConsumer != CONSUMER) {
291 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "ignored Address16 %s producer\n",
292 				  (res->Data.Address16.ResourceType == IO_RANGE) ?
293 				     "IO" : "Memory"));
294 		break;
295 	    }
296 	    if ((res->Data.Address16.ResourceType != MEMORY_RANGE) ||
297 		(res->Data.Address16.ResourceType != IO_RANGE)) {
298 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
299 				  "ignored Address16 for non-memory, non-I/O\n"));
300 		break;
301 	    }
302 
303 	    if ((res->Data.Address16.MinAddressFixed == ADDRESS_FIXED) &&
304 		(res->Data.Address16.MaxAddressFixed == ADDRESS_FIXED)) {
305 		if (res->Data.Address16.ResourceType == MEMORY_RANGE) {
306 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "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, "Address16/IO 0x%x/%d\n",
314 				      res->Data.Address16.MinAddressRange,
315 				      res->Data.Address16.AddressLength));
316 		    set->set_ioport(dev, context,
317 				    res->Data.Address16.MinAddressRange,
318 				    res->Data.Address16.AddressLength);
319 		}
320 	    } else {
321 		if (res->Data.Address16.ResourceType == MEMORY_RANGE) {
322 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address16/Memory 0x%x-0x%x/%d\n",
323 				      res->Data.Address16.MinAddressRange,
324 				      res->Data.Address16.MaxAddressRange,
325 				      res->Data.Address16.AddressLength));
326 		    set->set_memoryrange(dev, context,
327 					  res->Data.Address16.MinAddressRange,
328 					  res->Data.Address16.MaxAddressRange,
329 					  res->Data.Address16.AddressLength,
330 					  res->Data.Address16.Granularity);
331 		} else {
332 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address16/IO 0x%x-0x%x/%d\n",
333 				      res->Data.Address16.MinAddressRange,
334 				      res->Data.Address16.MaxAddressRange,
335 				      res->Data.Address16.AddressLength));
336 		    set->set_iorange(dev, context,
337 				     res->Data.Address16.MinAddressRange,
338 				     res->Data.Address16.MaxAddressRange,
339 				     res->Data.Address16.AddressLength,
340 				     res->Data.Address16.Granularity);
341 		}
342 	    }
343 	    break;
344 
345 	case ACPI_RSTYPE_ADDRESS64:
346 	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "unimplemented Address64 resource\n"));
347 	    break;
348 
349 	case ACPI_RSTYPE_EXT_IRQ:
350 	    /* XXX special handling? */
351 	    for (i = 0; i < res->Data.ExtendedIrq.NumberOfInterrupts; i++) {
352 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "ExtIrq %d\n",
353 				  res->Data.ExtendedIrq.Interrupts[i]));
354 		set->set_irq(dev, context,
355 			     res->Data.ExtendedIrq.Interrupts[i]);
356 	    }
357 	    break;
358 
359 	case ACPI_RSTYPE_VENDOR:
360 	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "unimplemented VendorSpecific resource\n"));
361 	    break;
362 	default:
363 	    break;
364 	}
365     }
366     AcpiOsFree(buf.Pointer);
367     set->set_done(dev, context);
368     return_ACPI_STATUS(AE_OK);
369 }
370 
371 /*
372  * Resource-set vectors used to attach _CRS-derived resources
373  * to an ACPI device.
374  */
375 static void	acpi_res_set_init(device_t dev, void **context);
376 static void	acpi_res_set_done(device_t dev, void *context);
377 static void	acpi_res_set_ioport(device_t dev, void *context, u_int32_t base, u_int32_t length);
378 static void	acpi_res_set_iorange(device_t dev, void *context, u_int32_t low, u_int32_t high,
379 				     u_int32_t length, u_int32_t align);
380 static void	acpi_res_set_memory(device_t dev, void *context, u_int32_t base, u_int32_t length);
381 static void	acpi_res_set_memoryrange(device_t dev, void *context, u_int32_t low, u_int32_t high,
382 					 u_int32_t length, u_int32_t align);
383 static void	acpi_res_set_irq(device_t dev, void *context, u_int32_t irq);
384 static void	acpi_res_set_drq(device_t dev, void *context, u_int32_t drq);
385 static void	acpi_res_set_start_dependant(device_t dev, void *context, int preference);
386 static void	acpi_res_set_end_dependant(device_t dev, void *context);
387 
388 struct acpi_parse_resource_set acpi_res_parse_set = {
389     acpi_res_set_init,
390     acpi_res_set_done,
391     acpi_res_set_ioport,
392     acpi_res_set_iorange,
393     acpi_res_set_memory,
394     acpi_res_set_memoryrange,
395     acpi_res_set_irq,
396     acpi_res_set_drq,
397     acpi_res_set_start_dependant,
398     acpi_res_set_end_dependant
399 };
400 
401 struct acpi_res_context {
402     int		ar_nio;
403     int		ar_nmem;
404     int		ar_nirq;
405     int		ar_ndrq;
406 };
407 
408 static void
409 acpi_res_set_init(device_t dev, void **context)
410 {
411     struct acpi_res_context	*cp;
412 
413     if ((cp = AcpiOsAllocate(sizeof(*cp))) != NULL) {
414 	bzero(cp, sizeof(*cp));
415 	*context = cp;
416     }
417 }
418 
419 static void
420 acpi_res_set_done(device_t dev, void *context)
421 {
422     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
423 
424     if (cp == NULL)
425 	return;
426     AcpiOsFree(cp);
427 }
428 
429 static void
430 acpi_res_set_ioport(device_t dev, void *context, u_int32_t base, u_int32_t length)
431 {
432     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
433 
434     if (cp == NULL)
435 	return;
436     bus_set_resource(dev, SYS_RES_IOPORT, cp->ar_nio++, base, length);
437 }
438 
439 static void
440 acpi_res_set_iorange(device_t dev, void *context, u_int32_t low, u_int32_t high, u_int32_t length, u_int32_t align)
441 {
442     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
443 
444     if (cp == NULL)
445 	return;
446     device_printf(dev, "I/O range not supported\n");
447 }
448 
449 static void
450 acpi_res_set_memory(device_t dev, void *context, u_int32_t base, u_int32_t length)
451 {
452     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
453 
454     if (cp == NULL)
455 	return;
456     bus_set_resource(dev, SYS_RES_MEMORY, cp->ar_nmem++, base, length);
457 }
458 
459 static void
460 acpi_res_set_memoryrange(device_t dev, void *context, u_int32_t low, u_int32_t high, u_int32_t length, u_int32_t align)
461 {
462     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
463 
464     if (cp == NULL)
465 	return;
466     device_printf(dev, "memory range not supported\n");
467 }
468 
469 static void
470 acpi_res_set_irq(device_t dev, void *context, u_int32_t irq)
471 {
472     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
473 
474     if (cp == NULL)
475 	return;
476     bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, irq, 1);
477 }
478 
479 static void
480 acpi_res_set_drq(device_t dev, void *context, u_int32_t drq)
481 {
482     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
483 
484     if (cp == NULL)
485 	return;
486     bus_set_resource(dev, SYS_RES_DRQ, cp->ar_ndrq++, drq, 1);
487 }
488 
489 static void
490 acpi_res_set_start_dependant(device_t dev, void *context, int preference)
491 {
492     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
493 
494     if (cp == NULL)
495 	return;
496     device_printf(dev, "dependant functions not supported\n");
497 }
498 
499 static void
500 acpi_res_set_end_dependant(device_t dev, void *context)
501 {
502     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
503 
504     if (cp == NULL)
505 	return;
506 }
507 
508 /*
509  * Resource-owning placeholders.
510  *
511  * This code "owns" system resource objects that aren't
512  * otherwise useful to devices, and which shouldn't be
513  * considered "free".
514  *
515  * Note that some systems claim *all* of the physical address space
516  * with a PNP0C01 device, so we cannot correctly "own" system memory
517  * here (must be done in the SMAP handler on x86 systems, for
518  * example).
519  */
520 
521 static int	acpi_sysresource_probe(device_t dev);
522 static int	acpi_sysresource_attach(device_t dev);
523 
524 static device_method_t acpi_sysresource_methods[] = {
525     /* Device interface */
526     DEVMETHOD(device_probe,	acpi_sysresource_probe),
527     DEVMETHOD(device_attach,	acpi_sysresource_attach),
528 
529     {0, 0}
530 };
531 
532 static driver_t acpi_sysresource_driver = {
533     "acpi_sysresource",
534     acpi_sysresource_methods,
535     0,
536 };
537 
538 static devclass_t acpi_sysresource_devclass;
539 DRIVER_MODULE(acpi_sysresource, acpi, acpi_sysresource_driver, acpi_sysresource_devclass, 0, 0);
540 
541 static int
542 acpi_sysresource_probe(device_t dev)
543 {
544     if (acpi_disabled("sysresource"))
545 	return(ENXIO);
546     if (acpi_MatchHid(dev, "PNP0C02")) {
547 	device_set_desc(dev, "system resource");
548     } else {
549 	return(ENXIO);
550     }
551     device_quiet(dev);
552     return(-100);
553 }
554 
555 static int
556 acpi_sysresource_attach(device_t dev)
557 {
558     struct resource	*res;
559     int			i, rid;
560 
561     /*
562      * Suck up all the resources that might have been assigned to us.
563      * Note that it's impossible to tell the difference between a
564      * resource that someone else has claimed, and one that doesn't
565      * exist.
566      */
567     for (i = 0; i < 100; i++) {
568 	rid = i;
569 	res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, 0);
570 	rid = i;
571 	res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, ~0, 1, 0);
572 	rid = i;
573 	res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_SHAREABLE);
574     }
575     return(0);
576 }
577