|
|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 15130 (0x3b1a)
Types: TextFile
Notes: UNIX file
Names: »kb.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
└─⟦2d53db1df⟧ UNIX Filesystem
└─⟦this⟧ »sys/z8001/drv/video/kb.c«
/* (-lgl
* The information contained herein is a trade secret of Mark Williams
* Company, and is confidential information. It is provided under a
* license agreement, and may be copied or disclosed only under the
* terms of that agreement. Any reproduction or disclosure of this
* material without the express written authorization of Mark Williams
* Company or persuant to the license agreement is unlawful.
*
* COHERENT Version 0.7.3
* Copyright (c) 1982, 1983, 1984.
* An unpublished work by Mark Williams Company, Chicago.
* All rights reserved.
-lgl) */
/*
* Keyboard/display driver.
* 8086/8088 Coherent, IBM PC.
*/
#include <coherent.h>
#if 0
#include <i8086.h>
#endif
#include <con.h>
#include <errno.h>
#include <stat.h>
#include <tty.h>
#include <uproc.h>
#include <signal.h>
#include <timeout.h>
#include <sched.h>
#define SPC 0376 /* Special encoding */
#define XXX 0377 /* Non-character */
#define KBDATA 0x60 /* Keyboard data */
#define KBCTRL 0x61 /* Keyboard control */
#define KBFLAG 0x80 /* Keyboard reset flag */
#define KEYUP 0x80 /* Key up change */
#define KEYSC 0x7F /* Key scan code mask */
#define LSHIFT 0x2A-1 /* Left shift key */
#define LSHIFTA 0x2B-1 /* Alternate left-shift key */
#define RSHIFT 0x36-1 /* Right shift key */
#define CTRL 0x1D-1 /* Control key */
#define ALT 0x38-1 /* Alt key */
#define CAPLOCK 0x3A-1 /* Caps lock key */
#define NUMLOCK 0x45-1 /* Numeric lock key */
#define DELETE 0x53-1 /* Del, as in CTRL-ALT-DEL */
#define BACKSP 0x0E-1 /* Back space */
#define SCRLOCK 0x46-1 /* Scroll lock */
/* Shift flags */
#define SRS 0x01 /* Right shift key on */
#define SLS 0x02 /* Left shift key on */
#define CTS 0x04 /* Ctrl key on */
#define ALS 0x08 /* Alt key on */
#define CPLS 0x10 /* Caps lock on */
#define NMLS 0x20 /* Num lock on */
#define AKPS 0x40 /* Alternate keypad shift */
#define SHFT 0x80 /* Shift key flag */
/* Function key information */
#define NFKEY 40 /* Number of settable functions */
#define NFCHAR 600 /* Number of characters settable */
#define NFBUF (NFKEY*2+NFCHAR+1) /* Size of buffer */
/*
* Functions.
*/
int isrint();
int istime();
int mmstart();
int isopen();
int isclose();
int isread();
int iswrite();
int isioctl();
int isload();
int isuload();
int nulldev();
int nonedev();
/* External from "mm.c" */
extern char mminsmode; /* insert mode state */
/*
* Configuration table.
*/
CON iscon ={
DFCHR, /* Flags */
15, /* Major index */
isopen, /* Open */
isclose, /* Close */
nulldev, /* Block */
isread, /* Read */
iswrite, /* Write */
isioctl, /* Ioctl */
nulldev, /* Powerfail */
nulldev, /* Timeout */
isload, /* Load */
isuload /* Unload */
};
/*
* Terminal structure.
*/
TTY istty = {
{0}, {0}, 0, mmstart, NULL, 0, 0
};
/*
* State variables.
*/
static char shift; /* Overall shift state */
static char lshift = LSHIFT; /* Left shift alternate state */
static char isfbuf[NFBUF]; /* Function key values */
static char *isfval[NFKEY]; /* Function key string pointers */
/*
* Tables for converting key code to ASCII.
* lmaptab specifies unshifted conversion,
* umaptab specifies shifted conversion,
* smaptab specifies the shift states which are active.
* An entry of XXX says the key is dead.
* An entry of SPC requires further processing.
*
* Key codes:
* ESC .. <- == 1 .. 14
* -> .. \n == 15 .. 28
* CTRL .. ` == 29 .. 41
* ^Shift .. PrtSc == 42 .. 55
* ALT .. CapsLock == 56 .. 58
* F1 .. F10 == 59 .. 68
* NumLock .. Del == 69 .. 83
*/
static unsigned char lmaptab[] ={
'\33', '1', '2', '3', '4', '5', '6', /* 1 - 7 */
'7', '8', '9', '0', '-', '=', '\b', '\t', /* 8 - 15 */
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', /* 16 - 23 */
'o', 'p', '[', ']', '\r', XXX, 'a', 's', /* 24 - 31 */
'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* 32 - 39 */
'\'', '`', XXX, '\\', 'z', 'x', 'c', 'v', /* 40 - 47 */
'b', 'n', 'm', ',', '.', '/', XXX, '*', /* 48 - 55 */
XXX, ' ', XXX, SPC, SPC, SPC, SPC, SPC, /* 56 - 63 */
SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC, /* 64 - 71 */
SPC, SPC, '-', SPC, SPC, SPC, '+', SPC, /* 72 - 79 */
SPC, SPC, SPC, SPC /* 80 - 83 */
};
static unsigned char umaptab[] ={
'\33', '!', '@', '#', '$', '%', '^', /* 1 - 7 */
'&', '*', '(', ')', '_', '+', '\b', '\t', /* 8 - 15 */
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', /* 16 - 23 */
'O', 'P', '{', '}', '\r', XXX, 'A', 'S', /* 24 - 31 */
'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', /* 32 - 39 */
'"', '~', XXX, '|', 'Z', 'X', 'C', 'V', /* 40 - 47 */
'B', 'N', 'M', '<', '>', '?', XXX, '*', /* 48 - 55 */
XXX, ' ', XXX, SPC, SPC, SPC, SPC, SPC, /* 56 - 63 */
SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC, /* 64 - 71 */
SPC, SPC, '-', SPC, SPC, SPC, '+', SPC, /* 72 - 79 */
SPC, SPC, SPC, SPC /* 80 - 83 */
};
#define SS0 0 /* No shift */
#define SS1 (SLS|SRS|CTS) /* Shift, Ctrl */
#define SES (SLS|SRS) /* Shift */
#define LET (SLS|SRS|CPLS|CTS) /* Shift, Caps, Ctrl */
#define KEY (SLS|SRS|NMLS|AKPS) /* Shift, Num, Alt keypad */
static unsigned char smaptab[] ={
SS0, SES, SS1, SES, SES, SES, SS1, /* 1 - 7 */
SES, SES, SES, SES, SS1, SES, CTS, SS0, /* 8 - 15 */
LET, LET, LET, LET, LET, LET, LET, LET, /* 16 - 23 */
LET, LET, SS1, SS1, CTS, SHFT, LET, LET, /* 24 - 31 */
LET, LET, LET, LET, LET, LET, LET, SES, /* 32 - 39 */
SES, SS1, SHFT, SS1, LET, LET, LET, LET, /* 40 - 47 */
LET, LET, LET, SES, SES, SES, SHFT, SES, /* 48 - 55 */
SHFT, SS1, SHFT, SS0, SS0, SS0, SS0, SS0, /* 56 - 63 */
SS0, SS0, SS0, SS0, SS0, SHFT, KEY, KEY, /* 64 - 71 */
KEY, KEY, SS0, KEY, KEY, KEY, SS0, KEY, /* 72 - 79 */
KEY, KEY, KEY, KEY /* 80 - 83 */
};
/*
* Load entry point.
* Do reset the keyboard because it gets terribly munged
* if you type during the boot.
*/
isload()
{
register int i;
#if 0
outb(KBCTRL, 0x0C); /* Clock low */
for (i = 10582; --i >= 0; ); /* For 20ms */
outb(KBCTRL, 0xCC); /* Clock high */
for (i = 0; --i != 0; )
;
i = inb(KBDATA);
outb(KBCTRL, 0xCC); /* Clear keyboard */
outb(KBCTRL, 0x4D); /* Enable keyboard */
setivec(1, isrint);
#endif
mmload();
}
/*
* Unload entry point.
*/
isuload()
{
#if 0
clrivec(1);
#endif
}
/*
* Default function key strings (terminated by -1 [\377])
*/
static char *deffuncs[] = {
"\33S\377", /* F1 */
"\33T\377", /* F2 */
"\33U\377", /* F3 */
"\33V\377", /* F4 */
"\33W\377", /* F5 */
"\33P\377", /* F6 (BLUE) */
"\33Q\377", /* F7 (RED) */
"\33R\377", /* F8 (GRAY) */
"\000\377", /* F9 (null) */
"\177\377" /* F10 (rubout) */
};
/*
* Open routine.
*/
isopen(dev)
dev_t dev;
{
register int s;
if (minor(dev) != 0) {
u.u_error = ENXIO;
return;
}
if ((istty.t_flags&T_EXCL)!=0 && super()==0) {
u.u_error = ENODEV;
return;
}
ttsetgrp(&istty, dev);
s = sphi();
if (istty.t_open++ == 0)
{
#if 0
initkeys(); /* init function keys */
#endif
istty.t_flags = T_CARR; /* indicate "carrier" */
ttopen(&istty);
}
spl(s);
}
/* Init function keys */
initkeys()
{ register int i;
register char *cp1, *cp2;
for (i=0; i<NFKEY; i++)
isfval[i] = -1; /* clear function key buffer */
cp1 = deffuncs; /* pointer to key init string */
cp2 = isfbuf; /* pointer to key buffer */
for (i=0; i<NFKEY; i++)
{ isfval[i] = cp2; /* save pointer to key string */
cp1 = deffuncs[i]; /* get init string pointer */
while ((*cp2++ = *cp1++) != -1) /* copy key data */
if (cp2 >= &isfbuf[NFBUF-3]) /* overflow? */
return;
}
}
/*
* Close a tty.
*/
isclose(dev)
{
register int s;
s = sphi();
if (--istty.t_open == 0)
{ s = sphi();
ttclose(&istty);
spl(s);
}
}
/*
* Read routine.
*/
isread(dev, iop)
dev_t dev;
IO *iop;
{
ttread(&istty, iop, SFCW);
}
/*
* Write routine.
*/
iswrite(dev, iop)
dev_t dev;
IO *iop;
{
ttwrite(&istty, iop, SFCW);
}
/*
* Ioctl routine.
*/
isioctl(dev, com, vec)
dev_t dev;
struct sgttyb *vec;
{
register int s;
switch(com) {
case TIOCSETF:
case TIOCGETF:
#if 0
isfunction(com, (char *)vec);
#endif
return;
case TIOCSHIFT: /* switch left-SHIFT and "\" */
lshift = LSHIFTA; /* alternate values */
lmaptab[41] = '\\';
lmaptab[42] = XXX;
umaptab[41] = '|';
umaptab[42] = XXX;
smaptab[41] = SS1;
smaptab[42] = SHFT;
return;
case TIOCCSHIFT: /* normal (default) left-SHIFT and "\" */
lshift = LSHIFT; /* normal values */
lmaptab[41] = XXX;
lmaptab[42] = '\\';
umaptab[41] = XXX;
umaptab[42] = '|';
smaptab[41] = SHFT;
smaptab[42] = SS1;
return;
case TIOVGETB:
case TIOVPUTB:
while (istty.t_oq.cq_cc != 0) {
s = sphi();
if (istty.t_oq.cq_cc != 0) {
istty.t_flags |= T_DRAIN;
sleep((char *)&istty.t_oq,
CVTTOUT, IVTTOUT, SVTTOUT);
}
spl(s);
if (SELF->p_ssig && nondsig()) {
u.u_error = EINTR;
return;
}
}
mmioctl(com, vec);
return;
}
s = sphi();
ttioctl(&istty, com, vec);
spl(s);
}
/*
* Set and receive the function keys.
*/
isfunction(c, v)
int c;
char *v;
{
register char *cp;
register int i;
if (c == TIOCGETF) {
for (cp = isfbuf; cp < &isfbuf[NFBUF]; cp++)
putubd(v++, *cp);
} else {
for (i=0; i<NFKEY; i++) /* zap current settings */
isfval[i] = -1;
cp = isfbuf; /* pointer to key buffer */
for (i=0; i<NFKEY; i++) {
isfval[i] = cp; /* save pointer to key string */
while ((*cp++ = getubd(v++)) != -1) /* copy key data */
if (cp >= &isfbuf[NFBUF-3]) /* overflow? */
return;
}
}
}
/*
* Receive interrupt.
*/
isrint()
{
register int c;
register int s;
register int r;
/*
* Pull character from the data
* port. Pulse the KBFLAG in the control
* port to reset the data buffer.
*/
r = inb(KBDATA) & 0xFF;
c = inb(KBCTRL);
outb(KBCTRL, c|KBFLAG);
outb(KBCTRL, c);
if (r == 0xFF)
return; /* Overrun */
c = (r & KEYSC) - 1;
/*
* Check for reset.
*/
#if 0
if ((r&KEYUP) == 0 && c == DELETE && (shift&(CTS|ALS)) == (CTS|ALS))
boot();
#endif
/*
* Track "shift" keys.
*/
s = smaptab[c];
if (s&SHFT) {
if (r&KEYUP) { /* "shift" released */
if (c == RSHIFT)
shift &= ~SRS;
else if (c == lshift)
shift &= ~SLS;
else if (c == CTRL)
shift &= ~CTS;
else if (c == ALT)
shift &= ~ALS;
} else { /* "shift" pressed */
if (c == lshift)
shift |= SLS;
else if (c == RSHIFT)
shift |= SRS;
else if (c == CTRL)
shift |= CTS;
else if (c == ALT)
shift |= ALS;
else if (c == CAPLOCK)
shift ^= CPLS; /* toggle cap lock */
else if (c == NUMLOCK)
shift ^= NMLS; /* toggle num lock */
}
return;
}
/*
* No other key up codes of interest.
*/
if (r&KEYUP)
return;
/*
* If the tty is not open the character is
* just tossed away.
*/
if (istty.t_open == 0)
return;
/*
* Map character, based on the
* current state of the shift, control,
* meta and lock flags.
*/
if (shift & CTS) {
if (s == CTS) /* Map Ctrl (BS | NL) */
c = (c == BACKSP) ? 0x7F : 0x0A;
else if (s==SS1 || s==LET) /* Normal Ctrl map */
c = umaptab[c]&0x1F; /* Clear bits 5-6 */
else
return; /* Ignore this char */
} else if (s &= shift) {
if (shift & SES) { /* if shift on */
if (s & (CPLS|NMLS)) /* if caps/num lock */
c = lmaptab[c]; /* use unshifted */
else
c = umaptab[c]; /* use shifted */
} else { /* if shift not on */
if (s & (CPLS|NMLS)) /* if caps/num lock */
c = umaptab[c]; /* use shifted */
else
c = lmaptab[c]; /* use unshifted */
}
} else
c = lmaptab[c]; /* use unshifted */
/*
* Act on character.
*/
if (c == XXX)
return; /* char to ignore */
if (c != SPC) { /* not special char? */
if (shift & ALS) /* ALT (meta bit)? */
c |= 0x80; /* set meta */
s = sphi();
ttin(&istty, c); /* send the char */
spl(s);
} else
isspecial(r); /* special chars */
}
/*
* Handle special input sequences.
* The character passed is the key number.
*
* The keypad is translated by the following table,
* the first entry is the normal sequence, the second the shifted,
* and the third the alternate keypad sequence.
*/
static char *keypad[][3] = {
{ "7", 0, "\33?w" }, /* 71 (special shifted handling) */
{ "8", "\33A", "\33?x" }, /* 72 */
{ "9", "\33N", "\33?y" }, /* 73 */
{ "4", "\33D", "\33?t" }, /* 75 */
{ "5", "\33H", "\33?u" }, /* 76 */
{ "6", "\33C", "\33?v" }, /* 77 */
{ "1", "\33L", "\33?q" }, /* 79 */
{ "2", "\33B", "\33?r" }, /* 80 */
{ "3", "\33M", "\33?s" }, /* 81 */
{ "0", "0", "\33?p" }, /* 82 */
{ ".", ".", "\33?n" } /* 83 */
};
isspecial(c)
int c;
{
register char *cp;
register int s;
cp = 0;
switch (c) {
case 59: case 60: case 61: case 62: case 63: /* Function keys */
case 64: case 65: case 66: case 67: case 68:
if (shift & SES)
if (shift & ALS)
cp = isfval[c - 59 +30];
else
cp = isfval[c - 59 + 10];
else if (shift & ALS)
cp = isfval[c - 59 + 20];
else
cp = isfval[c-59]; /* offset to function string */
while (*cp != -1) /* copy chars up to -1 to istty */
{ s = sphi();
ttin(&istty, *cp++);
spl(s);
}
return;
case 70: /* Scroll Lock -- stop/start output */
{
static char cbuf[2];
cp = &cbuf[0]; /* working buffer */
if (istty.t_flags & T_STOP) /* output stopped? */
cbuf[0] = istty.t_tchars.t_startc; /* start output */
else
cbuf[0] = istty.t_tchars.t_stopc; /* stop output */
break;
}
case 79: /* 1/End */
case 80: /* 2/DOWN */
case 81: /* 3/PgDn */
case 82: /* 0/Ins */
case 83: /* ./Del */
--c; /* adjust code */
case 75: /* 4/LEFT */
case 76: /* 5 */
case 77: /* 6/RIGHT */
--c; /* adjust code */
case 71: /* 7/Home/Clear */
case 72: /* 8/UP */
case 73: /* 9/PgUp */
s = 0; /* start off with normal keypad */
if (shift&NMLS) /* num lock? */
s = 1; /* set shift pad */
if (shift&SES) /* shift? */
s ^= 1; /* toggle shift pad */
if (s == 0 && (shift&AKPS)) /* (!shifted) and alternate pad? */
s = 2; /* set alternate pad */
cp = keypad[c-71][s]; /* get keypad value */
if (cp == 0) /* shift-keypad-7 ? (special) */
{ if (mminsmode) /* in insert mode? */
cp = "\33O"; /* send exit insert sequence */
else
cp = "\33@"; /* send enter insert sequence */
}
break;
}
if (cp) /* send string */
while (*cp) {
s = sphi();
ttin(&istty, (*cp++&0377));
spl(s);
}
}
ismmfunc(c)
register int c;
{
switch (c) {
case 't': /* Enter numlock */
shift |= NMLS;
break;
case 'u': /* Leave numlock */
shift &= ~NMLS;
break;
case '=': /* Enter alternate keypad */
shift |= AKPS;
break;
case '>': /* Exit alternate keypad */
shift &= ~AKPS;
break;
case 'z': /* Reset terminal */
shift = 0;
break;
}
}