xref: /freebsd/sys/dev/acpica/acpi_resource.c (revision ee2ea5ceafed78a5bd9810beb9e3ca927180c226)
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 ACPI_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     ACPI_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     buf.Length = ACPI_ALLOCATE_BUFFER;
84     if (ACPI_FAILURE((status = AcpiGetCurrentResources(handle, &buf)))) {
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 	    /*
202 	     * from 1.0b 6.4.2
203 	     * "This structure is repeated for each separate interrupt
204 	     * required"
205 	     */
206 	    set->set_irq(dev, context, res->Data.Irq.Interrupts,
207 			 res->Data.Irq.NumberOfInterrupts);
208 	    break;
209 
210 	case ACPI_RSTYPE_DMA:
211 	    /*
212 	     * from 1.0b 6.4.3
213 	     * "This structure is repeated for each separate dma channel
214 	     * required"
215 	     */
216 
217 	    set->set_drq(dev, context, res->Data.Dma.Channels,
218 			 res->Data.Dma.NumberOfChannels);
219 	    break;
220 
221 	case ACPI_RSTYPE_START_DPF:
222 	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "start dependant functions\n"));
223 	    set->set_start_dependant(dev, context,
224 				     res->Data.StartDpf.CompatibilityPriority);
225 	    break;
226 
227 	case ACPI_RSTYPE_END_DPF:
228 	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "end dependant functions\n"));
229 	    set->set_end_dependant(dev, context);
230 	    break;
231 
232 	case ACPI_RSTYPE_ADDRESS32:
233 	    if (res->Data.Address32.AddressLength <= 0)
234 		break;
235 	    if (res->Data.Address32.ProducerConsumer != ACPI_CONSUMER) {
236 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "ignored Address32 %s producer\n",
237 				  (res->Data.Address32.ResourceType == ACPI_IO_RANGE) ?
238 				     "IO" : "Memory"));
239 		break;
240 	    }
241 	    if ((res->Data.Address32.ResourceType != ACPI_MEMORY_RANGE) ||
242 		(res->Data.Address32.ResourceType != ACPI_IO_RANGE)) {
243 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
244 				  "ignored Address32 for non-memory, non-I/O\n"));
245 		break;
246 	    }
247 
248 	    if ((res->Data.Address32.MinAddressFixed == ACPI_ADDRESS_FIXED) &&
249 		(res->Data.Address32.MaxAddressFixed == ACPI_ADDRESS_FIXED)) {
250 		if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) {
251 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address32/Memory 0x%x/%d\n",
252 				      res->Data.Address32.MinAddressRange,
253 				      res->Data.Address32.AddressLength));
254 		    set->set_memory(dev, context,
255 				    res->Data.Address32.MinAddressRange,
256 				    res->Data.Address32.AddressLength);
257 		} else {
258 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address32/IO 0x%x/%d\n",
259 				      res->Data.Address32.MinAddressRange,
260 				      res->Data.Address32.AddressLength));
261 		    set->set_ioport(dev, context,
262 				    res->Data.Address32.MinAddressRange,
263 				    res->Data.Address32.AddressLength);
264 		}
265 	    } else {
266 		if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) {
267 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address32/Memory 0x%x-0x%x/%d\n",
268 				      res->Data.Address32.MinAddressRange,
269 				      res->Data.Address32.MaxAddressRange,
270 				      res->Data.Address32.AddressLength));
271 		    set->set_memoryrange(dev, context,
272 					  res->Data.Address32.MinAddressRange,
273 					  res->Data.Address32.MaxAddressRange,
274 					  res->Data.Address32.AddressLength,
275 					  res->Data.Address32.Granularity);
276 		} else {
277 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address32/IO 0x%x-0x%x/%d\n",
278 				      res->Data.Address32.MinAddressRange,
279 				      res->Data.Address32.MaxAddressRange,
280 				      res->Data.Address32.AddressLength));
281 		    set->set_iorange(dev, context,
282 				     res->Data.Address32.MinAddressRange,
283 				     res->Data.Address32.MaxAddressRange,
284 				     res->Data.Address32.AddressLength,
285 				     res->Data.Address32.Granularity);
286 		}
287 	    }
288 	    break;
289 
290 	case ACPI_RSTYPE_ADDRESS16:
291 	    if (res->Data.Address16.AddressLength <= 0)
292 		break;
293 	    if (res->Data.Address16.ProducerConsumer != ACPI_CONSUMER) {
294 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "ignored Address16 %s producer\n",
295 				  (res->Data.Address16.ResourceType == ACPI_IO_RANGE) ?
296 				     "IO" : "Memory"));
297 		break;
298 	    }
299 	    if ((res->Data.Address16.ResourceType != ACPI_MEMORY_RANGE) ||
300 		(res->Data.Address16.ResourceType != ACPI_IO_RANGE)) {
301 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
302 				  "ignored Address16 for non-memory, non-I/O\n"));
303 		break;
304 	    }
305 
306 	    if ((res->Data.Address16.MinAddressFixed == ACPI_ADDRESS_FIXED) &&
307 		(res->Data.Address16.MaxAddressFixed == ACPI_ADDRESS_FIXED)) {
308 		if (res->Data.Address16.ResourceType == ACPI_MEMORY_RANGE) {
309 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address16/Memory 0x%x/%d\n",
310 				      res->Data.Address16.MinAddressRange,
311 				      res->Data.Address16.AddressLength));
312 		    set->set_memory(dev, context,
313 				    res->Data.Address16.MinAddressRange,
314 				    res->Data.Address16.AddressLength);
315 		} else {
316 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address16/IO 0x%x/%d\n",
317 				      res->Data.Address16.MinAddressRange,
318 				      res->Data.Address16.AddressLength));
319 		    set->set_ioport(dev, context,
320 				    res->Data.Address16.MinAddressRange,
321 				    res->Data.Address16.AddressLength);
322 		}
323 	    } else {
324 		if (res->Data.Address16.ResourceType == ACPI_MEMORY_RANGE) {
325 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Address16/Memory 0x%x-0x%x/%d\n",
326 				      res->Data.Address16.MinAddressRange,
327 				      res->Data.Address16.MaxAddressRange,
328 				      res->Data.Address16.AddressLength));
329 		    set->set_memoryrange(dev, context,
330 					  res->Data.Address16.MinAddressRange,
331 					  res->Data.Address16.MaxAddressRange,
332 					  res->Data.Address16.AddressLength,
333 					  res->Data.Address16.Granularity);
334 		} else {
335 		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "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 
348 	case ACPI_RSTYPE_ADDRESS64:
349 	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "unimplemented Address64 resource\n"));
350 	    break;
351 
352 	case ACPI_RSTYPE_EXT_IRQ:
353 	    /* XXX special handling? */
354 	    set->set_irq(dev, context,res->Data.ExtendedIrq.Interrupts,
355 			 res->Data.ExtendedIrq.NumberOfInterrupts);
356 	    break;
357 
358 	case ACPI_RSTYPE_VENDOR:
359 	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "unimplemented VendorSpecific resource\n"));
360 	    break;
361 	default:
362 	    break;
363 	}
364     }
365     AcpiOsFree(buf.Pointer);
366     set->set_done(dev, context);
367     return_ACPI_STATUS(AE_OK);
368 }
369 
370 /*
371  * Resource-set vectors used to attach _CRS-derived resources
372  * to an ACPI device.
373  */
374 static void	acpi_res_set_init(device_t dev, void **context);
375 static void	acpi_res_set_done(device_t dev, void *context);
376 static void	acpi_res_set_ioport(device_t dev, void *context, u_int32_t base, u_int32_t length);
377 static void	acpi_res_set_iorange(device_t dev, void *context, u_int32_t low, u_int32_t high,
378 				     u_int32_t length, u_int32_t align);
379 static void	acpi_res_set_memory(device_t dev, void *context, u_int32_t base, u_int32_t length);
380 static void	acpi_res_set_memoryrange(device_t dev, void *context, u_int32_t low, u_int32_t high,
381 					 u_int32_t length, u_int32_t align);
382 static void	acpi_res_set_irq(device_t dev, void *context, u_int32_t *irq,
383 				 int count);
384 static void	acpi_res_set_drq(device_t dev, void *context, u_int32_t *drq,
385 				 int count);
386 static void	acpi_res_set_start_dependant(device_t dev, void *context, int preference);
387 static void	acpi_res_set_end_dependant(device_t dev, void *context);
388 
389 struct acpi_parse_resource_set acpi_res_parse_set = {
390     acpi_res_set_init,
391     acpi_res_set_done,
392     acpi_res_set_ioport,
393     acpi_res_set_iorange,
394     acpi_res_set_memory,
395     acpi_res_set_memoryrange,
396     acpi_res_set_irq,
397     acpi_res_set_drq,
398     acpi_res_set_start_dependant,
399     acpi_res_set_end_dependant
400 };
401 
402 struct acpi_res_context {
403     int		ar_nio;
404     int		ar_nmem;
405     int		ar_nirq;
406     int		ar_ndrq;
407 };
408 
409 static void
410 acpi_res_set_init(device_t dev, void **context)
411 {
412     struct acpi_res_context	*cp;
413 
414     if ((cp = AcpiOsAllocate(sizeof(*cp))) != NULL) {
415 	bzero(cp, sizeof(*cp));
416 	*context = cp;
417     }
418 }
419 
420 static void
421 acpi_res_set_done(device_t dev, void *context)
422 {
423     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
424 
425     if (cp == NULL)
426 	return;
427     AcpiOsFree(cp);
428 }
429 
430 static void
431 acpi_res_set_ioport(device_t dev, void *context, u_int32_t base, u_int32_t length)
432 {
433     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
434 
435     if (cp == NULL)
436 	return;
437     bus_set_resource(dev, SYS_RES_IOPORT, cp->ar_nio++, base, length);
438 }
439 
440 static void
441 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)
442 {
443     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
444 
445     if (cp == NULL)
446 	return;
447     device_printf(dev, "I/O range not supported\n");
448 }
449 
450 static void
451 acpi_res_set_memory(device_t dev, void *context, u_int32_t base, u_int32_t length)
452 {
453     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
454 
455     if (cp == NULL)
456 	return;
457 
458     bus_set_resource(dev, SYS_RES_MEMORY, cp->ar_nmem++, base, length);
459 }
460 
461 static void
462 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)
463 {
464     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
465 
466     if (cp == NULL)
467 	return;
468     device_printf(dev, "memory range not supported\n");
469 }
470 
471 static void
472 acpi_res_set_irq(device_t dev, void *context, u_int32_t *irq, int count)
473 {
474     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
475 
476     if (cp == NULL)
477 	return;
478     if (irq == NULL)
479 	return;
480 
481     /*This implements no resource relocation.*/
482     if(count != 1)
483 	return;
484 
485     bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, *irq, 1);
486 }
487 
488 static void
489 acpi_res_set_drq(device_t dev, void *context, u_int32_t *drq, int count)
490 {
491     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
492 
493     if (cp == NULL)
494 	return;
495     if (drq == NULL)
496 	return;
497 
498     /*This implements no resource relocation.*/
499     if(count != 1)
500 	return;
501 
502     bus_set_resource(dev, SYS_RES_DRQ, cp->ar_ndrq++, *drq, 1);
503 }
504 
505 static void
506 acpi_res_set_start_dependant(device_t dev, void *context, int preference)
507 {
508     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
509 
510     if (cp == NULL)
511 	return;
512     device_printf(dev, "dependant functions not supported\n");
513 }
514 
515 static void
516 acpi_res_set_end_dependant(device_t dev, void *context)
517 {
518     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
519 
520     if (cp == NULL)
521 	return;
522 }
523 
524 /*
525  * Resource-owning placeholders.
526  *
527  * This code "owns" system resource objects that aren't
528  * otherwise useful to devices, and which shouldn't be
529  * considered "free".
530  *
531  * Note that some systems claim *all* of the physical address space
532  * with a PNP0C01 device, so we cannot correctly "own" system memory
533  * here (must be done in the SMAP handler on x86 systems, for
534  * example).
535  */
536 
537 static int	acpi_sysresource_probe(device_t dev);
538 static int	acpi_sysresource_attach(device_t dev);
539 
540 static device_method_t acpi_sysresource_methods[] = {
541     /* Device interface */
542     DEVMETHOD(device_probe,	acpi_sysresource_probe),
543     DEVMETHOD(device_attach,	acpi_sysresource_attach),
544 
545     {0, 0}
546 };
547 
548 static driver_t acpi_sysresource_driver = {
549     "acpi_sysresource",
550     acpi_sysresource_methods,
551     0,
552 };
553 
554 static devclass_t acpi_sysresource_devclass;
555 DRIVER_MODULE(acpi_sysresource, acpi, acpi_sysresource_driver, acpi_sysresource_devclass, 0, 0);
556 
557 static int
558 acpi_sysresource_probe(device_t dev)
559 {
560     if (acpi_disabled("sysresource"))
561 	return(ENXIO);
562     if (acpi_MatchHid(dev, "PNP0C02")) {
563 	device_set_desc(dev, "system resource");
564     } else {
565 	return(ENXIO);
566     }
567     device_quiet(dev);
568     return(-100);
569 }
570 
571 static int
572 acpi_sysresource_attach(device_t dev)
573 {
574     struct resource	*res;
575     int			i, rid;
576 
577     /*
578      * Suck up all the resources that might have been assigned to us.
579      * Note that it's impossible to tell the difference between a
580      * resource that someone else has claimed, and one that doesn't
581      * exist.
582      */
583     for (i = 0; i < 100; i++) {
584 	rid = i;
585 	res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, 0);
586 	rid = i;
587 	res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, ~0, 1, 0);
588 	rid = i;
589 	res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_SHAREABLE);
590     }
591     return(0);
592 }
593