📄 pi.c
字号:
break;
case 0:
xwrite_scc(hp,cmd,R9,CHRB); /* Reset channel B */
break;
}
/* Deselect all Rx and Tx interrupts */
xwrite_scc(hp,cmd,R1,0);
/* Turn off external interrupts (like CTS/CD) */
xwrite_scc(hp,cmd,R15,0);
/* X1 clock, SDLC mode */
xwrite_scc(hp,cmd,R4,SDLC|X1CLK);
/* Now some misc Tx/Rx parameters */
/* CRC PRESET 1, NRZI Mode */
if(hp->speed){
xwrite_scc(hp,cmd,R10,CRCPS|NRZI);
/* Tx Clk from BRG. Rcv Clk from DPLL, TRxC pin outputs DPLL */
xwrite_scc(hp,cmd,R11,TCBR|RCDPLL|TRxCDP|TRxCOI);
} else {
xwrite_scc(hp,cmd,R10,CRCPS);
/* Tx Clk from Trxcl. Rcv Clk from Rtxcl, TRxC pin is input */
xwrite_scc(hp,cmd,R11,TCTRxCP);
}
/* Null out SDLC start address */
xwrite_scc(hp,cmd,R6,0);
/* SDLC flag */
xwrite_scc(hp,cmd,R7,FLAG);
/* Set up the Transmitter but don't enable it
* DTR, 8 bit TX chars only - TX NOT ENABLED
*/
xwrite_scc(hp,cmd,R5,Tx8|DTR);
/* Receiver - intial setup only - more later */
xwrite_scc(hp,cmd,R3,Rx8); /* 8 bits/char */
/* Setting up BRG now - turn it off first */
xwrite_scc(hp,cmd,R14,BRSRC); /* BRG off, but keep Pclk source */
/* set the 32x time constant for the BRG in Receive mode */
if(hp->speed){
br = hp->speed; /* get desired speed */
tc = ((XTAL/32)/br)-2; /* calc 32X BRG divisor */
} else {
tc = 14;
}
xwrite_scc(hp,cmd,R12,tc&0xFF); /* lower byte */
xwrite_scc(hp,cmd,R13,(tc>>8)&0xFF); /* upper byte */
/* Following subroutine sets up and ENABLES the receiver */
rts(hp,OFF); /* TX OFF and RX ON */
if(hp->speed){
/* DPLL frm BRG, BRG src PCLK */
xwrite_scc(hp,cmd,R14,BRSRC|SSBR);
} else {
/* DPLL frm rtxc,BRG src PCLK */
xwrite_scc(hp,cmd,R14,BRSRC|SSRTxC);
}
xwrite_scc(hp,cmd,R14,BRSRC|SEARCH); /* SEARCH mode, keep BRG source */
xwrite_scc(hp,cmd,R14,BRSRC|BRENABL);/* Enable the BRG */
if(!(cmd & 2)) /* if channel b */
xwrite_scc(hp,cmd,R1,(INT_ALL_Rx|EXT_INT_ENAB));
xwrite_scc(hp,cmd,R15,BRKIE); /* ABORT int */
/* Now, turn on the receiver and hunt for a flag */
xwrite_scc(hp,cmd,R3,RxENABLE|RxCRC_ENAB|Rx8);
restore(i_state);
return 0;
}
/* Attach a PI interface to the system
* argv[0]: hardware type, must be "pi"
* argv[1]: I/O address, e.g., "0x300"
* argv[2]: vector, e.g., "2"
* argv[3]: dma channel (1..3)
* argv[4]: mode, must be:
* "ax25" (AX.25 UI frame format)
* argv[5]: interface label, e.g., "pi0"
* argv[6]: receiver packet buffer size in bytes
* argv[7]: maximum transmission unit, bytes
* argv[8]: channel A interface speed, e.g, "1200", 0 = ext. clock
* argv[9]: channel B interface speed
* argv[10]: First IP address, optional (defaults to Ip_addr);
* argv[11]: Second IP address, optional (defaults to Ip_addr);
*/
int
pi_attach(argc,argv)
int argc;
char *argv[];
{
register struct iface *if_pca,*if_pcb;
struct pichan *hp;
int dev;
int n;
char *cp;
if(acc_delay == 0){ /* Only do this once */
/* Adapt recovery time delay to processor speed */
set_acc_delay();
}
/* Quick check to make sure args are good and mycall is set */
if(setencap(NULL,argv[4]) == -1){
printf("PI: Mode %s unknown for interface %s\n",
argv[4],argv[5]);
return -1;
}
if(if_lookup(argv[5]) != NULL){
printf("PI: Interface %s already exists\n",argv[5]);
return -1;
}
if(Mycall[0] == '\0'){
printf("PI: Set mycall first\n");
return -1;
}
/* Note: each card must have a unique address, IRQ and DMA */
if(pinbr >= PIMAX){
printf("PI: Maximum of %d PI cards supported\n",PIMAX);
return -1;
}
dev = pinbr++;
/* Initialize hardware-level control structure */
Pi[dev].addr = htoi(argv[1]);
Pi[dev].vec = atoi(argv[2]);
if(strchr(argv[2],'c') != NULL)
Pi[dev].chain = 1;
else
Pi[dev].chain = 0;
/* Set up counter chip */
/* 500 uS square wave */
outportb(Pi[dev].addr+TMRCMD, SC0|LSB_MSB|MODE3);
for(n=0; n<5;n++) /* satisfy access time restriction */
;
outportb(Pi[dev].addr+TMR0, 922 & 0xFF);
for(n=0; n<5;n++) /* satisfy access time restriction */
;
outportb(Pi[dev].addr+TMR0, 922 >> 8);
for(n=0; n<5;n++) /* satisfy access time restriction */
;
/* Save original interrupt vector */
Pi[dev].oldvec = getirq(Pi[dev].vec);
/* Set new interrupt vector */
if(setirq(Pi[dev].vec,pihandle[dev]) == -1){
printf("PI: IRQ %u out of range\n",Pi[dev].vec);
pinbr--;
return -1;
}
if((atoi(argv[3]) < 1) || (atoi(argv[3]) > 3)){
printf("PI: DMA %d out of range\n",atoi(argv[3]));
pinbr--;
return -1;
}
/* set params in pichan table for CHANNEL B */
hp = &Pichan[2*dev+1]; /* pi1 is offset 1 */
hp->dmachan = 0; /* Channel B does not have dma */
hp->cardbase = Pi[dev].addr;
hp->stata = Pi[dev].addr + CHANA + CTL; /* permanent status */
hp->statb = Pi[dev].addr + CHANB + CTL; /* addrs for CHANA/B*/
hp->speed = (uint16)atoi(argv[9]);
hp->base = Pi[dev].addr + CHANB;
hp->bufsiz = atoi(argv[6]);
hp->tstate = IDLE;
/* default channel access Params */
hp->txdelay = 30; /* 300 Ms */
hp->persist = 128; /* 50% persistence */
hp->slotime = 30; /* 300 Ms */
hp->squeldelay = 3; /* 30 Ms */
xwrite_scc(hp,CTL+hp->stata,R9,FHWRES); /* Hardware reset */
/* one time only */
/* Disable interrupts with Master interrupt ctrl reg */
xwrite_scc(hp,CTL+hp->stata,R9,0);
scc_init(hp);
/* Pre-allocate a receive DMA buffer */
hp->rcvbuf = dma_malloc(&hp->rcvphys,hp->bufsiz);
if(hp->rcvbuf == NULL){
/* No memory, abort receiver */
printf("PI: No memory available for receive buffer\n");
/* Restore original interrupt vector */
setirq(Pi[dev].vec,Pi[dev].oldvec);
pinbr--;
return -1;
}
/* Pre-allocate a transmit DMA buffer */
hp->sndbuf = dma_malloc(&hp->sndphys,hp->bufsiz);
if(hp->sndbuf == NULL){
/* No memory, abort */
printf("PI: No memory available for transmit buffer\n");
/* Restore original interrupt vector */
setirq(Pi[dev].vec,Pi[dev].oldvec);
pinbr--;
free(hp->rcvbuf);
return -1;
}
hp->sndq = NULL;
/* set params in pichan table for CHANNEL A */
hp = &Pichan[2*dev]; /* pi0a is offset 0 */
hp->dmachan = (unsigned char)atoi(argv[3]);
/* Verify dma channel */
if(hp->dmachan >= 8){
printf("PI: DMA channel %d out of range\n",hp->dmachan);
free(hp->rcvbuf);
free(hp->sndbuf);
/* Restore original interrupt vector */
setirq(Pi[dev].vec,Pi[dev].oldvec);
pinbr--;
return -1;
}
hp->cardbase = Pi[dev].addr;
hp->speed = (uint16)atoi(argv[8]);
hp->base = Pi[dev].addr + CHANA;
hp->bufsiz = atoi(argv[6]);
hp->tstate = IDLE;
/* default channel access Params */
hp->txdelay = 15; /* 15 mS */
hp->persist = 128; /* 50% persistence */
hp->slotime = 15; /* 15 mS */
hp->squeldelay = 1; /* 1 mS */
/* Pre-allocate a receive buffer */
hp->rcvbuf = dma_malloc(&hp->rcvphys,hp->bufsiz);
if(hp->rcvbuf == NULL){
/* No memory, abort receiver */
printf("PI: No memory available for receive buffers\n");
/* Restore original interrupt vector */
setirq(Pi[dev].vec,Pi[dev].oldvec);
pinbr--;
return -1;
}
hp->sndq = NULL;
/* Get a buffer for tx which does not cross a dma boundary */
hp->sndbuf = dma_malloc(&hp->sndphys,hp->bufsiz);
if(hp->sndbuf == NULL){
printf("PI: No memory available for transmit buffer");
/* Restore original interrupt vector */
setirq(Pi[dev].vec,Pi[dev].oldvec);
pinbr--;
free(hp->rcvbuf);
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 > 10)
if_pca->addr = resolve(argv[10]);
if(argc > 11)
if_pcb->addr = resolve(argv[11]);
if(if_pca->addr == 0 || if_pcb->addr == 0)
printf("PI: No IP address!\n");
/* Append "a" to interface associated with A channel */
if_pca->name = malloc((unsigned)strlen(argv[5])+2);
strcpy(if_pca->name,argv[5]);
strcat(if_pca->name,"a");
/* Append "b" to interface associated with B channel */
if_pcb->name = malloc((unsigned)strlen(argv[5])+2);
strcpy(if_pcb->name,argv[5]);
strcat(if_pcb->name,"b");
if_pcb->mtu = if_pca->mtu = atoi(argv[7]);
if_pcb->ioctl = if_pca->ioctl = pi_ctl;
if_pca->dev = 2*dev; /* pi0a */
if_pcb->dev = 2*dev + 1; /* pi0b */
if_pcb->stop = if_pca->stop = pi_stop;
if_pcb->raw = if_pca->raw = pi_raw;
/* Must succeed, was checked at top */
setencap(if_pca,argv[4]);
setencap(if_pcb,argv[4]);
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);
Pichan[2*dev].iface = if_pca;
Pichan[2*dev+1].iface = if_pcb;
/* Link em in to the interface chain */
if_pca->next = if_pcb;
if_pcb->next = Ifaces;
Ifaces = if_pca;
scc_init(hp);
/* master interrupt enable */
xwrite_scc(hp,CTL+hp->base,R9,MIE|NV);
/* Enable interrupt */
maskon(Pi[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 */
int
pi_stop(iface)
struct iface *iface;
{
uint16 dev;
struct pichan *hp;
dev = iface->dev;
if(dev & 1) /* Because there are 2 devices per card */
return 0;
dev >>= 1; /* Convert back into pi number */
hp = &Pichan[2*dev]; /* pi0a is offset 0 */
outportb(DMA_MASK, DMA_DISABLE|hp->dmachan); /* Disable DMA channel */
/* Turn off interrupts */
maskoff(Pi[dev].vec);
/* Restore original interrupt vector */
setirq(Pi[dev].vec,Pi[dev].oldvec);
/* Force hardware reset */
xwrite_scc(&Pichan[2*dev],CTL+Pi[dev].addr + CHANA,R9,FHWRES);
return 0;
}
/* Send raw packet on pi card */
int
pi_raw(
struct iface *iface,
struct mbuf **bpp
){
char kickflag;
struct pichan *hp;
int i_state;
dump(iface,IF_TRACE_OUT,*bpp);
iface->rawsndcnt++;
iface->lastsent = secclock();
hp = &Pichan[iface->dev];
kickflag = (hp->sndq == NULL) & (hp->sndbuf == NULL);
enqueue(&hp->sndq,bpp);
hp->enqueued++;
if(kickflag){
/* simulate interrupt to xmit */
switch(hp->base & 2){
case 2:
a_txint(hp); /* process interrupt */
break;
case 0:
i_state = dirps();
if(hp->tstate == IDLE)
b_txint(hp);
restore(i_state);
break;
}
}
return 0;
}
/* display PI Channel stats */
int
dopistat()
{
struct pichan *hp;
int i;
printf("PI Board Statistics:\n\n");
printf("Base Addr Rxints Txints Exints TxFrms RxFrms Crcerr RxOvrs TxUndr \n");
printf("--------- ------ ------ ------ ------ ------ ------ ------ ------ \n");
for(i=0; i<pinbr*2; i++){
hp = &Pichan[i];
printf("0x%03x % 8lu% 8lu% 8lu% 8u% 8u% 8u% 8u% 8u\nRcv State=%s ",
hp->base, hp->rxints, hp->txints, hp->exints, hp->enqueued,
hp->rxframes, hp->crcerr, hp->rovers, hp->tunders,
hp->rstate==0 ?
"IDLE" : hp->rstate==1 ?
"ACTIVE" : hp->rstate==2 ?
"RXERROR" : hp->rstate==3 ?
"RXABORT":"TOOBIG"
);
printf("Tstate = %s\n",
hp->tstate == 0 ?
"IDLE" : hp->tstate == 1 ?
"ACTIVE" : hp->tstate == 2 ?
"UNDERRUN" : hp->tstate == 3 ?
"FLAGOUT" : hp->tstate == 4 ?
"DEFER" : hp->tstate == 5 ?
"TXDELAY" : "CRCOUT"
);
}
return 0;
}
/* Subroutine to set kiss params in channel tables */
int32
pi_ctl(iface,cmd,set,val)
struct iface *iface;
int cmd;
int set;
int32 val;
{
struct pichan *hp;
int32 t,ca;
hp = &Pichan[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;
case PARAM_MUTE:
if(set){
if(val == -1){
/* Special case for duration of a CTS */
val = hp->txdelay + 500;
}
hp->deftime = msclock() + val;
}
t = msclock();
ca = hp->deftime - t;
if(ca < 0){
hp->deftime = t;
ca = 0;
}
return ca;
}
return -1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -