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

📄 pi.c

📁 用于底层开发的TCPIP协议栈源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
			hp->rxcnt = 0;
			hp->rstate = RXERROR;	/* set error flag */
			hp->rovers++;
		} else if(hp->rxcnt >= hp->bufsiz){
			/* Too large -- toss entire frame */
			/* reset buffer pointers */
			hp->rcp = hp->rcvbuf;
			hp->rxcnt = 0;
			hp->rstate = TOOBIG;	/* when set, chars are not stored */
		}
		/* ok, we can store the received character now */
		if(hp->rstate == ACTIVE){	/* If no errors... */
			*hp->rcp++ = xread_scc(hp,cmd,R8); /* char to rcv buff */
			hp->rxcnt++;		   /* bump count */
		} else {
			/* got to empty FIFO */
			(void) xread_scc(hp,cmd,R8);
			xwrite_scc(hp,cmd,R0,ERR_RES);	/* reset err latch */
			hp->rstate = ACTIVE;
		}
	}

	if(rse & END_FR){
		/* END OF FRAME -- Make sure Rx was active */
		if(hp->rxcnt > 0){
			if((rse & CRC_ERR)||(hp->rstate > ACTIVE)||(hp->rxcnt < 10)){
				if((hp->rxcnt >= 10) && (rse & CRC_ERR))
					hp->crcerr++; /* Ignore noise */

				hp->rcp = hp->rcvbuf;
				hp->rxcnt = 0;
			} else {
				/* Here we have a valid frame */
				hp->rxcnt -= 2;  /* Toss 2 crc bytes */
				if((bp = alloc_mbuf(hp->rxcnt+sizeof(struct iface *)))
				 != NULL){
					bp->data += sizeof(struct iface *);
					bp->cnt = hp->rxcnt;
					memcpy(bp->data,hp->rcvbuf,hp->rxcnt);
					net_route(hp->iface,&bp);
					hp->rxframes++;
				}
				/* packet queued - get ready for next frame */
				hp->rcp = hp->rcvbuf;
				hp->rxcnt = 0;
			} /* end good frame queued */
		}  /* end check for active receive upon EOF */
		hp->rstate = ACTIVE;	/* and clear error status */
	} /* end EOF check */

	restore(i_state);
}

static void
b_txint(hp)
register struct pichan *hp;
{
	register uint16 cmd;
	char c;
	struct mbuf *bp;
	int i_state;

	cmd = CTL+hp->base;

	i_state = dirps();
	if(hp->tstate != DEFER && hp->tstate)
		hp->txints++;

	switch(hp->tstate){
	case CRCOUT:
		hp->tstate = FLAGOUT;
		tdelay(hp,hp->squeldelay);
		restore(i_state);
		return;
	case IDLE:
		/* Transmitter idle. Find a frame for transmission */
		if((bp = dequeue(&hp->sndq)) == NULL){
			/* Nothing to send - return to receive mode
			 * Tx OFF now - flag should have gone
			 */
			rts(hp,OFF);
			restore(i_state);
			return;
		}
		hp->txcnt = pullup(&bp,hp->sndbuf,hp->bufsiz);	
		free_p(&bp);	/* Truncate overly long packets */
		/* If a buffer to send, we drop thru here */
	case DEFER:	    /* we may have deferred prev xmit attempt */
		/* Check DCD - debounce it */
		/* See Intel Microcommunications Handbook, p2-308 */
		xwrite_scc(hp,cmd,R0,RES_EXT_INT);
		xwrite_scc(hp,cmd,R0,RES_EXT_INT);
		if((xread_scc(hp,cmd,R0) & DCD) != 0){
			hp->tstate = DEFER;
			tdelay(hp,100);
			/* defer until DCD transition or timeout */
			xwrite_scc(hp,cmd,R15,CTSIE|DCDIE);
			restore(i_state);
			return;
		}
		/* p - persist calculation */
		if(inportb(hp->cardbase+TMR0) > hp->persist){
			inportb(hp->cardbase+TMR0); /* Discard MSB */
			hp->tstate = DEFER;
			tdelay(hp,hp->slotime);
			restore(i_state);
			return;
		}
		inportb(hp->cardbase+TMR0); /* Discard MSB */

		rts(hp,ON);   /* Transmitter on */
		hp->tstate = ST_TXDELAY;
		tdelay(hp,hp->txdelay);
		restore(i_state);
		return;

	case ACTIVE:
		/* Here we are actively sending a frame */
		if(hp->txcnt-- != 0){
			c = *hp->tcp++;
			/* next char is gone */
			xwrite_scc(hp,cmd,R8,c);
			/* stuffing a char satisfies Interrupt condition */
		} else {
			/* No more to send */
			if((xread_scc(hp,cmd,R0) & 0x40)){
				/* Did we underrun? */
				/* unexpected underrun */
				hp->tunders++;
				xwrite_scc(hp,cmd,R0,SEND_ABORT);
				hp->tstate = FLAGOUT;
				tdelay(hp,hp->squeldelay);
				restore(i_state);
				return;
			}
			hp->tstate = UNDERRUN; /* Now we expect to underrun */
			/* Send flags on underrun */
			if(hp->speed){ /* If externally clocked */
				xwrite_scc(hp,cmd,R10,CRCPS|NRZI);
			} else {
				xwrite_scc(hp,cmd,R10,CRCPS);
			}
			xwrite_scc(hp,cmd,R0,RES_Tx_P); /* reset Tx Int Pend */
		}
		restore(i_state);
		return;     /* back to wait for interrupt */
	} /* end switch */
	restore(i_state);
}

