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

📄 eagle.c

📁 很好的TCP_IP协议源代码分析,很适用很好
💻 C
📖 第 1 页 / 共 2 页
字号:
	long br;
	register uint16 base;
	int i_state;

	/* Initialize 8530 channel for SDLC operation */

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

	switch(base & 2){
	case 2:
		write_scc(CTL+base,R9,CHRA);	/* Reset channel A */
		break;
	case 0:
		write_scc(CTL+base,R9,CHRB);	/* Reset channel B */
		break;
	}

	/* Deselect all Rx and Tx interrupts */
	write_scc(CTL+base,R1,0);

	/* Turn off external interrupts (like CTS/CD) */
	write_scc(CTL+base,R15,0);

	/* X1 clock, SDLC mode */
	write_scc(CTL+base,R4,SDLC|X1CLK);	       /* SDLC mode and X1 clock */

	/* Now some misc Tx/Rx parameters */
	/* CRC PRESET 1, NRZI Mode */
	write_scc(CTL+base,R10,CRCPS|NRZI);

	/* Set up BRG and DPLL multiplexers */
	/* Tx Clk from BRG. Rcv Clk from DPLL, TRxC pin outputs DPLL */
	write_scc(CTL+base,R11,TCBR|RCDPLL|TRxCDP|TRxCOI);

	/* Null out SDLC start address */
	write_scc(CTL+base,R6,0);

	/* SDLC flag */
	write_scc(CTL+base,R7,FLAG);

	/* Set up the Transmitter but don't enable it */
	/*  DTR, 8 bit TX chars only - TX NOT ENABLED */
	write_scc(CTL+base,R5,Tx8|DTR);

	/* Receiver - intial setup only - more later */
	write_scc(CTL+base,R3,Rx8); 	       /* 8 bits/char */

	/* Setting up BRG now - turn it off first */
	write_scc(CTL+hp->base,R14,BRSRC);	     /* BRG off, but keep Pclk source */

	/* set the 32x time constant for the BRG in Receive mode */

	br = hp->speed; 			/* get desired speed */
	tc = ((XTAL/32)/br)-2;			/* calc 32X BRG divisor */

	write_scc(CTL+hp->base,R12,tc&0xFF);      /* lower byte */
	write_scc(CTL+hp->base,R13,(tc>>8)&0xFF); /* upper bite */

	/* Time to set up clock control register for RECEIVE mode
	 * Eagle has xtal osc going to pclk at 3.6864 Mhz
	 * The BRG is sourced from that, and set to 32x clock
	 * The DPLL is sourced from the BRG, and feeds the TRxC pin
	 * Transmit clock & Receive clock come from DPLL
	 */

	/* Following subroutine sets up and ENABLES the receiver */
	rts(hp,OFF);		   /* TX OFF and RX ON */

	write_scc(CTL+hp->base,R14,BRSRC|SSBR);	   /* DPLL from BRG, BRG source is PCLK */
	write_scc(CTL+hp->base,R14,BRSRC|SEARCH);	   /* SEARCH mode, keep BRG source */

	write_scc(CTL+hp->base,R14,BRSRC|BRENABL);	/* Enable the BRG */

	/* enable the receive interrupts */

	write_scc(CTL+hp->base,R1,(INT_ALL_Rx|EXT_INT_ENAB));
	write_scc(CTL+hp->base,R15,BRKIE);	    /* ABORT int */
	write_scc(CTL+hp->base,R9,MIE|NV);	/* master enable */

	/* enable interrupt latch on board */
	outportb(hp->dmactrl,INTENABLE);

	/* Now, turn on the receiver and hunt for a flag */
	write_scc(CTL+hp->base,R3,RxENABLE|RxCRC_ENAB|Rx8);

	restore(i_state);
}

