c337804a176dff42a8482e2b388fc6dca261a52c
[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  * __FBSDID("$FreeBSD: src/sys/dev/acpica/acpi_resource.c,v 1.40.8.1 2009/04/15 03:14:26 kensmith Exp $");
27  */
28
29 #include <sys/cdefs.h>
30
31 #include "opt_acpi.h"
32 #include <sys/param.h>
33 #include <sys/kernel.h>
34 #include <sys/bus.h>
35 #include <sys/malloc.h>
36 #include <sys/module.h>
37 #include <sys/resource.h>
38
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 struct lookup_irq_request {
49     ACPI_RESOURCE *acpi_res;
50     struct resource *res;
51     int         counter;
52     int         rid;
53     int         found;
54 };
55
56 static ACPI_STATUS
57 acpi_lookup_irq_handler(ACPI_RESOURCE *res, void *context)
58 {
59     struct lookup_irq_request *req;
60     u_int irqnum, irq;
61
62     switch (res->Type) {
63     case ACPI_RESOURCE_TYPE_IRQ:
64     case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
65         if (res->Type == ACPI_RESOURCE_TYPE_IRQ) {
66             irqnum = res->Data.Irq.InterruptCount;
67             irq = res->Data.Irq.Interrupts[0];
68         } else {
69             irqnum = res->Data.ExtendedIrq.InterruptCount;
70             irq = res->Data.ExtendedIrq.Interrupts[0];
71         }
72         if (irqnum != 1)
73             break;
74         req = (struct lookup_irq_request *)context;
75         if (req->counter != req->rid) {
76             req->counter++;
77             break;
78         }
79         req->found = 1;
80         KASSERT(irq == rman_get_start(req->res),
81             ("IRQ resources do not match"));
82         bcopy(res, req->acpi_res, sizeof(ACPI_RESOURCE));
83         return (AE_CTRL_TERMINATE);
84     }
85     return (AE_OK);
86 }
87
88 ACPI_STATUS
89 acpi_lookup_irq_resource(device_t dev, int rid, struct resource *res,
90     ACPI_RESOURCE *acpi_res)
91 {
92     struct lookup_irq_request req;
93     ACPI_STATUS status;
94
95     req.acpi_res = acpi_res;
96     req.res = res;
97     req.counter = 0;
98     req.rid = rid;
99     req.found = 0;
100     status = AcpiWalkResources(acpi_get_handle(dev), "_CRS",
101         acpi_lookup_irq_handler, &req);
102     if (ACPI_SUCCESS(status) && req.found == 0)
103         status = AE_NOT_FOUND;
104     return (status);
105 }
106
107 void
108 acpi_config_intr(device_t dev, ACPI_RESOURCE *res)
109 {
110     u_int irq;
111     int pol, trig;
112     switch (res->Type) {
113     case ACPI_RESOURCE_TYPE_IRQ:
114         KASSERT(res->Data.Irq.InterruptCount == 1,
115             ("%s: multiple interrupts", __func__));
116         irq = res->Data.Irq.Interrupts[0];
117         trig = res->Data.Irq.Triggering;
118         pol = res->Data.Irq.Polarity;
119         break;
120     case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
121         KASSERT(res->Data.ExtendedIrq.InterruptCount == 1,
122             ("%s: multiple interrupts", __func__));
123         irq = res->Data.ExtendedIrq.Interrupts[0];
124         trig = res->Data.ExtendedIrq.Triggering;
125         pol = res->Data.ExtendedIrq.Polarity;
126         break;
127     default:
128         panic("%s: bad resource type %u", __func__, res->Type);
129     }
130     BUS_CONFIG_INTR(dev, dev, irq, (trig == ACPI_EDGE_SENSITIVE) ?
131         INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL, (pol == ACPI_ACTIVE_HIGH) ?
132         INTR_POLARITY_HIGH : INTR_POLARITY_LOW);
133 }
134
135 /*
136  * Fetch a device's resources and associate them with the device.
137  *
138  * Note that it might be nice to also locate ACPI-specific resource items, such
139  * as GPE bits.
140  *
141  * We really need to split the resource-fetching code out from the
142  * resource-parsing code, since we may want to use the parsing
143  * code for _PRS someday.
144  */
145 ACPI_STATUS
146 acpi_parse_resources(device_t dev, ACPI_HANDLE handle,
147                      struct acpi_parse_resource_set *set, void *arg)
148 {
149     ACPI_BUFFER         buf;
150     ACPI_RESOURCE       *res;
151     char                *curr, *last;
152     ACPI_STATUS         status;
153     void                *context;
154
155     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
156
157     /*
158      * Special-case some devices that abuse _PRS/_CRS to mean
159      * something other than "I consume this resource".
160      *
161      * XXX do we really need this?  It's only relevant once
162      *     we start always-allocating these resources, and even
163      *     then, the only special-cased device is likely to be
164      *     the PCI interrupt link.
165      */
166
167     /* Fetch the device's current resources. */
168     buf.Length = ACPI_ALLOCATE_BUFFER;
169     if (ACPI_FAILURE((status = AcpiGetCurrentResources(handle, &buf)))) {
170         if (status != AE_NOT_FOUND && status != AE_TYPE)
171             kprintf("can't fetch resources for %s - %s\n",
172                    acpi_name(handle), AcpiFormatException(status));
173         return_ACPI_STATUS (status);
174     }
175     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s - got %ld bytes of resources\n",
176                      acpi_name(handle), (long)buf.Length));
177     set->set_init(dev, arg, &context);
178
179     /* Iterate through the resources */
180     curr = buf.Pointer;
181     last = (char *)buf.Pointer + buf.Length;
182     while (curr < last) {
183         res = (ACPI_RESOURCE *)curr;
184         curr += res->Length;
185
186         /* Handle the individual resource types */
187         switch(res->Type) {
188         case ACPI_RESOURCE_TYPE_END_TAG:
189             ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "EndTag\n"));
190             curr = last;
191             break;
192         case ACPI_RESOURCE_TYPE_FIXED_IO:
193             if (res->Data.FixedIo.AddressLength <= 0)
194                 break;
195             ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedIo 0x%x/%d\n",
196                              res->Data.FixedIo.Address,
197                              res->Data.FixedIo.AddressLength));
198             set->set_ioport(dev, context,
199                             res->Data.FixedIo.Address,
200                             res->Data.FixedIo.AddressLength);
201             break;
202         case ACPI_RESOURCE_TYPE_IO:
203             if (res->Data.Io.AddressLength <= 0)
204                 break;
205             if (res->Data.Io.Minimum == res->Data.Io.Maximum) {
206                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x/%d\n",
207                                  res->Data.Io.Minimum,
208                                  res->Data.Io.AddressLength));
209                 set->set_ioport(dev, context,
210                                 res->Data.Io.Minimum,
211                                 res->Data.Io.AddressLength);
212             } else {
213                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x-0x%x/%d\n",
214                                  res->Data.Io.Minimum,
215                                  res->Data.Io.Maximum, 
216                                  res->Data.Io.AddressLength));
217                 set->set_iorange(dev, context,
218                                  res->Data.Io.Minimum,
219                                  res->Data.Io.Maximum, 
220                                  res->Data.Io.AddressLength,
221                                  res->Data.Io.Alignment);
222             }
223             break;
224         case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
225             if (res->Data.FixedMemory32.AddressLength <= 0)
226                 break;
227             ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedMemory32 0x%x/%d\n",
228                               res->Data.FixedMemory32.Address, 
229                               res->Data.FixedMemory32.AddressLength));
230             set->set_memory(dev, context,
231                             res->Data.FixedMemory32.Address, 
232                             res->Data.FixedMemory32.AddressLength);
233             break;
234         case ACPI_RESOURCE_TYPE_MEMORY32:
235             if (res->Data.Memory32.AddressLength <= 0)
236                 break;
237             if (res->Data.Memory32.Minimum ==
238                 res->Data.Memory32.Maximum) {
239
240                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x/%d\n",
241                                   res->Data.Memory32.Minimum, 
242                                   res->Data.Memory32.AddressLength));
243                 set->set_memory(dev, context,
244                                 res->Data.Memory32.Minimum,
245                                 res->Data.Memory32.AddressLength);
246             } else {
247                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x-0x%x/%d\n",
248                                  res->Data.Memory32.Minimum, 
249                                  res->Data.Memory32.Maximum,
250                                  res->Data.Memory32.AddressLength));
251                 set->set_memoryrange(dev, context,
252                                      res->Data.Memory32.Minimum,
253                                      res->Data.Memory32.Maximum,
254                                      res->Data.Memory32.AddressLength,
255                                      res->Data.Memory32.Alignment);
256             }
257             break;
258         case ACPI_RESOURCE_TYPE_MEMORY24:
259             if (res->Data.Memory24.AddressLength <= 0)
260                 break;
261             if (res->Data.Memory24.Minimum ==
262                 res->Data.Memory24.Maximum) {
263
264                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x/%d\n",
265                                  res->Data.Memory24.Minimum, 
266                                  res->Data.Memory24.AddressLength));
267                 set->set_memory(dev, context, res->Data.Memory24.Minimum,
268                                 res->Data.Memory24.AddressLength);
269             } else {
270                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x-0x%x/%d\n",
271                                  res->Data.Memory24.Minimum, 
272                                  res->Data.Memory24.Maximum,
273                                  res->Data.Memory24.AddressLength));
274                 set->set_memoryrange(dev, context,
275                                      res->Data.Memory24.Minimum,
276                                      res->Data.Memory24.Maximum,
277                                      res->Data.Memory24.AddressLength,
278                                      res->Data.Memory24.Alignment);
279             }
280             break;
281         case ACPI_RESOURCE_TYPE_IRQ:
282             /*
283              * from 1.0b 6.4.2 
284              * "This structure is repeated for each separate interrupt
285              * required"
286              */
287             set->set_irq(dev, context, res->Data.Irq.Interrupts,
288                 res->Data.Irq.InterruptCount, res->Data.Irq.Triggering,
289                 res->Data.Irq.Polarity);
290             break;
291         case ACPI_RESOURCE_TYPE_DMA:
292             /*
293              * from 1.0b 6.4.3 
294              * "This structure is repeated for each separate dma channel
295              * required"
296              */
297             set->set_drq(dev, context, res->Data.Dma.Channels,
298                          res->Data.Dma.ChannelCount);
299             break;
300         case ACPI_RESOURCE_TYPE_START_DEPENDENT:
301             ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "start dependent functions\n"));
302             set->set_start_dependent(dev, context,
303                                      res->Data.StartDpf.CompatibilityPriority);
304             break;
305         case ACPI_RESOURCE_TYPE_END_DEPENDENT:
306             ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "end dependent functions\n"));
307             set->set_end_dependent(dev, context);
308             break;
309         case ACPI_RESOURCE_TYPE_ADDRESS32:
310             if (res->Data.Address32.AddressLength <= 0)
311                 break;
312             if (res->Data.Address32.ProducerConsumer != ACPI_CONSUMER) {
313                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
314                     "ignored Address32 %s producer\n",
315                     res->Data.Address32.ResourceType == ACPI_IO_RANGE ?
316                     "IO" : "Memory"));
317                 break;
318             }
319             if (res->Data.Address32.ResourceType != ACPI_MEMORY_RANGE &&
320                 res->Data.Address32.ResourceType != ACPI_IO_RANGE) {
321                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
322                     "ignored Address32 for non-memory, non-I/O\n"));
323                 break;
324             }
325
326             if (res->Data.Address32.MinAddressFixed == ACPI_ADDRESS_FIXED &&
327                 res->Data.Address32.MaxAddressFixed == ACPI_ADDRESS_FIXED) {
328
329                 if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) {
330                     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
331                                      "Address32/Memory 0x%x/%d\n",
332                                      res->Data.Address32.Minimum,
333                                      res->Data.Address32.AddressLength));
334                     set->set_memory(dev, context,
335                                     res->Data.Address32.Minimum,
336                                     res->Data.Address32.AddressLength);
337                 } else {
338                     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
339                                      "Address32/IO 0x%x/%d\n",
340                                      res->Data.Address32.Minimum,
341                                      res->Data.Address32.AddressLength));
342                     set->set_ioport(dev, context,
343                                     res->Data.Address32.Minimum,
344                                     res->Data.Address32.AddressLength);
345                 }
346             } else {
347                 if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) {
348                     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
349                                      "Address32/Memory 0x%x-0x%x/%d\n",
350                                      res->Data.Address32.Minimum,
351                                      res->Data.Address32.Maximum,
352                                      res->Data.Address32.AddressLength));
353                     set->set_memoryrange(dev, context,
354                                           res->Data.Address32.Minimum,
355                                           res->Data.Address32.Maximum,
356                                           res->Data.Address32.AddressLength,
357                                           res->Data.Address32.Granularity);
358                 } else {
359                     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
360                                      "Address32/IO 0x%x-0x%x/%d\n",
361                                      res->Data.Address32.Minimum,
362                                      res->Data.Address32.Maximum,
363                                      res->Data.Address32.AddressLength));
364                     set->set_iorange(dev, context,
365                                      res->Data.Address32.Minimum,
366                                      res->Data.Address32.Maximum,
367                                      res->Data.Address32.AddressLength,
368                                      res->Data.Address32.Granularity);
369                 }
370             }               
371             break;
372         case ACPI_RESOURCE_TYPE_ADDRESS16:
373             if (res->Data.Address16.AddressLength <= 0)
374                 break;
375             if (res->Data.Address16.ProducerConsumer != ACPI_CONSUMER) {
376                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
377                     "ignored Address16 %s producer\n",
378                     res->Data.Address16.ResourceType == ACPI_IO_RANGE ?
379                     "IO" : "Memory"));
380                 break;
381             }
382             if (res->Data.Address16.ResourceType != ACPI_MEMORY_RANGE &&
383                 res->Data.Address16.ResourceType != ACPI_IO_RANGE) {
384                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
385                         "ignored Address16 for non-memory, non-I/O\n"));
386                 break;
387             }
388
389             if (res->Data.Address16.MinAddressFixed == ACPI_ADDRESS_FIXED &&
390                 res->Data.Address16.MaxAddressFixed == ACPI_ADDRESS_FIXED) {
391
392                 if (res->Data.Address16.ResourceType == ACPI_MEMORY_RANGE) {
393                     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
394                                      "Address16/Memory 0x%x/%d\n",
395                                      res->Data.Address16.Minimum,
396                                      res->Data.Address16.AddressLength));
397                     set->set_memory(dev, context,
398                                     res->Data.Address16.Minimum,
399                                     res->Data.Address16.AddressLength);
400                 } else {
401                     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
402                                      "Address16/IO 0x%x/%d\n",
403                                      res->Data.Address16.Minimum,
404                                      res->Data.Address16.AddressLength));
405                     set->set_ioport(dev, context,
406                                     res->Data.Address16.Minimum,
407                                     res->Data.Address16.AddressLength);
408                 }
409             } else {
410                 if (res->Data.Address16.ResourceType == ACPI_MEMORY_RANGE) {
411                     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
412                                      "Address16/Memory 0x%x-0x%x/%d\n",
413                                      res->Data.Address16.Minimum,
414                                      res->Data.Address16.Maximum,
415                                      res->Data.Address16.AddressLength));
416                     set->set_memoryrange(dev, context,
417                                           res->Data.Address16.Minimum,
418                                           res->Data.Address16.Maximum,
419                                           res->Data.Address16.AddressLength,
420                                           res->Data.Address16.Granularity);
421                 } else {
422                     ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
423                                      "Address16/IO 0x%x-0x%x/%d\n",
424                                      res->Data.Address16.Minimum,
425                                      res->Data.Address16.Maximum,
426                                      res->Data.Address16.AddressLength));
427                     set->set_iorange(dev, context,
428                                      res->Data.Address16.Minimum,
429                                      res->Data.Address16.Maximum,
430                                      res->Data.Address16.AddressLength,
431                                      res->Data.Address16.Granularity);
432                 }
433             }               
434             break;
435         case ACPI_RESOURCE_TYPE_ADDRESS64:
436             ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
437                              "unimplemented Address64 resource\n"));
438             break;
439         case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
440             if (res->Data.ExtendedIrq.ProducerConsumer != ACPI_CONSUMER) {
441                 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
442                     "ignored ExtIRQ producer\n"));
443                 break;
444             }
445             set->set_ext_irq(dev, context, res->Data.ExtendedIrq.Interrupts,
446                 res->Data.ExtendedIrq.InterruptCount,
447                 res->Data.ExtendedIrq.Triggering,
448                 res->Data.ExtendedIrq.Polarity);
449             break;
450         case ACPI_RESOURCE_TYPE_VENDOR:
451             ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
452                              "unimplemented VendorSpecific resource\n"));
453             break;
454         default:
455             break;
456         }
457     }    
458
459     AcpiOsFree(buf.Pointer);
460     set->set_done(dev, context);
461     return_ACPI_STATUS (AE_OK);
462 }
463
464 /*
465  * Resource-set vectors used to attach _CRS-derived resources 
466  * to an ACPI device.
467  */
468 static void     acpi_res_set_init(device_t dev, void *arg, void **context);
469 static void     acpi_res_set_done(device_t dev, void *context);
470 static void     acpi_res_set_ioport(device_t dev, void *context,
471                                     u_int32_t base, u_int32_t length);
472 static void     acpi_res_set_iorange(device_t dev, void *context,
473                                      u_int32_t low, u_int32_t high, 
474                                      u_int32_t length, u_int32_t align);
475 static void     acpi_res_set_memory(device_t dev, void *context,
476                                     u_int32_t base, u_int32_t length);
477 static void     acpi_res_set_memoryrange(device_t dev, void *context,
478                                          u_int32_t low, u_int32_t high, 
479                                          u_int32_t length, u_int32_t align);
480 static void     acpi_res_set_irq(device_t dev, void *context, u_int8_t *irq,
481                                  int count, int trig, int pol);
482 static void     acpi_res_set_ext_irq(device_t dev, void *context,
483                                  u_int32_t *irq, int count, int trig, int pol);
484 static void     acpi_res_set_drq(device_t dev, void *context, u_int8_t *drq,
485                                  int count);
486 static void     acpi_res_set_start_dependent(device_t dev, void *context,
487                                              int preference);
488 static void     acpi_res_set_end_dependent(device_t dev, void *context);
489
490 struct acpi_parse_resource_set acpi_res_parse_set = {
491     acpi_res_set_init,
492     acpi_res_set_done,
493     acpi_res_set_ioport,
494     acpi_res_set_iorange,
495     acpi_res_set_memory,
496     acpi_res_set_memoryrange,
497     acpi_res_set_irq,
498     acpi_res_set_ext_irq,
499     acpi_res_set_drq,
500     acpi_res_set_start_dependent,
501     acpi_res_set_end_dependent
502 };
503
504 struct acpi_res_context {
505     int         ar_nio;
506     int         ar_nmem;
507     int         ar_nirq;
508     int         ar_ndrq;
509     void        *ar_parent;
510 };
511
512 static void
513 acpi_res_set_init(device_t dev, void *arg, void **context)
514 {
515     struct acpi_res_context     *cp;
516
517     if ((cp = AcpiOsAllocate(sizeof(*cp))) != NULL) {
518         bzero(cp, sizeof(*cp));
519         cp->ar_parent = arg;
520         *context = cp;
521     }
522 }
523
524 static void
525 acpi_res_set_done(device_t dev, void *context)
526 {
527     struct acpi_res_context     *cp = (struct acpi_res_context *)context;
528
529     if (cp == NULL)
530         return;
531     AcpiOsFree(cp);
532 }
533
534 static void
535 acpi_res_set_ioport(device_t dev, void *context, u_int32_t base,
536                     u_int32_t length)
537 {
538     struct acpi_res_context     *cp = (struct acpi_res_context *)context;
539
540     if (cp == NULL)
541         return;
542     bus_set_resource(dev, SYS_RES_IOPORT, cp->ar_nio++, base, length);
543 }
544
545 static void
546 acpi_res_set_iorange(device_t dev, void *context, u_int32_t low,
547                      u_int32_t high, u_int32_t length, u_int32_t align)
548 {
549     struct acpi_res_context     *cp = (struct acpi_res_context *)context;
550
551     if (cp == NULL)
552         return;
553     device_printf(dev, "I/O range not supported\n");
554 }
555
556 static void
557 acpi_res_set_memory(device_t dev, void *context, u_int32_t base,
558                     u_int32_t length)
559 {
560     struct acpi_res_context     *cp = (struct acpi_res_context *)context;
561
562     if (cp == NULL)
563         return;
564
565     bus_set_resource(dev, SYS_RES_MEMORY, cp->ar_nmem++, base, length);
566 }
567
568 static void
569 acpi_res_set_memoryrange(device_t dev, void *context, u_int32_t low,
570                          u_int32_t high, u_int32_t length, u_int32_t align)
571 {
572     struct acpi_res_context     *cp = (struct acpi_res_context *)context;
573
574     if (cp == NULL)
575         return;
576     device_printf(dev, "memory range not supported\n");
577 }
578
579 static void
580 acpi_res_set_irq(device_t dev, void *context, u_int8_t *irq, int count,
581     int trig, int pol)
582 {
583     struct acpi_res_context     *cp = (struct acpi_res_context *)context;
584
585     if (cp == NULL || irq == NULL)
586         return;
587
588     /* This implements no resource relocation. */
589     if (count != 1)
590         return;
591
592     bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, *irq, 1);
593 }
594
595 static void
596 acpi_res_set_ext_irq(device_t dev, void *context, u_int32_t *irq, int count,
597     int trig, int pol)
598 {
599     struct acpi_res_context     *cp = (struct acpi_res_context *)context;
600
601     if (cp == NULL || irq == NULL)
602         return;
603
604     /* This implements no resource relocation. */
605     if (count != 1)
606         return;
607
608     bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, *irq, 1);
609 }
610
611 static void
612 acpi_res_set_drq(device_t dev, void *context, u_int8_t *drq, int count)
613 {
614     struct acpi_res_context     *cp = (struct acpi_res_context *)context;
615
616     if (cp == NULL || drq == NULL)
617         return;
618     
619     /* This implements no resource relocation. */
620     if (count != 1)
621         return;
622
623     bus_set_resource(dev, SYS_RES_DRQ, cp->ar_ndrq++, *drq, 1);
624 }
625
626 static void
627 acpi_res_set_start_dependent(device_t dev, void *context, int preference)
628 {
629     struct acpi_res_context     *cp = (struct acpi_res_context *)context;
630
631     if (cp == NULL)
632         return;
633     device_printf(dev, "dependent functions not supported\n");
634 }
635
636 static void
637 acpi_res_set_end_dependent(device_t dev, void *context)
638 {
639     struct acpi_res_context     *cp = (struct acpi_res_context *)context;
640
641     if (cp == NULL)
642         return;
643     device_printf(dev, "dependent functions not supported\n");
644 }
645
646 /*
647  * Resource-owning placeholders for IO and memory pseudo-devices.
648  *
649  * This code allocates system resources that will be used by ACPI
650  * child devices.  The acpi parent manages these resources through a
651  * private rman.
652  */
653
654 static int      acpi_sysres_rid = 100;
655
656 static int      acpi_sysres_probe(device_t dev);
657 static int      acpi_sysres_attach(device_t dev);
658
659 static device_method_t acpi_sysres_methods[] = {
660     /* Device interface */
661     DEVMETHOD(device_probe,     acpi_sysres_probe),
662     DEVMETHOD(device_attach,    acpi_sysres_attach),
663
664     {0, 0}
665 };
666
667 static driver_t acpi_sysres_driver = {
668     "acpi_sysresource",
669     acpi_sysres_methods,
670     0,
671 };
672
673 static devclass_t acpi_sysres_devclass;
674 DRIVER_MODULE(acpi_sysresource, acpi, acpi_sysres_driver, acpi_sysres_devclass,
675     0, 0);
676 MODULE_DEPEND(acpi_sysresource, acpi, 1, 1, 1);
677
678 static int
679 acpi_sysres_probe(device_t dev)
680 {
681     static char *sysres_ids[] = { "PNP0C01", "PNP0C02", NULL };
682
683     if (acpi_disabled("sysresource") ||
684         ACPI_ID_PROBE(device_get_parent(dev), dev, sysres_ids) == NULL)
685         return (ENXIO);
686
687     device_set_desc(dev, "System Resource");
688     device_quiet(dev);
689     return (BUS_PROBE_DEFAULT);
690 }
691
692 static int
693 acpi_sysres_attach(device_t dev)
694 {
695     device_t bus;
696     device_t gparent;
697     struct resource_list_entry *bus_rle, *dev_rle;
698     struct resource_list *bus_rl, *dev_rl;
699     int done, type;
700     u_long start, end, count;
701     /*
702      * Loop through all current resources to see if the new one overlaps
703      * any existing ones.  If so, grow the old one up and/or down
704      * accordingly.  Discard any that are wholly contained in the old.  If
705      * the resource is unique, add it to the parent.  It will later go into
706      * the rman pool.
707      */
708     bus = device_get_parent(dev);
709     gparent = device_get_parent(bus);
710     dev_rl = BUS_GET_RESOURCE_LIST(bus, dev);
711     bus_rl = BUS_GET_RESOURCE_LIST(device_get_parent(bus), bus);
712     if(bus_rl)
713         kprintf("busrl is not null!\n");
714         SLIST_FOREACH(dev_rle, dev_rl, link) {
715         if (dev_rle->type != SYS_RES_IOPORT && dev_rle->type != SYS_RES_MEMORY)
716             continue;
717
718         start = dev_rle->start;
719         end = dev_rle->end;
720         count = dev_rle->count;
721         type = dev_rle->type;
722         done = FALSE;
723         if(bus_rl) {
724         SLIST_FOREACH(bus_rle, bus_rl, link) {
725             if (bus_rle->type != type)
726                 continue;
727
728             /* New resource wholly contained in old, discard. */
729             if (start >= bus_rle->start && end <= bus_rle->end)
730                 break;
731
732             /* New tail overlaps old head, grow existing resource downward. */
733             if (start < bus_rle->start && end >= bus_rle->start) {
734                 bus_rle->count += bus_rle->start - start;
735                 bus_rle->start = start;
736                 done = TRUE;
737             }
738
739             /* New head overlaps old tail, grow existing resource upward. */
740             if (start <= bus_rle->end && end > bus_rle->end) {
741                 bus_rle->count += end - bus_rle->end;
742                 bus_rle->end = end;
743                 done = TRUE;
744             }
745
746             /* If we adjusted the old resource, we're finished. */
747             if (done)
748                 break;
749         }
750         } else bus_rle = NULL;
751         /* If we didn't merge with anything, add this resource. */
752         if (bus_rle == NULL) {
753             bus_set_resource(bus, type, acpi_sysres_rid++, start, count);
754         }
755     }
756
757     /* After merging/moving resources to the parent, free the list. */
758     resource_list_free(dev_rl);
759
760     return (0);
761 }