xref: /netbsd-src/usr.sbin/acpitools/aml/aml_region.c (revision 4b2c4b100e6c58101a975265496ec511c872b6bc)
1 /*	$NetBSD: aml_region.c,v 1.2 2011/05/30 01:15:30 dyoung 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.2 2011/05/30 01:15:30 dyoung 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/resource.h>
45 #include <sys/rman.h>
46 
47 #include <dev/acpi/acpireg.h>
48 #include <dev/acpi/acpivar.h>
49 #include <aml/aml_common.h>
50 #include <aml/aml_region.h>
51 #include <aml/aml_name.h>
52 
53 #ifndef ACPI_NO_OSDFUNC_INLINE
54 #include <machine/acpica_osd.h>
55 #endif
56 
57 /*
58  * Dummy functions for aml_region_io_simple()
59  */
60 u_int32_t
aml_region_prompt_read(struct aml_region_handle * h,u_int32_t value)61 aml_region_prompt_read(struct aml_region_handle *h, u_int32_t value)
62 {
63 
64 	return (value);
65 }
66 
67 u_int32_t
aml_region_prompt_write(struct aml_region_handle * h,u_int32_t value)68 aml_region_prompt_write(struct aml_region_handle *h, u_int32_t value)
69 {
70 
71 	return (value);
72 }
73 
74 int
aml_region_prompt_update_value(u_int32_t orgval,u_int32_t value,struct aml_region_handle * h)75 aml_region_prompt_update_value(u_int32_t orgval, u_int32_t value,
76     struct aml_region_handle *h)
77 {
78 	return (0);
79 }
80 
81 /*
82  * Primitive functions for aml_region_io_simple()
83  */
84 int
aml_region_read_simple(struct aml_region_handle * h,vm_offset_t offset,u_int32_t * valuep)85 aml_region_read_simple(struct aml_region_handle *h, vm_offset_t offset, u_int32_t *valuep)
86 {
87 	u_int32_t value;
88 
89 	switch (h->regtype) {
90 	case AML_REGION_SYSMEM:
91 		/* XXX should be MI */
92 		switch (h->unit) {
93 		case 1:
94 			value = *(volatile u_int8_t *)(h->vaddr + offset);
95 			value &= 0xff;
96 			break;
97 		case 2:
98 			value = *(volatile u_int16_t *)(h->vaddr + offset);
99 			value &= 0xffff;
100 			break;
101 		case 4:
102 			value = *(volatile u_int32_t *)(h->vaddr + offset);
103 			break;
104 		}
105 		break;
106 	case AML_REGION_SYSIO:
107 		switch (h->unit) {
108 		case 1:
109 			value = OsdIn8(h->addr + offset);
110 			value &= 0xff;
111 			break;
112 		case 2:
113 			value = OsdIn16(h->addr + offset);
114 			value &= 0xffff;
115 			break;
116 		case 4:
117 			value = OsdIn32(h->addr + offset);
118 			break;
119 		}
120 		break;
121 	case AML_REGION_PCICFG:
122 		switch (h->unit) {
123 		case 1:
124 			OsdReadPciCfgByte(h->pci_bus, h->pci_devfunc,
125 			    h->addr + offset, (UINT8 *)&value);
126 			value &= 0xff;
127 			break;
128 		case 2:
129 			OsdReadPciCfgWord(h->pci_bus, h->pci_devfunc,
130 			    h->addr + offset, (UINT16 *)&value);
131 			value &= 0xffff;
132 			break;
133 		case 4:
134 			OsdReadPciCfgDword(h->pci_bus, h->pci_devfunc,
135 			    h->addr + offset, &value);
136 			break;
137 		}
138 		break;
139 	default:
140 		printf("aml_region_read_simple: not supported yet (%d)\n",
141 		    h->regtype);
142 		value = 0;
143 		break;
144 	}
145 	*valuep = value;
146 	return (0);
147 }
148 
149 int
aml_region_write_simple(struct aml_region_handle * h,vm_offset_t offset,u_int32_t value)150 aml_region_write_simple(struct aml_region_handle *h, vm_offset_t offset, u_int32_t value)
151 {
152 
153 	switch (h->regtype) {
154 	case AML_REGION_SYSMEM:
155 		/* XXX should be MI */
156 		switch (h->unit) {
157 		case 1:
158 			value &= 0xff;
159 			*(volatile u_int8_t *)(h->vaddr + offset) = value;
160 			break;
161 		case 2:
162 			value &= 0xffff;
163 			*(volatile u_int16_t *)(h->vaddr + offset) = value;
164 			break;
165 		case 4:
166 			*(volatile u_int32_t *)(h->vaddr + offset) = value;
167 			break;
168 		}
169 		break;
170 	case AML_REGION_SYSIO:
171 		switch (h->unit) {
172 		case 1:
173 			value &= 0xff;
174 			OsdOut8(h->addr + offset, value);
175 			break;
176 		case 2:
177 			value &= 0xffff;
178 			OsdOut16(h->addr + offset, value);
179 			break;
180 		case 4:
181 			OsdOut32(h->addr + offset, value);
182 			break;
183 		}
184 		break;
185 	case AML_REGION_PCICFG:
186 		switch (h->unit) {
187 		case 1:
188 			OsdWritePciCfgByte(h->pci_bus, h->pci_devfunc,
189 			    h->addr + offset, value);
190 			break;
191 		case 2:
192 			OsdWritePciCfgWord(h->pci_bus, h->pci_devfunc,
193 			    h->addr + offset, value);
194 			break;
195 		case 4:
196 			OsdWritePciCfgDword(h->pci_bus, h->pci_devfunc,
197 			    h->addr + offset, value);
198 			break;
199 		}
200 		break;
201 	default:
202 		printf("aml_region_write_simple: not supported yet (%d)\n",
203 		    h->regtype);
204 		break;
205 	}
206 
207 	return (0);
208 }
209 
210 static int
aml_region_io_buffer(boolean_t io,int regtype,u_int32_t flags,u_int8_t * buffer,u_int32_t baseaddr,u_int32_t bitoffset,u_int32_t bitlen)211 aml_region_io_buffer(boolean_t io, int regtype, u_int32_t flags,
212     u_int8_t *buffer, u_int32_t baseaddr, u_int32_t bitoffset, u_int32_t bitlen)
213 {
214 	vm_offset_t	addr, vaddr;
215 	size_t		len;
216 	const char	*funcname[] = {
217 		"aml_region_read_into_buffer",
218 		"aml_region_write_from_buffer"
219 	};
220 
221 	if (regtype != AML_REGION_SYSMEM) {
222 		printf("%s: region type isn't system memory!\n", funcname[io]);
223 		return (-1);
224 	}
225 
226 	if (bitlen % 8) {
227 		printf("%s: bit length isn't a multiple of 8!\n", funcname[io]);
228 	}
229 	if (bitoffset % 8) {
230 		printf("%s: bit offset isn't a multiple of 8!\n", funcname[io]);
231 	}
232 
233 	addr = baseaddr + bitoffset / 8;
234 	len = bitlen / 8 + ((bitlen % 8) ? 1 : 0);
235 
236 	OsdMapMemory((void *)addr, len, (void **)&vaddr);
237 
238 	switch (io) {
239 	case AML_REGION_INPUT:
240 		bcopy((void *)vaddr, (void *)buffer, len);
241 		break;
242 	case AML_REGION_OUTPUT:
243 		bcopy((void *)buffer, (void *)vaddr, len);
244 		break;
245 	}
246 
247 	OsdUnMapMemory((void *)vaddr, len);
248 
249 	return (0);
250 }
251 
252 u_int32_t
aml_region_read(struct aml_environ * env,int regtype,u_int32_t flags,u_int32_t addr,u_int32_t bitoffset,u_int32_t bitlen)253 aml_region_read(struct aml_environ *env, int regtype, u_int32_t flags,
254     u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen)
255 {
256 	int	value;
257 	int	state;
258 
259 	AML_REGION_READ_DEBUG(regtype, flags, addr, bitoffset, bitlen);
260 
261 	state = aml_region_io(env, AML_REGION_INPUT, regtype,
262 	    flags, &value, addr, bitoffset, bitlen);
263 	AML_SYSASSERT(state != -1);
264 
265         return (value);
266 }
267 
268 int
aml_region_read_into_buffer(struct aml_environ * env,int regtype,u_int32_t flags,u_int32_t addr,u_int32_t bitoffset,u_int32_t bitlen,u_int8_t * buffer)269 aml_region_read_into_buffer(struct aml_environ *env, int regtype,
270     u_int32_t flags, u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen,
271     u_int8_t *buffer)
272 {
273 	int	state;
274 
275 	AML_REGION_READ_INTO_BUFFER_DEBUG(regtype, flags, addr, bitoffset, bitlen);
276 	state = aml_region_io_buffer(AML_REGION_INPUT, regtype, flags,
277 	    buffer, addr, bitoffset, bitlen);
278 
279         return (state);
280 }
281 
282 int
aml_region_write(struct aml_environ * env,int regtype,u_int32_t flags,u_int32_t value,u_int32_t addr,u_int32_t bitoffset,u_int32_t bitlen)283 aml_region_write(struct aml_environ *env, int regtype, u_int32_t flags,
284     u_int32_t value, u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen)
285 {
286 	int	state;
287 
288 	AML_REGION_WRITE_DEBUG(regtype, flags, value, addr, bitoffset, bitlen);
289 
290 	state = aml_region_io(env, AML_REGION_OUTPUT, regtype,
291 	    flags, &value, addr, bitoffset, bitlen);
292 	AML_SYSASSERT(state != -1);
293 
294         return (state);
295 }
296 
297 int
aml_region_write_from_buffer(struct aml_environ * env,int regtype,u_int32_t flags,u_int8_t * buffer,u_int32_t addr,u_int32_t bitoffset,u_int32_t bitlen)298 aml_region_write_from_buffer(struct aml_environ *env, int regtype,
299     u_int32_t flags, u_int8_t *buffer, u_int32_t addr, u_int32_t bitoffset,
300     u_int32_t bitlen)
301 {
302 	int	state;
303 
304 	AML_REGION_WRITE_FROM_BUFFER_DEBUG(regtype, flags,
305 	    addr, bitoffset, bitlen);
306 
307 	state = aml_region_io_buffer(AML_REGION_OUTPUT, regtype, flags,
308 	    buffer, addr, bitoffset, bitlen);
309 
310         return (state);
311 }
312 
313 int
aml_region_bcopy(struct aml_environ * env,int regtype,u_int32_t flags,u_int32_t addr,u_int32_t bitoffset,u_int32_t bitlen,u_int32_t dflags,u_int32_t daddr,u_int32_t dbitoffset,u_int32_t dbitlen)314 aml_region_bcopy(struct aml_environ *env, int regtype,
315     u_int32_t flags, u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen,
316     u_int32_t dflags, u_int32_t daddr, u_int32_t dbitoffset, u_int32_t dbitlen)
317 {
318 	vm_offset_t	from_addr, from_vaddr;
319 	vm_offset_t	to_addr, to_vaddr;
320 	size_t		len;
321 
322 	AML_REGION_BCOPY_DEBUG(regtype, flags, addr, bitoffset, bitlen,
323 	    dflags, daddr, dbitoffset, dbitlen);
324 
325 	if (regtype != AML_REGION_SYSMEM) {
326 		printf("aml_region_bcopy: region type isn't system memory!\n");
327 		return (-1);
328 	}
329 
330 	if ((bitlen % 8) || (dbitlen % 8)) {
331 		printf("aml_region_bcopy: bit length isn't a multiple of 8!\n");
332 	}
333 	if ((bitoffset % 8) || (dbitoffset % 8)) {
334 		printf("aml_region_bcopy: bit offset isn't a multiple of 8!\n");
335 	}
336 
337 	from_addr = addr + bitoffset / 8;
338 	to_addr = daddr + dbitoffset / 8;
339 
340 	len = (bitlen > dbitlen) ? dbitlen : bitlen;
341 	len = len / 8 + ((len % 8) ? 1 : 0);
342 
343 	OsdMapMemory((void *)from_addr, len, (void **)&from_vaddr);
344 	OsdMapMemory((void *)to_addr, len, (void **)&to_vaddr);
345 
346 	bcopy((void *)from_vaddr, (void *)to_vaddr, len);
347 
348 	OsdUnMapMemory((void *)from_vaddr, len);
349 	OsdUnMapMemory((void *)to_vaddr, len);
350 
351 	return (0);
352 }
353