kbdfs
This commit is contained in:
parent
67856b4507
commit
26c2845917
20 changed files with 1674 additions and 1611 deletions
|
@ -14,6 +14,7 @@ bind -a #S /dev
|
|||
|
||||
# mount points
|
||||
mount -a /srv/slashn /n
|
||||
mount -b /srv/cons /dev
|
||||
|
||||
# authentication
|
||||
mount -a /srv/factotum /mnt
|
||||
|
|
|
@ -2,6 +2,12 @@
|
|||
|
||||
bind -q '#p' /proc
|
||||
|
||||
if(test -e '#b' && ! test -e /dev/kbd){
|
||||
bind -a '#b' /dev
|
||||
aux/kbdfs -s cons
|
||||
exec /rc/bin/bootrc </dev/cons >/dev/cons >[2]/dev/cons
|
||||
}
|
||||
|
||||
bind -qa '#S' /dev
|
||||
bind -qa '#f' /dev
|
||||
bind -qa '#k' /dev
|
||||
|
|
481
sys/src/9/pc/devkbd.c
Normal file
481
sys/src/9/pc/devkbd.c
Normal file
|
@ -0,0 +1,481 @@
|
|||
/*
|
||||
* keyboard input
|
||||
*/
|
||||
#include "u.h"
|
||||
#include "../port/lib.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "io.h"
|
||||
#include "../port/error.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) */
|
||||
|
||||
Spec= 0xF800, /* Unicode private space */
|
||||
PF= Spec|0x20, /* num pad function key */
|
||||
View= Spec|0x00, /* view (shift window up) */
|
||||
KF= 0xF000, /* function key (begin Unicode private space) */
|
||||
Shift= Spec|0x60,
|
||||
Break= Spec|0x61,
|
||||
Ctrl= Spec|0x62,
|
||||
Latin= Spec|0x63,
|
||||
Caps= Spec|0x64,
|
||||
Num= Spec|0x65,
|
||||
Middle= Spec|0x66,
|
||||
Altgr= Spec|0x67,
|
||||
Kmouse= Spec|0x100,
|
||||
No= 0x00, /* peter */
|
||||
|
||||
Home= KF|13,
|
||||
Up= KF|14,
|
||||
Pgup= KF|15,
|
||||
Print= KF|16,
|
||||
Left= KF|17,
|
||||
Right= KF|18,
|
||||
End= KF|24,
|
||||
Down= View,
|
||||
Pgdown= KF|19,
|
||||
Ins= KF|20,
|
||||
Del= 0x7F,
|
||||
Scroll= KF|21,
|
||||
|
||||
Nscan= 128,
|
||||
|
||||
Int= 0, /* kbscans indices */
|
||||
Ext,
|
||||
Nscans,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
/* 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 */
|
||||
};
|
||||
|
||||
enum {
|
||||
Qdir,
|
||||
Qscancode,
|
||||
Qleds,
|
||||
};
|
||||
|
||||
static Dirtab kbdtab[] = {
|
||||
".", {Qdir, 0, QTDIR}, 0, 0555,
|
||||
"scancode", {Qscancode, 0}, 0, 0440,
|
||||
"leds", {Qleds, 0}, 0, 0220,
|
||||
};
|
||||
|
||||
static Lock i8042lock;
|
||||
static uchar ccc;
|
||||
static void kbdputc(int);
|
||||
static void (*auxputc)(int, int);
|
||||
static int nokbd = 1; /* flag: no PS/2 keyboard */
|
||||
|
||||
static struct {
|
||||
Ref ref;
|
||||
Queue *q;
|
||||
} kbd;
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
int i, x;
|
||||
|
||||
if(nokbd)
|
||||
return;
|
||||
|
||||
*((ushort*)KADDR(0x472)) = 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);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
i8042auxcmd(int cmd)
|
||||
{
|
||||
unsigned int c;
|
||||
int tries;
|
||||
static int badkbd;
|
||||
|
||||
if(badkbd)
|
||||
return -1;
|
||||
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);
|
||||
badkbd = 1; /* don't keep trying; there might not be one */
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
i8042auxcmds(uchar *cmd, int ncmd)
|
||||
{
|
||||
int i;
|
||||
|
||||
ilock(&i8042lock);
|
||||
for(i=0; i<ncmd; i++){
|
||||
if(outready() < 0)
|
||||
break;
|
||||
outb(Cmd, 0xD4);
|
||||
if(outready() < 0)
|
||||
break;
|
||||
outb(Data, cmd[i]);
|
||||
}
|
||||
iunlock(&i8042lock);
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
* set keyboard's leds for lock states (scroll, numeric, caps).
|
||||
*
|
||||
* at least one keyboard (from Qtronics) also sets its numeric-lock
|
||||
* behaviour to match the led state, though it has no numeric keypad,
|
||||
* and some BIOSes bring the system up with numeric-lock set and no
|
||||
* setting to change that. this combination steals the keys for these
|
||||
* characters and makes it impossible to generate them: uiolkjm&*().
|
||||
* thus we'd like to be able to force the numeric-lock led (and behaviour) off.
|
||||
*/
|
||||
static void
|
||||
setleds(int leds)
|
||||
{
|
||||
static int old = -1;
|
||||
|
||||
if(nokbd || leds == old)
|
||||
return;
|
||||
leds &= 7;
|
||||
ilock(&i8042lock);
|
||||
for(;;){
|
||||
if(outready() < 0)
|
||||
break;
|
||||
outb(Data, 0xed); /* `reset keyboard lock states' */
|
||||
if(outready() < 0)
|
||||
break;
|
||||
outb(Data, leds);
|
||||
if(outready() < 0)
|
||||
break;
|
||||
old = leds;
|
||||
break;
|
||||
}
|
||||
iunlock(&i8042lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* keyboard interrupt
|
||||
*/
|
||||
static void
|
||||
i8042intr(Ureg*, void*)
|
||||
{
|
||||
int s, c;
|
||||
uchar b;
|
||||
|
||||
/*
|
||||
* 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, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
b = c & 0xff;
|
||||
qproduce(kbd.q, &b, 1);
|
||||
}
|
||||
|
||||
void
|
||||
i8042auxenable(void (*putc)(int, int))
|
||||
{
|
||||
char *err = "i8042: aux init failed\n";
|
||||
|
||||
/* enable kbd/aux xfers and interrupts */
|
||||
ccc &= ~Cauxdis;
|
||||
ccc |= Cauxint;
|
||||
|
||||
ilock(&i8042lock);
|
||||
if(outready() < 0)
|
||||
print(err);
|
||||
outb(Cmd, 0x60); /* write control register */
|
||||
if(outready() < 0)
|
||||
print(err);
|
||||
outb(Data, ccc);
|
||||
if(outready() < 0)
|
||||
print(err);
|
||||
outb(Cmd, 0xA8); /* auxiliary device enable */
|
||||
if(outready() < 0){
|
||||
iunlock(&i8042lock);
|
||||
return;
|
||||
}
|
||||
auxputc = putc;
|
||||
intrenable(IrqAUX, i8042intr, 0, BUSUNKNOWN, "kbdaux");
|
||||
iunlock(&i8042lock);
|
||||
}
|
||||
|
||||
static Chan *
|
||||
kbdattach(char *spec)
|
||||
{
|
||||
return devattach(L'b', spec);
|
||||
}
|
||||
|
||||
static Walkqid*
|
||||
kbdwalk(Chan *c, Chan *nc, char **name, int nname)
|
||||
{
|
||||
return devwalk(c, nc, name, nname, kbdtab, nelem(kbdtab), devgen);
|
||||
}
|
||||
|
||||
static int
|
||||
kbdstat(Chan *c, uchar *dp, int n)
|
||||
{
|
||||
return devstat(c, dp, n, kbdtab, nelem(kbdtab), devgen);
|
||||
}
|
||||
|
||||
static Chan*
|
||||
kbdopen(Chan *c, int omode)
|
||||
{
|
||||
if(!iseve())
|
||||
error(Eperm);
|
||||
if(c->qid.path == Qscancode){
|
||||
if(incref(&kbd.ref) != 1){
|
||||
decref(&kbd.ref);
|
||||
error(Einuse);
|
||||
}
|
||||
}
|
||||
return devopen(c, omode, kbdtab, nelem(kbdtab), devgen);
|
||||
}
|
||||
|
||||
static void
|
||||
kbdclose(Chan *c)
|
||||
{
|
||||
if(c->qid.path == Qscancode)
|
||||
decref(&kbd.ref);
|
||||
}
|
||||
|
||||
static Block*
|
||||
kbdbread(Chan *c, long n, ulong)
|
||||
{
|
||||
if(c->qid.path != Qscancode)
|
||||
error(Egreg);
|
||||
|
||||
return qbread(kbd.q, n);
|
||||
}
|
||||
|
||||
static long
|
||||
kbdread(Chan *c, void *a, long n, vlong)
|
||||
{
|
||||
if(c->qid.path != Qscancode)
|
||||
error(Egreg);
|
||||
|
||||
return qread(kbd.q, a, n);
|
||||
}
|
||||
|
||||
static long
|
||||
kbdwrite(Chan *c, void *a, long n, vlong)
|
||||
{
|
||||
char tmp[8+1], *p;
|
||||
|
||||
if(c->qid.path != Qleds)
|
||||
error(Egreg);
|
||||
|
||||
p = tmp + n;
|
||||
if(n >= sizeof(tmp))
|
||||
p = tmp + sizeof(tmp)-1;
|
||||
memmove(tmp, a, p - tmp);
|
||||
*p = 0;
|
||||
|
||||
setleds(atoi(tmp));
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
Dev kbddevtab = {
|
||||
L'b',
|
||||
"kbd",
|
||||
|
||||
devreset,
|
||||
devinit,
|
||||
devshutdown,
|
||||
kbdattach,
|
||||
kbdwalk,
|
||||
kbdstat,
|
||||
kbdopen,
|
||||
devcreate,
|
||||
kbdclose,
|
||||
kbdread,
|
||||
kbdbread,
|
||||
kbdwrite,
|
||||
devbwrite,
|
||||
devremove,
|
||||
devwstat,
|
||||
};
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void
|
||||
kbdenable(void)
|
||||
{
|
||||
kbd.q = qopen(4*1024, 0, 0, 0);
|
||||
if(kbd.q == nil)
|
||||
panic("kbdenable");
|
||||
qnoblock(kbd.q, 1);
|
||||
|
||||
ioalloc(Data, 1, 0, "kbd");
|
||||
ioalloc(Cmd, 1, 0, "kbd");
|
||||
|
||||
intrenable(IrqKBD, i8042intr, 0, BUSUNKNOWN, "kbd");
|
||||
}
|
||||
|
||||
void
|
||||
kbdinit(void)
|
||||
{
|
||||
int c, try;
|
||||
|
||||
/* 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) {
|
||||
print(initfailed);
|
||||
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) {
|
||||
print(initfailed);
|
||||
return;
|
||||
}
|
||||
|
||||
nokbd = 0;
|
||||
|
||||
/* disable mouse */
|
||||
if (outbyte(Cmd, 0x60) < 0 || outbyte(Data, ccc) < 0)
|
||||
print("i8042: kbdinit mouse disable failed\n");
|
||||
}
|
|
@ -1,715 +0,0 @@
|
|||
/*
|
||||
* keyboard input
|
||||
*/
|
||||
#include "u.h"
|
||||
#include "../port/lib.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "io.h"
|
||||
#include "../port/error.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) */
|
||||
|
||||
Spec= 0xF800, /* Unicode private space */
|
||||
PF= Spec|0x20, /* num pad function key */
|
||||
View= Spec|0x00, /* view (shift window up) */
|
||||
KF= 0xF000, /* function key (begin Unicode private space) */
|
||||
Shift= Spec|0x60,
|
||||
Break= Spec|0x61,
|
||||
Ctrl= Spec|0x62,
|
||||
Latin= Spec|0x63,
|
||||
Caps= Spec|0x64,
|
||||
Num= Spec|0x65,
|
||||
Middle= Spec|0x66,
|
||||
Altgr= Spec|0x67,
|
||||
Kmouse= Spec|0x100,
|
||||
No= 0x00, /* peter */
|
||||
|
||||
Home= KF|13,
|
||||
Up= KF|14,
|
||||
Pgup= KF|15,
|
||||
Print= KF|16,
|
||||
Left= KF|17,
|
||||
Right= KF|18,
|
||||
End= KF|24,
|
||||
Down= View,
|
||||
Pgdown= KF|19,
|
||||
Ins= KF|20,
|
||||
Del= 0x7F,
|
||||
Scroll= KF|21,
|
||||
|
||||
Nscan= 128,
|
||||
|
||||
Int= 0, /* kbscans indices */
|
||||
Ext,
|
||||
Nscans,
|
||||
};
|
||||
|
||||
/*
|
||||
* The codes at 0x79 and 0x7b are produced by the PFU Happy Hacking keyboard.
|
||||
* A 'standard' keyboard doesn't produce anything above 0x58.
|
||||
*/
|
||||
Rune kbtab[Nscan] =
|
||||
{
|
||||
[0x00] No, 0x1b, '1', '2', '3', '4', '5', '6',
|
||||
[0x08] '7', '8', '9', '0', '-', '=', '\b', '\t',
|
||||
[0x10] 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
|
||||
[0x18] 'o', 'p', '[', ']', '\n', Ctrl, 'a', 's',
|
||||
[0x20] 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
|
||||
[0x28] '\'', '`', Shift, '\\', 'z', 'x', 'c', 'v',
|
||||
[0x30] 'b', 'n', 'm', ',', '.', '/', Shift, '*',
|
||||
[0x38] Latin, ' ', Ctrl, KF|1, KF|2, KF|3, KF|4, KF|5,
|
||||
[0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, Scroll, '7',
|
||||
[0x48] '8', '9', '-', '4', '5', '6', '+', '1',
|
||||
[0x50] '2', '3', '0', '.', No, No, No, KF|11,
|
||||
[0x58] KF|12, No, No, No, No, No, No, No,
|
||||
[0x60] No, No, No, No, No, No, No, No,
|
||||
[0x68] No, No, No, No, No, No, No, No,
|
||||
[0x70] No, No, No, No, No, No, No, No,
|
||||
[0x78] No, View, No, Up, No, No, No, No,
|
||||
};
|
||||
|
||||
Rune kbtabshift[Nscan] =
|
||||
{
|
||||
[0x00] No, 0x1b, '!', '@', '#', '$', '%', '^',
|
||||
[0x08] '&', '*', '(', ')', '_', '+', '\b', '\t',
|
||||
[0x10] 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
|
||||
[0x18] 'O', 'P', '{', '}', '\n', Ctrl, 'A', 'S',
|
||||
[0x20] 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
|
||||
[0x28] '"', '~', Shift, '|', 'Z', 'X', 'C', 'V',
|
||||
[0x30] 'B', 'N', 'M', '<', '>', '?', Shift, '*',
|
||||
[0x38] Latin, ' ', Ctrl, KF|1, KF|2, KF|3, KF|4, KF|5,
|
||||
[0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, Scroll, '7',
|
||||
[0x48] '8', '9', '-', '4', '5', '6', '+', '1',
|
||||
[0x50] '2', '3', '0', '.', No, No, No, KF|11,
|
||||
[0x58] KF|12, No, No, No, No, No, No, No,
|
||||
[0x60] No, No, No, No, No, No, No, No,
|
||||
[0x68] No, No, No, No, No, No, No, No,
|
||||
[0x70] No, No, No, No, No, No, No, No,
|
||||
[0x78] No, Up, No, Up, No, No, No, No,
|
||||
};
|
||||
|
||||
Rune kbtabesc1[Nscan] =
|
||||
{
|
||||
[0x00] No, No, No, No, No, No, No, No,
|
||||
[0x08] No, No, No, No, No, No, No, No,
|
||||
[0x10] No, No, No, No, No, No, No, No,
|
||||
[0x18] No, No, No, No, '\n', Ctrl, No, No,
|
||||
[0x20] No, No, No, No, No, No, No, No,
|
||||
[0x28] No, No, Shift, No, No, No, No, No,
|
||||
[0x30] No, No, No, No, No, '/', No, Print,
|
||||
[0x38] Altgr, No, No, No, No, No, No, No,
|
||||
[0x40] No, No, No, No, No, No, Break, Home,
|
||||
[0x48] Up, Pgup, No, Left, No, Right, No, End,
|
||||
[0x50] Down, Pgdown, Ins, Del, No, No, No, No,
|
||||
[0x58] No, No, No, No, No, No, No, No,
|
||||
[0x60] No, No, No, No, No, No, No, No,
|
||||
[0x68] No, No, No, No, No, No, No, No,
|
||||
[0x70] No, No, No, No, No, No, No, No,
|
||||
[0x78] No, Up, No, No, No, No, No, No,
|
||||
};
|
||||
|
||||
Rune kbtabaltgr[Nscan] =
|
||||
{
|
||||
[0x00] No, No, No, No, No, No, No, No,
|
||||
[0x08] No, No, No, No, No, No, No, No,
|
||||
[0x10] No, No, No, No, No, No, No, No,
|
||||
[0x18] No, No, No, No, '\n', Ctrl, No, No,
|
||||
[0x20] No, No, No, No, No, No, No, No,
|
||||
[0x28] No, No, Shift, No, No, No, No, No,
|
||||
[0x30] No, No, No, No, No, '/', No, Print,
|
||||
[0x38] Altgr, No, No, No, No, No, No, No,
|
||||
[0x40] No, No, No, No, No, No, Break, Home,
|
||||
[0x48] Up, Pgup, No, Left, No, Right, No, End,
|
||||
[0x50] Down, Pgdown, Ins, Del, No, No, No, No,
|
||||
[0x58] No, No, No, No, No, No, No, No,
|
||||
[0x60] No, No, No, No, No, No, No, No,
|
||||
[0x68] No, No, No, No, No, No, No, No,
|
||||
[0x70] No, No, No, No, No, No, No, No,
|
||||
[0x78] No, Up, No, No, No, No, No, No,
|
||||
};
|
||||
|
||||
Rune kbtabctrl[Nscan] =
|
||||
{
|
||||
[0x00] No, '', '', '', '', '', '', '',
|
||||
[0x08] '', '', '', '', '
', '', '\b', '\t',
|
||||
[0x10] '', '', '', '', '', '', '', '\t',
|
||||
[0x18] '', '', '', '', '\n', Ctrl, '', '',
|
||||
[0x20] '', '', '', '\b', '\n', '', '', '',
|
||||
[0x28] '', No, Shift, '', '', '', '', '',
|
||||
[0x30] '', '', '
', '', '', '', Shift, '\n',
|
||||
[0x38] Latin, No, Ctrl, '', '', '', '', '',
|
||||
[0x40] '', '', '', '
', '', '', '', '',
|
||||
[0x48] '', '', '
', '', '', '', '', '',
|
||||
[0x50] '', '', '', '', No, No, No, '',
|
||||
[0x58] '', No, No, No, No, No, No, No,
|
||||
[0x60] No, No, No, No, No, No, No, No,
|
||||
[0x68] No, No, No, No, No, No, No, No,
|
||||
[0x70] No, No, No, No, No, No, No, No,
|
||||
[0x78] No, '', No, '\b', No, No, No, No,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
/* 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 */
|
||||
};
|
||||
|
||||
int mouseshifted;
|
||||
void (*kbdmouse)(int);
|
||||
|
||||
static Lock i8042lock;
|
||||
static uchar ccc;
|
||||
static void (*auxputc)(int, int);
|
||||
static int nokbd = 1; /* flag: no PS/2 keyboard */
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
int i, x;
|
||||
|
||||
if(nokbd)
|
||||
return;
|
||||
|
||||
*((ushort*)KADDR(0x472)) = 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);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
i8042auxcmd(int cmd)
|
||||
{
|
||||
unsigned int c;
|
||||
int tries;
|
||||
static int badkbd;
|
||||
|
||||
if(badkbd)
|
||||
return -1;
|
||||
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);
|
||||
badkbd = 1; /* don't keep trying; there might not be one */
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
i8042auxcmds(uchar *cmd, int ncmd)
|
||||
{
|
||||
int i;
|
||||
|
||||
ilock(&i8042lock);
|
||||
for(i=0; i<ncmd; i++){
|
||||
if(outready() < 0)
|
||||
break;
|
||||
outb(Cmd, 0xD4);
|
||||
if(outready() < 0)
|
||||
break;
|
||||
outb(Data, cmd[i]);
|
||||
}
|
||||
iunlock(&i8042lock);
|
||||
return i;
|
||||
}
|
||||
|
||||
typedef struct Kbscan Kbscan;
|
||||
struct Kbscan {
|
||||
int esc1;
|
||||
int esc2;
|
||||
int alt;
|
||||
int altgr;
|
||||
int caps;
|
||||
int ctl;
|
||||
int num;
|
||||
int shift;
|
||||
int collecting;
|
||||
int nk;
|
||||
Rune kc[5];
|
||||
int buttons;
|
||||
};
|
||||
|
||||
Kbscan kbscans[Nscans]; /* kernel and external scan code state */
|
||||
|
||||
static int kdebug;
|
||||
|
||||
/*
|
||||
* set keyboard's leds for lock states (scroll, numeric, caps).
|
||||
*
|
||||
* at least one keyboard (from Qtronics) also sets its numeric-lock
|
||||
* behaviour to match the led state, though it has no numeric keypad,
|
||||
* and some BIOSes bring the system up with numeric-lock set and no
|
||||
* setting to change that. this combination steals the keys for these
|
||||
* characters and makes it impossible to generate them: uiolkjm&*().
|
||||
* thus we'd like to be able to force the numeric-lock led (and behaviour) off.
|
||||
*/
|
||||
static void
|
||||
setleds(Kbscan *kbscan)
|
||||
{
|
||||
int leds;
|
||||
|
||||
if(nokbd || kbscan != &kbscans[Int])
|
||||
return;
|
||||
leds = 0;
|
||||
if(kbscan->num)
|
||||
leds |= 1<<1;
|
||||
if(0 && kbscan->caps) /* we don't implement caps lock */
|
||||
leds |= 1<<2;
|
||||
ilock(&i8042lock);
|
||||
outready();
|
||||
outb(Data, 0xed); /* `reset keyboard lock states' */
|
||||
outready();
|
||||
outb(Data, leds);
|
||||
outready();
|
||||
iunlock(&i8042lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan code processing
|
||||
*/
|
||||
void
|
||||
kbdputsc(int c, int external)
|
||||
{
|
||||
int i, keyup;
|
||||
Kbscan *kbscan;
|
||||
|
||||
if(external)
|
||||
kbscan = &kbscans[Ext];
|
||||
else
|
||||
kbscan = &kbscans[Int];
|
||||
|
||||
if(kdebug)
|
||||
print("sc %x ms %d\n", c, mouseshifted);
|
||||
/*
|
||||
* e0's is the first of a 2 character sequence, e1 the first
|
||||
* of a 3 character sequence (on the safari)
|
||||
*/
|
||||
if(c == 0xe0){
|
||||
kbscan->esc1 = 1;
|
||||
return;
|
||||
} else if(c == 0xe1){
|
||||
kbscan->esc2 = 2;
|
||||
return;
|
||||
}
|
||||
|
||||
keyup = c & 0x80;
|
||||
c &= 0x7f;
|
||||
if(c > sizeof kbtab){
|
||||
c |= keyup;
|
||||
if(c != 0xFF) /* these come fairly often: CAPSLOCK U Y */
|
||||
print("unknown key %ux\n", c);
|
||||
return;
|
||||
}
|
||||
|
||||
if(kbscan->esc1){
|
||||
c = kbtabesc1[c];
|
||||
kbscan->esc1 = 0;
|
||||
} else if(kbscan->esc2){
|
||||
kbscan->esc2--;
|
||||
return;
|
||||
} else if(kbscan->shift)
|
||||
c = kbtabshift[c];
|
||||
else if(kbscan->altgr)
|
||||
c = kbtabaltgr[c];
|
||||
else if(kbscan->ctl)
|
||||
c = kbtabctrl[c];
|
||||
else
|
||||
c = kbtab[c];
|
||||
|
||||
if(kbscan->caps && c<='z' && c>='a')
|
||||
c += 'A' - 'a';
|
||||
|
||||
/*
|
||||
* keyup only important for shifts
|
||||
*/
|
||||
if(keyup){
|
||||
switch(c){
|
||||
case Latin:
|
||||
kbscan->alt = 0;
|
||||
break;
|
||||
case Shift:
|
||||
kbscan->shift = 0;
|
||||
mouseshifted = 0;
|
||||
if(kdebug)
|
||||
print("shiftclr\n");
|
||||
break;
|
||||
case Ctrl:
|
||||
kbscan->ctl = 0;
|
||||
break;
|
||||
case Altgr:
|
||||
kbscan->altgr = 0;
|
||||
break;
|
||||
case Kmouse|1:
|
||||
case Kmouse|2:
|
||||
case Kmouse|3:
|
||||
case Kmouse|4:
|
||||
case Kmouse|5:
|
||||
kbscan->buttons &= ~(1<<(c-Kmouse-1));
|
||||
if(kbdmouse)
|
||||
kbdmouse(kbscan->buttons);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* normal character
|
||||
*/
|
||||
if(!(c & (Spec|KF))){
|
||||
if(kbscan->ctl)
|
||||
if(kbscan->alt && c == Del)
|
||||
exit(0);
|
||||
if(!kbscan->collecting){
|
||||
kbdputc(kbdq, c);
|
||||
return;
|
||||
}
|
||||
kbscan->kc[kbscan->nk++] = c;
|
||||
c = latin1(kbscan->kc, kbscan->nk);
|
||||
if(c < -1) /* need more keystrokes */
|
||||
return;
|
||||
if(c != -1) /* valid sequence */
|
||||
kbdputc(kbdq, c);
|
||||
else /* dump characters */
|
||||
for(i=0; i<kbscan->nk; i++)
|
||||
kbdputc(kbdq, kbscan->kc[i]);
|
||||
kbscan->nk = 0;
|
||||
kbscan->collecting = 0;
|
||||
return;
|
||||
} else {
|
||||
switch(c){
|
||||
case Caps:
|
||||
kbscan->caps ^= 1;
|
||||
return;
|
||||
case Num:
|
||||
kbscan->num ^= 1;
|
||||
if(!external)
|
||||
setleds(kbscan);
|
||||
return;
|
||||
case Shift:
|
||||
kbscan->shift = 1;
|
||||
if(kdebug)
|
||||
print("shift\n");
|
||||
mouseshifted = 1;
|
||||
return;
|
||||
case Latin:
|
||||
kbscan->alt = 1;
|
||||
/*
|
||||
* VMware and Qemu use Ctl-Alt as the key combination
|
||||
* to make the VM give up keyboard and mouse focus.
|
||||
* This has the unfortunate side effect that when you
|
||||
* come back into focus, Plan 9 thinks you want to type
|
||||
* a compose sequence (you just typed alt).
|
||||
*
|
||||
* As a clumsy hack around this, we look for ctl-alt
|
||||
* and don't treat it as the start of a compose sequence.
|
||||
*/
|
||||
if(!kbscan->ctl){
|
||||
kbscan->collecting = 1;
|
||||
kbscan->nk = 0;
|
||||
}
|
||||
return;
|
||||
case Ctrl:
|
||||
kbscan->ctl = 1;
|
||||
return;
|
||||
case Altgr:
|
||||
kbscan->altgr = 1;
|
||||
return;
|
||||
case Kmouse|1:
|
||||
case Kmouse|2:
|
||||
case Kmouse|3:
|
||||
case Kmouse|4:
|
||||
case Kmouse|5:
|
||||
kbscan->buttons |= 1<<(c-Kmouse-1);
|
||||
if(kbdmouse)
|
||||
kbdmouse(kbscan->buttons);
|
||||
return;
|
||||
case KF|11:
|
||||
print("kbd debug on, F12 turns it off\n");
|
||||
kdebug = 1;
|
||||
break;
|
||||
case KF|12:
|
||||
kdebug = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
kbdputc(kbdq, c);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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, kbscans[Int].shift);
|
||||
return;
|
||||
}
|
||||
|
||||
kbdputsc(c, Int);
|
||||
}
|
||||
|
||||
void
|
||||
i8042auxenable(void (*putc)(int, int))
|
||||
{
|
||||
char *err = "i8042: aux init failed\n";
|
||||
|
||||
/* enable kbd/aux xfers and interrupts */
|
||||
ccc &= ~Cauxdis;
|
||||
ccc |= Cauxint;
|
||||
|
||||
ilock(&i8042lock);
|
||||
if(outready() < 0)
|
||||
print(err);
|
||||
outb(Cmd, 0x60); /* write control register */
|
||||
if(outready() < 0)
|
||||
print(err);
|
||||
outb(Data, ccc);
|
||||
if(outready() < 0)
|
||||
print(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;
|
||||
}
|
||||
|
||||
void
|
||||
kbdinit(void)
|
||||
{
|
||||
int c, try;
|
||||
|
||||
/* 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) {
|
||||
print(initfailed);
|
||||
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) {
|
||||
print(initfailed);
|
||||
return;
|
||||
}
|
||||
|
||||
nokbd = 0;
|
||||
|
||||
/* disable mouse */
|
||||
if (outbyte(Cmd, 0x60) < 0 || outbyte(Data, ccc) < 0)
|
||||
print("i8042: kbdinit mouse disable failed\n");
|
||||
}
|
||||
|
||||
void
|
||||
kbdenable(void)
|
||||
{
|
||||
kbdq = qopen(4*1024, 0, 0, 0);
|
||||
if(kbdq == nil)
|
||||
panic("kbdinit");
|
||||
qnoblock(kbdq, 1);
|
||||
|
||||
ioalloc(Data, 1, 0, "kbd");
|
||||
ioalloc(Cmd, 1, 0, "kbd");
|
||||
|
||||
intrenable(IrqKBD, i8042intr, 0, BUSUNKNOWN, "kbd");
|
||||
|
||||
kbscans[Int].num = 0;
|
||||
setleds(&kbscans[Int]);
|
||||
}
|
||||
|
||||
void
|
||||
kbdputmap(ushort m, ushort scanc, Rune r)
|
||||
{
|
||||
if(scanc >= Nscan)
|
||||
error(Ebadarg);
|
||||
switch(m) {
|
||||
default:
|
||||
error(Ebadarg);
|
||||
case 0:
|
||||
kbtab[scanc] = r;
|
||||
break;
|
||||
case 1:
|
||||
kbtabshift[scanc] = r;
|
||||
break;
|
||||
case 2:
|
||||
kbtabesc1[scanc] = r;
|
||||
break;
|
||||
case 3:
|
||||
kbtabaltgr[scanc] = r;
|
||||
break;
|
||||
case 4:
|
||||
kbtabctrl[scanc] = r;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
kbdgetmap(uint offset, int *t, int *sc, Rune *r)
|
||||
{
|
||||
if ((int)offset < 0)
|
||||
error(Ebadarg);
|
||||
*t = offset/Nscan;
|
||||
*sc = offset%Nscan;
|
||||
switch(*t) {
|
||||
default:
|
||||
return 0;
|
||||
case 0:
|
||||
*r = kbtab[*sc];
|
||||
return 1;
|
||||
case 1:
|
||||
*r = kbtabshift[*sc];
|
||||
return 1;
|
||||
case 2:
|
||||
*r = kbtabesc1[*sc];
|
||||
return 1;
|
||||
case 3:
|
||||
*r = kbtabaltgr[*sc];
|
||||
return 1;
|
||||
case 4:
|
||||
*r = kbtabctrl[*sc];
|
||||
return 1;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
CONF=pc
|
||||
CONFLIST=pc pccpu pcf pccpuf
|
||||
CRAPLIST=pccd pcflop
|
||||
CONF=pcf
|
||||
CONFLIST=pcf pccpuf
|
||||
CRAPLIST=pc pccpu pccd pcflop
|
||||
EXTRACOPIES=
|
||||
#EXTRACOPIES=lookout boundary # copy to these servers on install
|
||||
|
||||
|
@ -49,7 +49,6 @@ OBJ=\
|
|||
cga.$O\
|
||||
i8253.$O\
|
||||
i8259.$O\
|
||||
kbd.$O\
|
||||
main.$O\
|
||||
memory.$O\
|
||||
mmu.$O\
|
||||
|
|
|
@ -22,8 +22,6 @@ enum
|
|||
MousePS2= 2,
|
||||
};
|
||||
|
||||
extern int mouseshifted;
|
||||
|
||||
static QLock mousectlqlock;
|
||||
static int mousetype;
|
||||
static int intellimouse;
|
||||
|
@ -95,11 +93,6 @@ ps2mouseputc(int c, int shift)
|
|||
ulong m;
|
||||
int buttons, dx, dy;
|
||||
|
||||
/*
|
||||
* non-ps2 keyboards might not set shift
|
||||
* but still set mouseshifted.
|
||||
*/
|
||||
shift |= mouseshifted;
|
||||
/*
|
||||
* Resynchronize in stream with timing; see comment above.
|
||||
*/
|
||||
|
|
134
sys/src/9/pc/pc
134
sys/src/9/pc/pc
|
@ -1,134 +0,0 @@
|
|||
dev
|
||||
root
|
||||
cons
|
||||
|
||||
arch
|
||||
pnp pci
|
||||
env
|
||||
pipe
|
||||
proc
|
||||
mnt
|
||||
srv
|
||||
dup
|
||||
rtc
|
||||
ssl
|
||||
tls
|
||||
cap
|
||||
kprof
|
||||
fs
|
||||
|
||||
ether netif
|
||||
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum386 inferno
|
||||
|
||||
draw screen vga vgax
|
||||
mouse mouse
|
||||
vga
|
||||
kbmap
|
||||
kbin
|
||||
|
||||
sd
|
||||
floppy dma
|
||||
lpt
|
||||
|
||||
audio dma
|
||||
pccard
|
||||
i82365 cis
|
||||
uart
|
||||
usb
|
||||
|
||||
|
||||
link
|
||||
realmode
|
||||
devpccard
|
||||
devi82365
|
||||
ether2000 ether8390
|
||||
ether2114x pci
|
||||
ether589 etherelnk3
|
||||
ether79c970 pci
|
||||
ether8003 ether8390
|
||||
ether8139 pci
|
||||
ether8169 pci ethermii
|
||||
ether82543gc pci
|
||||
ether82563 pci
|
||||
ether82557 pci
|
||||
ether83815 pci
|
||||
etherbcm pci
|
||||
etherdp83820 pci
|
||||
etherec2t ether8390
|
||||
etherelnk3 pci
|
||||
etherga620 pci
|
||||
etherigbe pci ethermii
|
||||
ethervgbe pci ethermii
|
||||
ethervt6102 pci ethermii
|
||||
ethervt6105m pci ethermii
|
||||
ethersink
|
||||
ethersmc devi82365 cis
|
||||
etherwavelan wavelan devi82365 cis pci
|
||||
ethermedium
|
||||
# etherm10g
|
||||
ether82598 pci
|
||||
pcmciamodem
|
||||
netdevmedium
|
||||
loopbackmedium
|
||||
usbuhci
|
||||
usbohci
|
||||
usbehci usbehcipc
|
||||
|
||||
misc
|
||||
archmp mp apic
|
||||
mtrr
|
||||
|
||||
sdata pci sdscsi
|
||||
sd53c8xx pci sdscsi
|
||||
sdmylex pci sdscsi
|
||||
sdiahci pci sdscsi
|
||||
|
||||
uarti8250
|
||||
uartpci pci
|
||||
uartisa
|
||||
|
||||
vga3dfx +cur
|
||||
vgaark2000pv +cur
|
||||
vgabt485 =cur
|
||||
vgaclgd542x +cur
|
||||
vgaclgd546x +cur
|
||||
vgact65545 +cur
|
||||
vgacyber938x +cur
|
||||
vgaet4000 +cur
|
||||
vgahiqvideo +cur
|
||||
vgai81x +cur
|
||||
vgamach64xx +cur
|
||||
vgamga2164w +cur
|
||||
vgamga4xx +cur
|
||||
vganeomagic +cur
|
||||
vganvidia +cur
|
||||
vgargb524 =cur
|
||||
vgas3 +cur vgasavage
|
||||
vgat2r4 +cur
|
||||
vgatvp3020 =cur
|
||||
vgatvp3026 =cur
|
||||
vgavesa
|
||||
vgavmware +cur
|
||||
vgageode +cur
|
||||
|
||||
ip
|
||||
tcp
|
||||
udp
|
||||
ipifc
|
||||
icmp
|
||||
icmp6
|
||||
gre
|
||||
ipmux
|
||||
esp
|
||||
|
||||
port
|
||||
int cpuserver = 0;
|
||||
|
||||
boot
|
||||
tcp
|
||||
|
||||
bootdir
|
||||
bootpc.out boot
|
||||
/386/bin/ip/ipconfig
|
||||
/386/bin/auth/factotum
|
||||
/386/bin/usb/usbd
|
|
@ -1,99 +0,0 @@
|
|||
# pccpu - cpu server kernel
|
||||
dev
|
||||
root
|
||||
cons
|
||||
arch
|
||||
pnp pci
|
||||
env
|
||||
pipe
|
||||
proc
|
||||
mnt
|
||||
srv
|
||||
dup
|
||||
rtc
|
||||
ssl
|
||||
tls
|
||||
bridge log
|
||||
sdp thwack unthwack
|
||||
cap
|
||||
kprof
|
||||
fs
|
||||
segment
|
||||
|
||||
ether netif
|
||||
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum386 inferno
|
||||
|
||||
sd
|
||||
floppy dma
|
||||
aoe
|
||||
|
||||
uart
|
||||
usb
|
||||
kbin
|
||||
audio
|
||||
|
||||
link
|
||||
realmode
|
||||
ether2000 ether8390
|
||||
ether2114x pci
|
||||
ether79c970 pci
|
||||
ether8003 ether8390
|
||||
ether8139 pci
|
||||
ether8169 pci ethermii
|
||||
ether82543gc pci
|
||||
ether82563 pci
|
||||
ether82557 pci
|
||||
ether83815 pci
|
||||
etherdp83820 pci
|
||||
etherelnk3 pci
|
||||
etherga620 pci
|
||||
etherigbe pci ethermii
|
||||
ethervgbe pci ethermii
|
||||
ethervt6102 pci ethermii
|
||||
ethervt6105m pci ethermii
|
||||
# etherm10g pci ethermii
|
||||
ether82598 pci
|
||||
ethersink
|
||||
ethermedium
|
||||
loopbackmedium
|
||||
usbuhci
|
||||
usbohci
|
||||
usbehci usbehcipc
|
||||
|
||||
misc
|
||||
archmp mp apic
|
||||
mtrr
|
||||
|
||||
uarti8250
|
||||
uartpci pci
|
||||
uartaxp pci
|
||||
|
||||
sdata pci sdscsi
|
||||
sd53c8xx pci sdscsi
|
||||
sdmv50xx pci sdscsi
|
||||
sdmylex pci sdscsi
|
||||
sdiahci pci sdscsi
|
||||
sdaoe sdscsi
|
||||
|
||||
ip
|
||||
tcp
|
||||
udp
|
||||
ipifc
|
||||
icmp
|
||||
icmp6
|
||||
gre
|
||||
ipmux
|
||||
esp
|
||||
rudp
|
||||
|
||||
port
|
||||
int cpuserver = 1;
|
||||
|
||||
boot cpu
|
||||
tcp
|
||||
|
||||
bootdir
|
||||
bootpccpu.out boot
|
||||
/386/bin/ip/ipconfig ipconfig
|
||||
/386/bin/auth/factotum
|
||||
/386/bin/usb/usbd
|
|
@ -24,6 +24,7 @@ dev
|
|||
|
||||
draw screen vga vgax
|
||||
mouse mouse
|
||||
kbd
|
||||
vga
|
||||
|
||||
sd
|
||||
|
@ -32,7 +33,6 @@ dev
|
|||
|
||||
uart
|
||||
usb
|
||||
kbin
|
||||
|
||||
link
|
||||
realmode
|
||||
|
|
|
@ -22,9 +22,8 @@ dev
|
|||
|
||||
draw screen vga vgax
|
||||
mouse mouse
|
||||
kbd
|
||||
vga
|
||||
kbmap
|
||||
kbin
|
||||
|
||||
sd
|
||||
floppy dma
|
||||
|
|
|
@ -133,6 +133,7 @@ hostownerwrite(char *a, int n)
|
|||
buf[n] = 0;
|
||||
|
||||
renameuser(eve, buf);
|
||||
srvrenameuser(eve, buf);
|
||||
kstrdup(&eve, buf);
|
||||
kstrdup(&up->user, buf);
|
||||
up->basepri = PriNormal;
|
||||
|
|
|
@ -2,6 +2,8 @@ $cputype
|
|||
bin
|
||||
9660srv
|
||||
awk
|
||||
aux
|
||||
kbdfs
|
||||
bind
|
||||
bzfs
|
||||
cat
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
void (*consdebug)(void) = nil;
|
||||
void (*screenputs)(char*, int) = nil;
|
||||
|
||||
Queue* kbdq; /* unprocessed console input */
|
||||
Queue* lineq; /* processed console input */
|
||||
Queue* serialoq; /* serial console output */
|
||||
Queue* kprintoq; /* console output, for /dev/kprint */
|
||||
ulong kprintinuse; /* test and set whether /dev/kprint is open */
|
||||
|
@ -20,30 +18,6 @@ int iprintscreenputs = 1;
|
|||
|
||||
int panicking;
|
||||
|
||||
static struct
|
||||
{
|
||||
QLock;
|
||||
|
||||
int raw; /* true if we shouldn't process input */
|
||||
Ref ctl; /* number of opens to the control file */
|
||||
int x; /* index into line */
|
||||
char line[1024]; /* current input line */
|
||||
|
||||
int count;
|
||||
int ctlpoff;
|
||||
|
||||
/* a place to save up characters at interrupt time before dumping them in the queue */
|
||||
Lock lockputc;
|
||||
char istage[1024];
|
||||
char *iw;
|
||||
char *ir;
|
||||
char *ie;
|
||||
} kbd = {
|
||||
.iw = kbd.istage,
|
||||
.ir = kbd.istage,
|
||||
.ie = kbd.istage + sizeof(kbd.istage),
|
||||
};
|
||||
|
||||
char *sysname;
|
||||
vlong fasthz;
|
||||
|
||||
|
@ -70,10 +44,6 @@ Cmdtab rebootmsg[] =
|
|||
void
|
||||
printinit(void)
|
||||
{
|
||||
lineq = qopen(2*1024, 0, nil, nil);
|
||||
if(lineq == nil)
|
||||
panic("printinit");
|
||||
qnoblock(lineq, 1);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -179,7 +149,7 @@ putstrn0(char *str, int n, int usewrite)
|
|||
|
||||
while(n > 0) {
|
||||
t = memchr(str, '\n', n);
|
||||
if(t && !kbd.raw) {
|
||||
if(t) {
|
||||
m = t-str;
|
||||
if(usewrite){
|
||||
qwrite(serialoq, str, m);
|
||||
|
@ -206,8 +176,6 @@ putstrn(char *str, int n)
|
|||
putstrn0(str, n, 0);
|
||||
}
|
||||
|
||||
int noprint;
|
||||
|
||||
int
|
||||
print(char *fmt, ...)
|
||||
{
|
||||
|
@ -215,9 +183,6 @@ print(char *fmt, ...)
|
|||
va_list arg;
|
||||
char buf[PRINTSIZE];
|
||||
|
||||
if(noprint)
|
||||
return -1;
|
||||
|
||||
va_start(arg, fmt);
|
||||
n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
|
||||
va_end(arg);
|
||||
|
@ -350,231 +315,10 @@ pprint(char *fmt, ...)
|
|||
return n;
|
||||
}
|
||||
|
||||
static void
|
||||
echoscreen(char *buf, int n)
|
||||
{
|
||||
char *e, *p;
|
||||
char ebuf[128];
|
||||
int x;
|
||||
|
||||
p = ebuf;
|
||||
e = ebuf + sizeof(ebuf) - 4;
|
||||
while(n-- > 0){
|
||||
if(p >= e){
|
||||
screenputs(ebuf, p - ebuf);
|
||||
p = ebuf;
|
||||
}
|
||||
x = *buf++;
|
||||
if(x == 0x15){
|
||||
*p++ = '^';
|
||||
*p++ = 'U';
|
||||
*p++ = '\n';
|
||||
} else
|
||||
*p++ = x;
|
||||
}
|
||||
if(p != ebuf)
|
||||
screenputs(ebuf, p - ebuf);
|
||||
}
|
||||
|
||||
static void
|
||||
echoserialoq(char *buf, int n)
|
||||
{
|
||||
char *e, *p;
|
||||
char ebuf[128];
|
||||
int x;
|
||||
|
||||
p = ebuf;
|
||||
e = ebuf + sizeof(ebuf) - 4;
|
||||
while(n-- > 0){
|
||||
if(p >= e){
|
||||
qiwrite(serialoq, ebuf, p - ebuf);
|
||||
p = ebuf;
|
||||
}
|
||||
x = *buf++;
|
||||
if(x == '\n'){
|
||||
*p++ = '\r';
|
||||
*p++ = '\n';
|
||||
} else if(x == 0x15){
|
||||
*p++ = '^';
|
||||
*p++ = 'U';
|
||||
*p++ = '\n';
|
||||
} else
|
||||
*p++ = x;
|
||||
}
|
||||
if(p != ebuf)
|
||||
qiwrite(serialoq, ebuf, p - ebuf);
|
||||
}
|
||||
|
||||
static void
|
||||
echo(char *buf, int n)
|
||||
{
|
||||
static int ctrlt, pid;
|
||||
int x;
|
||||
char *e, *p;
|
||||
|
||||
if(n == 0)
|
||||
return;
|
||||
|
||||
e = buf+n;
|
||||
for(p = buf; p < e; p++){
|
||||
switch(*p){
|
||||
case 0x10: /* ^P */
|
||||
if(cpuserver && !kbd.ctlpoff){
|
||||
active.exiting = 1;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0x14: /* ^T */
|
||||
ctrlt++;
|
||||
if(ctrlt > 2)
|
||||
ctrlt = 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(ctrlt != 2)
|
||||
continue;
|
||||
|
||||
/* ^T escapes */
|
||||
ctrlt = 0;
|
||||
switch(*p){
|
||||
case 'S':
|
||||
x = splhi();
|
||||
dumpstack();
|
||||
procdump();
|
||||
splx(x);
|
||||
return;
|
||||
case 's':
|
||||
dumpstack();
|
||||
return;
|
||||
case 'x':
|
||||
xsummary();
|
||||
ixsummary();
|
||||
mallocsummary();
|
||||
// memorysummary();
|
||||
pagersummary();
|
||||
return;
|
||||
case 'd':
|
||||
if(consdebug == nil)
|
||||
consdebug = rdb;
|
||||
else
|
||||
consdebug = nil;
|
||||
print("consdebug now %#p\n", consdebug);
|
||||
return;
|
||||
case 'D':
|
||||
if(consdebug == nil)
|
||||
consdebug = rdb;
|
||||
consdebug();
|
||||
return;
|
||||
case 'p':
|
||||
x = spllo();
|
||||
procdump();
|
||||
splx(x);
|
||||
return;
|
||||
case 'q':
|
||||
scheddump();
|
||||
return;
|
||||
case 'k':
|
||||
killbig("^t ^t k");
|
||||
return;
|
||||
case 'r':
|
||||
exit(0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
qproduce(kbdq, buf, n);
|
||||
if(kbd.raw)
|
||||
return;
|
||||
kmesgputs(buf, n);
|
||||
if(screenputs != nil)
|
||||
echoscreen(buf, n);
|
||||
if(serialoq)
|
||||
echoserialoq(buf, n);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called by a uart interrupt for console input.
|
||||
*
|
||||
* turn '\r' into '\n' before putting it into the queue.
|
||||
*/
|
||||
int
|
||||
kbdcr2nl(Queue*, int ch)
|
||||
{
|
||||
char *next;
|
||||
|
||||
ilock(&kbd.lockputc); /* just a mutex */
|
||||
if(ch == '\r' && !kbd.raw)
|
||||
ch = '\n';
|
||||
next = kbd.iw+1;
|
||||
if(next >= kbd.ie)
|
||||
next = kbd.istage;
|
||||
if(next != kbd.ir){
|
||||
*kbd.iw = ch;
|
||||
kbd.iw = next;
|
||||
}
|
||||
iunlock(&kbd.lockputc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Put character, possibly a rune, into read queue at interrupt time.
|
||||
* Called at interrupt time to process a character.
|
||||
*/
|
||||
int
|
||||
kbdputc(Queue*, int ch)
|
||||
{
|
||||
int i, n;
|
||||
char buf[3];
|
||||
Rune r;
|
||||
char *next;
|
||||
|
||||
if(kbd.ir == nil)
|
||||
return 0; /* in case we're not inited yet */
|
||||
|
||||
ilock(&kbd.lockputc); /* just a mutex */
|
||||
r = ch;
|
||||
n = runetochar(buf, &r);
|
||||
for(i = 0; i < n; i++){
|
||||
next = kbd.iw+1;
|
||||
if(next >= kbd.ie)
|
||||
next = kbd.istage;
|
||||
if(next == kbd.ir)
|
||||
break;
|
||||
*kbd.iw = buf[i];
|
||||
kbd.iw = next;
|
||||
}
|
||||
iunlock(&kbd.lockputc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* we save up input characters till clock time to reduce
|
||||
* per character interrupt overhead.
|
||||
*/
|
||||
static void
|
||||
kbdputcclock(void)
|
||||
{
|
||||
char *iw;
|
||||
|
||||
/* this amortizes cost of qproduce */
|
||||
if(kbd.iw != kbd.ir){
|
||||
iw = kbd.iw;
|
||||
if(iw < kbd.ir){
|
||||
echo(kbd.ir, kbd.ie-kbd.ir);
|
||||
kbd.ir = kbd.istage;
|
||||
}
|
||||
if(kbd.ir != iw){
|
||||
echo(kbd.ir, iw-kbd.ir);
|
||||
kbd.ir = iw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum{
|
||||
Qdir,
|
||||
Qbintime,
|
||||
Qcons,
|
||||
Qconsctl,
|
||||
Qcputime,
|
||||
Qdrivers,
|
||||
Qkmesg,
|
||||
|
@ -607,7 +351,6 @@ static Dirtab consdir[]={
|
|||
".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
|
||||
"bintime", {Qbintime}, 24, 0664,
|
||||
"cons", {Qcons}, 0, 0660,
|
||||
"consctl", {Qconsctl}, 0, 0220,
|
||||
"cputime", {Qcputime}, 6*NUMSIZE, 0444,
|
||||
"drivers", {Qdrivers}, 0, 0444,
|
||||
"hostdomain", {Qhostdomain}, DOMLEN, 0664,
|
||||
|
@ -665,11 +408,6 @@ consinit(void)
|
|||
{
|
||||
todinit();
|
||||
randominit();
|
||||
/*
|
||||
* at 115200 baud, the 1024 char buffer takes 56 ms to process,
|
||||
* processing it every 22 ms should be fine
|
||||
*/
|
||||
addclock0link(kbdputcclock, 22);
|
||||
}
|
||||
|
||||
static Chan*
|
||||
|
@ -696,10 +434,6 @@ consopen(Chan *c, int omode)
|
|||
c->aux = nil;
|
||||
c = devopen(c, omode, consdir, nelem(consdir), devgen);
|
||||
switch((ulong)c->qid.path){
|
||||
case Qconsctl:
|
||||
incref(&kbd.ctl);
|
||||
break;
|
||||
|
||||
case Qkprint:
|
||||
if(tas(&kprintinuse) != 0){
|
||||
c->flag &= ~COPEN;
|
||||
|
@ -724,14 +458,6 @@ static void
|
|||
consclose(Chan *c)
|
||||
{
|
||||
switch((ulong)c->qid.path){
|
||||
/* last close of control file turns off raw */
|
||||
case Qconsctl:
|
||||
if(c->flag&COPEN){
|
||||
if(decref(&kbd.ctl) == 0)
|
||||
kbd.raw = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
/* close of kprint allows other opens */
|
||||
case Qkprint:
|
||||
if(c->flag & COPEN){
|
||||
|
@ -747,9 +473,9 @@ consread(Chan *c, void *buf, long n, vlong off)
|
|||
{
|
||||
ulong l;
|
||||
Mach *mp;
|
||||
char *b, *bp, ch;
|
||||
char *b, *bp;
|
||||
char tmp[256]; /* must be >= 18*NUMSIZE (Qswap) */
|
||||
int i, k, id, send;
|
||||
int i, k, id;
|
||||
vlong offset = off;
|
||||
extern char configfile[];
|
||||
|
||||
|
@ -761,49 +487,7 @@ consread(Chan *c, void *buf, long n, vlong off)
|
|||
return devdirread(c, buf, n, consdir, nelem(consdir), devgen);
|
||||
|
||||
case Qcons:
|
||||
qlock(&kbd);
|
||||
if(waserror()) {
|
||||
qunlock(&kbd);
|
||||
nexterror();
|
||||
}
|
||||
while(!qcanread(lineq)){
|
||||
if(qread(kbdq, &ch, 1) == 0)
|
||||
continue;
|
||||
send = 0;
|
||||
if(ch == 0){
|
||||
/* flush output on rawoff -> rawon */
|
||||
if(kbd.x > 0)
|
||||
send = !qcanread(kbdq);
|
||||
}else if(kbd.raw){
|
||||
kbd.line[kbd.x++] = ch;
|
||||
send = !qcanread(kbdq);
|
||||
}else{
|
||||
switch(ch){
|
||||
case '\b':
|
||||
if(kbd.x > 0)
|
||||
kbd.x--;
|
||||
break;
|
||||
case 0x15: /* ^U */
|
||||
kbd.x = 0;
|
||||
break;
|
||||
case '\n':
|
||||
case 0x04: /* ^D */
|
||||
send = 1;
|
||||
default:
|
||||
if(ch != 0x04)
|
||||
kbd.line[kbd.x++] = ch;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(send || kbd.x == sizeof kbd.line){
|
||||
qwrite(lineq, kbd.line, kbd.x);
|
||||
kbd.x = 0;
|
||||
}
|
||||
}
|
||||
n = qread(lineq, buf, n);
|
||||
qunlock(&kbd);
|
||||
poperror();
|
||||
return n;
|
||||
error(Egreg);
|
||||
|
||||
case Qcputime:
|
||||
k = offset;
|
||||
|
@ -980,7 +664,7 @@ consread(Chan *c, void *buf, long n, vlong off)
|
|||
static long
|
||||
conswrite(Chan *c, void *va, long n, vlong off)
|
||||
{
|
||||
char buf[256], ch;
|
||||
char buf[256];
|
||||
long l, bp;
|
||||
char *a;
|
||||
Mach *mp;
|
||||
|
@ -1010,29 +694,6 @@ conswrite(Chan *c, void *va, long n, vlong off)
|
|||
}
|
||||
break;
|
||||
|
||||
case Qconsctl:
|
||||
if(n >= sizeof(buf))
|
||||
n = sizeof(buf)-1;
|
||||
strncpy(buf, a, n);
|
||||
buf[n] = 0;
|
||||
for(a = buf; a;){
|
||||
if(strncmp(a, "rawon", 5) == 0){
|
||||
kbd.raw = 1;
|
||||
/* clumsy hack - wake up reader */
|
||||
ch = 0;
|
||||
qwrite(kbdq, &ch, 1);
|
||||
} else if(strncmp(a, "rawoff", 6) == 0){
|
||||
kbd.raw = 0;
|
||||
} else if(strncmp(a, "ctlpon", 6) == 0){
|
||||
kbd.ctlpoff = 0;
|
||||
} else if(strncmp(a, "ctlpoff", 7) == 0){
|
||||
kbd.ctlpoff = 1;
|
||||
}
|
||||
if(a = strchr(a, ' '))
|
||||
a++;
|
||||
}
|
||||
break;
|
||||
|
||||
case Qtime:
|
||||
if(!iseve())
|
||||
error(Eperm);
|
||||
|
|
|
@ -1,120 +0,0 @@
|
|||
/*
|
||||
* keyboard scan code input from outside the kernel.
|
||||
* to avoid duplication of keyboard map processing for usb.
|
||||
*/
|
||||
|
||||
#include "u.h"
|
||||
#include "../port/lib.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "../port/error.h"
|
||||
|
||||
extern void kbdputsc(int, int);
|
||||
|
||||
enum {
|
||||
Qdir,
|
||||
Qkbd,
|
||||
};
|
||||
|
||||
Dirtab kbintab[] = {
|
||||
".", {Qdir, 0, QTDIR}, 0, 0555,
|
||||
"kbin", {Qkbd, 0}, 0, 0200,
|
||||
};
|
||||
|
||||
Lock kbinlck;
|
||||
int kbinbusy;
|
||||
|
||||
static Chan *
|
||||
kbinattach(char *spec)
|
||||
{
|
||||
return devattach(L'Ι', spec);
|
||||
}
|
||||
|
||||
static Walkqid*
|
||||
kbinwalk(Chan *c, Chan *nc, char **name, int nname)
|
||||
{
|
||||
return devwalk(c, nc, name, nname, kbintab, nelem(kbintab), devgen);
|
||||
}
|
||||
|
||||
static int
|
||||
kbinstat(Chan *c, uchar *dp, int n)
|
||||
{
|
||||
return devstat(c, dp, n, kbintab, nelem(kbintab), devgen);
|
||||
}
|
||||
|
||||
static Chan*
|
||||
kbinopen(Chan *c, int omode)
|
||||
{
|
||||
if(!iseve())
|
||||
error(Eperm);
|
||||
if(c->qid.path == Qkbd){
|
||||
lock(&kbinlck);
|
||||
if(kbinbusy){
|
||||
unlock(&kbinlck);
|
||||
error(Einuse);
|
||||
}
|
||||
kbinbusy++;
|
||||
unlock(&kbinlck);
|
||||
}
|
||||
return devopen(c, omode, kbintab, nelem(kbintab), devgen);
|
||||
}
|
||||
|
||||
static void
|
||||
kbinclose(Chan *c)
|
||||
{
|
||||
if(c->aux){
|
||||
free(c->aux);
|
||||
c->aux = nil;
|
||||
}
|
||||
if(c->qid.path == Qkbd)
|
||||
kbinbusy = 0;
|
||||
}
|
||||
|
||||
static long
|
||||
kbinread(Chan *c, void *a, long n, vlong )
|
||||
{
|
||||
if(c->qid.type == QTDIR)
|
||||
return devdirread(c, a, n, kbintab, nelem(kbintab), devgen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long
|
||||
kbinwrite(Chan *c, void *a, long n, vlong)
|
||||
{
|
||||
int i;
|
||||
uchar *p = a;
|
||||
|
||||
if(c->qid.type == QTDIR)
|
||||
error(Eisdir);
|
||||
switch((int)c->qid.path){
|
||||
case Qkbd:
|
||||
for(i = 0; i < n; i++)
|
||||
kbdputsc(*p++, 1); /* external source */
|
||||
break;
|
||||
default:
|
||||
error(Egreg);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
Dev kbindevtab = {
|
||||
L'Ι',
|
||||
"kbin",
|
||||
|
||||
devreset,
|
||||
devinit,
|
||||
devshutdown,
|
||||
kbinattach,
|
||||
kbinwalk,
|
||||
kbinstat,
|
||||
kbinopen,
|
||||
devcreate,
|
||||
kbinclose,
|
||||
kbinread,
|
||||
devbread,
|
||||
kbinwrite,
|
||||
devbwrite,
|
||||
devremove,
|
||||
devwstat,
|
||||
};
|
|
@ -1,179 +0,0 @@
|
|||
/*
|
||||
* keyboard map
|
||||
*/
|
||||
|
||||
#include "u.h"
|
||||
#include "../port/lib.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "../port/error.h"
|
||||
|
||||
enum{
|
||||
Qdir,
|
||||
Qdata,
|
||||
};
|
||||
Dirtab kbmaptab[]={
|
||||
".", {Qdir, 0, QTDIR}, 0, 0555,
|
||||
"kbmap", {Qdata, 0}, 0, 0600,
|
||||
};
|
||||
#define NKBFILE sizeof(kbmaptab)/sizeof(kbmaptab[0])
|
||||
|
||||
#define KBLINELEN (3*NUMSIZE+1) /* t code val\n */
|
||||
|
||||
static Chan *
|
||||
kbmapattach(char *spec)
|
||||
{
|
||||
return devattach(L'κ', spec);
|
||||
}
|
||||
|
||||
static Walkqid*
|
||||
kbmapwalk(Chan *c, Chan *nc, char **name, int nname)
|
||||
{
|
||||
return devwalk(c, nc, name, nname, kbmaptab, NKBFILE, devgen);
|
||||
}
|
||||
|
||||
static int
|
||||
kbmapstat(Chan *c, uchar *dp, int n)
|
||||
{
|
||||
return devstat(c, dp, n, kbmaptab, NKBFILE, devgen);
|
||||
}
|
||||
|
||||
static Chan*
|
||||
kbmapopen(Chan *c, int omode)
|
||||
{
|
||||
if(!iseve())
|
||||
error(Eperm);
|
||||
return devopen(c, omode, kbmaptab, NKBFILE, devgen);
|
||||
}
|
||||
|
||||
static void
|
||||
kbmapclose(Chan *c)
|
||||
{
|
||||
if(c->aux){
|
||||
free(c->aux);
|
||||
c->aux = nil;
|
||||
}
|
||||
}
|
||||
|
||||
static long
|
||||
kbmapread(Chan *c, void *a, long n, vlong offset)
|
||||
{
|
||||
char *bp;
|
||||
char tmp[KBLINELEN+1];
|
||||
int t, sc;
|
||||
Rune r;
|
||||
|
||||
if(c->qid.type == QTDIR)
|
||||
return devdirread(c, a, n, kbmaptab, NKBFILE, devgen);
|
||||
|
||||
switch((int)(c->qid.path)){
|
||||
case Qdata:
|
||||
if(kbdgetmap(offset/KBLINELEN, &t, &sc, &r)) {
|
||||
bp = tmp;
|
||||
bp += readnum(0, bp, NUMSIZE, t, NUMSIZE);
|
||||
bp += readnum(0, bp, NUMSIZE, sc, NUMSIZE);
|
||||
bp += readnum(0, bp, NUMSIZE, r, NUMSIZE);
|
||||
*bp++ = '\n';
|
||||
*bp = 0;
|
||||
n = readstr(offset%KBLINELEN, a, n, tmp);
|
||||
} else
|
||||
n = 0;
|
||||
break;
|
||||
default:
|
||||
n=0;
|
||||
break;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static long
|
||||
kbmapwrite(Chan *c, void *a, long n, vlong)
|
||||
{
|
||||
char line[100], *lp, *b;
|
||||
int key, m, l;
|
||||
Rune r;
|
||||
|
||||
if(c->qid.type == QTDIR)
|
||||
error(Eperm);
|
||||
|
||||
switch((int)(c->qid.path)){
|
||||
case Qdata:
|
||||
b = a;
|
||||
l = n;
|
||||
lp = line;
|
||||
if(c->aux){
|
||||
strcpy(line, c->aux);
|
||||
lp = line+strlen(line);
|
||||
free(c->aux);
|
||||
c->aux = nil;
|
||||
}
|
||||
while(--l >= 0) {
|
||||
*lp++ = *b++;
|
||||
if(lp[-1] == '\n' || lp == &line[sizeof(line)-1]) {
|
||||
*lp = 0;
|
||||
if(*line == 0)
|
||||
error(Ebadarg);
|
||||
if(*line == '\n' || *line == '#'){
|
||||
lp = line;
|
||||
continue;
|
||||
}
|
||||
lp = line;
|
||||
while(*lp == ' ' || *lp == '\t')
|
||||
lp++;
|
||||
m = strtoul(line, &lp, 0);
|
||||
key = strtoul(lp, &lp, 0);
|
||||
while(*lp == ' ' || *lp == '\t')
|
||||
lp++;
|
||||
r = 0;
|
||||
if(*lp == '\'' && lp[1])
|
||||
chartorune(&r, lp+1);
|
||||
else if(*lp == '^' && lp[1]){
|
||||
chartorune(&r, lp+1);
|
||||
if(0x40 <= r && r < 0x60)
|
||||
r -= 0x40;
|
||||
else
|
||||
error(Ebadarg);
|
||||
}else if(*lp == 'M' && ('1' <= lp[1] && lp[1] <= '5'))
|
||||
r = 0xF900+lp[1]-'0';
|
||||
else if(*lp>='0' && *lp<='9') /* includes 0x... */
|
||||
r = strtoul(lp, &lp, 0);
|
||||
else
|
||||
error(Ebadarg);
|
||||
kbdputmap(m, key, r);
|
||||
lp = line;
|
||||
}
|
||||
}
|
||||
if(lp != line){
|
||||
l = lp-line;
|
||||
c->aux = lp = smalloc(l+1);
|
||||
memmove(lp, line, l);
|
||||
lp[l] = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error(Ebadusefd);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
Dev kbmapdevtab = {
|
||||
L'κ',
|
||||
"kbmap",
|
||||
|
||||
devreset,
|
||||
devinit,
|
||||
devshutdown,
|
||||
kbmapattach,
|
||||
kbmapwalk,
|
||||
kbmapstat,
|
||||
kbmapopen,
|
||||
devcreate,
|
||||
kbmapclose,
|
||||
kbmapread,
|
||||
devbread,
|
||||
kbmapwrite,
|
||||
devbwrite,
|
||||
devremove,
|
||||
devwstat,
|
||||
};
|
|
@ -352,3 +352,15 @@ Dev srvdevtab = {
|
|||
srvremove,
|
||||
srvwstat,
|
||||
};
|
||||
|
||||
void
|
||||
srvrenameuser(char *old, char *new)
|
||||
{
|
||||
Srv *sp;
|
||||
|
||||
qlock(&srvlk);
|
||||
for(sp = srv; sp; sp = sp->link)
|
||||
if(sp->owner!=nil && strcmp(old, sp->owner)==0)
|
||||
kstrdup(&sp->owner, new);
|
||||
qunlock(&srvlk);
|
||||
}
|
||||
|
|
|
@ -223,9 +223,7 @@ uartreset(void)
|
|||
if(p->console || p->special){
|
||||
if(uartenable(p) != nil){
|
||||
if(p->console){
|
||||
kbdq = p->iq;
|
||||
serialoq = p->oq;
|
||||
p->putc = kbdcr2nl;
|
||||
}
|
||||
p->opens++;
|
||||
}
|
||||
|
|
|
@ -142,10 +142,6 @@ Segment* isoverlap(Proc*, ulong, int);
|
|||
int ispages(void*);
|
||||
int isphysseg(char*);
|
||||
void ixsummary(void);
|
||||
int kbdcr2nl(Queue*, int);
|
||||
int kbdgetmap(uint, int*, int*, Rune*);
|
||||
int kbdputc(Queue*, int);
|
||||
void kbdputmap(ushort, ushort, Rune);
|
||||
void kickpager(void);
|
||||
void killbig(char*);
|
||||
void kproc(char*, void(*)(void*), void*);
|
||||
|
@ -323,6 +319,7 @@ int spllo(void);
|
|||
void splx(int);
|
||||
void splxpc(int);
|
||||
char* srvname(Chan*);
|
||||
void srvrenameuser(char*, char*);
|
||||
int swapcount(ulong);
|
||||
int swapfull(void);
|
||||
void swapinit(void);
|
||||
|
|
1159
sys/src/cmd/aux/kbdfs.c
Normal file
1159
sys/src/cmd/aux/kbdfs.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -16,6 +16,7 @@ TARG=\
|
|||
depend\
|
||||
disksim\
|
||||
getflags\
|
||||
kbdfs\
|
||||
lines\
|
||||
listen\
|
||||
listen1\
|
||||
|
|
Loading…
Reference in a new issue