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

📄 hs.c

📁 uCLinux下的一个TCP/IP协议栈源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		hp->txdelay = atol(argv[7]);
	else
		hp->txdelay = 15L;
	if(argc > 8)
		hp->p = atoi(argv[8]);
	else
		hp->p = 64;
	if(argc > 9 && argv[9][0] == 'r')
		hp->clkrev = 1;
	else
		hp->clkrev = 0;
	hp->iface = if_hsb;
	hdlcparam(hp);

	hp = &Hdlc[2*dev];
	hp->ctl = Hs[dev].addr + CHANA + CTL;
	hp->data = Hs[dev].addr + CHANA + DATA;
	hp->bufsiz = atoi(argv[5]);
	hp->txdelay = Hdlc[2*dev+1].txdelay;
	hp->p = Hdlc[2*dev+1].p;
	if(argc > 9 && argv[9][0] == 'r')
		hp->clkrev = 1;
	else
		hp->clkrev = 0;
	hp->iface = if_hsa;
	hdlcparam(hp);

	outportb(Hs[dev].addr + 4,0x08);	/*EAGLE INT GATE */
	/* Clear mask (enable interrupt) in 8259 interrupt controller */
	maskon(Hs[dev].vec);

	/* Initialize timing delay loop */
	init_delay();
	cp = if_name(if_hsa," tx");
	if_hsa->txproc = newproc(cp,512,if_tx,0,if_hsa,NULL,0);
	free(cp);
	cp = if_name(if_hsb," tx");
	if_hsb->txproc = newproc(cp,512,if_tx,0,if_hsb,NULL,0);
	free(cp);
	return 0;
}
static int
hs_stop(iface)
struct iface *iface;
{
	int dev;

	dev = iface->dev;
	if(dev & 1)
		return -1;	/* Valid only for the first device */
	dev >>= 1;	/* Convert back into hs number */

	/* Turn off interrupts */
	maskoff(Hs[dev].vec);

	/* Restore original interrupt vector */
	setirq(Hs[dev].vec,Hs[dev].save.vec);

	/* Force hardware reset */
	write_scc(Hs[dev].addr + CHANA+CTL,R9,FHWRES);
	return 0;
}
/* Send raw packet */
static int
hs_raw(
struct iface *iface,
struct mbuf **bpp
){

	struct hdlc *hp;
	struct mbuf *nbp;
	register uint16 cnt;
	register uint8 *cp;
	uint16 ctl,data;

	dump(iface,IF_TRACE_OUT,*bpp);
	iface->rawsndcnt++;
	iface->lastsent = secclock();
	hp = &Hdlc[iface->dev];
	hp->txpkts++;

	ctl = hp->ctl;
	data = hp->data;

	cnt = len_p(*bpp);
	/* If buffer isn't contiguous (which is almost always
	 * the case) copy it to a new buffer for speed
	 */
	if((*bpp)->next != NULL){
		if((nbp = copy_p(*bpp,cnt)) == NULL){
			hp->nomem++;
			free_p(bpp);
			return -1;
		}
		free_p(bpp);
		*bpp = nbp;
	}
	cp = (*bpp)->data;
	/* Turn transmitter on */
	hstxon(hp);
	/* Initialize transmitter CRC */
	write_scc(ctl,R0,RES_Tx_CRC);
	for(;;){
		/* Wait for the transmitter to become ready */
		while(!(inportb(ctl) & Tx_BUF_EMP))
			;
		if(cnt-- == 0)
			break;
		outportb(data,*cp++); /* Send the character */
	}
	write_scc(ctl,R0,RES_EOM_L);	/* Allow CRC generation */
	/* End of frame. Wait for TxEOM to go high, indicating start of
	 * CRC transmission. Note that we don't reset the transmit
	 * interrupt pending flag as one ordinarily would, since we're
	 * not using tx interrupts.
	 */
	while(!(inportb(ctl) & TxEOM))
		;

	free_p(bpp);
	hstxoff(hp);	/* Shut down tx */
	/* Hold off to give other guy a chance to
	 * respond
	 */
	hp->deftime = msclock() + hp->txdelay + 500;
	return 0;
}

/* Turn on high speed transmitter. Does p-persistence, then sends a dummy
 * frame to allow for keyup delay. Returns with transmitter on and interrupts
 * disabled
 */
static void
hstxon(hp)
struct hdlc *hp;
{
	uint16 ctl;
	int i;
	long ca;
	int32 t;

	ctl = hp->ctl;

	/* Defer logic. Wait until deftime is in the past (so we
	 * defer to any overheard CTS messages) AND the p-persistence
	 * dice roll succeeds. The computation of ca allows for clock
	 * rollover (which happens every 49+ days).
	 */
	for(;;){
		t = msclock();
		ca = hp->deftime - t;
		if(ca > 0){
			ppause(ca);
			continue;
		}
		hp->deftime = t;	/* Keep from getting too old */
		if((rand() & 0xff) > hp->p){
			ppause((long)MSPTICK);
			continue;
		}
		break;
	}
	/* Prevent distractions. In particular, block off the DCD interrupt
	 * so we don't hear our own carrier and hang in the interrupt handler!
	 * Note that simply disabling CPU interrupts isn't enough since
	 * the call to ppause will block and the kernel will re-enable
	 * them.
	 */
	write_scc(ctl,R9,0);	/* Disable all SCC interrupts */
	disable();

