|  | #include <stdio.h> | 
|  | #include <stdlib.h> | 
|  | #include <string.h> | 
|  | #include <unistd.h> | 
|  | #include <fcntl.h> | 
|  | #include <malloc.h> | 
|  |  | 
|  | /* ioctl crap */ | 
|  | #define SYREN_RD		101 | 
|  | #define SYREN_WR		102 | 
|  | #define SYREN_OLD_RD	108 | 
|  | #define SYREN_OLD_WR	109 | 
|  |  | 
|  | struct syren_io_args { | 
|  | unsigned long	page; | 
|  | unsigned long	addr; | 
|  | unsigned long	value; | 
|  | }; | 
|  |  | 
|  | typedef struct { | 
|  | u_char			page; | 
|  | u_char			addr; | 
|  | const char		*name; | 
|  | } syren_reg; | 
|  |  | 
|  | static syren_reg registers[] = { | 
|  | { 0, 0x04, "TOGBR1" }, | 
|  | { 0, 0x05, "TOGBR2" }, | 
|  | { 0, 0x06, "VBDCTRL" }, | 
|  | { 1, 0x07, "VBUCTRL" }, | 
|  | { 1, 0x08, "VBCTRL" }, | 
|  | { 1, 0x09, "PWDNRG" }, | 
|  | { 1, 0x0a, "VBPOP" }, | 
|  | { 1, 0x0b, "VBCTRL2" }, | 
|  | { 1, 0x0f, "VAUDCTRL" }, | 
|  | { 1, 0x10, "VAUSCTRL" }, | 
|  | { 1, 0x11, "VAUOCTRL" }, | 
|  | { 1, 0x12, "VAUDPLL" }, | 
|  | { 1, 0x17, "VRPCSIMR" }, | 
|  | { 0, 0, 0 } | 
|  | }; | 
|  |  | 
|  | static syren_reg *find_reg(const char *name) | 
|  | { | 
|  | int i; | 
|  |  | 
|  | for (i = 0; registers[i].name != 0; i++) { | 
|  | if (!strcasecmp(registers[i].name, name)) | 
|  | return ®isters[i]; | 
|  | } | 
|  |  | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | static int usage(void) | 
|  | { | 
|  | fprintf(stderr, "usage: syren [r/w] [REGNAME | page:addr] (value)\n"); | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | int | 
|  | syren_main(int argc, char **argv) | 
|  | { | 
|  | int cmd = -1; | 
|  | syren_reg *r; | 
|  | struct syren_io_args sio; | 
|  | char name[32]; | 
|  | int fd; | 
|  |  | 
|  | if (argc < 3) { | 
|  | return usage(); | 
|  | } | 
|  |  | 
|  | switch(argv[1][0]) { | 
|  | case 'r': | 
|  | cmd = SYREN_RD; | 
|  | break; | 
|  | case 'w': | 
|  | cmd = SYREN_WR; | 
|  | break; | 
|  | case 'R': | 
|  | cmd = SYREN_OLD_RD; | 
|  | break; | 
|  | case 'W': | 
|  | cmd = SYREN_OLD_WR; | 
|  | break; | 
|  | default: | 
|  | return usage(); | 
|  | } | 
|  |  | 
|  | if (cmd == SYREN_WR || cmd == SYREN_OLD_WR) { | 
|  | if (argc < 4) | 
|  | return usage(); | 
|  | sio.value = strtoul(argv[3], 0, 0); | 
|  | } | 
|  |  | 
|  | fd = open("/dev/eac", O_RDONLY); | 
|  | if (fd < 0) { | 
|  | fprintf(stderr, "can't open /dev/eac\n"); | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | if (strcasecmp(argv[2], "all") == 0) { | 
|  | int i; | 
|  | if (cmd != SYREN_RD && cmd != SYREN_OLD_RD) { | 
|  | fprintf(stderr, "can only read all registers\n"); | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | for (i = 0; registers[i].name; i++) { | 
|  | sio.page = registers[i].page; | 
|  | sio.addr = registers[i].addr; | 
|  | if (ioctl(fd, cmd, &sio) < 0) { | 
|  | fprintf(stderr, "%s: error\n", registers[i].name); | 
|  | } else { | 
|  | fprintf(stderr, "%s: %04x\n", registers[i].name, sio.value); | 
|  | } | 
|  | } | 
|  |  | 
|  | close(fd); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | r = find_reg(argv[2]); | 
|  | if (r == NULL) { | 
|  | if(strlen(argv[2]) >= sizeof(name)){ | 
|  | fprintf(stderr, "REGNAME too long\n"); | 
|  | return 0; | 
|  | } | 
|  | strlcpy(name, argv[2], sizeof(name)); | 
|  | char *addr_str = strchr(argv[2], ':'); | 
|  | if (addr_str == NULL) | 
|  | return usage(); | 
|  | *addr_str++ = 0; | 
|  | sio.page = strtoul(argv[2], 0, 0); | 
|  | sio.addr = strtoul(addr_str, 0, 0); | 
|  | } else { | 
|  | strlcpy(name, r->name, sizeof(name)); | 
|  | sio.page = r->page; | 
|  | sio.addr = r->addr; | 
|  | } | 
|  |  | 
|  | if (ioctl(fd, cmd, &sio) < 0) { | 
|  | fprintf(stderr, "ioctl(%d) failed\n", cmd); | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | if (cmd == SYREN_RD || cmd == SYREN_OLD_RD) { | 
|  | printf("%s: %04x\n", name, sio.value); | 
|  | } else { | 
|  | printf("wrote %04x to %s\n", sio.value, name); | 
|  | } | 
|  |  | 
|  | close(fd); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  |