Merge from vendor branch LESS:
[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.8 2007/05/13 22:25:42 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 && status != AE_TYPE)
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->Type) {
98         case ACPI_RESOURCE_TYPE_END_TAG:
99             ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "EndTag\n"));
100             curr = last;
101             break;
102         case ACPI_RESOURCE_TYPE_FIXED_IO:
103             if (res->Data.FixedIo.AddressLength <= 0)
104                 break;
105             ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedIo 0x%x/%d\n",
106                              res->Data.FixedIo.Address,
107                              res->Data.FixedIo.AddressLength));
108             set->set_ioport(dev, context,
109                             res->Data.FixedIo.Address,
110                             res->Data.FixedIo.AddressLength);
111             break;
112         case ACPI_RESOURCE_TYPE_IO:
113             if (res->Data.Io.AddressLength <= 0)
114                 break;
115             if (res->Data.Io.Minimum == res->Data.Io.Maximum) {
116                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x/%d\n",
117                                  res->Data.Io.Minimum,
118                                  res->Data.Io.AddressLength));
119                 set->set_ioport(dev, context,
120                                 res->Data.Io.Minimum,
121                                 res->Data.Io.AddressLength);
122             } else {
123                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x-0x%x/%d\n",
124                                  res->Data.Io.Minimum,
125                                  res->Data.Io.Maximum, 
126                                  res->Data.Io.AddressLength));
127                 set->set_iorange(dev, context,
128                                  res->Data.Io.Minimum,
129                                  res->Data.Io.Maximum, 
130                                  res->Data.Io.AddressLength,
131                                  res->Data.Io.Alignment);
132             }
133             break;
134         case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
135             if (res->Data.FixedMemory32.AddressLength <= 0)
136                 break;
137             ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedMemory32 0x%x/%d\n",
138                               res->Data.FixedMemory32.Address, 
139                               res->Data.FixedMemory32.AddressLength));
140             set->set_memory(dev, context,
141                             res->Data.FixedMemory32.Address, 
142                             res->Data.FixedMemory32.AddressLength);
143             break;
144         case ACPI_RESOURCE_TYPE_MEMORY32:
145             if (res->Data.Memory32.AddressLength <= 0)
146                 break;
147             if (res->Data.Memory32.Minimum ==
148                 res->Data.Memory32.Maximum) {
149
150                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x/%d\n",
151                                   res->Data.Memory32.Minimum, 
152                                   res->Data.Memory32.AddressLength));
153                 set->set_memory(dev, context,
154                                 res->Data.Memory32.Minimum,
155                                 res->Data.Memory32.AddressLength);
156             } else {
157                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x-0x%x/%d\n",
158                                  res->Data.Memory32.Minimum, 
159                                  res->Data.Memory32.Maximum,
160                                  res->Data.Memory32.AddressLength));
161                 set->set_memoryrange(dev, context,
162                                      res->Data.Memory32.Minimum,
163                                      res->Data.Memory32.Maximum,
164                                      res->Data.Memory32.AddressLength,
165                                      res->Data.Memory32.Alignment);
166             }
167             break;
168         case ACPI_RESOURCE_TYPE_MEMORY24:
169             if (res->Data.Memory24.AddressLength <= 0)
170                 break;
171             if (res->Data.Memory24.Minimum ==
172                 res->Data.Memory24.Maximum) {
173
174                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x/%d\n",
175                                  res->Data.Memory24.Minimum, 
176                                  res->Data.Memory24.AddressLength));
177                 set->set_memory(dev, context, res->Data.Memory24.Minimum,
178                                 res->Data.Memory24.AddressLength);
179             } else {
180                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x-0x%x/%d\n",
181                                  res->Data.Memory24.Minimum, 
182                                  res->Data.Memory24.Maximum,
183                                  res->Data.Memory24.AddressLength));
184                 set->set_memoryrange(dev, context,
185                                      res->Data.Memory24.Minimum,
186                                      res->Data.Memory24.Maximum,
187                                      res->Data.Memory24.AddressLength,
188                                      res->Data.Memory24.Alignment);
189             }
190             break;
191         case ACPI_RESOURCE_TYPE_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.InterruptCount, res->Data.Irq.Triggering,
199                 res->Data.Irq.Polarity);
200             break;
201         case ACPI_RESOURCE_TYPE_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.ChannelCount);
209             break;
210         case ACPI_RESOURCE_TYPE_START_DEPENDENT:
211             ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "start dependent functions\n"));
212             set->set_start_dependant(dev, context,
213                                      res->Data.StartDpf.CompatibilityPriority);
214             break;
215         case ACPI_RESOURCE_TYPE_END_DEPENDENT:
216             ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "end dependent functions\n"));
217             set->set_end_dependant(dev, context);
218             break;
219         case ACPI_RESOURCE_TYPE_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.Minimum == ACPI_ADDRESS_FIXED &&
237                 res->Data.Address32.Maximum == 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.Minimum,
243                                      res->Data.Address32.AddressLength));
244                     set->set_memory(dev, context,
245                                     res->Data.Address32.Minimum,
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.Minimum,
251                                      res->Data.Address32.AddressLength));
252                     set->set_ioport(dev, context,
253                                     res->Data.Address32.Minimum,
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.Minimum,
261                                      res->Data.Address32.Maximum,
262                                      res->Data.Address32.AddressLength));
263                     set->set_memoryrange(dev, context,
264                                           res->Data.Address32.Minimum,
265                                           res->Data.Address32.Maximum,
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.Minimum,
272                                      res->Data.Address32.Maximum,
273                                      res->Data.Address32.AddressLength));
274                     set->set_iorange(dev, context,
275                                      res->Data.Address32.Minimum,
276                                      res->Data.Address32.Maximum,
277                                      res->Data.Address32.AddressLength,
278                                      res->Data.Address32.Granularity);
279                 }
280             }               
281             break;
282         case ACPI_RESOURCE_TYPE_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.Minimum == ACPI_ADDRESS_FIXED &&
300                 res->Data.Address16.Maximum == 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.Minimum,
306                                      res->Data.Address16.AddressLength));
307                     set->set_memory(dev, context,
308                                     res->Data.Address16.Minimum,
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.Minimum,
314                                      res->Data.Address16.AddressLength));
315                     set->set_ioport(dev, context,
316                                     res->Data.Address16.Minimum,
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.Minimum,
324                                      res->Data.Address16.Maximum,
325                                      res->Data.Address16.AddressLength));
326                     set->set_memoryrange(dev, context,
327                                           res->Data.Address16.Minimum,
328                                           res->Data.Address16.Maximum,
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.Minimum,
335                                      res->Data.Address16.Maximum,
336                                      res->Data.Address16.AddressLength));
337                     set->set_iorange(dev, context,
338                                      res->Data.Address16.Minimum,
339                                      res->Data.Address16.Maximum,
340                                      res->Data.Address16.AddressLength,
341                                      res->Data.Address16.Granularity);
342                 }
343             }               
344             break;
345         case ACPI_RESOURCE_TYPE_ADDRESS64:
346             ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
347                              "unimplemented Address64 resource\n"));
348             break;
349         case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
350             /* XXX special handling? */
351             set->set_ext_irq(dev, context, res->Data.ExtendedIrq.Interrupts,
352                 res->Data.ExtendedIrq.InterruptCount,
353                 res->Data.ExtendedIrq.Triggering,
354                 res->Data.ExtendedIrq.Polarity);
355             break;
356         case ACPI_RESOURCE_TYPE_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_int8_t *irq,
387                                  int count, int trig, int pol);
388 static void     acpi_res_set_ext_irq(device_t dev, void *context,
389                                      u_int32_t *irq, int count, int trig,
390                                      int pol);
391 static void     acpi_res_set_drq(device_t dev, void *context, u_int8_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_ext_irq,
406     acpi_res_set_drq,
407     acpi_res_set_start_dependant,
408     acpi_res_set_end_dependant
409 };
410
411 struct acpi_res_context {
412     int         ar_nio;
413     int         ar_nmem;
414     int         ar_nirq;
415     int         ar_ndrq;
416     void        *ar_parent;
417 };
418
419 static void
420 acpi_res_set_init(device_t dev, void *arg, void **context)
421 {
422     struct acpi_res_context     *cp;
423
424     if ((cp = AcpiOsAllocate(sizeof(*cp))) != NULL) {
425         bzero(cp, sizeof(*cp));
426         cp->ar_parent = arg;
427         *context = cp;
428     }
429 }
430
431 static void
432 acpi_res_set_done(device_t dev, void *context)
433 {
434     struct acpi_res_context     *cp = (struct acpi_res_context *)context;
435
436     if (cp == NULL)
437         return;
438     AcpiOsFree(cp);
439 }
440
441 static void
442 acpi_res_set_ioport(device_t dev, void *context, u_int32_t base,
443                     u_int32_t length)
444 {
445     struct acpi_res_context     *cp = (struct acpi_res_context *)context;
446
447     if (cp == NULL)
448         return;
449     bus_set_resource(dev, SYS_RES_IOPORT, cp->ar_nio++, base, length);
450 }
451
452 static void
453 acpi_res_set_iorange(device_t dev, void *context, u_int32_t low,
454                      u_int32_t high, u_int32_t length, u_int32_t align)
455 {
456     struct acpi_res_context     *cp = (struct acpi_res_context *)context;
457
458     if (cp == NULL)
459         return;
460     device_printf(dev, "I/O range not supported\n");
461 }
462
463 static void
464 acpi_res_set_memory(device_t dev, void *context, u_int32_t base,
465                     u_int32_t length)
466 {
467     struct acpi_res_context     *cp = (struct acpi_res_context *)context;
468
469     if (cp == NULL)
470         return;
471
472     bus_set_resource(dev, SYS_RES_MEMORY, cp->ar_nmem++, base, length);
473 }
474
475 static void
476 acpi_res_set_memoryrange(device_t dev, void *context, u_int32_t low,
477                          u_int32_t high, u_int32_t length, u_int32_t align)
478 {
479     struct acpi_res_context     *cp = (struct acpi_res_context *)context;
480
481     if (cp == NULL)
482         return;
483     device_printf(dev, "memory range not supported\n");
484 }
485
486 static void
487 acpi_res_set_irq(device_t dev, void *context, u_int8_t *irq, int count,
488     int trig, int pol)
489 {
490     struct acpi_res_context     *cp = (struct acpi_res_context *)context;
491
492     if (cp == NULL || irq == NULL)
493         return;
494
495     /* This implements no resource relocation. */
496     if (count != 1)
497         return;
498
499     bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, *irq, 1);
500 #if 0   /* From FreeBSD-5 XXX */
501     BUS_CONFIG_INTR(dev, *irq, (trig == ACPI_EDGE_SENSITIVE) ?
502         INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL, (pol == ACPI_ACTIVE_HIGH) ?
503         INTR_POLARITY_HIGH : INTR_POLARITY_LOW);
504 #endif
505 }
506
507 static void
508 acpi_res_set_ext_irq(device_t dev, void *context, u_int32_t *irq, int count,
509     int trig, int pol)
510 {
511     struct acpi_res_context     *cp = (struct acpi_res_context *)context;
512
513     if (cp == NULL || irq == NULL)
514         return;
515
516     /* This implements no resource relocation. */
517     if (count != 1)
518         return;
519
520     bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, *irq, 1);
521 #if 0   /* From FreeBSD-5 XXX */
522     BUS_CONFIG_INTR(dev, *irq, (trig == ACPI_EDGE_SENSITIVE) ?
523         INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL, (pol == ACPI_ACTIVE_HIGH) ?
524         INTR_POLARITY_HIGH : INTR_POLARITY_LOW);
525 #endif
526 }
527
528 static void
529 acpi_res_set_drq(device_t dev, void *context, u_int8_t *drq, int count)
530 {
531     struct acpi_res_context     *cp = (struct acpi_res_context *)context;
532
533     if (cp == NULL || drq == NULL)
534         return;
535     
536     /* This implements no resource relocation. */
537     if (count != 1)
538         return;
539
540     bus_set_resource(dev, SYS_RES_DRQ, cp->ar_ndrq++, *drq, 1);
541 }
542
543 static void
544 acpi_res_set_start_dependant(device_t dev, void *context, int preference)
545 {
546     struct acpi_res_context     *cp = (struct acpi_res_context *)context;
547
548     if (cp == NULL)
549         return;
550     device_printf(dev, "dependent functions not supported\n");
551 }
552
553 static void
554 acpi_res_set_end_dependant(device_t dev, void *context)
555 {
556     struct acpi_res_context     *cp = (struct acpi_res_context *)context;
557
558     if (cp == NULL)
559         return;
560     device_printf(dev, "dependent functions not supported\n");
561 }
562
563 /*
564  * Resource-owning placeholders.
565  *
566  * This code "owns" system resource objects that aren't
567  * otherwise useful to devices, and which shouldn't be
568  * considered "free".
569  *
570  * Note that some systems claim *all* of the physical address space
571  * with a PNP0C01 device, so we cannot correctly "own" system memory
572  * here (must be done in the SMAP handler on x86 systems, for
573  * example).
574  */
575
576 static int      acpi_sysresource_probe(device_t dev);
577 static int      acpi_sysresource_attach(device_t dev);
578
579 static device_method_t acpi_sysresource_methods[] = {
580     /* Device interface */
581     DEVMETHOD(device_probe,     acpi_sysresource_probe),
582     DEVMETHOD(device_attach,    acpi_sysresource_attach),
583
584     {0, 0}
585 };
586
587 static driver_t acpi_sysresource_driver = {
588     "acpi_sysresource",
589     acpi_sysresource_methods,
590     0,
591 };
592
593 static devclass_t acpi_sysresource_devclass;
594 DRIVER_MODULE(acpi_sysresource, acpi, acpi_sysresource_driver,
595               acpi_sysresource_devclass, 0, 0);
596 MODULE_DEPEND(acpi_sysresource, acpi, 1, 1, 1);
597
598 static int
599 acpi_sysresource_probe(device_t dev)
600 {
601     if (!acpi_disabled("sysresource") && acpi_MatchHid(dev, "PNP0C02"))
602         device_set_desc(dev, "System Resource");
603     else
604         return (ENXIO);
605
606     device_quiet(dev);
607     return (-100);
608 }
609
610 static int
611 acpi_sysresource_attach(device_t dev)
612 {
613     struct resource     *res;
614     int                 i, rid;
615
616     /*
617      * Suck up all the resources that might have been assigned to us.
618      * Note that it's impossible to tell the difference between a
619      * resource that someone else has claimed, and one that doesn't
620      * exist.
621      */
622     for (i = 0; i < 100; i++) {
623         rid = i;
624         res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, 0);
625         rid = i;
626         res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 0);
627         rid = i;
628         res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE);
629     }
630
631     return (0);
632 }