xref: /netbsd/usr.sbin/acpitools/aml/aml_region.c (revision 6550d01e)
1 /*	$NetBSD: aml_region.c,v 1.1 2007/01/14 04:36:13 christos Exp $	*/
2 
3 /*-
4  * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
5  * Copyright (c) 2000 Munehiro Matsuda <haro@tk.kubota.co.jp>
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  *	Id: aml_region.c,v 1.10 2000/08/09 14:47:44 iwasaki Exp
30  *	$FreeBSD: src/usr.sbin/acpi/amldb/aml/aml_region.c,v 1.5 2000/11/09 06:24:45 iwasaki Exp $
31  */
32 #include <sys/cdefs.h>
33 __RCSID("$NetBSD: aml_region.c,v 1.1 2007/01/14 04:36:13 christos Exp $");
34 
35 /*
36  * Region I/O subroutine
37  */
38 
39 #include "opt_acpi.h"
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/bus.h>
43 
44 #include <machine/bus.h>
45 #include <machine/resource.h>
46 #include <sys/rman.h>
47 
48 #include <dev/acpi/acpireg.h>
49 #include <dev/acpi/acpivar.h>
50 #include <aml/aml_common.h>
51 #include <aml/aml_region.h>
52 #include <aml/aml_name.h>
53 
54 #ifndef ACPI_NO_OSDFUNC_INLINE
55 #include <machine/acpica_osd.h>
56 #endif
57 
58 /*
59  * Dummy functions for aml_region_io_simple()
60  */
61 u_int32_t
62 aml_region_prompt_read(struct aml_region_handle *h, u_int32_t value)
63 {
64 
65 	return (value);
66 }
67 
68 u_int32_t
69 aml_region_prompt_write(struct aml_region_handle *h, u_int32_t value)
70 {
71 
72 	return (value);
73 }
74 
75 int
76 aml_region_prompt_update_value(u_int32_t orgval, u_int32_t value,
77     struct aml_region_handle *h)
78 {
79 	return (0);
80 }
81 
82 /*
83  * Primitive functions for aml_region_io_simple()
84  */
85 int
86 aml_region_read_simple(struct aml_region_handle *h, vm_offset_t offset, u_int32_t *valuep)
87 {
88 	u_int32_t value;
89 
90 	switch (h->regtype) {
91 	case AML_REGION_SYSMEM:
92 		/* XXX should be MI */
93 		switch (h->unit) {
94 		case 1:
95 			value = *(volatile u_int8_t *)(h->vaddr + offset);
96 			value &= 0xff;
97 			break;
98 		case 2:
99 			value = *(volatile u_int16_t *)(h->vaddr + offset);
100 			value &= 0xffff;
101 			break;
102 		case 4:
103 			value = *(volatile u_int32_t *)(h->vaddr + offset);
104 			break;
105 		}
106 		break;
107 	case AML_REGION_SYSIO:
108 		switch (h->unit) {
109 		case 1:
110 			value = OsdIn8(h->addr + offset);
111 			value &= 0xff;
112 			break;
113 		case 2:
114 			value = OsdIn16(h->addr + offset);
115 			value &= 0xffff;
116 			break;
117 		case 4:
118 			value = OsdIn32(h->addr + offset);
119 			break;
120 		}
121 		break;
122 	case AML_REGION_PCICFG:
123 		switch (h->unit) {
124 		case 1:
125 			OsdReadPciCfgByte(h->pci_bus, h->pci_devfunc,
126 			    h->addr + offset, (UINT8 *)&value);
127 			value &= 0xff;
128 			break;
129 		case 2:
130 			OsdReadPciCfgWord(h->pci_bus, h->pci_devfunc,
131 			    h->addr + offset, (UINT16 *)&value);
132 			value &= 0xffff;
133 			break;
134 		case 4:
135 			OsdReadPciCfgDword(h->pci_bus, h->pci_devfunc,
136 			    h->addr + offset, &value);
137 			break;
138 		}
139 		break;
140 	default:
141 		printf("aml_region_read_simple: not supported yet (%d)\n",
142 		    h->regtype);
143 		value = 0;
144 		break;
145 	}
146 	*valuep = value;
147 	return (0);
148 }
149 
150 int
151 aml_region_write_simple(struct aml_region_handle *h, vm_offset_t offset, u_int32_t value)
152 {
153 
154 	switch (h->regtype) {
155 	case AML_REGION_SYSMEM:
156 		/* XXX should be MI */
157 		switch (h->unit) {
158 		case 1:
159 			value &= 0xff;
160 			*(volatile u_int8_t *)(h->vaddr + offset) = value;
161 			break;
162 		case 2:
163 			value &= 0xffff;
164 			*(volatile u_int16_t *)(h->vaddr + offset) = value;
165 			break;
166 		case 4:
167 			*(volatile u_int32_t *)(h->vaddr + offset) = value;
168 			break;
169 		}
170 		break;
171 	case AML_REGION_SYSIO:
172 		switch (h->unit) {
173 		case 1:
174 			value &= 0xff;
175 			OsdOut8(h->addr + offset, value);
176 			break;
177 		case 2:
178 			value &= 0xffff;
179 			OsdOut16(h->addr + offset, value);
180 			break;
181 		case 4:
182 			OsdOut32(h->addr + offset, value);
183 			break;
184 		}
185 		break;
186 	case AML_REGION_PCICFG:
187 		switch (h->unit) {
188 		case 1:
189 			OsdWritePciCfgByte(h->pci_bus, h->pci_devfunc,
190 			    h->addr + offset, value);
191 			break;
192 		case 2:
193 			OsdWritePciCfgWord(h->pci_bus, h->pci_devfunc,
194 			    h->addr + offset, value);
195 			break;
196 		case 4:
197 			OsdWritePciCfgDword(h->pci_bus, h->pci_devfunc,
198 			    h->addr + offset, value);
199 			break;
200 		}
201 		break;
202 	default:
203 		printf("aml_region_write_simple: not supported yet (%d)\n",
204 		    h->regtype);
205 		break;
206 	}
207 
208 	return (0);
209 }
210 
211 static int
212 aml_region_io_buffer(boolean_t io, int regtype, u_int32_t flags,
213     u_int8_t *buffer, u_int32_t baseaddr, u_int32_t bitoffset, u_int32_t bitlen)
214 {
215 	vm_offset_t	addr, vaddr;
216 	size_t		len;
217 	const char	*funcname[] = {
218 		"aml_region_read_into_buffer",
219 		"aml_region_write_from_buffer"
220 	};
221 
222 	if (regtype != AML_REGION_SYSMEM) {
223 		printf("%s: region type isn't system memory!\n", funcname[io]);
224 		return (-1);
225 	}
226 
227 	if (bitlen % 8) {
228 		printf("%s: bit length isn't a multiple of 8!\n", funcname[io]);
229 	}
230 	if (bitoffset % 8) {
231 		printf("%s: bit offset isn't a multiple of 8!\n", funcname[io]);
232 	}
233 
234 	addr = baseaddr + bitoffset / 8;
235 	len = bitlen / 8 + ((bitlen % 8) ? 1 : 0);
236 
237 	OsdMapMemory((void *)addr, len, (void **)&vaddr);
238 
239 	switch (io) {
240 	case AML_REGION_INPUT:
241 		bcopy((void *)vaddr, (void *)buffer, len);
242 		break;
243 	case AML_REGION_OUTPUT:
244 		bcopy((void *)buffer, (void *)vaddr, len);
245 		break;
246 	}
247 
248 	OsdUnMapMemory((void *)vaddr, len);
249 
250 	return (0);
251 }
252 
253 u_int32_t
254 aml_region_read(struct aml_environ *env, int regtype, u_int32_t flags,
255     u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen)
256 {
257 	int	value;
258 	int	state;
259 
260 	AML_REGION_READ_DEBUG(regtype, flags, addr, bitoffset, bitlen);
261 
262 	state = aml_region_io(env, AML_REGION_INPUT, regtype,
263 	    flags, &value, addr, bitoffset, bitlen);
264 	AML_SYSASSERT(state != -1);
265 
266         return (value);
267 }
268 
269 int
270 aml_region_read_into_buffer(struct aml_environ *env, int regtype,
271     u_int32_t flags, u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen,
272     u_int8_t *buffer)
273 {
274 	int	state;
275 
276 	AML_REGION_READ_INTO_BUFFER_DEBUG(regtype, flags, addr, bitoffset, bitlen);
277 	state = aml_region_io_buffer(AML_REGION_INPUT, regtype, flags,
278 	    buffer, addr, bitoffset, bitlen);
279 
280         return (state);
281 }
282 
283 int
284 aml_region_write(struct aml_environ *env, int regtype, u_int32_t flags,
285     u_int32_t value, u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen)
286 {
287 	int	state;
288 
289 	AML_REGION_WRITE_DEBUG(regtype, flags, value, addr, bitoffset, bitlen);
290 
291 	state = aml_region_io(env, AML_REGION_OUTPUT, regtype,
292 	    flags, &value, addr, bitoffset, bitlen);
293 	AML_SYSASSERT(state != -1);
294 
295         return (state);
296 }
297 
298 int
299 aml_region_write_from_buffer(struct aml_environ *env, int regtype,
300     u_int32_t flags, u_int8_t *buffer, u_int32_t addr, u_int32_t bitoffset,
301     u_int32_t bitlen)
302 {
303 	int	state;
304 
305 	AML_REGION_WRITE_FROM_BUFFER_DEBUG(regtype, flags,
306 	    addr, bitoffset, bitlen);
307 
308 	state = aml_region_io_buffer(AML_REGION_OUTPUT, regtype, flags,
309 	    buffer, addr, bitoffset, bitlen);
310 
311         return (state);
312 }
313 
314 int
315 aml_region_bcopy(struct aml_environ *env, int regtype,
316     u_int32_t flags, u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen,
317     u_int32_t dflags, u_int32_t daddr, u_int32_t dbitoffset, u_int32_t dbitlen)
318 {
319 	vm_offset_t	from_addr, from_vaddr;
320 	vm_offset_t	to_addr, to_vaddr;
321 	size_t		len;
322 
323 	AML_REGION_BCOPY_DEBUG(regtype, flags, addr, bitoffset, bitlen,
324 	    dflags, daddr, dbitoffset, dbitlen);
325 
326 	if (regtype != AML_REGION_SYSMEM) {
327 		printf("aml_region_bcopy: region type isn't system memory!\n");
328 		return (-1);
329 	}
330 
331 	if ((bitlen % 8) || (dbitlen % 8)) {
332 		printf("aml_region_bcopy: bit length isn't a multiple of 8!\n");
333 	}
334 	if ((bitoffset % 8) || (dbitoffset % 8)) {
335 		printf("aml_region_bcopy: bit offset isn't a multiple of 8!\n");
336 	}
337 
338 	from_addr = addr + bitoffset / 8;
339 	to_addr = daddr + dbitoffset / 8;
340 
341 	len = (bitlen > dbitlen) ? dbitlen : bitlen;
342 	len = len / 8 + ((len % 8) ? 1 : 0);
343 
344 	OsdMapMemory((void *)from_addr, len, (void **)&from_vaddr);
345 	OsdMapMemory((void *)to_addr, len, (void **)&to_vaddr);
346 
347 	bcopy((void *)from_vaddr, (void *)to_vaddr, len);
348 
349 	OsdUnMapMemory((void *)from_vaddr, len);
350 	OsdUnMapMemory((void *)to_vaddr, len);
351 
352 	return (0);
353 }
354