/* Attach a EAGLE interface to the system
 * argv[0]: hardware type, must be "eagle"
 * argv[1]: I/O address, e.g., "0x300"
 * argv[2]: vector, e.g., "2"
 * argv[3]: mode, must be:
 *	    "ax25" (AX.25 UI frame format)
 * argv[4]: interface label, e.g., "eg0"
 * argv[5]: receiver packet buffer size in bytes
 * argv[6]: maximum transmission unit, bytes
 * argv[7]: interface speed, e.g, "1200"
 * argv[8]: First IP address, optional (defaults to Ip_addr);
 * argv[9]: Second IP address, optional (defaults to Ip_addr);
 */
int
eg_attach(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	register struct iface *if_pca,*if_pcb;
	struct egchan *hp;
	int dev;
	char *cp;

	/* Quick check to make sure args are good and mycall is set */
	if(strcmp(argv[3],"ax25") != 0){
		printf("Mode %s unknown for interface %s\n",
			argv[3],argv[4]);
		return -1;
	}
	if(if_lookup(argv[4]) != NULL){
		printf("Interface %s already exists\n",argv[4]);
		return -1;
	}
	if(Mycall[0] == '\0'){
		printf("set mycall first\n");
		return -1;
	}
	/* Note: More than one card can be supported if you give up a COM:
	 * port, thus freeing up an IRQ line and port address
	 */

	if(Egnbr >= EGMAX) {
		printf("Only 1 EAGLE controller supported right now!\n");
		return -1;
	}
	if(setencap(NULL,argv[3]) == -1){
		printf("Unknown encapsulation %s\n",argv[3]);
		return -1;
	}
	dev = Egnbr++;

	/* Initialize hardware-level control structure */
	Eagle[dev].addr = htoi(argv[1]);
	Eagle[dev].vec = atoi(argv[2]);
	if(strchr(argv[2],'c') != NULL)
		Eagle[dev].chain = 1;
	else
		Eagle[dev].chain = 0;


	/* Save original interrupt vector */
	Eagle[dev].oldvec = getirq(Eagle[dev].vec);

	/* Set new interrupt vector */
	if(setirq(Eagle[dev].vec,eghandle[dev]) == -1){
		printf("IRQ %u out of range\n",Eagle[dev].vec);
		Egnbr--;
		return -1;
	}
	/* Create interface structures and fill in details */
	if_pca = (struct iface *)callocw(1,sizeof(struct iface));
	if_pcb = (struct iface *)callocw(1,sizeof(struct iface));

	if_pca->addr = if_pcb->addr = Ip_addr;
	if(argc > 8)
		if_pca->addr = resolve(argv[8]);
	if(argc > 9)
		if_pcb->addr = resolve(argv[9]);

	if(if_pca->addr == 0 || if_pcb->addr == 0){
		printf(Noipaddr);
		free(if_pca);
		free(if_pcb);
		return -1;
	}
	/* Append "a" to interface associated with A channel */
	if_pca->name = mallocw((unsigned)strlen(argv[4])+2);
	strcpy(if_pca->name,argv[4]);
	strcat(if_pca->name,"a");
	/* Append "b" to iface associated with B channel */
	if_pcb->name = mallocw((unsigned)strlen(argv[4])+2);
	strcpy(if_pcb->name,argv[4]);
	strcat(if_pcb->name,"b");

	if_pcb->mtu = if_pca->mtu = atoi(argv[6]);
	if_pcb->ioctl = if_pca->ioctl = eg_ctl;
	if_pca->dev = 2*dev;			/* eg0a */
	if_pcb->dev = 2*dev + 1;		/* eg0b */
	if_pcb->stop = if_pca->stop = eg_stop;
	if_pcb->raw = if_pca->raw = eg_raw;

	/* Must work, was checked at top */
	setencap(if_pca,argv[3]);
	setencap(if_pcb,argv[3]);
	if(if_pcb->hwaddr == NULL)
		if_pcb->hwaddr = mallocw(AXALEN);
	memcpy(if_pcb->hwaddr,Mycall,AXALEN);
	if(if_pca->hwaddr == NULL)
		if_pca->hwaddr = mallocw(AXALEN);
	memcpy(if_pca->hwaddr,Mycall,AXALEN);

	/* Link em in to the interface chain */
	if_pca->next = if_pcb;
	if_pcb->next = Ifaces;
	Ifaces = if_pca;

	/* set params in egchan table for CHANNEL B */

	hp = &Egchan[2*dev+1];				/* eg1 is offset 1 */
	hp->iface = if_pcb;
	hp->stata = Eagle[dev].addr + CHANA + CTL;	/* permanent status */
	hp->statb = Eagle[dev].addr + CHANB + CTL;	/* addrs for CHANA/B*/
	hp->dmactrl = Eagle[dev].addr + DMACTRL;	/* Eagle control reg */
	hp->speed = (uint16)atoi(argv[7]);
	hp->base = Eagle[dev].addr + CHANB;
	hp->bufsiz = atoi(argv[5]);
	hp->tstate = IDLE;
	/* default KISS Params */
	hp->txdelay = 25;		/* 250 Ms */
	hp->persist = 64;		/* 25% persistence */
	hp->slotime = 10;		/* 100 Ms */
	hp->squeldelay = 20;		/* 200 Ms */

	write_scc(CTL+hp->stata,R9,FHWRES); 	/* Hardware reset */
						/* one time only */
	/* Disable interrupts with Master interrupt ctrl reg */
	write_scc(CTL+hp->stata,R9,0);

	egchanparam(hp);

	/* Pre-allocate a receive buffer */
	hp->rcvbuf = alloc_mbuf(hp->bufsiz);
	if(hp->rcvbuf == NULL) {
	    /* No memory, abort receiver */
	    printf("EGATTACH: No memory available for Receive buffers\n");
	    /* Restore original interrupt vector */
	    setirq(Eagle[dev].vec,Eagle[dev].oldvec);
	    Egnbr--;
	    return(-1);
	}
	hp->rcp = hp->rcvbuf->data;
	hp->rcvbuf->cnt = 0;
	hp->sndq = NULL;

	/* set params in egchan table for CHANNEL A */
	hp = &Egchan[2*dev];			/* eg0a is offset 0 */
	hp->iface = if_pca;
	hp->speed = (uint16)atoi(argv[7]);
	hp->base = Eagle[dev].addr + CHANA;
	hp->bufsiz = atoi(argv[5]);
	hp->tstate = IDLE;
	/* default KISS Params */
	hp->txdelay = 25;		/* 250 Ms */
	hp->persist = 64;		/* 25% persistence */
	hp->slotime = 10;		/* 100 Ms */
	hp->squeldelay = 20;		/* 200 Ms */

	egchanparam(hp);

	/* Pre-allocate a receive buffer */
	hp->rcvbuf = alloc_mbuf(hp->bufsiz);
	if(hp->rcvbuf == NULL) {
		/* No memory, abort receiver */
		printf("EGATTACH: No memory available for Receive buffers\n");
		/* Restore original interrupt vector */
		setirq(Eagle[dev].vec,Eagle[dev].oldvec);
		Egnbr--;
		return -1;
	}
	hp->rcp = hp->rcvbuf->data;
	hp->rcvbuf->cnt = 0;
	hp->sndq = NULL;

	write_scc(CTL+hp->base,R9,MIE|NV);		/* master interrupt enable */

	/* Enable interrupts on the EAGLE card itself */
	outportb(hp->dmactrl,INTENABLE);

	/* Enable interrupt */
	maskon(Eagle[dev].vec);

	cp = if_name(if_pca," tx");
	if_pca->txproc = newproc(cp,512,if_tx,0,if_pca,NULL,0);
	free(cp);
	cp = if_name(if_pcb," tx");
	if_pcb->txproc = newproc(cp,512,if_tx,0,if_pcb,NULL,0);
	free(cp);

	return 0;
}


