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