📄 termio.c
字号:
/************************************************************* * File: lib/termio.c * Purpose: Part of C runtime library * Author: Phil Bunce (pjb@carmel.com) * Revision History: * 970304 Start of revision history * 970826 Created addDevice. Changed devinit to use addDevice. * 980616 Removed devinit. * 980618 Added ioctl call to get baudlist from driver. */#include <queue.h>#include <stdio.h>#include <termio.h>#include <mips.h>#include <errno.h>#include <terms.h>fFunc *clkinit_ptr;void *_clkinfo;DevEntry DevTable[DEV_MAX];File _file[OPEN_MAX] = { {0,1},{0,1},{0,1} };struct TermEntry { char *name; Func *func; };int tvi920(),vt100();int p2681();struct TermEntry TermTable[] = { {"tvi920",tvi920}, {"vt100",vt100}, {0}};int *curlst; /* list of files open in the current context */int re_ether;/************************************************************** _write(fd,buf,n) write n bytes from buf to fd*/_write(fd,buf,n)int fd,n;char *buf;{int i;DevEntry *p;char *t;if (fd == ETHERFD) return(0);p = &DevTable[_file[fd].dev];for (i=0;i<n;i++) { scandevs(); if (p->t.c_oflag&ONLCR && buf[i] == '\n') _chwrite(p,'\r'); if (p->t.c_lflag&ECHOE && buf[i] == p->t.c_cc[VERASE]) { for (t="\b \b";*t;t++) _chwrite(p,*t); } else _chwrite(p,buf[i]); }return(i);}/************************************************************** _chwrite(p,ch)* write one character*/_chwrite(p,ch)DevEntry *p;char ch;{while (p->txoff) reschedule("write txoff");while (!(*p->handler)(OP_TXRDY,p->sio,p->chan)) reschedule("write txrdy");(*p->handler)(OP_TX,p->sio,p->chan,ch);}/************************************************************** scandevs()* scan devices for input*/scandevs(){int i,c,n;DevEntry *p;for (i=0;DevTable[i].rxq && DevTable[i].pollin;i++) { p = &DevTable[i]; if ((*p->handler)(OP_RXRDY,p->sio,p->chan)) { c = (*p->handler)(OP_RX,p->sio,p->chan); if (p->t.c_iflag&ISTRIP) c &= 0x7f; n = Qinquiry(p->rxq,Q_SPACE); if (c == p->t.c_cc[VINTR] && p->intr) longjmp(p->intr,1); else if (p->t.c_iflag&IXON && p->t.c_iflag&IXANY && p->txoff) p->txoff = 0; else if (p->t.c_iflag&IXON && c == p->t.c_cc[V_STOP]) p->txoff = 1; else if (p->t.c_iflag&IXON && c == p->t.c_cc[V_START]) p->txoff = 0; else if (n > 0) { Qput(p->rxq,c); if (n < 10 && p->t.c_iflag&IXOFF && !p->rxoff) { p->rxoff = 1; _chwrite(p,CNTRL('S')); } } } }}#ifdef BSO_TASKING#pragma nooptim#endif/************************************************************** _ioctl(fd,op,argp) perform control operation on fd */_ioctl(fd,op,argp)int fd,op,*argp;{DevEntry *p;struct termio *t;int i;if (fd == ETHERFD) return(0);switch (op) { case TXRDY : p = &DevTable[_file[fd].dev]; if ((*p->handler)(OP_TXRDY,p->sio,p->chan,0)) return(1); break; case TCGETA : p = &DevTable[_file[fd].dev]; t = (struct termio *) argp; *t = p->t; break; case TCSETAF : /* after flush of input queue */ p = &DevTable[_file[fd].dev]; while (! Qempty(p->rxq)) Qget(p->rxq); case TCSETAW : /* after write */ /* no txq, so no delay needed */ p = &DevTable[_file[fd].dev]; if (p->t.c_cflag != ((struct termio *)argp)->c_cflag) { if ((*p->handler)(OP_BAUD,p->sio,p->chan, CBAUD&((struct termio *)argp)->c_cflag)) return(-1); } p->t = *((struct termio *) argp); break; case FIONREAD : p = &DevTable[_file[fd].dev]; scandevs(); *argp = Qinquiry(p->rxq,Q_USED); break; case SETINTR : p = &DevTable[_file[fd].dev]; p->intr = (jmp_buf *)argp; break; case GETINTR : p = &DevTable[_file[fd].dev]; *argp = (unsigned long)p->intr; break; case SETICEE : /* ICANON & ECHOE */ p = &DevTable[_file[fd].dev]; p->t.c_lflag = (ICANON|ECHOE); break; case SETSANE : p = &DevTable[_file[fd].dev]; p->t.c_iflag |= (ISTRIP|ICRNL|IXON); p->t.c_lflag = (ICANON|ECHO|ECHOE); /* required */ p->t.c_oflag = (ONLCR); p->t.c_cc[VINTR] = CNTRL('c'); p->t.c_cc[VEOL] = '\n'; p->t.c_cc[VEOL2] = CNTRL('c'); p->t.c_cc[VERASE] = CNTRL('h'); p->t.c_cc[V_STOP] = CNTRL('s'); p->t.c_cc[V_START] = CNTRL('q'); break; case SETNCNE : p = &DevTable[_file[fd].dev]; if (argp != 0) { t = (struct termio *) argp; *t = p->t; } p->t.c_lflag &= ~(ICANON|ECHO|ECHOE); p->t.c_cc[4] = 1; break; case CBREAK : p = &DevTable[_file[fd].dev]; if (argp != 0) { t = (struct termio *) argp; *t = p->t; } p->t.c_lflag &= ~(ICANON|ECHO); p->t.c_cc[4] = 1; break; case GETTERM : p = &DevTable[_file[fd].dev]; *argp = 0; if (p->tfunc == 0) return(-1); strcpy((char *)argp,p->tname); break; case SETTERM : p = &DevTable[_file[fd].dev]; for (i=0;TermTable[i].name;i++) { if (strequ(argp,TermTable[i].name)) break; } if (TermTable[i].name == 0) return(-1); p->tname = TermTable[i].name; p->tfunc = TermTable[i].func; break; case TERMTYPE : if (TermTable[fd].name == 0) return(-1); strcpy((char *)argp,TermTable[fd].name); return(fd+1); case DEVENTRY : p = &DevTable[_file[fd].dev]; *argp = (int)p; break; case BAUDRATES : p = &DevTable[_file[fd].dev]; *argp = (*p->handler)(OP_BAUDRATES,p->sio,p->chan,0); break; default: return(-1); }return(0);}#ifdef BSO_TASKING#pragma optim#endif/************************************************************** reschedule(p)* gets called when there's nothing better to do*/reschedule(p)char *p;{ scandevs();}/************************************************************** ttctl(fd,op,a1,a2) perform terminal specific operation */ttctl(fd,op,a1,a2)int fd,op,a1,a2;{DevEntry *p;int r;p = &DevTable[_file[fd].dev];if (p->tfunc == 0) return(-1);r = (*p->tfunc)(fd,op,a1,a2);return(r);}/************************************************************** _open(fname,mode,perms) * return fd for fname. mode and perms are ignored.*/_open(fname,mode,perms)char *fname;int mode,perms;{int i,c,dev,len;char tmp[80];#ifdef ETHERNETif (strequ(fname,"ethernet")) return ether_open(getMonEnv("etheraddr"));#endiffor (i=0;i<OPEN_MAX && _file[i].valid;i++) ;if (i == OPEN_MAX) { errno = EMFILE; return(-1); }len = strlen(fname);if (len == 9) fname += 5; /* step past "/dev/" */else if (len != 4) { /* name too short */ errno = ENOENT; return(-1); }strncpy(tmp,fname,3);if (!strequ(tmp,"tty")) { /* must be ttyX */ errno = ENOENT; return(-1); }c = fname[3]; /* accept tty[a-z] tty[A-Z] tty[0-9] */if (c >= 'a' && c <= 'z') dev = c - 'a';if (c >= 'A' && c <= 'Z') dev = c - 'A';if (c >= '0' && c <= '9') dev = c - '0';if (dev > DEV_MAX) { /* device number too large */ errno = ENOENT; return(-1); }if (DevTable[dev].rxq == 0) { /* device not initialized */ errno = ENOENT; return(-1); }_file[i].valid = 1;_file[i].dev = dev;ioctl(i,SETSANE);if (curlst) *curlst |= (1<<i);return(i);}/************************************************************** _close(fd) close fd */_close(fd)int fd;{#ifdef ETHERNETif (fd == ETHERFD) { ether_close(); return; }#endif_file[fd].valid = 0;if (curlst) *curlst &= ~(1<<fd);}/************************************************************** _read(fd,buf,n) read n bytes into buf from fd */_read(fd,buf,n)int fd,n;char *buf;{int i,used;DevEntry *p;char ch;#ifdef ETHERNETif (fd == ETHERFD) return ether_read(fd,buf,n);#endifp = &DevTable[_file[fd].dev];for (i=0;i<n;) { scandevs(); while ((used=Qinquiry(p->rxq,Q_USED)) == 0) reschedule("read Qempty"); if (used < 10 && p->rxoff) { p->rxoff = 0; _chwrite(p,CNTRL('Q')); } ch = Qget(p->rxq); if (p->t.c_iflag&ICRNL && ch == '\r') ch = '\n'; if (p->t.c_lflag&ICANON) { if (p->t.c_cc[VERASE] != 0xff && ch == p->t.c_cc[VERASE]) { if (i > 0) { i--; if (p->t.c_lflag&ECHO) write(fd,&ch,1); } } else { if (p->t.c_lflag&ECHO) write(fd,&ch,1); buf[i++] = ch; } if (ch == p->t.c_cc[VEOL]) break; if (ch == p->t.c_cc[VEOL2]) break; } else { if (p->t.c_lflag&ECHO) write(fd,&ch,1); buf[i++] = ch; break; } }return(i);}/************************************************************** Func *_clkinit()*/Func *_clkinit(){if (!clkinit_ptr) return(0);return (* clkinit_ptr)();}/************************************************************** addDevice(devinfo,chan,handler,rxqsize,brate)*/addDevice(devinfo,chan,handler,rxqsize,brate)Addr devinfo; /* addr of struct containing device address etc */int chan; /* channel#. Used for DUARTS */Func *handler; /* addr of driver */int rxqsize; /* size of receive buffer */int brate; /* default baudrate */{int i,r;DevEntry *p;/* find first available device */for (i=0;DevTable[i].rxq && i < DEV_MAX;i++) ;if (i >= DEV_MAX) return;p = &DevTable[i];p->txoff = 0;p->rxoff = 0;if (chan == 0) (*handler)(OP_INIT,devinfo,brate);p->qsize = rxqsize;p->rxq = Qcreate(p->qsize);if (p->rxq == 0) return(-1);r = (*handler)(OP_BAUD,devinfo,chan,brate);p->sio = devinfo;p->chan = chan;p->handler = handler;p->intr = 0;p->pollin = 1;p->tfunc = 0;p->t.c_iflag = (ISTRIP|ICRNL|IXON);p->t.c_oflag = (ONLCR);p->t.c_lflag = (ICANON|ECHO|ECHOE);p->t.c_cflag = brate;p->t.c_cc[VINTR] = CNTRL('c');p->t.c_cc[VEOL] = '\n';p->t.c_cc[VEOL2] = CNTRL('c');p->t.c_cc[VERASE] = CNTRL('h');p->t.c_cc[V_STOP] = CNTRL('s');p->t.c_cc[V_START] = CNTRL('q');if (r==0) _chwrite(p,CNTRL('Q'));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -