Home | History | Annotate | Line # | Download | only in amldb
region.c revision 1.1
      1 /*	$NetBSD: region.c,v 1.1 2007/01/14 04:36:13 christos Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1999 Mitsuru IWASAKI <iwasaki (at) FreeBSD.org>
      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  *	Id: region.c,v 1.14 2000/08/08 14:12:25 iwasaki Exp
     29  *	$FreeBSD: src/usr.sbin/acpi/amldb/region.c,v 1.4 2000/11/19 13:29:43 kris Exp $
     30  */
     31 #include <sys/cdefs.h>
     32 __RCSID("$NetBSD: region.c,v 1.1 2007/01/14 04:36:13 christos Exp $");
     33 
     34 /*
     35  * Region I/O subroutine
     36  */
     37 
     38 #include <sys/param.h>
     39 #include <sys/queue.h>
     40 
     41 #include <acpi_common.h>
     42 #include <aml/aml_amlmem.h>
     43 #include <aml/aml_name.h>
     44 #include <aml/aml_region.h>
     45 #include <aml/aml_common.h>
     46 
     47 #include <assert.h>
     48 #include <err.h>
     49 #include <stdlib.h>
     50 #include <stdio.h>
     51 #include <string.h>
     52 #include <unistd.h>
     53 
     54 #include "debug.h"
     55 
     56 int	aml_debug_prompt_regoutput = 0;
     57 int	aml_debug_prompt_reginput = 1;
     58 
     59 static void	aml_simulation_regload(const char *dumpfile);
     60 
     61 struct ACPIRegionContent {
     62 	TAILQ_ENTRY(ACPIRegionContent) links;
     63 	int		regtype;
     64 	u_int32_t	addr;
     65 	u_int8_t	value;
     66 };
     67 
     68 TAILQ_HEAD(ACPIRegionContentList, ACPIRegionContent);
     69 struct	ACPIRegionContentList RegionContentList;
     70 
     71 static int	aml_simulation_initialized = 0;
     72 
     73 static void
     74 aml_simulation_init(void)
     75 {
     76 
     77 	aml_simulation_initialized = 1;
     78 	TAILQ_INIT(&RegionContentList);
     79 	aml_simulation_regload("region.ini");
     80 }
     81 
     82 static int
     83 aml_simulate_regcontent_add(int regtype, u_int32_t addr, u_int8_t value)
     84 {
     85 	struct	ACPIRegionContent *rc;
     86 
     87 	rc = malloc(sizeof(struct ACPIRegionContent));
     88 	if (rc == NULL) {
     89 		return (-1);	/* malloc fail */
     90 	}
     91 	rc->regtype = regtype;
     92 	rc->addr = addr;
     93 	rc->value = value;
     94 
     95 	TAILQ_INSERT_TAIL(&RegionContentList, rc, links);
     96 	return (0);
     97 }
     98 
     99 static int
    100 aml_simulate_regcontent_read(int regtype, u_int32_t addr, u_int8_t *valuep)
    101 {
    102 	struct	ACPIRegionContent *rc;
    103 
    104 	if (!aml_simulation_initialized) {
    105 		aml_simulation_init();
    106 	}
    107 	TAILQ_FOREACH(rc, &RegionContentList, links) {
    108 		if (rc->regtype == regtype && rc->addr == addr) {
    109 			*valuep = rc->value;
    110 			return (1);	/* found */
    111 		}
    112 	}
    113 
    114 	return (aml_simulate_regcontent_add(regtype, addr, 0));
    115 }
    116 
    117 static int
    118 aml_simulate_regcontent_write(int regtype, u_int32_t addr, u_int8_t *valuep)
    119 {
    120 	struct	ACPIRegionContent *rc;
    121 
    122 	if (!aml_simulation_initialized) {
    123 		aml_simulation_init();
    124 	}
    125 	TAILQ_FOREACH(rc, &RegionContentList, links) {
    126 		if (rc->regtype == regtype && rc->addr == addr) {
    127 			rc->value = *valuep;
    128 			return (1);	/* exists */
    129 		}
    130 	}
    131 
    132 	return (aml_simulate_regcontent_add(regtype, addr, *valuep));
    133 }
    134 
    135 static u_int32_t
    136 aml_simulate_prompt(char *msg, u_int32_t def_val)
    137 {
    138 	char		buf[16], *ep;
    139 	u_int32_t	val;
    140 
    141 	val = def_val;
    142 	printf("DEBUG");
    143 	if (msg != NULL) {
    144 		printf("%s", msg);
    145 	}
    146 	printf("(default: 0x%x / %u) >>", val, val);
    147 	fflush(stdout);
    148 
    149 	bzero(buf, sizeof buf);
    150 	while (1) {
    151 		if (read(0, buf, sizeof buf) == 0) {
    152 			continue;
    153 		}
    154 		if (buf[0] == '\n') {
    155 			break;	/* use default value */
    156 		}
    157 		if (buf[0] == '0' && buf[1] == 'x') {
    158 			val = strtoq(buf, &ep, 16);
    159 		} else {
    160 			val = strtoq(buf, &ep, 10);
    161 		}
    162 		break;
    163 	}
    164 	return (val);
    165 }
    166 
    167 static void
    168 aml_simulation_regload(const char *dumpfile)
    169 {
    170 	char	buf[256], *np, *ep;
    171 	struct	ACPIRegionContent rc;
    172 	FILE	*fp;
    173 
    174 	if (!aml_simulation_initialized) {
    175 		return;
    176 	}
    177 	if ((fp = fopen(dumpfile, "r")) == NULL) {
    178 		warn("%s", dumpfile);
    179 		return;
    180 	}
    181 	while (fgets(buf, sizeof buf, fp) != NULL) {
    182 		np = buf;
    183 		/* reading region type */
    184 		rc.regtype = strtoq(np, &ep, 10);
    185 		if (np == ep) {
    186 			continue;
    187 		}
    188 		np = ep;
    189 
    190 		/* reading address */
    191 		rc.addr = strtoq(np, &ep, 16);
    192 		if (np == ep) {
    193 			continue;
    194 		}
    195 		np = ep;
    196 
    197 		/* reading value */
    198 		rc.value = strtoq(np, &ep, 16);
    199 		if (np == ep) {
    200 			continue;
    201 		}
    202 		aml_simulate_regcontent_write(rc.regtype, rc.addr, &rc.value);
    203 	}
    204 
    205 	fclose(fp);
    206 }
    207 
    208 int
    209 aml_region_read_simple(struct aml_region_handle *h, vm_offset_t offset,
    210     u_int32_t *valuep)
    211 {
    212 	int		i, state;
    213 	u_int8_t	val;
    214 	u_int32_t	value;
    215 
    216 	state = 0;
    217 	value = val = 0;
    218 	for (i = 0; i < h->unit; i++) {
    219 		state = aml_simulate_regcontent_read(h->regtype,
    220 		    h->addr + offset + i, &val);
    221 		if (state == -1) {
    222 			goto out;
    223 		}
    224 		value |= val << (i * 8);
    225 	}
    226 	*valuep = value;
    227 out:
    228 	return (state);
    229 }
    230 
    231 int
    232 aml_region_write_simple(struct aml_region_handle *h, vm_offset_t offset,
    233     u_int32_t value)
    234 {
    235 	int		i, state;
    236 	u_int8_t	val;
    237 
    238 	state = 0;
    239 	val = 0;
    240 	for (i = 0; i < h->unit; i++) {
    241 		val = value & 0xff;
    242 		state = aml_simulate_regcontent_write(h->regtype,
    243 		    h->addr + offset + i, &val);
    244 		if (state == -1) {
    245 			goto out;
    246 		}
    247 		value = value >> 8;
    248 	}
    249 out:
    250 	return (state);
    251 }
    252 
    253 u_int32_t
    254 aml_region_prompt_read(struct aml_region_handle *h, u_int32_t value)
    255 {
    256 	u_int32_t 	retval;
    257 	char		buf[64];
    258 
    259 	retval = value;
    260 	sprintf(buf, "[read(%d, 0x%lx)&mask:0x%x]",
    261 	    h->regtype, h->addr, value);
    262 	if (aml_debug_prompt_reginput) {
    263 		retval = aml_simulate_prompt(buf, value);
    264 	} else {
    265 		printf("\t%s\n", buf);
    266 	}
    267 
    268 	return (retval);
    269 }
    270 
    271 u_int32_t
    272 aml_region_prompt_write(struct aml_region_handle *h, u_int32_t value)
    273 {
    274 	u_int32_t 	retval;
    275 	char		buf[64];
    276 
    277 	retval = value;
    278 	if (aml_debug_prompt_regoutput) {
    279 		printf("\n");
    280 		sprintf(buf, "[write(%d, 0x%x, 0x%lx)]",
    281 		    h->regtype, value, h->addr);
    282 		retval = aml_simulate_prompt(buf, value);
    283 	}
    284 
    285 	return (retval);
    286 }
    287 
    288 int
    289 aml_region_prompt_update_value(u_int32_t orgval, u_int32_t value,
    290     struct aml_region_handle *h)
    291 {
    292 	int	state;
    293 
    294 	state = 0;
    295 	if (orgval != value) {
    296 		state = aml_region_io(h->env, AML_REGION_OUTPUT, h->regtype,
    297 		    h->flags, &value, h->baseaddr, h->bitoffset, h->bitlen);
    298 		if (state == -1) {
    299 			goto out;
    300 		}
    301 	}
    302 
    303 out:
    304 	return (state);
    305 }
    306 
    307 static int
    308 aml_simulate_region_io_buffer(int io, int regtype, u_int32_t flags,
    309     u_int8_t *buffer, u_int32_t baseaddr, u_int32_t bitoffset, u_int32_t bitlen)
    310 {
    311 	u_int8_t	val;
    312 	u_int8_t	offsetlow, offsethigh;
    313 	u_int32_t	addr, byteoffset, bytelen;
    314 	int		state, i;
    315 
    316 	val = 0;
    317 	offsetlow = offsethigh = 0;
    318 	state = 0;
    319 
    320 	byteoffset = bitoffset / 8;
    321 	bytelen = bitlen / 8 + ((bitlen % 8) ? 1 : 0);
    322 	addr = baseaddr + byteoffset;
    323 	offsetlow = bitoffset % 8;
    324 	assert(offsetlow == 0);
    325 
    326 	if (bytelen > 1) {
    327 		offsethigh = (bitlen - (8 - offsetlow)) % 8;
    328 	}
    329 	assert(offsethigh == 0);
    330 
    331 	for (i = bytelen; i > 0; i--, addr++) {
    332 		switch (io) {
    333 		case AML_REGION_INPUT:
    334 			val = 0;
    335 			state = aml_simulate_regcontent_read(regtype, addr, &val);
    336 			if (state == -1) {
    337 				goto finish;
    338 			}
    339 			buffer[bytelen - i] = val;
    340 			break;
    341 		case AML_REGION_OUTPUT:
    342 			val = buffer[bytelen - i];
    343 			state = aml_simulate_regcontent_write(regtype,
    344 			    addr, &val);
    345 			if (state == -1) {
    346 				goto finish;
    347 			}
    348 			break;
    349 		}
    350 	}
    351 finish:
    352 	return (state);
    353 }
    354 
    355 static u_int32_t
    356 aml_simulate_region_read(struct aml_environ *env, int regtype,
    357     u_int32_t flags, u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen)
    358 {
    359 	u_int32_t	value;
    360 	int	state;
    361 
    362 	state = aml_region_io(env, AML_REGION_INPUT, regtype, flags, &value,
    363 	    addr, bitoffset, bitlen);
    364 	assert(state != -1);
    365 	return (value);
    366 }
    367 
    368 static int
    369 aml_simulate_region_read_into_buffer(int regtype, u_int32_t flags,
    370     u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen, u_int8_t *buffer)
    371 {
    372 	int	state;
    373 
    374 	state = aml_simulate_region_io_buffer(AML_REGION_INPUT, regtype, flags,
    375 	    buffer, addr, bitoffset, bitlen);
    376 	assert(state != -1);
    377 	return (state);
    378 }
    379 
    380 static int
    381 aml_simulate_region_write(struct aml_environ *env, int regtype,
    382     u_int32_t flags, u_int32_t value, u_int32_t addr, u_int32_t bitoffset,
    383     u_int32_t bitlen)
    384 {
    385 	int	state;
    386 
    387 	state = aml_region_io(env, AML_REGION_OUTPUT, regtype, flags,
    388 	    &value, addr, bitoffset, bitlen);
    389 	assert(state != -1);
    390 	return (state);
    391 }
    392 
    393 static int
    394 aml_simulate_region_write_from_buffer(int regtype, u_int32_t flags,
    395     u_int8_t *buffer, u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen)
    396 {
    397 	int	state;
    398 
    399 	state = aml_simulate_region_io_buffer(AML_REGION_OUTPUT, regtype,
    400 	    flags, buffer, addr, bitoffset, bitlen);
    401 	assert(state != -1);
    402 	return (state);
    403 }
    404 
    405 static int
    406 aml_simulate_region_bcopy(struct aml_environ *env, int regtype,
    407     u_int32_t flags, u_int32_t addr,
    408     u_int32_t bitoffset, u_int32_t bitlen,
    409     u_int32_t dflags, u_int32_t daddr,
    410     u_int32_t dbitoffset, u_int32_t dbitlen)
    411 {
    412 	u_int32_t	len, i;
    413 	u_int32_t	value;
    414 	int		state;
    415 
    416 	len = (bitlen > dbitlen) ? dbitlen : bitlen;
    417 	len = len / 8 + ((len % 8) ? 1 : 0);
    418 
    419 	for (i = 0; i < len; i++) {
    420 		state = aml_region_io(env, AML_REGION_INPUT, regtype,
    421 		    flags, &value, addr, bitoffset + i * 8, 8);
    422 		assert(state != -1);
    423 		state = aml_region_io(env, AML_REGION_OUTPUT, regtype,
    424 		    dflags, &value, daddr, dbitoffset + i * 8, 8);
    425 		assert(state != -1);
    426 	}
    427 
    428 	return (0);
    429 }
    430 
    431 u_int32_t
    432 aml_region_read(struct aml_environ *env, int regtype, u_int32_t flags,
    433     u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen)
    434 {
    435 
    436 	AML_REGION_READ_DEBUG(regtype, flags, addr, bitoffset, bitlen);
    437 
    438 	return (aml_simulate_region_read(env, regtype, flags, addr,
    439 	    bitoffset, bitlen));
    440 }
    441 
    442 int
    443 aml_region_read_into_buffer(struct aml_environ *env, int regtype,
    444     u_int32_t flags, u_int32_t addr, u_int32_t bitoffset,
    445     u_int32_t bitlen, u_int8_t *buffer)
    446 {
    447 
    448 	AML_REGION_READ_INTO_BUFFER_DEBUG(regtype, flags, addr, bitoffset, bitlen);
    449 
    450 	return (aml_simulate_region_read_into_buffer(regtype, flags, addr,
    451 	    bitoffset, bitlen, buffer));
    452 }
    453 
    454 int
    455 aml_region_write(struct aml_environ *env, int regtype, u_int32_t flags,
    456     u_int32_t value, u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen)
    457 {
    458 
    459 	AML_REGION_WRITE_DEBUG(regtype, flags, value, addr, bitoffset, bitlen);
    460 
    461 	return (aml_simulate_region_write(env, regtype, flags, value, addr,
    462 	    bitoffset, bitlen));
    463 }
    464 
    465 int
    466 aml_region_write_from_buffer(struct aml_environ *env, int regtype,
    467     u_int32_t flags, u_int8_t *buffer, u_int32_t addr, u_int32_t bitoffset,
    468     u_int32_t bitlen)
    469 {
    470 
    471 	AML_REGION_WRITE_FROM_BUFFER_DEBUG(regtype, flags,
    472 	    addr, bitoffset, bitlen);
    473 
    474 	return (aml_simulate_region_write_from_buffer(regtype, flags, buffer,
    475 	    addr, bitoffset, bitlen));
    476 }
    477 
    478 int
    479 aml_region_bcopy(struct aml_environ *env, int regtype, u_int32_t flags,
    480     u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen,
    481     u_int32_t dflags, u_int32_t daddr,
    482     u_int32_t dbitoffset, u_int32_t dbitlen)
    483 {
    484 
    485 	AML_REGION_BCOPY_DEBUG(regtype, flags, addr, bitoffset, bitlen,
    486 	    dflags, daddr, dbitoffset, dbitlen);
    487 
    488 	return (aml_simulate_region_bcopy(env, regtype, flags, addr, bitoffset,
    489 	    bitlen, dflags, daddr, dbitoffset, dbitlen));
    490 }
    491 
    492 void
    493 aml_simulation_regdump(const char *dumpfile)
    494 {
    495 	struct	ACPIRegionContent *rc;
    496 	FILE	*fp;
    497 
    498 	if (!aml_simulation_initialized) {
    499 		return;
    500 	}
    501 	if ((fp = fopen(dumpfile, "w")) == NULL) {
    502 		warn("%s", dumpfile);
    503 		return;
    504 	}
    505 	while (!TAILQ_EMPTY(&RegionContentList)) {
    506 		rc = TAILQ_FIRST(&RegionContentList);
    507 		fprintf(fp, "%d	0x%x	0x%x\n",
    508 		    rc->regtype, rc->addr, rc->value);
    509 		TAILQ_REMOVE(&RegionContentList, rc, links);
    510 		free(rc);
    511 	}
    512 
    513 	fclose(fp);
    514 	TAILQ_INIT(&RegionContentList);
    515 }
    516