/*
	writeb.c
	
	Write 8-bit integers to memory-mapped I/O.
	
	Andy Lowe, MontaVista Software, 9/26/2006
*/

#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#include <fcntl.h>
#include <stdio.h>

#define TYPE unsigned char

/* function prototypes */
void write_element(volatile unsigned char *p, TYPE data);

int main(int argc, char *argv[])
{
	volatile unsigned char *p;
	int fd;
	unsigned base;
	unsigned offset;
	unsigned cnt;
	unsigned map_start, map_size, map_offset;
	unsigned data;
	int i;

	if ((fd = open("/dev/mem", O_RDWR)) < 0) {
		perror("open");
		exit(1);
	}

	if (argc < 4) {
		printf("Usage:  %s <base> <offset> <val1> [<val2> <val3> ...]\n", argv[0]);
		printf("        All arguments are in hex.\n");
		exit(1);
	}

	sscanf(argv[1], "%x", &base);
	sscanf(argv[2], "%x", &offset);
	cnt = argc - 3;

	if (((base + offset) < base)
		|| ((base + offset + cnt*sizeof(TYPE)) < (base + offset)))
	{
		perror("Invalid offset.\n");
		exit(1);
	}

	map_start = (base + offset) & ~0xfff;
	map_offset = (base + offset) & 0xfff;
	map_size = (map_offset + cnt*sizeof(TYPE) + 0xfff) & ~0xfff;

	p = (volatile unsigned char *) mmap((void *) 0, map_size,
					PROT_READ | PROT_WRITE, MAP_SHARED, fd,
					map_start);

	for (i = 0; i < cnt; ++i) {
		sscanf(argv[i + 3], "%x", &data);
		write_element(p + map_offset + i*sizeof(TYPE), data);
	}

	exit(0);
}

void write_element(volatile unsigned char *p, TYPE data)
{
	*(volatile TYPE *) p = data;
}
