2 * Copyright (c) 2000 Mitsaru Iwasaki
3 * Copyright (c) 2000 Michael Smith
4 * Copyright (c) 2000 BSDi
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
28 * $FreeBSD: src/sys/dev/acpica/Osd/OsdMemory.c,v 1.11 2004/04/14 03:39:08 njl Exp $
37 #include <sys/kernel.h>
38 #include <sys/malloc.h>
42 MALLOC_DEFINE(M_ACPICA, "acpica", "ACPICA memory pool");
44 struct acpi_memtrack {
45 struct acpi_memtrack *next;
48 #ifdef ACPI_DEBUG_MEMMAP
57 typedef struct acpi_memtrack *acpi_memtrack_t;
59 static acpi_memtrack_t acpi_mapbase;
62 AcpiOsAllocate(ACPI_SIZE Size)
64 return (kmalloc(Size, M_ACPICA, M_INTWAIT));
68 AcpiOsAllocateZeroed(ACPI_SIZE Size)
70 return (kmalloc(Size, M_ACPICA, M_INTWAIT | M_ZERO));
74 AcpiOsFree(void *Memory)
76 kfree(Memory, M_ACPICA);
79 #ifdef ACPI_DEBUG_MEMMAP
81 _AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS Where, ACPI_SIZE Length,
82 const char *caller, int line)
85 AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS Where, ACPI_SIZE Length)
88 acpi_memtrack_t track;
91 map = pmap_mapdev((vm_offset_t)Where, Length);
95 #ifdef ACPI_DEBUG_MEMMAP
96 for (track = acpi_mapbase; track != NULL; track = track->next) {
97 if (track->base == map)
104 track = kmalloc(sizeof(*track), M_ACPICA, M_INTWAIT);
105 track->next = acpi_mapbase;
108 track->size = Length;
109 #ifdef ACPI_DEBUG_MEMMAP
111 track->mapper.func = caller;
112 track->mapper.line = line;
113 track->unmapper.func = "";
114 track->unmapper.line = 0;
116 acpi_mapbase = track;
121 #ifdef ACPI_DEBUG_MEMMAP
123 _AcpiOsUnmapMemory(void *LogicalAddress, ACPI_SIZE Length,
124 const char *caller, int line)
127 AcpiOsUnmapMemory(void *LogicalAddress, ACPI_SIZE Length)
130 struct acpi_memtrack **ptrack;
131 acpi_memtrack_t track;
134 for (ptrack = &acpi_mapbase; (track = *ptrack); ptrack = &track->next) {
135 #ifdef ACPI_DEBUG_MEMMAP
140 * Exact match, degenerate case
142 if (track->base == LogicalAddress && track->size == Length) {
143 *ptrack = track->next;
144 pmap_unmapdev((vm_offset_t)track->base, track->size);
145 #ifdef ACPI_DEBUG_MEMMAP
147 track->unmapper.func = caller;
148 track->unmapper.line = line;
150 kfree(track, M_ACPICA);
157 if ((char *)LogicalAddress <= (char *)track->base &&
158 (char *)LogicalAddress + Length >= (char *)track->base + track->size
160 *ptrack = track->next;
161 pmap_unmapdev((vm_offset_t)track->base, track->size);
162 kprintf("AcpiOsUnmapMemory: Warning, deallocation request too"
163 " large! %p/%08jx (actual was %p/%08jx)\n",
164 LogicalAddress, (intmax_t)Length,
165 track->base, (intmax_t)track->size);
166 #ifdef ACPI_DEBUG_MEMMAP
168 track->unmapper.func = caller;
169 track->unmapper.line = line;
171 kfree(track, M_ACPICA);
179 if ((char *)LogicalAddress + Length >= (char *)track->base &&
180 (char *)LogicalAddress < (char *)track->base + track->size
182 kprintf("AcpiOsUnmapMemory: Warning, deallocation did not "
183 "track allocation: %p/%08jx (actual was %p/%08jx)\n",
184 LogicalAddress, (intmax_t)Length,
185 track->base, (intmax_t)track->size);
188 kprintf("AcpiOsUnmapMemory: Warning, broken ACPI, bad unmap: %p/%08jx\n",
189 LogicalAddress, (intmax_t)Length);
190 #ifdef ACPI_DEBUG_MEMMAP
191 for (track = acpi_mapbase; track != NULL; track = track->next) {
192 if (track->freed && track->base == LogicalAddress) {
193 kprintf("%s: unmapping: %p/%08jx, mapped by %s:%d,"
194 "last unmapped by %s:%d\n",
195 __func__, LogicalAddress, (uintmax_t)Length,
196 track->mapper.func, track->mapper.line,
197 track->unmapper.func, track->unmapper.line
205 AcpiOsGetPhysicalAddress(void *LogicalAddress,
206 ACPI_PHYSICAL_ADDRESS *PhysicalAddress)
208 /* We can't necessarily do this, so cop out. */
209 return (AE_BAD_ADDRESS);
213 * There is no clean way to do this. We make the charitable assumption
214 * that callers will not pass garbage to us.
217 AcpiOsReadable (void *Pointer, ACPI_SIZE Length)
223 AcpiOsWritable (void *Pointer, ACPI_SIZE Length)
229 AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS Address, UINT64 *Value, UINT32 Width)
231 void *LogicalAddress;
233 LogicalAddress = AcpiOsMapMemory(Address, Width / 8);
234 if (LogicalAddress == NULL)
235 return (AE_NOT_EXIST);
239 *Value = *(volatile uint8_t *)LogicalAddress;
242 *Value = *(volatile uint16_t *)LogicalAddress;
245 *Value = *(volatile uint32_t *)LogicalAddress;
248 *Value = *(volatile uint64_t *)LogicalAddress;
252 AcpiOsUnmapMemory(LogicalAddress, Width / 8);
258 AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address, UINT64 Value, UINT32 Width)
260 void *LogicalAddress;
262 LogicalAddress = AcpiOsMapMemory(Address, Width / 8);
263 if (LogicalAddress == NULL)
264 return (AE_NOT_EXIST);
268 *(volatile uint8_t *)LogicalAddress = Value;
271 *(volatile uint16_t *)LogicalAddress = Value;
274 *(volatile uint32_t *)LogicalAddress = Value;
277 *(volatile uint64_t *)LogicalAddress = Value;
281 AcpiOsUnmapMemory(LogicalAddress, Width / 8);