/* Shut down interface */
static int
eg_stop(iface)
struct iface *iface;
{
	int dev;

	dev = iface->dev;
	if(dev & 1)
		return 0;
	dev >>= 1;	/* Convert back into eagle number */

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

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

	/* Force hardware reset */
	write_scc(CTL+Eagle[dev].addr + CHANA,R9,FHWRES);

	/* resets interrupt enable on eagle card itself */
	outportb(Eagle[dev].addr+DMACTRL,0);
	return 0;
}

/* Send raw packet on eagle card */
static int
eg_raw(
struct iface *iface,
struct mbuf **bpp
){
	char kickflag;
	struct egchan *hp;

	dump(iface,IF_TRACE_OUT,*bpp);
	iface->rawsndcnt++;
	iface->lastsent = secclock();
	hp = &Egchan[iface->dev];
	kickflag = (hp->sndq == NULL) & (hp->sndbuf == NULL);	/* clever! flag=1 if something in queue */
	enqueue(&hp->sndq,bpp);
	if(kickflag)			/* simulate interrupt to xmit */
		egtxint(hp);		/* process interrupt */
	return 0;
}
/* routine to delay n increments of 10 milliseconds
 * about right on a turbo XT - will be slow on 4.77
 * Still looking for a way to use the 8253 timer...
 */