/* Pi SIO External/Status interrupts (for the B channel)
 * This can be caused by a receiver abort, or a Tx UNDERRUN/EOM.
 * Receiver automatically goes to Hunt on an abort.
 *
 * If the Tx Underrun interrupt hits, change state and
 * issue a reset command for it, and return.
 */
static void
b_exint(hp)
register struct pichan *hp;
{
	char st;
	register uint16 cmd;
	char c;
	struct mbuf *bp;
	int i_state;

	cmd = CTL+hp->base;
	hp->exints++;
	i_state = dirps();
	st = xread_scc(hp,cmd,R0);     /* Fetch status */
	/* reset external status latch */
	xwrite_scc(hp,cmd,R0,RES_EXT_INT);

	switch(hp->tstate){
	case ACTIVE:	/* Unexpected underrun */
		xwrite_scc(hp,cmd,R0,SEND_ABORT);
		hp->tstate = FLAGOUT;
		hp->tunders++;
		tdelay(hp,hp->squeldelay);
		restore(i_state);
		return;
	case UNDERRUN:
		hp->tstate = CRCOUT;
		restore(i_state);
		return;
	case FLAGOUT: 
		/* Find a frame for transmission */
		if((bp = dequeue(&hp->sndq)) == NULL){
			/* Nothing to send - return to receive mode
			 * Tx OFF now - flag should have gone
			 */
			rts(hp,OFF);
			hp->tstate = IDLE;
			restore(i_state);
			return;
		}
		hp->txcnt = pullup(&bp,hp->sndbuf,hp->bufsiz);
                free_p(&bp); /* Truncate overly long packets */
		hp->tcp = hp->sndbuf;

		/* Get next char to send */
		c = *hp->tcp++;
		hp->txcnt--;
		xwrite_scc(hp,cmd,R0,RES_Tx_CRC);/* reset for next frame */

		/* Send abort on underrun */
		if(hp->speed){ /* If externally clocked */
			xwrite_scc(hp,cmd,R10,CRCPS|NRZI|ABUNDER);
		} else {
			xwrite_scc(hp,cmd,R10,CRCPS|ABUNDER);
		}

		xwrite_scc(hp,cmd,R8,c);	/* First char out now */
		xwrite_scc(hp,cmd,R0,RES_EOM_L);/* Reset end of message latch */

		/* select transmit interrupts to enable */

		xwrite_scc(hp,cmd,R15,TxUIE);	/* allow Underrun int only */
		xwrite_scc(hp,cmd,R0,RES_EXT_INT);
		xwrite_scc(hp,cmd,R1,TxINT_ENAB|EXT_INT_ENAB);  /* Tx/Extern ints on */

		hp->tstate = ACTIVE;	/* char going out now */
		restore(i_state);
		return;

	case DEFER:
		/* Check DCD - debounce it
		 * See Intel Microcommunications Handbook, p2-308
		 */
		xwrite_scc(hp,cmd,R0,RES_EXT_INT);
		xwrite_scc(hp,cmd,R0,RES_EXT_INT);
		if((xread_scc(hp,cmd,R0) & DCD) != 0){
			hp->tstate = DEFER;
			tdelay(hp,100);
			/* defer until DCD transition or timeout */
			xwrite_scc(hp,cmd,R15,CTSIE|DCDIE);
			restore(i_state);
			return;
		}
		/* p - persist calculation */
		if(inportb(hp->cardbase+TMR0) > hp->persist){
			inportb(hp->cardbase+TMR0); /* Discard MSB */
			hp->tstate = DEFER;
			tdelay(hp,hp->slotime);
			restore(i_state);
			return;
		}
		inportb(hp->cardbase+TMR0); /* Discard MSB */

		rts(hp,ON);   /* Transmitter on */
		hp->tstate = ST_TXDELAY;
		tdelay(hp,hp->txdelay);
		restore(i_state);
		return;

	case ST_TXDELAY:

		/* Get next char to send */
		c = *hp->tcp++;
		hp->txcnt--;
		xwrite_scc(hp,cmd,R0,RES_Tx_CRC);/* reset for next frame */

		/* Send abort on underrun */
		if(hp->speed){ /* If externally clocked */
			xwrite_scc(hp,cmd,R10,CRCPS|NRZI|ABUNDER);
		} else {
			xwrite_scc(hp,cmd,R10,CRCPS|ABUNDER);
		}

		xwrite_scc(hp,cmd,R8,c);	/* First char out now */
		xwrite_scc(hp,cmd,R0,RES_EOM_L);/* Reset end of message latch */

		/* select transmit interrupts to enable */

		xwrite_scc(hp,cmd,R15,TxUIE);	/* allow Underrun int only */
		xwrite_scc(hp,cmd,R0,RES_EXT_INT);
		/* Tx/Extern ints on */
		xwrite_scc(hp,cmd,R1,TxINT_ENAB|EXT_INT_ENAB);

		hp->tstate = ACTIVE;	/* char going out now */
		restore(i_state);
		return;
	}

	/* Receive Mode only
	 * This triggers when hunt mode is entered, & since an ABORT
	 * automatically enters hunt mode, we use that to clean up
	 * any waiting garbage
	 */
	if((hp->rstate == ACTIVE) && (st & BRK_ABRT)){
		(void) xread_scc(hp,cmd,R8);
		(void) xread_scc(hp,cmd,R8);
		(void) xread_scc(hp,cmd,R8);
		hp->rcp = hp->rcvbuf;
		hp->rxcnt = 0;	      /* rewind on DCD transition */
	}
	restore(i_state);
}

