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

📄 si.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	}	sc->sc_ports = (struct si_port *)malloc(sizeof(struct si_port) * nport,		M_DEVBUF, M_NOWAIT);	if (sc->sc_ports == 0) {mem_fail:		printf("si%d: fail to malloc memory for port structs\n",			unit);		return 0;	}	bzero(sc->sc_ports, sizeof(struct si_port) * nport);	sc->sc_nport = nport;	/*	 * allocate tty structures for ports	 */	tp = (struct tty *)malloc(sizeof(*tp) * nport, M_DEVBUF, M_NOWAIT);	if (tp == 0)		goto mem_fail;	bzero(tp, sizeof(*tp) * nport);	si_tty = tp;	/* mark the device state as attached */	si_kdc[unit].kdc_state = DC_BUSY;	/*	 * Scan round the ports again, this time initialising.	 */	pp = sc->sc_ports;	nmodule = 0;	modp = (struct si_module *)(maddr + 0x80);	uart_type = 0;	for (;;) {		switch (modp->sm_type & (~MMASK)) {		case M232:		case M422:			nmodule++;			nport = (modp->sm_type & MMASK);			ccbp = (struct si_channel *)((char *)modp+0x100);			if (uart_type == 0)				uart_type = ccbp->type;			for (x = 0; x < nport; x++, pp++, ccbp++) {				pp->sp_ccb = ccbp;	/* save the address */				pp->sp_tty = tp++;				pp->sp_pend = IDLE_CLOSE;				pp->sp_state = 0;	/* internal flag */				pp->sp_dtr_wait = 3 * hz;				pp->sp_iin.c_iflag = si_default_iflag;				pp->sp_iin.c_oflag = si_default_oflag;				pp->sp_iin.c_cflag = si_default_cflag;				pp->sp_iin.c_lflag = si_default_lflag;				termioschars(&pp->sp_iin);				pp->sp_iin.c_ispeed = pp->sp_iin.c_ospeed =					si_default_rate;				pp->sp_iout = pp->sp_iin;			}			break;		default:			break;		}		if (modp->sm_next == 0) {			printf("si%d: card: %s, ports: %d, modules: %d (type: %d)\n",				unit,				sc->sc_typename,				sc->sc_nport,				nmodule,				uart_type);			break;		}		modp = (struct si_module *)			(maddr + (unsigned)(modp->sm_next & 0x7fff));	}	if (done_chartimes == 0) {		for (spt = chartimes ; spt->sp_speed != -1; spt++) {			if ((spt->sp_code /= hz) == 0)				spt->sp_code = 1;		}		done_chartimes = 1;	}	return (1);}struct isa_driver sidriver =	{ siprobe, siattach, "si" };intsiopen(dev, flag, mode, p)	dev_t dev;	int flag, mode;	struct proc *p;{	int oldspl, error;	int card, port;	register struct si_softc *sc;	register struct tty *tp;	volatile struct si_channel *ccbp;	struct si_port *pp;	int mynor = minor(dev);	/* quickly let in /dev/si_control */	if (IS_CONTROLDEV(mynor)) {		if (error = suser(p->p_ucred, &p->p_acflag))			return(error);		return(0);	}	card = SI_CARD(mynor);	if (card >= NSI)		return (ENXIO);	sc = &si_softc[card];	if (sc->sc_type == SIEMPTY) {		DPRINT((0, DBG_OPEN|DBG_FAIL, "si%d: type %s??\n",			card, sc->sc_typename));		return(ENXIO);	}	port = SI_PORT(mynor);	if (port >= sc->sc_nport) {		DPRINT((0, DBG_OPEN|DBG_FAIL, "si%d: nports %d\n",			card, sc->sc_nport));		return(ENXIO);	}#ifdef	POLL	/*	 * We've now got a device, so start the poller.	 */	if (init_finished == 0) {		timeout(si_poll, (caddr_t)0L, POLL_INTERVAL);		init_finished = 1;	}#endif	/* initial/lock device */	if (IS_STATE(mynor)) {		return(0);	}	pp = sc->sc_ports + port;	tp = pp->sp_tty;			/* the "real" tty */	ccbp = pp->sp_ccb;			/* Find control block */	DPRINT((pp, DBG_ENTRY|DBG_OPEN, "siopen(%x,%x,%x,%x)\n",		dev, flag, mode, p));	oldspl = spltty();			/* Keep others out */	error = 0;open_top:	while (pp->sp_state & SS_DTR_OFF) {		error = tsleep(&pp->sp_dtr_wait, TTIPRI|PCATCH, "sidtr", 0);		if (error != 0)			goto out;	}	if (tp->t_state & TS_ISOPEN) {		/*		 * The device is open, so everything has been initialised.		 * handle conflicts.		 */		if (IS_CALLOUT(mynor)) {			if (!pp->sp_active_out) {				error = EBUSY;				goto out;			}		} else {			if (pp->sp_active_out) {				if (flag & O_NONBLOCK) {					error = EBUSY;					goto out;				}				error = tsleep(&pp->sp_active_out,						TTIPRI|PCATCH, "sibi", 0);				if (error != 0)					goto out;				goto open_top;			}		}		if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) {			DPRINT((pp, DBG_OPEN|DBG_FAIL,				"already open and EXCLUSIVE set\n"));			error = EBUSY;			goto out;		}	} else {		/*		 * The device isn't open, so there are no conflicts.		 * Initialize it. Avoid sleep... :-)		 */		DPRINT((pp, DBG_OPEN, "first open\n"));		tp->t_oproc = si_start;		tp->t_param = siparam;		tp->t_dev = dev;		tp->t_termios = mynor & SI_CALLOUT_MASK				? pp->sp_iout : pp->sp_iin;		(void) si_modem(pp, SET, TIOCM_DTR|TIOCM_RTS);		++pp->sp_wopeners;	/* in case of sleep in siparam */		error = siparam(tp, &tp->t_termios);		--pp->sp_wopeners;		if (error != 0)			goto out;		/* XXX: we should goto_top if siparam slept */		ttsetwater(tp);		/* set initial DCD state */		pp->sp_last_hi_ip = ccbp->hi_ip;		if ((pp->sp_last_hi_ip & IP_DCD) || IS_CALLOUT(mynor)) {			(*linesw[tp->t_line].l_modem)(tp, 1);		}	}	/* whoops! we beat the close! */	if (pp->sp_state & SS_CLOSING) {		/* try and stop it from proceeding to bash the hardware */		pp->sp_state &= ~SS_CLOSING;	}	/*	 * Wait for DCD if necessary	 */	if (!(tp->t_state & TS_CARR_ON)	    && !IS_CALLOUT(mynor)	    && !(tp->t_cflag & CLOCAL)	    && !(flag & O_NONBLOCK)) {		++pp->sp_wopeners;		DPRINT((pp, DBG_OPEN, "sleeping for carrier\n"));		error = tsleep(TSA_CARR_ON(tp), TTIPRI|PCATCH, "sidcd", 0);		--pp->sp_wopeners;		if (error != 0)			goto out;		goto open_top;	}	error = (*linesw[tp->t_line].l_open)(dev, tp);	si_disc_optim(tp, &tp->t_termios, pp);	if (tp->t_state & TS_ISOPEN && IS_CALLOUT(mynor))		pp->sp_active_out = TRUE;	pp->sp_state |= SS_OPEN;	/* made it! */out:	splx(oldspl);	DPRINT((pp, DBG_OPEN, "leaving siopen\n"));	if (!(tp->t_state & TS_ISOPEN) && pp->sp_wopeners == 0)		sihardclose(pp);	return(error);}intsiclose(dev, flag, mode, p)	dev_t dev;	int flag, mode;	struct proc *p;{	register struct si_port *pp;	register struct tty *tp;	int oldspl;	int error = 0;	int mynor = minor(dev);	if (IS_SPECIAL(mynor))		return(0);	oldspl = spltty();	pp = MINOR2PP(mynor);	tp = pp->sp_tty;	DPRINT((pp, DBG_ENTRY|DBG_CLOSE, "siclose(%x,%x,%x,%x) sp_state:%x\n",		dev, flag, mode, p, pp->sp_state));	/* did we sleep and loose a race? */	if (pp->sp_state & SS_CLOSING) {		/* error = ESOMETING? */		goto out;	}	/* begin race detection.. */	pp->sp_state |= SS_CLOSING;	si_write_enable(pp, 0);		/* block writes for ttywait() */	/* THIS MAY SLEEP IN TTYWAIT!!! */	(*linesw[tp->t_line].l_close)(tp, flag);	si_write_enable(pp, 1);	/* did we sleep and somebody started another open? */	if (!(pp->sp_state & SS_CLOSING)) {		/* error = ESOMETING? */		goto out;	}	/* ok. we are now still on the right track.. nuke the hardware */	if (pp->sp_state & SS_LSTART) {		untimeout((timeout_func_t)si_lstart, (caddr_t)pp);		pp->sp_state &= ~SS_LSTART;	}	sistop(tp, FREAD | FWRITE);	sihardclose(pp);	ttyclose(tp);	pp->sp_state &= ~SS_OPEN;out:	DPRINT((pp, DBG_CLOSE|DBG_EXIT, "close done, returning\n"));	splx(oldspl);	return(error);}static voidsihardclose(pp)	struct si_port *pp;{	int oldspl;	struct tty *tp;	volatile struct si_channel *ccbp;	oldspl = spltty();	tp = pp->sp_tty;	ccbp = pp->sp_ccb;			/* Find control block */	if (tp->t_cflag & HUPCL	    || !pp->sp_active_out	       && !(ccbp->hi_ip & IP_DCD)	       && !(pp->sp_iin.c_cflag && CLOCAL)	    || !(tp->t_state & TS_ISOPEN)) {		(void) si_modem(pp, BIC, TIOCM_DTR|TIOCM_RTS);		(void) si_command(pp, FCLOSE, SI_NOWAIT);		if (pp->sp_dtr_wait != 0) {			timeout(sidtrwakeup, pp, pp->sp_dtr_wait);			pp->sp_state |= SS_DTR_OFF;		}	}	pp->sp_active_out = FALSE;	wakeup((caddr_t)&pp->sp_active_out);	wakeup(TSA_CARR_ON(tp));	splx(oldspl);}/* * called at splsoftclock()... */static voidsidtrwakeup(chan)	void *chan;{	struct si_port *pp;	int oldspl;	oldspl = spltty();	pp = (struct si_port *)chan;	pp->sp_state &= ~SS_DTR_OFF;	wakeup(&pp->sp_dtr_wait);	splx(oldspl);}/* * User level stuff - read and write */intsiread(dev, uio, flag)	register dev_t dev;	struct uio *uio;	int flag;{	register struct tty *tp;	int mynor = minor(dev);	if (IS_SPECIAL(mynor)) {		DPRINT((0, DBG_ENTRY|DBG_FAIL|DBG_READ, "siread(CONTROLDEV!!)\n"));		return(ENODEV);	}	tp = MINOR2TP(mynor);	DPRINT((TP2PP(tp), DBG_ENTRY|DBG_READ,		"siread(%x,%x,%x)\n", dev, uio, flag));	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));}intsiwrite(dev, uio, flag)	dev_t dev;	struct uio *uio;	int flag;{	register struct si_port *pp;	register struct tty *tp;	int error = 0;	int mynor = minor(dev);	int oldspl;	if (IS_SPECIAL(mynor)) {		DPRINT((0, DBG_ENTRY|DBG_FAIL|DBG_WRITE, "siwrite(CONTROLDEV!!)\n"));		return(ENODEV);	}	pp = MINOR2PP(mynor);	tp = pp->sp_tty;	DPRINT((pp, DBG_WRITE, "siwrite(%x,%x,%x)\n", dev, uio, flag));	oldspl = spltty();	/*	 * If writes are currently blocked, wait on the "real" tty	 */	while (pp->sp_state & SS_BLOCKWRITE) {		pp->sp_state |= SS_WAITWRITE;		DPRINT((pp, DBG_WRITE, "in siwrite, wait for SS_BLOCKWRITE to clear\n"));		if (error = ttysleep(tp, (caddr_t)pp, TTOPRI|PCATCH,				     "siwrite", 0))			goto out;	}	error = (*linesw[tp->t_line].l_write)(tp, uio, flag);out:	splx(oldspl);	return (error);}struct tty *sidevtotty(dev_t dev){	struct si_port *pp;	int mynor = minor(dev);	struct si_softc *sc = &si_softc[SI_CARD(mynor)];	if (IS_SPECIAL(mynor))		return(NULL);	if (SI_PORT(mynor) >= sc->sc_nport)		return(NULL);	pp = MINOR2PP(mynor);	return (pp->sp_tty);}intsiioctl(dev, cmd, data, flag, p)	dev_t dev;	int cmd;	caddr_t data;	int flag;	struct proc *p;{	struct si_port *pp;	register struct tty *tp;	int error;	int mynor = minor(dev);	int oldspl;	int blocked = 0;#if defined(COMPAT_43)	int oldcmd;	struct termios term;#endif	if (IS_SI_IOCTL(cmd))		return(si_Sioctl(dev, cmd, data, flag, p));	pp = MINOR2PP(mynor);	tp = pp->sp_tty;	DPRINT((pp, DBG_ENTRY|DBG_IOCTL, "siioctl(%x,%x,%x,%x)\n",		dev, cmd, data, flag));	if (IS_STATE(mynor)) {		struct termios *ct;		switch (mynor & SI_STATE_MASK) {		case SI_INIT_STATE_MASK:			ct = IS_CALLOUT(mynor) ? &pp->sp_iout : &pp->sp_iin;			break;		case SI_LOCK_STATE_MASK:			ct = IS_CALLOUT(mynor) ? &pp->sp_lout : &pp->sp_lin;			break;		default:			return (ENODEV);		}		switch (cmd) {		case TIOCSETA:			error = suser(p->p_ucred, &p->p_acflag);			if (error != 0)				return (error);			*ct = *(struct termios *)data;			return (0);		case TIOCGETA:			*(struct termios *)data = *ct;			return (0);		case TIOCGETD:			*(int *)data = TTYDISC;			return (0);		case TIOCGWINSZ:			bzero(data, sizeof(struct winsize));			return (0);		default:			return (ENOTTY);		}	}	/*	 * Do the old-style ioctl compat routines...	 */#if defined(COMPAT_43)	term = tp->t_termios;	oldcmd = cmd;	error = ttsetcompat(tp, &cmd, data, &term);	if (error != 0)		return (error);	if (cmd != oldcmd)		data = (caddr_t)&term;#endif	/*	 * Do the initial / lock state business	 */	if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) {		int     cc;		struct termios *dt = (struct termios *)data;		struct termios *lt = mynor & SI_CALLOUT_MASK				     ? &pp->sp_lout : &pp->sp_lin;		dt->c_iflag = (tp->t_iflag & lt->c_iflag)			| (dt->c_iflag & ~lt->c_iflag);		dt->c_oflag = (tp->t_oflag & lt->c_oflag)			| (dt->c_oflag & ~lt->c_oflag);		dt->c_cflag = (tp->t_cflag & lt->c_cflag)			| (dt->c_cflag & ~lt->c_cflag);		dt->c_lflag = (tp->t_lflag & lt->c_lflag)			| (dt->c_lflag & ~lt->c_lflag);		for (cc = 0; cc < NCCS; ++cc)			if (lt->c_cc[cc] != 0)				dt->c_cc[cc] = tp->t_cc[cc];		if (lt->c_ispeed != 0)			dt->c_ispeed = tp->t_ispeed;		if (lt->c_ospeed != 0)			dt->c_ospeed = tp->t_ospeed;	}	/*	 * Block user-level writes to give the ttywait()	 * a chance to completely drain for commands	 * that require the port to be in a quiescent state.	 */	switch (cmd) {	case TIOCSETAW: case TIOCSETAF:	case TIOCDRAIN: case TIOCSETP:		blocked++;	/* block writes for ttywait() and siparam() */		si_write_enable(pp, 0);	}	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);	if (error >= 0)		goto out;	oldspl = spltty();	error = ttioctl(tp, cmd, data, flag);	si_disc_optim(tp, &tp->t_termios, pp);	if (error >= 0)		goto outspl;	switch (cmd) {	case TIOCSBRK:		si_command(pp, SBREAK, SI_WAIT);		break;	case TIOCCBRK:		si_command(pp, EBREAK, SI_WAIT);		break;	case TIOCSDTR:

⌨️ 快捷键说明

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