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

  1. /****************************************************************************
  2. *
  3. *            COPYRIGHT 1990,91,92 BY GRACILIS INC.
  4. *
  5. *                          623 Palace St.
  6. *                        Aurora, Il. 60506
  7. *
  8. * GRACILIS, INC., MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS
  9. * SOFTWARE FOR ANY PURPOSE.
  10. *
  11. * THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
  12. *
  13. * Permission is granted for non-commercial distribution only.
  14. *
  15. ******************************************************************************/
  16.   
  17. /****************************************************************************
  18. *
  19. *
  20. * File: twin_dr.c
  21. *
  22. * Rev : 3.0
  23. *
  24. * Description:
  25. *
  26. *    This File contains routines that implement PackeTwin
  27. *    synchronous SCC driver with an interface to KA9Q's TCP/IP suite.
  28. *
  29. *
  30. * Routines:
  31. *
  32. *    tsync_raw    - Applications' routine for transmitting
  33. *                   a message via tsync_driver.
  34. *
  35. *    tsync_stop   - Stop I/O
  36. *
  37. *    tsync_recv   - Applications' routine for receiving a message
  38. *                   from the tsync_driver.   Left over from NET.
  39. *
  40. *
  41. *    tsync_hwinit - Initialize the SCC chip for synchronous operation.
  42. *
  43. *    tsync_txisr  - Handles transmit interrupts.
  44. *
  45. *    tsync_rxisr  - Handles receive interrupts.
  46. *
  47. *    tsync_xstatisr - Handles the SCC's external status interrupts.
  48. *
  49. *    transon      - Turn-on transmitter and turn-off receiver or
  50. *                   turn-off transmitter and turn-on receiver.
  51. *                   Will change txstate.  Also
  52. *                   handles time delays needed for data set
  53. *                   control signals (RTS).
  54. *
  55. */
  56.   
  57. #include <dos.h>
  58. #include "global.h"
  59. #ifdef PACKETWIN
  60. #include "hardware.h"
  61. #include "mbuf.h"
  62. #include "iface.h"
  63. #include "ax25.h"
  64. #include "trace.h"
  65. #include "proc.h"
  66. #include "pktdrvr.h"
  67. #include "z8530.h"
  68. #include "gracilis.h"
  69. #include "twin.h"
  70.   
  71. #ifdef TSYNC_DEBUG
  72. unsigned char Lastint;
  73. #endif
  74.   
  75. #ifdef SCOPE_LOOP
  76. unsigned char scope_state = 0;
  77. #endif
  78.   
  79.   
  80. /* interrupt handler */
  81. extern INTERRUPT twinvec();
  82.   
  83. INTERRUPT (*Twin_oldvec) __ARGS((void)); /* Old vector contents */
  84. INTERRUPT (*Twin_handler) __ARGS((void)) = { twinvec };
  85.   
  86. unsigned int    Twin_io_base = 0x230;
  87. int16                   Twin_vector;
  88. int                     Twin_cputype;
  89.   
  90. /* The pwait/psignal inter-process communication wake-up array */
  91. /* for getting pre-allocated receive buffers */
  92. int  Twin_bufpp[5];
  93.   
  94. /* The pwait/psignal inter-process communication wake-up array */
  95. /* for kicking the transmitter */
  96. int  Twin_kickpp[5];
  97.   
  98. /* The pwait/psignal inter-process communication wake-up array */
  99. /* for free-ing transmitted messages */
  100. int  Twin_freetxpp[5];
  101.   
  102. uchar                   Twin_sercfg = 0;                /* image of the SERIAL_CFG port */
  103. uchar                   Twin_dmacfg = 0;                /* image of the DMA_CFG port */
  104.   
  105. /* Master device control blocks for the Tsync drivers... */
  106. UNI_DCB Twin_udcb[2] = {
  107.     FALSE, 0, NULL, NULL, NULL, NULL, NULL,
  108.     FALSE, 0, NULL, NULL, NULL, NULL, NULL,
  109. };
  110.   
  111. /* a simple delay instruction... */
  112. int     nop1;
  113. #define nop nop1++;
  114.   
  115. void tsync_txisr(DCB *);
  116. void tsync_entpt(void);
  117. void empty_scc(int16,int16);
  118. void tsync_srcisr(DCB *);
  119. void time_wait(DCB *,struct drv_timer *,int16,void (*timerfunc)(),unsigned long);
  120. void transon(DCB *,int16);
  121. void tsync_persist(DCB *);
  122. void tsync_sqdelay(DCB *);
  123. void tsync_txondelay(DCB *);
  124.   
  125. /* Send raw packet */
  126. int
  127. tsync_raw(intfp, mbufp)
  128. register struct iface *intfp;
  129. register struct mbuf *mbufp;
  130. {
  131.     register DCB *dcbp;
  132.     register struct drvbuf *xbufp ;
  133.     int16  msgsize;
  134.     int i_state;
  135.   
  136. #ifdef TSYNC_DEBUG_PRT
  137.     int16  pullsize;
  138. #endif
  139.   
  140. #ifdef OLD_KA9Q
  141.     dump(intfp, IF_TRACE_OUT, CL_AX25, mbufp);
  142. #else
  143.     dump(intfp,IF_TRACE_OUT,mbufp);
  144. #endif
  145.   
  146.     dcbp = (DCB *)Twin_udcb[intfp->dev].dcbp;
  147.   
  148.     /* get packet's transmission size */
  149.     msgsize = len_p(mbufp);
  150.   
  151.     xbufp = (struct drvbuf *)malloc(sizeof(struct drvbuf) + msgsize);
  152.   
  153.     /* If no memory for buffering... then dump the packet on floor */
  154.     /* and return error to caller */
  155.     if(xbufp == (struct drvbuf *)NULL)
  156.     {
  157.         free_p(mbufp);
  158.         return(-1);
  159.     }
  160.   
  161.   
  162.     xbufp->msgsize = msgsize;
  163.     xbufp->next = (struct drvbuf *)NULLBUF;
  164.   
  165. #ifdef TSYNC_DEBUG_PRT
  166.     if ( (pullsize = dqdata(mbufp, &(xbufp->buf), msgsize+1)) != msgsize )
  167.     {   /* somethings wrong.  should have gotten all of message */
  168.         printf("tsync_raw error wanted %d bytes pullup-up got only %d\n",
  169.         msgsize, pullsize);
  170.     }
  171. #else
  172.     /* there will be no check for mismatching msgsize and pullsize */
  173.     dqdata(mbufp, &(xbufp->buf), msgsize);
  174. #endif
  175.   
  176.     /* now enqueue the message !!! */
  177.     i_state = dirps();
  178.     if ( dcbp->xmtq == (struct drvbuf *)NULLBUF )
  179.     {
  180.         dcbp->xmtq = dcbp->xmtqtail = xbufp;
  181.     }
  182.     else
  183.     {
  184.         dcbp->xmtqtail->next = xbufp;
  185.         dcbp->xmtqtail = xbufp;
  186.     }
  187.   
  188.     /* Note tsync_txisr must be able to run from ISR level as well */
  189.     /* as from "task" level, since tsync_raw is called from task */
  190.     /* level */
  191.   
  192.     /* Only if the transmitter is not doing anything then call it */
  193.   
  194.     if ( dcbp->txstate == IDLE )tsync_txisr(dcbp);
  195.   
  196.     restore(i_state);
  197.   
  198.     return(0);
  199. }
  200.   
  201. /*
  202.  * Master interrupt handler.  One interrupt at a time is handled.
  203.  * here. Service routines are called from here.
  204.  *
  205.  * This 8530 interrupt handler will take care of both async and
  206.  * sync drivers' interrupts.
  207.  */
  208.   
  209. /******************************************************/
  210. /* 85230 Mods:                                        */
  211. /******************************************************/
  212. /* NOTE: This interrupt handler is constructed to get */
  213. /*              around a bug in the Zilog 85c230 while            */
  214. /*              still allowing use of it's advanced FIFOs     */
  215. /*                                                    */
  216. /*              The basic bug is as follows...                            */
  217. /*                      If an interrupt driver is written for the */
  218. /*                      85230, which does NOT make use of the     */
  219. /*                      automatic vector generation facilities    */
  220. /*                      provided by RR2,      AND.....            */
  221. /*                      If RR1 is used as the ONLY means of       */
  222. /*                      identifying the End of a received frame,  */
  223. /*                      then the 85230 will mis-report the EOF    */
  224. /*          when the 1st byte of a CRC is read from   */
  225. /*                      the receive FIFO, resulting in checking   */
  226. /*                      the CRC status flag at the wrong time.    */
  227. /*          This of course then indicates a CRC       */
  228. /*                      error, and results in the driver          */
  229. /*          discarding an otherwise good frame...     */
  230. /*                                                                                                        */
  231. /*              The FIX:                                                                          */
  232. /*                      The Basic idea here is to simulate the    */
  233. /*          use of true VECTORED interrupts.          */
  234. /*                                                    */
  235. /*                      First look for a pending interrupt in     */
  236. /*                      RR3, then read the VECTOR which would     */
  237. /*                      have been generated IF we were using      */
  238. /*                      vectored interrupts.  Dispatch to the     */
  239. /*                      appropriate handler routine.                      */
  240. /*                                                                                                        */
  241. /*              The reason this approach works is that the    */
  242. /*              Special Receive condition interrupt VECTOR    */
  243. /*              is not asserted until AFTER the first CRC     */
  244. /*              byte is read from the FIFO.  This is the      */
  245. /*              expected behaviour, and allows the programmer */
  246. /*              to read the second CRC byte, and know that    */
  247. /*              he/she may appropriately check the CRC status */
  248. /*      indicator, for the completed frame.           */
  249. /*              Additionally, it is known at this point that  */
  250. /*              the last two bytes received are the CRC bytes */
  251. /*      which must be discarded, since they are not   */
  252. /*              a part of the user data frame.                */
  253. /*                                                    */
  254. /* MORAL: Dont believe RR1's end of received frame    */
  255. /*        indication, until you have first waited     */
  256. /*        for a SPECIAL RECEIVE CONDITION VECTOR      */
  257. /*        to be asserted... or YOU'll be SORRY!!!     */
  258. /******************************************************/
  259. void
  260. tsync_entpt()
  261. {
  262.     register char st;
  263.   
  264. #ifdef notdef
  265.     int i_state;
  266. #endif
  267.   
  268.     register DCB  *dcbp;
  269.     register int16  ctl;
  270.     register unsigned intreg;
  271.     struct drv_timer *tblk;
  272.     void    (*timer_func)(unsigned long);
  273.   
  274. #ifdef notdef
  275.     i_state = dirps();
  276. #endif
  277.   
  278.     intreg = inportb( Twin_io_base + INT_REG);
  279.   
  280.     while((intreg & (0x07)) != 0x07 )
  281.     {
  282.   
  283.   
  284.       /* Read interrupt pending register from channel A */
  285.         while(Twin_read_scc( Twin_io_base+SCCA_CMD,R3) != 0 )
  286.         {
  287.         /* Get interrupt vector info from Channel B RR2 */
  288.             st = (Twin_read_scc( Twin_io_base+SCCB_CMD,R2) & 0x0E);
  289.   
  290. #ifdef TSYNC_DEBUG
  291.             Lastint = st;
  292. #endif
  293.             switch(st)
  294.             {
  295.                 case    VEC_CHB_TBE:
  296.                 /* Channel B Transmit Int Pending */
  297.                     dcbp = (DCB *)Twin_udcb[TWINCOMM2].dcbp;
  298.                 /* milt tsync_txisr(dcbp); */
  299.                 /* Call the Transmit Buffer Empty Handler */
  300.                     (*(Twin_udcb[TWINCOMM2].prev_vec2))(dcbp);
  301.                     ctl = (int16)(Twin_io_base+SCCB_CMD);
  302.                     break;
  303.   
  304.                 case    VEC_CHB_XTS:
  305.                 /* Channel B External Status Int */
  306.                     dcbp = (DCB *)Twin_udcb[TWINCOMM2].dcbp;
  307.                 /* milt tsync_xstatisr(dcbp); */
  308.                 /* Call the External Status Change Handler */
  309.                     (*(Twin_udcb[TWINCOMM2].prev_vec4))(dcbp);
  310.                     ctl = (int16)(Twin_io_base+SCCB_CMD);
  311.                     break;
  312.   
  313.                 case    VEC_CHB_RCAV:
  314.                 /* Channel B Rcv Interrupt Pending */
  315.                     dcbp = (DCB *)Twin_udcb[TWINCOMM2].dcbp;
  316.                 /* milt tsync_rxisr(dcbp); */
  317.                 /* Call the Receive Character Available Handler */
  318.                     (*(Twin_udcb[TWINCOMM2].prev_vec3))(dcbp);
  319.                     ctl = (int16)(Twin_io_base+SCCB_CMD);
  320.                     break;
  321.   
  322.                 case    VEC_CHB_SRC:
  323.                 /* Channel B Special Rcv Int Pending */
  324.                     dcbp = (DCB *)Twin_udcb[TWINCOMM2].dcbp;
  325.                 /* milt tsync_rxisr(dcbp); */
  326.                 /* Call the Special Receive Condition Handler */
  327.                     (*(Twin_udcb[TWINCOMM2].prev_vec3))(dcbp);
  328.                     ctl = (int16)(Twin_io_base+SCCB_CMD);
  329.                     break;
  330.   
  331.                 case    VEC_CHA_TBE:
  332.                 /* Channel A Transmit Int Pending */
  333.                     dcbp = (DCB *)Twin_udcb[TWINCOMM1].dcbp;
  334.                 /* milt tsync_txisr(dcbp); */
  335.                 /* Call the Transmit Buffer Empty Handler */
  336.                     (*(Twin_udcb[TWINCOMM1].prev_vec2))(dcbp);
  337.                     ctl = (int16)(Twin_io_base+SCCA_CMD);
  338.                     break;
  339.   
  340.                 case    VEC_CHA_XTS:
  341.                 /* Channel A External Status Int */
  342.                     dcbp = (DCB *)Twin_udcb[TWINCOMM1].dcbp;
  343.                 /* milt tsync_xstatisr(dcbp); */
  344.                 /* Call the External Status Change Handler */
  345.                     (*(Twin_udcb[TWINCOMM1].prev_vec4))(dcbp);
  346.                     ctl = (int16)(Twin_io_base+SCCA_CMD);
  347.                     break;
  348.   
  349.                 case    VEC_CHA_RCAV:
  350.                 /* Channel A Rcv Interrupt Pending */
  351.                     dcbp = (DCB *)Twin_udcb[TWINCOMM1].dcbp;
  352.                 /* milt tsync_rxisr(dcbp); */
  353.                 /* Call the Receive Character Available Handler */
  354.                     (*(Twin_udcb[TWINCOMM1].prev_vec3))(dcbp);
  355.                     ctl = (int16)(Twin_io_base+SCCA_CMD);
  356.                     break;
  357.   
  358.                 case    VEC_CHA_SRC:
  359.                 /* Channel A Special Rcv Int Pending */
  360.                     dcbp = (DCB *)Twin_udcb[TWINCOMM1].dcbp;
  361.                 /* milt tsync_rxisr(dcbp); */
  362.                 /* Call the Special Receive Condition Handler */
  363.                     (*(Twin_udcb[TWINCOMM1].prev_vec3))(dcbp);
  364.                     ctl = (int16)(Twin_io_base+SCCA_CMD);
  365.                     break;
  366.             }
  367.   
  368.         /* Reset highest interrupt under service */
  369. #ifdef TSYNC_DEBUG
  370.             Twin_write_scc(ctl,R0,(dcbp->wr0 = RES_H_IUS));
  371. #else
  372.             Twin_write_scc(ctl,R0,RES_H_IUS);
  373. #endif
  374.         }
  375.   
  376.         if(!(intreg & PKTWIN_TMR1_MSK))
  377.         {
  378.             dcbp = (DCB *)Twin_udcb[TWINCOMM1].dcbp;
  379.             tblk = dcbp->timer1;
  380.         /* Now clear the timer interrupt */
  381.             inportb(Twin_io_base + CLR_TMR1);
  382.   
  383.         /* Now perform the timer's requested function */
  384.             if(tblk->thandler != NULL)
  385.             {
  386.                 timer_func = tblk->thandler;
  387.                 tblk->thandler = (void (*)())NULL;
  388.                 (timer_func)(tblk->targ);
  389.             }
  390.         }
  391.   
  392.   
  393.         if(!(intreg & PKTWIN_TMR2_MSK))
  394.         {
  395.             dcbp = (DCB *)Twin_udcb[TWINCOMM2].dcbp;
  396.             tblk = dcbp->timer1;
  397.         /* Now clear the timer interrupt */
  398.             inportb(Twin_io_base + CLR_TMR2);
  399.   
  400.         /* Now perform the timer's requested function */
  401.             if(tblk->thandler != NULL)
  402.             {
  403.                 timer_func = tblk->thandler;
  404.                 tblk->thandler = (void (*)())NULL;
  405.                 (timer_func)(tblk->targ);
  406.             }
  407.   
  408.         }
  409.   
  410.         intreg = inportb( Twin_io_base + INT_REG);
  411.   
  412.     }
  413.   
  414. #ifdef notdef
  415. /* Dont need this... causewe only got here though an int... */
  416.     restore(i_state);
  417. #endif
  418. }
  419.   
  420.   
  421. /*
  422.  * External/Status interrupts caused by a receiver abort,
  423.  * a Transmit UNDERRUN/EOM.
  424.  * SCC enters hunt mode on  an abort.
  425.  *
  426.  * On a Transmit Underrun, change state and
  427.  * issue a reset command for it, and return.
  428.  */
  429. void
  430. tsync_xstatisr(dcbp)
  431. register DCB *dcbp;
  432. {
  433.     register uchar  scc_stat,newstat,new_xbits;
  434.   
  435.     /* find out why the external/status interrupt occurred */
  436.     scc_stat = Twin_read_scc(dcbp->zhwmap.ctl,R0);
  437.   
  438. /* 9/23/91 DGL Try to fix possible race condition */
  439.     /* reset external status latch  to enable future changes to catch us */
  440.   
  441. #ifdef TSYNC_DEBUG
  442.     Twin_write_scc(dcbp->zhwmap.ctl,R0,(dcbp->wr0 = RES_EXT_INT));
  443. #else
  444.     Twin_write_scc(dcbp->zhwmap.ctl,R0,RES_EXT_INT);
  445. #endif
  446.   
  447.     new_xbits = scc_stat ^ dcbp->extreg;
  448.   
  449.     /* Check for Tx UNDERRUN/EOM  */
  450.     if(new_xbits & TxEOM )
  451.     {
  452.         if(dcbp->dma_flg == TRUE)
  453.         {
  454.             /* Disable this DMA channel */
  455.             outportb(DMAWSMR,dcbp->dma_tx_chan | 0x04);
  456.   
  457.             dcbp->txstate = TX_DONE;
  458.   
  459.             /* update the xmit data tally*/
  460.             dcbp->txbytecnt += dcbp->cur_xbytes;
  461.   
  462.             /* don't allow Underruns to interrupt us */
  463.             Twin_write_scc(dcbp->zhwmap.ctl,R15,(dcbp->wr15 &= ~0x40));
  464.             /* set the TxEOM bit in the image */
  465.             dcbp->extreg |= TxEOM;
  466.   
  467.   
  468.             /* enable the tx empty interrupt... */
  469.             /* so it can catch us if necessary */
  470.             /* This handles condition where the buffer */
  471.             /* goes empty while we're checking... */
  472.             /* Avoid's a race. 9/23/91 */
  473. #ifdef TSYNC_DEBUG
  474.             Twin_write_scc(dcbp->zhwmap.ctl,R1,(dcbp->wr1 = 0xfb));
  475. #else
  476.             Twin_write_scc(dcbp->zhwmap.ctl,R1,0xfb);
  477. #endif
  478.   
  479.             /* Now check to see if the CRC has already cleared */
  480.             /* the SCC's xmit buffer... */
  481.             newstat = Twin_read_scc(dcbp->zhwmap.ctl,R0);
  482.   
  483.             /* If so, turn off the tx empty interrupt we just enabled */
  484.             /* and process the end of frame condition */
  485.             if(newstat & Tx_BUF_EMP)
  486.             {
  487.                 /* Rx and Extern ints on : No Tx ints */
  488. #ifdef TSYNC_DEBUG
  489.                 Twin_write_scc(dcbp->zhwmap.ctl,R1,(dcbp->wr1 = 0xf9));
  490. #else
  491.                 Twin_write_scc(dcbp->zhwmap.ctl,R1,0xf9);
  492. #endif
  493.   
  494.                 tsync_txisr(dcbp);
  495.             }
  496.   
  497.             /* else... it will happen under interrupt ctl */
  498.             /* when the buffer goes empty */
  499.   
  500.         }
  501.   
  502.         else
  503.         {
  504.             /* set the TxEOM bit in the image */
  505.             dcbp->extreg |= TxEOM;
  506.   
  507.   
  508.             if((dcbp->txstate == TX_ACTIVE) || (dcbp->txstate == CRCING))
  509.             {
  510.                 dcbp->txstate = TX_DONE;
  511.   
  512.                 /* don't allow Underruns to interrupt us */
  513.                 Twin_write_scc(dcbp->zhwmap.ctl,R15,(dcbp->wr15 &= ~0x40));
  514.   
  515.   
  516.                 /* if unexpected... bump transmit underrun counts */
  517.                 if( dcbp->cur_xbytes > 0 )
  518.                 {
  519.                     dcbp->txunderun++;
  520.                 }
  521.   
  522.                 /* enable the tx empty interrupt... */
  523.                 /* so it can catch us if necessary */
  524.                 /* This handles condition where the buffer */
  525.                 /* goes empty while we're checking... */
  526.                 /* Avoid's a race. 9/23/91 */
  527. #ifdef TSYNC_DEBUG
  528.                 Twin_write_scc(dcbp->zhwmap.ctl,R1,(dcbp->wr1 = 0x13));
  529. #else
  530.                 Twin_write_scc(dcbp->zhwmap.ctl,R1,0x13);
  531. #endif
  532.   
  533.                 /* check to see if the CRC has already cleared */
  534.                 /* the SCC's xmit buffer... */
  535.                 newstat = Twin_read_scc(dcbp->zhwmap.ctl,R0);
  536.   
  537.                 /* If so, turn off the tx empty interrupt we just enabled */
  538.                 /* and process the end of frame condition */
  539.                 if(newstat & Tx_BUF_EMP)
  540.                 {
  541. #ifdef TSYNC_DEBUG
  542.                     Twin_write_scc(dcbp->zhwmap.ctl,R1,(dcbp->wr1 = 0x11));
  543. #else
  544.                     Twin_write_scc(dcbp->zhwmap.ctl,R1,0x11);
  545. #endif
  546.                     tsync_txisr(dcbp);
  547.                 }
  548.   
  549.                 /* else... it will happen under interrupt ctl */
  550.   
  551.             }
  552.         }
  553.   
  554.     }
  555.   
  556.     /* Receive Mode only
  557.      * This triggers when hunt mode is entered, & since an ABORT
  558.      * automatically enters hunt mode, we use that to clean up
  559.      * any waiting garbage
  560.      */
  561.     if(new_xbits & BRK_ABRT )
  562.     {
  563.         if(scc_stat & BRK_ABRT ) dcbp->extreg |= BRK_ABRT;
  564.         else dcbp->extreg &= ~BRK_ABRT;
  565.         dcbp->rxstate = RXABORT;
  566.         dcbp->rxabortcnt++;       /* bump aborts */
  567.   
  568.         /* No  more Abort interrupts  */
  569. #ifdef notdef
  570.         Twin_write_scc(dcbp->zhwmap.ctl,R15,(dcbp->wr15 &= ~(0x80)));
  571. #endif
  572.         if(dcbp->dma_flg == TRUE)
  573.         {
  574.             rxprime_dma(dcbp);        /* restart for a new frame */
  575.         }
  576.         else
  577.         {
  578.             /* reset err latch */
  579. #ifdef TSYNC_DEBUG
  580.             Twin_write_scc(dcbp->zhwmap.ctl,R0,(dcbp->wr0 = ERR_RES));
  581. #else
  582.             Twin_write_scc(dcbp->zhwmap.ctl,R0,ERR_RES);
  583. #endif
  584.             /* read and toss any  data */
  585.             inportb(dcbp->zhwmap.data);
  586.             inportb(dcbp->zhwmap.data);
  587.             inportb(dcbp->zhwmap.data);
  588.             inportb(dcbp->zhwmap.data);
  589.   
  590.             /* make sure dcbp->rxbufp has a data buffer to work with!!! */
  591.             dcbp->rxcurp = dcbp->rxbufp->data;
  592. #ifdef OLD_KA9Q
  593.             dcbp->rxbufp->cnt = sizeof(struct phdr);
  594. #else
  595.             dcbp->rxbufp->cnt = 0;
  596. #endif
  597.             /* resync the receiver... */
  598. #ifdef TSYNC_DEBUG
  599.             Twin_write_scc(dcbp->zhwmap.ctl,R3,(dcbp->wr3 = 0xf9));
  600. #else
  601.             Twin_write_scc(dcbp->zhwmap.ctl,R3,0xf9);
  602. #endif
  603.   
  604.         }
  605.     }
  606.     if(new_xbits & DCD )
  607.     {
  608.         if((scc_stat & DCD) == 0)
  609.         {
  610.             dcbp->extreg &= ~DCD;
  611.             if(dcbp->dma_flg == TRUE)
  612.             {
  613.                 rxprime_dma(dcbp);        /* restart for a new frame */
  614.             }
  615.             else
  616.             {
  617.                 /* reset err latch */
  618. #ifdef TSYNC_DEBUG
  619.                 Twin_write_scc(dcbp->zhwmap.ctl,R0,(dcbp->wr0=ERR_RES));
  620. #else
  621.                 Twin_write_scc(dcbp->zhwmap.ctl,R0,ERR_RES);
  622. #endif
  623.                 /* read and toss any  data */
  624.                 inportb(dcbp->zhwmap.data);
  625.                 inportb(dcbp->zhwmap.data);
  626.                 inportb(dcbp->zhwmap.data);
  627.                 inportb(dcbp->zhwmap.data);
  628.   
  629.                 /* make sure dcbp->rxbufp has a data buffer to work with!!! */
  630.                 dcbp->rxcurp = dcbp->rxbufp->data;
  631. #ifdef OLD_KA9Q
  632.                 dcbp->rxbufp->cnt = sizeof(struct phdr);
  633. #else
  634.                 dcbp->rxbufp->cnt = 0;
  635. #endif
  636.                 /* resync the receiver... */
  637.                 /* Rx 8 bit/chars, enter hunt mode, CRC enable */
  638. #ifdef TSYNC_DEBUG
  639.                 Twin_write_scc(dcbp->zhwmap.ctl,R3,(dcbp->wr3 = 0xf9));
  640. #else
  641.                 Twin_write_scc(dcbp->zhwmap.ctl,R3,0xf9);
  642. #endif
  643.   
  644.             }
  645.         }
  646.         else    dcbp->extreg |= DCD;
  647.     }
  648.   
  649.     if(new_xbits & CTS )
  650.     {
  651.         if((scc_stat & CTS) == 0)
  652.         {
  653.             dcbp->extreg &= ~CTS;
  654.   
  655.             dcbp->txctslost++;
  656.   
  657.             if((dcbp->txstate == TX_ACTIVE) || (dcbp->txstate == CRCING))
  658.             {
  659.                 dcbp->txstate = TX_DONE;
  660.   
  661.                 /* don't allow Underruns to interrupt us */
  662.                 Twin_write_scc(dcbp->zhwmap.ctl,R15,(dcbp->wr15 &= ~0x40));
  663.   
  664.   
  665.                 /* if unexpected... bump transmit underrun counts */
  666.                 if( dcbp->cur_xbytes > 0 )
  667.                 {
  668.                     dcbp->txunderun++;
  669.                 }
  670.   
  671.                 /* Toss the frame being sent, and continue... */
  672.                 tsync_txisr(dcbp);
  673.   
  674.             }
  675.         }
  676.         else    dcbp->extreg |= CTS;
  677.     }
  678.   
  679. #ifdef notdef           /* fix race 9/23/91 */
  680.   
  681.     /* reset external status latch */
  682. #ifdef TSYNC_DEBUG
  683.     Twin_write_scc(dcbp->zhwmap.ctl,R0,(dcbp->wr0 = RES_EXT_INT));
  684. #else
  685.     Twin_write_scc(dcbp->zhwmap.ctl,R0,RES_EXT_INT);
  686. #endif
  687.   
  688. #endif
  689.   
  690.     return;
  691. }
  692. /*
  693.  * end of tsync_xstatisr
  694.  ******************************************************************/
  695.   
  696.   
  697. /*
  698.  * Receive ISR.
  699.  * The first receive buffer is pre-allocated
  700.  * in the init routine.  Thereafter, it is filled here, queued out, and a
  701.  * new one acquired.  CRC, OVERRUN and TOOBIG errors merely 'rewind' the
  702.  * pointers and reuse the same buffer.
  703.  */
  704. void
  705. tsync_rxisr(dcbp)
  706. register DCB *dcbp;
  707. {
  708.     register int16 ctl;
  709.     int16 data;
  710.     struct mbuf *f_dequeavail();
  711.     unsigned char   vecmsk;
  712.   
  713.     /* If this channel is a DMA channel handle it elsewhere */
  714.     if(dcbp->dma_flg == TRUE)
  715.     {
  716.         tsync_rxdmaisr(dcbp);
  717.         return;
  718.     }
  719.   
  720.     /* speed up access to 8530 regs */
  721.     ctl = dcbp->zhwmap.ctl;
  722.     data = dcbp->zhwmap.data;
  723.   
  724.   
  725.     /* Get interrupt vector info from Channel B RR2 */
  726.     vecmsk = (Twin_read_scc( Twin_io_base+SCCB_CMD,R2) & 0x0E);
  727.   
  728.     /* If this is an SRC interrupt... handle it that way... */
  729.     if((vecmsk == VEC_CHA_SRC) || (vecmsk == VEC_CHB_SRC))
  730.     {
  731.         tsync_srcisr(dcbp);
  732.         return;
  733.     }
  734.   
  735.   
  736.     /* Check status of receive interrupt */
  737.     if(Twin_read_scc(ctl,R0) & Rx_CH_AV)
  738.     {
  739.   
  740.         /* get char and store it */
  741.         *dcbp->rxcurp++ = inportb(data);
  742.   
  743.         /* tally data byte received */
  744.         dcbp->rxbytecnt++;
  745.   
  746.         /* Allow aborts to get us after we receive a first char */
  747. #ifdef OLD_KA9Q
  748.         if(dcbp->rxbufp->cnt == sizeof(struct phdr))
  749. #else
  750.             if(dcbp->rxbufp->cnt == 0)
  751. #endif
  752.             {
  753.             /* allow Aborts to interrupt us. */
  754.                 Twin_write_scc(ctl,R15,(dcbp->wr15 |= 0x80));
  755.             }
  756.   
  757.         /* bump count & check for TOOBIG frames... */
  758. #ifdef OLD_KA9Q
  759.         if ((++dcbp->rxbufp->cnt) >= (dcbp->rxbufsize+sizeof(struct phdr)))
  760. #else
  761.             if ((++dcbp->rxbufp->cnt) >= dcbp->rxbufsize)
  762. #endif
  763.             {
  764.             /* dump buffer - incoming packet is too big */
  765.                 dcbp->rxtruncnt++;
  766.   
  767.             /* read all the data out of the rx fifo... */
  768.             /* and TOSS it.. */
  769.                 empty_scc(ctl,data);
  770.   
  771.             /* reset buf "pointers" - dump data */
  772.                 dcbp->rxcurp = dcbp->rxbufp->data;
  773. #ifdef OLD_KA9Q
  774.                 dcbp->rxbufp->cnt = sizeof(struct phdr);
  775. #else
  776.                 dcbp->rxbufp->cnt = 0;
  777. #endif
  778.             /* restart the receiver in HUNT  MODE... */
  779.             /* to resync it... */
  780. #ifdef TSYNC_DEBUG
  781.                 Twin_write_scc(dcbp->zhwmap.ctl,R3,(dcbp->wr3 = 0xf9));
  782. #else
  783.                 Twin_write_scc(dcbp->zhwmap.ctl,R3,0xf9);
  784. #endif
  785.             }
  786.   
  787.     }
  788.   
  789.     return;
  790. }
  791. /*
  792.  * end of tsync_rxisr
  793.  ****************************************************************/
  794.   
  795.   
  796. /****************************************************************/
  797. /* Special Receive Condition Interrupt Handler... */
  798. /****************************************************************/
  799. void
  800. tsync_srcisr(dcbp)
  801. register DCB *dcbp;
  802. {
  803.     unsigned char rx1stat;
  804.     struct mbuf *tmpbufp;
  805.     struct mbuf *f_dequeavail();
  806.     register int16 ctl;
  807.     int16 data;
  808.   
  809.         /* speed up access to 8530 regs */
  810.     ctl = dcbp->zhwmap.ctl;
  811.     data = dcbp->zhwmap.data;
  812.   
  813.         /* Per ZILOG... only read R1 when R0 says there is */
  814.         /* a char waiting... */
  815.         /* get status byte from R1 */
  816.   
  817.     if(Twin_read_scc(ctl,R0) & Rx_CH_AV)
  818.     {
  819.         rx1stat = Twin_read_scc(ctl,R1);
  820.   
  821.         /* empty the 2nd CRC char */
  822.         inportb(data);
  823.   
  824.         /* The End of Frame bit is ALWAYS associated with a character,
  825.         * usually, it is the last CRC char.  Only when EOF is true can
  826.         * we look at the CRC byte to see if we have a valid frame
  827.         */
  828.         dcbp->rxpackcnt++;
  829.   
  830.         /* No  Abort interrupts  */
  831.         Twin_write_scc(ctl,R15,(dcbp->wr15 &= ~(0x80)));
  832.   
  833.         /* END OF FRAME -- Make sure Rx was active */
  834.         if(rx1stat & END_FR)
  835.         {
  836.             /* got a packet - check for CRC error */
  837.             if ( (rx1stat & CRC_ERR) ||
  838. #ifdef OLD_KA9Q
  839.                 (dcbp->rxbufp->cnt < (sizeof(struct phdr) + 10)) )
  840. #else
  841.                 (dcbp->rxbufp->cnt <  10 ) )
  842. #endif
  843.             {
  844.                 /* error occurred; toss frame */
  845.                 if (( rx1stat & CRC_ERR ) &&
  846. #ifdef OLD_KA9Q
  847.                     (dcbp->rxbufp->cnt  >= (sizeof(struct phdr) + 10)))
  848. #else
  849.                     (dcbp->rxbufp->cnt  >= 10) )
  850. #endif
  851.                     dcbp->rxcrcerrcnt++;    /* bump CRC errs */
  852.   
  853.                 /* read all data out of the rx fifo...*/
  854.                 /* and TOSS it.. */
  855.                 empty_scc(ctl,data);
  856.   
  857.                 /* reusing the old data buffer "dumps" the data */
  858.   
  859.                 /* restart the receiver in HUNT  MODE... */
  860.                 /* to resync it... */
  861. #ifdef TSYNC_DEBUG
  862.                 Twin_write_scc(dcbp->zhwmap.ctl,R3,(dcbp->wr3 = 0xf9));
  863. #else
  864.                 Twin_write_scc(dcbp->zhwmap.ctl,R3,0xf9);
  865. #endif
  866.             }
  867.             else
  868.             {
  869.                 /* Got a valid packet !! */
  870.   
  871.                 /* get next buffer */
  872.                 tmpbufp = f_dequeavail((struct mbuf **)&dcbp->rxavailq, (int16 *)&dcbp->rxavailcount);
  873.   
  874.                 if ( tmpbufp != NULLBUF )
  875.                 {
  876.   
  877.                     /* dump crc bytes, i.e. '-1' */
  878.                     dcbp->rxbufp->cnt -= 1;
  879.   
  880.                     /* new for NOS */
  881.                     /* adjust for packet header */
  882. #ifdef OLD_KA9Q
  883.                     dcbp->rxbufp->data -= sizeof(struct phdr);
  884.                     enqueue(&Hopper, dcbp->rxbufp);
  885. #else
  886.                     net_route(dcbp->iface,dcbp->rxbufp);
  887. #endif
  888.                     /* bump packets rreceived */
  889.                     /* successfully */
  890.                     dcbp->rxnqued++;
  891.   
  892.                     dcbp->rxbufp = tmpbufp;
  893.                 }
  894.   
  895.                 /* No buffers available... */
  896.                 /* re-use old buffer - dump data */
  897.                 else dcbp->nobufs++;
  898.   
  899.                 /* signal the process which */
  900.                 /* allocates the rx buffers */
  901.                 psignal(&Twin_bufpp[dcbp->dev],1);
  902.   
  903.             } /* end good packet > 10 long received */
  904.   
  905.         }       /* End of FRAME */
  906.   
  907.         /* Not EOF... check for overrun */
  908.         else if (rx1stat & Rx_OVR)
  909.         {
  910.             /* Rx overrun - toss buffer */
  911.             /* reset buffer pointers */
  912.             dcbp->rxovercnt++;      /* bump overruns */
  913.   
  914.             /* read all data out of the rx fifo...*/
  915.             /* and TOSS it.. */
  916.             empty_scc(ctl,data);
  917.   
  918.             /* reuse old rx buffer.. */
  919.             /* restart the receiver in HUNT  MODE... */
  920.             /* to resync it... */
  921. #ifdef TSYNC_DEBUG
  922.             Twin_write_scc(dcbp->zhwmap.ctl,R3,(dcbp->wr3 = 0xf9));
  923. #else
  924.             Twin_write_scc(dcbp->zhwmap.ctl,R3,0xf9);
  925. #endif
  926.         }
  927.   
  928.         /* regardless of why we terminating/restarting... */
  929.         /* make sure dcbp->rxbufp has a data buffer!!! */
  930.         dcbp->rxcurp = dcbp->rxbufp->data;
  931. #ifdef OLD_KA9Q
  932.         dcbp->rxbufp->cnt = sizeof(struct phdr);
  933. #else
  934.         dcbp->rxbufp->cnt = 0;
  935. #endif
  936.   
  937.   
  938.         /* reset err latch */
  939. #ifdef TSYNC_DEBUG
  940.         Twin_write_scc(ctl,R0,(dcbp->wr0 = ERR_RES));
  941. #else
  942.         Twin_write_scc(ctl,R0,ERR_RES);
  943. #endif
  944.     }
  945. }
  946.   
  947.   
  948.   
  949.   
  950.   
  951. /* read the SCC channel till no more data in receiver... */
  952. void
  953. empty_scc(ctl,data)
  954. int16   ctl,data;
  955. {
  956.   
  957.     while(Twin_read_scc(ctl,R0) & Rx_CH_AV)
  958.     {
  959.             /* get char and toss it */
  960.         inportb(data);
  961.     }
  962. }
  963.   
  964.   
  965. /*
  966.  * DMA Receive ISR.
  967.  * The first receive buffer is pre-allocated
  968.  * in the init routine.  Thereafter, it is filled here, queued out, and a
  969.  * new one acquired.  CRC, OVERRUN and TOOBIG errors merely 'rewind' the
  970.  * pointers and reuse the same buffer.
  971.  */
  972. tsync_rxdmaisr(dcbp)
  973. register DCB *dcbp;
  974. {
  975.     register int16 ctl;
  976.     register int16 dmacnt;
  977.     char rxstat;
  978.     int16   rxbytecnt;
  979.     struct mbuf *f_dequeavail();
  980.     struct mbuf *tmpbufp;
  981.   
  982.     /* mask off this DMA channel */
  983.     outportb(DMAWSMR,(dcbp->dma_rx_chan | 0x04));
  984.   
  985.     /* speed up access to 8530 regs */
  986.     ctl = dcbp->zhwmap.ctl;
  987.   
  988.     /* Check status of receive interrupt */
  989.     rxstat = Twin_read_scc(ctl,R1); /* get status byte from R1 */
  990.   
  991.     /* clear the DMA byte ptr FF */
  992.     outportb(DMAFFCL,00);
  993.   
  994.     /* Rx overrun - toss data by reusing the buffer */
  995.     if (rxstat & Rx_OVR ) dcbp->rxovercnt++;        /* bump overruns */
  996.   
  997.     /* The End of Frame bit is ALWAYS associated with a character,
  998.      * usually, it is the last CRC char.  Only when EOF is true can
  999.      * we look at the CRC byte to see if we have a valid frame
  1000.      */
  1001.   
  1002.     /* CRC error occurred; toss frame */
  1003.     else if ((rxstat & (CRC_ERR|END_FR)) == (CRC_ERR|END_FR) )
  1004.     {
  1005.         dcbp->rxpackcnt++;
  1006.         dcbp->rxcrcerrcnt++;
  1007.     }
  1008.     else if( rxstat & END_FR )
  1009.     {
  1010.         /* Disable further Abort interrupts  */
  1011.         Twin_write_scc(ctl,R15,(dcbp->wr15 &= ~(0x80)));
  1012.   
  1013.         dcbp->rxpackcnt++;
  1014.   
  1015.         /* calculate # of bytes received less CRC */
  1016.         dmacnt = inportb(dcbp->dma_rx_cnt_reg);
  1017.         dmacnt += (inportb(dcbp->dma_rx_cnt_reg) << 8);
  1018.   
  1019.   
  1020.         rxbytecnt = (dcbp->rxbufsize-1) - dmacnt;
  1021.   
  1022.         dcbp->rxbufp->cnt += rxbytecnt;
  1023.   
  1024.         /* # of data bytes received... Not including CRC's */
  1025.         dcbp->rxbytecnt += rxbytecnt-2;
  1026.   
  1027.         /* Make sure Rx was active */
  1028. #ifdef OLD_KA9Q
  1029.         if ( dcbp->rxbufp->cnt > sizeof(struct phdr) )
  1030. #else
  1031.             if ( dcbp->rxbufp->cnt > 0)
  1032. #endif
  1033.             {       /* then bytes have been received */
  1034.   
  1035. #ifdef OLD_KA9Q
  1036.                 if ( dcbp->rxbufp->cnt >= (sizeof(struct phdr)+10) )
  1037. #else
  1038.                     if ( dcbp->rxbufp->cnt >= 10 )
  1039. #endif
  1040.                     {
  1041.                 /* Got a valid packet !! */
  1042.   
  1043.                 /* get next buffer */
  1044.                         tmpbufp = f_dequeavail((struct mbuf **)&dcbp->rxavailq, (int16 *)&dcbp->rxavailcount);
  1045.   
  1046.                         if ( tmpbufp != NULLBUF )
  1047.                         {
  1048.   
  1049.                     /* dump crc bytes, i.e. '-2' */
  1050.                             dcbp->rxbufp->cnt -= 2;
  1051.                     /* new for NOS */
  1052.                     /* adjust for packet header */
  1053. #ifdef OLD_KA9Q
  1054.                             dcbp->rxbufp->data -= sizeof(struct phdr);
  1055.                             enqueue(&Hopper, dcbp->rxbufp);
  1056. #else
  1057.                             net_route(dcbp->iface,dcbp->rxbufp);
  1058. #endif
  1059.                     /* bump packets rreceived */
  1060.                     /* successfully */
  1061.                             dcbp->rxnqued++;
  1062.   
  1063.                             dcbp->rxbufp = tmpbufp;
  1064.                         }
  1065.   
  1066.                 /* No buffers available... */
  1067.                 /* re-use old buffer - dump data */
  1068.                         else dcbp->nobufs++;
  1069.   
  1070.                 /* signal the process which */
  1071.                 /* allocates the rx buffers */
  1072.                         psignal(&Twin_bufpp[dcbp->dev],1);
  1073.   
  1074.                     } /* end good packet > 10 long received */
  1075.   
  1076.             }  /* received frame with > 0 chars */
  1077.   
  1078.     } /* end END_FR check */
  1079.   
  1080.     rxprime_dma(dcbp);
  1081.   
  1082.     return;
  1083. }
  1084. /*
  1085.  * end of tsync_rxdmaisr
  1086.  ****************************************************************/
  1087.   
  1088. void
  1089. rxprime_dma(dcbp)
  1090. register DCB *dcbp;
  1091. {
  1092.     register int16 ctl;
  1093.     ulong realaddr;
  1094.     unsigned page;
  1095.   
  1096.     /* speed up access to 8530 regs */
  1097.     ctl = dcbp->zhwmap.ctl;
  1098.   
  1099.     /* make sure dcbp->rxbufp has data!!! */
  1100.     dcbp->rxcurp = dcbp->rxbufp->data;
  1101. #ifdef OLD_KA9Q
  1102.     dcbp->rxbufp->cnt = sizeof(struct phdr);
  1103. #else
  1104.     dcbp->rxbufp->cnt = 0;
  1105. #endif
  1106.     /* reset any errors... */
  1107. #ifdef TSYNC_DEBUG
  1108.     Twin_write_scc(ctl,R0,(dcbp->wr0 = ERR_RES));
  1109. #else
  1110.     Twin_write_scc(ctl,R0,ERR_RES);
  1111. #endif
  1112.     /* Reprime the dma pump... */
  1113.   
  1114.     /* A rendition of an absolute address for the ptr */
  1115.     realaddr = ((ulong)FP_SEG(dcbp->rxcurp) << 4) +
  1116.     (ulong)FP_OFF(dcbp->rxcurp);
  1117.   
  1118.     /* DMA page reg for 8237 */
  1119.     page = (unsigned)(realaddr >> 16);
  1120.   
  1121.     outportb(dcbp->dma_rx_pagereg,page);    /* setup 64k page */
  1122.   
  1123.   
  1124.     /* mode setup required if we are in HDX operation */
  1125.     if(dcbp->hduplex == TRUE)
  1126.     {
  1127.         outportb(DMAMODE,dcbp->dma_rx_chan |  RX_DMA);
  1128.         outportb(Twin_io_base+DMA_CFG,dcbp->dma_rx_mode);
  1129.     }
  1130.   
  1131.     /* clear the DMA byte ptr FF */
  1132.     outportb(DMAFFCL,00);
  1133.   
  1134.     /* Max xfer count setup */
  1135.     outportb(dcbp->dma_rx_cnt_reg,dcbp->rxbufsize-1);
  1136.     outportb(dcbp->dma_rx_cnt_reg,((dcbp->rxbufsize-1)>>8));
  1137.   
  1138.     /* destination buffer address */
  1139.     outportb(dcbp->dma_rx_addr_reg,(realaddr & 0xff));
  1140.     outportb(dcbp->dma_rx_addr_reg,((realaddr >> 8) & 0xff));
  1141.   
  1142.     /* If we are in DMA mode/Half duplex: Turn on the recvr */
  1143.     /* Rx 8 bit/chars, enter hunt mode, CRC enable */
  1144.     /* Autoenables... */
  1145.     if(dcbp->hduplex == TRUE)
  1146. #ifdef TSYNC_DEBUG
  1147.         Twin_write_scc(dcbp->zhwmap.ctl,R3,(dcbp->wr3 = 0xf9));
  1148. #else
  1149.     Twin_write_scc(dcbp->zhwmap.ctl,R3,0xf9);
  1150. #endif
  1151.   
  1152.     /* Enable this DMA channel */
  1153.     outportb(DMAWSMR,dcbp->dma_rx_chan);
  1154.     return;
  1155. }
  1156.   
  1157.   
  1158. /*
  1159.  * PackTen's SCC transmit interrupt service routine
  1160.  */
  1161. void
  1162. tsync_txisr(dcbp)
  1163. register DCB  *dcbp;
  1164. {
  1165.     register int16 ctl;
  1166.     register struct drvbuf *btemp;
  1167.     int i_state;
  1168.   
  1169. #ifdef TSYNC_DEBUG
  1170.     int     tstbyt_cnt= 0;
  1171. #endif
  1172.   
  1173.     /* This routine MAY be able to run with ints ENABLED later... */
  1174.     /* We need to investigate... milt / {dgl} */
  1175.     /* NEVER NEVER NEVER!!!!!!!!! */
  1176.     i_state = dirps();
  1177.   
  1178.     /* speedup access to 8530 regs */
  1179.     ctl = dcbp->zhwmap.ctl;
  1180.   
  1181.     switch (dcbp->txstate) {
  1182.   
  1183.         case TX_ACTIVE:
  1184.   
  1185.         /* Here we are actively sending a frame */
  1186.         /* We should only hit this case in NON-DMA modes */
  1187.   
  1188.         /* If there are more bytes to send... */
  1189.             if( dcbp->cur_xbytes > 0 )
  1190.             {
  1191.             /* Try to feed the ESCC/SCC as many bytes as we can */
  1192.                 while((Twin_read_scc(ctl,R0) & Tx_BUF_EMP) && (dcbp->cur_xbytes > 0))
  1193.                 {
  1194.                 /* send next char and bump the pointer */
  1195.                     outportb(dcbp->zhwmap.data,*dcbp->cur_xbufp++);
  1196.   
  1197.                 /* tally data byte sent */
  1198.                     dcbp->txbytecnt++;
  1199.                     dcbp->cur_xbytes--;
  1200. #ifdef TSYNC_DEBUG
  1201.                     tstbyt_cnt++;
  1202. #endif
  1203.                 }
  1204.   
  1205. #ifdef TSYNC_DEBUG
  1206.                 if(tstbyt_cnt > dcbp->maxtxbytes)dcbp->maxtxbytes = tstbyt_cnt;
  1207. #endif
  1208.                 if(dcbp->cur_xbytes <= 0)
  1209.                 {
  1210.   
  1211.                 /* turn-off the xmission of Abort on underrun */
  1212.                 /* To allow the CRC to go out */
  1213. #ifdef TSYNC_DEBUG
  1214.                     if(dcbp->nrzi_flg == TRUE)
  1215.                         Twin_write_scc(ctl,R10,(dcbp->wr10 = 0xa0));
  1216.                     else Twin_write_scc(ctl,R10,(dcbp->wr10 = 0x80));
  1217. #else
  1218.                     if(dcbp->nrzi_flg == TRUE)
  1219.                         Twin_write_scc(ctl,R10,0xa0);
  1220.                     else Twin_write_scc(ctl,R10,0x80);
  1221. #endif
  1222.                 /* Sent all the data bytes, now send CRCs */
  1223.                 /* CRCING is a tsync_xstatisr state */
  1224. /*                              dcbp->txstate = CRCING;
  1225. */
  1226.   
  1227.                 }
  1228.             }
  1229.   
  1230. #ifdef notdef
  1231.             if( dcbp->cur_xbytes > 0 )
  1232.             {
  1233.   
  1234.                 /* send next char and bump the pointer */
  1235.                 outportb(dcbp->zhwmap.data,*dcbp->cur_xbufp++);
  1236.   
  1237.                 /* tally data byte sent */
  1238.                 dcbp->txbytecnt++;
  1239.   
  1240.                 /* sent a byte */
  1241.                 if((--dcbp->cur_xbytes) <= 0)
  1242.                 {
  1243.   
  1244.                     /* turn-off the xmission of Abort on underrun */
  1245.                     /* To allow the CRC to go out */
  1246. #ifdef TSYNC_DEBUG
  1247.                     if(dcbp->nrzi_flg == TRUE)
  1248.                         Twin_write_scc(ctl,R10,(dcbp->wr10 = 0xa0));
  1249.                     else Twin_write_scc(ctl,R10,(dcbp->wr10 = 0x80));
  1250. #else
  1251.                     if(dcbp->nrzi_flg == TRUE)
  1252.                         Twin_write_scc(ctl,R10,0xa0);
  1253.                     else Twin_write_scc(ctl,R10,0x80);
  1254. #endif
  1255.                     /* Sent all the data bytes, now send CRCs */
  1256.                     /* CRCING is a tsync_xstatisr state */
  1257. /*                                      dcbp->txstate = CRCING;
  1258. */
  1259.   
  1260. /* for slow PCs... */
  1261.                 }
  1262.   
  1263.             }
  1264. #endif
  1265.   
  1266.             else
  1267.             {
  1268.   
  1269. #ifdef TSYNC_DEBUG
  1270.             /* reset Tx int pending  to allow the */
  1271.             /* Underrun/EOM to happen */
  1272.                 Twin_write_scc(ctl,R0,(dcbp->wr0 = 0x28));
  1273.   
  1274.             /* disable tx ints... */
  1275.                 Twin_write_scc(ctl,R1,(dcbp->wr1 = 0x11));
  1276. #else
  1277.             /* reset Tx int pending  to allow the */
  1278.             /* Underrun/EOM to happen */
  1279.                 Twin_write_scc(ctl,R0,0x28);
  1280.   
  1281.             /* disable tx ints... */
  1282.                 Twin_write_scc(ctl,R1,0x11);
  1283. #endif
  1284.   
  1285.             /* Sent all the data bytes, now send CRCs */
  1286.             /* CRCING is a tsync_xstatisr state */
  1287.                 dcbp->txstate = CRCING;
  1288.   
  1289.             }
  1290.             break;
  1291.   
  1292.         case CRCING:
  1293.   
  1294.             /* reset Tx int pending  to allow the */
  1295.             /* Underrun/EOM to happen */
  1296. #ifdef TSYNC_DEBUG
  1297.             Twin_write_scc(ctl,R0,(dcbp->wr0 = 0x28));
  1298. #else
  1299.             Twin_write_scc(ctl,R0,0x28);
  1300. #endif
  1301.             break;
  1302.   
  1303.   
  1304.   
  1305.         case TX_DONE:   /* All done sending a packet... */
  1306.   
  1307.             tsync_txdone:
  1308.   
  1309.         /* for slow PCs... reenable the timer ints... */
  1310.             if ((Twin_cputype < 2) && (dcbp->baud >= 9600L)) maskon(0);
  1311.   
  1312.         /* sent a packet */
  1313.             dcbp->txpackcnt++;
  1314.   
  1315.         /* reset Tx int pending */
  1316. #ifdef TSYNC_DEBUG
  1317.             Twin_write_scc(ctl,R0,(dcbp->wr0 = 0x28));
  1318. #else
  1319.             Twin_write_scc(ctl,R0,0x28);
  1320. #endif
  1321.         /* If we were not called by mistake... */
  1322.         /* I.E. by an underrun with no current buffer... */
  1323.             if(dcbp->xmtq != (struct drvbuf *)NULLBUF)
  1324.             {
  1325.   
  1326.             /* done sending message so move on to next one */
  1327.                 if ( dcbp->freem == (struct drvbuf *)NULLBUF )
  1328.                 {
  1329.                     dcbp->freem = dcbp->xmtq;
  1330.                     dcbp->xmtq = dcbp->xmtq->next;
  1331.                     dcbp->freem->next = (struct drvbuf *)NULLBUF;
  1332.                 }
  1333.                 else
  1334.                 {
  1335.                     btemp = dcbp->xmtq; /* addr of one to free */
  1336.                     dcbp->xmtq = btemp->next; /* next one TO BE xmitted */
  1337.                     btemp->next = dcbp->freem; /* one to be freed is queued */
  1338.                     dcbp->freem = btemp; /* now set free head ptr */
  1339.                 }
  1340.   
  1341.             /* signal the process which is supposed to free the */
  1342.             /* transmitted message */
  1343.                 psignal(&Twin_freetxpp[dcbp->dev],1);
  1344.   
  1345.             }
  1346.   
  1347.         /* Check NEW xmtq */
  1348.             if(dcbp->xmtq == (struct drvbuf *)NULLBUF)
  1349.             {
  1350.   
  1351.             /* no more msgs to send */
  1352.                 dcbp->xmtqtail = (struct drvbuf *)NULLBUF;
  1353.   
  1354.             /* take care of SQUELCH DELAY wait for */
  1355.             /* flag byte to go out */
  1356.                 dcbp->txstate = TX_KEYDOWN_DELAY;
  1357.   
  1358. #ifdef notdef
  1359. /* shouldn't need this... if we reset the tx ip bit */
  1360.             /* Turn off Tx ints */
  1361.                 if(dcbp->dma_flg == FALSE)Twin_write_scc(ctl,R1,(dcbp->wr1 = 0x11));
  1362.                 else Twin_write_scc(ctl,R1,(dcbp->wr1 = 0xf9));
  1363.   
  1364. #endif
  1365.   
  1366.                 transon(dcbp,OFF);
  1367.             }
  1368.             else
  1369.             {
  1370.             /* immediately start sending the next msg */
  1371.                 dcbp->cur_xbufp = &(dcbp->xmtq->buf);
  1372.                 dcbp->cur_xbytes = dcbp->xmtq->msgsize;
  1373.                 txprime_dma(dcbp);      /* start sending a frame */
  1374.   
  1375.             }
  1376.             break;
  1377.   
  1378.         case IDLE: /* Transmitter idle. Find a frame for transmission */
  1379.             if ( dcbp->xmtq == (struct drvbuf *)NULLBUF )
  1380.             {
  1381.             /* totally idle dudes */
  1382.   
  1383.             /* reset Tx int pending */
  1384. #ifdef TSYNC_DEBUG
  1385.                 Twin_write_scc(ctl,R0,(dcbp->wr0 = 0x28));
  1386. #else
  1387.                 Twin_write_scc(ctl,R0,0x28);
  1388. #endif
  1389.                 break;
  1390.             }
  1391.             else
  1392.             {
  1393.             /* point to the next message to send */
  1394.                 dcbp->cur_xbufp = &(dcbp->xmtq->buf);
  1395.                 dcbp->cur_xbytes = dcbp->xmtq->msgsize;
  1396.   
  1397.                 dcbp->txstate = DEFER; /* AND FALL THROUGH */
  1398.             }
  1399.         case DEFER:
  1400.   
  1401.         /* If we are in HALF-DUPLEX mode, then we must wait */
  1402.         /* for a free channel, and be polite about it (ppersist) */
  1403.         /* Otherwise just fire up the transmitter... */
  1404.   
  1405.             if(dcbp->hduplex == TRUE)
  1406.             {
  1407.   
  1408.            /* Check DCD so we don't step on a frame being received */
  1409.            /* DCD is ACTIVE LOW on the SCC DCD pin, but the bit in R0 */
  1410.            /* is SET when DCD is ACTIVE!! */
  1411.   
  1412. #ifdef notdef
  1413. /* This was the way it was released originally...  */
  1414. /* I changed it cause I think this is more robust, if we somehow dropped */
  1415. /* an external status event.... We now poll the CD line to determine if  */
  1416. /* we can send, and if needed, then we also will re_sync the extrn stats reg */
  1417.   
  1418.                 if(dcbp->extreg & DCD)
  1419. #endif
  1420.                     if ( (Twin_read_scc(dcbp->zhwmap.ctl,R0) & DCD) != 0 )
  1421.                     {
  1422.   
  1423.                 /* DGL 9/22/91 */
  1424.                 /* sync_up the extreg, if it somehow gets out of sync */
  1425.                         if(!(dcbp->extreg & DCD)) dcbp->extreg |= DCD;
  1426.   
  1427.   
  1428. #ifdef TSYNC_DEBUG_PRT
  1429.                         printf("TSYNC_TXISR: Device num %d DEFER state DCD is not right to xmit \n", dcbp->dev);
  1430. #endif
  1431.                         psignal(&Twin_kickpp[dcbp->dev],1);
  1432.                         break;
  1433.                     }
  1434.   
  1435.            /* DCD is down */
  1436.                 if ( (dcbp->ioctlparams->persist & 0x00ff) <= (rand() & 0x00ff) )
  1437.                 { /* then have to wait, be a less persistent */
  1438.                     dcbp->txstate = TX_PERSIST;
  1439.                     time_wait(dcbp,dcbp->timer1, dcbp->ioctlparams->slotime, tsync_persist,(long)dcbp);
  1440.                     break;
  1441.                 }
  1442.   
  1443.             }       /* end of Half duplex carrier handling... */
  1444.   
  1445.         /* Raise RTS and start transmiting */
  1446.         /* txstate is changed by the routine, but when */
  1447.         /* tsync_txisr is called next the state will be KEYED_UP */
  1448.             dcbp->txstate = TX_KEYUP_DELAY;
  1449.             transon(dcbp,ON);
  1450.             break;
  1451.   
  1452.         case KEYED_UP:
  1453.         /* RTS is ACTIVE or in radio terms the radio is keyed */
  1454.         /* and transmiting */
  1455.   
  1456.             txprime_dma(dcbp);      /* start sending a frame */
  1457.         /* chars will be going out */
  1458.             break;
  1459.   
  1460.   
  1461.         default:
  1462. #ifdef TSYNC_DEBUG_PRT
  1463.             printf("DEBUG tsync_txisr: invalid txstate, %d \n\r", dcbp->txstate);
  1464. #endif
  1465.   
  1466.                 /* reset Tx int pending */
  1467. #ifdef TSYNC_DEBUG
  1468.             Twin_write_scc(ctl,R0,(dcbp->wr0 = 0x28));
  1469. #else
  1470.             Twin_write_scc(ctl,R0,0x28);
  1471. #endif
  1472.             break;
  1473.   
  1474.         /* end switch */
  1475.     }
  1476.   
  1477.     restore(i_state);
  1478.     return;
  1479. }
  1480.   
  1481. void
  1482. txprime_dma(dcbp)
  1483. register DCB *dcbp;
  1484. {
  1485.     register int16 ctl;
  1486.     ulong realaddr;
  1487.     unsigned page;
  1488.   
  1489.     /* speed up access to 8530 regs */
  1490.     ctl = dcbp->zhwmap.ctl;
  1491.   
  1492.     /* if we are NOT DMA tx driven */
  1493.     if(dcbp->dma_flg == FALSE)
  1494.     {
  1495.   
  1496.         /* reset CRC for next frame */
  1497. #ifdef TSYNC_DEBUG
  1498.         Twin_write_scc(ctl,R0,(dcbp->wr0 = RES_Tx_CRC));
  1499.   
  1500.         /* reset Tx int pending */
  1501.         Twin_write_scc(ctl,R0,(dcbp->wr0 = 0x28));
  1502. #else
  1503.         Twin_write_scc(ctl,R0,RES_Tx_CRC);
  1504.   
  1505.         /* reset Tx int pending */
  1506.         Twin_write_scc(ctl,R0,0x28);
  1507. #endif
  1508.         /* Get First char to send */
  1509.         /* send the transmission char and bump the pointer */
  1510.   
  1511.         outportb(dcbp->zhwmap.data,*dcbp->cur_xbufp++);
  1512.   
  1513.         dcbp->txstate = TX_ACTIVE;
  1514.   
  1515.         /* sent one byte */
  1516.         dcbp->cur_xbytes--;
  1517.   
  1518. #ifdef TSYNC_DEBUG
  1519.         /* Rx/Tx and Extern ints on */
  1520.         Twin_write_scc(ctl,R1,(dcbp->wr1 = 0x13));
  1521.   
  1522.         /* Reset Underrun/EOM latch */
  1523.         Twin_write_scc(ctl,R0,(dcbp->wr0 = 0xc0));
  1524.   
  1525.         /* turn-on the xmission of Abort on underrun */
  1526.         if(dcbp->nrzi_flg == TRUE)Twin_write_scc(ctl,R10,(dcbp->wr10 = 0xa4));
  1527.         else Twin_write_scc(ctl,R10,(dcbp->wr10 = 0x84));
  1528. #else
  1529.         /* Rx/Tx and Extern ints on */
  1530.         Twin_write_scc(ctl,R1,0x13);
  1531.   
  1532.         /* Reset Underrun/EOM latch */
  1533.         Twin_write_scc(ctl,R0,0xc0);
  1534.   
  1535.         /* turn-on the xmission of Abort on underrun */
  1536.         if(dcbp->nrzi_flg == TRUE)Twin_write_scc(ctl,R10,0xa4);
  1537.         else Twin_write_scc(ctl,R10,0x84);
  1538.   
  1539. #endif
  1540.   
  1541. /* 4/18/91 */
  1542.         /* clear the TxEOM bit in the image */
  1543.         dcbp->extreg &= ~TxEOM;
  1544.   
  1545.         /* allow Underruns to interrupt us */
  1546.         Twin_write_scc(ctl,R15,(dcbp->wr15 |= 0x40));
  1547.   
  1548.         /* for slow PCs... mask out the timer ints... */
  1549.         /* This will cause the pc to lose time during xmissions... */
  1550.         /* but seems only way to make it work at 9600 */
  1551.         if ((Twin_cputype < 2) && (dcbp->baud >= 9600L)) maskoff(0);
  1552.   
  1553.     }
  1554.     else
  1555.     {
  1556.   
  1557.         /* Reprime the tx dma pump... */
  1558.   
  1559.         /* A rendition of an absolute address for ptr */
  1560.         realaddr = ((ulong)FP_SEG(dcbp->cur_xbufp) << 4)
  1561.         + (ulong)FP_OFF(dcbp->cur_xbufp);
  1562.   
  1563.         /* Disable this DMA channel */
  1564.         outportb(DMAWSMR,dcbp->dma_tx_chan | 0x04);
  1565.   
  1566.         /* DMA page reg for 8237 */
  1567.         page = (unsigned)(realaddr >> 16);
  1568.   
  1569.         /* setup 64k page */
  1570.         outportb(dcbp->dma_tx_pagereg,page);
  1571.   
  1572.         /* mode setup required if we are in HDX */
  1573.         if(dcbp->hduplex == TRUE)
  1574.         {
  1575.             outportb(DMAMODE,dcbp->dma_tx_chan |  TX_DMA);
  1576.             outportb(Twin_io_base+DMA_CFG,dcbp->dma_tx_mode);
  1577.         }
  1578.   
  1579.         /* clear the DMA byte ptr FF */
  1580.         outportb(DMAFFCL,00);
  1581.   
  1582.         /* Max xfer count setup */
  1583.         outportb(dcbp->dma_tx_cnt_reg,dcbp->cur_xbytes-1);
  1584.         outportb(dcbp->dma_tx_cnt_reg,((dcbp->cur_xbytes-1)>>8));
  1585.   
  1586.         /* destination buffer address */
  1587.         outportb(dcbp->dma_tx_addr_reg,(realaddr & 0xff));
  1588.         outportb(dcbp->dma_tx_addr_reg,((realaddr >> 8) & 0xff));
  1589.   
  1590.         /* reset CRC for next frame */
  1591. #ifdef TSYNC_DEBUG
  1592.         Twin_write_scc(ctl,R0,(dcbp->wr0 = RES_Tx_CRC));
  1593. #else
  1594.         Twin_write_scc(ctl,R0,RES_Tx_CRC);
  1595. #endif
  1596.         /* Enable this DMA channel */
  1597.         outportb(DMAWSMR,dcbp->dma_tx_chan);
  1598.         nop;
  1599.         nop;
  1600.   
  1601.         dcbp->txstate = TX_ACTIVE;
  1602.   
  1603.         /* Reset Underrun/EOM latch */
  1604. #ifdef TSYNC_DEBUG
  1605.         Twin_write_scc(ctl,R0,(dcbp->wr0 = 0xc0));
  1606. #else
  1607.         Twin_write_scc(ctl,R0,0xc0);
  1608. #endif
  1609.         /* allow Underruns to interrupt us */
  1610.         Twin_write_scc(ctl,R15,(dcbp->wr15 |= 0x40));
  1611.   
  1612.         /* clear the TxEOM bit in the image */
  1613.         dcbp->extreg &= ~TxEOM;
  1614.   
  1615. #ifdef TSYNC_DEBUG
  1616.         /* Rx and Extern ints on : No Tx ints */
  1617.         Twin_write_scc(ctl,R1,(dcbp->wr1 = 0xf9));
  1618.   
  1619.         /* reset Tx int pending */
  1620.         Twin_write_scc(ctl,R0,(dcbp->wr0 = 0x28));
  1621. #else
  1622.         /* Rx and Extern ints on : No Tx ints */
  1623.         Twin_write_scc(ctl,R1,0xf9);
  1624.   
  1625.         /* reset Tx int pending */
  1626.         Twin_write_scc(ctl,R0,0x28);
  1627. #endif
  1628.   
  1629.     }
  1630. }
  1631.   
  1632. /*
  1633.  * Transmit and Receive Control
  1634.  * SET Transmit or Receive Mode
  1635.  * Set RTS (request-to-send) to modem on Transmit
  1636.  */
  1637. void
  1638. transon(dcbp, onoff)
  1639. register DCB *dcbp;
  1640. int16 onoff;
  1641. {
  1642.     register int16  ctl;
  1643.   
  1644.     /* speed-up access to the SCC's control register */
  1645.     ctl = dcbp->zhwmap.ctl;
  1646.   
  1647.     /* Turn on transmitter to send flags */
  1648.     if ( onoff == ON )
  1649.     {
  1650.   
  1651.   
  1652.         /* If we are in DMA mode/Half duplex: Turn off the recvr */
  1653.         /* Rx 8 bit/chars, enter hunt mode, CRC enable */
  1654. #ifdef notdef
  1655. /* NOT needed with autoenables */
  1656.         Twin_write_scc(dcbp->zhwmap.ctl,R3,(dcbp->wr3 = 0xd8));
  1657. #endif
  1658.   
  1659.         /* flags during KEYUP cause the other guy to sync up while */
  1660.         /* he sees garbage*/
  1661. #ifdef TSYNC_DEBUG
  1662.         if(dcbp->nrzi_flg == TRUE) Twin_write_scc(ctl,R10,(dcbp->wr10 = 0xa0));
  1663.         else Twin_write_scc(ctl,R10,(dcbp->wr10 = 0x80));
  1664.   
  1665.         /* Effectively just activate RTS */
  1666.         /* Which is used to key the "radio transmitter" */
  1667.         Twin_write_scc(dcbp->zhwmap.ctl,R5,(dcbp->wr5 = 0x6b));
  1668.   
  1669. #else
  1670.         if(dcbp->nrzi_flg == TRUE) Twin_write_scc(ctl,R10,0xa0);
  1671.         else Twin_write_scc(ctl,R10,0x80);
  1672.   
  1673.         /* Effectively just activate RTS */
  1674.         /* Which is used to key the "radio transmitter" */
  1675.         Twin_write_scc(dcbp->zhwmap.ctl,R5,0x6b);
  1676.   
  1677. #endif
  1678.         /*
  1679.          * Transmitter now on
  1680.          */
  1681.   
  1682.         /* Delay after Tx on */
  1683.   
  1684.         /* Handle the special case of NO keyup delay... */
  1685.         if(dcbp->ioctlparams->xmitdelay == 0)tsync_txondelay(dcbp);
  1686.   
  1687.         /* otherwise set up the keyup timer... */
  1688.         else
  1689.             time_wait(dcbp,dcbp->timer1, dcbp->ioctlparams->xmitdelay, tsync_txondelay,(long)dcbp);
  1690.   
  1691.   
  1692.     }
  1693.   
  1694.     else
  1695.     {       /* Tx OFF and Rx ON */
  1696.   
  1697.         /* delay for squelch tail before enable of Rx */
  1698.   
  1699.         /* Handle the special case of NO keydown delay... */
  1700.         if(dcbp->ioctlparams->squelch == 0)tsync_sqdelay(dcbp);
  1701.   
  1702.         /* otherwise set up the keydown timer... */
  1703.         else
  1704.             time_wait(dcbp,dcbp->timer1, dcbp->ioctlparams->squelch, tsync_sqdelay,(long)dcbp);
  1705.   
  1706.     }
  1707.     return;
  1708. }
  1709. /*
  1710.  * end of transon
  1711.  ********************************************************************/
  1712.   
  1713. /*
  1714.  *  Called by the timer isr at an interrupt level.
  1715.  *  Persist time is up.
  1716.  */
  1717. void tsync_persist(dcbp)
  1718. DCB *dcbp;
  1719. {
  1720.     /* new for NOS */
  1721.   
  1722.     /* persist time is up, have NOS process check for transmit */
  1723.     /* by changing the driver's transmit state */
  1724.     dcbp->txstate = DEFER;
  1725.   
  1726.   
  1727.     /* AND signal the process which is supposed to kick  */
  1728.     /* the transmitter */
  1729.     psignal(&Twin_kickpp[dcbp->dev],1);
  1730.   
  1731.     return;
  1732. }
  1733.   
  1734. /*
  1735.  *  Called by the timer isr at an interrupt level.
  1736.  *  Transmitter on delay is up.
  1737.  */
  1738. void tsync_txondelay(dcbp)
  1739. DCB *dcbp;
  1740. {
  1741.     /* transmiter is ON and can start sending */
  1742.     dcbp->txstate = KEYED_UP;
  1743.     tsync_txisr(dcbp);
  1744.     return;
  1745. }
  1746.   
  1747. /*
  1748.  *  Called by the timer isr at an interrupt level.
  1749.  *  Squelch delay is up.
  1750.  */
  1751. void tsync_sqdelay(dcbp)
  1752. DCB *dcbp;
  1753. {
  1754.     register int16  ctl;
  1755.   
  1756.   
  1757.     /* We are going to shut down the "radio" transmitter.    */
  1758.     /* REGARDLESS of whether we now have a new frame to send */
  1759.     /* or not...  Because if we DO have more to send, we     */
  1760.     /* set txstate to DEFER, and let the tsync_recv routine     */
  1761.     /* kick us off again from the start, and if we don't     */
  1762.     /* have more to send we go to IDLE mode.                 */
  1763.   
  1764.     /* speed-up access to the SCC's control register */
  1765.     ctl = dcbp->zhwmap.ctl;
  1766.   
  1767.     /* Send MARK on IDLE to make sure other guy aborts any trailing */
  1768.     /* garbage */
  1769.     /* EXCEPT in NRZI... */
  1770. #ifdef TSYNC_DEBUG
  1771.     if(dcbp->nrzi_flg == TRUE) Twin_write_scc(ctl,R10,(dcbp->wr10 = 0xa0));
  1772.     else Twin_write_scc(ctl,R10,(dcbp->wr10 = 0x88));
  1773.   
  1774.     Twin_write_scc(ctl,R5,(dcbp->wr5 = 0x68));      /* TX off now */
  1775.                                             /* I.E. drop RTS */
  1776. #else
  1777.     if(dcbp->nrzi_flg == TRUE) Twin_write_scc(ctl,R10,0xa0);
  1778.     else Twin_write_scc(ctl,R10,0x88);
  1779.   
  1780.     Twin_write_scc(ctl,R5,0x68);    /* TX off now */
  1781.                                             /* I.E. drop RTS */
  1782. #endif
  1783.     /* re-prime the dma driver if necessary */
  1784.     /* Necessary because we took the SINGLE dma channel away */
  1785.     /* and used it to transmit... now give it back to receiver */
  1786.   
  1787.     if((dcbp->dma_flg == TRUE) && (dcbp->hduplex == TRUE))rxprime_dma(dcbp);
  1788.   
  1789.     /* perhaps while waiting for the squelch delay tsync_raw was */
  1790.     /* called and there is a buffer to send */
  1791.   
  1792.     if ( dcbp->xmtq != (struct drvbuf *)NULLBUF )
  1793.     { /* then start the transmit process */
  1794.       /* but not at an interrupt level!! */
  1795.       /* now when tsync_recv is called, tx_isr will run */
  1796.         dcbp->cur_xbufp = &(dcbp->xmtq->buf);
  1797.         dcbp->cur_xbytes = dcbp->xmtq->msgsize;
  1798.   
  1799.         /* new for NOS */
  1800.         /* signal the process which is supposed to kick  */
  1801.         /* the transmitter */
  1802.         dcbp->txstate = DEFER;
  1803.         psignal(&Twin_kickpp[dcbp->dev],1);
  1804.     }
  1805.     else
  1806.     { /* now only when tsync_raw runs will the transmit */
  1807.       /* process go on */
  1808.   
  1809.         dcbp->txstate = IDLE;
  1810.     }
  1811.   
  1812.     return;
  1813. }
  1814.   
  1815.   
  1816. /* This is the driver timer service.  */
  1817. /* It's resolution is in 1 msec intervals */
  1818.   
  1819. void
  1820. time_wait(dcbp,timer,msecs,timerfunc,arg)
  1821. DCB *dcbp;
  1822. struct drv_timer *timer;
  1823. int16   msecs;
  1824. void (*timerfunc)();
  1825. unsigned long arg;
  1826. {
  1827.     int16   hrd_addr;
  1828.   
  1829.     /* calculate the timer counter reg address */
  1830.     hrd_addr = Twin_io_base + TMR_CNT1 + dcbp->dev;
  1831.   
  1832.     timer->thandler = timerfunc;
  1833.     timer->targ = arg;
  1834.   
  1835.     /* start the timer */
  1836.     outportb(hrd_addr,(uchar)(msecs & 0xff));
  1837.     nop;
  1838.     nop;
  1839.     outportb(hrd_addr,(uchar)(msecs >> 8));
  1840.     nop;
  1841.     nop;
  1842. }
  1843.   
  1844.   
  1845. /***********************************************************
  1846.  * GRACILIS - processes to manage buffer maintenance for the
  1847.  *            PackeTwin synchronous drivers.  These processes
  1848.  *                        are used to insure that buffer maintenance is
  1849.  *                        not performed at interrupt time.
  1850.  ***********************************************************/
  1851.   
  1852. /* This process is used to pre-allocate receive    */
  1853. /* buffers for the 8530 synchronous driver to use. */
  1854. void
  1855. tsync_rxavget(dev, p1, p2)
  1856. int     dev;                    /* device number */
  1857. void    *p1;                    /* not used */
  1858. void    *p2;                    /* not used */
  1859. {
  1860.     register int i_state;
  1861.     DCB *dcbp;
  1862.     int16 cur_rxavail, min_rxavail;
  1863.   
  1864.   
  1865.     /* killself if device is not attached yet */
  1866.     if  (dev > 1)           /* only support 0 through 1 */
  1867.         return;
  1868.     else if (Twin_udcb[dev].attached == FALSE)
  1869.         return;
  1870.   
  1871.     for (;;)
  1872.     {
  1873.   
  1874.         /* wait for the driver to signal it needs */
  1875.         /* a look at its pre-allocated receive buffers */
  1876.         pwait(&Twin_bufpp[dev]);
  1877.   
  1878.         dcbp = (DCB *)Twin_udcb[dev].dcbp;
  1879.   
  1880.         i_state = dirps();
  1881.   
  1882.         cur_rxavail = dcbp->rxavailcount;
  1883.         min_rxavail = dcbp->ioctlparams->rxavailbufs;
  1884.   
  1885.         restore(i_state);
  1886.   
  1887.   
  1888.         /* see if more receive buffers need allocating */
  1889.         if ( cur_rxavail < min_rxavail )
  1890.         {
  1891.             f_getavail((struct mbuf **)&(dcbp->rxavailq),
  1892.             (int16)(min_rxavail - cur_rxavail),
  1893.             (int16)dcbp->rxbufsize,
  1894.             (int16 *)&(dcbp->rxavailcount),
  1895.             (struct iface *)dcbp->iface,
  1896.             (bool)dcbp->dma_flg);
  1897.         }
  1898.     } /* end of for(;;) loop */
  1899.   
  1900. } /* end of tsync_rxavget() */
  1901.   
  1902.   
  1903.   
  1904.   
  1905. /* This process is used to periodically kick */
  1906. /* the PackeTwin synchronous driver whenever */
  1907. /* it is in the DEFERED state  */
  1908. void
  1909. tsync_txkick(dev, p1, p2)
  1910. int     dev;                    /* device number */
  1911. void    *p1;                    /* not used */
  1912. void    *p2;                    /* not used */
  1913. {
  1914.     register DCB *dcbp;
  1915.     register bool pwait_null = FALSE;       /* 1st time wait for driver's psignal */
  1916.     void tsync_txisr();
  1917.   
  1918.   
  1919.     /* killself if device is not attached yet */
  1920.     if  (dev > 1)           /* only support 0 through 1 */
  1921.         return;
  1922.     else if (Twin_udcb[dev].attached == FALSE)
  1923.         return;
  1924.   
  1925.     for (;;)
  1926.     {
  1927.   
  1928.         /* wait for the driver to signal it needs */
  1929.         /* kick */
  1930.         if ( pwait_null )
  1931.             pwait(NULL);                    /* have NOS provide */
  1932.                             /* the delay needed */
  1933.         else
  1934.             pwait(&Twin_kickpp[dev]);
  1935.   
  1936.         /* driver control block */
  1937.         dcbp = (DCB *)Twin_udcb[dev].dcbp;
  1938.   
  1939.         /*  Test for DEFERED transmit state */
  1940.         if (dcbp->txstate == DEFER)
  1941.         {
  1942.             tsync_txisr(dcbp);
  1943.             if ( dcbp->txstate == DEFER )
  1944.                 pwait_null = TRUE;      /* then driver still */
  1945.                             /* needs a kick */
  1946.             else
  1947.                 pwait_null = FALSE;
  1948.         }
  1949.   
  1950.     } /* end of for(;;) loop */
  1951.   
  1952. } /* end of tsync_txkick() */
  1953.   
  1954.   
  1955.   
  1956. /* This process is used to free buffers */
  1957. /* which have been transmitted by the driver. */
  1958. void
  1959. tsync_freetx(dev, p1, p2)
  1960. int     dev;                    /* device number */
  1961. void    *p1;                    /* not used */
  1962. void    *p2;                    /* not used */
  1963. {
  1964.     register int i_state;
  1965.     register DCB *dcbp;
  1966.     register struct drvbuf *xbufp, *btemp;
  1967.   
  1968.   
  1969.     /* killself if device is not attached yet */
  1970.     if  (dev > 4)           /* only support 0 through 4 */
  1971.         return;
  1972.     else if (Twin_udcb[dev].attached == FALSE)
  1973.         return;
  1974.   
  1975.     for (;;)
  1976.     {
  1977.   
  1978.         /* wait for driver to signal that there are transmitted */
  1979.         /* messages to be freed */
  1980.         pwait(&Twin_freetxpp[dev]);
  1981.   
  1982.         /* driver control block */
  1983.         dcbp = (DCB *)Twin_udcb[dev].dcbp;
  1984.   
  1985.         /* Do not do memory free-ups while interrupts are */
  1986.         /* disabled! Here xbufp is a "to be free'd"  */
  1987.         /* queue pointer" */
  1988.   
  1989.         i_state = dirps();
  1990.         xbufp = dcbp->freem;
  1991.         dcbp->freem = NULLBUF;
  1992.         restore(i_state);
  1993.   
  1994.         /* now free memory of all the xmitted messages */
  1995.         while ( xbufp != (struct drvbuf *)NULL )
  1996.         {
  1997.             btemp = xbufp->next;
  1998.             free((char *)xbufp);
  1999.             xbufp = btemp;
  2000.         }
  2001.     } /* end of for(;;) loop */
  2002.   
  2003. } /* end of tsync_freetx() */
  2004.   
  2005. #endif
  2006.