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

📄 drsi.c

📁 用于底层开发的TCPIP协议栈源代码
💻 C
📖 第 1 页 / 共 2 页
字号:

	/* See if theres anything left to send - if there is,  send it ! */
	if((hp->sndbuf = dequeue(&hp->sndq)) == NULL){
		/* Nothing left to send - return to receive */
		write_scc(base, R5, Tx8|DTR);   /* Tx off now */
		write_scc(base, R0, ERR_RES);   /* Reset error bits */
		hp->tstate = IDLE;
		hp->tx_state = drtx_idle;
		hp->rstate = ENABLE;
		hp->rx_state = drrx_enable;
		drrx_enable(hp);
	} else
		drtx_tfirst(hp);

}
    
/* Write CTC register */
static void
write_ctc(base, reg, val)
uint16 base;
uint8 reg,val;
{
	int i_state;
	
	i_state = dirps();
	/* Select register */
	outportb(base+Z8536_MASTER,reg);
	outportb(base+Z8536_MASTER,val);
	restore(i_state);
}

/* Read CTC register */
static char
read_ctc(base, reg)
uint16 base;
uint8 reg;
{
	uint8 c;
	uint16 i;
	int i_state;
	
	i_state = dirps();
	/* Select register */
        outportb(base+Z8536_MASTER,reg);
	/* Delay for a short time to allow 8536 to settle */
	for(i=0;i<100;i++)
		;
	c = inportb(base+Z8536_MASTER);
	restore(i_state);
	return(c);
}

/* Initialize dr controller parameters */
static int
drchanparam(hp)
register struct drchan *hp;
{
	uint16 tc;
	long br;
	register uint16 base;
	int i_state;

	/* Initialize 8530 channel for SDLC operation */
	base = hp->base;
	i_state = dirps();

	switch(base & 2){
	case 2:
		write_scc(base,R9,CHRA);	/* Reset channel A */
		break;
	case 0:
		write_scc(base,R9,CHRB);	/* Reset channel B */
		break;
	}
	/* Deselect all Rx and Tx interrupts */
	write_scc(base,R1,0);

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

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

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

	/* Set up BRG and DPLL multiplexers */
	/* Tx Clk from RTxC. Rcv Clk from DPLL, TRxC pin outputs BRG */
	write_scc(base,R11,RCDPLL|TCRTxCP|TRxCOI|TRxCBR);

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

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

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

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

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

	/* set the 32x time constant for the BRG */

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

	write_scc(base,R12,tc);      /* lower byte */
	write_scc(base,R13,(tc>>8)); /* upper bite */

	/* Time to set up clock control register for RECEIVE mode
	 * DRSI has xtal osc going to pclk at 4.9152 Mhz
	 * The BRG is sourced from that, and set to 32x clock
	 * The DPLL is sourced from the BRG.  BRG is fed to the TRxC pin
	 * Transmit clock is provided by the BRG externally divided by
	 * 32 in the CTC counter 1 and 2.
	 * Receive clock is from the DPLL
	 */

	/* Following subroutine sets up and ENABLES the receiver */
	drrx_enable(hp);
	
	/* DPLL from BRG, BRG source is PCLK */
	write_scc(hp->base,R14,BRSRC|SSBR);
	/* SEARCH mode, keep BRG source */
	write_scc(hp->base,R14,BRSRC|SEARCH);
	/* Enable the BRG */
	write_scc(hp->base,R14,BRSRC|BRENABL);

	/* enable the receive interrupts */

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


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

	restore(i_state);
	return 0;
}

/*
 * Initialize the CTC (8536)
 * Only the counter/timers are used - the IO ports are un-comitted.
 * Channels 1 and 2 are linked to provide a /32 counter to convert
 * the SIO BRG to a real clock for Transmit clocking.
 * CTC 3 is left free running on a 10 mS period.  It is always polled
 * and therefore all interrupts from the chip are disabled.
 *
 * Updated 02/16/89 by N6TTO
 * Changed to support the use of the second channel on the 8530.
 * Added so that the driver works on the DRSI type 2 PC Adaptor
 * which has 2 1200 bps modems.
 *
 */
