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

📄 cx.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	unsigned short port = c->chip->port, len = 0, cnt_port, sts_port;	struct tty *tp = c->ttyp;	int i;	if (! tp)		return;	/* Choose the buffer. */	if (b == 'A') {		buf      = c->atbuf;		cnt_port = ATBCNT(port);		sts_port = ATBSTS(port);	} else {		buf      = c->btbuf;		cnt_port = BTBCNT(port);		sts_port = BTBSTS(port);	}	/* Is it busy? */	if (inb (sts_port) & BSTS_OWN24) {		tp->t_state |= TS_BUSY;		return;	}	switch (c->brk) {	case BRK_SEND:		*buf++ = 0;     /* extended transmit command */		*buf++ = 0x81;  /* send break */		*buf++ = 0;     /* extended transmit command */		*buf++ = 0x82;  /* insert delay */		*buf++ = 250;   /* 1/4 of second */		*buf++ = 0;     /* extended transmit command */		*buf++ = 0x82;  /* insert delay */		*buf++ = 250;   /* + 1/4 of second */		len = 8;		c->brk = BRK_IDLE;		break;	case BRK_STOP:		*buf++ = 0;     /* extended transmit command */		*buf++ = 0x83;  /* stop break */		len = 2;		c->brk = BRK_IDLE;		break;	case BRK_IDLE:		p = buf;		if (tp->t_iflag & IXOFF)			while (RB_LEN (tp->t_out) && p<buf+DMABUFSZ-1) {				sym = RB_GETC (tp->t_out);				/* Send XON/XOFF out of band. */				if (sym == tp->t_cc[VSTOP]) {					outb (STCR(port), STC_SNDSPC|STC_SSPC_2);					continue;				}				if (sym == tp->t_cc[VSTART]) {					outb (STCR(port), STC_SNDSPC|STC_SSPC_1);					continue;				}				/* Duplicate NULLs in ETC mode. */				if (! sym)					*p++ = 0;				*p++ = sym;			}		else			while (RB_LEN (tp->t_out) && p<buf+DMABUFSZ-1) {				sym = RB_GETC (tp->t_out);				/* Duplicate NULLs in ETC mode. */				if (! sym)					*p++ = 0;				*p++ = sym;			}		len = p - buf;		break;	}	/* Start transmitter. */	if (len) {		outw (cnt_port, len);		outb (sts_port, BSTS_INTR | BSTS_OWN24);		c->stat->obytes += len;		tp->t_state |= TS_BUSY;		print (("cx%d.%d: out %d bytes to %c\n",			c->board->num, c->num, len, b));	}}void cxoproc (struct tty *tp){	int unit = UNIT (tp->t_dev);	cx_chan_t *c = cxchan[unit];	unsigned short port = c->chip->port;	int s = spltty ();	/* Set current channel number */	outb (CAR(port), c->num & 3);	if (! (tp->t_state & (TS_TIMEOUT | TS_TTSTOP))) {		/* Start transmitter. */		if (! (inb (CSR(port)) & CSRA_TXEN))			cx_cmd (port, CCR_ENTX);		/* Determine the buffer order. */		if (inb (DMABSTS(port)) & DMABSTS_NTBUF) {			cxout (c, 'B');			cxout (c, 'A');		} else {			cxout (c, 'A');			cxout (c, 'B');		}	}#if defined (__FreeBSD__) && __FreeBSD__ < 2	if (tp->t_state & (TS_SO_OCOMPLETE | TS_SO_OLOWAT) || tp->t_wsel)		ttwwakeup (tp);#else /* FreeBSD 2.x and BSDI */#ifndef TS_ASLEEP /* FreeBSD some time after 2.0.5 */	ttwwakeup(tp);#else	if (RB_LEN (tp->t_out) <= tp->t_lowat) {		if (tp->t_state & TS_ASLEEP) {			tp->t_state &= ~TS_ASLEEP;			wakeup(TSA_OLOWAT(tp));		}		selwakeup(&tp->t_wsel);	}#endif#endif	splx (s);}int cxparam (struct tty *tp, struct termios *t){	int unit = UNIT (tp->t_dev);	cx_chan_t *c = cxchan[unit];	unsigned short port = c->chip->port;	int clock, period, s;	cx_cor1_async_t cor1;	if (t->c_ospeed == 0) {		/* Clear DTR and RTS. */		s = spltty ();		cx_chan_dtr (c, 0);		cx_chan_rts (c, 0);		splx (s);		print (("cx%d.%d: cxparam (hangup)\n", c->board->num, c->num));		return (0);	}	print (("cx%d.%d: cxparam\n", c->board->num, c->num));	/* Check requested parameters. */	if (t->c_ospeed < 300 || t->c_ospeed > 256*1024)                return(EINVAL);	if (t->c_ispeed && (t->c_ispeed < 300 || t->c_ispeed > 256*1024))                return(EINVAL);#ifdef __bsdi__	/* CLOCAL flag set -- wakeup everybody who waits for CD. */	/* FreeBSD does this themselves. */	if (! (tp->t_cflag & CLOCAL) && (t->c_cflag & CLOCAL))		wakeup ((caddr_t) &tp->t_rawq);#endif	/* And copy them to tty and channel structures. */	c->rxbaud = tp->t_ispeed = t->c_ispeed;	c->txbaud = tp->t_ospeed = t->c_ospeed;	tp->t_cflag = t->c_cflag;	/* Set character length and parity mode. */	BYTE cor1 = 0;	switch (t->c_cflag & CSIZE) {	default:	case CS8: cor1.charlen = 7; break;	case CS7: cor1.charlen = 6; break;	case CS6: cor1.charlen = 5; break;	case CS5: cor1.charlen = 4; break;	}	if (t->c_cflag & PARENB) {		cor1.parmode = PARM_NORMAL;		cor1.ignpar = 0;		cor1.parity = (t->c_cflag & PARODD) ? PAR_ODD : PAR_EVEN;	} else {		cor1.parmode = PARM_NOPAR;		cor1.ignpar = 1;	}	/* Enable/disable hardware CTS. */	c->aopt.cor2.ctsae = (t->c_cflag & CRTSCTS) ? 1 : 0;	/* Handle DSR as CTS. */	c->aopt.cor2.dsrae = (t->c_cflag & CRTSCTS) ? 1 : 0;	/* Enable extended transmit command mode.	 * Unfortunately, there is no other method for sending break. */	c->aopt.cor2.etc = 1;	/* Enable/disable hardware XON/XOFF. */	c->aopt.cor2.ixon = (t->c_iflag & IXON) ? 1 : 0;	c->aopt.cor2.ixany = (t->c_iflag & IXANY) ? 1 : 0;	/* Set the number of stop bits. */	if (t->c_cflag & CSTOPB)		c->aopt.cor3.stopb = STOPB_2;	else		c->aopt.cor3.stopb = STOPB_1;	/* Disable/enable passing XON/XOFF chars to the host. */	c->aopt.cor3.scde = (t->c_iflag & IXON) ? 1 : 0;	c->aopt.cor3.flowct = (t->c_iflag & IXON) ? FLOWCC_NOTPASS : FLOWCC_PASS;	c->aopt.schr1 = t->c_cc[VSTART];        /* XON */	c->aopt.schr2 = t->c_cc[VSTOP];         /* XOFF */	/* Set current channel number. */	s = spltty ();	outb (CAR(port), c->num & 3);	/* Set up receiver clock values. */	cx_clock (c->chip->oscfreq, c->rxbaud, &clock, &period);	c->opt.rcor.clk = clock;	outb (RCOR(port), BYTE c->opt.rcor);	outb (RBPR(port), period);	/* Set up transmitter clock values. */	cx_clock (c->chip->oscfreq, c->txbaud, &clock, &period);	c->opt.tcor.clk = clock;	c->opt.tcor.ext1x = 0;	outb (TCOR(port), BYTE c->opt.tcor);	outb (TBPR(port), period);	outb (COR2(port), BYTE c->aopt.cor2);	outb (COR3(port), BYTE c->aopt.cor3);	outb (SCHR1(port), c->aopt.schr1);	outb (SCHR2(port), c->aopt.schr2);	if (BYTE c->aopt.cor1 != BYTE cor1) {		BYTE c->aopt.cor1 = BYTE cor1;		outb (COR1(port), BYTE c->aopt.cor1);		/* Any change to COR1 require reinitialization. */		/* Unfortunately, it may cause transmitter glitches... */		cx_cmd (port, CCR_INITCH);	}	splx (s);	return (0);}struct tty *cxdevtotty (dev_t dev){	int unit = UNIT(dev);	if (unit == UNIT_CTL || unit >= NCX*NCHAN)		return (0);	return (cxchan[unit]->ttyp);}int cxselect (dev_t dev, int flag, struct proc *p){	int unit = UNIT (dev);	if (unit == UNIT_CTL || unit >= NCX*NCHAN)		return (0);#if defined (__FreeBSD__) && __FreeBSD__ < 2	return (ttselect (dev, flag, p));#else /* FreeBSD 2.x and BSDI */	return (ttyselect (cxchan[unit]->ttyp, flag, p));#endif}/* * Stop output on a line */void cxstop (struct tty *tp, int flag){	cx_chan_t *c = cxchan[UNIT(tp->t_dev)];	unsigned short port = c->chip->port;	int s = spltty ();	if (tp->t_state & TS_BUSY) {		print (("cx%d.%d: cxstop\n", c->board->num, c->num));		/* Set current channel number */		outb (CAR(port), c->num & 3);		/* Stop transmitter */		cx_cmd (port, CCR_DISTX);	}	splx (s);}/* * Handle receive interrupts, including receive errors and * receive timeout interrupt. */int cxrinta (cx_chan_t *c){	unsigned short port = c->chip->port;	unsigned short len = 0, risr = inw (RISR(port)), reoir = 0;	struct tty *tp = c->ttyp;	/* Compute optimal receiver buffer length. */	int rbsz = (c->rxbaud + 800 - 1) / 800 * 2;	if (rbsz < 4)		rbsz = 4;	else if (rbsz > DMABUFSZ)		rbsz = DMABUFSZ;	if (risr & RISA_TIMEOUT) {		unsigned long rcbadr = (unsigned short) inw (RCBADRL(port)) |			(long) inw (RCBADRU(port)) << 16;		unsigned char *buf = 0;		unsigned short cnt_port = 0, sts_port = 0;		if (rcbadr >= c->brphys && rcbadr < c->brphys+DMABUFSZ) {			buf = c->brbuf;			len = rcbadr - c->brphys;			cnt_port = BRBCNT(port);			sts_port = BRBSTS(port);		} else if (rcbadr >= c->arphys && rcbadr < c->arphys+DMABUFSZ) {			buf = c->arbuf;			len = rcbadr - c->arphys;			cnt_port = ARBCNT(port);			sts_port = ARBSTS(port);		} else			printf ("cx%d.%d: timeout: invalid buffer address\n",				c->board->num, c->num);		if (len) {			print (("cx%d.%d: async receive timeout (%d bytes), risr=%b, arbsts=%b, brbsts=%b\n",				c->board->num, c->num, len, risr, RISA_BITS,				inb (ARBSTS(port)), BSTS_BITS, inb (BRBSTS(port)), BSTS_BITS));			c->stat->ibytes += len;			if (tp && (tp->t_state & TS_ISOPEN)) {				int i;				void (*rint)() = (void(*)())					linesw[tp->t_line].l_rint;				for (i=0; i<len; ++i)					(*rint) (buf[i], tp);			}			/* Restart receiver. */			outw (cnt_port, rbsz);			outb (sts_port, BSTS_OWN24);		}		return (REOI_TERMBUFF);	}	print (("cx%d.%d: async receive interrupt, risr=%b, arbsts=%b, brbsts=%b\n",		c->board->num, c->num, risr, RISA_BITS,		inb (ARBSTS(port)), BSTS_BITS, inb (BRBSTS(port)), BSTS_BITS));	if (risr & RIS_BUSERR) {		printf ("cx%d.%d: receive bus error\n", c->board->num, c->num);		++c->stat->ierrs;	}	if (risr & (RIS_OVERRUN | RISA_PARERR | RISA_FRERR | RISA_BREAK)) {		int err = 0;		if (risr & RISA_PARERR)			err |= TTY_PE;		if (risr & RISA_FRERR)			err |= TTY_FE;#ifdef TTY_OE		if (risr & RIS_OVERRUN)			err |= TTY_OE;#endif#ifdef TTY_BI		if (risr & RISA_BREAK)			err |= TTY_BI;#endif		print (("cx%d.%d: receive error %x\n", c->board->num, c->num, err));		if (tp && (tp->t_state & TS_ISOPEN))			(*linesw[tp->t_line].l_rint) (err, tp);		++c->stat->ierrs;	}	/* Discard exception characters. */	if ((risr & RISA_SCMASK) && (tp->t_iflag & IXON))		reoir |= REOI_DISCEXC;	/* Handle received data. */	if ((risr & RIS_EOBUF) && tp && (tp->t_state & TS_ISOPEN)) {		void (*rint)() = (void(*)()) linesw[tp->t_line].l_rint;		unsigned char *buf;		int i;		len = (risr & RIS_BB) ? inw(BRBCNT(port)) : inw(ARBCNT(port));		print (("cx%d.%d: async: %d bytes received\n",			c->board->num, c->num, len));		c->stat->ibytes += len;		buf = (risr & RIS_BB) ? c->brbuf : c->arbuf;		for (i=0; i<len; ++i)			(*rint) (buf[i], tp);	}	/* Restart receiver. */	if (! (inb (ARBSTS(port)) & BSTS_OWN24)) {		outw (ARBCNT(port), rbsz);		outb (ARBSTS(port), BSTS_OWN24);	}	if (! (inb (BRBSTS(port)) & BSTS_OWN24)) {		outw (BRBCNT(port), rbsz);		outb (BRBSTS(port), BSTS_OWN24);	}	return (reoir);}/* * Handle transmit interrupt. */void cxtinta (cx_chan_t *c){	struct tty *tp = c->ttyp;	unsigned short port = c->chip->port;	unsigned char tisr = inb (TISR(port));	print (("cx%d.%d: async transmit interrupt, tisr=%b, atbsts=%b, btbsts=%b\n",		c->board->num, c->num, tisr, TIS_BITS,		inb (ATBSTS(port)), BSTS_BITS, inb (BTBSTS(port)), BSTS_BITS));	if (tisr & TIS_BUSERR) {		printf ("cx%d.%d: transmit bus error\n",			c->board->num, c->num);		++c->stat->oerrs;	} else if (tisr & TIS_UNDERRUN) {		printf ("cx%d.%d: transmit underrun error\n",			c->board->num, c->num);		++c->stat->oerrs;	}	if (tp) {		tp->t_state &= ~(TS_BUSY | TS_FLUSH);		if (tp->t_line)			(*linesw[tp->t_line].l_start) (tp);		else			cxoproc (tp);	}}/* * Handle modem interrupt. */void cxmint (cx_chan_t *c){	unsigned short port = c->chip->port;	unsigned char misr = inb (MISR(port));	unsigned char msvr = inb (MSVR(port));	struct tty *tp = c->ttyp;	if (c->mode != M_ASYNC) {		printf ("cx%d.%d: unexpected modem interrupt, misr=%b, msvr=%b\n",			c->board->num, c->num, misr, MIS_BITS, msvr, MSV_BITS);		return;	}	print (("cx%d.%d: modem interrupt, misr=%b, msvr=%b\n",		c->board->num, c->num, misr, MIS_BITS, msvr, MSV_BITS));	/* Ignore DSR events. */	/* Ignore RTC/CTS events, handled by hardware. */	/* Handle carrier detect/loss. */	if (tp && (misr & MIS_CCD))		(*linesw[tp->t_line].l_modem) (tp, (msvr & MSV_CD) != 0);}/* * Recover after lost transmit interrupts. */void cxtimeout (caddr_t a){	cx_board_t *b;	cx_chan_t *c;	struct tty *tp;	int s;	for (b=cxboard; b<cxboard+NCX; ++b)		for (c=b->chan; c<b->chan+NCHAN; ++c) {			tp = c->ttyp;			if (c->type==T_NONE || c->mode!=M_ASYNC || !tp)				continue;			s = spltty ();			if (tp->t_state & TS_BUSY) {				tp->t_state &= ~TS_BUSY;				if (tp->t_line)					(*linesw[tp->t_line].l_start) (tp);				else					cxoproc (tp);			}			splx (s);		}	timeout ((timeout_func_t) cxtimeout, 0, hz*5);}#endif /* NCX */

⌨️ 快捷键说明

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