plan 9 kernel history: overview | file list | diff list

1997/1101/carrera/kbd.c (diff list | history)

carrera/kbd.c on 1993/0907
1993/0907    
#include	"u.h" 
#include	"../port/lib.h" 
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"io.h" 
#include	"../port/error.h" 
 
1997/1101    
#define	Image	IMAGE 
#include	<draw.h> 
1997/0327    
#include	"screen.h" 
1993/0907    
 
enum 
{ 
1994/0306    
	/* controller command byte */ 
	Cscs1=		(1<<6),		/* scan code set 1 */ 
	Cmousedis=	(1<<5),		/* mouse disable */ 
	Ckbddis=	(1<<4),		/* kbd disable */ 
	Csf=		(1<<2),		/* system flag */ 
	Cmouseint=	(1<<1),		/* mouse interrupt enable */ 
	Ckbdint=	(1<<0),		/* kbd interrupt enable */ 
 
1993/0907    
	/* 
	 *  responses from keyboard 
	 */ 
	Rok=		0xAA,		/* self test OK */ 
	Recho=		0xEE,		/* ??? */ 
	Rack=		0xFA,		/* command acknowledged */ 
	Rfail=		0xFC,		/* self test failed */ 
	Rresend=	0xFE,		/* ??? */ 
	Rovfl=		0xFF,		/* input overflow */ 
1994/0306    
 
1993/0907    
	/* 
	 *  status bits 
	 */ 
	Sobf=		1<<0,	/* output buffer full */ 
	Sibf=		1<<1,	/* input buffer full */ 
	Ssys=		1<<2,	/* set by self-test */ 
	Slast=		1<<3,	/* last access was to data */ 
	Senabled=	1<<4,	/* keyboard is enabled */ 
	Stxtimeout=	1<<5,	/* transmit to kybd has timed out */ 
	Srxtimeout=	1<<6,	/* receive from kybd has timed out */ 
	Sparity=	1<<7,	/* parity on byte was even */ 
1994/0306    
 
	Spec=		0x80, 
 
	PF=		Spec|0x20,	/* num pad function key */ 
	View=		Spec|0x00,	/* view (shift window up) */ 
	KF=		Spec|0x40,	/* function key */ 
	Shift=		Spec|0x60, 
	Break=		Spec|0x61, 
	Ctrl=		Spec|0x62, 
	Latin=		Spec|0x63, 
	Caps=		Spec|0x64, 
	Num=		Spec|0x65, 
	Middle=		Spec|0x66, 
	No=		0x00,		/* peter */ 
 
	Home=		KF|13, 
	Up=		KF|14, 
	Pgup=		KF|15, 
	Print=		KF|16, 
	Left=		View, 
	Right=		View, 
	End=		'\r', 
	Down=		View, 
	Pgdown=		View, 
	Ins=		KF|20, 
	Del=		0x7F, 
1993/0907    
}; 
 
#define KBDCTL	(*(uchar*)(KeyboardIO+Keyctl)) 
#define KBDDAT	(*(uchar*)(KeyboardIO+Keydat)) 
#define OUTWAIT	while(KBDCTL & Sibf); kdbdly(1) 
#define INWAIT	while(!(KBDCTL & Sobf)); kdbdly(1) 
#define ACKWAIT INWAIT ; if(KBDDAT != Rack) print("bad response\n"); kdbdly(1) 
 
