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

📄 dcm.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
{	int unit = UNIT(dev);	register struct tty *tp; 	tp = &dcm_tty[unit];	/*	 * XXX we disallow virtual consoles if the physical console is	 * a serial port.  This is in case there is a display attached that	 * is not the console.  In that situation we don't need/want the X	 * server taking over the console.	 */	if (constty && unit == dcmconsole)		constty = NULL;	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));} dcmintr(brd)	register int brd;{	register struct dcmdevice *dcm = dcm_addr[brd];	register struct dcmischeme *dis;	register int unit = MKUNIT(brd, 0);	register int code, i;	int pcnd[4], mcode, mcnd[4];	/*	 * Do all guarded register accesses right off to minimize	 * block out of hardware.	 */	SEM_LOCK(dcm);	if ((dcm->dcm_ic & IC_IR) == 0) {		SEM_UNLOCK(dcm);		return (0);	}	for (i = 0; i < 4; i++) {		pcnd[i] = dcm->dcm_icrtab[i].dcm_data;		dcm->dcm_icrtab[i].dcm_data = 0;		code = dcm_modem[unit+i]->mdmin;		if (dcmsoftCAR[brd] & FLAG_STDDCE)			code = hp2dce_in(code);		mcnd[i] = code;	}	code = dcm->dcm_iir & IIR_MASK;	dcm->dcm_iir = 0;	/* XXX doc claims read clears interrupt?! */	mcode = dcm->dcm_modemintr;	dcm->dcm_modemintr = 0;	SEM_UNLOCK(dcm);#ifdef DEBUG	if (dcmdebug & DDB_INTR) {		printf("dcmintr(%d): iir %x pc %x/%x/%x/%x ",		       brd, code, pcnd[0], pcnd[1], pcnd[2], pcnd[3]); 		printf("miir %x mc %x/%x/%x/%x\n",		       mcode, mcnd[0], mcnd[1], mcnd[2], mcnd[3]);	}#endif	if (code & IIR_TIMEO)		dcmrint(brd, dcm);	if (code & IIR_PORT0)		dcmpint(unit+0, pcnd[0], dcm);	if (code & IIR_PORT1)		dcmpint(unit+1, pcnd[1], dcm);	if (code & IIR_PORT2)		dcmpint(unit+2, pcnd[2], dcm);	if (code & IIR_PORT3)		dcmpint(unit+3, pcnd[3], dcm);	if (code & IIR_MODM) {		if (mcode == 0 || mcode & 0x1)	/* mcode==0 -> 98642 board */			dcmmint(unit+0, mcnd[0], dcm);		if (mcode & 0x2)			dcmmint(unit+1, mcnd[1], dcm);		if (mcode & 0x4)			dcmmint(unit+2, mcnd[2], dcm);		if (mcode & 0x8)			dcmmint(unit+3, mcnd[3], dcm);	}	dis = &dcmischeme[brd];	/*	 * Chalk up a receiver interrupt if the timer running or one of	 * the ports reports a special character interrupt.	 */	if ((code & IIR_TIMEO) ||	    ((pcnd[0]|pcnd[1]|pcnd[2]|pcnd[3]) & IT_SPEC))		dis->dis_intr++;	/*	 * See if it is time to check/change the interrupt rate.	 */	if (dcmistype < 0 &&	    (i = time.tv_sec - dis->dis_time) >= dcminterval) {		/*		 * If currently per-character and averaged over 70 interrupts		 * per-second (66 is threshold of 600 baud) in last interval,		 * switch to timer mode.		 *		 * XXX decay counts ala load average to avoid spikes?		 */		if (dis->dis_perchar && dis->dis_intr > 70 * i)			dcmsetischeme(brd, DIS_TIMER);		/*		 * If currently using timer and had more interrupts than		 * received characters in the last interval, switch back		 * to per-character.  Note that after changing to per-char		 * we must process any characters already in the queue		 * since they may have arrived before the bitmap was setup.		 *		 * XXX decay counts?		 */		else if (!dis->dis_perchar && dis->dis_intr > dis->dis_char) {			dcmsetischeme(brd, DIS_PERCHAR);			dcmrint(brd, dcm);		}		dis->dis_intr = dis->dis_char = 0;		dis->dis_time = time.tv_sec;	}	return (1);}/* *  Port interrupt.  Can be two things: *	First, it might be a special character (exception interrupt); *	Second, it may be a buffer empty (transmit interrupt); */dcmpint(unit, code, dcm)	int unit, code;	struct dcmdevice *dcm;{	struct tty *tp = &dcm_tty[unit];	if (code & IT_SPEC)		dcmreadbuf(unit, dcm, tp);	if (code & IT_TX)		dcmxint(unit, dcm, tp);}dcmrint(brd, dcm)	int brd;	register struct dcmdevice *dcm;{	register int i, unit;	register struct tty *tp;	unit = MKUNIT(brd, 0);	tp = &dcm_tty[unit];	for (i = 0; i < 4; i++, tp++, unit++)		dcmreadbuf(unit, dcm, tp);}dcmreadbuf(unit, dcm, tp)	int unit;	register struct dcmdevice *dcm;	register struct tty *tp;{	int port = PORT(unit);	register struct dcmpreg *pp = dcm_preg(dcm, port);	register struct dcmrfifo *fifo;	register int c, stat;	register unsigned head;	int nch = 0;#ifdef DCMSTATS	struct dcmstats *dsp = &dcmstats[BOARD(unit)];	dsp->rints++;#endif	if ((tp->t_state & TS_ISOPEN) == 0) {#ifdef KGDB		if ((makedev(dcmmajor, unit) == kgdb_dev) &&		    (head = pp->r_head & RX_MASK) != (pp->r_tail & RX_MASK) &&		    dcm->dcm_rfifos[3-port][head>>1].data_char == FRAME_START) {			pp->r_head = (head + 2) & RX_MASK;			kgdb_connect(0);	/* trap into kgdb */			return;		}#endif /* KGDB */		pp->r_head = pp->r_tail & RX_MASK;		return;	}	head = pp->r_head & RX_MASK;	fifo = &dcm->dcm_rfifos[3-port][head>>1];	/*	 * XXX upper bound on how many chars we will take in one swallow?	 */	while (head != (pp->r_tail & RX_MASK)) {		/*		 * Get character/status and update head pointer as fast		 * as possible to make room for more characters.		 */		c = fifo->data_char;		stat = fifo->data_stat;		head = (head + 2) & RX_MASK;		pp->r_head = head;		fifo = head ? fifo+1 : &dcm->dcm_rfifos[3-port][0];		nch++;#ifdef DEBUG		if (dcmdebug & DDB_INPUT)			printf("dcmreadbuf(%d): c%x('%c') s%x f%x h%x t%x\n",			       unit, c&0xFF, c, stat&0xFF,			       tp->t_flags, head, pp->r_tail);#endif		/*		 * Check for and handle errors		 */		if (stat & RD_MASK) {#ifdef DEBUG			if (dcmdebug & (DDB_INPUT|DDB_SIOERR))				printf("dcmreadbuf(%d): err: c%x('%c') s%x\n",				       unit, stat, c&0xFF, c);#endif			if (stat & (RD_BD | RD_FE))				c |= TTY_FE;			else if (stat & RD_PE)				c |= TTY_PE;			else if (stat & RD_OVF)				log(LOG_WARNING,				    "dcm%d: silo overflow\n", unit);			else if (stat & RD_OE)				log(LOG_WARNING,				    "dcm%d: uart overflow\n", unit);		}		(*linesw[tp->t_line].l_rint)(c, tp);	}	dcmischeme[BOARD(unit)].dis_char += nch;#ifdef DCMSTATS	dsp->rchars += nch;	if (nch <= DCMRBSIZE)		dsp->rsilo[nch]++;	else		dsp->rsilo[DCMRBSIZE+1]++;#endif}dcmxint(unit, dcm, tp)	int unit;	struct dcmdevice *dcm;	register struct tty *tp;{	tp->t_state &= ~TS_BUSY;	if (tp->t_state & TS_FLUSH)		tp->t_state &= ~TS_FLUSH;	(*linesw[tp->t_line].l_start)(tp);}dcmmint(unit, mcnd, dcm)	register int unit;	register struct dcmdevice *dcm;        int mcnd;{	register struct tty *tp;	int delta;#ifdef DEBUG	if (dcmdebug & DDB_MODEM)		printf("dcmmint: port %d mcnd %x mcndlast %x\n",		       unit, mcnd, mcndlast[unit]);#endif	tp = &dcm_tty[unit];	delta = mcnd ^ mcndlast[unit];	mcndlast[unit] = mcnd;	if ((delta & MI_CTS) && (tp->t_state & TS_ISOPEN) &&	    (tp->t_flags & CCTS_OFLOW)) {		if (mcnd & MI_CTS) {			tp->t_state &= ~TS_TTSTOP;			ttstart(tp);		} else			tp->t_state |= TS_TTSTOP;	/* inline dcmstop */	}	if (delta & MI_CD) {		if (mcnd & MI_CD)			(void)(*linesw[tp->t_line].l_modem)(tp, 1);		else if ((dcmsoftCAR[BOARD(unit)] & (1 << PORT(unit))) == 0 &&		    (*linesw[tp->t_line].l_modem)(tp, 0) == 0) {			dcm_modem[unit]->mdmout = MO_OFF;			SEM_LOCK(dcm);			dcm->dcm_modemchng |= 1<<(unit & 3);			dcm->dcm_cr |= CR_MODM;			SEM_UNLOCK(dcm);			DELAY(10); /* time to change lines */		}	}}dcmioctl(dev, cmd, data, flag, p)	dev_t dev;	int cmd;	caddr_t data;	int flag;	struct proc *p;{	register struct tty *tp;	register int unit = UNIT(dev);	register struct dcmdevice *dcm;	register int port;	int error, s; #ifdef DEBUG	if (dcmdebug & DDB_IOCTL)		printf("dcmioctl: unit %d cmd %x data %x flag %x\n",		       unit, cmd, *data, flag);#endif	tp = &dcm_tty[unit];	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);	if (error >= 0)		return (error);	error = ttioctl(tp, cmd, data, flag);	if (error >= 0)		return (error);	port = PORT(unit);	dcm = dcm_addr[BOARD(unit)];	switch (cmd) {	case TIOCSBRK:		/*		 * Wait for transmitter buffer to empty		 */		s = spltty();		while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr)			DELAY(DCM_USPERCH(tp->t_ospeed));		SEM_LOCK(dcm);		dcm->dcm_cmdtab[port].dcm_data |= CT_BRK;		dcm->dcm_cr |= (1 << port);	/* start break */		SEM_UNLOCK(dcm);		splx(s);		break;	case TIOCCBRK:		SEM_LOCK(dcm);		dcm->dcm_cmdtab[port].dcm_data |= CT_BRK;		dcm->dcm_cr |= (1 << port);	/* end break */		SEM_UNLOCK(dcm);		break;	case TIOCSDTR:		(void) dcmmctl(dev, MO_ON, DMBIS);		break;	case TIOCCDTR:		(void) dcmmctl(dev, MO_ON, DMBIC);		break;	case TIOCMSET:		(void) dcmmctl(dev, *(int *)data, DMSET);		break;	case TIOCMBIS:		(void) dcmmctl(dev, *(int *)data, DMBIS);		break;	case TIOCMBIC:		(void) dcmmctl(dev, *(int *)data, DMBIC);		break;	case TIOCMGET:		*(int *)data = dcmmctl(dev, 0, DMGET);		break;	default:		return (ENOTTY);	}	return (0);}dcmparam(tp, t)	register struct tty *tp;	register struct termios *t;{	register struct dcmdevice *dcm;	register int port, mode, cflag = t->c_cflag;	int ospeed = ttspeedtab(t->c_ospeed, dcmspeedtab);	/* check requested parameters */        if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))                return (EINVAL);        /* and copy to tty */        tp->t_ispeed = t->c_ispeed;        tp->t_ospeed = t->c_ospeed;        tp->t_cflag = cflag;	if (ospeed == 0) {		(void) dcmmctl(UNIT(tp->t_dev), MO_OFF, DMSET);		return (0);	}	mode = 0;	switch (cflag&CSIZE) {	case CS5:		mode = LC_5BITS; break;	case CS6:		mode = LC_6BITS; break;	case CS7:		mode = LC_7BITS; break;	case CS8:		mode = LC_8BITS; break;	}	if (cflag&PARENB) {		if (cflag&PARODD)			mode |= LC_PODD;		else			mode |= LC_PEVEN;	}	if (cflag&CSTOPB)		mode |= LC_2STOP;	else		mode |= LC_1STOP;#ifdef DEBUG	if (dcmdebug & DDB_PARAM)		printf("dcmparam(%d): cflag %x mode %x speed %d uperch %d\n",		       UNIT(tp->t_dev), cflag, mode, tp->t_ospeed,		       DCM_USPERCH(tp->t_ospeed));#endif	port = PORT(tp->t_dev);	dcm = dcm_addr[BOARD(tp->t_dev)];	/*	 * Wait for transmitter buffer to empty.	 */	while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr)		DELAY(DCM_USPERCH(tp->t_ospeed));	/*	 * Make changes known to hardware.	 */	dcm->dcm_data[port].dcm_baud = ospeed;	dcm->dcm_data[port].dcm_conf = mode;	SEM_LOCK(dcm);	dcm->dcm_cmdtab[port].dcm_data |= CT_CON;	dcm->dcm_cr |= (1 << port);	SEM_UNLOCK(dcm);	/*	 * Delay for config change to take place. Weighted by baud.	 * XXX why do we do this?	 */	DELAY(16 * DCM_USPERCH(tp->t_ospeed));	return (0);} voiddcmstart(tp)	register struct tty *tp;{	register struct dcmdevice *dcm;	register struct dcmpreg *pp;	register struct dcmtfifo *fifo;

⌨️ 快捷键说明

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