xref: /freebsd/sys/dev/acpica/acpi_resource.c (revision 7660b554bc59a07be0431c17e0e33815818baa69)
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$");
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 }
606