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

📄 scc.c

📁 用于底层开发的TCPIP协议栈源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		ifp->ioctl = kiss_ioctl;
		ifp->raw = kiss_raw;

		for(xdev = 0;xdev < SLIP_MAX;xdev++){
			if(Slip[xdev].iface == NULL)
				break;
		}
		ifp->xdev = xdev;
		Slip[xdev].iface = ifp;
		Slip[xdev].type = CL_KISS;
		Slip[xdev].send = scc_send;
		Slip[xdev].get = get_scc;
		cp = if_name(ifp," rx");
		ifp->rxproc = newproc(cp,256,slip_rx,xdev,NULL,NULL,0);
		free(cp);
		break;
#endif
#ifdef SLIP
	case 's':	/* slip */
		scc_async(scc);				/* init SCC in async mode */
		brgrate = scc_speed(scc,16,atol(argv[5]));
		scc->speed = Sccinfo.clk / (32L * (brgrate + 2));
		setencap(ifp,"SLIP");
		ifp->ioctl = scc_aioctl;
		ifp->raw = slip_raw;
		for(xdev = 0;xdev < SLIP_MAX;xdev++){
			if(Slip[xdev].iface == NULL)
				break;
		}
		ifp->xdev = xdev;
		Slip[xdev].iface = ifp;
		Slip[xdev].type = CL_SERIAL_LINE;
		Slip[xdev].send = scc_send;
		Slip[xdev].get = get_scc;
		cp = if_name(ifp," rx");

#ifdef VJCOMPRESS
		if((argc > 8) && (strchr(argv[8],'v') != NULL)) {
			Slip[xdev].escaped |= SLIP_VJCOMPR;
			Slip[xdev].slcomp = slhc_init(16,16);

		} else if((argc > 7) && (strchr(argv[7],'v') != NULL)) {
			Slip[xdev].escaped |= SLIP_VJCOMPR;
			Slip[xdev].slcomp = slhc_init(16,16);
		}
#else
		Slip[xdev].slcomp = NULL;
#endif	/* VJCOMPRESS */
		ifp->rxproc = newproc(cp,256,slip_rx,xdev,NULL,NULL,0);
		free(cp);
		break;
#endif
#ifdef NRS
	case 'n':	/* nrs */
		scc_async(scc);				/* init SCC in async mode */
		brgrate = scc_speed(scc,16,atol(argv[5]));
		scc->speed = Sccinfo.clk / (32L * (brgrate + 2));
		setencap(ifp,"AX25UI");
		scc_call(ifp,argc > 7 ? argv[7] : (char *) 0);	/* set the callsign */
		ifp->ioctl = scc_aioctl;
		ifp->raw = nrs_raw;
	
		for(xdev = 0;xdev < NRS_MAX;xdev++)
			if(Nrs[xdev].iface == NULL)
				break;

		ifp->xdev = xdev;
		Nrs[xdev].iface = ifp;
		Nrs[xdev].send = scc_send;
		Nrs[xdev].get = get_scc;
		cp = if_name(ifp," rx");
		ifp->rxproc = newproc(cp,256,nrs_recv,xdev,NULL,NULL,0);
		free(cp);
		break;
#endif
	}
	ifp->next = Ifaces;			/* link interface in list */
	Ifaces = ifp;
	cp = if_name(ifp," tx");
	ifp->txproc = newproc(cp,512,if_tx,0,ifp,NULL,0);
	free(cp);
	return 0;
}

