portable keyboard for pcpae kernels Reference: /n/atom/patch/applied/pckbpcpae Date: Tue May 6 19:46:19 CES 2014 Signed-off-by: quanstro@quanstro.net --- /sys/src/9/pcpae/fns.h Tue May 6 19:45:29 2014 +++ /sys/src/9/pcpae/fns.h Tue May 6 19:45:29 2014 @@ -14,6 +14,7 @@ int cpuidentify(void); void cpuidprint(void); void cycles(uvlong*); +int cas(int*, int, int); void delay(int); #define evenaddr(x) /* x86 doesn't care */ void fpclear(void); @@ -30,8 +31,10 @@ void halt(void); int i8042auxcmd(int); int i8042auxcmds(uchar*, int); -void i8042auxenable(void (*)(int, int)); +void i8042auxenable(void (*)(int)); void i8042reset(void); +void i8042kbdenable(void); +void i8042init(void); void i8250console(void); void* i8250alloc(int, int, int); void i8250mouse(char*, int (*)(Queue*, int), int); @@ -68,13 +71,11 @@ int iprint(char*, ...); int isaconfig(char*, int, ISAConf*); void* kaddr(uintmem); -void kbdenable(void); -void kbdinit(void); #define kmapinval() void lgdt(ushort[3]); void lidt(ushort[3]); void links(void); -void ltr(ulong); +void ltr(u32int); void mach0init(void); void mathinit(void); void mb586(void); @@ -117,7 +118,7 @@ int pcisetpms(Pcidev*, int); void pcmcisread(PCMslot*); int pcmcistuple(int, int, int, void*, int); -PCMmap* pcmmap(int, ulong, int, int); +PCMmap* pcmmap(int, u32int, int, int); int pcmspecial(char*, ISAConf*); int (*_pcmspecial)(char *, ISAConf *); void pcmspecialclose(int); @@ -139,8 +140,8 @@ void sfence(void); int strtotbdf(char*, char**, int); void syncclock(void); -void syscallfmt(int syscallno, uintptr pc, va_list list); -void sysretfmt(int syscallno, va_list list, long ret, uvlong start, uvlong stop); +void syscallfmt(int, uintptr, va_list); +void sysretfmt(int, va_list, long, uvlong, uvlong); void* tmpmap(Page*); void tmpunmap(void*); void touser(void*); --- /sys/src/9/pcpae/i8042.c Thu Jan 1 00:00:00 1970 +++ /sys/src/9/pcpae/i8042.c Tue May 6 19:45:29 2014 @@ -0,0 +1,337 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" + +enum { + Data= 0x60, /* data port */ + + Status= 0x64, /* status port */ + Inready= 0x01, /* input character ready */ + Outbusy= 0x02, /* output busy */ + Sysflag= 0x04, /* system flag */ + Cmddata= 0x08, /* cmd==0, data==1 */ + Inhibit= 0x10, /* keyboard/mouse inhibited */ + Minready= 0x20, /* mouse character ready */ + Rtimeout= 0x40, /* general timeout */ + Parity= 0x80, + + Cmd= 0x64, /* command port (write only) */ + + /* controller command byte */ + Cscs1= 1<<6, /* scan code set 1 */ + Cauxdis= 1<<5, /* mouse disable */ + Ckbddis= 1<<4, /* kbd disable */ + Csf= 1<<2, /* system flag */ + Cauxint= 1<<1, /* mouse interrupt enable */ + Ckbdint= 1<<0, /* kbd interrupt enable */ +}; + +extern int mouseshifted; + +static void (*auxputc)(int); +static Lock i8042lock; +static uchar ccc; +static Kbscan *scan; + +/* + * wait for output no longer busy + */ +static int +outready(void) +{ + int tries; + + for(tries = 0; (inb(Status) & Outbusy); tries++){ + if(tries > 500) + return -1; + delay(2); + } + return 0; +} + +/* + * wait for input + */ +static int +inready(void) +{ + int tries; + + for(tries = 0; !(inb(Status) & Inready); tries++){ + if(tries > 500) + return -1; + delay(2); + } + return 0; +} + +/* + * ask 8042 to reset the machine + */ +void +i8042reset(void) +{ + ushort *s; + int i, x; + + if(conf.nokbd) + return; + + s = KADDR(0x472); + *s = 0x1234; /* BIOS warm-boot flag */ + + /* + * newer reset the machine command + */ + outready(); + outb(Cmd, 0xFE); + outready(); + + /* + * Pulse it by hand (old somewhat reliable) + */ + x = 0xDF; + for(i = 0; i < 5; i++){ + x ^= 1; + outready(); + outb(Cmd, 0xD1); + outready(); + outb(Data, x); /* toggle reset */ + delay(100); + } +} + +/* + * keyboard interrupt + */ +static void +i8042intr(Ureg*, void*) +{ + int s, c; + + /* + * get status + */ + ilock(&i8042lock); + s = inb(Status); + if(!(s&Inready)){ + iunlock(&i8042lock); + return; + } + + /* + * get the character + */ + c = inb(Data); + iunlock(&i8042lock); + + /* + * if it's the aux port... + */ + if(s & Minready){ + if(auxputc != nil) + auxputc(c); + return; + } + kbdputsc(c, scan); +} + +void +i8042auxenable(void (*putc)(int)) +{ + char *err = "i8042: aux init failed\n"; + + /* enable kbd/aux xfers and interrupts */ + ccc &= ~Cauxdis; + ccc |= Cauxint; + + ilock(&i8042lock); + if(outready() < 0) + iprint(err); + outb(Cmd, 0x60); /* write control register */ + if(outready() < 0) + iprint(err); + outb(Data, ccc); + if(outready() < 0) + iprint(err); + outb(Cmd, 0xA8); /* auxiliary device enable */ + if(outready() < 0){ + iunlock(&i8042lock); + return; + } + auxputc = putc; + intrenable(IrqAUX, i8042intr, 0, BUSUNKNOWN, "kbdaux"); + iunlock(&i8042lock); +} + +static char *initfailed = "i8042: kbdinit failed\n"; + +static int +outbyte(int port, int c) +{ + outb(port, c); + if(outready() < 0) { + print(initfailed); + return -1; + } + return 0; +} + +int +i8042auxcmd(int cmd) +{ + uint c; + int tries; + + c = 0; + tries = 0; + + ilock(&i8042lock); + do{ + if(tries++ > 2) + break; + if(outready() < 0) + break; + outb(Cmd, 0xD4); + if(outready() < 0) + break; + outb(Data, cmd); + if(outready() < 0) + break; + if(inready() < 0) + break; + c = inb(Data); + } while(c == 0xFE || c == 0); + iunlock(&i8042lock); + + if(c != 0xFA){ + print("i8042: %2.2ux returned to the %2.2ux command\n", c, cmd); + return -1; + } + return 0; +} + +/* + * set keyboard's leds for lock states (scroll, numeric, caps). + * pc keyboards set numeric-lock behaviour to match the led state + */ +static void +setleds(int leds) +{ + if(conf.nokbd) + return; + ilock(&i8042lock); + outready(); + outb(Data, 0xed); /* talk directly to kbd, not ctlr */ + microdelay(1); + outready(); + if(inready() == 0) + inb(Data); + outb(Data, leds); + if(inready() == 0) + inb(Data); + + outready(); + iunlock(&i8042lock); +} + +static int +ledmsg(char *msg) +{ + int leds, c; + + leds = 0; + while(c = *msg++){ + switch(c){ + case 's': + leds |= 1<<0; + break; + case 'n': + leds |= 1<<1; + break; + case 'c': + leds |= 1<<2; + break; + } + } + return leds; +} + +static void +i8042msg(char *msg) +{ + switch(*msg){ + case 'L': + setleds(ledmsg(msg+1)); + break; + } +} + +void +failkbd(void) +{ + conf.nokbd = 1; + iofree(Data); + iofree(Cmd); + print(initfailed); +} + +void +i8042init(void) +{ + int c, try; + + if(conf.nokbd) + return; + + ioalloc(Data, 1, 0, "kbd data"); + ioalloc(Cmd, 1, 0, "kbd cmd"); + + /* wait for a quiescent controller */ + try = 1000; + while(try-- > 0 && (c = inb(Status)) & (Outbusy | Inready)) { + if(c & Inready) + inb(Data); + delay(1); + } + if (try <= 0) { + failkbd(); + return; + } + + /* get current controller command byte */ + outb(Cmd, 0x20); + if(inready() < 0){ + print("i8042: kbdinit can't read ccc\n"); + ccc = 0; + } else + ccc = inb(Data); + + /* enable kbd xfers and interrupts */ + ccc &= ~Ckbddis; + ccc |= Csf | Ckbdint | Cscs1; + if(outready() < 0) { + failkbd(); + return; + } + + /* disable mouse */ + if (outbyte(Cmd, 0x60) < 0 || outbyte(Data, ccc) < 0) + print("i8042: kbdinit mouse disable failed\n"); + + /* set typematic rate/delay (0 -> delay=250ms & rate=30cps) */ + if(outbyte(Cmd, 0xf3) < 0 || outbyte(Data, 0) < 0) + print("i8042: kbdinit set typematic rate failed\n"); +} + +void +i8042kbdenable(void) +{ + if(!conf.nokbd){ + intrenable(IrqKBD, i8042intr, 0, BUSUNKNOWN, "i8042"); + scan = kbdnewscan(i8042msg); + } +} --- /sys/src/9/pcpae/main.c Tue May 6 19:45:29 2014 +++ /sys/src/9/pcpae/main.c Tue May 6 19:45:29 2014 @@ -94,7 +94,7 @@ trapinit0(); mmuinit0(); - kbdinit(); + i8042init(); i8253init(); cpuidentify(); meminit(); @@ -112,6 +112,7 @@ timersinit(); mathinit(); kbdenable(); + i8042kbdenable(); if(arch->clockenable) arch->clockenable(); procinit0(); --- /sys/src/9/pcpae/mkfile Tue May 6 19:45:29 2014 +++ /sys/src/9/pcpae/mkfile Tue May 6 19:45:29 2014 @@ -45,7 +45,7 @@ cga.$O\ i8253.$O\ i8259.$O\ - kbd.$O\ + i8042.$O\ main.$O\ memory.$O\ mmu.$O\ --- /sys/src/9/pcpae/mouse.c Tue May 6 19:45:29 2014 +++ /sys/src/9/pcpae/mouse.c Tue May 6 19:45:29 2014 @@ -103,14 +103,14 @@ static void resetmouse(void); static void -ps2mouseputc(int c, int shift) +ps2mouseputc(int c) { static short msg[4]; static int nb, aa; static uchar b[] = {0, 1, 4, 5, 2, 3, 6, 7, 0, 1, 2, 3, 2, 3, 6, 7 }; static ulong lasttick; ulong m; - int buttons, dx, dy; + int shift, buttons, dx, dy; if(c == 0xaa){ aa = 1; @@ -127,7 +127,7 @@ * non-ps2 keyboards might not set shift * but still set mouseshifted. */ - shift |= mouseshifted; + shift = mouseshifted; /* * Resynchronize in stream with timing; see comment above. */ @@ -205,7 +205,7 @@ mousetype = MousePS2; packetsize = 3; mousehwaccel = 1; -resetmouse(); + resetmouse(); } /* --- /sys/src/9/pcpae/pae Tue May 6 19:45:29 2014 +++ /sys/src/9/pcpae/pae Tue May 6 19:45:29 2014 @@ -24,13 +24,12 @@ draw drawalloc screen vga vgax swcursor mouse mouse vga - kbmap - kbin sd sdalloc audio uart + pckb usb link @@ -39,7 +38,7 @@ ether8139 pci ether8169 pci ethermii ether82557 pci - ether82563 pci + etherigbe pci ethermii ether82563 pci etherbcm pci etherigbe pci ethermii @@ -89,7 +88,7 @@ il bootdir - bootpae.out boot + boot$CONF.out boot /386/bin/ip/ipconfig /386/bin/auth/factotum /386/bin/usb/usbd --- /sys/src/9/pcpae/paecpu Tue May 6 19:45:29 2014 +++ /sys/src/9/pcpae/paecpu Tue May 6 19:45:29 2014 @@ -16,6 +16,7 @@ cap kprof # fs + snap trace archtrace ether netif @@ -26,6 +27,7 @@ sd sdalloc uart + pckb # usb link @@ -37,10 +39,9 @@ ether8169 pci ethermii ether82557 pci ether82563 pci - ether82563 pci # ether83815 pci etherbcm pci -# etherigbe pci ethermii + etherigbe pci ethermii # etheryuk pci etherm10g pci ether82598 pci @@ -90,8 +91,8 @@ il bootdir - bootpaecpu.out boot - /386/bin/ip/ipconfig ipconfig + boot$CONF.out boot + /386/bin/ip/ipconfig /386/bin/auth/factotum lib /$objtype/lib/libaml.a --- /sys/src/9/pcpae/paecpuf Tue May 6 19:45:29 2014 +++ /sys/src/9/pcpae/paecpuf Tue May 6 19:45:29 2014 @@ -27,6 +27,7 @@ sd sdalloc uart + pckb usb link @@ -91,7 +92,7 @@ il bootdir - bootpaecpuf.out boot + boot$CONF.out boot /386/bin/ip/ipconfig /386/bin/auth/factotum # /386/bin/disk/kfs --- /sys/src/9/pcpae/paed Tue May 6 19:45:29 2014 +++ /sys/src/9/pcpae/paed Tue May 6 19:45:29 2014 @@ -13,8 +13,8 @@ ssl tls cap - trace archtrace kprof + trace archtrace fs ether netif @@ -25,13 +25,12 @@ draw drawalloc screen vga vgax swcursor mouse mouse vga - kbmap - kbin sd sdalloc audio uart + pckb usb link @@ -91,7 +90,7 @@ local bootdir - bootpaed.out boot + boot$CONF.out boot /386/bin/ip/ipconfig /386/bin/auth/factotum /386/bin/disk/kfs --- /sys/src/9/pcpae/paef Tue May 6 19:45:29 2014 +++ /sys/src/9/pcpae/paef Tue May 6 19:45:29 2014 @@ -24,13 +24,12 @@ draw drawalloc screen vga vgax swcursor mouse mouse vga - kbmap - kbin sd sdalloc audio uart + pckb usb link @@ -40,7 +39,6 @@ ether8169 pci ethermii ether82557 pci ether82563 pci - ether82563 pci etherbcm pci etherigbe pci ethermii ethermedium @@ -90,7 +88,7 @@ local bootdir - bootpaef.out boot + boot$CONF.out boot /386/bin/ip/ipconfig /386/bin/auth/factotum /386/bin/fossil/fossil