Annotation of coherent/b/kernel/FWB2/interfac.c, revision 1.1.1.1

1.1       root        1: /*-----------------------------------------------------------------------------
                      2:        Talking BIOS device driver for the AT&T PC6300.
                      3:        Copyright (C) Karl Dahlke 1987
                      4:        This software may be freely used and distributed
                      5:        for any non-profit purpose.
                      6:  *-----------------------------------------------------------------------------
                      7:  */
                      8: 
                      9: /* interfac.c: interface function to kernel and device drivers */
                     10: 
                     11: /* This file contains routines to speak letters, words, single lines,
                     12:  * and the entire screen/buffer.
                     13:  * These routines are called at interrupt level, but they may take
                     14:  * as long as they wish.  A frozen view of pointers is presented,
                     15:  * and I know of no way they can change while these routines are executing
                     16:  * (though there may be an obscure scenario).
                     17:  * A separate stack of around 200 bytes is provided,
                     18:  * but there's no stack checking, so be careful.
                     19:  * Also, this stack is not aligned with the data segment,
                     20:  * so don't use the address of any auto variable.
                     21:  */
                     22: 
                     23: #ifndef MSDOS
                     24: #include <sgtty.h>
                     25: #else
                     26: /* taken from Coherent sgtty.h */
                     27: #define TIOCSDSIZE 0140
                     28: #define TIOCSDGETBUF 0141
                     29: #endif
                     30: 
                     31: #include "speech.h"
                     32: 
                     33: /* control variables for each of 5 concurrent sessions: console + 4 comports */
                     34: struct SDCONTROL *sdcontrol[5];
                     35: struct SDCONTROL *sdc; /* set to sdcontrol[sdsession] */
                     36: int sdsession; /* current session, 0 for the console, 1-4 for the comports */
                     37: char sdw[WORDLEN*2]; /* word to be spoken */
                     38: 
                     39: /* patchable variables that establish synthesizer, comport,
                     40:  * and size of internal circular buffer, for each of 5 possible sessions.
                     41:  * The 5 configured synthesizers */
                     42: int sd0synth = 0, sd1synth = 0, sd2synth = 0, sd3synth = 0, sd4synth = 0;
                     43: int sd0comport = 0, sd1comport = 0, sd2comport = 0, sd3comport = 0, sd4comport = 0;
                     44: unsigned int sd0cbufsz = 0, sd1cbufsz = 0, sd2cbufsz = 0, sd3cbufsz = 0, sd4cbufsz = 0;
                     45: 
                     46: #ifdef MSDOS
                     47: static char far *doslineptr;
                     48: skipwhite()
                     49: {
                     50: char c;
                     51: c = *doslineptr;
                     52: while(c == ' ' || c == '\t') c = *++doslineptr;
                     53: } /* skipwhite */
                     54: 
                     55: /* a version of strtol, to help crack the dos parameters */
                     56: static unsigned int nextparm()
                     57: {
                     58: unsigned int n = 0;
                     59: char c;
                     60: 
                     61: skipwhite();
                     62: c = *doslineptr;
                     63: 
                     64: while(isdigit(c)) {
                     65: n = 10*n + c - '0';
                     66: c = *++doslineptr;
                     67: } /* n is built */
                     68: 
                     69: return n;
                     70: } /* nextparm */
                     71: 
                     72: /* interpret line in config.sys, DOS only.
                     73:  * Coherent just patches the global variables to set parameters. */
                     74: dosline(line)
                     75: char far *line;
                     76: {
                     77: char c;
                     78: 
                     79: /* skip past command name and set doslineptr */
                     80: c = *line;
                     81: while(c != ' ' && c != '\t' && c != '\r')
                     82: c = *++line;
                     83: doslineptr = line;
                     84: 
                     85: sd0cbufsz = nextparm();
                     86: sd0comport = nextparm();
                     87: sd0synth = nextparm();
                     88: 
                     89: skipwhite();
                     90: c = *doslineptr;
                     91: if(c != '\r') /* error message about command line format */;
                     92: } /* dosline */
                     93: #endif
                     94: 
                     95: /* interface function, called from isload() */
                     96: sdload()
                     97: {
                     98: char *bufstart;
                     99: int i;
                    100: unsigned int reqsz;
                    101: struct SDCONTROL *o;
                    102: extern isin();
                    103: static char defkeymap[] = {
                    104: 12,13,14,15,16,
                    105: 17,18,23,22,28};
                    106: static char defpuncmap[] = "\
                    107: null~~~~~~\
                    108: escape~~~~\
                    109: askie 1c~~\
                    110: askie 1d~~\
                    111: askie 1e~~\
                    112: askie 1f~~\
                    113: space~~~~~\
                    114: bang~~~~~~\
                    115: quoat~~~~~\
                    116: pound~~~~~\
                    117: doller~~~~\
                    118: percent~~~\
                    119: and~~~~~~~\
                    120: single~~~~\
                    121: left paren\
                    122: rite paren\
                    123: star~~~~~~\
                    124: plus~~~~~~\
                    125: comma~~~~~\
                    126: mighnus~~~\
                    127: periud~~~~\
                    128: slash~~~~~\
                    129: colen~~~~~\
                    130: semmy~~~~~\
                    131: less~~~~~~\
                    132: eequal~~~~\
                    133: greater~~~\
                    134: question~~\
                    135: at sign~~~\
                    136: left b~~~~\
                    137: backslash~\
                    138: rite b~~~~\
                    139: up airow~~\
                    140: underline~\
                    141: backquoat~\
                    142: left brace\
                    143: vertical~~\
                    144: rite brace\
                    145: tillda~~~~\
                    146: deleet~~~~\
                    147: ";
                    148: 
                    149: /* allocate word replacement and macro definition areas */
                    150: sdtblload();
                    151: 
                    152: /* find and establish screen memory */
                    153: sdscrnset();
                    154: 
                    155: for(i=0; i<5; ++i) {
                    156: sdsynth_init(i);
                    157: if(!(o = sdcontrol[i])) continue; /* kalloc failed */
                    158: 
                    159: /* I/O functions. */
                    160: o->dev_in = isin;
                    161: 
                    162: /* initialize the punctuation pronunciation table */
                    163: memcpy(o->punctab, defpuncmap, 40*10);
                    164: 
                    165: /* initialize the key mappings */
                    166: memcpy(o->keymap+0x3b, defkeymap, 10);
                    167: 
                    168: /* circular buffer */
                    169: reqsz = (&sd0cbufsz)[i];
                    170: if(reqsz < 400) reqsz = 400;
                    171: if(!(bufstart = kalloc(reqsz))) {
                    172: reqsz = sizeof(o->defcbuf);
                    173: bufstart = o->defcbuf;
                    174: }
                    175: o->bufbot =
                    176: o->bufhead =
                    177: o->buftail =
                    178: o->bufcur =
                    179: bufstart;
                    180: o->buftop = bufstart + reqsz;
                    181: 
                    182: /* modes that are set */
                    183: o->dev_ok = 1;
                    184: o->buf_ok = 1;
                    185: } /* end loop initializing structures */
                    186: 
                    187: /* startup sound.
                    188:  * More than just cute, we need to do this, or something like it,
                    189:  * to enable the speaker, so that subsequen noises,
                    190:  * produce by system output, before going multiuser,
                    191:  * generates audio feedback. */
                    192: sdsound(8);
                    193: } /* sdload */
                    194: 
                    195: #ifndef MSDOS
                    196: /* interface function, called from isuload() */
                    197: sduload()
                    198: {
                    199: int i;
                    200: struct SDCONTROL *o;
                    201: int comport;
                    202: extern char *sdscreenmem;
                    203: 
                    204: for(i=0; i<5; ++i) {
                    205: if(!(o = sdcontrol[i])) continue;
                    206: 
                    207: comport = (&sd0comport)[i];
                    208: if(comport)
                    209: clrivec((comport&1)+3);
                    210: 
                    211: if(o->bufbot != o->defcbuf)
                    212: kfree(o->bufbot);
                    213: kfree(o);
                    214: sdcontrol[i] = 0;
                    215: } /* end loop over sessions */
                    216: 
                    217: unmap_pv(sdscreenmem);
                    218: } /* sduload */
                    219: #endif
                    220: 
                    221: /* ioctl call, only used to save the buffer to a file */
                    222: #ifdef MSDOS
                    223: sdioctl(session, v)
                    224: char far * far *v;
                    225: {
                    226: struct SDCONTROL *o = sdcontrol[session];
                    227: extern char far *sdscreenmem;
                    228: 
                    229: if(!o) return -1;
                    230: 
                    231: if(!session && sdscreenmode) {
                    232: v[0] = sdscreenmem;
                    233: v[1] = 0; /* indicate scren mode */
                    234: } else {
                    235: v[0] = (char far *)o->bufbot;
                    236: v[1] = (char far *)o->buftop;
                    237: v[2] = (char far *)o->buftail;
                    238: v[3] = (char far *)o->bufhead;
                    239: }
                    240: 
                    241: return 0;
                    242: } /* sdioctl */
                    243: #else
                    244: sdioctl(session, cmd, v)
                    245: char *v;
                    246: {
                    247: struct SDCONTROL *o = sdcontrol[session];
                    248: char *cp;
                    249: int i, j;
                    250: extern char *sdscreenmem;
                    251: 
                    252: if(!o) return -1;
                    253: 
                    254: switch(cmd) {
                    255: case TIOCSDSIZE: /* get size of buffer */
                    256: if(!session && sdscreenmode)
                    257: putuwd(v, (80+1)*25 + 1);
                    258: else
                    259: putuwd(v, (&sd0cbufsz)[session]);
                    260: break;
                    261: 
                    262: case TIOCSDGETBUF: /* get text buffer */
                    263: if(!session && sdscreenmode) {
                    264: cp = sdscreenmem;
                    265: for(i=0; i<25; ++i) {
                    266: for(j=0; j<80; ++j) {
                    267: putubd(v++, *cp);
                    268: cp += 2;
                    269: }
                    270: putubd(v++, '\r');
                    271: }
                    272: } else {
                    273: cp = o->buftail;
                    274: while(cp != o->bufhead) {
                    275: putubd(v, *cp);
                    276: ++v;
                    277: if(++cp == o->buftop)
                    278: cp = o->bufbot;
                    279: } /* end copying buffer */
                    280: }
                    281: /* end of text indicator, sign bit never makes it into the text buffer */
                    282: putubd(v, -1);
                    283: break;
                    284: 
                    285: default:
                    286: return -1;
                    287: } /* end switch on command */
                    288: 
                    289: return 0;
                    290: } /* sdioctl */
                    291: #endif
                    292: 
                    293: /* interface function, executed every 0.01 or 0.055 seconds */
                    294: sdtime()
                    295: {
                    296: int session, c;
                    297: struct SDCONTROL *o;
                    298: short istate;
                    299: 
                    300: chkfifo();
                    301: 
                    302: for(session=0; session<5; ++session) {
                    303: o = sdcontrol[session];
                    304: if(!o || o->xparent) continue;
                    305: 
                    306: if(o->talkcmd) {
                    307: if(!keycmd_start(session)) continue;
                    308: istate = sphi();
                    309: c = o->talkcmd;
                    310: o->talkcmd = o->talkcmd2;
                    311: o->talkcmd2 = 0;
                    312: spl(istate);
                    313: keycmd( 128 | c);
                    314: keycmd_end();
                    315: } /* o->talkcmd set */
                    316: 
                    317: if(o->rdflag | o->onesymb) {
                    318: if(keycmd_start(session)) {
                    319: reading();
                    320: keycmd_end();
                    321: }
                    322: }
                    323: } /* end loop over 5 sessions */
                    324: } /* sdtime */
                    325: 
                    326: /* before a byte is written to the screen,
                    327:  * place it in the internal circular buffer.
                    328:  * runs with interrupts off. */
                    329: static bufstore(o, c)
                    330: struct SDCONTROL *o;
                    331: char c;
                    332: {
                    333: char *bufbot = o->bufbot, *buftop = o->buftop,
                    334: *bufhead = o->bufhead, *buftail = o->buftail,
                    335: *bufcur = o->bufcur;
                    336: char *t;
                    337: 
                    338: if(!o->ctrl_ok && c != 7 && c != '\r') {
                    339: /* control h removes the last byte in the buffer */
                    340: if(c == 8 && bufhead != buftail) {
                    341: if((t = bufhead) == bufbot) t = buftop;
                    342: if(*--t != '\r') {
                    343: /* ok to back up */
                    344: bufhead = t;
                    345: if(t == bufcur && t != buftail) {
                    346: if(t == bufbot) t = buftop;
                    347: bufcur = --t;
                    348: }
                    349: }
                    350: } /* backing up for control-h */
                    351: 
                    352: if(c < ' ') goto done;
                    353: } /* control charactercheck */
                    354: 
                    355: t = bufhead;
                    356: *t = c;
                    357: if(++t == buftop) t = bufbot;
                    358: bufhead = t;
                    359: if(t == buftail) { /* buffer full */
                    360: /* drop oldest character */
                    361: if(++t == buftop) t = bufbot;
                    362: if(buftail == bufcur) bufcur = t;
                    363: buftail = t;
                    364: } /* full buffer */
                    365: 
                    366: done: /* copy pointers */
                    367: o->bufcur = bufcur;
                    368: o->bufhead = bufhead;
                    369: o->buftail = buftail;
                    370: } /* bufstore */
                    371: 
                    372: /* interface routine, called from mmgo1() or ih_bsc() */
                    373: /* bits returned mean:
                    374:  * 0: display character on device
                    375:  * 1: display an escape before displaying the character
                    376:  * 2: need to take a 10ms real time break before processing this character.
                    377:  * 3: musical output, take a longer real time break. */
                    378: int sdoutchar(session, c)
                    379: char c;
                    380: {
                    381: struct SDCONTROL *o = sdcontrol[session];
                    382: short istate;
                    383: int rc = 0;
                    384: 
                    385: if(!o) return 1; /* not active */
                    386: 
                    387: c &= 0x7f;
                    388: 
                    389: if(!o->xparent) {
                    390: /* check for esc{x sequences */
                    391: if(o->esc_lc) {
                    392: o->esc_lc = 0;
                    393: c-='@';
                    394: if(c > 0 && c < N_CMDS)
                    395: multikey(session, 0, 0, c);
                    396: return 0;
                    397: }
                    398: 
                    399: if(o->esc) {
                    400: o->esc = 0;
                    401: if(c == '{') {
                    402: o->esc_lc = 1;
                    403: return 0;
                    404: } else rc = 2;
                    405: } else {
                    406: if(multikey(session, 0, c, 0))
                    407: return 0;
                    408: }
                    409: 
                    410: if(c == '\033') {
                    411: o->esc = 1;
                    412: if(!rc) return 0;
                    413: rc = 0;
                    414: }
                    415: } /* end transparent mode check */
                    416: 
                    417: if(o->buf_ok) {
                    418: /* Coherent could run bufstore() with interrupts on, but MSDOS cannot.
                    419:  * This is because a sdtime() reading function could take place
                    420:  * during a real time interrupt, while the head/tail buffer
                    421:  * pointers are being modified. */
                    422: #ifdef MSDOS
                    423: istate = sphi();
                    424: #endif
                    425: if(rc) bufstore(o, '\033');
                    426: bufstore(o, c);
                    427: #ifdef MSDOS
                    428: spl(istate);
                    429: #endif
                    430: }
                    431: 
                    432: if(o->xparent) return 1;
                    433: 
                    434: if(o->dev_ok) rc |= 1;
                    435: else rc = 0;
                    436: 
                    437: if(!session) {
                    438: /* make sound accompanying output byte */
                    439: if(sdnoises|sdtones)
                    440: rc |= sdcharsnd(c);
                    441: if(c == 7) rc &= 0xe;
                    442: }
                    443: 
                    444: return rc;
                    445: } /* sdoutchar */
                    446: 
                    447: /* entered character, via keyboard or terminal.
                    448:  * do not call this if the session is null, because
                    449:  * this routine is suppose to call the lower level keyboard input routine.
                    450:  * Note the difference between input and output.
                    451:  * In output, we return 1 and let the calling
                    452:  * routine display the character by calling its own device driver routines.
                    453:  * But on input, we might want to expand a macro, sending a string of
                    454:  * accumulated characters to the input queue.
                    455:  * So we set o->dev_in to the appropriate device driver input
                    456:  * routine, and invoke it as needed. */
                    457: sdinkey(session, key)
                    458: {
                    459: struct SDCONTROL *o = sdcontrol[session];
                    460: int rc;
                    461: int cmd, xcmd;
                    462: 
                    463: /* hardcoded transparent mode toggle, cannot be reassigned */
                    464: if(key == 0x8300) {
                    465: o->xparent ^= 1;
                    466: if(!session) sdsound(o->xparent+5);
                    467: return;
                    468: }
                    469: 
                    470: xcmd = cmd = transkey(key);
                    471: if(cmd) cmd = o->keymap[cmd];
                    472: 
                    473: if(rc = multikey(session, 1, key, cmd)) {
                    474: if(!session) sdsound(rc);
                    475: } else {
                    476: mexpand(session, key, xcmd);
                    477: }
                    478: } /* sdinkey */
                    479: 
                    480: #ifndef MSDOS
                    481: /* The prexisting system was written for Dos, with Dos key conventions in place.
                    482:  * In order to use the same software, I convert the Coherent representation
                    483:  * of key codes into Dos representation.  My appologies to you purists.
                    484:  * Thus function and alt keys become 0 followed by the scan code.
                    485:  * Coherent doesn't allow for shift-fkey or ctrl-fkey, but the Dos
                    486:  * driver lets you map speech to these keys.  Coherent must therefore pass the
                    487:  * shift state in, so that we can check for shift-F3 etc. */
                    488: sdinkey_coh(c, scan, shift)
                    489: {
                    490: int key;
                    491: static char numpad[] = "789x456x1230.";
                    492: char numlock;
                    493: 
                    494: key = c;
                    495: 
                    496: /* check for Coherent special code or alt key, indicated by the sign bit */
                    497: if(c&0x80) {
                    498: if(scan >= 59 && scan <= 68) { /* function key */
                    499: /* adjust scan codes for shift or control or alt.
                    500:  * Check with Coherent kb.c to make sure the bits in shift are correct. */
                    501: if(shift&8) scan += 0x2d;
                    502: else if(shift & 4) scan += 0x23;
                    503: else if(shift & 3) scan += 0x19;
                    504: } /* end fkey */
                    505: 
                    506: /* MSDOS has a strange code for alt-= */
                    507: if(scan == 13) scan = 0x83;
                    508: 
                    509: /* scan code now the same as Dos */
                    510: key = scan<<8;
                    511: 
                    512: /* turn numlock-keypad back to a number */
                    513: if(scan >= 71 && scan <= 83) { /* on the keypad */
                    514: /* exactly one of numlock and shift should be set */
                    515: numlock = shift | (shift>>1);
                    516: numlock ^= (shift >> 5);
                    517: numlock &= ~(shift>>6);
                    518: if(numlock&1) key = numpad[scan-71];
                    519: } /* end keypad */
                    520: } /* end special code */
                    521: 
                    522: /* call sdinkey if the session is active and not in transparent mode,
                    523:  * or if this key would release an active session from transparent mode */
                    524: if(sdcontrol[0] &&
                    525: (!sdcontrol[0]->xparent || key == 0x8300)) {
                    526: sdinkey(0, key);
                    527: return 1;
                    528: }
                    529: 
                    530: return 0; /* you handle it */
                    531: } /* sdinkey_coh */
                    532: #endif
                    533: 
                    534: /* is this key part of a multikey sequence?
                    535:  * Return nonzero iff this key is absorbed.
                    536:  * This nonzero value also indicates the sound (e.g. error tone) that should be produced.
                    537:  * A return value of 1 requires no sound. */
                    538: static multikey(session, input, key, cmd)
                    539: /* Are we processing input or output characters?
                    540:  * If the characters represent input, entered from the keyboard,
                    541:  * this routine is running at interrupt level.
                    542:  * Output comes from the device driver, at process level. */
                    543: int input;
                    544: /* The character entered at the keyboard (input = 1)
                    545:  * or produced by the running process (input = 0) and destined for the screen.
                    546:  * For evolutionary reasons, we follow the DOS convention for
                    547:  * representing special input characters.  Thus F1 = 0x3b00. */
                    548: int key;
                    549: /* Instead of an output character, we may send a command directly,
                    550:  * as when esc{A is translated into a speech command. */
                    551: char cmd;
                    552: {
                    553: struct SDCONTROL *o = sdcontrol[session];
                    554: struct MULTIKEY *a = input ? &o->indata : &o->outdata;
                    555: char lastcmd, c;
                    556: int i, rc;
                    557: struct SDCMD *cmdp;
                    558: 
                    559: rc = 0;
                    560: if(!o->xparent) {
                    561: if(a->nextchar | a->nextline) {
                    562: cmd = 0;
                    563: rc = 1;
                    564: lastcmd = a->lastcmd;
                    565: a->nextchar = 0;
                    566: a->support = key;
                    567: c = key;
                    568: if(!c && lastcmd != 20 && lastcmd != 21)
                    569: return 3;
                    570: 
                    571: if(a->nextline) {
                    572: if(c == '\33') { a->nextline = 0; return 2; }
                    573: /* input line becomes null-terminated string */
                    574: if(c == '\r' || c == '\n') c = 0;
                    575: i = a->textlen;
                    576: a->text[i] = c;
                    577: if(c) {
                    578: if(++i == LINELEN)
                    579: return 4;
                    580: a->textlen = i;
                    581: return 1;
                    582: } /* test for cr */
                    583: a->nextline = 0;
                    584: rc = 2;
                    585: } /* absorbing a line */
                    586: cmd = lastcmd; /* extra data gathered, ready for the command */
                    587: } /* end nextchar or nextline mode */
                    588: else if(cmd) {
                    589: /* comand supplied directly */
                    590: cmdp = &sdcmds[cmd];
                    591: rc = 1;
                    592: if(cmdp->nextkey | cmdp->nextline) {
                    593: a->nextchar = cmdp->nextkey;
                    594: if(a->nextline = cmdp->nextline) rc = 5;
                    595: a->lastcmd = cmd;
                    596: a->textlen = 0;
                    597: cmd = 0;
                    598: }
                    599: } /* a valid speech command */
                    600: 
                    601: if(cmd) {
                    602: if(input) {
                    603: /* speech command from the keyboard */
                    604: /* interrupt level, defer command */
                    605: if(o->talkcmd) {
                    606: if(o->talkcmd2) o->talkcmd = o->talkcmd2;
                    607: o->talkcmd2 = cmd;
                    608: }
                    609: else o->talkcmd = cmd;
                    610: #ifndef MSDOS
                    611: mmhasten();
                    612: #endif
                    613: } else {
                    614: /* speech commands are executed immediately when they come via output characters */
                    615: while(!keycmd_start(session))  ;
                    616: keycmd(cmd);
                    617: keycmd_end();
                    618: } /* end input/output test */
                    619: } /* cmd to run */
                    620: } /* xparent test */
                    621: 
                    622: return rc;
                    623: } /* multikey */
                    624: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.