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