#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <err.h>
#include <sys/types.h>
#include <sys/cdefs.h>
#include <machine/cpufunc.h>

#define VREF	1.235
#define V245	2.45

#define VDIV(a, b)	(((a) + (b)) / (a))
struct avi {
	const char 	*name;
	double		offset;
	double		scale;
} avi[14] = {
	{ "avi0",	0.0,	1.0 },
	{ "VCORE",	0.0,	1.0 },
	{ "VCC",	0.0,	VDIV(10.0, 10.0) },
	{ "VPWR",	0.0,	VDIV(10.0, 191.0) },
	{ "+12V",	0.0,	VDIV(10.0, 38.3) },
	{ "-12V",	3.33,	VDIV(3.32, 60.4) },
	{ "GND",	0.0,	1.0 },
	{ "Vsb",	0.0,	2.0 },
	{ "Vdd",	0.0,	2.0 },
	{ "Vbat",	0.0,	1.0 },
	{ "AVdd",	0.0,	2.0 },
	{ "TS1",	0.0,	1.0 },
	{ "TS2",	0.0,	1.0 },
	{ "TS3",	0.0,	1.0 }
};

int
main(int argc, char **argv)
{
	FILE *f;
	int i, j, atms, avlm;
	struct avi *avp;
	double a;
	double vref = VREF;

	f = fopen("/dev/io", "r");
	if (f == NULL)
		err(1, "Could not open /dev/io");
	outb(0x2e, 0x20);
	i = inb(0x2f);
	if (i != 0xe9)
		errx(1, "Expected 0xe9 for SuperIO ID, got %x", i);

	outb(0x2e, 0x7);  outb(0x2f, 0xe);
	outb(0x2e, 0x60); atms = inb(0x2f) * 256;
	outb(0x2e, 0x61); atms |= inb(0x2f);
	outb(0x2e, 0x30); i = inb(0x2f);
	if (!(i & 1))
		errx(1, "TMS not enabled");

	outb(0x2e, 0x7);  outb(0x2f, 0xd);
	outb(0x2e, 0x60); avlm = inb(0x2f) * 256;
	outb(0x2e, 0x61); avlm |= inb(0x2f);
	outb(0x2e, 0x30); i = inb(0x2f);
	if (!(i & 1))
		errx(1, "VLM not enabled");

	if (argc == 2 && !strcmp(argv[1], "-i")) {
		/* Magic init sequence from page 208 */
		outb(atms + 0x8, 0x00);
		outb(atms + 0x9, 0x0f);
		outb(atms + 0xa, 0x08);
		outb(atms + 0xb, 0x04);
		outb(atms + 0xc, 0x35);
		outb(atms + 0xd, 0x05);
		outb(atms + 0xe, 0x05);

		outb(atms + 8, 0);
		for(i = 0; i < 3; i++) {
			outb(atms + 9, i);
			outb(atms + 0xa, 1);
		}
		outb(avlm + 7, 0x10);
		outb(avlm + 8, 0);
		for(i = 0; i < 10; i++) {
			outb(avlm + 9, i);
			outb(avlm + 0xa, 1);
		}
		for(; i < 14; i++) {
			outb(avlm + 9, i);
			outb(avlm + 0xa, 0);
		}
		return (0);
	}
	if (argc >= 2 && !strcmp(argv[1], "-r")) {
		vref = strtod(argv[2], NULL);
	}

	printf("VREF = %.3f  V245 = %.3f\n", vref, V245);

	for(i = 2; i < 3; i++) {
		outb(atms + 9, i);
		printf("Temp %d (status=0x%2x) %4d C\n", i, 
		    inb(atms + 0xa), (char)inb(atms + 0xb));

	}

#if 0
	/* The offset for the -12V is measured on AD10 */
	i = 10;
	avp = &avi[i];
	outb(avlm + 9, i);
	j = inb(avlm + 0x0b);
	a = vref * V245 * j / 256.0;
	avi[5].offset = a * avp->scale;
#endif

	for(i = 1; i < 11; i++) {
		avp = &avi[i];
		outb(avlm + 9, i);
		j = inb(avlm + 0x0b);
		a = vref * V245 * j / 256.0;
		printf(
		    "Volt %2d %-5s %3d %6.3f V scale %4.1f %7.3f V +/- %6.4f V\n",
		    i, avp->name, j, a,
		    avp->scale, (a - avp->offset) * avp->scale + avp->offset, 
		    vref * V245 / 256.0 * avp->scale);
	}
	return (0);
}


syntax highlighted by Code2HTML, v. 0.9.1