Annotation of coherent/b/kernel/FWB2/synth.c, revision 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: /* synth.c: interface functions to the speech synthesizer */
        !            10: 
        !            11: #include "speech.h"
        !            12: 
        !            13: #ifdef MSDOS
        !            14: /* taken from Coherent ins8250.h */
        !            15: #define        DREG            0       /* Data Register               (DLAB=0) */
        !            16: #define        IER             1       /* Interrupt Enable Register   (DLAB=0) */
        !            17: #define        IIR             2       /* Interrupt Identification Register    */
        !            18: #define        FCR             2       /* FIFO Control Register                */
        !            19: #define        LCR             3       /* Line Control Register                */
        !            20: #define        MCR             4       /* Modem Control Register               */
        !            21: #define        LSR             5       /* Line Status Register                 */
        !            22: #define        MSR             6       /* Modem Status Register                */
        !            23: #define        SCR             7       /* Scratch Register                     */
        !            24: #else
        !            25: #include <sys/ins8250.h>
        !            26: #endif
        !            27: 
        !            28: #define LDLR 0 /* low divisor latch */
        !            29: #define HDLR 1 /* high divisor latch */
        !            30: 
        !            31: #ifdef MSDOS
        !            32: static int AL_ADDR[] = {0x3f8, 0x2f8, 0x3e8, 0x2e8};
        !            33: #else
        !            34: extern int AL_ADDR[];
        !            35: extern int C1BAUD, C2BAUD, C3BAUD, C4BAUD, albaud[];
        !            36: #endif
        !            37: 
        !            38: int sdoverride; /* override bad signals */
        !            39: 
        !            40: static int crticks, deadbuzz, inxmit;
        !            41: static char *xmit_ptr;
        !            42: static int i_comport; /* com port with the interrupt active */
        !            43: static short i_combase; /* AL_ADDR[i_comport-1]; */
        !            44: static struct SDCONTROL *i_sdc;
        !            45: 
        !            46: /* replace ? in error message with session number, then print */
        !            47: static fix_ques(s, n)
        !            48: char *s;
        !            49: {
        !            50: extern char *strchr();
        !            51: s = strchr(s,'?');
        !            52: if(s) *s = n+'0';
        !            53: printf(s);
        !            54: } /* fix_ques */
        !            55: 
        !            56: /* init the synthesizer */
        !            57: sdsynth_init(session)
        !            58: short session;
        !            59: {
        !            60: short istate;
        !            61: int synth, comport;
        !            62: int baud;
        !            63: static char emsg1[] = "ERROR: patchable variable sd?synth is out of range";
        !            64: static char emsg2[] = "ERROR: patchable variable sd?comport is out of range";
        !            65: static char emsg3[] = "ERROR: synthesizer must run on a serial port, please patch sd?comport\n";
        !            66: static char emsg4[] = "ERROR: synthesizer cannot run on a serial port, please patch sd?comport to 0\n";
        !            67: static char emsg5[] = "ERROR: only one speech session can be activated, and it must run from the console\n";
        !            68: static char emsg6[] = "ERROR: cannot allocate structure for speech session ?\n";
        !            69: static char emsg7[] = "ERROR: speech session cannot use com?, no UART present\n";
        !            70: /* for each synthesizer, is it external or internal? */
        !            71: static char inout[] = {0, 2};
        !            72: extern int sdintr();
        !            73: 
        !            74: synth = (&sd0synth)[session];
        !            75: comport = (&sd0comport)[session];
        !            76: 
        !            77: if(synth < 0 || synth > 1) {
        !            78: fix_ques(emsg1, session);
        !            79: return;
        !            80: }
        !            81: 
        !            82: if(!synth) return;
        !            83: 
        !            84: if(comport < 0 || comport > 4) {
        !            85: fix_ques(emsg2, session);
        !            86: return;
        !            87: }
        !            88: 
        !            89: if(comport && !(inout[synth]&2)) {
        !            90: fix_ques(emsg3, session);
        !            91: return;
        !            92: }
        !            93: 
        !            94: if(!comport && !(inout[synth]&1)) {
        !            95: fix_ques(emsg4, session);
        !            96: return;
        !            97: }
        !            98: 
        !            99: if(session || i_comport) {
        !           100: fix_ques(emsg5, session);
        !           101: return;
        !           102: }
        !           103: 
        !           104: sdcontrol[session] = i_sdc = (struct SDCONTROL *) kalloc(sizeof(struct SDCONTROL));
        !           105: if(!i_sdc) {; /* kalloc failed */
        !           106: fix_ques(emsg6, session);
        !           107: return;
        !           108: }
        !           109: memset(i_sdc, 0, sizeof(struct SDCONTROL));
        !           110: 
        !           111: if(comport) { /* unit is on a serial port */
        !           112: i_comport = comport;
        !           113: i_combase = AL_ADDR[comport-1];
        !           114: 
        !           115: /* set vector early, to handle any spurious interrupts */
        !           116: setivec((comport&1)+3, sdintr);
        !           117: 
        !           118: #ifndef MSDOS
        !           119: if(uart_sense(i_combase) == US_NONE) {
        !           120: fix_ques(emsg7, comport);
        !           121: fail:
        !           122: kfree(i_sdc);
        !           123: sdcontrol[session] = 0;
        !           124: clrivec((comport&1)+3);
        !           125: return;
        !           126: }
        !           127: printf(" monopolized by console speech session\n");
        !           128: #endif
        !           129: 
        !           130: istate = sphi();
        !           131: /* initialize the UART */
        !           132: /* no transmit interrupt until we start sending text */
        !           133: outb(i_combase+IER, 0);
        !           134: outb(i_combase+MCR, 0);
        !           135: inb(i_combase+DREG); /* clear any input */
        !           136: inb(i_combase+LSR);
        !           137: inb(i_combase+MSR);
        !           138: /* set baud rate to 9600 baud */
        !           139: baud = getbaudrate(comport);
        !           140: outb(i_combase+LCR, 0x80);
        !           141: outb(i_combase+LDLR, baud);
        !           142: outb(i_combase+HDLR, baud>>8);
        !           143: outb(i_combase+LCR, 3); /* 8 bits, no parity */
        !           144: 
        !           145: /* set DTR and RTS */
        !           146: /* extra bit (8[4]) is needed to generate interrupts */
        !           147: outb(i_combase+MCR, 15 - ((comport&1) << 2));
        !           148: spl(istate);
        !           149: 
        !           150: /* synthesizer specific initialization sequence here */
        !           151: return;
        !           152: } /* on a serial port */
        !           153: 
        !           154: /* this code not reached */
        !           155: return; /* only serial connections implemented */
        !           156: } /* sdsynth_init */
        !           157: 
        !           158: /* synthesizer appears to be dead */
        !           159: static synth_dead()
        !           160: {
        !           161: if(!deadbuzz) sdsound(7);
        !           162: deadbuzz = 1;
        !           163: i_sdc->rdflag = i_sdc->onesymb = 0;
        !           164: i_sdc->drain_lbolt = 0;
        !           165: } /* synth_dead */
        !           166: 
        !           167: /* serial port interrupt handler, runs with interrupts off */
        !           168: sdintr()
        !           169: {
        !           170: char linestat, c;
        !           171: short istate;
        !           172: 
        !           173: istate = sphi();
        !           174: inb(i_combase+IIR);
        !           175: linestat = inb(i_combase+LSR);
        !           176: if(linestat & 0x20) {
        !           177: 
        !           178: if(inxmit) {
        !           179: /* if no data to send then reset tx interrupt and return */
        !           180: if(!xmit_ptr) {
        !           181: outb(i_combase+IER, 0);
        !           182: inxmit = 0;
        !           183: } else {
        !           184: c = *xmit_ptr++;
        !           185: if(!c) c = '\r', xmit_ptr = 0;
        !           186: outb(i_combase+DREG, c);
        !           187: }
        !           188: }
        !           189: }
        !           190: 
        !           191: spl(istate);
        !           192: } /* sdintr */
        !           193: 
        !           194: /* return status of synthesizer,  ready for more or not.
        !           195:  * ideally, the unit is ready when it has spoken everything
        !           196:  * previously sent to it.  the Type & Talk has an
        !           197:  * annoying delay of about 10 seconds between ready indicated
        !           198:  * and all input spoken.  There is nothing I can do
        !           199:  * about this.  Other units, such as the echo,
        !           200:  * are out of the question, since their delay is measured
        !           201:  * in minutes.  Someday, a speech unit will indicate clearly when
        !           202:  * it has spoken all input. */
        !           203: sdready(session)
        !           204: /* only works for one session, i_sdc, ignore passed parameter */
        !           205: int session;
        !           206: {
        !           207: char mstat;
        !           208: 
        !           209: /* are we sending a string? */
        !           210: if(inxmit) return 0;
        !           211: 
        !           212: /* a real time delay, after sending return */
        !           213: if(crticks) { --crticks; return 0; }
        !           214: 
        !           215: if(!i_combase) return 1;
        !           216: 
        !           217: if(!sdoverride) {
        !           218: /* check to see if votrax is there and ready (DSR and CTS) */
        !           219: mstat = inb(i_combase+MSR);
        !           220: if(!(mstat & 0x20)) {
        !           221: synth_dead();
        !           222: return 1;
        !           223: }
        !           224: deadbuzz = 0;
        !           225: if(!(mstat & 0x10)) return 0;
        !           226: }
        !           227: 
        !           228: return 1; /* ready */
        !           229: } /* sdready */
        !           230: 
        !           231: /* send text string to the speech synthesizer.
        !           232:  * routine assumes the text is to be spoken immediately.
        !           233:  * once the text is spoken, cts will indicate ready for more. */
        !           234: sdtext(s)
        !           235: char *s;
        !           236: {
        !           237: deadbuzz = 0;
        !           238: /* is synthesizer dead? */
        !           239: if(!sdoverride && !(inb(i_combase+MSR) & 0x20)) {
        !           240: synth_dead();
        !           241: return;
        !           242: }
        !           243: 
        !           244: /* set delay, after text is transmitted, so votrax has time to disable cts */
        !           245: crticks = 1;
        !           246: xmit_ptr = s;
        !           247: inxmit = 1; /* in transmit state */
        !           248: /* enable transmit interrupt */
        !           249: outb(i_combase+IER, 2);
        !           250: } /* sdtext */
        !           251: 
        !           252: /* shut up and discard accumulated text.
        !           253:  * annoyingly, type & talk must be "ready" for text,
        !           254:  * before it will honor the shut up command (break on rs232).
        !           255:  * Be sure the unit is in the ready (cts high) state. */
        !           256: sdshutup()
        !           257: {
        !           258: char linectrl = inb(i_combase + LCR);
        !           259: outb(i_combase+LCR, linectrl|0x40);
        !           260: /* Occasionally an interrupt will come along while we are in break.
        !           261:  * This will cause the break to be a tad longer.
        !           262:  * The unbelievably picky Votrax unit may not recognize the break,
        !           263:  * and it may not shut up, or it may perceive
        !           264:  * a couple extra garbage characters.
        !           265:  * But long interrupts don't happen very often,
        !           266:  * and the short ones are potentially important,
        !           267:  * such as received characters on a serial port.
        !           268:  * So   we wait with interrupts enabled. */
        !           269: sdpause(2560);
        !           270: outb(i_combase+LCR, linectrl);
        !           271: } /* sdshutup */
        !           272: 
        !           273: /* given a port address, is it allocated to a speech unit? */
        !           274: sdport_taken(comport)
        !           275: {
        !           276: int i;
        !           277: 
        !           278: ++comport;
        !           279: 
        !           280: for(i=0; i<4; ++i)
        !           281: if((&sd0synth)[i] && comport == (&sd0comport)[i])
        !           282: return 1;
        !           283: 
        !           284: return 0;
        !           285: } /* sdport_taken */
        !           286: 
        !           287: static getbaudrate(comport)
        !           288: {
        !           289: int baud;
        !           290: #ifdef MSDOS
        !           291: baud = 12;
        !           292: #else
        !           293: switch(comport) {
        !           294: case 1: baud = albaud[C1BAUD]; break;
        !           295: case 2: baud = albaud[C2BAUD]; break;
        !           296: case 3: baud = albaud[C3BAUD]; break;
        !           297: case 4: baud = albaud[C4BAUD]; break;
        !           298: }
        !           299: #endif
        !           300: return baud;
        !           301: } /* getbaudrate */
        !           302: 

unix.superglobalmegacorp.com

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