⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 termio.c

📁 MIPS处理器的bootloader,龙芯就是用的修改过的PMON2
💻 C
字号:
/* $Id: termio.c,v 1.5 2002/03/01 22:15:46 patrik Exp $ */#include <sys/types.h>#include <stdlib.h>#include <queue.h>#include <stdio.h>#include <stdarg.h>#include <string.h>#include <termio.h>#include <unistd.h>#include <setjmp.h>#include <sys/ioctl.h>#include <pmon/netio/netio.h>#include <pmon.h>int _read __P((int, char *, int));int _write __P((int, char *, int));int  _open __P((char *, int, int));int _close __P((int));static void _chwrite __P((DevEntry *, char));extern void    gsignal __P((struct jmp_buf *, int sig));extern ConfigEntry ConfigTable[];DevEntry        DevTable[DEV_MAX];File            _file[OPEN_MAX] ={#ifdef NETIO    {0, 1, -1},    {0, 1, -1},    {0, 1, -1}#else    {0, 1},    {0, 1},    {0, 1}#endif};typedef int tFunc __P((int, int, int, int));struct TermEntry {    char           *name;    tFunc          *func;};struct TermEntry TermTable[] ={#if 0    {"tvi920", tvi920},#endif    {"vt100", vt100},    {0}};int            *curlst;		/* list of files open in the current context */static voidsetsane(DevEntry *p){	p->t.c_iflag |= (ISTRIP | ICRNL | IXON);	p->t.c_oflag = (ONLCR);	p->t.c_lflag = (ICANON | ISIG | ECHO | ECHOE);	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');}voidreschedule (p)     char           *p;{    scandevs ();}#define reschedule(p)    scandevs()/** _write(fd,buf,n) write n bytes from buf to fd */int_write (fd, buf, n)     int             fd, n;     char           *buf;{    int             i;    DevEntry       *p;    if (!_file[fd].valid)        return (-1);#ifdef NETIO    if (_file[fd].netfd >= 0)      return netwrite (_file[fd].netfd, buf, n);#endif    p = &DevTable[_file[fd].dev];    for (i = 0; i < n; i++) {	if (p->t.c_oflag & ONLCR && buf[i] == '\n') {	    _chwrite (p, '\r');	}	_chwrite (p, buf[i]);	scandevs ();    }    return (i);}static void_chwrite (p, ch)     DevEntry       *p;     char            ch;{    while (p->txoff)	reschedule ("write txoff");    if (p->handler) {	while (!(*p->handler) (OP_TXRDY, p->sio, p->chan, NULL))	  reschedule ("write txrdy");	(*p->handler) (OP_TX, p->sio, p->chan, ch);#if 0    } else {	/* early error? use main console (and hope someone has programmed it!) */	ConfigEntry *q = &ConfigTable[0];	while (!(*q->handler) (OP_TXRDY, q->devinfo, q->chan))	  continue;	(*q->handler) (OP_TX, q->devinfo, q->chan, ch);#endif    }}voidscandevs (){    int             c, n;    DevEntry       *p;    for (p = DevTable; p->rxq; p++) {	while ((*p->handler) (OP_RXRDY, p->sio, p->chan, NULL)) {	    c = (*p->handler) (OP_RX, p->sio, p->chan, NULL);	    if (p->t.c_iflag & ISTRIP)		c &= 0x7f;	    if (p->t.c_lflag & ISIG) {		if (c == p->t.c_cc[VINTR]) {		    gsignal (p->intr/*XXX*/, 2 /*SIGINT*/);		    continue;		}	    }	    if (p->t.c_iflag & IXON) {		if (p->t.c_iflag & IXANY && p->txoff) {		    p->txoff = 0;		    continue;		}		if (c == p->t.c_cc[V_STOP]) {		    p->txoff = 1;		    continue;		}		if (c == p->t.c_cc[V_START]) {		    p->txoff = 0;		    continue;		}	    }	    n = Qspace (p->rxq);	    if (n > 0) {		Qput (p->rxq, c);		if (n < 20 && !p->rxoff) {		    (*p->handler) (OP_RXSTOP, p->sio, p->chan, p->rxoff = 1);		    if (p->t.c_iflag & IXOFF)			_chwrite (p, CNTRL ('S'));		}	    }	}    }    tgt_poll ();#ifdef NETIO    tgt_netpoll ();#endif}/** ioctl(fd,op,argp) perform control operation on fd */intioctl (int fd, unsigned long op, ...){    DevEntry *p;    struct termio *at;    int i;    void *argp;    va_list ap;    va_start(ap, op);    argp = va_arg(ap, void *);    va_end(ap);    if (!_file[fd].valid)        return (-1);#ifdef NETIO    if (_file[fd].netfd >= 0)      return netioctl (_file[fd].netfd, op, argp);#endif    if (_file[fd].dev < 0)	return (-1);    p = &DevTable[_file[fd].dev];    switch (op) {    case TCGETA:	*(struct termio *)argp = p->t;	break;    case TCSETAF:		/* after flush of input queue */	while (!Qempty (p->rxq))	    Qget (p->rxq);	(*p->handler) (OP_FLUSH, p->sio, p->chan, 1);	if (p->rxoff) {	    (*p->handler) (OP_RXSTOP, p->sio, p->chan, p->rxoff = 0);	    if (p->t.c_iflag & IXOFF)		_chwrite (p, CNTRL ('Q'));	}    case TCSETAW:		/* after write */	/* no txq, so no delay needed */	at = (struct termio *)argp;	if (p->t.c_ispeed != at->c_ispeed) {	/* XXX FIX Split speed */		if ((*p->handler) (OP_BAUD, p->sio, p->freq, at->c_ispeed))		    return (-1);	}	p->t = *at;	break;    case FIONREAD:	scandevs ();	*(int *)argp = Qused (p->rxq);	break;    case SETINTR:	p->intr = (struct jmp_buf *) argp;	break;    case GETINTR:	*(struct jmp_buf **) argp = p->intr;	break;    case SETSANE:	(*p->handler) (OP_RESET, p->sio, p->chan, 0);	setsane(p);	break;    case SETNCNE:	if (argp)	  *(struct termio *)argp = p->t;	p->t.c_lflag &= ~(ICANON | ECHO | ECHOE);	p->t.c_cc[4] = 1;	break;    case CBREAK:	if (argp)	  *(struct termio *)argp = p->t;	p->t.c_lflag &= ~(ICANON | ECHO);	p->t.c_cc[4] = 1;	break;    case GETTERM:	*(int *)argp = 0;	if (p->tfunc == 0)	    return (-1);	strcpy ((char *)argp, p->tname);	break;    case SETTERM:	for (i = 0; TermTable[i].name; i++) {	    if (!strcmp(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);    default:	return (-1);    }    return (0);}intdevinit (){    int             i, brate;    ConfigEntry    *q;    DevEntry       *p;    char	   dname[5];    char	   *s;    strcpy (dname, "ttyx");    for (i = 0; ConfigTable[i].devinfo && i < DEV_MAX; i++) {	q = &ConfigTable[i];	p = &DevTable[i];	p->txoff = 0;	p->rxoff = 0;	if (q->chan == 0)	    (*q->handler) (OP_INIT, q->devinfo, 0, q->rxqsize);	p->qsize = q->rxqsize;	p->rxq = Qcreate (p->qsize);	if (p->rxq == 0)	    return (-1);	dname[3] = (i < 10) ? i + '0' : i - 10 + 'a';	if (!(s = getenv (dname)) || (brate = getbaudrate (s)) == 0)	    brate = q->brate;	/* set default baudrate in case anything goes wrong */	(void) (*q->handler) (OP_BAUD, q->devinfo, q->freq, q->brate);	/*	 * program requested baud rate, but fall back to default	 * if there is a problem	 */	if (brate != q->brate) {	    if ((*q->handler) (OP_BAUD, q->devinfo, q->freq, brate))		brate = q->brate;	}	p->sio = q->devinfo;	p->chan = q->chan;	p->handler = q->handler;	p->intr = 0;	p->tfunc = 0;	p->t.c_cflag = 0;	p->t.c_ispeed = brate;	p->t.c_ospeed = brate;	setsane(p);	_chwrite (p, CNTRL ('Q'));    }    return (0);}#if 0/** ttctl(fd,op,a1,a2) perform terminal specific operation */static intttctl (fd, op, a1, a2)     int             fd, op, a1, a2;{    DevEntry       *p;    int             r;    if (!_file[fd].valid || _file[fd].dev < 0)        return (-1);    p = &DevTable[_file[fd].dev];    if (p->tfunc == 0)	return (-1);    r = (*p->tfunc) (fd, op, a1, a2);    return (r);}#endif/** _open(fname,mode,perms) return fd for fname */int_open (fname, mode, perms)     char           *fname;     int             mode, perms;{    int             i, c, dev;    char            *dname;    for (i = 0; i < OPEN_MAX && _file[i].valid; i++);    if (i == OPEN_MAX)	return (-1);    dname = fname;    if (strncmp (dname, "/dev/", 5) == 0)      dname += 5;    if (strlen (dname) == 4 && strncmp (dname, "tty", 3) == 0) {	c = dname[3];	if (c >= 'a' && c <= 'z')	  dev = c - 'a';	else if (c >= 'A' && c <= 'Z')	  dev = c - 'A';	else if (c >= '0' && c <= '9')	  dev = c - '0';	if (dev >= DEV_MAX || DevTable[dev].rxq == 0)	  return (-1);	_file[i].dev = dev;#ifdef NETIO	_file[i].netfd = -1;#endif	_file[i].valid = 1;	{	    DevEntry *p = &DevTable[dev];	    (*p->handler) (OP_OPEN, p->sio, p->chan, 0);	}	ioctl (i, SETSANE);    } else {#ifdef NETIO	if ((_file[i].netfd = netopen (fname, mode)) < 0)	  return (-1);	_file[i].dev = -1;	_file[i].valid = 1;#else	return (-1);#endif    }    if (curlst)	*curlst |= (1 << i);    return (i);}/** _close(fd) close fd */int_close (fd)     int             fd;{    if (_file[fd].valid) {#ifdef NETIO	if (_file[fd].netfd >= 0) {	    netclose (_file[fd].netfd);	    _file[fd].netfd = -1;	}	else#endif	{	    DevEntry *p = &DevTable[_file[fd].dev];	    (*p->handler) (OP_CLOSE, p->sio, p->chan, 0);	}	_file[fd].valid = 0;	if (curlst)	  *curlst &= ~(1 << fd);    }    return(0);}/** _read(fd,buf,n) read n bytes into buf from fd */int_read (fd, buf, n)     int             fd, n;     char           *buf;{    int             i, used;    DevEntry       *p;    char            ch;    if (!_file[fd].valid)        return (-1);#ifdef NETIO    if (_file[fd].netfd >= 0)      return netread (_file[fd].netfd, buf, n);#endif    p = &DevTable[_file[fd].dev];    for (i = 0; i < n;) {	scandevs ();	while ((used = Qused (p->rxq)) == 0)	    reschedule ("read Qempty");	if (used < 20 && p->rxoff) {	    (*p->handler) (OP_RXSTOP, p->sio, p->chan, p->rxoff = 0);	    if (p->t.c_iflag & IXOFF)		_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 (ch == p->t.c_cc[VERASE]) {		if (i > 0) {		    i--;		    if (p->t.c_lflag & ECHOE)		      write (fd, "\b \b", 3);		    else if (p->t.c_lflag & ECHO)		      write (fd, "\b", 1);		}		continue;	    }	    if (p->t.c_lflag & ECHO)	      write (fd, &ch, 1);	    buf[i++] = ch;	    if (ch == p->t.c_cc[VEOL] || ch == p->t.c_cc[VEOL2])	      break;	} else {	    buf[i++] = ch;	}    }    return (i);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -