Home | History | Annotate | Line # | Download | only in aml
      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 (at) FreeBSD.org>
      5  * Copyright (c) 2000 Munehiro Matsuda <haro (at) 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
     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
     68 aml_region_prompt_write(struct aml_region_handle *h, u_int32_t value)
     69 {
     70 
     71 	return (value);
     72 }
     73 
     74 int
     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
     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
    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
    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
    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
    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
    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
    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
    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