static void
waitmsec(n)
int n;
{
	long i;

	for(i=0L; i < (200L*n); i++)
		;  /* simple loop delay */
}

/* display EAGLE Channel stats */
int
doegstat(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	struct egchan *hp0, *hp1;
	int i;

	for(i=0; i<EGMAX; i++) {
		hp0 = &Egchan[i];
		hp1 = &Egchan[i+1];

		printf("EAGLE Board Statistics:\n\n");
		printf("Base Addr\tRxints\tTxints\tExints\tEnqued\tCrcerr\tAborts\tRxOvers\tRFrames\n");
		printf("---------\t------\t------\t------\t------\t------\t------\t-------\t-------\n");
		printf("0x%x\t\t%ld\t%ld\t%ld\t%d\t%d\t%d\t%d\t%d\nRcv State=%s\n", hp0->base, hp0->rxints,
		    hp0->txints, hp0->exints, hp0->enqueued, hp0->crcerr, hp0->aborts,
		    hp0->rovers,hp0->rxframes,
		    hp0->rstate==0?"IDLE":hp0->rstate==1?"ACTIVE":hp0->rstate==2?"RXERROR":hp0->rstate==3?"RXABORT":"TOOBIG");

		printf("0x%x\t\t%ld\t%ld\t%ld\t%d\t%d\t%d\t%d\t%d\nRcv State=%s\n\n", hp1->base, hp1->rxints,
		    hp1->txints, hp1->exints, hp1->enqueued, hp1->crcerr, hp1->aborts,
		    hp1->rovers,hp1->rxframes,
		    hp1->rstate==0?"IDLE":hp1->rstate==1?"ACTIVE":hp1->rstate==2?"RXERROR":hp1->rstate==3?"RXABORT":"TOOBIG");
	}
	return 0;
}

/* Subroutine to set kiss params in channel tables */
static int32
eg_ctl(iface,cmd,set,val)
struct iface *iface;
int cmd;
int set;
int32 val;
{
	struct egchan *hp;

	hp = &Egchan[iface->dev];	    /* point to channel table */
	switch(cmd){
	case PARAM_TXDELAY:
		if(set)
			hp->txdelay = val;
		return hp->txdelay;
	case PARAM_PERSIST:
		if(set)
			hp->persist = val;
		return hp->persist;
	case PARAM_SLOTTIME:
		if(set)
			hp->slotime = val;
		return hp->slotime;
	case PARAM_TXTAIL:
		if(set)
			hp->squeldelay = val;
		return hp->squeldelay;
	}
	return -1;
}

⌨️ 快捷键说明

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