	/* Turn on carrier, enable transmitter */
	write_scc(ctl,R5,TxCRC_ENAB | RTS | TxENAB | Tx8 | DTR);

	/* Delay for keyup interval */
	for(i=hp->txdelay;i != 0;i--)
		msdelay();

}
/* Turn transmitter off at the end of a series of frames */
static void
hstxoff(hp)
struct hdlc *hp;
{
	int cnt;
	uint16 ctl,data;

	ctl = hp->ctl;
	data = hp->data;
	/* To allow the SCC buffering to drain, we begin a dummy frame,
	 * then abort it
	 */
	for(cnt=5;cnt != 0;cnt--){
		while(!(inportb(ctl) & Tx_BUF_EMP))
			;
		outportb(data,0);
	}
	write_scc(ctl,R0,SEND_ABORT);

	/* Turn off carrier and disable transmitter */
	write_scc(ctl,R5,TxCRC_ENAB | Tx8 | DTR);
	/* Re-Enable SCC interrupts */
	write_scc(ctl,R9,MIE|NV);		
	enable();	/* Turn interrupts back on */
}

int
dohs(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	register int i;
	register struct hdlc *hp;

	for(i=0;i<2*Nhs;i++){
		hp = &Hdlc[i];
		printf("port %d: txpkts %lu ints %lu rxpkts %lu rxbytes %lu nomem %lu toobig %lu crcerr %lu aborts %lu overrun %lu\n",
		 i,hp->txpkts,hp->exints,hp->good,hp->rxbytes,
		 hp->nomem,hp->toobig,hp->crcerr,hp->aborts,
		 hp->overrun);
	}
	return 0;
}
static int32
hs_ctl(iface,cmd,set,val)
struct iface *iface;
int cmd;
int set;
int32 val;
{
	register struct hdlc *hp;
	int32 t,ca;

	hp = &Hdlc[iface->dev];
	switch(cmd){
	case PARAM_TXDELAY:	/* Tx keyup delay */
		if(set)
			hp->txdelay = val;
		return hp->txdelay;
	case PARAM_PERSIST:
		if(set)
			hp->p = val;
		return hp->p;
	case PARAM_MUTE:
		/* Mute transmitter for specified # of ms */
		if(set){
			if(val == -1){
				/* Special case for duration of a CTS */
				val = hp->txdelay + 500;
			}
			hp->deftime = msclock() + val;
		}
		t = msclock();
		ca = hp->deftime - t;
		if(ca < 0){
			hp->deftime = t;
			ca = 0;
		}
		return ca;
	}
	return -1;
}
#ifdef	notdef		/* replaced with assembler in 8530.asm */
/* Read data from the 8530 receiver.
 * Returns when either a good frame is received, or when carrier drops.
 * If a good frame is received, the length is returned; otherwise -1.
 */
int
rx8530(ctl,data,buf,bufsize)
uint16 ctl,data;
char *buf;
uint16 bufsize;
{
	int cnt = 0;
	register char status;
	char error;
	register char *cp = buf;

	for(;;){
		status = inportb(ctl);
		if(!(status & DCD)){
			cnt = -1;
			break;
		} else if(status & BRK_ABRT){
			cp = buf;
			cnt = 0;
		} else if(status & Rx_CH_AV){
			/* Receive character is ready, get it */
			*cp++ = inportb(data);
			if(++cnt > bufsize){
				/* Buffer overflow, start again */
				write_scc(ctl,R3,ENT_HM|RxENABLE|RxCRC_ENAB|Rx8);
				cp = buf;
				cnt = 0;
			}
		} else if((error = read_scc(ctl,R1)) & END_FR){
			if(!(error & CRC_ERR))
				break;	/* Good frame! */
			/* Bad frame, start again */
			cp = buf;
			cnt = 0;
		}
	}
	return cnt;
}
#endif

static int32 Del_const;

/* Find the value of Del_const that will cause one execution of mloop()
 * to take one millisecond
 */
static void
init_delay()
{
	int32 start,delay;
	register int i,j;
	int success = 0;

	/* Start with small value to make things tolerable on slow machines */
	Del_const = 10;
	printf("Del_const = %lu\n",Del_const);
	/* Limit the number of iterations in case we don't converge */
	for(i=0;i<5;i++){
		start = msclock();
		for(j=0;j<1000;j++)
			msdelay();
		delay = msclock()-start;
		printf("delay %lu\n",delay);
		if(delay == 0){
			/* Too fast for accurate measurement on coarse clk */	
			Del_const *= 10;
			printf("Del_const = %lu\n",Del_const);
			continue;
		}
		Del_const = (Del_const * 1000)/delay;
		printf("Del_const = %lu\n",Del_const);
		if(delay > 950 && delay < 1050){
			success = 1;
			break;	/* Within 1 tick - Close enough */
		}
	}
	if(!success)
		printf("HS: Warning: auto delay set failed\n");
}
/* Delay for one millisecond (once calibrated by init_delay()) */
static void
msdelay()
{
	int32 i;

	for(i=Del_const;i !=0;i--)
		;
}

⌨️ 快捷键说明

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