home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / t / twindv21.zip / TWIN_DR.C < prev    next >
C/C++ Source or Header  |  1992-09-12  |  53KB  |  2,035 lines

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