static void
drinitctc(port)
unsigned port;
{
	long i;

	/* Initialize 8536 CTC */

	/* Initialize 8536 */
	/* Start by forcing chip into known state */
	(void) read_ctc(port, Z8536_MICR);

	write_ctc(port, Z8536_MICR, 0x01);	/* Reset the CTC */
	for(i=0;i < 1000L; i++)		/* Loop to delay */
		;
	write_ctc(port, Z8536_MICR, 0x00);	/* Clear reset and start init seq. */

	/* Wait for chip to come ready */
	while((read_ctc(port, Z8536_MICR)) != 0x02)
		;

	write_ctc(port, Z8536_MICR, 0xa6);	/* MIE|NV|CT_VIS|RJA */
	write_ctc(port, Z8536_MCCR, 0xf4);	/* PBE|CT1E|CT2E|CT3E|PAE */

	write_ctc(port, Z8536_CTMS1, 0xe2);	/* Continuous,EOE,ECE, Pulse output */
	write_ctc(port, Z8536_CTMS2, 0xe2);	/* Continuous,EOE,ECE, Pulse output */
	write_ctc(port, Z8536_CTMS3, 0x80);	/* Continuous,Pulse output */
	write_ctc(port, Z8536_CT1MSB, 0x00);	/* Load time constant CTC #1 */
	write_ctc(port, Z8536_CT1LSB, 0x10);
	write_ctc(port, Z8536_CT2MSB, 0x00);	/* Load time constant CTC #2 */
	write_ctc(port, Z8536_CT2LSB, 0x10);
	write_ctc(port, Z8536_CT3MSB, 0x60);	/* Load time constant CTC #3 */
	write_ctc(port, Z8536_CT3LSB, 0x00);

	write_ctc(port, Z8536_IVR, 0x06);

	/* Set port direction bits in port A and B
	 * Data is input on bits d1 and d5, output on d0 and d4.
	 * The direction is set by 1 for input and 0 for output
	 */
	write_ctc(port, Z8536_PDCA, 0x22);
	write_ctc(port, Z8536_PDCB, 0x22);

	write_ctc(port, Z8536_CSR1, Z_GCB|Z_TCB);  /* Start CTC #1 running */
	write_ctc(port, Z8536_CSR2, Z_GCB|Z_TCB);  /* Start CTC #2 running */
	write_ctc(port, Z8536_CSR3, Z_IE|Z_GCB|Z_TCB); /* Start CTC #3 running */
}

/* Attach a DRSI interface to the system
 * argv[0]: hardware type, must be "drsi"
 * argv[1]: I/O address, e.g., "0x300"
 * argv[2]: vector, e.g., "2"
 * argv[3]: mode, must be "ax25"
 * argv[4]: iface label, e.g., "dr0"
 * argv[5]: receiver packet buffer size in bytes
 * argv[6]: maximum transmission unit, bytes
 * argv[7]: iface speed for channel A
 * argv[8]: iface speed for channel B (defaults to same as A if absent)
 * argv[9]: First IP address, optional (defaults to Ip_addr)
 * argv[10]: Second IP address, optional (defaults to Ip_addr)
 */
