Merge from vendor branch NTPD:
[dragonfly.git] / sys / dev / acpica / Osd / OsdMemory.c
1 /*-
2  * Copyright (c) 2000 Mitsaru Iwasaki
3  * Copyright (c) 2000 Michael Smith
4  * Copyright (c) 2000 BSDi
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  *      $FreeBSD: src/sys/dev/acpica/Osd/OsdMemory.c,v 1.10.2.1 2003/08/22 20:49:21 jhb Exp $
29  *      $DragonFly: src/sys/dev/acpica/Osd/Attic/OsdMemory.c,v 1.2 2004/05/05 22:18:09 dillon Exp $ 
30  */
31
32 /*
33  * 6.2 : Memory Management
34  */
35
36 #include "acpi.h"
37
38 #include <sys/kernel.h>
39 #include <sys/malloc.h>
40 #include <vm/vm.h>
41 #include <vm/pmap.h>
42
43 static MALLOC_DEFINE(M_ACPICA, "acpica", "ACPI CA memory pool");
44
45 struct acpi_memtrack {
46     struct acpi_memtrack *next;
47     void *base;
48     ACPI_SIZE size;
49 };
50
51 typedef struct acpi_memtrack *acpi_memtrack_t;
52
53 static acpi_memtrack_t acpi_mapbase;
54
55 void *
56 AcpiOsAllocate(ACPI_SIZE Size)
57 {
58     return(malloc(Size, M_ACPICA, M_INTWAIT));
59 }
60
61 void
62 AcpiOsFree (void *Memory)
63 {
64     free(Memory, M_ACPICA);
65 }
66
67 ACPI_STATUS
68 AcpiOsMapMemory (ACPI_PHYSICAL_ADDRESS PhysicalAddress, ACPI_SIZE Length, void **LogicalAddress)
69 {
70     acpi_memtrack_t track;
71
72     *LogicalAddress = pmap_mapdev((vm_offset_t)PhysicalAddress, Length);
73     if (*LogicalAddress == NULL) {
74         return(AE_BAD_ADDRESS);
75     } else {
76         track = malloc(sizeof(struct acpi_memtrack), M_ACPICA, M_INTWAIT);
77         track->next = acpi_mapbase;
78         track->base = *LogicalAddress;
79         track->size = Length;
80         acpi_mapbase = track;
81     }
82     return(AE_OK);
83 }
84
85 void
86 AcpiOsUnmapMemory (void *LogicalAddress, ACPI_SIZE Length)
87 {
88     struct acpi_memtrack **ptrack;
89     acpi_memtrack_t track;
90
91 again:
92     for (ptrack = &acpi_mapbase; (track = *ptrack); ptrack = &track->next) {
93         /*
94          * Exact match, degenerate case
95          */
96         if (track->base == LogicalAddress && track->size == Length) {
97             *ptrack = track->next;
98             pmap_unmapdev((vm_offset_t)track->base, track->size);
99             free(track, M_ACPICA);
100             return;
101         }
102         /*
103          * Completely covered
104          */
105         if ((char *)LogicalAddress <= (char *)track->base &&
106             (char *)LogicalAddress + Length >= (char *)track->base + track->size
107         ) {
108             *ptrack = track->next;
109             pmap_unmapdev((vm_offset_t)track->base, track->size);
110             printf("AcpiOsUnmapMemory: Warning, deallocation request too"
111                    " large! %p/%08x (actual was %p/%08x)\n",
112                    LogicalAddress, Length,
113                    track->base, track->size);
114             free(track, M_ACPICA);
115             goto again;
116         }
117
118         /*
119          * Overlapping
120          */
121         if ((char *)LogicalAddress + Length >= (char *)track->base &&
122             (char *)LogicalAddress < (char *)track->base + track->size
123         ) {
124             printf("AcpiOsUnmapMemory: Warning, deallocation did not "
125                    "track allocation: %p/%08x (actual was %p/%08x)\n",
126                    LogicalAddress, Length,
127                    track->base, track->size);
128         }
129     }
130     printf("AcpiOsUnmapMemory: Warning, broken ACPI, bad unmap: %p/%08x\n",
131         LogicalAddress, Length);
132 }
133
134 ACPI_STATUS
135 AcpiOsGetPhysicalAddress(void *LogicalAddress, ACPI_PHYSICAL_ADDRESS *PhysicalAddress)
136 {
137     /* we can't necessarily do this, so cop out */
138     return(AE_BAD_ADDRESS);
139 }
140
141 /*
142  * There is no clean way to do this.  We make the charitable assumption
143  * that callers will not pass garbage to us.
144  */
145 BOOLEAN
146 AcpiOsReadable (void *Pointer, UINT32 Length)
147 {
148     return(TRUE);
149 }
150
151 BOOLEAN
152 AcpiOsWritable (void *Pointer, UINT32 Length)
153 {
154     return(TRUE);
155 }
156
157 ACPI_STATUS
158 AcpiOsReadMemory (
159     ACPI_PHYSICAL_ADDRESS       Address,
160     void                        *Value,
161     UINT32                      Width)
162 {
163     void        *LogicalAddress;
164
165     if (AcpiOsMapMemory(Address, Width / 8, &LogicalAddress) != AE_OK) {
166         return(AE_NOT_EXIST);
167     }
168
169     switch (Width) {
170     case 8:
171         *(u_int8_t *)Value = (*(volatile u_int8_t *)LogicalAddress);
172         break;
173     case 16:
174         *(u_int16_t *)Value = (*(volatile u_int16_t *)LogicalAddress);
175         break;
176     case 32:
177         *(u_int32_t *)Value = (*(volatile u_int32_t *)LogicalAddress);
178         break;
179     case 64:
180         *(u_int64_t *)Value = (*(volatile u_int64_t *)LogicalAddress);
181         break;
182     default:
183         /* debug trap goes here */
184         break;
185     }
186
187     AcpiOsUnmapMemory(LogicalAddress, Width / 8);
188
189     return(AE_OK);
190 }
191
192 ACPI_STATUS
193 AcpiOsWriteMemory (
194     ACPI_PHYSICAL_ADDRESS       Address,
195     ACPI_INTEGER                Value,
196     UINT32                      Width)
197 {
198     void        *LogicalAddress;
199
200     if (AcpiOsMapMemory(Address, Width / 8, &LogicalAddress) != AE_OK) {
201         return(AE_NOT_EXIST);
202     }
203
204     switch (Width) {
205     case 8:
206         (*(volatile u_int8_t *)LogicalAddress) = Value & 0xff;
207         break;
208     case 16:
209         (*(volatile u_int16_t *)LogicalAddress) = Value & 0xffff;
210         break;
211     case 32:
212         (*(volatile u_int32_t *)LogicalAddress) = Value & 0xffffffff;
213         break;
214     case 64:
215         (*(volatile u_int64_t *)LogicalAddress) = Value;
216         break;
217     default:
218         /* debug trap goes here */
219         break;
220     }
221
222     AcpiOsUnmapMemory(LogicalAddress, Width / 8);
223
224     return(AE_OK);
225 }