home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 1 / HamRadio.cdr / misc / src0131 / pi.c < prev    next >
C/C++ Source or Header  |  1991-01-27  |  40KB  |  1,454 lines

  1. /*
  2.  * Interface driver for the VE3IFB 8530 card (PI card)
  3.  * Copyright 1990 by Dave Perry, VE3IFB
  4.  *
  5.  * Portions of this driver were derived from the Eagle card
  6.  * driver by Art Goldman, WA3CVG. It has been very extensively
  7.  * modified from his work, due to the addition of DMA support
  8.  * and due to differences in the hardware.  The PI card is NOT
  9.  * an Eagle card clone. It is an original design by Dave Perry,
  10.  * VE3IFB.  Art's copyright notice follows:
  11.  *
  12.  *  Written by Art Goldman, WA3CVG - (c) Copyright 1987 All Rights Reserved
  13.  *  Permission for non-commercial use is hereby granted provided this notice
  14.  *  is retained.  For info call: (301) 997-3838.
  15.  * 
  16.  */
  17.  
  18. #include <stdio.h>
  19. #include <dos.h>
  20. #include <bios.h>
  21. #include "global.h"
  22. #include "mbuf.h"
  23. #include "iface.h"
  24. #include "pktdrvr.h"
  25. #include "netuser.h"
  26. #include "pi.h"
  27. #include "8530.h"
  28. #include "ax25.h"
  29. #include "trace.h"
  30. #include "pc.h"
  31. #include <time.h>
  32.  
  33. #include "session.h"
  34. #include "lapb.h"
  35. #include "proc.h"
  36. #include "ip.h"
  37.  
  38. #define FP_OFF(fp)    ((unsigned)(fp))
  39. #define FP_SEG(fp)    ((unsigned)((unsigned long)(fp) >> 16))
  40.  
  41. static void xwrite_scc __ARGS((struct pichan *hp,int16 ctl,int16 reg,
  42.     int16 val ));
  43. static char xread_scc __ARGS((struct pichan *hp, int16 ctl, char reg));
  44. static int pi_ctl __ARGS((struct iface *iface,int argc,char *argv[]));
  45. static int pi_raw __ARGS((struct iface *iface,struct mbuf *bp));
  46. static int pi_stop __ARGS((struct iface *iface));
  47. static void rts __ARGS((struct pichan *hp, int16 x));
  48. void setup_rx_dma __ARGS((struct pichan *hp));
  49. void setup_tx_dma __ARGS((struct pichan *hp, char *buffer, int length));
  50.  
  51. static struct PITAB Pi[PIMAX];    /* Device table - one entry per card */
  52. static INTERRUPT (*pihandle[])() = {    /* handler interrupt vector table */
  53.     pi0vec,
  54.     pi1vec,
  55.     pi2vec
  56. };
  57. static struct pichan Pichan[2*PIMAX];    /* channel table - 2 entries per card */
  58. static int16 pinbr;
  59.  
  60. extern int16 acc_delay;    /* Delay for the 8530 chip access recovery time */
  61.  
  62. /* Allocate a buffer which does not cross a dma page boundary */
  63. /* This really belongs in mbuf.c */
  64. struct mbuf *
  65. alloc_dmabuf(size)
  66. register int16 size;
  67. {
  68.     struct mbuf *bp[20],*retbuf;
  69.     unsigned buf_offset, buf_segment;
  70.     long longseg, dma_abs, dma_page;
  71.     int n;
  72.  
  73.     for(n = 0; n < 20 ;n++)
  74.     {
  75.         if((bp[n] = alloc_mbuf(size)) == NULLBUF)
  76.         {
  77.             while(--n >= 0) /* Free the buffers which failed the test */
  78.                 free_p(bp[n]);
  79.             return(NULLBUF);
  80.         }
  81.  
  82.         /* Calculate the DMA page */
  83.  
  84.         buf_offset = FP_OFF(bp[n]);
  85.         buf_segment= FP_SEG(bp[n]);
  86.         longseg = (long) buf_segment;
  87.         dma_abs = (longseg << 4) + (long) buf_offset;
  88.         dma_page = dma_abs >> 16;
  89.         if(((dma_abs+size) >> 16) == dma_page)
  90.         {
  91.             retbuf = bp[n]; /* Save the one that passed */
  92.             while(--n >= 0) /* Free the buffers which failed the test */
  93.                 free_p(bp[n]);
  94.             return(retbuf);
  95.         }
  96.     }
  97.     while(--n >= 0) /* Free the buffers which failed the test */
  98.         free_p(bp[n]);
  99.     return(NULLBUF);
  100. }
  101.  
  102. /* This calculates the constant to be used in the delay loops
  103.    which satify the SCC's access recovery time.  It needs to be timed and
  104.    calculated because a fixed value would not work in a 4.77mhz XT
  105.    to a 40mhz 486 (and beyond).
  106. */
  107. set_acc_delay()
  108. {    
  109.     long starttime, endtime;
  110.     int n;
  111.     int ticks;
  112.  
  113.     starttime = biostime(0,0l);
  114.     for(n = 0; n < 10; n++)
  115.         mloop();
  116.     endtime = biostime(0,0l);
  117.     ticks = (int) (endtime - starttime);
  118.     if(ticks == 0)
  119.         ticks = 1;
  120.     acc_delay = 61/ticks;
  121.     if(acc_delay == 0)
  122.         acc_delay = 1;
  123.     fflush(stdout);
  124. }
  125.  
  126. /* Write 8530 register */
  127. static void
  128. xwrite_scc(hp,ctl,reg,val)
  129. register struct pichan *hp;
  130. register int16 ctl;
  131. int16 reg,val;
  132. {
  133.     wrtscc(hp->cardbase,ctl,reg,val);
  134. }
  135.  
  136. /* Read 8530 register */
  137. static char
  138. xread_scc(hp,ctl,reg)
  139. register struct pichan *hp;
  140. register int16 ctl;
  141. char reg;
  142. {
  143.     return(rdscc(hp->cardbase,ctl,reg));
  144. }
  145.  
  146. /* Setup 8253 chip for time delay */
  147. static tdelay(hp,time)
  148. register struct pichan *hp;
  149. unsigned char time; /* Time to delay in milliseconds */
  150. {    int n;
  151.     int port, t1;
  152.     unsigned char sc;
  153.  
  154.     if(hp->base & 2) /* If A channel */
  155.     {
  156.         sc = SC1;
  157.         t1 = time;
  158.         port = hp->cardbase+TMR1;
  159.     }
  160.     else {
  161.         sc = SC2;
  162.         t1 = 10 * time; /* 10s of milliseconds for the B channel */
  163.         port = hp->cardbase+TMR2;
  164.     }
  165.  
  166.     outportb(hp->cardbase+TMRCMD, sc|LSB_MSB|MODE0); /* Setup timer sc */
  167.     for(n=0; n<5;n++) ; /* satisfy access time restriction */
  168.     outportb(port, (t1 << 1) & 0xFF);/* times 2 to make millisecs */
  169.     for(n=0; n<5;n++) ; /* satisfy access time restriction */
  170.     outportb(port, (t1 >> 7) & 0xFF);
  171.  
  172.     xwrite_scc(hp,hp->base+CTL,R15,CTSIE); /* Enable correct int for timeout */
  173.     xwrite_scc(hp,hp->base+CTL,R1,EXT_INT_ENAB);
  174.     xwrite_scc(hp,hp->base+CTL,R0,RES_EXT_INT);
  175. }
  176.  
  177. /* Master interrupt handler.  One interrupt at a time is handled.
  178.  * here. Service routines are called from here.
  179.  */
  180. void
  181. piint(dev)
  182. int dev;
  183. {
  184.     register char st;
  185.     register int16 pcbase;
  186.     struct pichan *hp;
  187.     void b_rxint(),b_txint(),b_exint();
  188.     void a_rxint(),a_txint(),a_exint();
  189.  
  190.     Pi[dev].ints++;
  191.     pcbase = Pi[dev].addr;
  192.  
  193.     /* Read interrupt status register (only valid from channel A)            */
  194.     /* Process all pending interrupts in while loop                            */
  195.     hp = &Pichan[2 * dev];    /* Assume channel A */
  196.     while((st = xread_scc(hp,pcbase+CHANA+CTL,R3)) != 0)
  197.     {
  198.         if (st & CHARxIP) {
  199.             /* Channel A Rcv Interrupt Pending */
  200.             hp = &Pichan[2 * dev];
  201.             a_rxint(hp);
  202.         } else if (st & CHATxIP) {
  203.             /* Channel A Transmit Int Pending */
  204.             hp = &Pichan[2 * dev];
  205.             a_txint(hp);
  206.         } else if (st & CHAEXT) {
  207.             /* Channel A External Status Int */
  208.             hp = &Pichan[2 * dev];
  209.             a_exint(hp);
  210.         } else if (st & CHBRxIP) {
  211.             /* Channel B Rcv Interrupt Pending */
  212.             hp = &Pichan[(2 * dev)+1];
  213.             b_rxint(hp);
  214.         } else if (st & CHBTxIP) {
  215.             /* Channel B Transmit Int Pending */
  216.             hp = &Pichan[(2 * dev)+1];
  217.             b_txint(hp);
  218.         } else if (st & CHBEXT) {
  219.             /* Channel B External Status Int */
  220.             hp = &Pichan[(2 * dev)+1];
  221.             b_exint(hp);
  222.         }
  223.         /* Reset highest interrupt under service */
  224.         xwrite_scc(hp,hp->base+CTL,R0,RES_H_IUS);
  225.     } /* End of while loop on int processing */
  226. }
  227.  
  228. static void
  229. a_exint(hp)
  230. register struct pichan *hp;
  231. {
  232.     register int16 cmd;
  233.     char st, i_state;
  234.     int i,length;
  235.  
  236.     i_state = dirps();        /* disable interrupts */
  237.  
  238.     st = xread_scc(hp,hp->base+CTL,R0);     /* Fetch status */
  239.  
  240.     /* reset external status latch */
  241.     xwrite_scc(hp,CTL+hp->base,R0,RES_EXT_INT);
  242.     cmd = hp->base+CTL;
  243.     hp->exints++;
  244.  
  245.     if((hp->rstate >= ACTIVE) && (st & BRK_ABRT))
  246.     {    
  247.         setup_rx_dma(hp);
  248.         hp->rstate = ACTIVE;
  249.     }
  250.  
  251.     switch(hp->tstate)
  252.     {
  253.         case ACTIVE:
  254.             free_p(hp->sndbuf);
  255.             hp->sndbuf = NULLBUF;
  256.             hp->tstate = FLAGOUT;
  257.             tdelay(hp,hp->params[SQUELDELAY]);
  258.             break;
  259.         case FLAGOUT:
  260.             if((hp->sndbuf = dequeue(&hp->sndq)) == NULLBUF)
  261.             {
  262.                 /* Nothing to send - return to receive mode */
  263.                 hp->tstate = IDLE;
  264.                 rts(hp,OFF);
  265.                 restore(i_state);
  266.                 return;
  267.             }
  268.             /* NOTE - fall through if more to send */
  269.         case ST_TXDELAY:
  270.             outportb(DMA_MASK, DMA_DISABLE|hp->dmachan);/* Disable DMA chan */
  271.             xwrite_scc(hp,cmd,R1,WT_FN_RDYFN|EXT_INT_ENAB);/*Set up for TX dma*/
  272.             length = pullup(&hp->sndbuf,hp->txdmabuf,hp->bufsiz); /* Get all chars */
  273.             setup_tx_dma(hp,hp->txdmabuf,length);/* Setup DMA controller for tx */
  274.             /* select transmit interrupts to enable */
  275.             outportb(DMA_MASK,DMA_ENABLE|hp->dmachan);/* Allow DMA on chan */
  276.             xwrite_scc(hp,cmd,R0,RES_Tx_CRC|RES_Tx_P);/* reset CRC, Txint pend*/
  277.             xwrite_scc(hp,cmd,R15,TxUIE);        /* allow Underrun int only */
  278.             /* Enable TX DMA */
  279.             xwrite_scc(hp,cmd,R1,WT_RDY_ENAB|WT_FN_RDYFN|EXT_INT_ENAB);
  280.             xwrite_scc(hp,cmd,R0,RES_EOM_L);    /* Send CRC on underrun */
  281.                                             /* Rest of frame sent by DMA */
  282.             hp->tstate = ACTIVE;            /* packet going out now */
  283.             break;
  284.         case DEFER:        /* we have deferred prev xmit attempt */
  285.  
  286.             /* See Intel Microcommunications Handbook, p2-308 */
  287.             xwrite_scc(hp,cmd,R0,RES_EXT_INT);
  288.             xwrite_scc(hp,cmd,R0,RES_EXT_INT);
  289.             if((xread_scc(hp,cmd,R0) & DCD) > 0)
  290.             {    hp->tstate = DEFER;
  291.                 tdelay(hp,100);
  292.                 /* Defer until dcd transition or 100mS timeout */
  293.                 xwrite_scc(hp,CTL+hp->base,R15,CTSIE|DCDIE);
  294.                 restore(i_state);
  295.                 return;
  296.             }
  297.  
  298.             if(inportb(hp->cardbase+TMR0) > hp->params[PERSIST])
  299.             {    inportb(hp->cardbase+TMR0); /* Discard MSB */
  300.                 hp->tstate = DEFER;
  301.                 tdelay(hp,hp->params[SLOTIME]);
  302.                 restore(i_state);
  303.                 return;
  304.             }
  305.             inportb(hp->cardbase+TMR0); /* Discard MSB */
  306.  
  307.             xwrite_scc(hp,cmd,R5,TxCRC_ENAB|RTS|Tx8);/* Assert RTS early minimize */
  308.                                                 /* collision window */
  309.             rts(hp,ON);                        /* Transmitter on */
  310.             hp->tstate = ST_TXDELAY;
  311.             tdelay(hp,hp->params[TXDELAY]);
  312.             restore(i_state);
  313.             return;
  314.  
  315.     } /* switch(hp->tstate) */
  316.  
  317.     restore(i_state);
  318. } /* a_exint() */
  319.  
  320. /* Receive interrupt handler for the A channel 
  321.  */
  322. static void
  323. a_rxint(hp)
  324. register struct pichan *hp;
  325. {
  326.     register int16 cmd;
  327.     register int16 bytecount;
  328.     char rse, i_state;
  329.     struct mbuf *bp;
  330.     struct phdr *phdr;
  331.  
  332.     i_state = dirps();        /* disable interrupts */
  333.     hp->rxints++;
  334.     cmd = hp->base+CTL;
  335.  
  336.     rse = xread_scc(hp,cmd,R1); /* Get special condition bits from R1 */
  337.     if(rse & Rx_OVR) /* If receiver overrun */
  338.     {
  339.         hp->rovers++;
  340.         hp->rstate = RXERROR;
  341.     }
  342.  
  343.     if(rse & END_FR) /* If end of frame */
  344.     {
  345.         /* figure length of frame from 8237 */
  346.         outportb(DMA_RESETFF,0); /* reset firstlast ff */
  347.         bytecount = inportb(hp->dma_wcr);
  348.         bytecount += inportb(hp->dma_wcr) << 8;
  349.         bytecount = (hp->bufsiz - 1) - bytecount;
  350.  
  351.         if((rse & CRC_ERR)||(hp->rstate > ACTIVE)||(bytecount < 10))
  352.         {
  353.             if((bytecount >= 10) && (rse & CRC_ERR)) /* Ignore noise */
  354.                 hp->crcerr++;
  355.  
  356.             /* Reset buffer pointers */
  357.             hp->rstate = ACTIVE;
  358.             setup_rx_dma(hp);
  359.         }
  360.         else
  361.         {
  362.             /* Here we have a valid frame */
  363.             hp->rcvbuf->cnt = bytecount - 2;   /* Toss 2 crc bytes */
  364.             bp = alloc_mbuf(sizeof(struct phdr));
  365.             if(!bp)
  366.             {
  367.                 setup_rx_dma(hp);
  368.                 xwrite_scc(hp,hp->base+CTL,R0,ERR_RES);    /* error reset */
  369.                 restore(i_state);
  370.                 return;
  371.             };
  372.             bp->cnt = sizeof(struct phdr);            
  373.             phdr = (struct phdr *)bp->data;
  374.             phdr->type = CL_AX25;
  375.             phdr->iface = hp->iface;
  376.             bp->next = hp->rcvbuf;
  377.             hp->rcvbuf = NULLBUF;
  378.             enqueue(&Hopper,bp);       /* queue it in */
  379.             hp->rxframes++;
  380.  
  381.             /* packet queued - get buffer for next frame */
  382.             hp->rcvbuf = alloc_mbuf(hp->bufsiz);
  383.             setup_rx_dma(hp);
  384.         } /* end good frame queued */
  385.     } /* end EOF check */
  386.  
  387.     xwrite_scc(hp,hp->base+CTL,R0,ERR_RES);    /* error reset */
  388.     restore(i_state);
  389. }
  390.  
  391. void
  392. a_txint(hp)
  393. register struct pichan *hp;
  394. {
  395.     register int16 cmd;
  396.     char i_state;
  397.  
  398.     i_state = dirps();
  399.     cmd = CTL+hp->base;
  400.  
  401.     switch(hp->tstate)
  402.     {
  403.         case IDLE:
  404.             /* Transmitter idle. Find a frame for transmission */
  405.             if((hp->sndbuf = dequeue(&hp->sndq)) == NULLBUF)
  406.             {
  407.                 rts(hp,OFF);
  408.                 restore(i_state);
  409.                 return;
  410.             }
  411.             /* If a buffer to send, we drop thru here */
  412.         case DEFER:        /* we may have deferred prev xmit attempt */
  413.  
  414.             /* Check DCD - debounce it */
  415.             /* See Intel Microcommunications Handbook, p2-308 */
  416.             xwrite_scc(hp,cmd,R0,RES_EXT_INT);
  417.             xwrite_scc(hp,cmd,R0,RES_EXT_INT);
  418.             if((xread_scc(hp,cmd,R0) & DCD) > 0)
  419.             {    hp->tstate = DEFER;
  420.                 tdelay(hp,100);
  421.                 /* defer until DCD transition or timeout */
  422.                 xwrite_scc(hp,cmd,R15,CTSIE|DCDIE);
  423.                 restore(i_state);
  424.                 return;
  425.             }
  426.  
  427.             if(inportb(hp->cardbase+TMR0) > hp->params[PERSIST])
  428.             {    inportb(hp->cardbase+TMR0); /* Discard MSB */
  429.                 hp->tstate = DEFER;
  430.                 tdelay(hp,hp->params[SLOTIME]);
  431.                 restore(i_state);
  432.                 return;
  433.             }
  434.             inportb(hp->cardbase+TMR0); /* Discard MSB */
  435.  
  436.             xwrite_scc(hp,cmd,R5,TxCRC_ENAB|RTS|Tx8);/* Assert RTS early minimize */
  437.                                                 /* collision window */
  438.             rts(hp,ON);                        /* Transmitter on */
  439.             hp->tstate = ST_TXDELAY;
  440.             tdelay(hp,hp->params[TXDELAY]);
  441.             restore(i_state);
  442.             return;
  443.  
  444.         default:
  445.             break;
  446.     } /* end switch(hp->state) */
  447.  
  448.     restore(i_state);
  449. } /*a_txint */
  450.  
  451. static void
  452. b_rxint(hp)
  453. register struct pichan *hp;
  454. {
  455.     register int16 cmd;
  456.     char rse, i_state;
  457.     struct mbuf *bp;
  458.     struct phdr *phdr;
  459.  
  460.     i_state = dirps();        /* disable interrupts */
  461.     hp->rxints++;
  462.     cmd = CTL+hp->base;
  463.  
  464.     if ((xread_scc(hp,cmd,R0)) & Rx_CH_AV)
  465.     {
  466.         /* there is a char to be stored
  467.          * read special condition bits before reading the data char
  468.          */
  469.         rse = xread_scc(hp,cmd,R1); /* get status byte from R1 */
  470.         if(rse & Rx_OVR) {
  471.             /* Rx overrun - toss buffer */
  472.             hp->rcp = hp->rcvbuf->data;    /* reset buffer pointers */
  473.             hp->rcvbuf->cnt = 0;
  474.             hp->rstate = RXERROR;    /* set error flag */
  475.             hp->rovers++;
  476.         } else if(hp->rcvbuf->cnt >= hp->bufsiz) {
  477.             /* Too large -- toss buffer */
  478.             hp->rcp = hp->rcvbuf->data;    /* reset buffer pointers */
  479.             hp->rcvbuf->cnt = 0;
  480.             hp->rstate = TOOBIG;    /* when set, chars are not stored */
  481.         }
  482.         /* ok, we can store the received character now */
  483.         if(hp->rstate == ACTIVE) {            /* If no errors... */
  484.             *hp->rcp++ = xread_scc(hp,cmd,R8);    /* char to rcv buff */
  485.             hp->rcvbuf->cnt++;                   /* bump count */
  486.         } else {
  487.             /* got to empty FIFO */
  488.             (void) xread_scc(hp,cmd,R8);
  489.             xwrite_scc(hp,cmd,R0,ERR_RES);    /* reset err latch */
  490.             hp->rstate = ACTIVE;
  491.         }
  492.     }
  493.  
  494.     if(rse & END_FR)
  495.     {
  496.         /* END OF FRAME -- Make sure Rx was active */
  497.         if(hp->rcvbuf->cnt > 0)
  498.         {
  499.             if((rse & CRC_ERR)||(hp->rstate > ACTIVE)||(hp->rcvbuf->cnt < 10))
  500.             {
  501.                 if((hp->rcvbuf->cnt >= 10) && (rse & CRC_ERR))/* Ignore noise */
  502.                     hp->crcerr++;
  503.  
  504.                 hp->rcp = hp->rcvbuf->data;
  505.                 hp->rcvbuf->cnt = 0;
  506.             } else {
  507.                 /* Here we have a valid frame */
  508.                 hp->rcvbuf->cnt -= 2;           /* Toss 2 crc bytes */
  509.                 bp = alloc_mbuf(sizeof(struct phdr));
  510.                 if(!bp) /* we can't get memory - throw it away */
  511.                 {
  512.                     hp->rcp = hp->rcvbuf->data;
  513.                     hp->rcvbuf->cnt = 0;
  514.                     restore(i_state);
  515.                     return;
  516.                 }
  517.                 bp->cnt = sizeof(struct phdr);            
  518.                 phdr = (struct phdr *)bp->data;
  519.                 phdr->type = CL_AX25;
  520.                 phdr->iface = hp->iface;
  521.                 bp->next = hp->rcvbuf;
  522.                 enqueue(&Hopper,bp);       /* queue it in */
  523.                 hp->rxframes++;
  524.  
  525.                 /* packet queued - get buffer for next frame */
  526.                 hp->rcvbuf = alloc_mbuf(hp->bufsiz);
  527.                 if(hp->rcvbuf == NULLBUF) {
  528.                     xwrite_scc(hp,cmd,R3,Rx8); /* No memory - abort rx */
  529.                     restore(i_state);
  530.                     return;
  531.                 }
  532.                 hp->rcp = hp->rcvbuf->data;
  533.                 hp->rcvbuf->cnt = 0;
  534.             } /* end good frame queued */
  535.         }  /* end check for active receive upon EOF */
  536.         hp->rstate = ACTIVE;    /* and clear error status */
  537.     } /* end EOF check */
  538.  
  539.     restore(i_state);
  540. }
  541.  
  542. static void
  543. b_txint(hp)
  544. register struct pichan *hp;
  545. {
  546.     register int16 cmd;
  547.     char i_state,c;
  548.  
  549.     i_state = dirps();
  550.     cmd = CTL+hp->base;
  551.  
  552.     if(hp->tstate != DEFER && hp->tstate)
  553.         hp->txints++;
  554.  
  555.     switch(hp->tstate) {
  556.     case CRCOUT:
  557.         hp->tstate = FLAGOUT;
  558.         tdelay(hp,hp->params[SQUELDELAY]);
  559.         restore(i_state);
  560.         return;
  561.     case IDLE:
  562.         /* Transmitter idle. Find a frame for transmission */
  563.         if((hp->sndbuf = dequeue(&hp->sndq)) == NULLBUF) {
  564.             /* Nothing to send - return to receive mode
  565.              * Tx OFF now - flag should have gone
  566.              */
  567.             rts(hp,OFF);
  568.             restore(i_state);
  569.             return;
  570.         }
  571.         /* If a buffer to send, we drop thru here */
  572.     case DEFER:        /* we may have deferred prev xmit attempt */
  573.         /* Check DCD - debounce it */
  574.         /* See Intel Microcommunications Handbook, p2-308 */
  575.         xwrite_scc(hp,cmd,R0,RES_EXT_INT);
  576.         xwrite_scc(hp,cmd,R0,RES_EXT_INT);
  577.         if((xread_scc(hp,cmd,R0) & DCD) > 0)
  578.         {    hp->tstate = DEFER;
  579.             tdelay(hp,100);
  580.             /* defer until DCD transition or timeout */
  581.             xwrite_scc(hp,cmd,R15,CTSIE|DCDIE);
  582.             restore(i_state);
  583.             return;
  584.         }
  585.  
  586.         /* p - persist calculation */
  587.         if(inportb(hp->cardbase+TMR0) > hp->params[PERSIST])
  588.         {    inportb(hp->cardbase+TMR0); /* Discard MSB */
  589.             hp->tstate = DEFER;
  590.             tdelay(hp,hp->params[SLOTIME]);
  591.             restore(i_state);
  592.             return;
  593.         }
  594.         inportb(hp->cardbase+TMR0); /* Discard MSB */
  595.  
  596.         rts(hp,ON);   /* Transmitter on */
  597.         hp->tstate = ST_TXDELAY;
  598.         tdelay(hp,hp->params[TXDELAY]);
  599.         restore(i_state);
  600.         return;
  601.  
  602.     case ACTIVE:
  603.         /* Here we are actively sending a frame */
  604.         if((c = PULLCHAR(&hp->sndbuf)) != -1){
  605.             xwrite_scc(hp,cmd,R8,c);        /* next char is gone */
  606.             /* stuffing a char satisfies Interrupt condition */
  607.         } else {
  608.             /* No more to send */
  609.             free_p(hp->sndbuf);
  610.             if((xread_scc(hp,cmd,R0) & 0x40)) /* Did we underrun? */
  611.             {    /* unexpected underrun */
  612.                 hp->tunders++;
  613.                 xwrite_scc(hp,cmd,R0,SEND_ABORT);
  614.                 hp->tstate = FLAGOUT;
  615.                 tdelay(hp,hp->params[SQUELDELAY]);
  616.                 restore(i_state);
  617.                 return;
  618.             }
  619.             hp->tstate = UNDERRUN; /* Now we expect to underrun */
  620.             /* Send flags on underrun */
  621.             if(hp->speed) { /* If externally clocked */
  622.                 xwrite_scc(hp,cmd,R10,CRCPS|NRZI);
  623.             } else {
  624.                 xwrite_scc(hp,cmd,R10,CRCPS);
  625.             }
  626.             xwrite_scc(hp,cmd,R0,RES_Tx_P); /* reset Tx Int Pend */
  627.         }
  628.         restore(i_state);
  629.         return;     /* back to wait for interrupt */
  630.     } /* end switch */
  631.     restore(i_state);
  632. }
  633.  
  634. /* Pi SIO External/Status interrupts (for the B channel)
  635.  * This can be caused by a receiver abort, or a Tx UNDERRUN/EOM.
  636.  * Receiver automatically goes to Hunt on an abort.
  637.  *
  638.  * If the Tx Underrun interrupt hits, change state and
  639.  * issue a reset command for it, and return.
  640.  */
  641. static void
  642. b_exint(hp)
  643. register struct pichan *hp;
  644. {
  645.     char st, i_state;
  646.     register int16 cmd;
  647.     char c;
  648.  
  649.     cmd = CTL+hp->base;
  650.     i_state = dirps();        /* disable interrupts */
  651.     hp->exints++;
  652.     st = xread_scc(hp,cmd,R0);     /* Fetch status */
  653.     /* reset external status latch */
  654.     xwrite_scc(hp,cmd,R0,RES_EXT_INT);
  655.  
  656.  
  657.     switch(hp->tstate) {
  658.     case ACTIVE:    /* Unexpected underrun */
  659.         free_p(hp->sndbuf);
  660.         xwrite_scc(hp,cmd,R0,SEND_ABORT);
  661.         hp->tstate = FLAGOUT;
  662.         hp->tunders++;
  663.         tdelay(hp,hp->params[SQUELDELAY]);
  664.         restore(i_state);
  665.         return;
  666.     case UNDERRUN:
  667.         hp->tstate = CRCOUT;
  668.         restore(i_state);
  669.         return;
  670.     case FLAGOUT: 
  671.         /* Find a frame for transmission */
  672.         if((hp->sndbuf = dequeue(&hp->sndq)) == NULLBUF) {
  673.             /* Nothing to send - return to receive mode
  674.              * Tx OFF now - flag should have gone
  675.              */
  676.             rts(hp,OFF);
  677.             hp->tstate = IDLE;
  678.             restore(i_state);
  679.             return;
  680.         }
  681.         /* Get next char to send */
  682.         pullup(&hp->sndbuf,&c,1);        /* one char at a time */
  683.         xwrite_scc(hp,cmd,R0,RES_Tx_CRC);    /* reset for next frame */
  684.  
  685.         /* Send abort on underrun */
  686.         if(hp->speed) { /* If externally clocked */
  687.             xwrite_scc(hp,cmd,R10,CRCPS|NRZI|ABUNDER);
  688.         } else {
  689.             xwrite_scc(hp,cmd,R10,CRCPS|ABUNDER);
  690.         }
  691.  
  692.         xwrite_scc(hp,cmd,R8,c);            /* First char out now */
  693.         xwrite_scc(hp,cmd,R0,RES_EOM_L);    /* Reset end of message latch */
  694.  
  695.         /* select transmit interrupts to enable */
  696.  
  697.         xwrite_scc(hp,cmd,R15,TxUIE);        /* allow Underrun int only */
  698.         xwrite_scc(hp,cmd,R0,RES_EXT_INT);
  699.         xwrite_scc(hp,cmd,R1,TxINT_ENAB|EXT_INT_ENAB);  /* Tx/Extern ints on */
  700.  
  701.         hp->tstate = ACTIVE;    /* char going out now */
  702.         restore(i_state);
  703.         return;
  704.  
  705.     case DEFER:
  706.         /* Check DCD - debounce it */
  707.         /* See Intel Microcommunications Handbook, p2-308 */
  708.         xwrite_scc(hp,cmd,R0,RES_EXT_INT);
  709.         xwrite_scc(hp,cmd,R0,RES_EXT_INT);
  710.         if((xread_scc(hp,cmd,R0) & DCD) > 0)
  711.         {    hp->tstate = DEFER;
  712.             tdelay(hp,100);
  713.             /* defer until DCD transition or timeout */
  714.             xwrite_scc(hp,cmd,R15,CTSIE|DCDIE);
  715.             restore(i_state);
  716.             return;
  717.         }
  718.  
  719.         /* p - persist calculation */
  720.         if(inportb(hp->cardbase+TMR0) > hp->params[PERSIST])
  721.         {    inportb(hp->cardbase+TMR0); /* Discard MSB */
  722.             hp->tstate = DEFER;
  723.             tdelay(hp,hp->params[SLOTIME]);
  724.             restore(i_state);
  725.             return;
  726.         }
  727.         inportb(hp->cardbase+TMR0); /* Discard MSB */
  728.  
  729.         rts(hp,ON);   /* Transmitter on */
  730.         hp->tstate = ST_TXDELAY;
  731.         tdelay(hp,hp->params[TXDELAY]);
  732.         restore(i_state);
  733.         return;
  734.  
  735.     case ST_TXDELAY:
  736.  
  737.         /* Get next char to send */
  738.         pullup(&hp->sndbuf,&c,1);        /* one char at a time */
  739.         xwrite_scc(hp,cmd,R0,RES_Tx_CRC);    /* reset for next frame */
  740.  
  741.         /* Send abort on underrun */
  742.         if(hp->speed) { /* If externally clocked */
  743.             xwrite_scc(hp,cmd,R10,CRCPS|NRZI|ABUNDER);
  744.         } else {
  745.             xwrite_scc(hp,cmd,R10,CRCPS|ABUNDER);
  746.         }
  747.  
  748.         xwrite_scc(hp,cmd,R8,c);            /* First char out now */
  749.         xwrite_scc(hp,cmd,R0,RES_EOM_L);    /* Reset end of message latch */
  750.  
  751.         /* select transmit interrupts to enable */
  752.  
  753.         xwrite_scc(hp,cmd,R15,TxUIE);        /* allow Underrun int only */
  754.         xwrite_scc(hp,cmd,R0,RES_EXT_INT);
  755.         xwrite_scc(hp,cmd,R1,TxINT_ENAB|EXT_INT_ENAB);  /* Tx/Extern ints on */
  756.  
  757.         hp->tstate = ACTIVE;    /* char going out now */
  758.         restore(i_state);
  759.         return;
  760.  
  761.     }
  762.  
  763.     /* Receive Mode only
  764.      * This triggers when hunt mode is entered, & since an ABORT
  765.      * automatically enters hunt mode, we use that to clean up
  766.      * any waiting garbage
  767.      */
  768.     if((hp->rstate == ACTIVE) && (st & BRK_ABRT)) {
  769.         (void) xread_scc(hp,cmd,R8);
  770.         (void) xread_scc(hp,cmd,R8);
  771.         (void) xread_scc(hp,cmd,R8);
  772.         hp->rcp = hp->rcvbuf->data;
  773.         hp->rcvbuf->cnt = 0;          /* rewind on DCD transition */
  774.     }
  775.  
  776.     restore(i_state);
  777. }
  778.  
  779. /* SET Transmit or Receive Mode
  780.  * Set RTS (request-to-send) to modem on Transmit
  781.  */
  782. static void
  783. rts(hp,x)
  784. register struct pichan *hp;
  785. int16 x;
  786. {
  787.     int16 tc;
  788.     long br;
  789.     int16 cmd;
  790.  
  791.     cmd = CTL+hp->base;
  792.  
  793.     /* Reprogram BRG and turn on transmitter to send flags */
  794.     if(x == ON) {                /* Turn Tx ON and Receive OFF */
  795.         xwrite_scc(hp,cmd,R15,0);    /* Exints off first to avoid abort int */
  796.         xwrite_scc(hp,cmd,R3,Rx8);    /* Rx off */
  797.         hp->rstate = IDLE;
  798.         if(cmd & 2) /* if channel a */
  799.             xwrite_scc(hp,cmd,R1,WT_FN_RDYFN|EXT_INT_ENAB);    /* Set up for TX dma */
  800.         else
  801.             xwrite_scc(hp,cmd,R1,0);    /* No interrupts */
  802.  
  803.         if(hp->speed) {                        /* if internally clocked */
  804.             br = hp->speed;                     /* get desired speed */
  805.             tc = (XTAL/br)-2;                /* calc 1X BRG divisor */
  806.             xwrite_scc(hp,cmd,R12,tc&0xFF);     /* lower byte */
  807.             xwrite_scc(hp,cmd,R13,(tc>>8)&0xFF);/* upper byte */
  808.         }
  809.  
  810.         xwrite_scc(hp,cmd,R5,TxCRC_ENAB|RTS|TxENAB|Tx8|DTR);
  811.         /* Transmitter now on */
  812.     } else {    /* Tx OFF and Rx ON */
  813.         hp->tstate = IDLE;
  814.         xwrite_scc(hp,cmd,R5,Tx8|DTR);     /*  TX off */
  815.  
  816.         if(hp->speed) {                            /* if internally clocked */
  817.             /* Reprogram BRG for 32x clock for receive DPLL */
  818.             xwrite_scc(hp,cmd,R14,BRSRC);            /* BRG off, keep Pclk source */
  819.             br = hp->speed;                         /* get desired speed */
  820.             tc = ((XTAL/32)/br)-2;                /* calc 32X BRG divisor */
  821.             xwrite_scc(hp,cmd,R12,tc&0xFF);            /* lower byte */
  822.             xwrite_scc(hp,cmd,R13,(tc>>8)&0xFF);    /* upper bite */
  823.             xwrite_scc(hp,cmd,R14,BRSRC|SEARCH);    /* SEARCH mode, BRG source */
  824.             xwrite_scc(hp,cmd,R14,BRSRC|BRENABL);    /* Enable the BRG */
  825.         }
  826.  
  827.         /* Now, turn on the receiver and hunt for a flag */
  828.         xwrite_scc(hp,cmd,R3,RxENABLE|RxCRC_ENAB|Rx8);
  829.         hp->rstate = ACTIVE;            /* Normal state */
  830.  
  831.         if(cmd & 2) {/* if channel a */
  832.             setup_rx_dma(hp);
  833.         } else {
  834.         /*    xwrite_scc(hp,cmd,R0,ERR_RES); */    /* reset error bits */
  835.             hp->rcp = hp->rcvbuf->data;    /* reset buffer pointers */
  836.             hp->rcvbuf->cnt = 0;
  837.             xwrite_scc(hp,cmd,R1,(INT_ALL_Rx|EXT_INT_ENAB));
  838.         }
  839.  
  840.         xwrite_scc(hp,cmd,R15,BRKIE);        /* allow ABORT int */
  841.     }
  842. }
  843.  
  844. void
  845. setup_rx_dma(hp)
  846. register struct pichan *hp;
  847. {
  848.     unsigned buf_offset, buf_segment;
  849.     int cmd;
  850.     char dummy;
  851.     long longseg, dma_abs, dma_page;
  852.     char i_state;
  853.  
  854.     i_state = dirps();        /* disable interrupts */
  855.  
  856.     cmd = hp->base+CTL;
  857.  
  858.     if(!hp->rcvbuf) /* No rx buffer available */
  859.     {    restore(i_state);
  860.         return;
  861.     }
  862.  
  863.     /* Calculate high order 4 bits of the buffer area and store
  864.         them in the DMA page register
  865.     */
  866.  
  867.     buf_offset = FP_OFF(hp->rcvbuf->data);
  868.     buf_segment= FP_SEG(hp->rcvbuf->data);
  869.     longseg = (long) buf_segment;
  870.     dma_abs = (longseg << 4) + (long) buf_offset;
  871.     dma_page = dma_abs >> 16;
  872.  
  873.     /* Get ready for RX DMA */
  874.     xwrite_scc(hp,cmd,R1,WT_FN_RDYFN|WT_RDY_RT|INT_ERR_Rx|EXT_INT_ENAB);
  875.     outportb(DMA_MASK, DMA_DISABLE|hp->dmachan); /* Disable DMA chan */
  876.     /* Set DMA mode register to single transfers, incrementing address,
  877.         auto init, writes
  878.     */
  879.     outportb(DMA_MODE,DMA_RX_MODE|hp->dmachan);
  880.  
  881.     outportb(hp->page_addr,dma_page); /* Store in  64K DMA page */
  882.     outportb(DMA_RESETFF,0); /* reset byte pointer flipflop */
  883.     outportb(hp->dma_dest,dma_abs);    /* Output buffer start (dest) address */
  884.     outportb(hp->dma_dest,dma_abs >> 8);
  885.     /* output DMA maximum byte count */
  886.     outportb(hp->dma_wcr,hp->bufsiz - 1);
  887.     outportb(hp->dma_wcr, (hp->bufsiz - 1) >> 8);
  888.     /* Unmask channel 1 (start DMA) */
  889.     outportb(DMA_MASK, DMA_ENABLE|hp->dmachan); /* Enable DMA chan */
  890.  
  891.     /* If a packet is already coming in, this line is supposed
  892.         to mess up the crc to avoid receiving a partial packet */
  893.     xwrite_scc(hp,cmd,R0,RES_Rx_CRC);
  894.  
  895.     /* Enable RX dma */
  896.     xwrite_scc(hp,cmd,R1,WT_RDY_ENAB|WT_FN_RDYFN|WT_RDY_RT|INT_ERR_Rx|EXT_INT_ENAB);
  897.  
  898.     restore(i_state);
  899. }
  900.  
  901. void
  902. setup_tx_dma(hp,buffer,length)
  903. struct pichan *hp;
  904. char *buffer;
  905. int length;
  906. {
  907.     unsigned buf_offset, buf_segment;
  908.     long longseg, dma_abs, dma_page;
  909.     char i_state;
  910.  
  911.     i_state = dirps();        /* disable interrupts */
  912.  
  913.     /* Calculate high order 4 bits of the buffer area and store
  914.         them in the DMA page register
  915.     */
  916.  
  917.     buf_offset = FP_OFF(buffer);
  918.     buf_segment= FP_SEG(buffer);
  919.     longseg = (long) buf_segment;
  920.     dma_abs = (longseg << 4) + (long) buf_offset;
  921.     dma_page = dma_abs >> 16;
  922.  
  923.     outportb(DMA_MASK, DMA_DISABLE|hp->dmachan); /* Disable DMA chan */
  924.     if(((dma_abs + length) >> 16) != dma_page)
  925.         tprintf("PI: ERROR - DMA page boundary violation\n");
  926.     --length; /* Adjust length for DMA chip */
  927.     /* Set DMA mode register to single transfers, incrementing address,
  928.         no auto init, reads
  929.     */
  930.     outportb(DMA_MODE,DMA_TX_MODE|hp->dmachan);
  931.  
  932.     outportb(hp->page_addr,dma_page); /* Store in 64K DMA page */
  933.     outportb(DMA_RESETFF,0); /* reset byte pointer flipflop */
  934.     outportb(hp->dma_dest,dma_abs);    /* Output buffer start (source) address */
  935.     outportb(hp->dma_dest,dma_abs >> 8);
  936.     /* output byte count */
  937.     outportb(hp->dma_wcr,length);
  938.     outportb(hp->dma_wcr, (length) >> 8);
  939.  
  940.     restore(i_state);
  941. }
  942.  
  943. /* Initialize pi controller parameters */
  944. static int
  945. scc_init(hp)
  946. register struct pichan *hp;
  947. {
  948.     int16 tc;
  949.     long br;
  950.     char i_state;
  951.     register int16 cmd;
  952.  
  953.     /* Initialize 8530 channel for SDLC operation */
  954.  
  955.     cmd = CTL+hp->base;
  956. #ifdef    notdef
  957.     tprintf("Pi: Initializing Channel %c - Base = %x\n",cmd&2?'A':'B',cmd&~CTL);
  958. #endif
  959.     i_state = dirps();
  960.  
  961.     switch(cmd & 2){
  962.     case 2:
  963.         xwrite_scc(hp,cmd,R9,CHRA);    /* Reset channel A */
  964.         xwrite_scc(hp,cmd,R2,0xff); /* Initialize interrupt vector */
  965.         break;
  966.     case 0:
  967.         xwrite_scc(hp,cmd,R9,CHRB);    /* Reset channel B */
  968.         break;
  969.     }
  970.  
  971.     /* Deselect all Rx and Tx interrupts */
  972.     xwrite_scc(hp,cmd,R1,0);
  973.  
  974.     /* Turn off external interrupts (like CTS/CD) */
  975.     xwrite_scc(hp,cmd,R15,0);
  976.  
  977.     /* X1 clock, SDLC mode */
  978.     xwrite_scc(hp,cmd,R4,SDLC|X1CLK);           /* SDLC mode and X1 clock */
  979.  
  980.     /* Now some misc Tx/Rx parameters */
  981.     /* CRC PRESET 1, NRZI Mode */
  982.     if(hp->speed) {
  983.         xwrite_scc(hp,cmd,R10,CRCPS|NRZI);
  984.         /* Tx Clk from BRG. Rcv Clk from DPLL, TRxC pin outputs DPLL */
  985.         xwrite_scc(hp,cmd,R11,TCBR|RCDPLL|TRxCDP|TRxCOI);
  986.     } else {
  987.         xwrite_scc(hp,cmd,R10,CRCPS);
  988.         /* Tx Clk from Trxcl. Rcv Clk from Rtxcl, TRxC pin is input */
  989.         xwrite_scc(hp,cmd,R11,TCTRxCP);
  990.     }
  991.  
  992.     /* Null out SDLC start address */
  993.     xwrite_scc(hp,cmd,R6,0);
  994.  
  995.     /* SDLC flag */
  996.     xwrite_scc(hp,cmd,R7,FLAG);
  997.  
  998.     /* Set up the Transmitter but don't enable it */
  999.     /*  DTR, 8 bit TX chars only - TX NOT ENABLED */
  1000.     xwrite_scc(hp,cmd,R5,Tx8|DTR);
  1001.  
  1002.     /* Receiver - intial setup only - more later */
  1003.     xwrite_scc(hp,cmd,R3,Rx8);            /* 8 bits/char */
  1004.  
  1005.     /* Setting up BRG now - turn it off first */
  1006.     xwrite_scc(hp,cmd,R14,BRSRC);         /* BRG off, but keep Pclk source */
  1007.  
  1008.     /* set the 32x time constant for the BRG in Receive mode */
  1009.  
  1010.     if(hp->speed) {
  1011.         br = hp->speed;             /* get desired speed */
  1012.         tc = ((XTAL/32)/br)-2;            /* calc 32X BRG divisor */
  1013.     } else {
  1014.         tc = 14;
  1015.     }
  1016.  
  1017.     xwrite_scc(hp,cmd,R12,tc&0xFF);      /* lower byte */
  1018.     xwrite_scc(hp,cmd,R13,(tc>>8)&0xFF); /* upper bite */
  1019.  
  1020.     /* Following subroutine sets up and ENABLES the receiver */
  1021.     rts(hp,OFF);           /* TX OFF and RX ON */
  1022.  
  1023.     if(hp->speed)
  1024.         xwrite_scc(hp,cmd,R14,BRSRC|SSBR);/*DPLL frm BRG, BRG src PCLK */
  1025.     else
  1026.         xwrite_scc(hp,cmd,R14,BRSRC|SSRTxC);/*DPLL frm rtxc,BRG src PCLK */
  1027.  
  1028.     xwrite_scc(hp,cmd,R14,BRSRC|SEARCH);       /* SEARCH mode, keep BRG source */
  1029.     xwrite_scc(hp,cmd,R14,BRSRC|BRENABL);    /* Enable the BRG */
  1030.  
  1031.     if(!(cmd & 2)) /* if channel b */
  1032.         xwrite_scc(hp,cmd,R1,(INT_ALL_Rx|EXT_INT_ENAB));
  1033.  
  1034.     xwrite_scc(hp,cmd,R15,BRKIE);        /* ABORT int */
  1035.  
  1036.     /* Now, turn on the receiver and hunt for a flag */
  1037.     xwrite_scc(hp,cmd,R3,RxENABLE|RxCRC_ENAB|Rx8);
  1038.  
  1039.     restore(i_state);
  1040.     return 0;
  1041. }
  1042.  
  1043. /* Process to recover from ibuffails.
  1044.    This could be done in the function network() in config.c,
  1045.    to save a context switch.  I put it here so the driver would
  1046.    be more self contained.
  1047. */
  1048. void
  1049. buf_recover(unused,b,a)
  1050. int unused;
  1051. void *b;    /* Unused */
  1052. void *a;    /* Unused */
  1053. {
  1054.     struct pichan *hp0, *hp1;
  1055.     char i_state;
  1056.     int i;
  1057.  
  1058.     for(;;)
  1059.     {    pwait(NULL);
  1060.  
  1061.         for(i=0; i<pinbr; i++) /* for each card */
  1062.         {
  1063.             hp0 = &Pichan[i];
  1064.             hp1 = &Pichan[i + 1];
  1065.             if(!hp0->rcvbuf) /* No rx buffer allocated */
  1066.             {
  1067.                 i_state = dirps();
  1068.                 hp0->rcvbuf = alloc_mbuf(hp0->bufsiz);
  1069.                 restore(i_state);
  1070.                 setup_rx_dma(hp0);
  1071.             }
  1072.             i_state = dirps();
  1073.             if(!hp1->rcvbuf && (hp1->rstate == ACTIVE))/* No rx buf allocated */
  1074.             {
  1075.                 if((hp1->rcvbuf = alloc_mbuf(hp1->bufsiz)) != NULL)
  1076.                 {    
  1077.                     hp1->rcp = hp1->rcvbuf->data;
  1078.                     hp1->rcvbuf->cnt = 0;
  1079.                     xwrite_scc(hp1,CTL+hp1->base,R3,RxENABLE|RxCRC_ENAB|Rx8);
  1080.                 }
  1081.             }
  1082.             restore(i_state);
  1083.         }
  1084.     }
  1085. }
  1086.  
  1087. /* Attach a PI interface to the system
  1088.  * argv[0]: hardware type, must be "pi"
  1089.  * argv[1]: I/O address, e.g., "0x300"
  1090.  * argv[2]: vector, e.g., "2"
  1091.  * argv[3]: dma channel (1..3)
  1092.  * argv[4]: mode, must be:
  1093.  *        "ax25" (AX.25 UI frame format)
  1094.  * argv[5]: interface label, e.g., "pi0"
  1095.  * argv[6]: receiver packet buffer size in bytes
  1096.  * argv[7]: maximum transmission unit, bytes
  1097.  * argv[8]: channel A interface speed, e.g, "1200", 0 = ext. clock
  1098.  * argv[9]: channel B interface speed
  1099.  * argv[10]: First IP address, optional (defaults to Ip_addr);
  1100.  * argv[11]: Second IP address, optional (defaults to Ip_addr);
  1101.  */
  1102. int
  1103. pi_attach(argc,argv)
  1104. int argc;
  1105. char *argv[];
  1106. {
  1107.     extern void refiq();
  1108.     register struct iface *if_pca,*if_pcb;
  1109.     struct pichan *hp;
  1110.     int dev;
  1111.     char i_state;
  1112.     int n;
  1113.  
  1114.     refiq(); /* replenish interrupt buffer pool (in mbuf.c) */
  1115.     if(acc_delay == 0)    /* Only do this once */
  1116.         set_acc_delay();/* Adapt recovery time delay to processor speed */
  1117.  
  1118.     /* Quick check to make sure args are good and mycall is set */
  1119.     if(strcmp(argv[4],"ax25") != 0){
  1120.         tprintf("PI: Mode %s unknown for interface %s\n",
  1121.             argv[4],argv[5]);
  1122.         return -1;
  1123.     }
  1124.     if(if_lookup(argv[5]) != NULLIF){
  1125.         tprintf("PI: Interface %s already exists\n",argv[5]);
  1126.         return -1;
  1127.     }
  1128.     if(Mycall[0] == '\0'){
  1129.         tprintf("PI: Set mycall first\n");
  1130.         return -1;
  1131.     }
  1132.     /* Note: each card must have a unique address, IRQ and DMA 
  1133.      */
  1134.  
  1135.     if(pinbr >= PIMAX) {
  1136.         tprintf("PI: Maximum of %d PI cards supported\n",PIMAX);
  1137.         return -1;
  1138.     }
  1139.     dev = pinbr++;
  1140.  
  1141.     /* Initialize hardware-level control structure */
  1142.     Pi[dev].addr = htoi(argv[1]);
  1143.     Pi[dev].vec = htoi(argv[2]);
  1144.  
  1145.     /* Set up counter chip */
  1146.     outportb(Pi[dev].addr+TMRCMD, SC0|LSB_MSB|MODE3); /* 500 uS square wave */
  1147.     for(n=0; n<5;n++) /* satisfy access time restriction */
  1148.         ;
  1149.     outportb(Pi[dev].addr+TMR0, 922 & 0xFF); 
  1150.     for(n=0; n<5;n++) /* satisfy access time restriction */
  1151.         ;
  1152.     outportb(Pi[dev].addr+TMR0, 922 >> 8);
  1153.     for(n=0; n<5;n++) /* satisfy access time restriction */
  1154.         ;
  1155.  
  1156.     /* Save original interrupt vector */
  1157.     Pi[dev].oldvec = getirq(Pi[dev].vec);
  1158.  
  1159.     /* Set new interrupt vector */
  1160.     if(setirq(Pi[dev].vec,pihandle[dev]) == -1){
  1161.         tprintf("PI: IRQ %u out of range\n",Pi[dev].vec);
  1162.         pinbr--;
  1163.         return -1;
  1164.     }
  1165.  
  1166.     if((atoi(argv[3]) < 1) || (atoi(argv[3]) > 3)){
  1167.         tprintf("PI: DMA %d out of range\n",atoi(argv[3]));
  1168.         pinbr--;
  1169.         return -1;
  1170.     }
  1171.  
  1172.     /* Create interface structures and fill in details */
  1173.     if_pca = (struct iface *)callocw(1,sizeof(struct iface));
  1174.     if_pcb = (struct iface *)callocw(1,sizeof(struct iface));
  1175.  
  1176.  
  1177.     if_pca->addr = if_pcb->addr = Ip_addr;
  1178.     if(argc > 10)
  1179.         if_pca->addr = resolve(argv[10]);
  1180.     if(argc > 11)
  1181.         if_pcb->addr = resolve(argv[11]);
  1182.  
  1183.     if(if_pca->addr == 0 || if_pcb->addr == 0){
  1184.         tprintf("PI: No IP address");
  1185.         free((char *)if_pca);
  1186.         free((char *)if_pcb);
  1187.         return -1;
  1188.     }
  1189.  
  1190.     /* Append "a" to interface associated with A channel */
  1191.     if_pca->name = malloc((unsigned)strlen(argv[5])+2);
  1192.     strcpy(if_pca->name,argv[5]);
  1193.     strcat(if_pca->name,"a");
  1194.     /* Append "b" to interface associated with B channel */
  1195.     if_pcb->name = malloc((unsigned)strlen(argv[5])+2);
  1196.     strcpy(if_pcb->name,argv[5]);
  1197.     strcat(if_pcb->name,"b");
  1198.  
  1199.     if_pcb->mtu = if_pca->mtu = atoi(argv[7]);
  1200.     if_pcb->type = if_pca->type = CL_AX25;
  1201.     if_pcb->ioctl = if_pca->ioctl = pi_ctl;
  1202.     if_pca->dev = 2*dev;            /* pi0a */
  1203.     if_pcb->dev = 2*dev + 1;        /* pi0b */
  1204.     if_pcb->stop = if_pca->stop = pi_stop;
  1205.     if_pcb->output = if_pca->output = ax_output;
  1206.     if_pcb->raw = if_pca->raw = pi_raw;
  1207.  
  1208.     if(strcmp(argv[4],"ax25") == 0) {
  1209.         /* Must be true, was checked at top */
  1210.         if_pcb->send = if_pca->send = ax_send;
  1211.         if(if_pcb->hwaddr == NULLCHAR)
  1212.             if_pcb->hwaddr = mallocw(AXALEN);
  1213.         memcpy(if_pcb->hwaddr,Mycall,AXALEN);
  1214.         if(if_pca->hwaddr == NULLCHAR)
  1215.             if_pca->hwaddr = mallocw(AXALEN);
  1216.         memcpy(if_pca->hwaddr,Mycall,AXALEN);
  1217.     }
  1218.     /* Link em in to the interface chain */
  1219.     if_pca->next = if_pcb;
  1220.     if_pcb->next = Ifaces;
  1221.     Ifaces = if_pca;
  1222.  
  1223.     /* set params in pichan table for CHANNEL B */
  1224.  
  1225.     hp = &Pichan[2*dev+1];                /* pi1 is offset 1 */
  1226.     hp->dmachan = 0; /* Channel B does not have dma */
  1227.     hp->cardbase = Pi[dev].addr;
  1228.     hp->iface = if_pcb;
  1229.     hp->stata = Pi[dev].addr + CHANA + CTL;    /* permanent status */
  1230.     hp->statb = Pi[dev].addr + CHANB + CTL;    /* addrs for CHANA/B*/
  1231.     hp->speed = (int16)atoi(argv[9]);
  1232.     hp->base = Pi[dev].addr + CHANB;
  1233.     hp->bufsiz = atoi(argv[6]);
  1234.     hp->tstate = IDLE;
  1235.     /* default KISS Params */
  1236.     hp->params[TXDELAY] = 30;        /* 300 Ms */
  1237.     hp->params[PERSIST] = 128;        /* 50% persistence */
  1238.     hp->params[SLOTIME] = 30;        /* 300 Ms */
  1239.     hp->params[SQUELDELAY] = 3;        /* 30 Ms */
  1240.  
  1241.     xwrite_scc(hp,CTL+hp->stata,R9,FHWRES);     /* Hardware reset */
  1242.                         /* one time only */
  1243.     /* Disable interrupts with Master interrupt ctrl reg */
  1244.     xwrite_scc(hp,CTL+hp->stata,R9,0);
  1245.  
  1246.     scc_init(hp);
  1247.  
  1248.     /* Pre-allocate a receive buffer */
  1249.     i_state = dirps();
  1250.     hp->rcvbuf = alloc_mbuf(hp->bufsiz);
  1251.     restore(i_state);
  1252.     if(hp->rcvbuf == NULLBUF) {
  1253.         /* No memory, abort receiver */
  1254.         tprintf("PI: No memory available for receive buffers\n");
  1255.         /* Restore original interrupt vector */
  1256.         setirq(Pi[dev].vec,Pi[dev].oldvec);
  1257.         pinbr--;
  1258.         return(-1);
  1259.     }
  1260.     hp->rcp = hp->rcvbuf->data;
  1261.     hp->rcvbuf->cnt = 0;
  1262.     hp->sndq = NULLBUF;
  1263.  
  1264.     /* set params in pichan table for CHANNEL A */
  1265.     hp = &Pichan[2*dev];            /* pi0a is offset 0 */
  1266.     hp->dmachan = (unsigned char)atoi(argv[3]);
  1267.     /* Figure out where the dma page register is. */
  1268.     switch(hp->dmachan) {
  1269.         case 0:
  1270.         case 1:
  1271.             hp->page_addr = 0x83;
  1272.             break;
  1273.         case 2:
  1274.             hp->page_addr = 0x81;
  1275.             break;
  1276.         case 3:
  1277.             hp->page_addr = 0x82;
  1278.             break;
  1279.     }
  1280.     hp->dma_dest = hp->dmachan * 2;
  1281.     hp->dma_wcr = hp->dma_dest + 1;
  1282.  
  1283.     hp->cardbase = Pi[dev].addr;
  1284.     hp->iface = if_pca;
  1285.     hp->speed = (int16)atoi(argv[8]);
  1286.     hp->base = Pi[dev].addr + CHANA;
  1287.     hp->bufsiz = atoi(argv[6]);
  1288.     hp->tstate = IDLE;
  1289.     /* default KISS Params */
  1290.     hp->params[TXDELAY] = 15;        /* 15 mS */
  1291.     hp->params[PERSIST] = 128;        /* 50% persistence */
  1292.     hp->params[SLOTIME] = 15;        /* 15 mS */
  1293.     hp->params[SQUELDELAY] = 1;        /* 1 mS */
  1294.     newproc("buf_recover",256,buf_recover,0,hp,NULL,0);
  1295.  
  1296.  
  1297.     /* Pre-allocate a receive buffer */
  1298.     i_state = dirps();/* buffer is allocated with ints off */
  1299.     hp->rcvbuf = alloc_mbuf(hp->bufsiz);
  1300.     restore(i_state);
  1301.     if(hp->rcvbuf == NULLBUF) {
  1302.         /* No memory, abort receiver */
  1303.         tprintf("PI: No memory available for receive buffers\n");
  1304.         /* Restore original interrupt vector */
  1305.         setirq(Pi[dev].vec,Pi[dev].oldvec);
  1306.         pinbr--;
  1307.         return -1;
  1308.     }
  1309.     hp->rcvbuf->cnt = 0;
  1310.     hp->sndq = NULLBUF;
  1311.  
  1312.     /* Get a buffer for tx which does not cross a dma boundary */
  1313.     i_state = dirps();/* buffer is allocated with ints off */
  1314.     hp->txdmabuf = (char *)alloc_mbuf(hp->bufsiz);
  1315.     restore(i_state);
  1316.     if(!hp->txdmabuf)
  1317.         tprintf("PI: No memory available for transmit buffer");
  1318.  
  1319.     scc_init(hp);
  1320.     xwrite_scc(hp,CTL+hp->base,R9,MIE|NV);        /* master interrupt enable */
  1321.  
  1322.     /* Enable interrupt */
  1323.     maskon(Pi[dev].vec);
  1324.  
  1325.     return 0;
  1326. }
  1327.  
  1328. /* Shut down interface */
  1329. int
  1330. pi_stop(iface)
  1331. struct iface *iface;
  1332. {
  1333.     int16 dev;
  1334.     struct pichan *hp;
  1335.  
  1336.     dev = iface->dev;
  1337.     if(dev & 1) /* Because there are 2 devices per card */
  1338.         return 0;
  1339.     dev >>= 1;    /* Convert back into pi number */
  1340.     hp = &Pichan[2*dev];            /* pi0a is offset 0 */
  1341.  
  1342.     outportb(DMA_MASK, DMA_DISABLE|hp->dmachan); /* Disable DMA channel */
  1343.  
  1344.     /* Turn off interrupts */
  1345.     maskoff(Pi[dev].vec);
  1346.  
  1347.     /* Restore original interrupt vector */
  1348.     setirq(Pi[dev].vec,Pi[dev].oldvec);
  1349.  
  1350.     /* Force hardware reset */
  1351.     xwrite_scc(&Pichan[2*dev],CTL+Pi[dev].addr + CHANA,R9,FHWRES);
  1352.  
  1353.     return 0;
  1354. }
  1355.  
  1356. /* Send raw packet on pi card */
  1357. int
  1358. pi_raw(iface,bp)
  1359. struct iface *iface;
  1360. struct mbuf *bp;
  1361. {
  1362.     char i_state;
  1363.     char kickflag;
  1364.     struct pichan *hp;
  1365.  
  1366.     dump(iface,IF_TRACE_OUT,CL_AX25,bp);
  1367.     iface->rawsndcnt++;
  1368.     iface->lastsent = secclock();
  1369.  
  1370.     hp = &Pichan[iface->dev];
  1371.     kickflag = (hp->sndq == NULLBUF) & (hp->sndbuf == NULLBUF);
  1372.     enqueue(&hp->sndq,bp);
  1373.     hp->enqueued++;
  1374.     if(kickflag)            /* simulate interrupt to xmit */
  1375.     {
  1376.         switch(hp->base & 2)
  1377.         {
  1378.             case 2:
  1379.                 a_txint(hp);        /* process interrupt */
  1380.                 break;
  1381.             case 0:
  1382.                 i_state = dirps();
  1383.                 if(hp->tstate == IDLE)
  1384.                     b_txint(hp);
  1385.                 restore(i_state);
  1386.                 break;
  1387.         }
  1388.     }
  1389.     return 0;
  1390. }
  1391.  
  1392. /* display PI Channel stats */
  1393. int
  1394. dopistat()
  1395. {
  1396.     struct pichan *hp;
  1397.     int i;
  1398.  
  1399.     tprintf("PI Board Statistics:\n\n");
  1400.     tprintf("Base Addr  Rxints  Txints  Exints  TxFrms  RxFrms  Crcerr  RxOvrs  TxUndr \n");
  1401.     tprintf("---------  ------  ------  ------  ------  ------  ------  ------  ------ \n");
  1402.     for(i=0; i<pinbr*2; i++)
  1403.     {
  1404.         hp = &Pichan[i];
  1405.  
  1406.         tprintf("0x%03x    % 8lu% 8lu% 8lu% 8u% 8u% 8u% 8u% 8u\nRcv State=%s ",
  1407.             hp->base, hp->rxints, hp->txints, hp->exints, hp->enqueued,
  1408.             hp->rxframes, hp->crcerr, hp->rovers, hp->tunders,
  1409.             hp->rstate==0 ?
  1410.                 "IDLE" : hp->rstate==1 ?
  1411.                     "ACTIVE" : hp->rstate==2 ?
  1412.                         "RXERROR" : hp->rstate==3 ?
  1413.                             "RXABORT":"TOOBIG"
  1414.         );
  1415.  
  1416.         tprintf("Tstate = %s\n",
  1417.             hp->tstate == 0 ?
  1418.                 "IDLE" : hp->tstate == 1 ?
  1419.                     "ACTIVE" : hp->tstate == 2 ?
  1420.                         "UNDERRUN" : hp->tstate == 3 ?
  1421.                             "FLAGOUT" : hp->tstate == 4 ?
  1422.                                 "DEFER" : hp->tstate == 5 ?
  1423.                                     "TXDELAY" : "CRCOUT"
  1424.         );
  1425.     }
  1426.     return 0;
  1427. }
  1428.  
  1429. /* Subroutine to set kiss params in channel tables */
  1430. int
  1431. pi_ctl(iface,argc,argv)
  1432. struct iface *iface;
  1433. int argc;
  1434. char *argv[];
  1435. {
  1436.     struct pichan *hp;
  1437.     int p, v;
  1438.  
  1439.     if(argc < 2){
  1440.         tprintf("PI: Insufficient parameters\n");
  1441.         return 1;
  1442.     }
  1443.     hp = &Pichan[iface->dev]; /* point to channel table */
  1444.     p = atoi(argv[0]);          /* parameter in binary */
  1445.     if(p > 3){
  1446.         tprintf("PI: Parameter %d out of range\n",p);
  1447.         return 1;
  1448.     }
  1449.     v = atoi(argv[1]);          /* value to be loaded */
  1450.     hp->params[p] = v;          /* Stuff in Kiss array */
  1451.     return 0;
  1452. }
  1453.  
  1454.