?? scc.c
字號(hào):
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){
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -