Mercurial > ~darius > hgwebdir.cgi > hwmon
view pcmon/pcmonhelper.c @ 0:c34b37680055 default tip
Inital commit of random SuperIO code.
author | Daniel O'Connor <darius@dons.net.au> |
---|---|
date | Thu, 20 Oct 2011 16:48:24 +1030 |
parents | |
children |
line wrap: on
line source
#define _WITH_GETLINE #include <stdio.h> #include <errno.h> #include <string.h> #include <fcntl.h> #include <stdlib.h> #include <sys/types.h> #include <machine/cpufunc.h> #include <unistd.h> /* Prototypes */ void ec_outb(uint16_t base, uint8_t adr, uint8_t val); uint8_t ec_inb(uint16_t base, uint8_t adr); void ec_run(uint16_t base); void freeargs(char **args, size_t nargs); void splitline(char *line, char ***args, size_t *nargs); void superio_enter(uint16_t base, char type); void superio_exit(uint16_t base, char type); uint8_t superio_inb(uint8_t base, uint8_t adr); void superio_outb(uint16_t base, uint8_t adr, uint8_t val); void usage(char *name); void usage(char *name) { fprintf(stderr, "Bad usage\n" "\t%s [-b base] [-t type]\n" "\n" "Read/write registers in the EC function of Winbond/ITE parts\n" "base is the base address for the chip (default: 0x2e)\n" "type is the chip type (i = ITE, w = WinBond)\n", name); exit(1); } int main(int argc, char **argv) { int fd, base, ch, ecbase, devid; char *progname, type; type = 'w'; base = 0x2e; progname = argv[0]; while ((ch = getopt(argc, argv, "b:t:")) != -1) { switch (ch) { case 'b': base = strtol(optarg, NULL, 0) & 0xffff; break; case 't': if (optarg[0] != 'w' && optarg[0] != 'i') { fprintf(stderr, "type must be w or i\n\n"); usage(progname); } type = optarg[0]; break; default: usage(progname); break; } } argc -= optind; argv += optind; if (argc != 0) usage(progname); if ((fd = open("/dev/io", O_RDWR)) == -1) { fprintf(stderr, "Can't open /dev/io: %s\n", strerror(errno)); exit(1); } /* Enter extended function mode */ superio_enter(base, type); /* Check device ID */ devid = superio_inb(base, 0x20) << 8 | superio_inb(base, 0x21); printf("Device ID = 0x%04x\n", devid); if (devid != 0x8720) { fprintf(stderr, "Device ID mismatch\n"); superio_exit(base, type); exit(1); } /* Select EC config registers */ superio_outb(base, 0x7, 4); /* Determine EC base address */ ecbase = superio_inb(base, 0x60) << 8; ecbase |= superio_inb(base, 0x61); /* Exit extended function mode */ superio_exit(base, type); ec_run(ecbase); exit(0); } /* Enter extended function mode */ void superio_enter(uint16_t base, char type) { if (type == 'w') { outb(base, 0x87); outb(base, 0x87); } else { outb(base, 0x87); outb(base, 0x01); outb(base, 0x55); outb(base, 0x55); } } /* Exit extended function mode */ void superio_exit(uint16_t base, char type) { if (type == 'w') { outb(base, 0xaa); outb(base, 0xaa); } else { outb(base, 0x02); outb(base, 0x02); } } void superio_outb(uint16_t base, uint8_t adr, uint8_t val) { outb(base, adr); outb(base + 1, val); } uint8_t superio_inb(uint8_t base, uint8_t adr) { outb(base, adr); return(inb(base + 1)); } void ec_outb(uint16_t base, uint8_t adr, uint8_t val) { outb(base + 5, adr); outb(base + 6, val); } uint8_t ec_inb(uint16_t base, uint8_t adr) { outb(base + 5, adr); return(inb(base + 6)); } void ec_run(uint16_t base) { char *line = NULL, **args = NULL, *p; size_t llen = 0, nargs; long tmp; uint8_t adr, val; printf("EC base address = 0x%04x\n", base); printf("EC Vendor ID = 0x%02x\n", ec_inb(base, 0x58)); printf("EC Core ID = 0x%02x\n", ec_inb(base, 0x5b)); while (1) { if (getline(&line, &llen, stdin) == -1) break; /* Snip trailing new line*/ *rindex(line, '\n')= '\0'; splitline(line, &args, &nargs); if (nargs != 2 && nargs != 3) { printf("Unable to parse line\n"); continue; } tmp = strtol(args[1], &p, 0); if (p == args[1]) { printf("Unable to parse address\n"); continue; } if (tmp < 0 || tmp > 255) { printf("Address out of range\n"); continue; } adr = tmp; if (!strcmp("read", args[0])) { if (nargs != 2) { printf("Bad usage of read command\n"); continue; } printf("0x%02x -> 0x%02x\n", adr, ec_inb(base, adr)); } else if (!strcmp("write", args[0])) { if (nargs != 3) { printf("Bad usage of write command\n"); continue; } tmp = strtol(args[2], &p, 0); if (p == args[1]) { printf("Unable to parse value\n"); continue; } if (tmp < 0 || tmp > 255) { printf("Value out of range\n"); continue; } val = tmp; ec_outb(base, adr, val); printf("0x%02x <- 0x%02x\n", adr, val); } else { printf("Unable to parse line\n"); } } free(line); } void splitline(char *line, char ***args, size_t *nargs) { char *token; freeargs(*args, *nargs); *args = NULL; *nargs = 0; while ((token = strsep(&line, " ")) != NULL) { *args = realloc(*args, sizeof(char *) * (*nargs + 1)); if (args == NULL) { fprintf(stderr, "Unable to allocate memory\n"); exit(1); } (*args)[*nargs] = malloc(strlen(token) + 1); strcpy((*args)[*nargs], token); (*nargs)++; } } void freeargs(char **args, size_t nargs) { int i; if (args != NULL) { for (i = 0; i < nargs; i++) free(args[i]); free(args); } }