xref: /freebsd/sys/dev/acpica/acpi_resource.c (revision eacee0ff7ec955b32e09515246bd97b6edcd2b0f)
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     void		*context;
67 
68     FUNCTION_TRACE(__func__);
69 
70     /*
71      * Special-case some devices that abuse _PRS/_CRS to mean
72      * something other than "I consume this resource".
73      *
74      * XXX do we really need this?  It's only relevant once
75      *     we start always-allocating these resources, and even
76      *     then, the only special-cased device is likely to be
77      *     the PCI interrupt link.
78      */
79 
80     /*
81      * Fetch the device's current resources.
82      */
83     if (((status = acpi_GetIntoBuffer(handle, AcpiGetCurrentResources, &buf)) != AE_OK)) {
84 	if (status != AE_NOT_FOUND)
85 	    printf("can't fetch resources for %s - %s\n",
86 		   acpi_name(handle), AcpiFormatException(status));
87 	return_ACPI_STATUS(status);
88     }
89     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s - got %d bytes of resources\n",
90 		      acpi_name(handle), buf.Length));
91     set->set_init(dev, &context);
92 
93     /*
94      * Iterate through the resources
95      */
96     curr = buf.Pointer;
97     last = (char *)buf.Pointer + buf.Length;
98     while (curr < last) {
99 	res = (ACPI_RESOURCE *)curr;
100 	curr += res->Length;
101 
102 	/*
103 	 * Handle the individual resource types
104 	 */
105 	switch(res->Id) {
106 	case ACPI_RSTYPE_END_TAG:
107 	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "EndTag\n"));
108 	    curr = last;
109 	    break;
110 
111 	case ACPI_RSTYPE_FIXED_IO:
112 	    if (res->Data.FixedIo.RangeLength <= 0)
113 		break;
114 	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedIo 0x%x/%d\n",
115 			      res->Data.FixedIo.BaseAddress,
116 			      res->Data.FixedIo.RangeLength));
117 	    set->set_ioport(dev, context,
118 			    res->Data.FixedIo.BaseAddress,
119 			    res->Data.FixedIo.RangeLength);
120 	    break;
121 
122 	case ACPI_RSTYPE_IO:
123 	    if (res->Data.Io.RangeLength <= 0)
124 		break;
125 	    if (res->Data.Io.MinBaseAddress == res->Data.Io.MaxBaseAddress) {
126 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x/%d\n",
127 				  res->Data.Io.MinBaseAddress,
128 				  res->Data.Io.RangeLength));
129 		set->set_ioport(dev, context,
130 				res->Data.Io.MinBaseAddress,
131 				res->Data.Io.RangeLength);
132 	    } else {
133 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x-0x%x/%d\n",
134 				  res->Data.Io.MinBaseAddress,
135 				  res->Data.Io.MaxBaseAddress,
136 				  res->Data.Io.RangeLength));
137 		set->set_iorange(dev, context,
138 				 res->Data.Io.MinBaseAddress,
139 				 res->Data.Io.MaxBaseAddress,
140 				 res->Data.Io.RangeLength, res->Data.Io.Alignment);
141 	    }
142 	    break;
143 
144 	case ACPI_RSTYPE_FIXED_MEM32:
145 	    if (res->Data.FixedMemory32.RangeLength <= 0)
146 		break;
147 	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedMemory32 0x%x/%d\n",
148 			      res->Data.FixedMemory32.RangeBaseAddress,
149 			      res->Data.FixedMemory32.RangeLength));
150 	    set->set_memory(dev, context, res->Data.FixedMemory32.RangeBaseAddress,
151 			    res->Data.FixedMemory32.RangeLength);
152 	    break;
153 
154 	case ACPI_RSTYPE_MEM32:
155 	    if (res->Data.Memory32.RangeLength <= 0)
156 		break;
157 	    if (res->Data.Memory32.MinBaseAddress == res->Data.Memory32.MaxBaseAddress) {
158 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x/%d\n",
159 				  res->Data.Memory32.MinBaseAddress,
160 				  res->Data.Memory32.RangeLength));
161 		set->set_memory(dev, context,
162 				res->Data.Memory32.MinBaseAddress,
163 				res->Data.Memory32.RangeLength);
164 	    } else {
165 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x-0x%x/%d\n",
166 				  res->Data.Memory32.MinBaseAddress,
167 				  res->Data.Memory32.MaxBaseAddress,
168 				  res->Data.Memory32.RangeLength));
169 		set->set_memoryrange(dev, context,
170 				     res->Data.Memory32.MinBaseAddress,
171 				     res->Data.Memory32.MaxBaseAddress,
172 				     res->Data.Memory32.RangeLength,
173 				     res->Data.Memory32.Alignment);
174 	    }
175 	    break;
176 
177 	case ACPI_RSTYPE_MEM24:
178 	    if (res->Data.Memory24.RangeLength <= 0)
179 		break;
180 	    if (res->Data.Memory24.MinBaseAddress == res->Data.Memory24.MaxBaseAddress) {
181 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x/%d\n",
182 				  res->Data.Memory24.MinBaseAddress,
183 				  res->Data.Memory24.RangeLength));
184 		set->set_memory(dev, context, res->Data.Memory24.MinBaseAddress,
185 				res->Data.Memory24.RangeLength);
186 	    } else {
187 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x-0x%x/%d\n",
188 				  res->Data.Memory24.MinBaseAddress,
189 				  res->Data.Memory24.MaxBaseAddress,
190 				  res->Data.Memory24.RangeLength));
191 		set->set_memoryrange(dev, context,
192 				     res->Data.Memory24.MinBaseAddress,
193 				     res->Data.Memory24.MaxBaseAddress,
194 				     res->Data.Memory24.RangeLength,
195 				     res->Data.Memory24.Alignment);
196 	    }
197 	    break;
198 
199 	case ACPI_RSTYPE_IRQ:
200 	    /*
201 	     * from 1.0b 6.4.2
202 	     * "This structure is repeated for each separate interrupt
203 	     * required"
204 	     */
205 	    set->set_irq(dev, context, res->Data.Irq.Interrupts,
206 			 res->Data.Irq.NumberOfInterrupts);
207 	    break;
208 
209 	case ACPI_RSTYPE_DMA:
210 	    /*
211 	     * from 1.0b 6.4.3
212 	     * "This structure is repeated for each separate dma channel
213 	     * required"
214 	     */
215 
216 	    set->set_drq(dev, context, res->Data.Dma.Channels,
217 			 res->Data.Dma.NumberOfChannels);
218 	    break;
219 
220 	case ACPI_RSTYPE_START_DPF:
221 	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "start dependant functions\n"));
222 	    set->set_start_dependant(dev, context,
223 				     res->Data.StartDpf.CompatibilityPriority);
224 	    break;
225 
226 	case ACPI_RSTYPE_END_DPF:
227 	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "end dependant functions\n"));
228 	    set->set_end_dependant(dev, context);
229 	    break;
230 
231 	case ACPI_RSTYPE_ADDRESS32:
232 	    if (res->Data.Address32.AddressLength <= 0)
233 		break;
234 	    if (res->Data.Address32.ProducerConsumer != CONSUMER) {
235 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "ignored Address32 %s producer\n",
236 				  (res->Data.Address32.ResourceType == IO_RANGE) ?
237 				     "IO" : "Memory"));
238 		break;
239 	    }
240 	    if ((res->Data.Address32.ResourceType != MEMORY_RANGE) ||
241 		(res->Data.Address32.ResourceType != IO_RANGE)) {
242 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
243 				  "ignored Address32 for non-memory, non-I/O\n"));
244 		break;
245 	    }
246 
247 	    if ((res->Data.Address32.MinAddressFixed == ADDRESS_FIXED) &&
248 		(res->Data.Address32.MaxAddressFixed == ADDRESS_FIXED)) {
249 		if (res->Data.Address32.ResourceType == MEMORY_RANGE) {
250 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address32/Memory 0x%x/%d\n",
251 				      res->Data.Address32.MinAddressRange,
252 				      res->Data.Address32.AddressLength));
253 		    set->set_memory(dev, context,
254 				    res->Data.Address32.MinAddressRange,
255 				    res->Data.Address32.AddressLength);
256 		} else {
257 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address32/IO 0x%x/%d\n",
258 				      res->Data.Address32.MinAddressRange,
259 				      res->Data.Address32.AddressLength));
260 		    set->set_ioport(dev, context,
261 				    res->Data.Address32.MinAddressRange,
262 				    res->Data.Address32.AddressLength);
263 		}
264 	    } else {
265 		if (res->Data.Address32.ResourceType == MEMORY_RANGE) {
266 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address32/Memory 0x%x-0x%x/%d\n",
267 				      res->Data.Address32.MinAddressRange,
268 				      res->Data.Address32.MaxAddressRange,
269 				      res->Data.Address32.AddressLength));
270 		    set->set_memoryrange(dev, context,
271 					  res->Data.Address32.MinAddressRange,
272 					  res->Data.Address32.MaxAddressRange,
273 					  res->Data.Address32.AddressLength,
274 					  res->Data.Address32.Granularity);
275 		} else {
276 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address32/IO 0x%x-0x%x/%d\n",
277 				      res->Data.Address32.MinAddressRange,
278 				      res->Data.Address32.MaxAddressRange,
279 				      res->Data.Address32.AddressLength));
280 		    set->set_iorange(dev, context,
281 				     res->Data.Address32.MinAddressRange,
282 				     res->Data.Address32.MaxAddressRange,
283 				     res->Data.Address32.AddressLength,
284 				     res->Data.Address32.Granularity);
285 		}
286 	    }
287 	    break;
288 
289 	case ACPI_RSTYPE_ADDRESS16:
290 	    if (res->Data.Address16.AddressLength <= 0)
291 		break;
292 	    if (res->Data.Address16.ProducerConsumer != CONSUMER) {
293 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "ignored Address16 %s producer\n",
294 				  (res->Data.Address16.ResourceType == IO_RANGE) ?
295 				     "IO" : "Memory"));
296 		break;
297 	    }
298 	    if ((res->Data.Address16.ResourceType != MEMORY_RANGE) ||
299 		(res->Data.Address16.ResourceType != IO_RANGE)) {
300 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
301 				  "ignored Address16 for non-memory, non-I/O\n"));
302 		break;
303 	    }
304 
305 	    if ((res->Data.Address16.MinAddressFixed == ADDRESS_FIXED) &&
306 		(res->Data.Address16.MaxAddressFixed == ADDRESS_FIXED)) {
307 		if (res->Data.Address16.ResourceType == MEMORY_RANGE) {
308 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address16/Memory 0x%x/%d\n",
309 				      res->Data.Address16.MinAddressRange,
310 				      res->Data.Address16.AddressLength));
311 		    set->set_memory(dev, context,
312 				    res->Data.Address16.MinAddressRange,
313 				    res->Data.Address16.AddressLength);
314 		} else {
315 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address16/IO 0x%x/%d\n",
316 				      res->Data.Address16.MinAddressRange,
317 				      res->Data.Address16.AddressLength));
318 		    set->set_ioport(dev, context,
319 				    res->Data.Address16.MinAddressRange,
320 				    res->Data.Address16.AddressLength);
321 		}
322 	    } else {
323 		if (res->Data.Address16.ResourceType == MEMORY_RANGE) {
324 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "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, "Address16/IO 0x%x-0x%x/%d\n",
335 				      res->Data.Address16.MinAddressRange,
336 				      res->Data.Address16.MaxAddressRange,
337 				      res->Data.Address16.AddressLength));
338 		    set->set_iorange(dev, context,
339 				     res->Data.Address16.MinAddressRange,
340 				     res->Data.Address16.MaxAddressRange,
341 				     res->Data.Address16.AddressLength,
342 				     res->Data.Address16.Granularity);
343 		}
344 	    }
345 	    break;
346 
347 	case ACPI_RSTYPE_ADDRESS64:
348 	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "unimplemented Address64 resource\n"));
349 	    break;
350 
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 	    break;
356 
357 	case ACPI_RSTYPE_VENDOR:
358 	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "unimplemented VendorSpecific resource\n"));
359 	    break;
360 	default:
361 	    break;
362 	}
363     }
364     AcpiOsFree(buf.Pointer);
365     set->set_done(dev, context);
366     return_ACPI_STATUS(AE_OK);
367 }
368 
369 /*
370  * Resource-set vectors used to attach _CRS-derived resources
371  * to an ACPI device.
372  */
373 static void	acpi_res_set_init(device_t dev, void **context);
374 static void	acpi_res_set_done(device_t dev, void *context);
375 static void	acpi_res_set_ioport(device_t dev, void *context, u_int32_t base, u_int32_t length);
376 static void	acpi_res_set_iorange(device_t dev, void *context, u_int32_t low, u_int32_t high,
377 				     u_int32_t length, u_int32_t align);
378 static void	acpi_res_set_memory(device_t dev, void *context, u_int32_t base, u_int32_t length);
379 static void	acpi_res_set_memoryrange(device_t dev, void *context, u_int32_t low, u_int32_t high,
380 					 u_int32_t length, u_int32_t align);
381 static void	acpi_res_set_irq(device_t dev, void *context, u_int32_t *irq,
382 				 int count);
383 static void	acpi_res_set_drq(device_t dev, void *context, u_int32_t *drq,
384 				 int count);
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 
457     bus_set_resource(dev, SYS_RES_MEMORY, cp->ar_nmem++, base, length);
458 }
459 
460 static void
461 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)
462 {
463     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
464 
465     if (cp == NULL)
466 	return;
467     device_printf(dev, "memory range not supported\n");
468 }
469 
470 static void
471 acpi_res_set_irq(device_t dev, void *context, u_int32_t *irq, int count)
472 {
473     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
474 
475     if (cp == NULL)
476 	return;
477     if (irq == NULL)
478 	return;
479 
480     /*This implements no resource relocation.*/
481     if(count != 1)
482 	return;
483 
484     bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, *irq, 1);
485 }
486 
487 static void
488 acpi_res_set_drq(device_t dev, void *context, u_int32_t *drq, int count)
489 {
490     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
491 
492     if (cp == NULL)
493 	return;
494     if (drq == NULL)
495 	return;
496 
497     /*This implements no resource relocation.*/
498     if(count != 1)
499 	return;
500 
501     bus_set_resource(dev, SYS_RES_DRQ, cp->ar_ndrq++, *drq, 1);
502 }
503 
504 static void
505 acpi_res_set_start_dependant(device_t dev, void *context, int preference)
506 {
507     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
508 
509     if (cp == NULL)
510 	return;
511     device_printf(dev, "dependant functions not supported\n");
512 }
513 
514 static void
515 acpi_res_set_end_dependant(device_t dev, void *context)
516 {
517     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
518 
519     if (cp == NULL)
520 	return;
521 }
522 
523 /*
524  * Resource-owning placeholders.
525  *
526  * This code "owns" system resource objects that aren't
527  * otherwise useful to devices, and which shouldn't be
528  * considered "free".
529  *
530  * Note that some systems claim *all* of the physical address space
531  * with a PNP0C01 device, so we cannot correctly "own" system memory
532  * here (must be done in the SMAP handler on x86 systems, for
533  * example).
534  */
535 
536 static int	acpi_sysresource_probe(device_t dev);
537 static int	acpi_sysresource_attach(device_t dev);
538 
539 static device_method_t acpi_sysresource_methods[] = {
540     /* Device interface */
541     DEVMETHOD(device_probe,	acpi_sysresource_probe),
542     DEVMETHOD(device_attach,	acpi_sysresource_attach),
543 
544     {0, 0}
545 };
546 
547 static driver_t acpi_sysresource_driver = {
548     "acpi_sysresource",
549     acpi_sysresource_methods,
550     0,
551 };
552 
553 static devclass_t acpi_sysresource_devclass;
554 DRIVER_MODULE(acpi_sysresource, acpi, acpi_sysresource_driver, acpi_sysresource_devclass, 0, 0);
555 
556 static int
557 acpi_sysresource_probe(device_t dev)
558 {
559     if (acpi_disabled("sysresource"))
560 	return(ENXIO);
561     if (acpi_MatchHid(dev, "PNP0C02")) {
562 	device_set_desc(dev, "system resource");
563     } else {
564 	return(ENXIO);
565     }
566     device_quiet(dev);
567     return(-100);
568 }
569 
570 static int
571 acpi_sysresource_attach(device_t dev)
572 {
573     struct resource	*res;
574     int			i, rid;
575 
576     /*
577      * Suck up all the resources that might have been assigned to us.
578      * Note that it's impossible to tell the difference between a
579      * resource that someone else has claimed, and one that doesn't
580      * exist.
581      */
582     for (i = 0; i < 100; i++) {
583 	rid = i;
584 	res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, 0);
585 	rid = i;
586 	res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, ~0, 1, 0);
587 	rid = i;
588 	res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_SHAREABLE);
589     }
590     return(0);
591 }
592