1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <unistd.h>
5#include <fcntl.h>
6#include <malloc.h>
7
8/* ioctl crap */
9#define SYREN_RD		101
10#define SYREN_WR		102
11#define SYREN_OLD_RD	108
12#define SYREN_OLD_WR	109
13
14struct syren_io_args {
15	unsigned long	page;
16	unsigned long	addr;
17	unsigned long	value;
18};
19
20typedef struct {
21	u_char			page;
22	u_char			addr;
23	const char		*name;
24} syren_reg;
25
26static syren_reg registers[] = {
27	{ 0, 0x04, "TOGBR1" },
28	{ 0, 0x05, "TOGBR2" },
29	{ 0, 0x06, "VBDCTRL" },
30	{ 1, 0x07, "VBUCTRL" },
31	{ 1, 0x08, "VBCTRL" },
32	{ 1, 0x09, "PWDNRG" },
33	{ 1, 0x0a, "VBPOP" },
34	{ 1, 0x0b, "VBCTRL2" },
35	{ 1, 0x0f, "VAUDCTRL" },
36	{ 1, 0x10, "VAUSCTRL" },
37	{ 1, 0x11, "VAUOCTRL" },
38	{ 1, 0x12, "VAUDPLL" },
39	{ 1, 0x17, "VRPCSIMR" },
40	{ 0, 0, 0 }
41};
42
43static syren_reg *find_reg(const char *name)
44{
45	int i;
46
47	for (i = 0; registers[i].name != 0; i++) {
48		if (!strcasecmp(registers[i].name, name))
49			return &registers[i];
50	}
51
52	return NULL;
53}
54
55static int usage(void)
56{
57	fprintf(stderr, "usage: syren [r/w] [REGNAME | page:addr] (value)\n");
58	return 1;
59}
60
61int
62syren_main(int argc, char **argv)
63{
64	int cmd = -1;
65	syren_reg *r;
66	struct syren_io_args sio;
67	char name[32];
68	int fd;
69
70	if (argc < 3) {
71		return usage();
72	}
73
74	switch(argv[1][0]) {
75	case 'r':
76		cmd = SYREN_RD;
77		break;
78	case 'w':
79		cmd = SYREN_WR;
80		break;
81	case 'R':
82		cmd = SYREN_OLD_RD;
83		break;
84	case 'W':
85		cmd = SYREN_OLD_WR;
86		break;
87	default:
88		return usage();
89	}
90
91	if (cmd == SYREN_WR || cmd == SYREN_OLD_WR) {
92		if (argc < 4)
93			return usage();
94		sio.value = strtoul(argv[3], 0, 0);
95	}
96
97	fd = open("/dev/eac", O_RDONLY);
98	if (fd < 0) {
99		fprintf(stderr, "can't open /dev/eac\n");
100		return 1;
101	}
102
103	if (strcasecmp(argv[2], "all") == 0) {
104		int i;
105		if (cmd != SYREN_RD && cmd != SYREN_OLD_RD) {
106			fprintf(stderr, "can only read all registers\n");
107			return 1;
108		}
109
110		for (i = 0; registers[i].name; i++) {
111			sio.page = registers[i].page;
112			sio.addr = registers[i].addr;
113			if (ioctl(fd, cmd, &sio) < 0) {
114				fprintf(stderr, "%s: error\n", registers[i].name);
115			} else {
116				fprintf(stderr, "%s: %04x\n", registers[i].name, sio.value);
117			}
118		}
119
120		close(fd);
121		return 0;
122	}
123
124	r = find_reg(argv[2]);
125	if (r == NULL) {
126		strcpy(name, argv[2]);
127		char *addr_str = strchr(argv[2], ':');
128		if (addr_str == NULL)
129			return usage();
130		*addr_str++ = 0;
131		sio.page = strtoul(argv[2], 0, 0);
132		sio.addr = strtoul(addr_str, 0, 0);
133	} else {
134		strcpy(name, r->name);
135		sio.page = r->page;
136		sio.addr = r->addr;
137	}
138
139	if (ioctl(fd, cmd, &sio) < 0) {
140		fprintf(stderr, "ioctl(%d) failed\n", cmd);
141		return 1;
142	}
143
144	if (cmd == SYREN_RD || cmd == SYREN_OLD_RD) {
145		printf("%s: %04x\n", name, sio.value);
146	} else {
147		printf("wrote %04x to %s\n", sio.value, name);
148	}
149
150	close(fd);
151
152	return 0;
153}
154
155