libbarrelfish: make cap deletion in memobj_destroy_anon() optional
[barrelfish] / usr / acpi / acpica_osglue.c
1 /******************************************************************************
2  *
3  * Module Name: osbarrelfishxf - Barrelfish OSL interfaces
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (c) 2008, 2010, ETH Zurich.
9  * All rights reserved.
10  *
11  * This file is distributed under the terms in the attached LICENSE file.
12  * If you do not find this file, copies can be found by writing to:
13  * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
14  */
15
16 /*****************************************************************
17  * Debug printer and its power-switch:
18  *****************************************************************/
19
20 #include "acpi_shared.h"
21 #include "acpi_debug.h"
22 #include <barrelfish/deferred.h>
23
24
25 /******************************************************************************
26  *
27  * 1. Copyright Notice
28  *
29  * Some or all of this work - Copyright (c) 1999 - 2008, Intel Corp.
30  * All rights reserved.
31  *
32  * 2. License
33  *
34  * 2.1. This is your license from Intel Corp. under its intellectual property
35  * rights.  You may have additional license terms from the party that provided
36  * you this software, covering your right to use that party's intellectual
37  * property rights.
38  *
39  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
40  * copy of the source code appearing in this file ("Covered Code") an
41  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
42  * base code distributed originally by Intel ("Original Intel Code") to copy,
43  * make derivatives, distribute, use and display any portion of the Covered
44  * Code in any form, with the right to sublicense such rights; and
45  *
46  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
47  * license (with the right to sublicense), under only those claims of Intel
48  * patents that are infringed by the Original Intel Code, to make, use, sell,
49  * offer to sell, and import the Covered Code and derivative works thereof
50  * solely to the minimum extent necessary to exercise the above copyright
51  * license, and in no event shall the patent license extend to any additions
52  * to or modifications of the Original Intel Code.  No other license or right
53  * is granted directly or by implication, estoppel or otherwise;
54  *
55  * The above copyright and patent license is granted only if the following
56  * conditions are met:
57  *
58  * 3. Conditions
59  *
60  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
61  * Redistribution of source code of any substantial portion of the Covered
62  * Code or modification with rights to further distribute source must include
63  * the above Copyright Notice, the above License, this list of Conditions,
64  * and the following Disclaimer and Export Compliance provision.  In addition,
65  * Licensee must cause all Covered Code to which Licensee contributes to
66  * contain a file documenting the changes Licensee made to create that Covered
67  * Code and the date of any change.  Licensee must include in that file the
68  * documentation of any changes made by any predecessor Licensee.  Licensee
69  * must include a prominent statement that the modification is derived,
70  * directly or indirectly, from Original Intel Code.
71  *
72  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
73  * Redistribution of source code of any substantial portion of the Covered
74  * Code or modification without rights to further distribute source must
75  * include the following Disclaimer and Export Compliance provision in the
76  * documentation and/or other materials provided with distribution.  In
77  * addition, Licensee may not authorize further sublicense of source of any
78  * portion of the Covered Code, and must include terms to the effect that the
79  * license from Licensee to its licensee is limited to the intellectual
80  * property embodied in the software Licensee provides to its licensee, and
81  * not to intellectual property embodied in modifications its licensee may
82  * make.
83  *
84  * 3.3. Redistribution of Executable. Redistribution in executable form of any
85  * substantial portion of the Covered Code or modification must reproduce the
86  * above Copyright Notice, and the following Disclaimer and Export Compliance
87  * provision in the documentation and/or other materials provided with the
88  * distribution.
89  *
90  * 3.4. Intel retains all right, title, and interest in and to the Original
91  * Intel Code.
92  *
93  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
94  * Intel shall be used in advertising or otherwise to promote the sale, use or
95  * other dealings in products derived from or relating to the Covered Code
96  * without prior written authorization from Intel.
97  *
98  * 4. Disclaimer and Export Compliance
99  *
100  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
101  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
102  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
103  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
104  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
105  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
106  * PARTICULAR PURPOSE.
107  *
108  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
109  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
110  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
111  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
112  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
113  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
114  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
115  * LIMITED REMEDY.
116  *
117  * 4.3. Licensee shall not export, either directly or indirectly, any of this
118  * software or system incorporating such software without first obtaining any
119  * required license or other approval from the U. S. Department of Commerce or
120  * any other agency or department of the United States Government.  In the
121  * event Licensee exports any such software from the United States or
122  * re-exports any such software from a foreign destination, Licensee shall
123  * ensure that the distribution and export/re-export of the software is in
124  * compliance with all laws, regulations, orders, or other restrictions of the
125  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
126  * any of its subsidiaries will export/re-export any technical data, process,
127  * software, or service, directly or indirectly, to any country for which the
128  * United States government or any agency thereof requires an export license,
129  * other governmental approval, or letter of assurance, without first obtaining
130  * such license, approval or letter.
131  *
132  *****************************************************************************/
133
134 #include <stdio.h>
135 #include <stdlib.h>
136 #include <barrelfish/barrelfish.h>
137 #include <barrelfish/dispatch.h>
138 #include <barrelfish/inthandler.h>
139
140 #include <acpi.h>
141 #include <accommon.h>
142 #include <amlcode.h>
143 #include <acparser.h>
144 #include <acdebug.h>
145
146 #include <pci/confspace/pci_confspace.h>
147 #include <pci/confspace/mackerelpci.h>
148
149 #include <mm/mm.h>
150
151 #define _COMPONENT          ACPI_OS_SERVICES
152         ACPI_MODULE_NAME    ("osbarrelfishxf")
153
154 //extern FILE *AcpiGbl_DebugFile;
155 static FILE *AcpiGbl_OutputFile;
156
157 /******************************************************************************
158  *
159  * FUNCTION:    AcpiOsInitialize, AcpiOsTerminate
160  *
161  * PARAMETERS:  None
162  *
163  * RETURN:      Status
164  *
165  * DESCRIPTION: Init and terminate.  Nothing to do.
166  *
167  *****************************************************************************/
168
169 ACPI_STATUS
170 AcpiOsInitialize (void)
171 {
172     AcpiGbl_OutputFile = stdout;
173     return AE_OK;
174 }
175
176
177 ACPI_STATUS
178 AcpiOsTerminate (void)
179 {
180     return AE_OK;
181 }
182
183
184 /******************************************************************************
185  *
186  * FUNCTION:    AcpiOsGetRootPointer
187  *
188  * PARAMETERS:  None
189  *
190  * RETURN:      RSDP physical address
191  *
192  * DESCRIPTION: Gets the root pointer (RSDP)
193  *
194  *****************************************************************************/
195
196 static ACPI_PHYSICAL_ADDRESS acpi_root_pointer = 0;
197
198 ACPI_PHYSICAL_ADDRESS
199 AcpiOsGetRootPointer (
200     void)
201 {
202     if (acpi_root_pointer != 0) {
203         return acpi_root_pointer;
204     }
205     ACPI_PHYSICAL_ADDRESS physaddr;
206     ACPI_STATUS as = AcpiFindRootPointer(&physaddr);
207     if (as == AE_OK) {
208         return physaddr;
209     } else {
210         return 0;
211     }
212 }
213
214 void
215 AcpiOsSetRootPointer (
216         ACPI_PHYSICAL_ADDRESS physaddr)
217 {
218     acpi_root_pointer = physaddr;
219 }
220
221
222 /******************************************************************************
223  *
224  * FUNCTION:    AcpiOsPredefinedOverride
225  *
226  * PARAMETERS:  InitVal     - Initial value of the predefined object
227  *              NewVal      - The new value for the object
228  *
229  * RETURN:      Status, pointer to value.  Null pointer returned if not
230  *              overriding.
231  *
232  * DESCRIPTION: Allow the OS to override predefined names
233  *
234  *****************************************************************************/
235
236 ACPI_STATUS
237 AcpiOsPredefinedOverride (
238     const ACPI_PREDEFINED_NAMES *InitVal,
239     ACPI_STRING                 *NewVal)
240 {
241
242     if (!InitVal || !NewVal)
243     {
244         return (AE_BAD_PARAMETER);
245     }
246
247     *NewVal = NULL;
248     return (AE_OK);
249 }
250
251
252 /******************************************************************************
253  *
254  * FUNCTION:    AcpiOsTableOverride
255  *
256  * PARAMETERS:  ExistingTable   - Header of current table (probably firmware)
257  *              NewTable        - Where an entire new table is returned.
258  *
259  * RETURN:      Status, pointer to new table.  Null pointer returned if no
260  *              table is available to override
261  *
262  * DESCRIPTION: Return a different version of a table if one is available
263  *
264  *****************************************************************************/
265
266 ACPI_STATUS
267 AcpiOsTableOverride (
268     ACPI_TABLE_HEADER       *ExistingTable,
269     ACPI_TABLE_HEADER       **NewTable)
270 {
271
272     if (!ExistingTable || !NewTable)
273     {
274         return (AE_BAD_PARAMETER);
275     }
276
277     *NewTable = NULL;
278
279 #ifdef ACPI_EXEC_APP
280
281     AeTableOverride (ExistingTable, NewTable);
282     return (AE_OK);
283 #else
284     return AE_NO_ACPI_TABLES;
285 #endif
286 }
287
288
289 /******************************************************************************
290  *
291  * FUNCTION:    AcpiOsReadable
292  *
293  * PARAMETERS:  Pointer             - Area to be verified
294  *              Length              - Size of area
295  *
296  * RETURN:      TRUE if readable for entire length
297  *
298  * DESCRIPTION: Verify that a pointer is valid for reading
299  *
300  *****************************************************************************/
301
302 BOOLEAN
303 AcpiOsReadable (
304     void                    *Pointer,
305     ACPI_SIZE               Length)
306 {
307
308     return (TRUE);
309 }
310
311
312 /******************************************************************************
313  *
314  * FUNCTION:    AcpiOsWritable
315  *
316  * PARAMETERS:  Pointer             - Area to be verified
317  *              Length              - Size of area
318  *
319  * RETURN:      TRUE if writable for entire length
320  *
321  * DESCRIPTION: Verify that a pointer is valid for writing
322  *
323  *****************************************************************************/
324
325 BOOLEAN
326 AcpiOsWritable (
327     void                    *Pointer,
328     ACPI_SIZE               Length)
329 {
330
331     return (TRUE);
332 }
333
334
335 /******************************************************************************
336  *
337  * FUNCTION:    AcpiOsRedirectOutput
338  *
339  * PARAMETERS:  Destination         - An open file handle/pointer
340  *
341  * RETURN:      None
342  *
343  * DESCRIPTION: Causes redirect of AcpiOsPrintf and AcpiOsVprintf
344  *
345  *****************************************************************************/
346
347 void
348 AcpiOsRedirectOutput (
349     void                    *Destination)
350 {
351
352     AcpiGbl_OutputFile = Destination;
353 }
354
355
356 /******************************************************************************
357  *
358  * FUNCTION:    AcpiOsPrintf
359  *
360  * PARAMETERS:  fmt, ...            Standard printf format
361  *
362  * RETURN:      None
363  *
364  * DESCRIPTION: Formatted output
365  *
366  *****************************************************************************/
367
368 void ACPI_INTERNAL_VAR_XFACE
369 AcpiOsPrintf (
370     const char              *Fmt,
371     ...)
372 {
373     va_list                 Args;
374
375
376     va_start (Args, Fmt);
377
378 #ifdef ACPI_BF_DEBUG
379     AcpiOsVprintf (Fmt, Args);
380 #endif
381
382     va_end (Args);
383     return;
384 }
385
386
387 /******************************************************************************
388  *
389  * FUNCTION:    AcpiOsVprintf
390  *
391  * PARAMETERS:  fmt                 Standard printf format
392  *              args                Argument list
393  *
394  * RETURN:      None
395  *
396  * DESCRIPTION: Formatted output with argument list pointer
397  *
398  *****************************************************************************/
399
400 void
401 AcpiOsVprintf (
402     const char              *Fmt,
403     va_list                 Args)
404 {
405     INT32                   Count = 0;
406     UINT8                   Flags;
407
408
409     Flags = AcpiGbl_DbOutputFlags;
410     if (Flags & ACPI_DB_REDIRECTABLE_OUTPUT)
411     {
412         /* Output is directable to either a file (if open) or the console */
413
414 #if 0
415         if (AcpiGbl_DebugFile)
416         {
417             /* Output file is open, send the output there */
418
419             Count = vfprintf (AcpiGbl_DebugFile, Fmt, Args);
420         }
421         else
422 #endif
423         {
424             /* No redirection, send output to console (once only!) */
425
426             Flags |= ACPI_DB_CONSOLE_OUTPUT;
427         }
428     }
429
430 #ifdef ACPI_BF_DEBUG
431
432     if (Flags & ACPI_DB_CONSOLE_OUTPUT)
433     {
434         Count = vfprintf (AcpiGbl_OutputFile, Fmt, Args);
435     }
436
437 #else
438
439     Count = 0;
440
441 #endif
442
443     return;
444 }
445
446
447 /******************************************************************************
448  *
449  * FUNCTION:    AcpiOsGetLine
450  *
451  * PARAMETERS:  fmt                 Standard printf format
452  *              args                Argument list
453  *
454  * RETURN:      Actual bytes read
455  *
456  * DESCRIPTION: Formatted input with argument list pointer
457  *
458  *****************************************************************************/
459
460 UINT32
461 AcpiOsGetLine (
462     char                    *Buffer,
463     UINT32                  BufferLength,
464     UINT32                  *BytesRead)
465 {
466     assert(!"NYI: AcpiOsGetLine");
467     return 0;
468 #if 0
469     UINT8                   Temp;
470     UINT32                  i;
471
472
473     for (i = 0; ; i++)
474     {
475         scanf ("%1c", &Temp);
476         if (!Temp || Temp == '\n')
477         {
478             break;
479         }
480
481         Buffer [i] = Temp;
482     }
483
484     /* Null terminate the buffer */
485
486     Buffer [i] = 0;
487
488     /* Return the number of bytes in the string */
489
490     return (i);
491 #endif
492 }
493
494 /******************************************************************************
495  *
496  * FUNCTION:    AcpiOsMapMemory
497  *
498  * PARAMETERS:  where               Physical address of memory to be mapped
499  *              length              How much memory to map
500  *
501  * RETURN:      Pointer to mapped memory.  Null on error.
502  *
503  * DESCRIPTION: Map physical memory into caller's address space
504  *
505  *****************************************************************************/
506
507 struct AcpiMapping {
508     struct memobj_anon *memobj;
509     struct vregion *vregion;
510     lpaddr_t pbase;
511     ACPI_SIZE length;
512     unsigned refcount;
513     struct capref *caps;
514     size_t num_caps;
515     struct AcpiMapping *next;
516 };
517
518 static struct AcpiMapping *head = NULL;
519
520 #if 0
521 static void dump_map_list(void)
522 {
523     for (struct AcpiMapping *walk = head; walk; walk = walk->next)
524     {
525         printf("mapped region: pbase = 0x%"PRIxLPADDR"\n"
526                "               vbase = 0x%"PRIxGENVADDR"\n"
527                "               size  = %zd\n"
528                "               refc  = %u\n",
529                walk->pbase,
530                vregion_get_base_addr(walk->vregion),
531                walk->length,
532                walk->refcount);
533     }
534 }
535 #endif
536
537 void *
538 AcpiOsMapMemory (
539     ACPI_PHYSICAL_ADDRESS   where,  /* not page aligned */
540     ACPI_SIZE               length) /* in bytes, not page-aligned */
541 {
542     ACPI_DEBUG("AcpiOsMapMemory where=0x%016lx, length=%lu\n", where, length);
543     errval_t err;
544     //printf("AcpiOsMapMemory: 0x%"PRIxLPADDR", %lu\n", where, length);
545     lpaddr_t pbase = where & (~BASE_PAGE_MASK);
546     length += where - pbase;
547     length = ROUND_UP(length, BASE_PAGE_SIZE);
548     int npages = DIVIDE_ROUND_UP(length, BASE_PAGE_SIZE);
549     lpaddr_t pend  = pbase + length;
550
551     ACPI_DEBUG("AcpiOsMapMemory: aligned request: 0x%"PRIxLPADDR", %d\n", pbase, npages);
552
553     struct capref am_pages[npages];
554     memset(&am_pages, 0, npages*sizeof(struct capref));
555
556     for (struct AcpiMapping *walk = head; walk; walk = walk->next) {
557         lpaddr_t walk_end = walk->pbase + walk->length;
558         if (walk->pbase <= pbase && walk_end >= pend) {
559             walk->refcount++;
560             return (void*)(uintptr_t)vregion_get_base_addr(walk->vregion) + (where-walk->pbase);
561         }
562         // overlapping map requests
563         else if (walk->pbase >= pbase && walk_end <= pend) {
564             //printf("old mapping inside request\n");
565             // new request contains old mapping
566             //        |---| walk
567             // |---------------| new mapping
568             size_t first = (walk->pbase - pbase) / BASE_PAGE_SIZE;
569             // printf("pbase = 0x%"PRIxGENPADDR", walk->pbase = 0x%"PRIxGENPADDR"\n", pbase, walk->pbase);
570             // printf("npages = %d, walk->npages = %zd\n", npages, walk->num_caps);
571             // printf("caps %zd - %zd already retyped\n", first, first + walk->num_caps-1);
572             for (int c = 0; c < walk->num_caps; c++) {
573                 am_pages[first + c] = walk->caps[c];
574             }
575         }
576         else if (walk->pbase < pbase && walk_end > pbase && walk_end < pend) {
577             //printf("old mapping at beginning of new request\n");
578             // new request overlaps end of old mapping-->walk_end < pend
579             // |--------| walk
580             //       |--------------| new mapping
581             size_t overlap_count = (walk_end - pbase) / BASE_PAGE_SIZE;
582             //printf("pbase = 0x%"PRIxGENPADDR", walk->pbase = 0x%"PRIxGENPADDR"\n", pbase, walk->pbase);
583             //printf("npages = %d, walk->npages = %zd\n", npages, walk->num_caps);
584             //printf("caps %d - %zd already retyped\n", 0, overlap_count - 1);
585             for (int c = 0; c < overlap_count; c++) {
586                 am_pages[c] = walk->caps[walk->num_caps - overlap_count + c];
587             }
588         }
589         else if (walk->pbase > pbase && walk->pbase < pend && walk_end > pend) {
590             //printf("old mapping at end of new request\n");
591             // new request overlaps beginning of old mapping
592             //               |-----| walk
593             // |---------------| new mapping
594             size_t first = (pend - walk->pbase) / BASE_PAGE_SIZE;
595             size_t overlap_count = npages - first;
596             //printf("pbase = 0x%"PRIxGENPADDR", walk->pbase = 0x%"PRIxGENPADDR"\n", pbase, walk->pbase);
597             //printf("npages = %d, walk->npages = %zd\n", npages, walk->num_caps);
598             //printf("caps %zd - %zd already retyped\n", first, first + overlap_count - 1);
599             for (int c = 0; c < overlap_count; c++) {
600                 am_pages[first + c] =  walk->caps[c];
601             }
602         }
603     }
604
605     struct memobj_anon *memobj = malloc(sizeof(struct memobj_anon));
606     assert(memobj);
607     struct vregion *vregion = malloc(sizeof(struct vregion));
608     assert(vregion);
609     err = memobj_create_anon(memobj, length, 0);
610     if (err_is_fail(err)) {
611         DEBUG_ERR(err, "memobj_create_anon failed");
612         return NULL;
613     }
614     err = vregion_map(vregion, get_current_vspace(), &memobj->m, 0, length,
615                       VREGION_FLAGS_READ_WRITE);
616     if (err_is_fail(err)) {
617         DEBUG_ERR(err, "vregion_map failed");
618         return NULL;
619     }
620     ACPI_DEBUG("%s: Mapping %#"PRIxLPADDR" at %#"PRIxGENVADDR"\n",
621             __FUNCTION__, pbase, vregion_get_base_addr(vregion));
622
623     struct AcpiMapping *new = malloc(sizeof(struct AcpiMapping));
624     new->num_caps = npages;
625     new->caps = calloc(npages, sizeof(struct capref));
626     for (int page = 0; page < npages; page++) {
627
628         if (capref_is_null(am_pages[page])) {
629             lpaddr_t paddr = pbase + page * BASE_PAGE_SIZE;
630
631             ACPI_DEBUG("%s: allocating page for %#"PRIxLPADDR"\n",
632                     __FUNCTION__, paddr);
633
634             err = mm_realloc_range(&pci_mm_physaddr, BASE_PAGE_BITS, paddr,
635                     &new->caps[page]);
636             if (err_is_fail(err)) {
637                 free(new->caps);
638                 free(new);
639                 DEBUG_ERR(err, "AcpiOsMapMemory: allocating RAM at %lx failed\n",
640                         paddr);
641                 return NULL;
642             }
643             /* result of mm_realloc_range is already DevFrame */
644         }
645         else {
646             ACPI_DEBUG("%s: already have page for %#"PRIxLPADDR"\n",
647                     __FUNCTION__, pbase + page * BASE_PAGE_SIZE);
648
649             // Create a copy of the cap so we don't accidentally kill more
650             // than one mapping in AcpiOsUnmapMemory()
651             err = slot_alloc(&new->caps[page]);
652             if (err_is_fail(err)) {
653                 DEBUG_ERR(err, "slot_alloc for copy of page");
654                 // XXX: TODO: cleanup previous pages
655                 free(new->caps);
656                 free(new);
657                 return NULL;
658             }
659             err = cap_copy(new->caps[page], am_pages[page]);
660             if (err_is_fail(err)) {
661                 DEBUG_ERR(err, "slot_alloc for copy of page");
662                 // XXX: TODO: cleanup previous pages
663                 slot_free(new->caps[page]);
664                 free(new->caps);
665                 free(new);
666                 return NULL;
667             }
668         }
669
670         err = memobj->m.f.fill(&memobj->m, page * BASE_PAGE_SIZE, new->caps[page],
671                 BASE_PAGE_SIZE);
672         if (err_is_fail(err)) {
673             DEBUG_ERR(err, "AcpiOsMapMemory: memobj fill failed: %s.",
674                     err_getstring(err_no(err)));
675             // XXX: TODO: cleanup
676             return NULL;
677         }
678         assert(err == 0);
679         err = memobj->m.f.pagefault(&memobj->m, vregion, page * BASE_PAGE_SIZE, 0);
680         if (err_is_fail(err)) {
681             DEBUG_ERR(err, "AcpiOsMapMemory: memobj pagefault failed: %s.",
682                     err_getstring(err_no(err)));
683             // XXX: TODO: cleanup
684             return NULL;
685         }
686         assert(err == 0);
687     }
688
689     // add new mapping to tracking list
690     new->memobj = memobj;
691     new->vregion = vregion;
692     new->pbase = pbase;
693     new->length = length;
694     new->refcount = 1;
695     new->next = head;
696     head = new;
697
698     return (void*)(uintptr_t)vregion_get_base_addr(vregion) + (where - pbase);
699 }
700
701
702 /******************************************************************************
703  *
704  * FUNCTION:    AcpiOsUnmapMemory
705  *
706  * PARAMETERS:  where               Logical address of memory to be unmapped
707  *              length              How much memory to unmap
708  *
709  * RETURN:      None.
710  *
711  * DESCRIPTION: Delete a previously created mapping.  Where and Length must
712  *              correspond to a previous mapping exactly.
713  *
714  *****************************************************************************/
715
716 void
717 AcpiOsUnmapMemory (
718     void                    *where,
719     ACPI_SIZE               length)
720 {
721     ACPI_DEBUG("%s: %p %zd\n", __FUNCTION__, where, (size_t)length);
722
723     uintptr_t vbase = (uintptr_t)where & (~BASE_PAGE_MASK);
724     length = ROUND_UP(length, BASE_PAGE_SIZE);
725
726     ACPI_DEBUG("%s: aligned request: %#"PRIxPTR", %zu pages\n",
727             __FUNCTION__, vbase, length / BASE_PAGE_SIZE);
728
729     // printf("AcpiOsUnmapMemory: 0x%lx, %ld\n", vbase, length / BASE_PAGE_SIZE);
730
731     // printf("unmap 0x%lx %zd\n", vbase, length);
732     // printf("vend 0x%lx\n", vbase + length);
733
734     assert(head); // there should be a mapped region if Unmap is called
735
736     struct AcpiMapping *prev = NULL;
737     errval_t err;
738     for (struct AcpiMapping *walk = head; walk; prev = walk, walk = walk->next) {
739         genvaddr_t walk_vaddr = vregion_get_base_addr(walk->vregion);
740         genvaddr_t walk_end   = walk_vaddr + walk->length;
741         // printf("0x%"PRIxGENVADDR", 0x%"PRIxGENVADDR"\n", walk_vaddr, walk_end);
742         if (walk_vaddr <= vbase && walk_end >= vbase + length) {
743             ACPI_DEBUG("region: %#"PRIxGENVADDR", %zu pages\n",
744                     walk_vaddr, walk->length / BASE_PAGE_SIZE);
745             // printf("match\n");
746             walk->refcount--;
747             if (!walk->refcount) {
748                 ACPI_DEBUG("%s: last reference to region, cleaning up\n", __FUNCTION__);
749
750                 // Remove from list
751                 if (prev) {
752                     prev->next = walk->next;
753                 }
754                 else { // we were head
755                     head = walk->next;
756                 }
757
758                 // Delete vregion; do this first because vnode_unmap complains
759                 // about missing caps if we mm_free() the backing caps first
760                 err = vregion_destroy(walk->vregion);
761                 if (err_is_fail(err)) {
762                     DEBUG_ERR(err, "%s: vregion_destroy", __FUNCTION__);
763                 }
764
765                 // return backing caps to MM
766                 for (int page = 0; page < walk->num_caps; page++) {
767                     lpaddr_t pagebase = walk->pbase + page * BASE_PAGE_SIZE;
768                     err = mm_free(&pci_mm_physaddr, walk->caps[page],
769                             pagebase, BASE_PAGE_BITS);
770                     if (err_is_fail(err)) {
771                         DEBUG_ERR(err, "mm_free()");
772                     }
773                 }
774
775                 // memobj destroy will fail as backing caps are already
776                 // deleted, so we don't check errors.
777                 memobj_destroy_anon((struct memobj *)walk->memobj, false);
778
779                 // Free malloc'd memory for element
780                 free(walk->vregion);
781                 free(walk->memobj);
782                 free(walk->caps);
783                 free(walk);
784
785                 return;
786             }
787         }
788     }
789 }
790
791
792 /******************************************************************************
793  *
794  * FUNCTION:    AcpiOsAllocate
795  *
796  * PARAMETERS:  Size                Amount to allocate, in bytes
797  *
798  * RETURN:      Pointer to the new allocation.  Null on error.
799  *
800  * DESCRIPTION: Allocate memory.  Algorithm is dependent on the OS.
801  *
802  *****************************************************************************/
803
804 void *
805 AcpiOsAllocate (
806     ACPI_SIZE               size)
807 {
808     void                    *Mem;
809
810
811     Mem = (void *) malloc ((size_t) size);
812
813     return Mem;
814 }
815
816
817 /******************************************************************************
818  *
819  * FUNCTION:    AcpiOsFree
820  *
821  * PARAMETERS:  mem                 Pointer to previously allocated memory
822  *
823  * RETURN:      None.
824  *
825  * DESCRIPTION: Free memory allocated via AcpiOsAllocate
826  *
827  *****************************************************************************/
828
829 void
830 AcpiOsFree (
831     void                    *mem)
832 {
833     free(mem);
834 }
835
836
837 /******************************************************************************
838  *
839  * FUNCTION:    AcpiOsCreateSemaphore
840  *
841  * PARAMETERS:  InitialUnits        - Units to be assigned to the new semaphore
842  *              OutHandle           - Where a handle will be returned
843  *
844  * RETURN:      Status
845  *
846  * DESCRIPTION: Create an OS semaphore
847  *
848  *****************************************************************************/
849
850 ACPI_STATUS
851 AcpiOsCreateSemaphore (
852     UINT32              MaxUnits,
853     UINT32              InitialUnits,
854     ACPI_HANDLE         *OutHandle)
855 {
856     struct thread_sem *sem = malloc(sizeof(struct thread_sem));
857     assert(sem != NULL);
858     thread_sem_init(sem, InitialUnits);
859     *OutHandle = sem;
860     return AE_OK;
861 }
862
863 /******************************************************************************
864  *
865  * FUNCTION:    AcpiOsDeleteSemaphore
866  *
867  * PARAMETERS:  Handle              - Handle returned by AcpiOsCreateSemaphore
868  *
869  * RETURN:      Status
870  *
871  * DESCRIPTION: Delete an OS semaphore
872  *
873  *****************************************************************************/
874
875 ACPI_STATUS
876 AcpiOsDeleteSemaphore (
877     ACPI_HANDLE         Handle)
878 {
879
880     if (!Handle)
881     {
882         return AE_BAD_PARAMETER;
883     }
884
885     free(Handle);
886     return AE_OK;
887 }
888
889
890 /******************************************************************************
891  *
892  * FUNCTION:    AcpiOsWaitSemaphore
893  *
894  * PARAMETERS:  Handle              - Handle returned by AcpiOsCreateSemaphore
895  *              Units               - How many units to wait for
896  *              Timeout             - How long to wait
897  *
898  * RETURN:      Status
899  *
900  * DESCRIPTION: Wait for units
901  *
902  *****************************************************************************/
903
904 ACPI_STATUS
905 AcpiOsWaitSemaphore (
906     ACPI_HANDLE         Handle,
907     UINT32              Units,
908     UINT16              Timeout)
909 {
910     if(Units != 1) {
911         USER_PANIC("AcpiOsWaitSemaphore called with Units != 1");
912     }
913
914     if (Timeout == ACPI_DO_NOT_WAIT) {
915         bool ok = thread_sem_trywait(Handle);
916         return ok ? AE_OK : AE_TIME;
917     } else {
918         assert(Timeout == ACPI_WAIT_FOREVER); // no timeout
919         thread_sem_wait(Handle);
920         return AE_OK;
921     }
922 }
923
924
925 /******************************************************************************
926  *
927  * FUNCTION:    AcpiOsSignalSemaphore
928  *
929  * PARAMETERS:  Handle              - Handle returned by AcpiOsCreateSemaphore
930  *              Units               - Number of units to send
931  *
932  * RETURN:      Status
933  *
934  * DESCRIPTION: Send units
935  *
936  *****************************************************************************/
937
938 ACPI_STATUS
939 AcpiOsSignalSemaphore (
940     ACPI_HANDLE         Handle,
941     UINT32              Units)
942 {
943     if(Units != 1) {
944         USER_PANIC("AcpiOsSignalSemaphore called with Units != 1");
945     }
946     thread_sem_post(Handle);
947     return AE_OK;
948 }
949
950
951 ACPI_STATUS
952 AcpiOsCreateLock (
953     ACPI_SPINLOCK           *OutHandle)
954 {
955     spinlock_t *lock = malloc(sizeof(spinlock_t));
956     assert(lock != NULL);
957     *lock = 0;
958     *OutHandle = (void *)lock;
959     return AE_OK;
960 }
961
962 void
963 AcpiOsDeleteLock (
964     ACPI_SPINLOCK           Handle)
965 {
966     free((void *)Handle);
967 }
968
969
970 ACPI_CPU_FLAGS
971 AcpiOsAcquireLock (
972     ACPI_HANDLE             Handle)
973 {
974     acquire_spinlock((spinlock_t *)Handle);
975     return (0);
976 }
977
978
979 void
980 AcpiOsReleaseLock (
981     ACPI_SPINLOCK           Handle,
982     ACPI_CPU_FLAGS          Flags)
983 {
984     release_spinlock(Handle);
985 }
986
987
988 /******************************************************************************
989  *
990  * FUNCTION:    AcpiOsInstallInterruptHandler
991  *
992  * PARAMETERS:  InterruptNumber     Level handler should respond to.
993  *              Isr                 Address of the ACPI interrupt handler
994  *              ExceptPtr           Where status is returned
995  *
996  * RETURN:      Handle to the newly installed handler.
997  *
998  * DESCRIPTION: Install an interrupt handler.  Used to install the ACPI
999  *              OS-independent handler.
1000  *
1001  *****************************************************************************/
1002
1003 struct interrupt_closure {
1004     ACPI_OSD_HANDLER handler;
1005     void *context;
1006 };
1007
1008 static void interrupt_wrapper(void *arg)
1009 {
1010     struct interrupt_closure *ic = arg;
1011     printf("ACPI: interrupt!\n");
1012     ic->handler(ic->context); /* discards return value... what's it for? */
1013 }
1014
1015 UINT32
1016 AcpiOsInstallInterruptHandler (
1017     UINT32                  InterruptNumber,
1018     ACPI_OSD_HANDLER        ServiceRoutine,
1019     void                    *Context)
1020 {
1021     ACPI_DEBUG("AcpiOsInstallInterruptHandler(%"PRIu32")\n", (uint32_t)InterruptNumber);
1022
1023     struct interrupt_closure *ic = malloc(sizeof(struct interrupt_closure));
1024     assert(ic != NULL);
1025
1026     ic->handler = ServiceRoutine;
1027     ic->context = Context;
1028
1029     uint64_t vector;
1030     errval_t e = inthandler_setup(interrupt_wrapper, ic, &vector);
1031     ACPI_DEBUG("Allocated local vec %"PRIu64"\n", vector);
1032     if (err_is_fail(e)) {
1033         DEBUG_ERR(e, "failed to setup handler function/vector");
1034         return AE_ERROR;
1035     }
1036     
1037     // The enable and route interrupt call expects interrupt number that are
1038     // based on 32 (which is the first int number above the exceptions)
1039     e = enable_and_route_interrupt(InterruptNumber, disp_get_core_id(), vector-32);
1040     if (err_is_fail(e)) {
1041         DEBUG_ERR(e, "failed to route interrupt");
1042         return AE_ERROR;
1043     }
1044
1045     return AE_OK;
1046 }
1047
1048 /******************************************************************************
1049  *
1050  * FUNCTION:    AcpiOsRemoveInterruptHandler
1051  *
1052  * PARAMETERS:  Handle              Returned when handler was installed
1053  *
1054  * RETURN:      Status
1055  *
1056  * DESCRIPTION: Uninstalls an interrupt handler.
1057  *
1058  *****************************************************************************/
1059
1060 ACPI_STATUS
1061 AcpiOsRemoveInterruptHandler (
1062     UINT32                  InterruptNumber,
1063     ACPI_OSD_HANDLER        ServiceRoutine)
1064 {
1065     assert(!"NYI: AcpiOsRemoveInterruptHandler");
1066     return AE_OK;
1067 }
1068
1069
1070 /******************************************************************************
1071  *
1072  * FUNCTION:    AcpiOsExecute
1073  *
1074  * PARAMETERS:  Type            - Type of execution
1075  *              Function        - Address of the function to execute
1076  *              Context         - Passed as a parameter to the function
1077  *
1078  * RETURN:      Status.
1079  *
1080  * DESCRIPTION: Execute a new thread
1081  *
1082  *****************************************************************************/
1083
1084 ACPI_STATUS
1085 AcpiOsExecute (
1086     ACPI_EXECUTE_TYPE       Type,
1087     ACPI_OSD_EXEC_CALLBACK  Function,
1088     void                    *Context)
1089 {
1090     struct thread *thread = thread_create((thread_func_t)Function, Context);
1091     errval_t err = thread_detach(thread);
1092     assert(err_is_ok(err));
1093     return (thread == NULL);
1094 }
1095
1096
1097 /******************************************************************************
1098  *
1099  * FUNCTION:    AcpiOsBreakpoint
1100  *
1101  * PARAMETERS:  Msg                 Message to print
1102  *
1103  * RETURN:      Status
1104  *
1105  * DESCRIPTION: Print a message and break to the debugger.
1106  *
1107  *****************************************************************************/
1108
1109 #if 0 /* unused, undefined -AB */
1110 ACPI_STATUS
1111 AcpiOsBreakpoint (
1112     char                    *Msg)
1113 {
1114
1115     if (Msg)
1116     {
1117         AcpiOsPrintf ("AcpiOsBreakpoint: %s ****\n", Msg);
1118     }
1119     else
1120     {
1121         AcpiOsPrintf ("At AcpiOsBreakpoint ****\n");
1122     }
1123
1124     return AE_OK;
1125 }
1126 #endif
1127
1128
1129 /******************************************************************************
1130  *
1131  * FUNCTION:    AcpiOsStall
1132  *
1133  * PARAMETERS:  microseconds        To sleep
1134  *
1135  * RETURN:      Blocks until sleep is completed.
1136  *
1137  * DESCRIPTION: Sleep at microsecond granularity
1138  *
1139  *****************************************************************************/
1140
1141 void
1142 AcpiOsStall (
1143     UINT32                  microseconds)
1144 {
1145
1146     if (microseconds)
1147     {
1148         errval_t err;
1149         err = barrelfish_usleep(microseconds);
1150         if (err_is_fail(err)) {
1151             DEBUG_ERR(err, "barrelfish_usleep(%"PRIu32") in %s",
1152                     microseconds, __FUNCTION__);
1153         }
1154     }
1155     return;
1156 }
1157
1158
1159 /******************************************************************************
1160  *
1161  * FUNCTION:    AcpiOsSleep
1162  *
1163  * PARAMETERS:  milliseconds        To sleep
1164  *
1165  * RETURN:      Blocks until sleep is completed.
1166  *
1167  * DESCRIPTION: Sleep at millisecond granularity
1168  *
1169  *****************************************************************************/
1170
1171 void
1172 AcpiOsSleep (
1173     ACPI_INTEGER            milliseconds)
1174 {
1175
1176     if (milliseconds > 0) {
1177         assert(!"NYI: AcpiOsSleep");
1178     }
1179
1180     return;
1181 }
1182
1183 /******************************************************************************
1184  *
1185  * FUNCTION:    AcpiOsGetTimer
1186  *
1187  * PARAMETERS:  None
1188  *
1189  * RETURN:      Current time in 100 nanosecond units
1190  *
1191  * DESCRIPTION: Get the current system time
1192  *
1193  *****************************************************************************/
1194
1195 UINT64
1196 AcpiOsGetTimer (void)
1197 {
1198     assert(!"NYI: AcpiOsGetTimer");
1199     return 0;
1200 #if 0
1201     struct timeval  time;
1202
1203     gettimeofday(&time, NULL);
1204
1205     /* Seconds * 10^7 = 100ns(10^-7), Microseconds(10^-6) * 10^1 = 100ns */
1206
1207     return (((UINT64) time.tv_sec * 10000000) + ((UINT64) time.tv_usec * 10));
1208 #endif
1209 }
1210
1211
1212
1213 /******************************************************************************
1214  *
1215  * FUNCTION:    AcpiOsReadPciConfiguration
1216  *
1217  * PARAMETERS:  PciId               Seg/Bus/Dev
1218  *              Register            Device Register
1219  *              Value               Buffer where value is placed
1220  *              Width               Number of bits
1221  *
1222  * RETURN:      Status
1223  *
1224  * DESCRIPTION: Read data from PCI configuration space
1225  *
1226  *****************************************************************************/
1227
1228 ACPI_STATUS
1229 AcpiOsReadPciConfiguration (
1230     ACPI_PCI_ID             *PciId,
1231     UINT32                  Register,
1232     UINT64                  *Value,
1233     UINT32                  Width)
1234 {
1235     mackerel_pci_t addr = {
1236         .bus = PciId->Bus,
1237         .device = PciId->Device,
1238         .function = PciId->Function,
1239     };
1240
1241     //printf("AcpiOsReadPciConfiguration(%d %d %d %d %d)\n",
1242     //       addr.bus, addr.device, addr.function, Register, Width);
1243
1244     switch (Width) {
1245     case 32:
1246         *(uint32_t *)Value = mackerel_read_pci_32(addr, Register);
1247         break;
1248
1249     case 16:
1250         *(uint16_t *)Value = mackerel_read_pci_16(addr, Register);
1251         break;
1252
1253     case 8:
1254         *(uint8_t *)Value = mackerel_read_pci_8(addr, Register);
1255         break;
1256
1257     default:
1258         return AE_ERROR;
1259     }
1260
1261     return AE_OK;
1262 }
1263
1264
1265 /******************************************************************************
1266  *
1267  * FUNCTION:    AcpiOsWritePciConfiguration
1268  *
1269  * PARAMETERS:  PciId               Seg/Bus/Dev
1270  *              Register            Device Register
1271  *              Value               Value to be written
1272  *              Width               Number of bits
1273  *
1274  * RETURN:      Status.
1275  *
1276  * DESCRIPTION: Write data to PCI configuration space
1277  *
1278  *****************************************************************************/
1279
1280 ACPI_STATUS
1281 AcpiOsWritePciConfiguration (
1282     ACPI_PCI_ID             *PciId,
1283     UINT32                  Register,
1284     ACPI_INTEGER            Value,
1285     UINT32                  Width)
1286 {
1287     mackerel_pci_t addr = {
1288         .bus = PciId->Bus,
1289         .device = PciId->Device,
1290         .function = PciId->Function,
1291     };
1292
1293     switch (Width) {
1294     case 32:
1295         mackerel_write_pci_32(addr, Register, Value);
1296         break;
1297
1298     case 16:
1299         mackerel_write_pci_16(addr, Register, Value);
1300         break;
1301
1302     case 8:
1303         mackerel_write_pci_8(addr, Register, Value);
1304         break;
1305
1306     default:
1307         return AE_ERROR;
1308     }
1309
1310     return AE_OK;
1311 }
1312
1313
1314 /******************************************************************************
1315  *
1316  * FUNCTION:    AcpiOsReadMemory
1317  *
1318  * PARAMETERS:  Address             Physical Memory Address to read
1319  *              Value               Where value is placed
1320  *              Width               Number of bits
1321  *
1322  * RETURN:      Value read from physical memory address
1323  *
1324  * DESCRIPTION: Read data from a physical memory address
1325  *
1326  *****************************************************************************/
1327
1328 ACPI_STATUS
1329 AcpiOsReadMemory (
1330     ACPI_PHYSICAL_ADDRESS   Address,
1331     UINT64                  *Value,
1332     UINT32                  Width)
1333 {
1334     assert(!"NYI: AcpiOsReadMemory");
1335
1336     switch (Width)
1337     {
1338     case 8:
1339     case 16:
1340     case 32:
1341         *Value = 0;
1342         break;
1343
1344     default:
1345         return (AE_BAD_PARAMETER);
1346         break;
1347     }
1348     return (AE_OK);
1349 }
1350
1351
1352 /******************************************************************************
1353  *
1354  * FUNCTION:    AcpiOsWriteMemory
1355  *
1356  * PARAMETERS:  Address             Physical Memory Address to write
1357  *              Value               Value to write
1358  *              Width               Number of bits
1359  *
1360  * RETURN:      None
1361  *
1362  * DESCRIPTION: Write data to a physical memory address
1363  *
1364  *****************************************************************************/
1365
1366 ACPI_STATUS
1367 AcpiOsWriteMemory (
1368     ACPI_PHYSICAL_ADDRESS   Address,
1369     UINT64                  Value,
1370     UINT32                  Width)
1371 {
1372     assert(!"NYI: AcpiOsWriteMemory");
1373     return (AE_OK);
1374 }
1375
1376
1377 ACPI_THREAD_ID
1378 AcpiOsGetThreadId(void)
1379 {
1380     return (ACPI_THREAD_ID)(uintptr_t)thread_self();
1381 }
1382
1383
1384 /******************************************************************************
1385  *
1386  * FUNCTION:    AcpiOsSignal
1387  *
1388  * PARAMETERS:  Function            ACPI CA signal function code
1389  *              Info                Pointer to function-dependent structure
1390  *
1391  * RETURN:      Status
1392  *
1393  * DESCRIPTION: Miscellaneous functions
1394  *
1395  *****************************************************************************/
1396
1397 ACPI_STATUS
1398 AcpiOsSignal (
1399     UINT32                  Function,
1400     void                    *Info)
1401 {
1402     assert(!"NYI: AcpiOsSignal");
1403
1404     switch (Function)
1405     {
1406     case ACPI_SIGNAL_FATAL:
1407         break;
1408
1409     case ACPI_SIGNAL_BREAKPOINT:
1410
1411         if (Info)
1412         {
1413             AcpiOsPrintf ("AcpiOsBreakpoint: %s ****\n", Info);
1414         }
1415         else
1416         {
1417             AcpiOsPrintf ("At AcpiOsBreakpoint ****\n");
1418         }
1419
1420         break;
1421     }
1422
1423
1424     return (AE_OK);
1425 }
1426
1427
1428 /*-
1429  * Copyright (c) 2000 Michael Smith
1430  * Copyright (c) 2000 BSDi
1431  * All rights reserved.
1432  *
1433  * Redistribution and use in source and binary forms, with or without
1434  * modification, are permitted provided that the following conditions
1435  * are met:
1436  * 1. Redistributions of source code must retain the above copyright
1437  *    notice, this list of conditions and the following disclaimer.
1438  * 2. Redistributions in binary form must reproduce the above copyright
1439  *    notice, this list of conditions and the following disclaimer in the
1440  *    documentation and/or other materials provided with the distribution.
1441  *
1442  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1443  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1444  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1445  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1446  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1447  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1448  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1449  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1450  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1451  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1452  * SUCH DAMAGE.
1453  */
1454
1455
1456 /* Section 5.2.9.1:  global lock acquire/release functions */
1457 #define GL_ACQUIRED     (-1)
1458 #define GL_BUSY         0
1459 #define GL_BIT_PENDING  0x1
1460 #define GL_BIT_OWNED    0x2
1461 #define GL_BIT_MASK     (GL_BIT_PENDING | GL_BIT_OWNED)
1462
1463 /*
1464  * Acquire the global lock.  If busy, set the pending bit.  The caller
1465  * will wait for notification from the BIOS that the lock is available
1466  * and then attempt to acquire it again.
1467  */
1468 int acpi_acquire_global_lock(uint32_t *lock)
1469 {
1470     uint32_t new, old;
1471
1472     do {
1473         old = *lock;
1474         new = ((old & ~GL_BIT_MASK) | GL_BIT_OWNED) |
1475                ((old >> 1) & GL_BIT_PENDING);
1476     } while (!__sync_bool_compare_and_swap(lock, old, new));
1477
1478     return ((new < GL_BIT_MASK) ? GL_ACQUIRED : GL_BUSY);
1479 }
1480
1481 /*
1482  * Release the global lock, returning whether there is a waiter pending.
1483  * If the BIOS set the pending bit, OSPM must notify the BIOS when it
1484  * releases the lock.
1485  */
1486 int acpi_release_global_lock(uint32_t *lock)
1487 {
1488     uint32_t new, old;
1489
1490     do {
1491         old = *lock;
1492         new = old & ~GL_BIT_MASK;
1493     } while (!__sync_bool_compare_and_swap(lock, old, new));
1494
1495     return (old & GL_BIT_PENDING);
1496 }