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

📄 if_cx.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
#if __FreeBSD__ >= 2		/* Mark the board busy on the first startup.		 * Never goes idle. */		kdc_cx[c->board->num].kdc_state = DC_BUSY;#endif		/* Initialize channel, enable receiver and transmitter */		cx_cmd (port, CCR_INITCH | CCR_ENRX | CCR_ENTX);		/* Repeat the command, to avoid the rev.H bug */		cx_cmd (port, CCR_INITCH | CCR_ENRX | CCR_ENTX);		/* Start receiver */		outw (ARBCNT(port), DMABUFSZ);		outb (ARBSTS(port), BSTS_OWN24);		outw (BRBCNT(port), DMABUFSZ);		outb (BRBSTS(port), BSTS_OWN24);		/* Raise DTR and RTS */		cx_chan_dtr (c, 1);		cx_chan_rts (c, 1);		/* Enable interrupts */		outb (IER(port), IER_RXD | IER_TXD);}/* * Initialization of interface. */void cxinit (int unit){	cx_chan_t *q, *c = cxchan[unit];	int s = splimp();	print (("cx%d.%d: cxinit\n", c->board->num, c->num));	cxdown (c);	/* Stop all slave subchannels. */	for (q=c->slaveq; q; q=q->slaveq)		cxdown (q);	if (c->ifp->if_flags & IFF_RUNNING) {		cxup (c);		/* Start all slave subchannels. */		for (q=c->slaveq; q; q=q->slaveq)			cxup (q);	}	splx (s);}/* * Fill transmitter buffer with data. */void cxput (cx_chan_t *c, char b){	struct mbuf *m;	unsigned char *buf;	unsigned short port = c->chip->port, len, cnt_port, sts_port;	/* 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) {		if (c->ifp->if_flags & IFF_DEBUG)			print (("cx%d.%d: tbuf %c already busy, bsts=%b\n",				c->board->num, c->num, b,				inb (sts_port), BSTS_BITS));		goto ret;	}	/* Get the packet to send. */#ifdef __bsdi__	if (c->sopt.ext) {		struct p2pcom *p = (struct p2pcom*) c->master;		int s = splimp ();		IF_DEQUEUE (&p->p2p_isnd, m)		if (! m)			IF_DEQUEUE (&c->master->if_snd, m)		splx (s);	} else#endif	m = sppp_dequeue (c->master);	if (! m)		return;	len = m->m_pkthdr.len;	/* Count the transmitted bytes to the subchannel, not the master. */	c->master->if_obytes -= len + 3;	c->ifp->if_obytes += len + 3;	c->stat->obytes += len + 3;	if (len >= DMABUFSZ) {		printf ("cx%d.%d: too long packet: %d bytes: ",			c->board->num, c->num, len);		printmbuf (m);		m_freem (m);		return;	}	m_copydata (m, 0, len, buf);#if NBPFILTER > 0	if (c->bpf)		bpf_mtap (c->bpf, m);#endif	m_freem (m);	/* Start transmitter. */	outw (cnt_port, len);	outb (sts_port, BSTS_EOFR | BSTS_INTR | BSTS_OWN24);	if (c->ifp->if_flags & IFF_DEBUG)		print (("cx%d.%d: enqueue %d bytes to %c\n",			c->board->num, c->num, len, buf==c->atbuf ? 'A' : 'B'));ret:	c->ifp->if_flags |= IFF_OACTIVE;}/* * Start output on the (slave) interface.  Get another datagram to send * off of the interface queue, and copy it to the interface * before starting the output. */void cxsend (cx_chan_t *c){	unsigned short port = c->chip->port;	if (c->ifp->if_flags & IFF_DEBUG)		print (("cx%d.%d: cxsend\n", c->board->num, c->num));	/* No output if the interface is down. */	if (! (c->ifp->if_flags & IFF_RUNNING))		return;	/* Set the current channel number. */	outb (CAR(port), c->num & 3);	/* Determine the buffer order. */	if (inb (DMABSTS(port)) & DMABSTS_NTBUF) {		cxput (c, 'B');		cxput (c, 'A');	} else {		cxput (c, 'A');		cxput (c, 'B');	}	/* Set up transmit timeout. */	if (c->master->if_flags & IFF_OACTIVE)		c->master->if_timer = TXTIMEOUT;	/*	 * Enable TXMPTY interrupt,	 * to catch the case when the second buffer is empty.	 */	if ((inb (ATBSTS(port)) & BSTS_OWN24) &&	    (inb (BTBSTS(port)) & BSTS_OWN24)) {		outb (IER(port), IER_RXD | IER_TXD | IER_TXMPTY);	} else		outb (IER(port), IER_RXD | IER_TXD);}/* * Start output on the (master) interface and all slave interfaces. * Always called on splimp(). */void cxstart (struct ifnet *ifp){	cx_chan_t *q, *c = cxchan[ifp->if_unit];	if (c->ifp->if_flags & IFF_DEBUG)		print (("cx%d.%d: cxstart\n", c->board->num, c->num));	/* Start the master subchannel. */	cxsend (c);	/* Start all slave subchannels. */	if (c->slaveq && ! sppp_isempty (c->master))		for (q=c->slaveq; q; q=q->slaveq)			if ((q->ifp->if_flags & IFF_RUNNING) &&			    ! (q->ifp->if_flags & IFF_OACTIVE))				cxsend (q);}/* * Handle transmit timeouts. * Recover after lost transmit interrupts. * Always called on splimp(). */void cxwatchdog (int unit){	cx_chan_t *q, *c = cxchan[unit];	if (! (c->ifp->if_flags & IFF_RUNNING))		return;	if (c->ifp->if_flags & IFF_DEBUG)		printf ("cx%d.%d: device timeout\n", c->board->num, c->num);	cxdown (c);	for (q=c->slaveq; q; q=q->slaveq)		cxdown (q);	cxup (c);	for (q=c->slaveq; q; q=q->slaveq)		cxup (q);		cxstart (c->ifp);}/* * Handle receive interrupts, including receive errors and * receive timeout interrupt. */void cxrinth (cx_chan_t *c){	unsigned short port = c->chip->port;	unsigned short len, risr = inw (RISR(port));	/* Receive errors. */	if (risr & (RIS_BUSERR | RIS_OVERRUN | RISH_CRCERR | RISH_RXABORT)) {		if (c->ifp->if_flags & IFF_DEBUG)			printf ("cx%d.%d: receive error, risr=%b\n",				c->board->num, c->num, risr, RISH_BITS);		++c->ifp->if_ierrors;		++c->stat->ierrs;		if (risr & RIS_OVERRUN)			++c->ifp->if_collisions;	} else if (risr & RIS_EOBUF) {		if (c->ifp->if_flags & IFF_DEBUG)			print (("cx%d.%d: hdlc receive interrupt, risr=%b, arbsts=%b, brbsts=%b\n",				c->board->num, c->num, risr, RISH_BITS,				inb (ARBSTS(port)), BSTS_BITS,				inb (BRBSTS(port)), BSTS_BITS));		++c->stat->ipkts;		/* Handle received data. */		len = (risr & RIS_BB) ? inw(BRBCNT(port)) : inw(ARBCNT(port));		c->stat->ibytes += len;		if (len > DMABUFSZ) {			/* Fatal error: actual DMA transfer size			 * exceeds our buffer size.  It could be caused			 * by incorrectly programmed DMA register or			 * hardware fault.  Possibly, should panic here. */			printf ("cx%d.%d: panic! DMA buffer overflow: %d bytes\n",			       c->board->num, c->num, len);			++c->ifp->if_ierrors;		} else if (! (risr & RIS_EOFR)) {			/* The received frame does not fit in the DMA buffer.			 * It could be caused by serial lie noise,			 * or if the peer has too big MTU. */			if (c->ifp->if_flags & IFF_DEBUG)				printf ("cx%d.%d: received frame length exceeds MTU, risr=%b\n",					c->board->num, c->num, risr, RISH_BITS);			++c->ifp->if_ierrors;		} else {			/* Valid frame received. */			if (c->ifp->if_flags & IFF_DEBUG)				print (("cx%d.%d: hdlc received %d bytes\n",				c->board->num, c->num, len));			cxinput (c, (risr & RIS_BB) ? c->brbuf : c->arbuf, len);			++c->ifp->if_ipackets;		}	} else if (c->ifp->if_flags & IFF_DEBUG) {		print (("cx%d.%d: unknown hdlc receive interrupt, risr=%b\n",			c->board->num, c->num, risr, RISH_BITS));		++c->stat->ierrs;	}	/* Restart receiver. */	if (! (inb (ARBSTS(port)) & BSTS_OWN24)) {		outw (ARBCNT(port), DMABUFSZ);		outb (ARBSTS(port), BSTS_OWN24);	}	if (! (inb (BRBSTS(port)) & BSTS_OWN24)) {		outw (BRBCNT(port), DMABUFSZ);		outb (BRBSTS(port), BSTS_OWN24);	}}/* * Handle transmit interrupt. */int cxtinth (cx_chan_t *c){	unsigned short port = c->chip->port;	unsigned char tisr = inb (TISR(port));	unsigned char teoir = 0;	c->ifp->if_flags &= ~IFF_OACTIVE;	if (c->ifp == c->master)		c->ifp->if_timer = 0;	if (tisr & (TIS_BUSERR | TIS_UNDERRUN)) {		/* if (c->ifp->if_flags & IFF_DEBUG) */			print (("cx%d.%d: transmit error, 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));		++c->ifp->if_oerrors;		++c->stat->oerrs;		/* Terminate the failed buffer. */		/* teoir = TEOI_TERMBUFF; */	} else if (c->ifp->if_flags & IFF_DEBUG)		print (("cx%d.%d: hdlc 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_EOFR) {		++c->ifp->if_opackets;		++c->stat->opkts;	}	/* Start output on the (sub-) channel. */	cxsend (c);	return (teoir);}#ifdef __FreeBSD__void cxintr (int bnum){	cx_board_t *b = cxboard + bnum;#endif#ifdef __bsdi__void cxintr (cx_board_t *b){#endif	while (! (inw (BSR(b->port)) & BSR_NOINTR)) {		/* Acknowledge the interrupt to enter the interrupt context. */		/* Read the local interrupt vector register. */		unsigned char livr = inb (IACK(b->port, BRD_INTR_LEVEL));		cx_chan_t *c = b->chan + (livr>>2 & 0xf);		unsigned short port = c->chip->port;		unsigned short eoiport = REOIR(port);		unsigned char eoi = 0;		if (c->type == T_NONE) {			printf ("cx%d.%d: unexpected interrupt, livr=0x%x\n",				c->board->num, c->num, livr);			continue;       /* incorrect channel number? */		}		/* print (("cx%d.%d: interrupt, livr=0x%x\n",			c->board->num, c->num, livr)); */		/* Clear RTS to stop receiver data flow while we are busy		 * processing the interrupt, thus avoiding underruns. */		if (! c->sopt.norts) {			outb (MSVR_RTS(port), 0);			c->rts = 0;		}		switch (livr & 3) {		case LIV_EXCEP:         /* receive exception */		case LIV_RXDATA:        /* receive interrupt */			++c->stat->rintr;			switch (c->mode) {			case M_ASYNC: eoi = cxrinta (c); break;			case M_HDLC:  cxrinth (c);       break;			default:;       /* No bisync and X.21 yet */			}			break;		case LIV_TXDATA:        /* transmit interrupt */			++c->stat->tintr;			eoiport = TEOIR(port);			switch (c->mode) {			case M_ASYNC: cxtinta (c);       break;			case M_HDLC:  eoi = cxtinth (c); break;			default:;       /* No bisync and X.21 yet */			}			break;		case LIV_MODEM:         /* modem/timer interrupt */			++c->stat->mintr;			eoiport = MEOIR(port);			cxmint (c);			break;		}		/* Raise RTS for this channel if and only if		 * both receive buffers are empty. */		if (! c->sopt.norts && (inb (CSR(port)) & CSRA_RXEN) &&		    (inb (ARBSTS(port)) & BSTS_OWN24) &&		    (inb (BRBSTS(port)) & BSTS_OWN24)) {			outb (MSVR_RTS(port), MSV_RTS);			c->rts = 1;		}		/* Exit from interrupt context. */		outb (eoiport, eoi);		/* Master channel - start output on all idle subchannels. */		if (c->master == c->ifp && c->slaveq &&		    (livr & 3) == LIV_TXDATA && c->mode == M_HDLC &&		    ! sppp_isempty (c->ifp)) {			cx_chan_t *q;			for (q=c->slaveq; q; q=q->slaveq)				if ((q->ifp->if_flags & IFF_RUNNING) &&				    ! (q->ifp->if_flags & IFF_OACTIVE))					cxsend (q);		}	}}/* * Process the received packet. */void cxinput (cx_chan_t *c, void *buf, unsigned len){	/* Make an mbuf. */	struct mbuf *m = makembuf (buf, len);	if (! m) {		if (c->ifp->if_flags & IFF_DEBUG)			printf ("cx%d.%d: no memory for packet\n",				c->board->num, c->num);		++c->ifp->if_iqdrops;		return;	}	m->m_pkthdr.rcvif = c->master;#ifdef DEBUG	if (c->ifp->if_flags & IFF_DEBUG)	printmbuf (m);#endif#if NBPFILTER > 0	/*	 * Check if there's a BPF listener on this interface.	 * If so, hand off the raw packet to bpf.	 */	if (c->bpf)		bpf_tap (c->bpf, buf, len);#endif	/* Count the received bytes to the subchannel, not the master. */	c->master->if_ibytes -= len + 3;	c->ifp->if_ibytes += len + 3;#ifdef __bsdi__	if (c->sopt.ext) {		struct p2pcom *p = (struct p2pcom*) c->master;		(*p->p2p_input) (p, m);	} else#endif	sppp_input (c->master, m);}void cxswitch (cx_chan_t *c, cx_soft_opt_t new){#ifdef __bsdi__	if (new.ext && ! c->sopt.ext) {		/* Switch to external ppp implementation (BSDI) */		sppp_detach (c->ifp);		bzero ((void*) c->ifp + IFNETSZ, IFSTRUCTSZ-IFNETSZ);	} else if (! new.ext && c->sopt.ext) {		/* Switch to built-in ppp implementation */		bzero ((void*) c->ifp + IFNETSZ, IFSTRUCTSZ-IFNETSZ);		sppp_attach (c->ifp);	}#else	new.ext = 0;#endif	if (! new.ext) {		struct sppp *sp = (struct sppp*) c->ifp;		if (new.cisco)			sp->pp_flags |= PP_CISCO;		else			sp->pp_flags &= ~PP_CISCO;		if (new.keepalive)			sp->pp_flags |= PP_KEEPALIVE;		else			sp->pp_flags &= ~PP_KEEPALIVE;	}	c->sopt = new;}#endif /* NCX */

⌨️ 快捷键说明

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