Index: geode.c =================================================================== RCS file: /home/ncvs/src/sys/i386/i386/geode.c,v retrieving revision 1.3 diff -u -r1.3 geode.c --- geode.c 28 Feb 2004 22:33:28 -0000 1.3 +++ geode.c 20 Mar 2004 22:46:07 -0000 @@ -27,6 +27,20 @@ #include __FBSDID("$FreeBSD: src/sys/i386/i386/geode.c,v 1.3 2004/02/28 22:33:28 phk Exp $"); +#include +#include + +struct onew { + u_int rst; + u_int xmt; + u_int rcv; + uint8_t d[32]; +}; + +#define ONEW _IOWR('1', 0, struct onew) + +#ifdef _KERNEL + #include #include #include @@ -42,6 +56,189 @@ static unsigned gpio; static unsigned geode_counter; +/******************************************************************/ + +#include + +static u_int atms, porti, porto; +static uint8_t pd, pdh, pdl; + +#define onew_high() outb(porto, pdh) +#define onew_low() outb(porto, pdl) +#define onew_in() inb(porti) + +static void +onew_reset(void) +{ + int i; + u_long eflags; + + eflags = read_eflags(); + disable_intr(); + onew_high(); + for (i = 0; i < 480; i++) + onew_low(); + onew_high(); + write_eflags(eflags); + for (i = 0; i < 1000; i++) + onew_high(); + +} + +static void +onew_wr0(void) +{ + int i; + u_long eflags; + + eflags = read_eflags(); + disable_intr(); + for (i = 0; i < 60; i++) + onew_low(); + onew_high(); + write_eflags(eflags); + for (i = 0; i < 10; i++) + onew_high(); + +} + +static void +onew_wr1(void) +{ + int i; + u_long eflags; + + eflags = read_eflags(); + disable_intr(); + onew_low(); + onew_high(); + write_eflags(eflags); + for (i = 0; i < 60; i++) + onew_high(); + +} + +static void +onew_wr8(int i) +{ + + if (i & 0x01) onew_wr1(); else onew_wr0(); + if (i & 0x02) onew_wr1(); else onew_wr0(); + if (i & 0x04) onew_wr1(); else onew_wr0(); + if (i & 0x08) onew_wr1(); else onew_wr0(); + if (i & 0x10) onew_wr1(); else onew_wr0(); + if (i & 0x20) onew_wr1(); else onew_wr0(); + if (i & 0x40) onew_wr1(); else onew_wr0(); + if (i & 0x80) onew_wr1(); else onew_wr0(); +} + +static int +onew_rd1(void) +{ + int i, x, y; + u_long eflags; + + eflags = read_eflags(); + disable_intr(); + onew_low(); + onew_high(); + x = onew_in(); + write_eflags(eflags); + for (i = 0; i < 60; i++) + y = onew_in(); + do + y = onew_in(); + while (!(y & 4)); + return (x & 4 ? 1 : 0); +} + +static u_int +onew_rd8(void) +{ + u_int u; + + u = 0; + u |= onew_rd1() << 0; + u |= onew_rd1() << 1; + u |= onew_rd1() << 2; + u |= onew_rd1() << 3; + u |= onew_rd1() << 4; + u |= onew_rd1() << 5; + u |= onew_rd1() << 6; + u |= onew_rd1() << 7; + return (u); +} + + +static int +onew_ioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td) +{ + struct onew *op; + int i; + uint8_t *p; + + if (cmd != ONEW) + return (ENOIOCTL); + + op = (void *)data; +#if 0 + printf("rst %d xmt %d rcv %d -> ", op->rst, op->xmt, op->rcv); + hexdump (op->d, sizeof op->d, "d:", HD_OMIT_COUNT | HD_OMIT_CHARS); +#endif + if (op->rst) + onew_reset(); + p = op->d; + for (i = 0; i < op->xmt; i++) + onew_wr8(*p++); + for (i = 0; i < op->rcv; i++) + *p++ = onew_rd8(); + return (0); +} + +static struct cdevsw onew_cdevsw = { + .d_version = D_VERSION, + .d_flags = D_NEEDGIANT, + .d_ioctl = onew_ioctl, + .d_name = "ONEW", +}; + +static void +onew_init(void) +{ + int i; + + outb(0x2e, 0x20); + i = inb(0x2f); + if (i != 0xe9) { + printf("Expected 0xe9 for superIO ID, got 0x%x\n", i); + return; + } + + outb(0x2e, 0x07); outb(0x2f, 0x07); + outb(0x2e, 0x60); atms = inb(0x2f) << 8; + outb(0x2e, 0x61); atms |= inb(0x2f); + outb(0x2e, 0x30); i = inb(0x2f); + if (!(i & 1)) { + printf("GPIO not enabled\n"); + return; + } + printf("ATMS %x\n", atms); + outb(0x2e, 0xf0); outb(0x2f, 0x12); + outb(0x2e, 0xf1); outb(0x2f, 0x03); + + porto = atms + 4; + porti = atms + 5; + pd = inb(porti); + pdl = pd & ~0x4; + pdh = pd | 0x4; + + make_dev(&onew_cdevsw, 0, + UID_ROOT, GID_WHEEL, 0600, "onew"); + +} + +/*****************************************************************/ + #ifdef CPU_SOEKRIS #include @@ -130,6 +327,8 @@ tc_init(&geode_timecounter); EVENTHANDLER_REGISTER(watchdog_list, geode_watchdog, NULL, 0); + + onew_init(); } } else if (pci_get_devid(self) == 0x0510100b) { gpio = pci_read_config(self, PCIR_BAR(0), 4); @@ -168,3 +367,4 @@ static devclass_t geode_devclass; DRIVER_MODULE(geode, pci, geode_driver, geode_devclass, 0, 0); +#endif /* _KERNEL */