xref: /netbsd-src/usr.sbin/acpitools/aml/aml_region.c (revision 4b2c4b100e6c58101a975265496ec511c872b6bc)
1*4b2c4b10Sdyoung /*	$NetBSD: aml_region.c,v 1.2 2011/05/30 01:15:30 dyoung Exp $	*/
253e202c1Schristos 
353e202c1Schristos /*-
453e202c1Schristos  * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
553e202c1Schristos  * Copyright (c) 2000 Munehiro Matsuda <haro@tk.kubota.co.jp>
653e202c1Schristos  * All rights reserved.
753e202c1Schristos  *
853e202c1Schristos  * Redistribution and use in source and binary forms, with or without
953e202c1Schristos  * modification, are permitted provided that the following conditions
1053e202c1Schristos  * are met:
1153e202c1Schristos  * 1. Redistributions of source code must retain the above copyright
1253e202c1Schristos  *    notice, this list of conditions and the following disclaimer.
1353e202c1Schristos  * 2. Redistributions in binary form must reproduce the above copyright
1453e202c1Schristos  *    notice, this list of conditions and the following disclaimer in the
1553e202c1Schristos  *    documentation and/or other materials provided with the distribution.
1653e202c1Schristos  *
1753e202c1Schristos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1853e202c1Schristos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1953e202c1Schristos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2053e202c1Schristos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2153e202c1Schristos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2253e202c1Schristos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2353e202c1Schristos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2453e202c1Schristos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2553e202c1Schristos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2653e202c1Schristos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2753e202c1Schristos  * SUCH DAMAGE.
2853e202c1Schristos  *
2953e202c1Schristos  *	Id: aml_region.c,v 1.10 2000/08/09 14:47:44 iwasaki Exp
3053e202c1Schristos  *	$FreeBSD: src/usr.sbin/acpi/amldb/aml/aml_region.c,v 1.5 2000/11/09 06:24:45 iwasaki Exp $
3153e202c1Schristos  */
3253e202c1Schristos #include <sys/cdefs.h>
33*4b2c4b10Sdyoung __RCSID("$NetBSD: aml_region.c,v 1.2 2011/05/30 01:15:30 dyoung Exp $");
3453e202c1Schristos 
3553e202c1Schristos /*
3653e202c1Schristos  * Region I/O subroutine
3753e202c1Schristos  */
3853e202c1Schristos 
3953e202c1Schristos #include "opt_acpi.h"
4053e202c1Schristos #include <sys/param.h>
4153e202c1Schristos #include <sys/systm.h>
4253e202c1Schristos #include <sys/bus.h>
4353e202c1Schristos 
4453e202c1Schristos #include <machine/resource.h>
4553e202c1Schristos #include <sys/rman.h>
4653e202c1Schristos 
4753e202c1Schristos #include <dev/acpi/acpireg.h>
4853e202c1Schristos #include <dev/acpi/acpivar.h>
4953e202c1Schristos #include <aml/aml_common.h>
5053e202c1Schristos #include <aml/aml_region.h>
5153e202c1Schristos #include <aml/aml_name.h>
5253e202c1Schristos 
5353e202c1Schristos #ifndef ACPI_NO_OSDFUNC_INLINE
5453e202c1Schristos #include <machine/acpica_osd.h>
5553e202c1Schristos #endif
5653e202c1Schristos 
5753e202c1Schristos /*
5853e202c1Schristos  * Dummy functions for aml_region_io_simple()
5953e202c1Schristos  */
6053e202c1Schristos u_int32_t
aml_region_prompt_read(struct aml_region_handle * h,u_int32_t value)6153e202c1Schristos aml_region_prompt_read(struct aml_region_handle *h, u_int32_t value)
6253e202c1Schristos {
6353e202c1Schristos 
6453e202c1Schristos 	return (value);
6553e202c1Schristos }
6653e202c1Schristos 
6753e202c1Schristos u_int32_t
aml_region_prompt_write(struct aml_region_handle * h,u_int32_t value)6853e202c1Schristos aml_region_prompt_write(struct aml_region_handle *h, u_int32_t value)
6953e202c1Schristos {
7053e202c1Schristos 
7153e202c1Schristos 	return (value);
7253e202c1Schristos }
7353e202c1Schristos 
7453e202c1Schristos int
aml_region_prompt_update_value(u_int32_t orgval,u_int32_t value,struct aml_region_handle * h)7553e202c1Schristos aml_region_prompt_update_value(u_int32_t orgval, u_int32_t value,
7653e202c1Schristos     struct aml_region_handle *h)
7753e202c1Schristos {
7853e202c1Schristos 	return (0);
7953e202c1Schristos }
8053e202c1Schristos 
8153e202c1Schristos /*
8253e202c1Schristos  * Primitive functions for aml_region_io_simple()
8353e202c1Schristos  */
8453e202c1Schristos int
aml_region_read_simple(struct aml_region_handle * h,vm_offset_t offset,u_int32_t * valuep)8553e202c1Schristos aml_region_read_simple(struct aml_region_handle *h, vm_offset_t offset, u_int32_t *valuep)
8653e202c1Schristos {
8753e202c1Schristos 	u_int32_t value;
8853e202c1Schristos 
8953e202c1Schristos 	switch (h->regtype) {
9053e202c1Schristos 	case AML_REGION_SYSMEM:
9153e202c1Schristos 		/* XXX should be MI */
9253e202c1Schristos 		switch (h->unit) {
9353e202c1Schristos 		case 1:
9453e202c1Schristos 			value = *(volatile u_int8_t *)(h->vaddr + offset);
9553e202c1Schristos 			value &= 0xff;
9653e202c1Schristos 			break;
9753e202c1Schristos 		case 2:
9853e202c1Schristos 			value = *(volatile u_int16_t *)(h->vaddr + offset);
9953e202c1Schristos 			value &= 0xffff;
10053e202c1Schristos 			break;
10153e202c1Schristos 		case 4:
10253e202c1Schristos 			value = *(volatile u_int32_t *)(h->vaddr + offset);
10353e202c1Schristos 			break;
10453e202c1Schristos 		}
10553e202c1Schristos 		break;
10653e202c1Schristos 	case AML_REGION_SYSIO:
10753e202c1Schristos 		switch (h->unit) {
10853e202c1Schristos 		case 1:
10953e202c1Schristos 			value = OsdIn8(h->addr + offset);
11053e202c1Schristos 			value &= 0xff;
11153e202c1Schristos 			break;
11253e202c1Schristos 		case 2:
11353e202c1Schristos 			value = OsdIn16(h->addr + offset);
11453e202c1Schristos 			value &= 0xffff;
11553e202c1Schristos 			break;
11653e202c1Schristos 		case 4:
11753e202c1Schristos 			value = OsdIn32(h->addr + offset);
11853e202c1Schristos 			break;
11953e202c1Schristos 		}
12053e202c1Schristos 		break;
12153e202c1Schristos 	case AML_REGION_PCICFG:
12253e202c1Schristos 		switch (h->unit) {
12353e202c1Schristos 		case 1:
12453e202c1Schristos 			OsdReadPciCfgByte(h->pci_bus, h->pci_devfunc,
12553e202c1Schristos 			    h->addr + offset, (UINT8 *)&value);
12653e202c1Schristos 			value &= 0xff;
12753e202c1Schristos 			break;
12853e202c1Schristos 		case 2:
12953e202c1Schristos 			OsdReadPciCfgWord(h->pci_bus, h->pci_devfunc,
13053e202c1Schristos 			    h->addr + offset, (UINT16 *)&value);
13153e202c1Schristos 			value &= 0xffff;
13253e202c1Schristos 			break;
13353e202c1Schristos 		case 4:
13453e202c1Schristos 			OsdReadPciCfgDword(h->pci_bus, h->pci_devfunc,
13553e202c1Schristos 			    h->addr + offset, &value);
13653e202c1Schristos 			break;
13753e202c1Schristos 		}
13853e202c1Schristos 		break;
13953e202c1Schristos 	default:
14053e202c1Schristos 		printf("aml_region_read_simple: not supported yet (%d)\n",
14153e202c1Schristos 		    h->regtype);
14253e202c1Schristos 		value = 0;
14353e202c1Schristos 		break;
14453e202c1Schristos 	}
14553e202c1Schristos 	*valuep = value;
14653e202c1Schristos 	return (0);
14753e202c1Schristos }
14853e202c1Schristos 
14953e202c1Schristos int
aml_region_write_simple(struct aml_region_handle * h,vm_offset_t offset,u_int32_t value)15053e202c1Schristos aml_region_write_simple(struct aml_region_handle *h, vm_offset_t offset, u_int32_t value)
15153e202c1Schristos {
15253e202c1Schristos 
15353e202c1Schristos 	switch (h->regtype) {
15453e202c1Schristos 	case AML_REGION_SYSMEM:
15553e202c1Schristos 		/* XXX should be MI */
15653e202c1Schristos 		switch (h->unit) {
15753e202c1Schristos 		case 1:
15853e202c1Schristos 			value &= 0xff;
15953e202c1Schristos 			*(volatile u_int8_t *)(h->vaddr + offset) = value;
16053e202c1Schristos 			break;
16153e202c1Schristos 		case 2:
16253e202c1Schristos 			value &= 0xffff;
16353e202c1Schristos 			*(volatile u_int16_t *)(h->vaddr + offset) = value;
16453e202c1Schristos 			break;
16553e202c1Schristos 		case 4:
16653e202c1Schristos 			*(volatile u_int32_t *)(h->vaddr + offset) = value;
16753e202c1Schristos 			break;
16853e202c1Schristos 		}
16953e202c1Schristos 		break;
17053e202c1Schristos 	case AML_REGION_SYSIO:
17153e202c1Schristos 		switch (h->unit) {
17253e202c1Schristos 		case 1:
17353e202c1Schristos 			value &= 0xff;
17453e202c1Schristos 			OsdOut8(h->addr + offset, value);
17553e202c1Schristos 			break;
17653e202c1Schristos 		case 2:
17753e202c1Schristos 			value &= 0xffff;
17853e202c1Schristos 			OsdOut16(h->addr + offset, value);
17953e202c1Schristos 			break;
18053e202c1Schristos 		case 4:
18153e202c1Schristos 			OsdOut32(h->addr + offset, value);
18253e202c1Schristos 			break;
18353e202c1Schristos 		}
18453e202c1Schristos 		break;
18553e202c1Schristos 	case AML_REGION_PCICFG:
18653e202c1Schristos 		switch (h->unit) {
18753e202c1Schristos 		case 1:
18853e202c1Schristos 			OsdWritePciCfgByte(h->pci_bus, h->pci_devfunc,
18953e202c1Schristos 			    h->addr + offset, value);
19053e202c1Schristos 			break;
19153e202c1Schristos 		case 2:
19253e202c1Schristos 			OsdWritePciCfgWord(h->pci_bus, h->pci_devfunc,
19353e202c1Schristos 			    h->addr + offset, value);
19453e202c1Schristos 			break;
19553e202c1Schristos 		case 4:
19653e202c1Schristos 			OsdWritePciCfgDword(h->pci_bus, h->pci_devfunc,
19753e202c1Schristos 			    h->addr + offset, value);
19853e202c1Schristos 			break;
19953e202c1Schristos 		}
20053e202c1Schristos 		break;
20153e202c1Schristos 	default:
20253e202c1Schristos 		printf("aml_region_write_simple: not supported yet (%d)\n",
20353e202c1Schristos 		    h->regtype);
20453e202c1Schristos 		break;
20553e202c1Schristos 	}
20653e202c1Schristos 
20753e202c1Schristos 	return (0);
20853e202c1Schristos }
20953e202c1Schristos 
21053e202c1Schristos 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)21153e202c1Schristos aml_region_io_buffer(boolean_t io, int regtype, u_int32_t flags,
21253e202c1Schristos     u_int8_t *buffer, u_int32_t baseaddr, u_int32_t bitoffset, u_int32_t bitlen)
21353e202c1Schristos {
21453e202c1Schristos 	vm_offset_t	addr, vaddr;
21553e202c1Schristos 	size_t		len;
21653e202c1Schristos 	const char	*funcname[] = {
21753e202c1Schristos 		"aml_region_read_into_buffer",
21853e202c1Schristos 		"aml_region_write_from_buffer"
21953e202c1Schristos 	};
22053e202c1Schristos 
22153e202c1Schristos 	if (regtype != AML_REGION_SYSMEM) {
22253e202c1Schristos 		printf("%s: region type isn't system memory!\n", funcname[io]);
22353e202c1Schristos 		return (-1);
22453e202c1Schristos 	}
22553e202c1Schristos 
22653e202c1Schristos 	if (bitlen % 8) {
22753e202c1Schristos 		printf("%s: bit length isn't a multiple of 8!\n", funcname[io]);
22853e202c1Schristos 	}
22953e202c1Schristos 	if (bitoffset % 8) {
23053e202c1Schristos 		printf("%s: bit offset isn't a multiple of 8!\n", funcname[io]);
23153e202c1Schristos 	}
23253e202c1Schristos 
23353e202c1Schristos 	addr = baseaddr + bitoffset / 8;
23453e202c1Schristos 	len = bitlen / 8 + ((bitlen % 8) ? 1 : 0);
23553e202c1Schristos 
23653e202c1Schristos 	OsdMapMemory((void *)addr, len, (void **)&vaddr);
23753e202c1Schristos 
23853e202c1Schristos 	switch (io) {
23953e202c1Schristos 	case AML_REGION_INPUT:
24053e202c1Schristos 		bcopy((void *)vaddr, (void *)buffer, len);
24153e202c1Schristos 		break;
24253e202c1Schristos 	case AML_REGION_OUTPUT:
24353e202c1Schristos 		bcopy((void *)buffer, (void *)vaddr, len);
24453e202c1Schristos 		break;
24553e202c1Schristos 	}
24653e202c1Schristos 
24753e202c1Schristos 	OsdUnMapMemory((void *)vaddr, len);
24853e202c1Schristos 
24953e202c1Schristos 	return (0);
25053e202c1Schristos }
25153e202c1Schristos 
25253e202c1Schristos 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)25353e202c1Schristos aml_region_read(struct aml_environ *env, int regtype, u_int32_t flags,
25453e202c1Schristos     u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen)
25553e202c1Schristos {
25653e202c1Schristos 	int	value;
25753e202c1Schristos 	int	state;
25853e202c1Schristos 
25953e202c1Schristos 	AML_REGION_READ_DEBUG(regtype, flags, addr, bitoffset, bitlen);
26053e202c1Schristos 
26153e202c1Schristos 	state = aml_region_io(env, AML_REGION_INPUT, regtype,
26253e202c1Schristos 	    flags, &value, addr, bitoffset, bitlen);
26353e202c1Schristos 	AML_SYSASSERT(state != -1);
26453e202c1Schristos 
26553e202c1Schristos         return (value);
26653e202c1Schristos }
26753e202c1Schristos 
26853e202c1Schristos 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)26953e202c1Schristos aml_region_read_into_buffer(struct aml_environ *env, int regtype,
27053e202c1Schristos     u_int32_t flags, u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen,
27153e202c1Schristos     u_int8_t *buffer)
27253e202c1Schristos {
27353e202c1Schristos 	int	state;
27453e202c1Schristos 
27553e202c1Schristos 	AML_REGION_READ_INTO_BUFFER_DEBUG(regtype, flags, addr, bitoffset, bitlen);
27653e202c1Schristos 	state = aml_region_io_buffer(AML_REGION_INPUT, regtype, flags,
27753e202c1Schristos 	    buffer, addr, bitoffset, bitlen);
27853e202c1Schristos 
27953e202c1Schristos         return (state);
28053e202c1Schristos }
28153e202c1Schristos 
28253e202c1Schristos 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)28353e202c1Schristos aml_region_write(struct aml_environ *env, int regtype, u_int32_t flags,
28453e202c1Schristos     u_int32_t value, u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen)
28553e202c1Schristos {
28653e202c1Schristos 	int	state;
28753e202c1Schristos 
28853e202c1Schristos 	AML_REGION_WRITE_DEBUG(regtype, flags, value, addr, bitoffset, bitlen);
28953e202c1Schristos 
29053e202c1Schristos 	state = aml_region_io(env, AML_REGION_OUTPUT, regtype,
29153e202c1Schristos 	    flags, &value, addr, bitoffset, bitlen);
29253e202c1Schristos 	AML_SYSASSERT(state != -1);
29353e202c1Schristos 
29453e202c1Schristos         return (state);
29553e202c1Schristos }
29653e202c1Schristos 
29753e202c1Schristos 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)29853e202c1Schristos aml_region_write_from_buffer(struct aml_environ *env, int regtype,
29953e202c1Schristos     u_int32_t flags, u_int8_t *buffer, u_int32_t addr, u_int32_t bitoffset,
30053e202c1Schristos     u_int32_t bitlen)
30153e202c1Schristos {
30253e202c1Schristos 	int	state;
30353e202c1Schristos 
30453e202c1Schristos 	AML_REGION_WRITE_FROM_BUFFER_DEBUG(regtype, flags,
30553e202c1Schristos 	    addr, bitoffset, bitlen);
30653e202c1Schristos 
30753e202c1Schristos 	state = aml_region_io_buffer(AML_REGION_OUTPUT, regtype, flags,
30853e202c1Schristos 	    buffer, addr, bitoffset, bitlen);
30953e202c1Schristos 
31053e202c1Schristos         return (state);
31153e202c1Schristos }
31253e202c1Schristos 
31353e202c1Schristos 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)31453e202c1Schristos aml_region_bcopy(struct aml_environ *env, int regtype,
31553e202c1Schristos     u_int32_t flags, u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen,
31653e202c1Schristos     u_int32_t dflags, u_int32_t daddr, u_int32_t dbitoffset, u_int32_t dbitlen)
31753e202c1Schristos {
31853e202c1Schristos 	vm_offset_t	from_addr, from_vaddr;
31953e202c1Schristos 	vm_offset_t	to_addr, to_vaddr;
32053e202c1Schristos 	size_t		len;
32153e202c1Schristos 
32253e202c1Schristos 	AML_REGION_BCOPY_DEBUG(regtype, flags, addr, bitoffset, bitlen,
32353e202c1Schristos 	    dflags, daddr, dbitoffset, dbitlen);
32453e202c1Schristos 
32553e202c1Schristos 	if (regtype != AML_REGION_SYSMEM) {
32653e202c1Schristos 		printf("aml_region_bcopy: region type isn't system memory!\n");
32753e202c1Schristos 		return (-1);
32853e202c1Schristos 	}
32953e202c1Schristos 
33053e202c1Schristos 	if ((bitlen % 8) || (dbitlen % 8)) {
33153e202c1Schristos 		printf("aml_region_bcopy: bit length isn't a multiple of 8!\n");
33253e202c1Schristos 	}
33353e202c1Schristos 	if ((bitoffset % 8) || (dbitoffset % 8)) {
33453e202c1Schristos 		printf("aml_region_bcopy: bit offset isn't a multiple of 8!\n");
33553e202c1Schristos 	}
33653e202c1Schristos 
33753e202c1Schristos 	from_addr = addr + bitoffset / 8;
33853e202c1Schristos 	to_addr = daddr + dbitoffset / 8;
33953e202c1Schristos 
34053e202c1Schristos 	len = (bitlen > dbitlen) ? dbitlen : bitlen;
34153e202c1Schristos 	len = len / 8 + ((len % 8) ? 1 : 0);
34253e202c1Schristos 
34353e202c1Schristos 	OsdMapMemory((void *)from_addr, len, (void **)&from_vaddr);
34453e202c1Schristos 	OsdMapMemory((void *)to_addr, len, (void **)&to_vaddr);
34553e202c1Schristos 
34653e202c1Schristos 	bcopy((void *)from_vaddr, (void *)to_vaddr, len);
34753e202c1Schristos 
34853e202c1Schristos 	OsdUnMapMemory((void *)from_vaddr, len);
34953e202c1Schristos 	OsdUnMapMemory((void *)to_vaddr, len);
35053e202c1Schristos 
35153e202c1Schristos 	return (0);
35253e202c1Schristos }
353