cf1fcc4fa3a25bfd66a085c59e810505f9b0c01a
[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.5 2006/12/22 23:26:14 swildner 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 #include <sys/rman.h>
37
38 #include "acpi.h"
39 #include <dev/acpica5/acpivar.h>
40
41 /* Hooks for the ACPI CA debugging infrastructure */
42 #define _COMPONENT      ACPI_BUS
43 ACPI_MODULE_NAME("RESOURCE")
44
45 /*
46  * Fetch a device's resources and associate them with the device.
47  *
48  * Note that it might be nice to also locate ACPI-specific resource items, such
49  * as GPE bits.
50  *
51  * We really need to split the resource-fetching code out from the
52  * resource-parsing code, since we may want to use the parsing
53  * code for _PRS someday.
54  */
55 ACPI_STATUS
56 acpi_parse_resources(device_t dev, ACPI_HANDLE handle,
57                      struct acpi_parse_resource_set *set, void *arg)
58 {
59     ACPI_BUFFER         buf;
60     ACPI_RESOURCE       *res;
61     char                *curr, *last;
62     ACPI_STATUS         status;
63     void                *context;
64
65     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
66
67     /*
68      * Special-case some devices that abuse _PRS/_CRS to mean
69      * something other than "I consume this resource".
70      *
71      * XXX do we really need this?  It's only relevant once
72      *     we start always-allocating these resources, and even
73      *     then, the only special-cased device is likely to be
74      *     the PCI interrupt link.
75      */
76
77     /* Fetch the device's current resources. */
78     buf.Length = ACPI_ALLOCATE_BUFFER;
79     if (ACPI_FAILURE((status = AcpiGetCurrentResources(handle, &buf)))) {
80         if (status != AE_NOT_FOUND)
81             kprintf("can't fetch resources for %s - %s\n",
82                    acpi_name(handle), AcpiFormatException(status));
83         return_ACPI_STATUS (status);
84     }
85     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s - got %ld bytes of resources\n",
86                      acpi_name(handle), (long)buf.Length));
87     set->set_init(dev, arg, &context);
88
89     /* Iterate through the resources */
90     curr = buf.Pointer;
91     last = (char *)buf.Pointer + buf.Length;
92     while (curr < last) {
93         res = (ACPI_RESOURCE *)curr;
94         curr += res->Length;
95
96         /* Handle the individual resource types */
97         switch(res->Id) {
98         case ACPI_RSTYPE_END_TAG:
99             ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "EndTag\n"));
100             curr = last;
101             break;
102         case ACPI_RSTYPE_FIXED_IO:
103             if (res->Data.FixedIo.RangeLength <= 0)
104                 break;
105             ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedIo 0x%x/%d\n",
106                              res->Data.FixedIo.BaseAddress,
107                              res->Data.FixedIo.RangeLength));
108             set->set_ioport(dev, context,
109                             res->Data.FixedIo.BaseAddress,
110                             res->Data.FixedIo.RangeLength);
111             break;
112         case ACPI_RSTYPE_IO:
113             if (res->Data.Io.RangeLength <= 0)
114                 break;
115             if (res->Data.Io.MinBaseAddress == res->Data.Io.MaxBaseAddress) {
116                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x/%d\n",
117                                  res->Data.Io.MinBaseAddress,
118                                  res->Data.Io.RangeLength));
119                 set->set_ioport(dev, context,
120                                 res->Data.Io.MinBaseAddress,
121                                 res->Data.Io.RangeLength);
122             } else {
123                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x-0x%x/%d\n",
124                                  res->Data.Io.MinBaseAddress,
125                                  res->Data.Io.MaxBaseAddress, 
126                                  res->Data.Io.RangeLength));
127                 set->set_iorange(dev, context,
128                                  res->Data.Io.MinBaseAddress,
129                                  res->Data.Io.MaxBaseAddress, 
130                                  res->Data.Io.RangeLength,
131                                  res->Data.Io.Alignment);
132             }
133             break;
134         case ACPI_RSTYPE_FIXED_MEM32:
135             if (res->Data.FixedMemory32.RangeLength <= 0)
136                 break;
137             ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedMemory32 0x%x/%d\n",
138                               res->Data.FixedMemory32.RangeBaseAddress, 
139                               res->Data.FixedMemory32.RangeLength));
140             set->set_memory(dev, context,
141                             res->Data.FixedMemory32.RangeBaseAddress, 
142                             res->Data.FixedMemory32.RangeLength);
143             break;
144         case ACPI_RSTYPE_MEM32:
145             if (res->Data.Memory32.RangeLength <= 0)
146                 break;
147             if (res->Data.Memory32.MinBaseAddress ==
148                 res->Data.Memory32.MaxBaseAddress) {
149
150                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x/%d\n",
151                                   res->Data.Memory32.MinBaseAddress, 
152                                   res->Data.Memory32.RangeLength));
153                 set->set_memory(dev, context,
154                                 res->Data.Memory32.MinBaseAddress,
155                                 res->Data.Memory32.RangeLength);
156             } else {
157                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x-0x%x/%d\n",
158                                  res->Data.Memory32.MinBaseAddress, 
159                                  res->Data.Memory32.MaxBaseAddress,
160                                  res->Data.Memory32.RangeLength));
161                 set->set_memoryrange(dev, context,
162                                      res->Data.Memory32.MinBaseAddress,
163                                      res->Data.Memory32.MaxBaseAddress,
164                                      res->Data.Memory32.RangeLength,
165                                      res->Data.Memory32.Alignment);
166             }
167             break;
168         case ACPI_RSTYPE_MEM24:
169             if (res->Data.Memory24.RangeLength <= 0)
170                 break;
171             if (res->Data.Memory24.MinBaseAddress ==
172                 res->Data.Memory24.MaxBaseAddress) {
173
174                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x/%d\n",
175                                  res->Data.Memory24.MinBaseAddress, 
176                                  res->Data.Memory24.RangeLength));
177                 set->set_memory(dev, context, res->Data.Memory24.MinBaseAddress,
178                                 res->Data.Memory24.RangeLength);
179             } else {
180                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x-0x%x/%d\n",
181                                  res->Data.Memory24.MinBaseAddress, 
182                                  res->Data.Memory24.MaxBaseAddress,
183                                  res->Data.Memory24.RangeLength));
184                 set->set_memoryrange(dev, context,
185                                      res->Data.Memory24.MinBaseAddress,
186                                      res->Data.Memory24.MaxBaseAddress,
187                                      res->Data.Memory24.RangeLength,
188                                      res->Data.Memory24.Alignment);
189             }
190             break;
191         case ACPI_RSTYPE_IRQ:
192             /*
193              * from 1.0b 6.4.2 
194              * "This structure is repeated for each separate interrupt
195              * required"
196              */
197             set->set_irq(dev, context, res->Data.Irq.Interrupts,
198                 res->Data.Irq.NumberOfInterrupts, res->Data.Irq.EdgeLevel,
199                 res->Data.Irq.ActiveHighLow);
200             break;
201         case ACPI_RSTYPE_DMA:
202             /*
203              * from 1.0b 6.4.3 
204              * "This structure is repeated for each separate dma channel
205              * required"
206              */
207             set->set_drq(dev, context, res->Data.Dma.Channels,
208                          res->Data.Dma.NumberOfChannels);
209             break;
210         case ACPI_RSTYPE_START_DPF:
211             ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "start dependant functions\n"));
212             set->set_start_dependant(dev, context,
213                                      res->Data.StartDpf.CompatibilityPriority);
214             break;
215         case ACPI_RSTYPE_END_DPF:
216             ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "end dependant functions\n"));
217             set->set_end_dependant(dev, context);
218             break;
219         case ACPI_RSTYPE_ADDRESS32:
220             if (res->Data.Address32.AddressLength <= 0)
221                 break;
222             if (res->Data.Address32.ProducerConsumer != ACPI_CONSUMER) {
223                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
224                     "ignored Address32 %s producer\n",
225                     res->Data.Address32.ResourceType == ACPI_IO_RANGE ?
226                     "IO" : "Memory"));
227                 break;
228             }
229             if (res->Data.Address32.ResourceType != ACPI_MEMORY_RANGE &&
230                 res->Data.Address32.ResourceType != ACPI_IO_RANGE) {
231                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
232                     "ignored Address32 for non-memory, non-I/O\n"));
233                 break;
234             }
235
236             if (res->Data.Address32.MinAddressFixed == ACPI_ADDRESS_FIXED &&
237                 res->Data.Address32.MaxAddressFixed == ACPI_ADDRESS_FIXED) {
238
239                 if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) {
240                     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
241                                      "Address32/Memory 0x%x/%d\n",
242                                      res->Data.Address32.MinAddressRange,
243                                      res->Data.Address32.AddressLength));
244                     set->set_memory(dev, context,
245                                     res->Data.Address32.MinAddressRange,
246                                     res->Data.Address32.AddressLength);
247                 } else {
248                     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
249                                      "Address32/IO 0x%x/%d\n",
250                                      res->Data.Address32.MinAddressRange,
251                                      res->Data.Address32.AddressLength));
252                     set->set_ioport(dev, context,
253                                     res->Data.Address32.MinAddressRange,
254                                     res->Data.Address32.AddressLength);
255                 }
256             } else {
257                 if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) {
258                     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
259                                      "Address32/Memory 0x%x-0x%x/%d\n",
260                                      res->Data.Address32.MinAddressRange,
261                                      res->Data.Address32.MaxAddressRange,
262                                      res->Data.Address32.AddressLength));
263                     set->set_memoryrange(dev, context,
264                                           res->Data.Address32.MinAddressRange,
265                                           res->Data.Address32.MaxAddressRange,
266                                           res->Data.Address32.AddressLength,
267                                           res->Data.Address32.Granularity);
268                 } else {
269                     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
270                                      "Address32/IO 0x%x-0x%x/%d\n",
271                                      res->Data.Address32.MinAddressRange,
272                                      res->Data.Address32.MaxAddressRange,
273                                      res->Data.Address32.AddressLength));
274                     set->set_iorange(dev, context,
275                                      res->Data.Address32.MinAddressRange,
276                                      res->Data.Address32.MaxAddressRange,
277                                      res->Data.Address32.AddressLength,
278                                      res->Data.Address32.Granularity);
279                 }
280             }               
281             break;
282         case ACPI_RSTYPE_ADDRESS16:
283             if (res->Data.Address16.AddressLength <= 0)
284                 break;
285             if (res->Data.Address16.ProducerConsumer != ACPI_CONSUMER) {
286                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
287                     "ignored Address16 %s producer\n",
288                     res->Data.Address16.ResourceType == ACPI_IO_RANGE ?
289                     "IO" : "Memory"));
290                 break;
291             }
292             if (res->Data.Address16.ResourceType != ACPI_MEMORY_RANGE &&
293                 res->Data.Address16.ResourceType != ACPI_IO_RANGE) {
294                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
295                         "ignored Address16 for non-memory, non-I/O\n"));
296                 break;
297             }
298
299             if (res->Data.Address16.MinAddressFixed == ACPI_ADDRESS_FIXED &&
300                 res->Data.Address16.MaxAddressFixed == ACPI_ADDRESS_FIXED) {
301
302                 if (res->Data.Address16.ResourceType == ACPI_MEMORY_RANGE) {
303                     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
304                                      "Address16/Memory 0x%x/%d\n",
305                                      res->Data.Address16.MinAddressRange,
306                                      res->Data.Address16.AddressLength));
307                     set->set_memory(dev, context,
308                                     res->Data.Address16.MinAddressRange,
309                                     res->Data.Address16.AddressLength);
310                 } else {
311                     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
312                                      "Address16/IO 0x%x/%d\n",
313                                      res->Data.Address16.MinAddressRange,
314                                      res->Data.Address16.AddressLength));
315                     set->set_ioport(dev, context,
316                                     res->Data.Address16.MinAddressRange,
317                                     res->Data.Address16.AddressLength);
318                 }
319             } else {
320                 if (res->Data.Address16.ResourceType == ACPI_MEMORY_RANGE) {
321                     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
322                                      "Address16/Memory 0x%x-0x%x/%d\n",
323                                      res->Data.Address16.MinAddressRange,
324                                      res->Data.Address16.MaxAddressRange,
325                                      res->Data.Address16.AddressLength));
326                     set->set_memoryrange(dev, context,
327                                           res->Data.Address16.MinAddressRange,
328                                           res->Data.Address16.MaxAddressRange,
329                                           res->Data.Address16.AddressLength,
330                                           res->Data.Address16.Granularity);
331                 } else {
332                     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
333                                      "Address16/IO 0x%x-0x%x/%d\n",
334                                      res->Data.Address16.MinAddressRange,
335                                      res->Data.Address16.MaxAddressRange,
336                                      res->Data.Address16.AddressLength));
337                     set->set_iorange(dev, context,
338                                      res->Data.Address16.MinAddressRange,
339                                      res->Data.Address16.MaxAddressRange,
340                                      res->Data.Address16.AddressLength,
341                                      res->Data.Address16.Granularity);
342                 }
343             }               
344             break;
345         case ACPI_RSTYPE_ADDRESS64:
346             ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
347                              "unimplemented Address64 resource\n"));
348             break;
349         case ACPI_RSTYPE_EXT_IRQ:
350             /* XXX special handling? */
351             set->set_irq(dev, context,res->Data.ExtendedIrq.Interrupts,
352                 res->Data.ExtendedIrq.NumberOfInterrupts,
353                 res->Data.ExtendedIrq.EdgeLevel,
354                 res->Data.ExtendedIrq.ActiveHighLow);
355             break;
356         case ACPI_RSTYPE_VENDOR:
357             ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
358                              "unimplemented VendorSpecific resource\n"));
359             break;
360         default:
361             break;
362         }
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 *arg, 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,
377                                     u_int32_t base, u_int32_t length);
378 static void     acpi_res_set_iorange(device_t dev, void *context,
379                                      u_int32_t low, u_int32_t high, 
380                                      u_int32_t length, u_int32_t align);
381 static void     acpi_res_set_memory(device_t dev, void *context,
382                                     u_int32_t base, u_int32_t length);
383 static void     acpi_res_set_memoryrange(device_t dev, void *context,
384                                          u_int32_t low, u_int32_t high, 
385                                          u_int32_t length, u_int32_t align);
386 static void     acpi_res_set_irq(device_t dev, void *context, u_int32_t *irq,
387                                  int count, int trig, int pol);
388 static void     acpi_res_set_drq(device_t dev, void *context, u_int32_t *drq,
389                                  int count);
390 static void     acpi_res_set_start_dependant(device_t dev, void *context,
391                                              int preference);
392 static void     acpi_res_set_end_dependant(device_t dev, void *context);
393
394 struct acpi_parse_resource_set acpi_res_parse_set = {
395     acpi_res_set_init,
396     acpi_res_set_done,
397     acpi_res_set_ioport,
398     acpi_res_set_iorange,
399     acpi_res_set_memory,
400     acpi_res_set_memoryrange,
401     acpi_res_set_irq,
402     acpi_res_set_drq,
403     acpi_res_set_start_dependant,
404     acpi_res_set_end_dependant
405 };
406
407 struct acpi_res_context {
408     int         ar_nio;
409     int         ar_nmem;
410     int         ar_nirq;
411     int         ar_ndrq;
412     void        *ar_parent;
413 };
414
415 static void
416 acpi_res_set_init(device_t dev, void *arg, void **context)
417 {
418     struct acpi_res_context     *cp;
419
420     if ((cp = AcpiOsAllocate(sizeof(*cp))) != NULL) {
421         bzero(cp, sizeof(*cp));
422         cp->ar_parent = arg;
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 #if 0   /* From FreeBSD-5 XXX */
497     BUS_CONFIG_INTR(dev, *irq, (trig == ACPI_EDGE_SENSITIVE) ?
498         INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL, (pol == ACPI_ACTIVE_HIGH) ?
499         INTR_POLARITY_HIGH : INTR_POLARITY_LOW);
500 #endif
501 }
502
503 static void
504 acpi_res_set_drq(device_t dev, void *context, u_int32_t *drq, int count)
505 {
506     struct acpi_res_context     *cp = (struct acpi_res_context *)context;
507
508     if (cp == NULL || drq == NULL)
509         return;
510     
511     /* This implements no resource relocation. */
512     if (count != 1)
513         return;
514
515     bus_set_resource(dev, SYS_RES_DRQ, cp->ar_ndrq++, *drq, 1);
516 }
517
518 static void
519 acpi_res_set_start_dependant(device_t dev, void *context, int preference)
520 {
521     struct acpi_res_context     *cp = (struct acpi_res_context *)context;
522
523     if (cp == NULL)
524         return;
525     device_printf(dev, "dependant functions not supported\n");
526 }
527
528 static void
529 acpi_res_set_end_dependant(device_t dev, void *context)
530 {
531     struct acpi_res_context     *cp = (struct acpi_res_context *)context;
532
533     if (cp == NULL)
534         return;
535     device_printf(dev, "dependant functions not supported\n");
536 }
537
538 /*
539  * Resource-owning placeholders.
540  *
541  * This code "owns" system resource objects that aren't
542  * otherwise useful to devices, and which shouldn't be
543  * considered "free".
544  *
545  * Note that some systems claim *all* of the physical address space
546  * with a PNP0C01 device, so we cannot correctly "own" system memory
547  * here (must be done in the SMAP handler on x86 systems, for
548  * example).
549  */
550
551 static int      acpi_sysresource_probe(device_t dev);
552 static int      acpi_sysresource_attach(device_t dev);
553
554 static device_method_t acpi_sysresource_methods[] = {
555     /* Device interface */
556     DEVMETHOD(device_probe,     acpi_sysresource_probe),
557     DEVMETHOD(device_attach,    acpi_sysresource_attach),
558
559     {0, 0}
560 };
561
562 static driver_t acpi_sysresource_driver = {
563     "acpi_sysresource",
564     acpi_sysresource_methods,
565     0,
566 };
567
568 static devclass_t acpi_sysresource_devclass;
569 DRIVER_MODULE(acpi_sysresource, acpi, acpi_sysresource_driver,
570               acpi_sysresource_devclass, 0, 0);
571 MODULE_DEPEND(acpi_sysresource, acpi, 1, 1, 1);
572
573 static int
574 acpi_sysresource_probe(device_t dev)
575 {
576     if (!acpi_disabled("sysresource") && acpi_MatchHid(dev, "PNP0C02"))
577         device_set_desc(dev, "System Resource");
578     else
579         return (ENXIO);
580
581     device_quiet(dev);
582     return (-100);
583 }
584
585 static int
586 acpi_sysresource_attach(device_t dev)
587 {
588     struct resource     *res;
589     int                 i, rid;
590
591     /*
592      * Suck up all the resources that might have been assigned to us.
593      * Note that it's impossible to tell the difference between a
594      * resource that someone else has claimed, and one that doesn't
595      * exist.
596      */
597     for (i = 0; i < 100; i++) {
598         rid = i;
599         res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, 0);
600         rid = i;
601         res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 0);
602         rid = i;
603         res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE);
604     }
605
606     return (0);
607 }