/* SCC driver initialisation. called on "attach scc <num> init ..." */
static int
scc_init(nchips,iobase,space,aoff,boff,doff,intack,ivec,clk,pclk,hwtype,hwparam)
int nchips;			/* number of chips */
ioaddr iobase;			/* base of first chip */
int space,aoff,boff,doff;
ioaddr intack;			/* INTACK ioport or 0 for no INTACK */
int ivec;			/* interrupt vector number */
long clk;			/* clock frequency */
int pclk;			/* PCLK or RTxC for clock */
int hwtype;			/* selection of special hardware types */
int hwparam;			/* extra parameter for special hardware */
{
	int chip,chan;
	ioaddr chipbase;
	register ioaddr ctrl;
    int d;
    int dum = 1;
	int i_state;

#define z 0

	if(Sccinfo.init){
		printf("SCC driver already initialized - nothing done\n");
		return 1;
	}
	Sccinfo.init = 1;
	Sccinfo.nchips = nchips;
	Sccinfo.maxchan = (2 * nchips) - 1;
	Sccinfo.iobase = iobase;
	Sccinfo.space = space;
	Sccinfo.off[0] = aoff;
	Sccinfo.off[1] = boff;
	Sccinfo.doff = doff;
	Sccinfo.ivec = ivec;
	Sccinfo.clk = clk;
	Sccinfo.pclk = pclk;
	Sccinfo.hwtype = hwtype;
	Sccinfo.hwparam = hwparam;

	/* reset and pre-init all chips in the system */
	for(chip = 0; chip < nchips; chip++){
		chipbase = iobase + chip * space;
		ctrl = chipbase + Sccinfo.off[0];
		i_state = dirps();		/* because of 2-step accesses */
		VOID(RDREG(ctrl));		/* make sure pointer is written */
		WRSCC(ctrl,R9,FHWRES);		/* force hardware reset */
		for (d = 0; d < 1000; d++)	/* wait a while to be sure */
			dum *= 10;
		for(chan = 0; chan < 2; chan++){
			ctrl = chipbase + Sccinfo.off[chan];

			/* initialize a single channel to no-op */
			VOID(RDREG(ctrl));		/* make sure pointer is written */
			WRSCC(ctrl,R4,z);		/* no mode selected yet */
			WRSCC(ctrl,R1,z);		/* no W/REQ operation */
			WRSCC(ctrl,R2,16 * chip);	/* chip# in upper 4 bits of vector */
			WRSCC(ctrl,R3,z);		/* disable rx */
			WRSCC(ctrl,R5,z);		/* disable tx */
			WRSCC(ctrl,R9,VIS);		/* vector includes status, MIE off */
			Sccpolltab[chip][chan] = ctrl; /* store ctrl addr for polling */
		}

		if (hwtype & HWSEALEVEL)		/* if a SEALEVEL card, */
			WRREG(chipbase + 4,hwparam);	/* set control/status (DTR) */

		if(hwtype & HWEAGLE)		/* this is an EAGLE card */
			WRREG(chipbase + 4,0x08);	/* enable interrupt on the board */

		if(hwtype & HWPC100)		/* this is a PC100 card */
			WRREG(chipbase,hwparam);	/* set the MODEM mode (22H normally) */

		if(hwtype & HWPRIMUS)		/* this is a PRIMUS-PC */
			WRREG(chipbase + 4,hwparam); /* set the MODEM mode (02H normally) */

		if (hwtype & HWDRSI) {		/* this is a DRSI PC*Packet card */
			ioaddr z8536 = chipbase + 7; /* point to 8536 master ctrl reg */

			/* Initialize 8536 to perform its divide-by-32 function */
			/* This part copied from N6TTO DRSI-driver */

			/* Start by forcing chip into known state */

			VOID(RDREG(z8536));		/* make sure pointer is written */
			WRSCC(z8536,CIO_MICR,0x01); /* force hardware reset */

			for (d = 0; d < 1000; d++)	/* wait a while to be sure */
				dum *= 10;

			WRSCC(z8536,CIO_MICR,0x00); /* Clear reset and start */

			/* Wait for chip to come ready */

			while (RDSCC(z8536,CIO_MICR) != 0x02)
				dum *= 10;

			WRSCC(z8536,CIO_MICR,0x26); /* NV|CT_VIS|RJA */
			WRSCC(z8536,CIO_MCCR,0xf4); /* PBE|CT1E|CT2E|CT3E|PAE */

			WRSCC(z8536,CIO_CTMS1,0xe2);/* Continuous, EOE, ECE, Pulse output */
			WRSCC(z8536,CIO_CTMS2,0xe2);/* Continuous, EOE, ECE, Pulse output */
			
	    WRSCC(z8536,CIO_CT1MSB,0x00); /* Load time constant CTC #1 */
			WRSCC(z8536,CIO_CT1LSB,0x10);
			WRSCC(z8536,CIO_CT2MSB,0x00); /* Load time constant CTC #2 */
			WRSCC(z8536,CIO_CT2LSB,0x10);

			WRSCC(z8536,CIO_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  */

			WRSCC(z8536,CIO_PDCA,0x22);
			WRSCC(z8536,CIO_PDCB,0x22);

			WRSCC(z8536,CIO_CSR1,CIO_GCB|CIO_TCB); /* Start CTC #1 running */
			WRSCC(z8536,CIO_CSR2,CIO_GCB|CIO_TCB); /* Start CTC #2 running */
		}

		restore(i_state);
	}
	Sccpolltab[chip][0] = 0;	/* terminate the polling table */
	Sccvecloc = intack;		/* location of INTACK/vector read */
	Sccmaxvec = 16 * nchips;	/* upper limit on valid vector */
	/* save original interrupt vector */
	Orgivec = getirq(ivec);

	if(intack){	/* INTACK method selected? */
		/* set interrupt vector to INTACK-generating routine  */
		setirq(ivec,sccvec);
	} else {
		/* set interrupt vector to polling routine */
		setirq(ivec,sccnovec);
	}
	/* enable the interrupt  */
	maskon(ivec);
	return 0;
}

/* initialize an SCC channel in asynchronous mode */
static int
scc_async(scc)
register struct sccchan *scc;
{
	register struct fifo *fp = &(scc->fifo);
	int i_state;
	
	if((fp->buf = malloc(scc->bufsiz)) == NULL){
		printf("scc%d: No space for rx buffer\n",scc->iface->dev);
		return -1;
	}
	fp->bufsize = scc->bufsiz;
	fp->wp = fp->rp = fp->buf;
	fp->cnt = 0;

	scc->int_transmit = scc_asytx;	/* set interrupt handlers */
	scc->int_extstat = scc_asyex;
	scc->int_receive = scc_asyrx;
	scc->int_special = scc_asysp;

	i_state = dirps();

	if (scc->extclock) {
		wr(scc,R4,X1CLK|SB1);		/* *1 clock, 1 stopbit, no parity */
		wr(scc,R11,RCRTxCP|TCTRxCP);	/* RXclk RTxC, TXclk TRxC. */
		wr(scc,R14,z);			/* No BRG options */
	wr(scc,R4,X16CLK|SB1);		/* *16 clock, 1 stopbit, no parity */
		wr(scc,R11,RCBR|TCBR);		/* clocks are BR generator */
		wr(scc,R14,Sccinfo.pclk? BRSRC:z); /* brg source = PCLK/RTxC */
	}
	wr(scc,R1,z);			/* no W/REQ operation */
	wr(scc,R3,Rx8);			/* RX 8 bits/char, disabled */
	wr(scc,R5,Tx8|DTR|RTS);		/* TX 8 bits/char, disabled, DTR RTS */
	wr(scc,R9,VIS);			/* vector includes status */
	wr(scc,R10,NRZ|z);			/* select NRZ */
	wr(scc,R15,BRKIE);			/* enable BREAK ext/status int */

	or(scc,R3,RxENABLE);		/* enable receiver */
	or(scc,R5,TxENAB);			/* enable transmitter */

	WRREG(scc->ctrl,RES_EXT_INT);	/* reset ext/status interrupts */
	WRREG(scc->ctrl,RES_EXT_INT);	/* must be done twice */
	scc->status = RDREG(scc->ctrl);	/* read initial status */

	or(scc,R1,INT_ALL_Rx|TxINT_ENAB|EXT_INT_ENAB); /* enable interrupts */
	or(scc,R9,MIE);			/* master interrupt enable */

	restore(i_state);
	return 0;
}

/* initialize an SCC channel in SDLC mode */
static void
scc_sdlc(scc)
register struct sccchan *scc;
{
	int i_state;

	scc->int_transmit = scc_sdlctx;	/* set interrupt handlers */
	scc->int_extstat = scc_sdlcex;
	scc->int_receive = scc_sdlcrx;
	scc->int_special = scc_sdlcsp;

	i_state = dirps();

	wr(scc,R4,X1CLK|SDLC);		/* *1 clock, SDLC mode */
	wr(scc,R1,z);			/* no W/REQ operation */
	wr(scc,R3,Rx8|RxCRC_ENAB);	/* RX 8 bits/char, CRC, disabled */
	wr(scc,R5,Tx8|DTR|TxCRC_ENAB);	/* TX 8 bits/char, disabled, DTR */
	wr(scc,R6,z);			/* SDLC address zero (not used) */
	wr(scc,R7,FLAG);		/* SDLC flag value */
	wr(scc,R9,VIS);			/* vector includes status */
	wr(scc,R10,CRCPS|NRZI|ABUNDER);	/* CRC preset 1, select NRZI, ABORT on underrun */

	if (scc->extclock){			/* when using external clocks */
		/* RXclk RTxC, TXclk TRxC. */
		wr(scc,R11,RCRTxCP|TCTRxCP);
		wr(scc,R14,z);			/* No BRG options */
		WRSCC(scc->ctrl,R14,DISDPLL|scc->wreg[R14]); /* No DPLL operation */
	} else {
		if(scc->fulldup){		/* when external clock divider */
			if(Sccinfo.pclk){	/* when using PCLK as clock source */
				/* RXclk DPLL, TXclk RTxC, out=BRG.	 external /32 TRxC->RTxC */
				wr(scc,R11,RCDPLL|TCRTxCP|TRxCOI|TRxCBR);
			} else {
				/* RXclk DPLL, TXclk TRxC.	external TX clock to TRxC */
				wr(scc,R11,RCDPLL|TCTRxCP);
			}
		} else {		/* only half-duplex operation */
			/* RXclk DPLL, TXclk BRG. BRG reprogrammed at every TX/RX switch */
#ifdef	notdef	/* KA9Q - for PSK modem */
			wr(scc,R11,RCDPLL|TCBR);
#else
			/* DPLL -> Rx clk, DPLL -> Tx CLK, TxCLK -> TRxC pin */
			wr(scc,R11,RCDPLL|TCDPLL|TRxCOI|TRxCDP);
#endif
		}
		wr(scc,R14,Sccinfo.pclk? BRSRC:z);	/* BRG source = PCLK/RTxC */
		WRSCC(scc->ctrl,R14,SSBR|scc->wreg[R14]); /* DPLL source = BRG */
		WRSCC(scc->ctrl,R14,SNRZI|scc->wreg[R14]); /* DPLL NRZI mode */
	}
	wr(scc,R15,BRKIE|CTSIE|DCDIE);	/* enable ABORT, CTS & DCD interrupts */

	if(RDREG(scc->ctrl) & DCD){	/* DCD is now ON */
		if (!scc->extclock)
			WRSCC(scc->ctrl,R14,SEARCH|scc->wreg[R14]); /* DPLL: enter search mode */
		or(scc,R3,ENT_HM|RxENABLE);	/* enable the receiver, hunt mode */
	}
	WRREG(scc->ctrl,RES_EXT_INT);	/* reset ext/status interrupts */
	WRREG(scc->ctrl,RES_EXT_INT);	/* must be done twice */
	scc->status = RDREG(scc->ctrl);	/* read initial status */

	or(scc,R1,INT_ALL_Rx|TxINT_ENAB|EXT_INT_ENAB); /* enable interrupts */
	or(scc,R9,MIE);			/* master interrupt enable */

	restore(i_state);
}

/* set SCC channel speed
 * clkmode specifies the division rate (1,16,32) inside the SCC
 * returns the selected brgrate for "real speed" calculation
 */
static unsigned int
scc_speed(scc,clkmode,speed)
register struct sccchan *scc;
unsigned int clkmode;
long speed;				/* the desired baudrate */
{
	unsigned int brgrate;
	long spdclkm;
	int i_state;

	/* calculate baudrate generator value */

    if ((spdclkm = speed * clkmode) == 0)
	return 65000U;			/* avoid divide-by-zero */

	brgrate = (unsigned) ((Sccinfo.clk + spdclkm) / (spdclkm * 2)) - 2;

	i_state = dirps();		/* 2-step register accesses... */

	cl(scc,R14,BRENABL);		/* disable baudrate generator */
	wr(scc,R12,brgrate);		/* brg rate LOW */
	wr(scc,R13,brgrate >> 8);		/* brg rate HIGH */
	or(scc,R14,BRENABL);		/* enable baudrate generator */

	restore(i_state);
	return brgrate;
}

/* de-activate SCC channel */
static int
scc_stop(ifp)
struct iface *ifp;
{
	struct sccchan *scc = Sccchan[ifp->dev];
	int i_state;

	i_state = dirps();

	VOID(RDREG(scc->ctrl));		/* make sure pointer is written */
	wr(scc,R9,(ifp->dev % 2)? CHRB : CHRA); /* reset the channel */

	switch(ifp->iftype->type){

⌨️ 快捷键说明

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