/* SET Transmit or Receive Mode
 * Set RTS (request-to-send) to modem on Transmit
 */
static void
rts(hp,x)
register struct pichan *hp;
uint16 x;
{
	uint16 tc;
	long br;
	uint16 cmd;

	cmd = CTL+hp->base;

	/* Reprogram BRG and turn on transmitter to send flags */
	if(x == ON){	/* Turn Tx ON and Receive OFF */
		/* Exints off first to avoid abort int */
		xwrite_scc(hp,cmd,R15,0);
		xwrite_scc(hp,cmd,R3,Rx8);	/* Rx off */
		hp->rstate = IDLE;
		if(cmd & 2){ /* if channel a */
			/* Set up for TX dma */
			xwrite_scc(hp,cmd,R1,WT_FN_RDYFN|EXT_INT_ENAB);
		} else {
			xwrite_scc(hp,cmd,R1,0);	/* No interrupts */
		}
		if(hp->speed){			/* if internally clocked */
			br = hp->speed;		/* get desired speed */
			tc = (XTAL/br)-2;	/* calc 1X BRG divisor */
			xwrite_scc(hp,cmd,R12,tc&0xFF);     /* lower byte */
			xwrite_scc(hp,cmd,R13,(tc>>8)&0xFF);/* upper byte */
		}
		xwrite_scc(hp,cmd,R5,TxCRC_ENAB|RTS|TxENAB|Tx8|DTR);
		/* Transmitter now on */
	} else {	/* Tx OFF and Rx ON */
		hp->tstate = IDLE;
		xwrite_scc(hp,cmd,R5,Tx8|DTR); 	/*  TX off */

		if(hp->speed){		/* if internally clocked */
			/* Reprogram BRG for 32x clock for receive DPLL */
			/* BRG off, keep Pclk source */
			xwrite_scc(hp,cmd,R14,BRSRC);
			br = hp->speed;			/* get desired speed */
			/* calc 32X BRG divisor */
			tc = ((XTAL/32)/br)-2;
			xwrite_scc(hp,cmd,R12,tc&0xFF);	/* lower byte */
			xwrite_scc(hp,cmd,R13,(tc>>8)&0xFF);/* upper byte */
			/* SEARCH mode, BRG source */
			xwrite_scc(hp,cmd,R14,BRSRC|SEARCH);
			/* Enable the BRG */
			xwrite_scc(hp,cmd,R14,BRSRC|BRENABL);
		}
		/* Now, turn on the receiver and hunt for a flag */
		xwrite_scc(hp,cmd,R3,RxENABLE|RxCRC_ENAB|Rx8);
		hp->rstate = ACTIVE;		/* Normal state */

		if(cmd & 2){/* if channel a */
			setup_rx_dma(hp);
		} else {
			/* reset error bits */
		/*	xwrite_scc(hp,cmd,R0,ERR_RES); */
			/* reset buffer pointers */
			hp->rcp = hp->rcvbuf;
			hp->rxcnt = 0;
			xwrite_scc(hp,cmd,R1,(INT_ALL_Rx|EXT_INT_ENAB));
		}
		xwrite_scc(hp,cmd,R15,BRKIE);		/* allow ABORT int */
		/* Hold tx off long enough for other station to reply */
		hp->deftime = msclock() + hp->txdelay + 500;
	}
}

