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

📄 si.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
			maddr = sc->sc_maddr;			((volatile struct si_reg *)maddr)->int_pending = 0;			*(maddr+SIPLIRQCLR) = 0x00;			*(maddr+SIPLIRQCLR) = 0x10;			break;		case SIEISA:#if NEISA > 0			maddr = sc->sc_maddr;			((volatile struct si_reg *)maddr)->int_pending = 0;			(void)inb(sc->sc_eisa_iobase+3);			break;#endif	/* fall through if not EISA kernel */		case SIEMPTY:		default:			continue;		}		((volatile struct si_reg *)maddr)->int_scounter = 0;		/*		 * check each port		 */		for (pp=sc->sc_ports,port=0; port < sc->sc_nport; pp++,port++) {			ccbp = pp->sp_ccb;			tp = pp->sp_tty;			/*			 * See if a command has completed ?			 */			if (ccbp->hi_stat != pp->sp_pend) {				DPRINT((pp, DBG_INTR,					"siintr hi_stat = 0x%x, pend = %d\n",					ccbp->hi_stat, pp->sp_pend));				switch(pp->sp_pend) {				case LOPEN:				case MPEND:				case MOPEN:				case CONFIG:				case SBREAK:				case EBREAK:					pp->sp_pend = ccbp->hi_stat;						/* sleeping in si_command */					wakeup(&pp->sp_state);					break;				default:					pp->sp_pend = ccbp->hi_stat;				}	 		}			/*			 * Continue on if it's closed			 */			if (ccbp->hi_stat == IDLE_CLOSE) {				continue;			}			/*			 * Do modem state change if not a local device			 */			si_modem_state(pp, tp, ccbp->hi_ip);			/*			 * Check to see if there's we should 'receive'			 * characters.			 */			if (tp->t_state & TS_CONNECTED &&			    tp->t_state & TS_ISOPEN)				isopen = 1;			else				isopen = 0;			/*			 * Do input break processing			 */			if (ccbp->hi_state & ST_BREAK) {				if (isopen) {				    (*linesw[tp->t_line].l_rint)(TTY_BI, tp);				}				ccbp->hi_state &= ~ST_BREAK;   /* A Bit iffy this */				DPRINT((pp, DBG_INTR, "si_intr break\n"));			}			/*			 * Do RX stuff - if not open then dump any characters.			 * XXX: This is VERY messy and needs to be cleaned up.			 *			 * XXX: can we leave data in the host adapter buffer			 * when the clists are full?  That may be dangerous			 * if the user cannot get an interrupt signal through.			 */	more_rx:	/* XXX Sorry. the nesting was driving me bats! :-( */			if (!isopen) {				ccbp->hi_rxopos = ccbp->hi_rxipos;				goto end_rx;			}			/*			 * If the tty input buffers are blocked, stop emptying			 * the incoming buffers and let the auto flow control			 * assert..			 */			if (tp->t_state & TS_TBLOCK) {				goto end_rx;			}			/*			 * Process read characters if not skipped above			 */			op = ccbp->hi_rxopos;			ip = ccbp->hi_rxipos;			c = ip - op;			if (c == 0) {				goto end_rx;			}			n = c & 0xff;			if (n > 250)				n = 250;			DPRINT((pp, DBG_INTR, "n = %d, op = %d, ip = %d\n",						n, op, ip));			/*			 * Suck characters out of host card buffer into the			 * "input staging buffer" - so that we dont leave the			 * host card in limbo while we're possibly echoing			 * characters and possibly flushing input inside the			 * ldisc l_rint() routine.			 */			if (n <= SI_BUFFERSIZE - op) {				DPRINT((pp, DBG_INTR, "\tsingle copy\n"));				z = ccbp->hi_rxbuf + op;				bcopy((caddr_t)z, si_rxbuf, n);				op += n;			} else {				x = SI_BUFFERSIZE - op;				DPRINT((pp, DBG_INTR, "\tdouble part 1 %d\n", x));				z = ccbp->hi_rxbuf + op;				bcopy((caddr_t)z, si_rxbuf, x);				DPRINT((pp, DBG_INTR, "\tdouble part 2 %d\n", n-x));				z = ccbp->hi_rxbuf;				bcopy((caddr_t)z, si_rxbuf+x, n-x);				op += n;			}			/* clear collected characters from buffer */			ccbp->hi_rxopos = op;			DPRINT((pp, DBG_INTR, "n = %d, op = %d, ip = %d\n",						n, op, ip));			/*			 * at this point...			 * n = number of chars placed in si_rxbuf			 */			/*			 * Avoid the grotesquely inefficient lineswitch			 * routine (ttyinput) in "raw" mode. It usually			 * takes about 450 instructions (that's without			 * canonical processing or echo!). slinput is			 * reasonably fast (usually 40 instructions			 * plus call overhead).			 */			if (tp->t_state & TS_CAN_BYPASS_L_RINT) {				/* block if the driver supports it */				if (tp->t_rawq.c_cc + n >= SI_I_HIGH_WATER				    && (tp->t_cflag & CRTS_IFLOW					|| tp->t_iflag & IXOFF)				    && !(tp->t_state & TS_TBLOCK))					ttyblock(tp);				tk_nin += n;				tk_rawcc += n;				tp->t_rawcc += n;				pp->sp_delta_overflows +=				    b_to_q((char *)si_rxbuf, n, &tp->t_rawq);				ttwakeup(tp);				if (tp->t_state & TS_TTSTOP				    && (tp->t_iflag & IXANY					|| tp->t_cc[VSTART] == tp->t_cc[VSTOP])) {					tp->t_state &= ~TS_TTSTOP;					tp->t_lflag &= ~FLUSHO;					si_start(tp);				}			} else {				/*				 * It'd be nice to not have to go through the				 * function call overhead for each char here.				 * It'd be nice to block input it, saving a				 * loop here and the call/return overhead.				 */				for(x = 0; x < n; x++) {					i = si_rxbuf[x];					if ((*linesw[tp->t_line].l_rint)(i, tp)					     == -1) {						pp->sp_delta_overflows++;					}					/*					 * doesn't seem to be much point doing					 * this here.. this driver has no					 * softtty processing! ??					 */					if (pp->sp_hotchar && i == pp->sp_hotchar) {						setsofttty();					}				}			}			goto more_rx;	/* try for more until RXbuf is empty */	end_rx:		/* XXX: Again, sorry about the gotos.. :-) */			/*			 * Do TX stuff			 */			(*linesw[tp->t_line].l_start)(tp);		} /* end of for (all ports on this controller) */	} /* end of for (all controllers) */	in_intr = 0;	DPRINT((0, (unit < 0) ? DBG_POLL:DBG_INTR, "end siintr(%d)\n", unit));}/* * Nudge the transmitter... * * XXX: I inherited some funny code here.  It implies the host card only * interrupts when the transmit buffer reaches the low-water-mark, and does * not interrupt when it's actually hits empty.  In some cases, we have * processes waiting for complete drain, and we need to simulate an interrupt * about when we think the buffer is going to be empty (and retry if not). * I really am not certain about this...  I *need* the hardware manuals. */static voidsi_start(tp)	register struct tty *tp;{	struct si_port *pp;	volatile struct si_channel *ccbp;	register struct clist *qp;	register char *dptr;	BYTE ipos;	int nchar;	int oldspl, count, n, amount, buffer_full;	int do_exitproc;	oldspl = spltty();	qp = &tp->t_outq;	pp = TP2PP(tp);	DPRINT((pp, DBG_ENTRY|DBG_START,		"si_start(%x) t_state %x sp_state %x t_outq.c_cc %d\n",		tp, tp->t_state, pp->sp_state, qp->c_cc));	if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP))		goto out;	do_exitproc = 0;	buffer_full = 0;	ccbp = pp->sp_ccb;	/*	 * Handle the case where ttywait() is called on process exit	 * this may be BSDI specific, I dont know...	 */	if (tp->t_session != NULL && tp->t_session->s_leader != NULL &&	    (tp->t_session->s_leader->p_flag & P_WEXIT)) {		do_exitproc++;	}	count = (int)ccbp->hi_txipos - (int)ccbp->hi_txopos;	DPRINT((pp, DBG_START, "count %d\n", (BYTE)count));	dptr = (char *)ccbp->hi_txbuf;	/* data buffer */	while ((nchar = qp->c_cc) > 0) {		if ((BYTE)count >= 255) {			buffer_full++;			break;		}		amount = min(nchar, (255 - (BYTE)count));		ipos = (unsigned int)ccbp->hi_txipos;		/* will it fit in one lump? */		if ((SI_BUFFERSIZE - ipos) >= amount) {			n = q_to_b(&tp->t_outq,				(char *)&ccbp->hi_txbuf[ipos], amount);		} else {			n = q_to_b(&tp->t_outq,				(char *)&ccbp->hi_txbuf[ipos],				SI_BUFFERSIZE-ipos);			if (n == SI_BUFFERSIZE-ipos) {				n += q_to_b(&tp->t_outq,					(char *)&ccbp->hi_txbuf[0],					amount - (SI_BUFFERSIZE-ipos));			}		}		ccbp->hi_txipos += n;		count = (int)ccbp->hi_txipos - (int)ccbp->hi_txopos;	}	if (count != 0 && nchar == 0) {		tp->t_state |= TS_BUSY;	} else {		tp->t_state &= ~TS_BUSY;	}	/* wakeup time? */	ttwwakeup(tp);	DPRINT((pp, DBG_START, "count %d, nchar %d, tp->t_state 0x%x\n",		(BYTE)count, nchar, tp->t_state));	if ((tp->t_state & TS_BUSY) || do_exitproc)	{		int time;		if (do_exitproc != 0) {			time = hz / 10;		} else {			time = ttspeedtab(tp->t_ospeed, chartimes);			if (time > 0) {				if (time < nchar)					time = nchar / time;				else					time = 2;			} else {				DPRINT((pp, DBG_START,					"bad char time value! %d\n", time));				time = hz/10;			}		}		if ((pp->sp_state & (SS_LSTART|SS_INLSTART)) == SS_LSTART) {			untimeout((timeout_func_t)si_lstart, (caddr_t)pp);		} else {			pp->sp_state |= SS_LSTART;		}		DPRINT((pp, DBG_START, "arming lstart, time=%d\n", time));		timeout((timeout_func_t)si_lstart, (caddr_t)pp, time);	}out:	splx(oldspl);	DPRINT((pp, DBG_EXIT|DBG_START, "leave si_start()\n"));}/* * Note: called at splsoftclock from the timeout code * This has to deal with two things...  cause wakeups while waiting for * tty drains on last process exit, and call l_start at about the right * time for protocols like ppp. */static voidsi_lstart(pp)	register struct si_port *pp;{	register struct tty *tp;	int oldspl;	DPRINT((pp, DBG_ENTRY|DBG_LSTART, "si_lstart(%x) sp_state %x\n",		pp, pp->sp_state));	oldspl = spltty();	if ((pp->sp_state & SS_OPEN) == 0 || (pp->sp_state & SS_LSTART) == 0) {		splx(oldspl);		return;	}	pp->sp_state &= ~SS_LSTART;	pp->sp_state |= SS_INLSTART;	tp = pp->sp_tty;	/* deal with the process exit case */	ttwwakeup(tp);	/* nudge protocols - eg: ppp */	(*linesw[tp->t_line].l_start)(tp);	pp->sp_state &= ~SS_INLSTART;	splx(oldspl);}/* * Stop output on a line. called at spltty(); */voidsistop(tp, rw)	register struct tty *tp;	int rw;{	volatile struct si_channel *ccbp;	struct si_port *pp;	pp = TP2PP(tp);	ccbp = pp->sp_ccb;	DPRINT((TP2PP(tp), DBG_ENTRY|DBG_STOP, "sistop(%x,%x)\n", tp, rw));	/* XXX: must check (rw & FWRITE | FREAD) etc flushing... */	if (rw & FWRITE) {		/* what level are we meant to be flushing anyway? */		if (tp->t_state & TS_BUSY) {			si_command(TP2PP(tp), WFLUSH, SI_NOWAIT);			tp->t_state &= ~TS_BUSY;			ttwwakeup(tp);	/* Bruce???? */		}	}#if 1	/* XXX: this doesn't work right yet.. */	/* XXX: this may have been failing because we used to call l_rint()	 * while we were looping based on these two counters. Now, we collect	 * the data and then loop stuffing it into l_rint(), making this	 * useless.  Should we cause this to blow away the staging buffer?	 */	if (rw & FREAD) {		ccbp->hi_rxopos = ccbp->hi_rxipos;	}#endif}/* * Issue a command to the Z280 host card CPU. */static voidsi_command(pp, cmd, waitflag)	struct si_port *pp;		/* port control block (local) */	int cmd;	int waitflag;{	int oldspl;	volatile struct si_channel *ccbp = pp->sp_ccb;	int x;	DPRINT((pp, DBG_ENTRY|DBG_PARAM, "si_command(%x,%x,%d): hi_stat 0x%x\n",		pp, cmd, waitflag, ccbp->hi_stat));	oldspl = spltty();		/* Keep others out */	/* wait until it's finished what it was doing.. */	/* XXX: sits in IDLE_BREAK until something disturbs it or break	 * is turned off. */	while((x = ccbp->hi_stat) != IDLE_OPEN &&			x != IDLE_CLOSE &&			x != IDLE_BREAK &&			x != cmd) {		if (in_intr) {			/* Prevent sleep in intr */			DPRINT((pp, DBG_PARAM,				"cmd intr collision - completing %d\trequested %d\n",				x, cmd));			splx(oldspl);			return;		} else if (ttysleep(pp->sp_tty, (caddr_t)&pp->sp_state, TTIPRI|PCATCH,				"sicmd1", 1)) {			splx(oldspl);			return;		}	}	/* it should now be in IDLE_{OPEN|CLOSE|BREAK}, or "cmd" */	/* if there was a pending command, cause a state-change wakeup */	switch(pp->sp_pend) {	case LOPEN:	case MPEND:	case MOPEN:	case CONFIG:	case SBREAK:	case EBREAK:		wakeup(&pp->sp_state);		break;	default:		break;	}	pp->sp_pend = cmd;		/* New command pending */	ccbp->hi_stat = cmd;		/* Post it */	if (waitflag) {		if (in_intr) {		/* If in interrupt handler */			DPRINT((pp, DBG_PARAM,				"attempt to sleep in si_intr - cmd req %d\n",				cmd));			splx(oldspl);			return;		} else while(ccbp->hi_stat != IDLE_OPEN &&			     ccbp->hi_stat != IDLE_BREAK) {			if (ttysleep(pp->sp_tty, (caddr_t)&pp->sp_state, TTIPRI|PCATCH,			    "sicmd2", 0))				break;		}	}	splx(oldspl);}static voidsi_disc_optim(tp, t, pp)	struct tty	*tp;	struct termios	*t;	struct si_port	*pp;{	/*	 * XXX can skip a lot more cases if Smarts.  Maybe	 * (IGNCR | ISTRIP | IXON) in c_iflag.  But perhaps we	 * shouldn't skip if (TS_CNTTB | TS_LNCH) is set in t_state.	 */	if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))	    && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))	    && (!(t->c_iflag & PARMRK)		|| (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))	    && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))	    && linesw[tp->t_line].l_rint == ttyinput)		tp->t_state |= TS_CAN_BYPASS_L_RINT;	else		tp->t_state &= ~TS_CAN_BYPASS_L_RINT;	/*	 * Prepare to reduce input latency for packet	 * discplines with a end of packet character.	 */	if (tp->t_line == SLIPDISC)		pp->sp_hotchar = 0xc0;	else if (tp->t_line == PPPDISC)		pp->sp_hotchar = 0x7e;	else		pp->sp_hotchar = 0;	DPRINT((pp, DBG_OPTIM, "bypass: %s, hotchar: %x\n", 		(tp->t_state & TS_CAN_BYPASS_L_RINT) ? "on" : "off",		pp->sp_hotchar));}#ifdef	SI_DEBUGstatic voidsi_dprintf(pp, flags, str, a1, a2, a3, a4, a5, a6)	struct si_port *pp;	int flags;	char *str;	int a1, a2, a3, a4, a5, a6;{	if ((pp == NULL && (si_debug&flags)) ||	    (pp != NULL && ((pp->sp_debug&flags) || (si_debug&flags)))) {	    	if (pp != NULL)	    		printf("%ci%d(%d): ", 's',	    			(int)SI_CARD(pp->sp_tty->t_dev),	    			(int)SI_PORT(pp->sp_tty->t_dev));		printf(str, a1, a2, a3, a4, a5, a6);	}}static char *si_mctl2str(cmd)	enum si_mctl cmd;{	switch (cmd) {	case GET:	return("GET");	case SET:	return("SET");	case BIS:	return("BIS");	case BIC:	return("BIC");	}	return("BAD");}#endif

⌨️ 快捷键说明

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