# HG changeset patch # User Daniel O'Connor # Date 1319091504 -37800 # Node ID c34b37680055651fdbe625af82d04eff7fa22363 Inital commit of random SuperIO code. diff -r 000000000000 -r c34b37680055 Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile Thu Oct 20 16:48:24 2011 +1030 @@ -0,0 +1,3 @@ +SUBDIR= io superio wbio wbread + +.include diff -r 000000000000 -r c34b37680055 io/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/io/Makefile Thu Oct 20 16:48:24 2011 +1030 @@ -0,0 +1,5 @@ +PROG= io + +NO_MAN= + +.include diff -r 000000000000 -r c34b37680055 io/io.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/io/io.c Thu Oct 20 16:48:24 2011 +1030 @@ -0,0 +1,42 @@ +#include +#include +#include +#include +#include +#include +#include + +void +usage(char *name) { + fprintf(stderr, + "Bad usage\n" + "\t%s adr [data]\n" + "\n" + "Read/write adr with data\n", name); + exit(1); +} + +int +main(int argc, char **argv) { + int fd, adr, data; + + if (argc != 2 && argc != 3) + usage(argv[0]); + + if ((fd = open("/dev/io", O_RDWR)) == -1) { + fprintf(stderr, "Can't open /dev/io: %s\n", strerror(errno)); + exit(1); + } + + adr = strtol(argv[1], NULL, 0) & 0xffff; + + if (argc == 3) { + data = strtol(argv[2], NULL, 0) & 0xff; + printf("0x%02x <- 0x%02x\n", adr, data); + outb(adr, data); + } else + printf("0x%02x -> 0x%02x\n", adr, inb(adr)); + + exit(0); +} + diff -r 000000000000 -r c34b37680055 pcmon/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pcmon/Makefile Thu Oct 20 16:48:24 2011 +1030 @@ -0,0 +1,7 @@ +PROG= pcmonhelper + +CFLAGS+=-g -Wall + +NO_MAN= + +.include diff -r 000000000000 -r c34b37680055 pcmon/pcmon.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pcmon/pcmon.py Thu Oct 20 16:48:24 2011 +1030 @@ -0,0 +1,13 @@ +#!/usr/bin/env python + +import subprocess + +baseadr = 0x2e +type = 'i' + +class pcmon(object): + def __init__(self): + p = subprocess.Popen(["./pcmonhelper", "-b", "0x%x" % (baseadr), "-t", type], stdout=subprocess.PIPE, stdin=subprocess.PIPE) + +if __name__ == "__main__": + pass diff -r 000000000000 -r c34b37680055 pcmon/pcmonhelper.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pcmon/pcmonhelper.c Thu Oct 20 16:48:24 2011 +1030 @@ -0,0 +1,252 @@ +#define _WITH_GETLINE + +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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); + } +} + diff -r 000000000000 -r c34b37680055 superio/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/superio/Makefile Thu Oct 20 16:48:24 2011 +1030 @@ -0,0 +1,5 @@ +PROG= superio + +NO_MAN= + +.include diff -r 000000000000 -r c34b37680055 superio/superio.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/superio/superio.c Thu Oct 20 16:48:24 2011 +1030 @@ -0,0 +1,112 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +void +usage(char *name) { + fprintf(stderr, + "Bad usage\n" + "\t%s [-b base] [-d dev] [-t type] adr [data]\n" + "\n" + "Read/write registers in Winbond SuperIO parts\n" + "base is the base address for the chip (default: 0x2e)\n" + "dev is the sub-device to talk to (default: -1/global)\n" + "type is the chip type (i = ITE, w = WinBond)\n" + "adr is the register to read/write\n" + "data is the data to write to adr\n", name); + exit(1); +} + +int +main(int argc, char **argv) { + int fd, base, dev, type, adr, data, ch; + char *progname; + + type = 'w'; + base = 0x2e; + dev = -1; + + progname = argv[0]; + + while ((ch = getopt(argc, argv, "b:d:t:")) != -1) { + switch (ch) { + case 'b': + base = strtol(optarg, NULL, 0) & 0xffff; + break; + + case 'd': + dev = strtol(optarg, NULL, 0) & 0xff; + 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 != 1 && argc != 2) + usage(progname); + + if ((fd = open("/dev/io", O_RDWR)) == -1) { + fprintf(stderr, "Can't open /dev/io: %s\n", strerror(errno)); + exit(1); + } + + adr = strtol(argv[0], NULL, 0) & 0xff; + + /* Enter extended function mode */ + if (type == 'w') { + outb(base, 0x87); + outb(base, 0x87); + } else { + /* Taken from the Linux driver drivers/hwmon/it87.c */ + outb(base, 0x87); + outb(base, 0x01); + outb(base, 0x55); + outb(base, 0x55); + } + + /* Sub device to select (skip if global) */ + if (dev != -1) { + outb(base, 0x07); /* Logical device select register */ + outb(base + 1, dev & 0xff); + } + + /* Register to access */ + outb(base, adr); + + if (argc == 2) { + data = strtol(argv[1], NULL, 0) & 0xff; + printf("Bank 0x%02x: 0x%02x <- 0x%02x\n", dev, adr, data); + outb(base + 1, data); + } else + printf("Bank 0x%02x: 0x%02x -> 0x%02x\n", dev, adr, inb(base + 1)); + + /* Exit extended function mode */ + if (type == 'w') { + outb(base, 0xaa); + outb(base, 0xaa); + } else { + outb(base, 0x02); + outb(base, 0x02); + } + + exit(0); +} + diff -r 000000000000 -r c34b37680055 wbio/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wbio/Makefile Thu Oct 20 16:48:24 2011 +1030 @@ -0,0 +1,5 @@ +PROG= wbio + +NO_MAN= + +.include diff -r 000000000000 -r c34b37680055 wbio/wbio.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wbio/wbio.c Thu Oct 20 16:48:24 2011 +1030 @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +void +usage(char *name) { + fprintf(stderr, + "Bad usage\n" + "\t%s [-b base] adr [data]\n" + "\n" + "Read/write registers in Winbond SuperIO parts\n" + "base is the base address for the chip (default: 0x290)\n" + "adr is the register to read/write\n" + "data is the data to write to adr\n", name); + exit(1); +} + +int +main(int argc, char **argv) { + int fd, base, dev, adr, data, ch, type; + char *progname; + +#define WB_ADR 0x5 +#define WB_DATA 0x6 + + base = 0x290; + + progname = argv[0]; + + while ((ch = getopt(argc, argv, "b:")) != -1) { + switch (ch) { + case 'b': + base = strtol(optarg, NULL, 0) & 0xffff; + break; + + default: + usage(progname); + break; + } + } + argc -= optind; + argv += optind; + + if (argc != 1 && argc != 2) + usage(progname); + + if ((fd = open("/dev/io", O_RDWR)) == -1) { + fprintf(stderr, "Can't open /dev/io: %s\n", strerror(errno)); + exit(1); + } + + adr = strtol(argv[0], NULL, 0) & 0xff; + + /* Register to access */ + outb(base + WB_ADR, adr); + + if (argc == 2) { + data = strtol(argv[1], NULL, 0) & 0xff; + printf("Base 0x%02x: 0x%02x <- 0x%02x\n", base, adr, data); + outb(base + WB_DATA, data); + } else + printf("Bank 0x%02x: 0x%02x -> 0x%02x\n", dev, adr, inb(base + WB_DATA)); + + exit(0); +} + diff -r 000000000000 -r c34b37680055 wbread/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wbread/Makefile Thu Oct 20 16:48:24 2011 +1030 @@ -0,0 +1,7 @@ +PROG= wbread + +NO_MAN= + +CFLAGS+=-Wall + +.include diff -r 000000000000 -r c34b37680055 wbread/wbread.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wbread/wbread.c Thu Oct 20 16:48:24 2011 +1030 @@ -0,0 +1,105 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define VPERLSB 0.008 +#define MAXDIG (VPERLSB * 256) + +#define WB_ADR 0x5 +#define WB_DATA 0x6 + +void +usage(char *name) { + fprintf(stderr, + "Bad usage\n" + "\t%s [-b base]\n" + "\n" + "Read/write registers in Winbond SuperIO parts\n" + "base is the base address for the chip (default: 0x290)\n" + "adr is the register to read/write\n" + "data is the data to write to adr\n", name); + exit(1); +} + +int +readwb(int base, int adr) { + /* Register to access */ + outb(base + WB_ADR, adr); + + return(inb(base + WB_DATA)); +} + +void +writewb(int base, int adr, int val) { + /* Register to access */ + outb(base + WB_ADR, adr); + + outb(base + WB_DATA, val); +} + +float +raw2volt(int val, float r1, float r2) { + float digval, result; + + digval = val * VPERLSB; + result = digval * ((r1 + r2) / r2); + return(result); +} + +float +raw2negvolt(int val, float r1, float r2) { + return((val * 0.008 - 2.048)/(r2 / (r1 + r2))) + 2.048; +} + +float +raw2rpm(int val, int divisor) { + return(1360000 / (float)(val) / divisor); +} + +int +raw2divisor(int val) { + return(1 << val); +} + +int +main(int argc, char **argv) { + int fd, base, ch, tmp; + char *progname; + + base = 0x290; + + progname = argv[0]; + + while ((ch = getopt(argc, argv, "b:")) != -1) { + switch (ch) { + case 'b': + base = strtol(optarg, NULL, 0) & 0xffff; + break; + + default: + usage(progname); + break; + } + } + argc -= optind; + argv += optind; + + if ((fd = open("/dev/io", O_RDWR)) == -1) { + fprintf(stderr, "Can't open /dev/io: %s\n", strerror(errno)); + exit(1); + } + + printf("3V3 = %.2f V\n", raw2volt(readwb(base, 0x23), 34000, 34000)); + printf("-12V = %.2f V\n", raw2negvolt(readwb(base, 0x26), 232000, 10000)); + tmp = (readwb(base, 0x47) & 0xc0) >> 6; + tmp |= (readwb(base, 0x5d) & 0x40) >> 4; + tmp = raw2divisor(tmp); + printf("CPU fan = %.0f rpm (divisor %d)\n", raw2rpm(readwb(base, 0x29), tmp), tmp); + exit(0); +} +