xref: /dragonfly/sys/dev/acpica/Osd/OsdMemory.c (revision 1bf4b486)
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 }
226