#include <err.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/param.h>
#include <sys/mman.h>

uint16_t *mmcr;

static int dir;

static void
W(int a, unsigned d)
{
	mmcr[a / 2] = d;
}

static unsigned
R(int a)
{
	return (mmcr[a/2]);
}

static void
BO(int i)
{
	u_int u;

	if (i) 
		W(0xc34, 0x0080);
	else
		W(0xc38, 0x0080);
	if (dir == 0) {
		u = R(0xc2a);
		W(0xc2a, u | 0x0080);
		dir = 1;
	}
	W(0xc34, 0x0100);
	W(0xc34, 0x0100);
	W(0xc34, 0x0100);
	W(0xc34, 0x0100);
	W(0xc38, 0x0100);
	W(0xc38, 0x0100);
	W(0xc38, 0x0100);
	W(0xc38, 0x0100);
}

static int
BI(void)
{
	u_int u;

	if (dir == 1) {
		u = R(0xc2a);
		W(0xc2a, u & ~0x0080);
		dir = 0;
	}
	W(0xc34, 0x0100);
	W(0xc34, 0x0100);
	W(0xc34, 0x0100);
	W(0xc34, 0x0100);
	u = R(0xc30) & 0x0080;
	W(0xc38, 0x0100);
	W(0xc38, 0x0100);
	W(0xc38, 0x0100);
	W(0xc38, 0x0100);
	return (u ? 1 : 0);
}

static void
START(void)
{
	u_int u;

	W(0xc34, 0x0180);
	if (dir == 0) {
		u = R(0xc2a);
		W(0xc2a, u | 0x0080);
		dir = 1;
	}
	W(0xc38, 0x0080);
	W(0xc38, 0x0100);
	W(0xc38, 0x0100);
}

static void
STOP(void)
{
	u_int u;

	W(0xc38, 0x0080);
	if (dir == 0) {
		u = R(0xc2a);
		W(0xc2a, u | 0x0080);
		dir = 1;
	}
	W(0xc34, 0x0100);
	W(0xc34, 0x0100);
	W(0xc34, 0x0100);
	W(0xc34, 0x0100);
	W(0xc34, 0x0080);
}

int
main(int argc __unused, char **argv __unused)
{
	int fd;
	int i;
	u_int j, u;
	char buf1[20];
	char buf2[20];

	fd = open("/dev/elan-mmcr", O_RDWR);
	if (fd < 0)
		err(1, "/dev/elan-mmcr");
	mmcr = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
	printf("mmcr = %p\n", mmcr);

	u = R(0xc2a);
	W(0xc2a, u | 0x0180);
	W(0xc34, 0x0180);

	u = 0;
	START();
	BO(1);
	BO(0);
	BO(0);
	BO(1);
	BO(u & 4);
	BO(u & 2);
	BO(u & 1);
	BO(0);
	BI();
	for (i = 0; i < 6; i++)
		BO(0);
	BO(0);
	BO(0);
	BI();
	STOP();
	while (1) {
		usleep(1000000);
		printf("%u: ", u);
		START();
		BO(1);
		BO(0);
		BO(0);
		BO(1);
		BO(u & 4);
		BO(u & 2);
		BO(u & 1);
		BO(1);
		for (i = 0; i < 9; i++)
			buf1[i] = BI();
		BO(0);
		for (i = 0; i < 8; i++)
			buf2[i] = BI();
		BO(1);
		STOP();

		printf("%d ", buf1[0]);
		j = 0;
		for (i = 1; i < 9; i++) {
			printf("%d", buf1[i]);
			j |= buf1[i];
			j += j;
		}
		printf(" ");
		for (i = 0; i < 8; i++) {
			printf("%d", buf2[i]);
			j |= buf2[i];
			j += j;
		}

		printf(" %x %u %f\n", j, j, j / 512.0);
	}

	
	return (0);
}
