home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 3 / hamradioversion3.0examsandprograms1992.iso / packet / n17jsrc / pi.c < prev    next >
C/C++ Source or Header  |  1991-05-31  |  42KB  |  1,534 lines

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