1994/0306    
uchar kbtab[] =  
1993/0907    
{ 
1994/0306    
[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,	KF|12,	'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, 
1993/0907    
}; 
 
1994/0306    
uchar kbtabshift[] = 
{ 
[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,	KF|12,	'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, 
1993/0907    
}; 
 
1994/0306    
uchar kbtabesc1[] = 
{ 
[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]	Latin,	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, 
1993/0907    
}; 
 
struct Kbd 
{ 
	Lock; 
	int l; 
} kbd; 
1994/0306    
static uchar ccc; 
1993/0907    
 
void 
kdbdly(int l) 
{ 
	int i; 
 
1993/0908    
	l *= 21;	/* experimentally determined */ 
1993/0907    
	for(i=0; i<l; i++) 
		; 
} 
 
/* 
 *  wait for a keyboard event (or some max time) 
 */ 
int 
kbdwait(void) 
{ 
	int tries; 
 
	for(tries = 0; tries < 2000; tries++){ 
1993/1001    
		if(KBDCTL & Sobf) 
1993/0907    
			return 1; 
		kdbdly(1); 
	} 
	return 0; 
} 
 
1993/1001    
void 
mouseintr(void) 
{ 
1993/1003    
	uchar c; 
	static int nb; 
	int buttons, dx, dy; 
	static short msg[3]; 
	static uchar b[] = {0, 1, 4, 5, 2, 3, 6, 7, 0, 1, 2, 5, 2, 3, 6, 7 }; 
1993/1001    
 
	kbdwait(); 
1993/1003    
	c = KBDDAT; 
 
	/*  
	 *  check byte 0 for consistency 
	 */ 
	if(nb==0 && (c&0xc8)!=0x08) 
		return; 
 
	msg[nb] = c; 
	if(++nb == 3){ 
		nb = 0; 
		if(msg[0] & 0x10) 
			msg[1] |= 0xFF00; 
		if(msg[0] & 0x20) 
			msg[2] |= 0xFF00; 
 
		buttons = b[msg[0]&7]; 
		dx = msg[1]; 
		dy = -msg[2]; 
		mousetrack(buttons, dx, dy); 
	} 
1993/0907    
} 
 
1994/0306    
void 
1993/0907    
kbdintr(void) 
{ 
1994/0503    
	int c, i; 
1994/0306    
	static int esc1, esc2; 
	static int caps; 
	static int ctl; 
	static int num; 
1994/0503    
	static int collecting, nk; 
1993/0907    
	static uchar kc[5]; 
1994/0306    
	static int shift; 
	int keyup; 
1993/0907    
 
	kbdwait(); 
1994/0306    
	c = KBDDAT; 
1993/0907    
 
	/* 
1994/0306    
	 *  e0's is the first of a 2 character sequence 
1993/0907    
	 */ 
1994/0306    
	if(c == 0xe0){ 
		esc1 = 1; 
		return; 
	} else if(c == 0xe1){ 
		esc2 = 2; 
		return; 
1993/0908    
	} 
 
1994/0306    
	keyup = c&0x80; 
	c &= 0x7f; 
	if(c > sizeof kbtab){ 
		print("unknown key %ux\n", c|keyup); 
		return; 
	} 
1993/0908    
 
1994/0306    
	if(esc1){ 
		c = kbtabesc1[c]; 
		esc1 = 0; 
1993/0907    
	} 
1994/0306    
	else if(esc2){ 
		esc2--; 
		return; 
	} 
	else if(shift) 
		c = kbtabshift[c]; 
	else 
		c = kbtab[c]; 
1993/0907    
 
1994/0306    
	if(caps && c<='z' && c>='a') 
		c += 'A' - 'a'; 
 
1993/0907    
	/* 
1994/0306    
	 *  keyup only important for shifts 
1993/0907    
	 */ 
1994/0306    
	if(keyup){ 
		switch(c){ 
		case Shift: 
			shift = 0; 
			break; 
		case Ctrl: 
			ctl = 0; 
			break; 
		} 
		return; 
	} 
1993/0907    
	/* 
 	 *  normal character 
	 */ 
1994/0306    
	if(!(c & Spec)){ 
		if(ctl) 
			c &= 0x1f; 
1994/0503    
		if(!collecting){ 
1994/0306    
			kbdputc(kbdq, c); 
1994/0503    
			return; 
1993/0907    
		} 
1994/0503    
		kc[nk++] = c; 
		c = latin1(kc, nk); 
		if(c < -1)	/* need more keystrokes */ 
			return; 
		if(c != -1)	/* valid sequence */ 
			kbdputc(kbdq, c); 
		else	/* dump characters */ 
			for(i=0; i<nk; i++) 
				kbdputc(kbdq, kc[i]); 
		nk = 0; 
		collecting = 0; 
1994/0306    
		return; 
1993/0907    
	} 
1994/0306    
	else { 
		switch(c){ 
		case Caps: 
			caps ^= 1; 
			return; 
		case Num: 
			num ^= 1; 
			return; 
		case Shift: 
			shift = 1; 
			return; 
		case Latin: 
1994/0503    
			collecting = 1; 
			nk = 0; 
1994/0306    
			return; 
		case Ctrl: 
			ctl = 1; 
			return; 
		} 
1993/0907    
	} 
1994/0306    
	kbdputc(kbdq, c); 
1993/0907    
} 
 
void 
lights(int l) 
{ 
1994/0306    
	USED(l); 
1993/0907    
} 
 
static void 
empty(void) 
{ 
	int i; 
 
	/* 
	 *  empty the buffer 
	 */ 
	kdbdly(20); 
	while(KBDCTL & Sobf){ 
		i = KBDDAT; 
		USED(i); 
		kdbdly(1); 
	} 
} 
 
1993/1003    
/* 
 *  send a command to the mouse 
 */ 
static int 
mousecmd(int cmd) 
{ 
	int tries; 
	unsigned int c; 
 
	c = 0; 
	tries = 0; 
	do{ 
		if(tries++ > 2) 
			break; 
		OUTWAIT; 
		KBDCTL = 0xD4; 
		OUTWAIT; 
		KBDDAT = cmd; 
		OUTWAIT; 
		kbdwait(); 
		c = KBDDAT; 
	} while(c == 0xFE || c == 0); 
	if(c != 0xFA){ 
1995/1101    
		/*print("mouse returns %2.2ux to the %2.2ux command\n", c, cmd);/**/ 
1993/1003    
		return -1; 
	} 
	return 0; 
} 
 
1993/0907    
int 
kbdinit(void) 
{ 
	int i; 
1994/0428    
 
1994/0621    
	kbdq = qopen(4*1024, 0, 0, 0); 
1994/0902    
	qnoblock(kbdq, 1); 
1994/0621    
 
1993/0907    
	/* 
	 *  empty the buffer 
	 */ 
	while(KBDCTL & Sobf){ 
		i = KBDDAT; 
		USED(i); 
	} 
 
 
1994/0306    
	/* wait for a quiescent controller */ 
1993/0907    
	OUTWAIT; 
1994/0306    
	KBDCTL = 0x20; 
	if(kbdwait() == 0) { 
		print("kbdinit: can't read ccc\n"); 
		ccc = 0; 
	} else 
		ccc = KBDDAT; 
1993/0907    
 
1994/0306    
	/* enable kbd xfers and interrupts */ 
	ccc &= ~Ckbddis; 
	ccc |= Csf | Ckbdint | Cscs1 | Cmouseint; 
1993/0907    
 
	OUTWAIT; 
1994/0306    
	KBDCTL = 0x60; 
1993/0907    
	OUTWAIT; 
1994/0306    
	KBDDAT = ccc; 
1993/0907    
	OUTWAIT; 
1993/1003    
 
1994/0201    
	mousecmd(0xEA);	/* streaming */ 
	mousecmd(0xE8);	/* set resolution */ 
	mousecmd(3); 
	mousecmd(0xF4);	/* enabled */ 
1993/0907    
 
	return 1; 
} 
1994/0910    
 
void 
mousectl(char *cmd) 
{ 
	int s; 
 
	if(strncmp(cmd, "reset", 5) == 0){ 
		s = splhi(); 
		mousecmd(0xF6); 
		mousecmd(0xEA);	/* streaming */ 
		mousecmd(0xE8);	/* set resolution */ 
		mousecmd(3); 
		mousecmd(0xF4);	/* enabled */ 
		splx(s); 
	} 
1995/1216    
	else if(strcmp(cmd, "accelerated") == 0){ 
		s = splhi(); 
		mousecmd(0xE7); 
		splx(s); 
	} 
1995/0207    
	else 
		error(Ebadctl); 
1994/0910    
} 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)