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

📄 si.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		(void) si_modem(pp, SET, TIOCM_DTR|TIOCM_RTS);		break;	case TIOCCDTR:		(void) si_modem(pp, SET, 0);		break;	case TIOCMSET:		(void) si_modem(pp, SET, *(int *)data);		break;	case TIOCMBIS:		(void) si_modem(pp, BIS, *(int *)data);		break;	case TIOCMBIC:		(void) si_modem(pp, BIC, *(int *)data);		break;	case TIOCMGET:		*(int *)data = si_modem(pp, GET, 0);		break;	case TIOCMSDTRWAIT:		/* must be root since the wait applies to following logins */		error = suser(p->p_ucred, &p->p_acflag);		if (error != 0) {			goto outspl;		}		pp->sp_dtr_wait = *(int *)data * hz / 100;		break;	case TIOCMGDTRWAIT:		*(int *)data = pp->sp_dtr_wait * 100 / hz;		break;	default:		error = ENOTTY;	}	error = 0;outspl:	splx(oldspl);out:	DPRINT((pp, DBG_IOCTL|DBG_EXIT, "siioctl ret %d\n", error));	if (blocked)		si_write_enable(pp, 1);	return(error);}/* * Handle the Specialix ioctls. All MUST be called via the CONTROL device */static intsi_Sioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p){	struct si_softc *xsc;	register struct si_port *xpp;	volatile struct si_reg *regp;	struct si_tcsi *dp;	struct si_pstat *sps;	int *ip, error = 0;	int oldspl;	int card, port;	int mynor = minor(dev);	DPRINT((0, DBG_ENTRY|DBG_IOCTL, "si_Sioctl(%x,%x,%x,%x)\n",		dev, cmd, data, flag));#if 1	DPRINT((0, DBG_IOCTL, "TCSI_PORT=%x\n", TCSI_PORT));	DPRINT((0, DBG_IOCTL, "TCSI_CCB=%x\n", TCSI_CCB));	DPRINT((0, DBG_IOCTL, "TCSI_TTY=%x\n", TCSI_TTY));#endif	if (!IS_CONTROLDEV(mynor)) {		DPRINT((0, DBG_IOCTL|DBG_FAIL, "not called from control device!\n"));		return(ENODEV);	}	oldspl = spltty();	/* better safe than sorry */	ip = (int *)data;#define SUCHECK if (error = suser(p->p_ucred, &p->p_acflag)) goto out	switch (cmd) {	case TCSIPORTS:		*ip = si_Nports;		goto out;	case TCSIMODULES:		*ip = si_Nmodules;		goto out;	case TCSISDBG_ALL:		SUCHECK;		si_debug = *ip;		goto out;	case TCSIGDBG_ALL:		*ip = si_debug;		goto out;	default:		/*		 * Check that a controller for this port exists		 */		/* may also be a struct si_pstat, a superset of si_tcsi */		dp = (struct si_tcsi *)data;		sps = (struct si_pstat *)data;		card = dp->tc_card;		xsc = &si_softc[card];	/* check.. */		if (card < 0 || card >= NSI || xsc->sc_type == SIEMPTY) {			error = ENOENT;			goto out;		}		/*		 * And check that a port exists		 */		port = dp->tc_port;		if (port < 0 || port >= xsc->sc_nport) {			error = ENOENT;			goto out;		}		xpp = xsc->sc_ports + port;		regp = (struct si_reg *)xsc->sc_maddr;	}	switch (cmd) {	case TCSIDEBUG:#ifdef	SI_DEBUG		SUCHECK;		if (xpp->sp_debug)			xpp->sp_debug = 0;		else {			xpp->sp_debug = DBG_ALL;			DPRINT((xpp, DBG_IOCTL, "debug toggled %s\n",				(xpp->sp_debug&DBG_ALL)?"ON":"OFF"));		}		break;#else		error = ENODEV;		goto out;#endif	case TCSISDBG_LEVEL:	case TCSIGDBG_LEVEL:#ifdef	SI_DEBUG		if (cmd == TCSIGDBG_LEVEL) {			dp->tc_dbglvl = xpp->sp_debug;		} else {			SUCHECK;			xpp->sp_debug = dp->tc_dbglvl;		}		break;#else		error = ENODEV;		goto out;#endif	case TCSIGRXIT:		dp->tc_int = regp->rx_int_count;		break;	case TCSIRXIT:		SUCHECK;		regp->rx_int_count = dp->tc_int;		break;	case TCSIGIT:		dp->tc_int = regp->int_count;		break;	case TCSIIT:		SUCHECK;		regp->int_count = dp->tc_int;		break;	case TCSISTATE:		dp->tc_int = xpp->sp_ccb->hi_ip;		break;	/* these next three use a different structure */	case TCSI_PORT:		SUCHECK;		sps->tc_siport = *xpp;		break;	case TCSI_CCB:		SUCHECK;		sps->tc_ccb = *xpp->sp_ccb;		break;	case TCSI_TTY:		SUCHECK;		sps->tc_tty = *xpp->sp_tty;		break;	default:		error = EINVAL;		goto out;	}out:	splx(oldspl);	return(error);		/* success */}/* *	siparam()	: Configure line params *	called at spltty(); *	this may sleep, does not flush, nor wait for drain, nor block writes *	caller must arrange this if it's important.. */intsiparam(tp, t)	register struct tty *tp;	register struct termios *t;{	register struct si_port *pp = TP2PP(tp);	volatile struct si_channel *ccbp;	int oldspl, cflag, iflag, oflag, lflag;	int error = 0;		/* shutup gcc */	int ispeed = 0;		/* shutup gcc */	int ospeed = 0;		/* shutup gcc */	BYTE val;	DPRINT((pp, DBG_ENTRY|DBG_PARAM, "siparam(%x,%x)\n", tp, t));	cflag = t->c_cflag;	iflag = t->c_iflag;	oflag = t->c_oflag;	lflag = t->c_lflag;	DPRINT((pp, DBG_PARAM, "OFLAG 0x%x CFLAG 0x%x IFLAG 0x%x LFLAG 0x%x\n",		oflag, cflag, iflag, lflag));	/* if not hung up.. */	if (t->c_ospeed != 0) {		/* translate baud rate to firmware values */		ospeed = ttspeedtab(t->c_ospeed, bdrates);		ispeed = t->c_ispeed ?			 ttspeedtab(t->c_ispeed, bdrates) : ospeed;		/* enforce legit baud rate */		if (ospeed < 0 || ispeed < 0)			return (EINVAL);	}	oldspl = spltty();	ccbp = pp->sp_ccb;	/* ========== set hi_break ========== */	val = 0;	if (iflag & IGNBRK)		/* Breaks */		val |= BR_IGN;	if (iflag & BRKINT)		/* Interrupt on break? */		val |= BR_INT;	if (iflag & PARMRK)		/* Parity mark? */		val |= BR_PARMRK;	if (iflag & IGNPAR)		/* Ignore chars with parity errors? */		val |= BR_PARIGN;	ccbp->hi_break = val;	/* ========== set hi_csr ========== */	/* if not hung up.. */	if (t->c_ospeed != 0) {		/* Set I/O speeds */		 val = (ispeed << 4) | ospeed;	}	ccbp->hi_csr = val;	/* ========== set hi_mr2 ========== */	val = 0;	if (cflag & CSTOPB)				/* Stop bits */		val |= MR2_2_STOP;	else		val |= MR2_1_STOP;	/*	 * Enable H/W RTS/CTS handshaking. The default TA/MTA is	 * a DCE, hence the reverse sense of RTS and CTS	 */	/* Output Flow - RTS must be raised before data can be sent */	if (cflag & CCTS_OFLOW)		val |= MR2_RTSCONT;	ccbp->hi_mr2 = val;	/* ========== set hi_mr1 ========== */	val = 0;	if (!(cflag & PARENB))				/* Parity */		val |= MR1_NONE;	else		val |= MR1_WITH;	if (cflag & PARODD)		val |= MR1_ODD;	if ((cflag & CS8) == CS8) {			/* 8 data bits? */		val |= MR1_8_BITS;	} else if ((cflag & CS7) == CS7) {		/* 7 data bits? */		val |= MR1_7_BITS;	} else if ((cflag & CS6) == CS6) {		/* 6 data bits? */		val |= MR1_6_BITS;	} else {					/* Must be 5 */		val |= MR1_5_BITS;	}	/*	 * Enable H/W RTS/CTS handshaking. The default TA/MTA is	 * a DCE, hence the reverse sense of RTS and CTS	 */	/* Input Flow - CTS is raised when port is ready to receive data */	if (cflag & CRTS_IFLOW)		val |= MR1_CTSCONT;	ccbp->hi_mr1 = val;	/* ========== set hi_mask ========== */	val = 0xff;	if ((cflag & CS8) == CS8) {			/* 8 data bits? */		val &= 0xFF;	} else if ((cflag & CS7) == CS7) {		/* 7 data bits? */		val &= 0x7F;	} else if ((cflag & CS6) == CS6) {		/* 6 data bits? */		val &= 0x3F;	} else {					/* Must be 5 */		val &= 0x1F;	}	if (iflag & ISTRIP)		val &= 0x7F;	ccbp->hi_mask = val;	/* ========== set hi_prtcl ========== */	val = 0;				/* Monitor DCD etc. if a modem */	if (!(cflag & CLOCAL))		val |= SP_DCEN;	if (iflag & IXANY)		val |= SP_TANY;	if (iflag & IXON)		val |= SP_TXEN;	if (iflag & IXOFF)		val |= SP_RXEN;	if (iflag & INPCK)		val |= SP_PAEN;	ccbp->hi_prtcl = val;	/* ========== set hi_{rx|tx}{on|off} ========== */	/* XXX: the card TOTALLY shields us from the flow control... */	ccbp->hi_txon = t->c_cc[VSTART];	ccbp->hi_txoff = t->c_cc[VSTOP];	ccbp->hi_rxon = t->c_cc[VSTART];	ccbp->hi_rxoff = t->c_cc[VSTOP];	/* ========== send settings to the card ========== */	/* potential sleep here */	if (ccbp->hi_stat == IDLE_CLOSE)		/* Not yet open */		si_command(pp, LOPEN, SI_WAIT);		/* open it */	else		si_command(pp, CONFIG, SI_WAIT);	/* change params */	/* ========== set DTR etc ========== */	/* Hangup if ospeed == 0 */	if (t->c_ospeed == 0) {		(void) si_modem(pp, BIC, TIOCM_DTR|TIOCM_RTS);	} else {		/*		 * If the previous speed was 0, may need to re-enable	 	 * the modem signals	 	 */		(void) si_modem(pp, SET, TIOCM_DTR|TIOCM_RTS);	}	DPRINT((pp, DBG_PARAM, "siparam, complete: MR1 %x MR2 %x HI_MASK %x PRTCL %x HI_BREAK %x\n",		ccbp->hi_mr1, ccbp->hi_mr2, ccbp->hi_mask, ccbp->hi_prtcl, ccbp->hi_break));	splx(oldspl);	return(error);}/* * Enable or Disable the writes to this channel... * "state" ->  enabled = 1; disabled = 0; */static voidsi_write_enable(pp, state)	register struct si_port *pp;	int state;{	int oldspl;	oldspl = spltty();	if (state) {		pp->sp_state &= ~SS_BLOCKWRITE;		if (pp->sp_state & SS_WAITWRITE) {			pp->sp_state &= ~SS_WAITWRITE;			/* thunder away! */			wakeup((caddr_t)pp);		}	} else {		pp->sp_state |= SS_BLOCKWRITE;	}	splx(oldspl);}/* * Set/Get state of modem control lines. * Due to DCE-like behaviour of the adapter, some signals need translation: *	TIOCM_DTR	DSR *	TIOCM_RTS	CTS */static intsi_modem(pp, cmd, bits)	struct si_port *pp;	enum si_mctl cmd;	int bits;{	volatile struct si_channel *ccbp;	int x;	DPRINT((pp, DBG_ENTRY|DBG_MODEM, "si_modem(%x,%s,%x)\n", pp, si_mctl2str(cmd), bits));	ccbp = pp->sp_ccb;		/* Find channel address */	switch (cmd) {	case GET:		x = ccbp->hi_ip;		bits = TIOCM_LE;		if (x & IP_DCD)		bits |= TIOCM_CAR;		if (x & IP_DTR)		bits |= TIOCM_DTR;		if (x & IP_RTS)		bits |= TIOCM_RTS;		if (x & IP_RI)		bits |= TIOCM_RI;		return(bits);	case SET:		ccbp->hi_op &= ~(OP_DSR|OP_CTS);		/* fall through */	case BIS:		x = 0;		if (bits & TIOCM_DTR)			x |= OP_DSR;		if (bits & TIOCM_RTS)			x |= OP_CTS;		ccbp->hi_op |= x;		break;	case BIC:		if (bits & TIOCM_DTR)			ccbp->hi_op &= ~OP_DSR;		if (bits & TIOCM_RTS)			ccbp->hi_op &= ~OP_CTS;	}	return 0;}/* * Handle change of modem state */static voidsi_modem_state(pp, tp, hi_ip)	register struct si_port *pp;	register struct tty *tp;	register int hi_ip;{							/* if a modem dev */	if (hi_ip & IP_DCD) {		if ( !(pp->sp_last_hi_ip & IP_DCD)) {			DPRINT((pp, DBG_INTR, "modem carr on t_line %d\n",				tp->t_line));			(void)(*linesw[tp->t_line].l_modem)(tp, 1);		}	} else {		if (pp->sp_last_hi_ip & IP_DCD) {			DPRINT((pp, DBG_INTR, "modem carr off\n"));			if ((*linesw[tp->t_line].l_modem)(tp, 0))				(void) si_modem(pp, SET, 0);		}	}	pp->sp_last_hi_ip = hi_ip;}/* * Poller to catch missed interrupts. * * Note that the SYSV Specialix drivers poll at 100 times per second to get * better response.  We could really use a "periodic" version timeout(). :-) */#ifdef POLLstatic voidsi_poll(void *nothing){	register struct si_softc *sc;	register int i;	volatile struct si_reg *regp;	register struct si_port *pp;	int lost, oldspl, port;	DPRINT((0, DBG_POLL, "si_poll()\n"));	oldspl = spltty();	if (in_intr)		goto out;	lost = 0;	for (i=0; i<NSI; i++) {		sc = &si_softc[i];		if (sc->sc_type == SIEMPTY)			continue;		regp = (struct si_reg *)sc->sc_maddr;		/*		 * See if there has been a pending interrupt for 2 seconds		 * or so. The test <int_scounter >= 200) won't correspond		 * to 2 seconds if int_count gets changed.		 */		if (regp->int_pending != 0) {			if (regp->int_scounter >= 200 &&			    regp->initstat == 1) {				printf("si%d: lost intr\n", i);				lost++;			}		} else {			regp->int_scounter = 0;		}		/*		 * gripe about no input flow control..		 */		pp = sc->sc_ports;		for (port = 0; port < sc->sc_nport; pp++, port++) {			if (pp->sp_delta_overflows > 0) {				printf("si%d: %d tty level buffer overflows\n",					i, pp->sp_delta_overflows);				pp->sp_delta_overflows = 0;			}		}	}	if (lost)		siintr(-1);	/* call intr with fake vector */out:	splx(oldspl);	timeout(si_poll, (caddr_t)0L, POLL_INTERVAL);}#endif	/* ifdef POLL *//* * The interrupt handler polls ALL ports on ALL adapters each time * it is called. */static BYTE si_rxbuf[SI_BUFFERSIZE];	/* input staging area */voidsiintr(int unit){	register struct si_softc *sc;	register struct si_port *pp;	volatile struct si_channel *ccbp;	register struct tty *tp;	volatile caddr_t maddr;	BYTE op, ip;	int x, card, port, n, i, isopen;	volatile BYTE *z;	BYTE c;	DPRINT((0, (unit < 0) ? DBG_POLL:DBG_INTR, "siintr(%d)\n", unit));	if (in_intr) {		if (unit < 0)	/* should never happen */			return;		printf("si%d: Warning interrupt handler re-entered\n",			unit);		return;	}	in_intr = 1;	/*	 * When we get an int we poll all the channels and do ALL pending	 * work, not just the first one we find. This allows all cards to	 * share the same vector.	 */	for (card=0; card < NSI; card++) {		sc = &si_softc[card];		if (sc->sc_type == SIEMPTY)			continue;		/*		 * First, clear the interrupt		 */		switch(sc->sc_type) {		case SIHOST :			maddr = sc->sc_maddr;			((volatile struct si_reg *)maddr)->int_pending = 0;							/* flag nothing pending */			*(maddr+SIINTCL) = 0x00;	/* Set IRQ clear */			*(maddr+SIINTCL_CL) = 0x00;	/* Clear IRQ clear */			break;		case SIHOST2:

⌨️ 快捷键说明

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