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

📄 drsi.c

📁 完整的TCPIP!验证过的!
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * TX finite state machine - dispatcher
 */
static void
tx_fsm(hp)
struct drchan *hp;
{
	int i_state;

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

/* drtx_idle
 * Transmit IDLE transmit state processor
 */
static void
drtx_idle(hp)
struct drchan *hp;
{
	register uint16 base;

	/* Tx idle - is there a frame to transmit ? */
	if((hp->sndbuf = dequeue(&hp->sndq)) == NULL){
		/* Nothing to send - return to receive mode
		 * Turn Tx off - any trailing flag should have been sent
		 * by now
		 */
#ifdef DRSIDEBUG
		printf("Nothing to TX\n");
#endif
		base = hp->base;
		write_scc(base, R5, Tx8|DTR);   /* Tx off now */
		write_scc(base, R0, ERR_RES);	/* Reset error bits */

		/* Delay for squelch tail before enabling receiver */
		hp->rstate = ENABLE;
		hp->rx_state = drrx_enable;
		dr_wake(hp, RX, rx_fsm, hp->squeldelay);
	} else {
		/* Frame to transmit */
		hp->tstate = DEFER;
		hp->tx_state = drtx_defer;
		drtx_defer(hp);
	}
}

/* drtx_defer
 * Transmit DEFER state processor
 */
static void
drtx_defer(hp)
struct drchan *hp;
{
	register uint16 base = hp->base;

	/* We may have defered a previous tx attempt - in any event...
	 * Check DCD in case someone is already transmitting
	 * then check to see if we should defer due to P-PERSIST.
	 */

#ifdef DRSIDEBUG
	printf("drtx_defer - checking for DCD\n");
#endif
	if((read_scc(base+CTL, R0) & DCD) > 0){
		/* Carrier detected - defer */
		hp->txdefers++;
		dr_wake(hp, TX, tx_fsm, 10);	/* Defer for 100 mS */
#ifdef DRSIDEBUG
		printf("drtx_defer - TX deferred\n");
#endif
		return;
	}

#ifdef DRSIDEBUG
	printf("drtx_defer - checking for P-PERSIST backoff\n");
#endif
	/* P-PERSIST is checked against channel 3 of the 8536 which is
	 * the free running counter for the 10 mS tick; The counter
	 * goes through 0x6000 ticks per 10 mS or one tick every
	 * 407 nS - this is pretty random compared to the DOS time of
	 * day clock (0x40:0x6C) used by the other (EAGLE) drivers.
	 */
        if (hp->persist <= read_ctc(base,Z8536_CC3LSB)) {
#ifdef DRSIDEBUG
	    printf("drtx_defer - BACKOFF\n");
#endif
	    hp->txppersist++;
	    dr_wake (hp, TX, tx_fsm, hp->slotime);
	    return;
	}
	/* No backoff - set RTS and start to transmit frame */
	write_scc(base, R1, 0);		/* Prevent external status int */
	write_scc(base, R3, Rx8);	/* Turn Rx off */
	hp->rstate = IDLE;		/* Mark Rx as idle */
	hp->tstate = RRTS;
	hp->tx_state = drtx_rrts;
#ifdef DRSIDEBUG
	printf("drtx_defer - wake posted for drtx_rrts\n");
#endif
	write_scc(base, R9, 0);		/* Interrupts off */
	write_scc(base,R5,RTS|Tx8|DTR);	/* Turn tx on */
	dr_wake(hp, TX, tx_fsm, 10);
}

/* drtx_rrts
 * Transmit RRTS state processor
 */
static void
drtx_rrts(hp)
struct drchan *hp;
{
	register uint16 base = hp->base;

	write_scc(base, R9, 0);	/* Interrupts off */
	write_scc(base,R5,TxCRC_ENAB|RTS|TxENAB|Tx8|DTR);	/* Tx now on */
	hp->tstate = TFIRST;
	hp->tx_state = drtx_tfirst;
#ifdef DRSIDEBUG
	printf("8530 Int status %x\n", read_scc(base+CHANA,R3)); 
	printf("drtx_rrts - Wake posted for TXDELAY\n");
#endif
	dr_wake(hp, TX, tx_fsm, hp->txdelay);
}
    
/* drtx_tfirst
 * Transmit TFIRST state processor
 */
static void
drtx_tfirst(hp)
struct drchan *hp;
{
	register uint16 base = hp->base;
	char c;
	
	/* Copy data to a local buffer to save on mbuf overheads
	 * during transmit interrupt time.
	 */
	hp->drtx_cnt = len_p(hp->sndbuf);
	hp->drtx_tcp = hp->drtx_buffer;
	
	pullup(&hp->sndbuf, hp->drtx_tcp, hp->drtx_cnt);
	
	/* Transmit the first character in the buffer */
	c = *hp->drtx_tcp++;
	hp->drtx_cnt--;

	write_scc(base, R0, RES_Tx_CRC);	/* Reset CRC */
	write_scc(base, R0, RES_EOM_L);		/* Reset underrun latch */
	outportb(base+DATA, c);			/* Output first character */
	write_scc(base, R15, TxUIE);		/* Allow underrun ints only */
	write_scc(base, R1, TxINT_ENAB|EXT_INT_ENAB); /* Tx/Ext status ints on */
	write_scc(base, R9, MIE|NV);		/* master enable */
	hp->tstate = ACTIVE;
	hp->tx_state = drtx_active;
}

/* drtx_active
 * Transmit ACTIVE state processor
 */
static void
drtx_active(hp)
struct drchan *hp;
{
	if(hp->drtx_cnt-- > 0){
		/* Send next character */
		outportb(hp->base+DATA, *hp->drtx_tcp++);
	} else {
		/* No more to send - wait for underrun to hit */
		hp->tstate = UNDERRUN;
		hp->tx_state = drtx_flagout;
		free_p(&hp->sndbuf);
		write_scc(hp->base, R0, RES_EOM_L);  /* Send CRC on underrun */
		write_scc(hp->base, R0, RES_Tx_P);   /* Reset Tx Int pending */
	}
}

/* drtx_flagout
 * Transmit FLAGOUT state processor
 */
static void
drtx_flagout(hp)
struct drchan *hp;
{
	/* Arrive here after CRC sent and Tx interrupt fires.
	 * Post a wake for ENDDELAY
	 */

	hp->tstate = UNDERRUN;
	hp->tx_state = drtx_downtx;
	write_scc(hp->base, R9, 0);
	write_scc(hp->base, R0,  RES_Tx_P);
	dr_wake(hp, TX, tx_fsm, hp->enddelay);
}

/* drtx_downtx
 * Transmit DOWNTX state processor
 */
static void
drtx_downtx(hp)
struct drchan *hp;
{
	register int base = hp->base;

	/* 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)

⌨️ 快捷键说明

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