home *** CD-ROM | disk | FTP | other *** search
/ The Pier Shareware 6 / The_Pier_Shareware_Number_6_(The_Pier_Exchange)_(1995).iso / 024 / psi110g.zip / PI.C < prev    next >
C/C++ Source or Header  |  1994-04-17  |  53KB  |  1,580 lines

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