int
dr_attach(argc,argv)
int argc;
char *argv[];
{
	register struct iface *if_pca,*if_pcb;
	struct drchan *hp;
	int dev;
	char *cp;

	/* Quick check to make sure args are good and mycall is set */
	if(setencap(NULL,argv[3]) == -1){
		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(Drnbr >= DRMAX){
		printf("Only %d DRSI controller(s) supported right now!\n",DRMAX);
		return -1;
	}
	dev = Drnbr++;

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

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

	/* Set new interrupt vector */
	if(setirq(Drsi[dev].vec,Drhandle[dev]) == -1){
		printf("IRQ %u out of range\n",Drsi[dev].vec);
		Drnbr--;
	}	
	/* Initialize the CTC */
	drinitctc(Drsi[dev].addr);
	
	/* Create iface 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 > 9)
		if_pca->addr = resolve(argv[9]);
	if(argc > 10)
		if_pcb->addr = resolve(argv[10]);
	if(if_pca->addr == 0 || if_pcb->addr == 0){
		printf(Noipaddr);
		free(if_pca);
		free(if_pcb);
		return -1;
	}
	/* Append "a" to iface 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 = dr_ctl;
	if_pca->dev = 2*dev;			/* dr0a */
	if_pcb->dev = 2*dev + 1;		/* dr0b */
	if_pcb->stop = if_pca->stop = dr_stop;
	if_pcb->raw = if_pca->raw = dr_raw;

	setencap(if_pca,argv[3]);
	setencap(if_pcb,argv[3]);
	if(if_pcb->hwaddr == NULL)
		if_pcb->hwaddr = mallocw(sizeof(Mycall));
	memcpy(if_pcb->hwaddr,&Mycall,sizeof(Mycall));
	if(if_pca->hwaddr == NULL)
		if_pca->hwaddr = mallocw(sizeof(Mycall));
	memcpy(if_pca->hwaddr,&Mycall,sizeof(Mycall));
	/* Link em in to the iface chain */
	if_pca->next = if_pcb;
	if_pcb->next = Ifaces;
	Ifaces = if_pca;

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

	hp = &Drchan[2*dev+1];				/* dr1 is offset 1 */
	hp->iface = if_pcb;
	hp->stata = Drsi[dev].addr + CHANA + CTL;	/* permanent status */
	hp->statb = Drsi[dev].addr + CHANB + CTL;	/* addrs for CHANA/B*/
	if(argc > 8){
		/* Separate speed for channel B */
		hp->speed = (uint16)atoi(argv[8]);
	} else {
		/* Set speed to same as for channel A */
		hp->speed = (uint16)atoi(argv[7]);
	}
	hp->base = Drsi[dev].addr + CHANB;
	hp->bufsiz = atoi(argv[5]);
	hp->drtx_buffer = mallocw(if_pcb->mtu+100);
	hp->tstate = IDLE;
	hp->tx_state = drtx_idle;
	hp->w[RX].wcall = NULL;
	hp->w[RX].wakecnt = 0;
	hp->w[TX].wcall = NULL;
	hp->w[TX].wakecnt = 0;
	/* default KISS Params */
	hp->txdelay = 25;		/* 250 Ms */
	hp->persist = 64;		/* 25% persistence */
	hp->slotime = 10;		/* 100 Ms */
	hp->squeldelay = 20;		/* 200 Ms */
	hp->enddelay = 10;		/* 100 Ms */
	
	write_scc(hp->stata,R9,FHWRES);		/* Hardware reset */
	
	/* Disable interrupts with Master interrupt ctrl reg */
	write_scc(hp->stata,R9,0);

	drchanparam(hp); 

	/* Initialize buffer pointers */
	hp->rcvbuf = NULL;
	hp->rcvbuf->cnt = 0;
	hp->sndq = NULL;
	
	/* set params in drchan table for CHANNEL A */
	hp = &Drchan[2*dev];			/* dr0a is offset 0 */
	hp->iface = if_pca;
	hp->speed = (uint16)atoi(argv[7]);
	hp->base = Drsi[dev].addr + CHANA;
	hp->bufsiz = atoi(argv[5]);
	hp->drtx_buffer = mallocw(if_pca->mtu+100);
	hp->tstate = IDLE;
	hp->tx_state = drtx_idle;
	hp->w[RX].wcall = NULL;
	hp->w[RX].wakecnt = 0;
	hp->w[TX].wcall = NULL;
	hp->w[TX].wakecnt = 0;
	/* default KISS Params */
	hp->txdelay = 30;		/* 300 Ms */
	hp->persist = 64;		/* 25% persistence */
	hp->slotime = 10;		/* 100 Ms */
	hp->squeldelay = 20;		/* 200 Ms */
	hp->enddelay = 10;		/* 100 Ms */

	drchanparam(hp);

	/* Initialize buffer pointers */
	hp->rcvbuf = NULL;
	hp->rcvbuf->cnt = 0;
	hp->sndq = NULL;

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

	/* Enable interrupt in 8259 interrupt controller */
	maskon(Drsi[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 iface */
static int
dr_stop(iface)
struct iface *iface;
{
	uint16 dev;

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

	/* Set 8259 interrupt mask (turn off interrupts) */
	maskoff(Drsi[dev].vec);

	/* Restore original interrupt vector */
	setirq(Drsi[dev].vec, Drsi[dev].oldvec);
	Drnbr--;
	
	/* Force hardware reset */
	write_scc(Drsi[dev].addr + CHANA + CTL,R9,FHWRES);
	/* Reset the CTC */
	(void) read_ctc(Drsi[dev].addr, Z8536_MICR);
	write_ctc(Drsi[dev].addr, Z8536_MICR, 0x01);
	return 0;
}

/* Send raw packet on DRSI card */
static int
dr_raw(
struct iface *iface,
struct mbuf **bpp
){
	char kickflag;
	struct drchan *hp;
	int i_state;

	dump(iface,IF_TRACE_OUT,*bpp);
	iface->rawsndcnt++;
	iface->lastsent = secclock();

	hp = &Drchan[iface->dev];
	i_state = dirps();
	kickflag = (hp->sndq == NULL) & (hp->sndbuf == NULL);
	/* clever! flag=1 if something in queue */
	enqueue(&hp->sndq,bpp);

	if(kickflag)			/* simulate interrupt to xmit */
		tx_fsm(hp);		/* process interrupt */

	restore(i_state);
	return 0;
}

/* display DRSI Channel stats */
int
dodrstat(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	struct drchan *hp0, *hp1;
	int i;

	for(i=0; i<DRMAX; i++){
		hp0 = &Drchan[i];
		hp1 = &Drchan[i+1];
		i = Drchan[i].base;
		printf("DRSI Board Statistics - N6TTO 112790.0\n");
		printf("--------------------------------------\n");
		printf("Channel - %s\n", hp0->iface->name);
		printf("Rxints  - %8ld  Txints  - %8ld  Exints  - %8ld\n",
			hp0->rxints, hp0->txints, hp0->exints);
		printf("Enqued  - %8ld  Crcerr  - %8ld  Aborts  - %8ld\n",
			hp0->enqueued, hp0->crcerr, hp0->aborts);
		printf("RFrames - %8ld  Rxovers - %8ld  TooBig  - %8ld\n",
			hp0->rxframes, hp0->rovers, hp0->toobig);
		printf("Txdefer - %8ld  Txppers - %8ld  Nomem   - %8ld\n",
			hp0->txdefers, hp0->txppersist, hp0->nomem);
		printf("Tx state  %8d  Rx state  %8d\n\n",hp0->tstate,hp0->rstate);
		printf("Channel - %s\n", hp1->iface->name);
		printf("Rxints  - %8ld  Txints  - %8ld  Exints  - %8ld\n",
			hp1->rxints, hp1->txints, hp1->exints);
		printf("Enqued  - %8ld  Crcerr  - %8ld  Aborts  - %8ld\n",
			hp1->enqueued, hp1->crcerr, hp1->aborts);
		printf("RFrames - %8ld  Rxovers - %8ld  TooBig  - %8ld\n",
			hp1->rxframes, hp1->rovers, hp1->toobig);
		printf("Txdefer - %8ld  Txppers - %8ld  Nomem   - %8ld\n",
			hp1->txdefers, hp1->txppersist, hp1->nomem);
		printf("Tx state  %8d  Rx state  %8d\n",hp1->tstate,hp1->rstate);
	}
	return 0;
}

/* Subroutine to set kiss params in channel tables */
static int32
dr_ctl(iface,cmd,set,val)
struct iface *iface;
int cmd;
int set;
int32 val;
{
	struct drchan *hp;
	hp = &Drchan[iface->dev];

	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;
	case PARAM_ENDDELAY:
		if(set)
			hp->enddelay = val;
		return hp->enddelay;
	case PARAM_SPEED:
		return hp->speed;
	}
	return -1;
}

⌨️ 快捷键说明

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