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.11 2004/04/14 03:39:08 njl Exp $ 29 */ 30 31 /* 32 * 6.2 : Memory Management 33 */ 34 35 #include "acpi.h" 36 37 #include <sys/kernel.h> 38 #include <sys/malloc.h> 39 #include <vm/vm.h> 40 #include <vm/pmap.h> 41 42 MALLOC_DEFINE(M_ACPICA, "acpica", "ACPI CA memory pool"); 43 44 struct acpi_memtrack { 45 struct acpi_memtrack *next; 46 void *base; 47 ACPI_SIZE size; 48 #ifdef ACPI_DEBUG_MEMMAP 49 int freed; 50 struct { 51 const char *func; 52 int line; 53 } mapper, unmapper; 54 #endif 55 }; 56 57 typedef struct acpi_memtrack *acpi_memtrack_t; 58 59 static acpi_memtrack_t acpi_mapbase; 60 61 void * 62 AcpiOsAllocate(ACPI_SIZE Size) 63 { 64 return (kmalloc(Size, M_ACPICA, M_INTWAIT)); 65 } 66 67 void 68 AcpiOsFree(void *Memory) 69 { 70 kfree(Memory, M_ACPICA); 71 } 72 73 #ifdef ACPI_DEBUG_MEMMAP 74 void * 75 _AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS Where, ACPI_SIZE Length, 76 const char *caller, int line) 77 #else 78 void * 79 AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS Where, ACPI_SIZE Length) 80 #endif 81 { 82 acpi_memtrack_t track; 83 void *map; 84 85 map = pmap_mapdev((vm_offset_t)Where, Length); 86 if (map == NULL) 87 return(NULL); 88 else { 89 #ifdef ACPI_DEBUG_MEMMAP 90 for (track = acpi_mapbase; track != NULL; track = track->next) { 91 if (track->base == map) 92 break; 93 } 94 #else 95 track = NULL; 96 #endif 97 if (track == NULL) { 98 track = kmalloc(sizeof(*track), M_ACPICA, M_INTWAIT); 99 track->next = acpi_mapbase; 100 track->base = map; 101 } 102 track->size = Length; 103 #ifdef ACPI_DEBUG_MEMMAP 104 track->freed = 0; 105 track->mapper.func = caller; 106 track->mapper.line = line; 107 track->unmapper.func = ""; 108 track->unmapper.line = 0; 109 #endif 110 acpi_mapbase = track; 111 } 112 return(map); 113 } 114 115 #ifdef ACPI_DEBUG_MEMMAP 116 void 117 _AcpiOsUnmapMemory(void *LogicalAddress, ACPI_SIZE Length, 118 const char *caller, int line) 119 #else 120 void 121 AcpiOsUnmapMemory(void *LogicalAddress, ACPI_SIZE Length) 122 #endif 123 { 124 struct acpi_memtrack **ptrack; 125 acpi_memtrack_t track; 126 127 again: 128 for (ptrack = &acpi_mapbase; (track = *ptrack); ptrack = &track->next) { 129 #ifdef ACPI_DEBUG_MEMMAP 130 if (track->freed) 131 continue; 132 #endif 133 /* 134 * Exact match, degenerate case 135 */ 136 if (track->base == LogicalAddress && track->size == Length) { 137 *ptrack = track->next; 138 pmap_unmapdev((vm_offset_t)track->base, track->size); 139 #ifdef ACPI_DEBUG_MEMMAP 140 track->freed = 1; 141 track->unmapper.func = caller; 142 track->unmapper.line = line; 143 #else 144 kfree(track, M_ACPICA); 145 #endif 146 return; 147 } 148 /* 149 * Completely covered 150 */ 151 if ((char *)LogicalAddress <= (char *)track->base && 152 (char *)LogicalAddress + Length >= (char *)track->base + track->size 153 ) { 154 *ptrack = track->next; 155 pmap_unmapdev((vm_offset_t)track->base, track->size); 156 kprintf("AcpiOsUnmapMemory: Warning, deallocation request too" 157 " large! %p/%08jx (actual was %p/%08jx)\n", 158 LogicalAddress, (intmax_t)Length, 159 track->base, (intmax_t)track->size); 160 #ifdef ACPI_DEBUG_MEMMAP 161 track->freed = 1; 162 track->unmapper.func = caller; 163 track->unmapper.line = line; 164 #else 165 kfree(track, M_ACPICA); 166 #endif 167 goto again; 168 } 169 170 /* 171 * Overlapping 172 */ 173 if ((char *)LogicalAddress + Length >= (char *)track->base && 174 (char *)LogicalAddress < (char *)track->base + track->size 175 ) { 176 kprintf("AcpiOsUnmapMemory: Warning, deallocation did not " 177 "track allocation: %p/%08jx (actual was %p/%08jx)\n", 178 LogicalAddress, (intmax_t)Length, 179 track->base, (intmax_t)track->size); 180 } 181 } 182 kprintf("AcpiOsUnmapMemory: Warning, broken ACPI, bad unmap: %p/%08jx\n", 183 LogicalAddress, (intmax_t)Length); 184 #ifdef ACPI_DEBUG_MEMMAP 185 for (track = acpi_mapbase; track != NULL; track = track->next) { 186 if (track->freed && track->base == LogicalAddress) { 187 kprintf("%s: unmapping: %p/%08x, mapped by %s:%d," 188 "last unmapped by %s:%d\n", 189 __func__, LogicalAddress, Length, 190 track->mapper.func, track->mapper.line, 191 track->unmapper.func, track->unmapper.line 192 ); 193 } 194 } 195 #endif 196 } 197 198 ACPI_STATUS 199 AcpiOsGetPhysicalAddress(void *LogicalAddress, 200 ACPI_PHYSICAL_ADDRESS *PhysicalAddress) 201 { 202 /* We can't necessarily do this, so cop out. */ 203 return (AE_BAD_ADDRESS); 204 } 205 206 /* 207 * There is no clean way to do this. We make the charitable assumption 208 * that callers will not pass garbage to us. 209 */ 210 BOOLEAN 211 AcpiOsReadable (void *Pointer, ACPI_SIZE Length) 212 { 213 return (TRUE); 214 } 215 216 BOOLEAN 217 AcpiOsWritable (void *Pointer, ACPI_SIZE Length) 218 { 219 return (TRUE); 220 } 221 222 ACPI_STATUS 223 AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS Address, UINT32 *Value, UINT32 Width) 224 { 225 void *LogicalAddress; 226 227 LogicalAddress = AcpiOsMapMemory(Address, Width / 8); 228 if (LogicalAddress == NULL) 229 return (AE_NOT_EXIST); 230 231 switch (Width) { 232 case 8: 233 *(u_int8_t *)Value = (*(volatile u_int8_t *)LogicalAddress); 234 break; 235 case 16: 236 *(u_int16_t *)Value = (*(volatile u_int16_t *)LogicalAddress); 237 break; 238 case 32: 239 *(u_int32_t *)Value = (*(volatile u_int32_t *)LogicalAddress); 240 break; 241 case 64: 242 *(u_int64_t *)Value = (*(volatile u_int64_t *)LogicalAddress); 243 break; 244 default: 245 /* debug trap goes here */ 246 break; 247 } 248 249 AcpiOsUnmapMemory(LogicalAddress, Width / 8); 250 251 return (AE_OK); 252 } 253 254 ACPI_STATUS 255 AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address, UINT32 Value, UINT32 Width) 256 { 257 void *LogicalAddress; 258 259 LogicalAddress = AcpiOsMapMemory(Address, Width / 8); 260 if (LogicalAddress == NULL) 261 return (AE_NOT_EXIST); 262 263 switch (Width) { 264 case 8: 265 (*(volatile u_int8_t *)LogicalAddress) = Value & 0xff; 266 break; 267 case 16: 268 (*(volatile u_int16_t *)LogicalAddress) = Value & 0xffff; 269 break; 270 case 32: 271 (*(volatile u_int32_t *)LogicalAddress) = Value & 0xffffffff; 272 break; 273 case 64: 274 (*(volatile u_int64_t *)LogicalAddress) = Value; 275 break; 276 default: 277 /* debug trap goes here */ 278 break; 279 } 280 281 AcpiOsUnmapMemory(LogicalAddress, Width / 8); 282 283 return (AE_OK); 284 } 285