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