void
setup_rx_dma(hp)
register struct pichan *hp;
{
	int cmd;
	int dmaport;
	int i_state;

	cmd = hp->base+CTL;
	dmaport = DMABASE+2*hp->dmachan;

	i_state = dirps();
	if(!hp->rcvbuf){
		/* No rx buffer available */
		restore(i_state);
		return;
	}

	/* Get ready for RX DMA */
	xwrite_scc(hp,cmd,R1,WT_FN_RDYFN|WT_RDY_RT|INT_ERR_Rx|EXT_INT_ENAB);
	outportb(DMA_MASK, DMA_DISABLE|hp->dmachan); /* Disable DMA chan */
	/* Set DMA mode register to single transfers, incrementing address,
	 *	auto init, writes
	 */
	outportb(DMA_MODE,DMA_RX_MODE|hp->dmachan);

	outportb(Page_regs[hp->dmachan],hp->rcvphys >> 16);/* Store in  64K DMA page */
	outportb(DMA_RESETFF,0);	 /* reset byte pointer flipflop */
	/* Output buffer start (dest) address */
	outportb(dmaport,hp->rcvphys);
	outportb(dmaport,hp->rcvphys >> 8);
	/* output DMA maximum byte count */
	dmaport++;
	outportb(dmaport,hp->bufsiz - 1);
	outportb(dmaport, (hp->bufsiz - 1) >> 8);
	/* Unmask channel 1 (start DMA) */
	outportb(DMA_MASK, DMA_ENABLE|hp->dmachan); /* Enable DMA chan */

	/* If a packet is already coming in, this line is supposed
	 *	to mess up the crc to avoid receiving a partial packet
	 */
	xwrite_scc(hp,cmd,R0,RES_Rx_CRC);

	/* Enable RX dma */
	xwrite_scc(hp,cmd,R1,WT_RDY_ENAB|WT_FN_RDYFN|WT_RDY_RT|INT_ERR_Rx|EXT_INT_ENAB);

	restore(i_state);
}

void
setup_tx_dma(hp)
struct pichan *hp;
{
	int dmaport;
	uint16 length;
	int i_state;

	length = hp->txcnt - 1;
	dmaport = DMABASE + 2*hp->dmachan;
	i_state = dirps();

	outportb(DMA_MASK, DMA_DISABLE|hp->dmachan); /* Disable DMA chan */
	/* Set DMA mode register to single transfers, incrementing address,
	 *	no auto init, reads
 	 */
	outportb(DMA_MODE,DMA_TX_MODE|hp->dmachan);

	outportb(Page_regs[hp->dmachan],hp->sndphys >> 16); /* Store in 64K DMA page */
	outportb(DMA_RESETFF,0);	/* reset byte pointer flipflop */
	outportb(dmaport,hp->sndphys);	/* Output buffer start (source) address */
	outportb(dmaport,hp->sndphys >> 8);
	/* output byte count */
	dmaport++;
	outportb(dmaport,length);
	outportb(dmaport, length >> 8);

	restore(i_state);
}

/* Initialize pi controller parameters */
static int
scc_init(hp)
register struct pichan *hp;
{
	uint16 tc;
	long br;
	register uint16 cmd;
	int i_state;

	/* Initialize 8530 channel for SDLC operation */

	cmd = CTL+hp->base;
#ifdef	notdef
	printf("Pi: Initializing Channel %c - Base = %x\n",cmd&2?'A':'B',cmd&~CTL);
#endif
	i_state = dirps();

	switch(cmd & 2){
	case 2:
		xwrite_scc(hp,cmd,R9,CHRA);	/* Reset channel A */
		xwrite_scc(hp,cmd,R2,0xff); /* Initialize interrupt vector */

⌨️ 快捷键说明

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