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_AT.C < prev    next >
C/C++ Source or Header  |  1992-09-12  |  47KB  |  1,727 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_at.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_attach - Performs attach functions for TCP/IP, i.e.
  36. *                   attach the tsync_driver to TCP/IP.
  37. *
  38. *    do_tsync_stat  - Applications' routine for "displaying" the
  39. *                     tsync_driver statistics.
  40. *
  41. *    tsync_ioctl  - Set the IO Control parameters.
  42. *
  43. *
  44. * Revision History:
  45. *
  46. *    Release 2.0        - 9/7/92    First Release of cleaned up Twin driver
  47. *                                with fewer files, and called twin_at instead
  48. *                                of tsync_at
  49. *
  50. *    Release 2.1        - 9/12/92    Fix bug in half-duplex dma mode, which caused
  51. *                                loss of every other receive frame in a multi-
  52. *                                frame transmission.  
  53. */
  54.  
  55.  
  56. #include <stdio.h>
  57. #include <dos.h>
  58. #include "global.h"
  59. #include "config.h"
  60. #include "hardware.h"
  61. #include "mbuf.h"
  62. #include "iface.h"
  63. #include "ax25.h"
  64. #include "trace.h"
  65. #include "netuser.h"
  66. #include "proc.h"
  67. #include "pktdrvr.h"
  68. #include "devparams.h"
  69. #include "z8530.h"
  70. #include "gracilis.h"
  71. #include "twin.h"
  72.  
  73.  
  74. /* If using the Borland stdio library... */
  75. #ifdef    OLD_KA9Q
  76. #else
  77. /* If using the new KA9Q stdio library... */
  78. #define    tprintf    printf
  79. #endif
  80.  
  81.  
  82. /*******************************************************************
  83. *                        TSYNC_ATTACH                              *
  84. *                                                                  *
  85. * File: tsync_at.c                                                 * 
  86. * Rev : 3.0                                                        *
  87. *                                                                  *
  88. ********************************************************************
  89. *
  90. *
  91. * DESCRIPTION: 
  92. * -----------
  93. * Attaches the PackeTwin's synchronous SCC driver to TCP/IP.
  94. *
  95. * ARGUMENTS:
  96. * ---------
  97. *    All argv's are strings
  98. * argv[0]:  hardware type,  "tsync"  
  99. * argv[1]:  "0" = 8530 SCC A  
  100. *           "1" = 8530 SCC B 
  101. * argv[2]:  vector, Interrupt request line #
  102. *
  103. * argv[3]:  IOBASE : base address for PackeTwin default 0x230
  104. *
  105. * argv[4]:  "HDX"  half-duplex
  106. *           "FDX"  full-duplex
  107. *
  108. * argv[5]:  mode, DMA/INTS for channel 1, MUST be INTS
  109. *
  110. * argv[6]:  Dma channel to use for receive...
  111. *           0 = none... 
  112. *           1 = Rx on dma channel 1 and if FULL DUPLEX tx on channel 3
  113. *           3 = Rx on dma channel 3 and if FULL DUPLEX tx on channel 1
  114. *
  115. * argv[7]:  interface label
  116. *
  117. *           This label is provided by the user and the attach uses
  118. *           it in its tprintf's to tell the user which interface
  119. *           is being talked about.
  120. *
  121. * argv[8]:  max receive packet buffer  size in bytes
  122. * argv[9]:  max xmit packet buffer size in bytes
  123. * argv[10]: interface baud rate, e.g, "9600"
  124. * argv[11]: OPTIONAL - clocking options
  125. * argv[12]: OPTIONAL - clocking options
  126. * argv[13]: OPTIONAL - Data Encoding: NRZ/NRZI
  127. * argv[14]: OPTIONAL - IP address - default is Ip_addr
  128. * argv[15]: OPTIONAL - number of RX buffers to pre-allocate
  129. *
  130. * RETURN VALUES:
  131. * -------------
  132. *  0 - success
  133. * -1 - failure, driver not attached and no memory left allocated
  134. *
  135. * GLOBAL INPUTS:
  136. * -------------
  137. *        
  138. * GLOBAL OUTPUTS:
  139. * --------------
  140. *
  141. * FUNCTIONS CALLED:
  142. * ----------------
  143. * tprintf
  144. * calloc
  145. * malloc
  146. * tsync_hwinit
  147. * free
  148. *
  149. * IO:
  150. * --
  151. *
  152. *
  153. ******************************************************************/
  154.  
  155.  
  156.  
  157.                                     /* Extern declaration for the */
  158. extern UNI_DCB    Twin_udcb[];        /* array of universal control */
  159.                                     /* blocks for this driver */
  160.  
  161. /* interrupt handler */
  162. extern INTERRUPT twinvec();
  163.  
  164. extern INTERRUPT (*Twin_oldvec) __ARGS((void)); /* Old vector contents */
  165. extern INTERRUPT (*Twin_handler) __ARGS((void));
  166.  
  167.  
  168. extern    char *Twin_dvr_version;
  169. extern    int Twin_io_base;
  170.  
  171.  
  172. extern    int16    Twin_vector;
  173. extern    int        Twin_cputype;        /* Global to identify the machine type */
  174.                     /* 0 = 8086        */
  175.                     /* 2 = 80286        */
  176.                     /* 3 = 80386        */
  177.  
  178. int
  179. tsync_attach(argc,argv,p)
  180. int argc;            
  181. char *argv[];
  182. void *p;                /* new for NOS */
  183. {
  184.     extern void tsyncvec();
  185.  
  186.     extern struct iface *ifaces;
  187.     char    i_state;
  188.     int32    ipaddr;            /* new for NOS - IP address */
  189.     int    i;
  190.     char    tmpbuf[80];
  191.     register struct iface *intfc_p;
  192.     DCB *dcbp;
  193.     UNI_DCB *udcbp;
  194.     int udcb_dev;
  195.     int16 rbufsize, xbufsize;
  196.     int    rxdmachan,txdmachan;
  197.     struct drv_timer *timer1;
  198.     unsigned char far *cpusig_ptr;    /* ptr to CPU signature byte in rom */
  199.  
  200.     bool    hdxflg,dmaflg;
  201. #ifdef OLD_KA9Q
  202.     struct phdr *hdr;        /* new for NOS - packet header*/
  203. #endif
  204.  
  205.     void tsync_recv(), tsync_txisr(), tsync_rxisr(), tsync_xstatisr();
  206.  
  207.     int32 tsync_ioctl();
  208.     int tsync_send();
  209.     int tsync_output();
  210.     int tsync_stop();
  211.     int tsync_raw();
  212.     int ax_send();
  213.     int ax_output();
  214.  
  215.  
  216.  
  217.     /* Try reading the Machine ID in ROM... */
  218.     cpusig_ptr = (unsigned char *)MK_FP(0xf000,0xfffe);
  219.  
  220.     if((*cpusig_ptr == 0xfc) || (*cpusig_ptr == 0xf8))
  221.                 Twin_cputype = 2;        /* 80286 or better */
  222.         
  223.     else         Twin_cputype = 0;        /* Default to type 8086 */
  224.  
  225.  
  226. #ifdef TSYNC_DEBUG_PRT
  227.     printf("tsync_attach: argument count is %d\n",argc);
  228.     for(i=0;i<argc;i++)
  229.         printf("arg #%d: %s\n",i,argv[i]);
  230.     printf("\n\n");
  231. #endif
  232.  
  233.  
  234.     /* 
  235.      * validate input params 
  236.      */
  237.     if ( argc < 11 )
  238.     {
  239.         tprintf("tsync_attach: too few arguments (%d) \n", argc);
  240.  
  241.         tprintf("tsync <chan> <vec> <iobase> <hdx|fdx> <dma|ints> <rx dmachan>\n");
  242.         tprintf("      <name> <rxsize> <txsize> <speed> [txclk] [rxclk] [nrz|nrzi] \n");
  243.         tprintf("      [ipaddr] [#rxbufs]\n");
  244.         return(1); /* should this be a -1, milt milt */
  245.     }
  246.  
  247.     /* get the PackeTwin device number/address 
  248.      * and validate it for a synchronous driver
  249.      */
  250.     udcb_dev = htoi(argv[1]);        
  251.  
  252.     /* range check device number */
  253.     if ( (udcb_dev < 0) || (udcb_dev > 1) )
  254.     {
  255.         tprintf("tsync_attach error: Channel number %x out of range!\n", udcb_dev);
  256.         return(-1);
  257.     }
  258.  
  259.     udcbp = &Twin_udcb[udcb_dev];    /* dev num is index number!!! */
  260.  
  261.     /* See if already attached */
  262.     if ( udcbp->attached  == TRUE )
  263.     {
  264.         tprintf("tsync_attach error: Channel %s already attached; interface is %s", argv[1], argv[7]); 
  265.         return(-1);
  266.     }
  267.  
  268.  
  269.     if ( if_lookup(argv[7]) != NULLIF )    /* new for NOS */
  270.     {
  271.         tprintf("Interface %s already exists \n", argv[7]);
  272.         return(-1);
  273.     }
  274.  
  275.     Twin_vector = htoi(argv[2]);
  276.  
  277.     if( Twin_vector <= 0 || Twin_vector > 15)
  278.     {
  279.         tprintf("Illegal vector specified: %s\n", argv[2]);
  280.         return(-1);
  281.  
  282.  
  283.     }
  284.  
  285.     if((htoi(argv[3])) >= 0x100)
  286.         Twin_io_base = htoi(argv[3]);
  287.     else
  288.     {
  289.         tprintf("Illegal iobase specified: %s\n", argv[3]);
  290.         return(-1);
  291.     }
  292.  
  293.     if(strcmpi(argv[4],"hdx") == 0) hdxflg = TRUE; 
  294.     else if(strcmpi(argv[4],"fdx") == 0) hdxflg = FALSE;
  295.     else
  296.     {
  297.         tprintf("tsync_attach error: Specified %s instead of \"hdx\" or \"fdx\" for interface %s\n",
  298.             argv[4],argv[7]);
  299.         return(-1);
  300.     }
  301.  
  302.       /* Are we in DMA mode? */
  303.     if (strcmpi(argv[5],"dma") == 0)
  304.     {
  305.             dmaflg = TRUE;
  306.             rxdmachan = htoi(argv[6]);
  307.  
  308.             /* Did they enter a valid dma channel #? */
  309.             if((rxdmachan != 3) && (rxdmachan != 1))
  310.             {
  311.                 /* NO... bad channel # */
  312.                 tprintf("tsync_attach error: Specified dma channel: %d instead of 1 or 3 for interface %s\n",
  313.                 rxdmachan,argv[7]);
  314.                 return(-1);
  315.             }
  316.  
  317.             /* YES valid channel # */
  318.             else
  319.             {
  320.                 if(hdxflg == FALSE)
  321.                 {
  322.                     if(rxdmachan == 1)txdmachan = 3;
  323.                     else    txdmachan = 1;
  324.                 }
  325.                 else txdmachan = rxdmachan;
  326.             }
  327.     }
  328.  
  329.        /* in interrupt mode? */
  330.     else if (strcmpi(argv[5],"ints") == 0)dmaflg = FALSE;
  331.     else
  332.     {
  333.         tprintf("tsync_attach error: Specified %s instead of \"dma\" or \"ints\" for interface %s\n",
  334.             argv[5],argv[7]);
  335.         return(-1);
  336.     }
  337.  
  338.     /* Can't specify DMA for port B */
  339.     if((dmaflg == TRUE) && (udcb_dev != 0))
  340.     {
  341.         tprintf("tsync_attach error: DMA is not supported on channel 1!\n");
  342.         return(-1);
  343.     }
  344.  
  345.     if ( (rbufsize = atoi(argv[8])) == 0 )
  346.     {
  347.         tprintf("tsync_attach error: Receive buffer size error %s, interface %s\n",
  348.             argv[8],argv[7]);
  349.         return(-1);
  350.     }
  351.  
  352.     if ( (xbufsize = atoi(argv[9])) == 0 )
  353.     {
  354.         tprintf("tsync_attach error: Transmit buffer size error %s, interface %s\n",
  355.             argv[9],argv[7]);
  356.         return(-1);
  357.     }
  358.  
  359.  
  360.     /* new for NOS, Set the IP address */
  361.     ipaddr = Ip_addr;            /* default value */
  362.     if ( argc >= 15 )
  363.         ipaddr = resolve(argv[14]);    
  364.     if ( ipaddr == 0 )
  365.     {
  366.         tprintf(Noipaddr);
  367.         return(-1);
  368.     }
  369.  
  370.  
  371.     /* 
  372.      * try to allocate necessary memory 
  373.      */
  374.     intfc_p = (struct iface *)calloc(1,sizeof(struct iface));
  375.     if ( intfc_p !=  (struct iface *)NULLBUF )
  376.     {
  377.         intfc_p->name = malloc((unsigned int)strlen(argv[7])+2);
  378.         if (intfc_p->name != (char *)NULLBUF )    
  379.         {
  380.             /*  device hw addr  */
  381.             intfc_p->hwaddr = malloc(AXALEN);
  382.             if ( intfc_p->hwaddr == NULLCHAR )
  383.             {
  384.                 free(intfc_p->name);
  385.                 free(intfc_p);
  386.                 tprintf("tsync_attach error: no memory for interface hwaddr, size of sizeof(struct mycall) bytes, interface %s", argv[7]);
  387.                 return(-1);
  388.             }
  389.  
  390.         }
  391.         else
  392.         {
  393.             free(intfc_p);
  394.             tprintf("tsync_attach error: no memory for interface name, size 7 bytes, interface %s", argv[7]);
  395.             return(-1);
  396.         }
  397.     }
  398.     else
  399.     {
  400.         tprintf("tsync_attach error: no memory for interface struct, size of sizeof(struct iface), interface %s", argv[7]);
  401.         return(-1);
  402.     }
  403.     
  404.     /* get the timer control blocks */
  405.     /* must have zeros in structure, so use calloc */
  406.     if ( (timer1 = (struct drv_timer *)calloc(1,sizeof(struct drv_timer))) == (struct drv_timer *)NULLBUF )
  407.     {
  408.         free(intfc_p->hwaddr);
  409.         free(intfc_p->name);
  410.         free(intfc_p);
  411.         tprintf("tsync_attach error: no memory for timer control block structure, size of sizeof(struct drv_timer), interface %s", argv[7]);
  412.         return(-1);
  413.     }
  414.  
  415.  
  416.     dcbp = (DCB *)calloc(1,sizeof(DCB));    /* zero-out the dcb */
  417.     if ( dcbp != (DCB *)NULLBUF )
  418.     {
  419.         dcbp->rxbufsize = rbufsize;
  420. #ifdef OLD_KA9Q
  421.         dcbp->rxbufp = alloc_mbuf(rbufsize+sizeof(struct phdr));
  422. #else
  423.         dcbp->rxbufp = alloc_mbuf(rbufsize);
  424. #endif
  425.         if (dcbp->rxbufp != NULLBUF )    
  426.         {
  427.             dcbp->ioctlparams = (struct tsync_ioctl *)malloc(sizeof(struct tsync_ioctl));
  428.             if ( dcbp->ioctlparams == (struct tsync_ioctl *)NULLBUF )
  429.             {
  430.                 free(timer1);
  431.                 free(intfc_p->hwaddr);
  432.                 free(intfc_p->name);
  433.                 free(intfc_p);
  434.                 free(dcbp->rxbufp);
  435.                 free(dcbp);
  436.                 tprintf("tsync_attach error: no memory for IOCTL params size %x bytes, interface %s", sizeof(struct tsync_ioctl), argv[7]);
  437.                 return(-1);
  438.             }
  439.         }
  440.         else 
  441.         {
  442.             free(timer1);
  443.             free(intfc_p->hwaddr);
  444.             free(intfc_p->name);
  445.             free(intfc_p);
  446.             free(dcbp);
  447.             tprintf("tsync_attach error: no memory for receive buffer, size %x bytes, interface %s", rbufsize, argv[7]);
  448.             return(-1);
  449.         }
  450.     }
  451.     else
  452.     {
  453.         free(timer1);
  454.         free(intfc_p->hwaddr);
  455.         free(intfc_p->name);
  456.         free(intfc_p);
  457.         tprintf("tsync_attach error: no memory for device control block structure, size of sizeof(DCB), interface %s", argv[7]);
  458.         return(-1);
  459.     }
  460.  
  461.  
  462.     if ( Mycall[0] == '\0' )
  463.     {
  464.         free(timer1);
  465.         free(intfc_p->hwaddr);
  466.         free(intfc_p->name);
  467.         free(intfc_p);
  468.         free(dcbp->rxbufp);
  469.         free(dcbp);
  470.         tprintf("tsync_attach error: mycall not set\n");
  471.         return(-1);
  472.     }
  473.  
  474.  
  475.     /* 
  476.      *  Universal Driver Control Block Init -
  477.      *  Except for the saving of old vectors and attached field.
  478.      *  Attached field is saved for the very end.
  479.      */
  480.     udcbp->type = SYNC_8530;            /* 8530 scc */
  481.     
  482.     /* set address of the unit's driver control block */
  483.     udcbp->dcbp = (char *)dcbp;
  484.  
  485.     /* setup this device's interrupt handlers */
  486.     udcbp->prev_vec2 = tsync_txisr;
  487.     udcbp->prev_vec3 = tsync_rxisr;
  488.     udcbp->prev_vec4 = tsync_xstatisr;
  489.  
  490.  
  491.     /*
  492.      * Setup the interface structure and link it to the list
  493.      * of interface structures.
  494.      */
  495.     /* the Ascii name of the driver unit */
  496.     strcpy(intfc_p->name,argv[7]);
  497.  
  498.     /* set the device number, must be able to tell whether */
  499.     /* channel A or channel B is being used */
  500.     dcbp->dev = udcb_dev;
  501.     switch ( udcb_dev ) 
  502.     {
  503.         case TWINCOMM1:
  504.             dcbp->zhwmap.ctl = (int16)(Twin_io_base+SCCA_CMD);
  505.             dcbp->zhwmap.data = (int16)(Twin_io_base+SCCA_DATA);
  506.             break;
  507.  
  508.         case TWINCOMM2: 
  509.             dcbp->zhwmap.ctl = (int16)(Twin_io_base+SCCB_CMD);
  510.             dcbp->zhwmap.data = (int16)(Twin_io_base+SCCB_DATA);
  511.             break;
  512.  
  513.     }
  514.  
  515.  
  516. /* not for NOS    intfc_p->recv = tsync_recv;   
  517. */
  518.     intfc_p->mtu = xbufsize - MAX_AX25_HDR_LEN;
  519.     intfc_p->ioctl =  tsync_ioctl;
  520.     intfc_p->raw = tsync_raw;
  521.     intfc_p->addr = ipaddr;            /* new for NOS */
  522.     intfc_p->stop = tsync_stop;
  523.     intfc_p->dev = udcb_dev;
  524.  
  525.     setencap(intfc_p,"AX25");
  526.  
  527.     /* For packet radio put in the sender's "call letters" */
  528.     memcpy(intfc_p->hwaddr,Mycall,AXALEN);  
  529.  
  530.     /* lastly, but very importantly, put in the LL of interfaces */
  531.     intfc_p->next = Ifaces;
  532.     Ifaces = intfc_p;
  533.  
  534.  
  535.     /* 
  536.      * Initialize the unit's driver control block 
  537.      */
  538.     dcbp->iface = intfc_p;        /* new for NOS - save the iface */
  539.                     /* address for use in queueing */
  540.                     /* mbufs onto Hopper */
  541.     dcbp->txstate = IDLE;
  542.     dcbp->xmtq = (struct drvbuf *)NULLBUF;
  543.     dcbp->xmtqtail = (struct drvbuf *)NULLBUF;     /* milt */
  544.     dcbp->freem = (struct drvbuf *)NULLBUF;          /* milt */
  545.  
  546.     dcbp->rxstate = IDLE;    
  547.     dcbp->rxbufsize = atoi(argv[8]);
  548.  
  549. /*milt 3/15/91
  550.     dcbp->rxqhat.headp = NULLBUF;
  551.     dcbp->rxqhat.tailp = NULLBUF;
  552. */
  553.  
  554.     /* Configure DMA stuff */
  555.     dcbp->dma_flg = dmaflg;
  556.     if(dmaflg == TRUE)
  557.     {
  558.  
  559.         dcbp->dma_rx_chan = rxdmachan;
  560.         dcbp->dma_tx_chan = txdmachan;
  561.  
  562.         switch(dcbp->dma_tx_chan)
  563.         {
  564.             case 1:    dcbp->dma_tx_pagereg = 0x83;
  565.                 dcbp->dma_tx_cnt_reg = DMA1CNT;
  566.                 dcbp->dma_tx_addr_reg = DMA1ADR;
  567.                 break;
  568.             case 3: dcbp->dma_tx_pagereg = 0x82;
  569.                 dcbp->dma_tx_cnt_reg = DMA3CNT;
  570.                 dcbp->dma_tx_addr_reg = DMA3ADR;
  571.                 break;
  572.         }
  573.  
  574.         switch(dcbp->dma_rx_chan)
  575.         {
  576.             case 1:    dcbp->dma_rx_pagereg = 0x83;
  577.                 dcbp->dma_rx_cnt_reg = DMA1CNT;
  578.                 dcbp->dma_rx_addr_reg = DMA1ADR;
  579.                 break;
  580.             case 3: dcbp->dma_rx_pagereg = 0x82;
  581.                 dcbp->dma_rx_cnt_reg = DMA3CNT;
  582.                 dcbp->dma_rx_addr_reg = DMA3ADR;
  583.                 break;
  584.         }
  585.  
  586.         /* SET up of the mode reg values for the DMA channels to be used */
  587.         if(hdxflg == FALSE) 
  588.         {
  589.             /* FULL DUPLEX the values never change between rx/tx */
  590.             if(rxdmachan == 3)
  591.                 dcbp->dma_rx_mode = dcbp->dma_tx_mode = PKTWIN_DMA_FDX_T1R3;
  592.             else
  593.                 dcbp->dma_rx_mode = dcbp->dma_tx_mode = PKTWIN_DMA_FDX_T3R1;
  594.         }
  595.         else
  596.         {
  597.             /* Half DUPLEX... */
  598.             if(rxdmachan == 3)
  599.             {
  600.                 dcbp->dma_rx_mode = PKTWIN_DMA_HDX_R3;
  601.                 dcbp->dma_tx_mode = PKTWIN_DMA_HDX_T3;
  602.             }
  603.             else
  604.             {
  605.                 dcbp->dma_rx_mode = PKTWIN_DMA_HDX_R1;
  606.                 dcbp->dma_tx_mode = PKTWIN_DMA_HDX_T1;
  607.             }
  608.         }
  609.  
  610.     }        /* End of dma info setup */
  611.  
  612.  
  613.     /* no need to init stats because calloc zero-ed the dcbp */
  614.  
  615.     /* default IOCTL Params */
  616.     dcbp->ioctlparams->xmitdelay = 250;    /* 250 Ms */
  617.     dcbp->ioctlparams->persist= 64;        /* 25% of 255 = 64 persistance*/
  618.     dcbp->ioctlparams->slotime = 10;    /* 10 Ms */
  619.     dcbp->ioctlparams->squelch   = 200;    /* 200 Ms */
  620.  
  621.     /* set the rxavailbufs parameter */
  622.     dcbp->ioctlparams->rxavailbufs = 0;    /* zero 1st */
  623.     if ( argc >= 16 )
  624.         dcbp->ioctlparams->rxavailbufs = atoi(argv[15]);
  625.     
  626.     if ( dcbp->ioctlparams->rxavailbufs < 4 )
  627.         dcbp->ioctlparams->rxavailbufs = 4;    /* 4 is min!! */
  628.  
  629.     /* 
  630.      * setup the packet header for the DRIVER 
  631.      * calling this routine 
  632.      */
  633.     /* init to packet header's byte count */
  634. #ifdef OLD_KA9Q
  635.     dcbp->rxbufp->cnt = sizeof(struct phdr);
  636.     hdr = (struct phdr *)dcbp->rxbufp->data;
  637.     hdr->type = intfc_p->type;
  638.     hdr->iface = intfc_p;
  639.     /* Rx data goes in after packet header  */
  640.     /* works because data is a char pointer */
  641.     dcbp->rxbufp->data += sizeof(struct phdr);
  642. #else
  643.     dcbp->rxbufp->cnt = 0;
  644. #endif
  645.  
  646.     dcbp->rxcurp = dcbp->rxbufp->data;
  647.  
  648.     /* get as many of the requested rx pre-allocated mbuf's */
  649.     dcbp->rxavailq = NULLBUF;
  650.  
  651.     f_getavail(&(dcbp->rxavailq), dcbp->ioctlparams->rxavailbufs,
  652.                     dcbp->rxbufsize, 
  653.                 &(dcbp->rxavailcount), 
  654.                    intfc_p, dcbp->dma_flg);
  655.  
  656. #ifdef TSYNC_DEBUG_PRT
  657. printf("TSYNC_ATTACH: rxavailbufs is %d, rxavailcount is %d\n", dcbp->ioctlparams->rxavailbufs, dcbp->rxavailcount); 
  658. #endif
  659.  
  660.     /* put in the timer control blocks */
  661.     dcbp->timer1 = timer1;
  662.  
  663.     dcbp->baud = (int16)atoi(argv[10]);
  664.     /* set up duplex mode... */
  665.     dcbp->hduplex = hdxflg;
  666.  
  667.  
  668.     /* SET UP CLOCKING OPTIONS... */
  669.     /* Default to Externally supplied clocks */
  670.  
  671.     /* select Tx clock mode for SCC */
  672.     /* Default is to expect clock to be supplied externally */
  673.     if((argc >= 12) && (strcmpi(argv[11],"int") == 0))dcbp->txclk_extrn = FALSE;
  674.     else dcbp->txclk_extrn = TRUE;
  675.  
  676.     /* select Rx clock mode for SCC */
  677.     /* Default is to expect clock to be supplied externally */
  678.     if((argc >= 13) && (strcmpi(argv[12],"int") == 0))dcbp->rxclk_extrn = FALSE;
  679.     else dcbp->rxclk_extrn = TRUE;
  680.  
  681.     /* select data coding scheme for SCC */
  682.     /* Default is NRZ */
  683.     if(argc >= 14)
  684.     {
  685.         if((strlen(argv[13]) >= strlen("nrzi")) && 
  686.                         (strcmpi(argv[13],"nrzi") == 0))
  687.         {
  688.             dcbp->nrzi_flg = TRUE;
  689.         }
  690.         else dcbp->nrzi_flg = FALSE;
  691.     }
  692.  
  693.     /*
  694.      *  Now for the hardware dependent initializations.
  695.        *  If device control block is an 8530 driver, then SCC
  696.      *  stuff needs to be done.  
  697.      *
  698.      *  udcbp->type tells if its an 8530
  699.      *  intfc_p->dev tells which unit/dev
  700.       *
  701.      */
  702.  
  703. #ifdef TSYNC_DEBUG_PRT
  704.     printf("tsync_attach: intfc_p->dev = %x config 8530 HW \n", intfc_p->dev);
  705. #endif
  706.  
  707.  
  708.     i_state = dirps();    /* {dgl} protect the writescc's */
  709.                 /* and the vector reads/writes */
  710.     /* disable our ints */
  711.     maskoff(Twin_vector);
  712.     outportb(Twin_io_base+INT_CFG,(Twin_sercfg &= (~PKTWIN_EI)));
  713.  
  714.  
  715.     /*
  716.      * Can only reset the chip when it is not being used!!!
  717.      * This handles first time use of 8530.
  718.      * Set the base vector - since it is common set it here.
  719.      */
  720.  
  721.  
  722.     if ( (Twin_udcb[TWINCOMM1].attached == FALSE) && 
  723.          (Twin_udcb[TWINCOMM2].attached == FALSE) )
  724.     {
  725.  
  726.         /* This should NOT be done... if either ports are in use */
  727.         /* for ANYTHING */
  728.         Twin_write_scc(dcbp->zhwmap.ctl,R9,(dcbp->wr9 = FHWRES));     
  729.  
  730.  
  731.         /* Save original interrupt vector */
  732.         Twin_oldvec = (INTERRUPT (*)())getirq(Twin_vector);
  733.         
  734.         udcbp->prev_vec1 = (void (*)())Twin_oldvec; 
  735.  
  736.         /* New vector... */
  737.         setirq(Twin_vector, Twin_handler);
  738.  
  739.         /* set up register images, and regs to defaults */
  740.  
  741.         Twin_sercfg = Twin_dmacfg = 0;
  742.         outportb(Twin_io_base+INT_CFG,Twin_sercfg);
  743.         outportb(Twin_io_base+DMA_CFG,Twin_dmacfg);
  744.     }
  745.     /*
  746.      * Reset the individual channel.  Handles cases of re-attaching
  747.      * channels and first attachment.
  748.      *
  749.      * For safetys sake set the Disable Lower Chain bit too.
  750.      */
  751.     if ( dcbp->dev == TWINCOMM1 )
  752.         Twin_write_scc(dcbp->zhwmap.ctl,R9,(dcbp->wr9 = 0x84));    
  753.     else    
  754.         Twin_write_scc(dcbp->zhwmap.ctl,R9,(dcbp->wr9 = 0x44));    
  755.     
  756.     /* wait a bit... for chip to settle after reset */
  757.     /* Just in case... */
  758.     for(i=0;i<20;i++);     /* milt */ 
  759.  
  760.     /* configure the 8530 SCC */     
  761.     if(tsync_hwinit(dcbp) == -1)
  762.     {
  763.         /* An error occurred in the hw init */
  764.         /* so clean up and leave... */
  765.  
  766.         /* Mark it attached so the following detach routine */
  767.         /* won't complain */
  768.         udcbp->attached = TRUE;
  769.         if_detach(intfc_p);
  770.  
  771.         /* re-enable this interrupt input */
  772.         maskon(Twin_vector);
  773.  
  774.         restore(i_state);
  775.         tprintf("PackeTwin hardware unavailable or malfunctioning...\n");
  776.         return(-1);
  777.     }
  778.  
  779.  
  780.     /* enable PackeTwin ints */
  781.     outportb(Twin_io_base+INT_CFG,(Twin_sercfg |= PKTWIN_EI));
  782.  
  783.     /* enable this level ints on 8259 */
  784.     maskon(Twin_vector);
  785.  
  786.     /* {dgl} enable system-wide ints */
  787.     restore(i_state);
  788.  
  789.     /*
  790.      *  This channel is ATTACHED.
  791.      */
  792.     udcbp->attached = TRUE;
  793.  
  794.  
  795.     /* new for NOS - start the two processes needed by the */
  796.     /* sync driver; one is for getting pre-allocated buffers */
  797.     /* the other is for kicking the transmitter after its */
  798.     /* timer has expired or when it needs a transmitted */
  799.     /* message free-ed.  P.S. must do after attached set to TRUE */
  800.  
  801.     sprintf(tmpbuf,"%s:getbuf",intfc_p->name);
  802.     dcbp->rxavproc = newproc(tmpbuf,150,tsync_rxavget,udcb_dev,NULL,NULL,0);
  803.  
  804. #ifdef TSYNC_DEBUG_PRT
  805.     printf("tsync_attach: called newproc for tsync_getbfs, procid = %lx \n",
  806.         dcbp->rxavproc);
  807. #endif
  808.  
  809.  
  810.     sprintf(tmpbuf,"%s:kick",intfc_p->name);
  811.     dcbp->txkickproc = newproc(tmpbuf,150,tsync_txkick,udcb_dev,NULL,NULL,0);
  812.  
  813. #ifdef TSYNC_DEBUG_PRT
  814.     printf("tsync_attach: called newproc for tsync_txkick, procid = %lx \n",
  815.         dcbp->txkickproc);
  816.  
  817.     tprintf("tsync_attach: All done!!! \n");
  818. #endif
  819.     sprintf(tmpbuf,"%s:free",intfc_p->name);
  820.     dcbp->freetxproc = newproc(tmpbuf,150,tsync_freetx,udcb_dev,NULL,NULL,0);
  821.  
  822.     /* Let our new processes get running... */
  823.     for(i=0;i<10;i++)pwait(NULL);
  824.  
  825.     return(0);
  826.  }
  827. /*
  828.  * End of tsync_attach()
  829.  ******************************************************************/
  830.  
  831.  
  832.  
  833. /* 
  834.  *  Stop I/O
  835.  */
  836. int
  837. tsync_stop(intfcp)
  838. struct iface *intfcp;
  839. {
  840.     DCB *sp;
  841.     UNI_DCB *udcbp;
  842.     int16 dev;
  843.     char     i_state;
  844.     struct drvbuf *xbufp, *tmpptr;
  845.     struct mbuf *tmpbufp;
  846.  
  847.  
  848.     dev = intfcp->dev;
  849.     udcbp = &Twin_udcb[dev];        /* dev num is index number!!! */
  850.  
  851.     if ( udcbp->attached != TRUE )
  852.     {
  853.         tprintf("tsync_stop err: Device already stopped/de-attached!!\n");
  854.         return(0);
  855.     }
  856.     else if ( (dev != TWINCOMM1) && (dev != TWINCOMM2) )
  857.          return(0);        /* not for this driver */
  858.  
  859.     sp = (DCB *)Twin_udcb[dev].dcbp;
  860.  
  861.     /* kill off the support processes */
  862.     /* so they don't allocate memory */
  863.     /* whils't we're freeing it */
  864.  
  865.     killproc(sp->rxavproc);
  866.     killproc(sp->txkickproc);
  867.     killproc(sp->freetxproc);
  868.  
  869.     /* Turn off interrupts */
  870.  
  871.     i_state = dirps();
  872.  
  873.     /* mark port as available - do it now for if below */
  874.     udcbp->attached = FALSE;
  875.  
  876.  
  877.  
  878.     /* Disable the DMA channels if any... */
  879.     if(sp->dma_flg)
  880.     {
  881.         outportb(DMAWSMR,sp->dma_rx_chan | 0x04);
  882.         outportb(DMAWSMR,sp->dma_tx_chan | 0x04);
  883.     }
  884.  
  885.     /*
  886.      * Can only reset the chip when it is not being used!!!
  887.      * This handles first time use of 8530.
  888.      * Set the base vector - since it is common set it here.
  889.      */
  890.  
  891.  
  892.     if ( (Twin_udcb[TWINCOMM2].attached == FALSE) && 
  893.          (Twin_udcb[TWINCOMM1].attached == FALSE) )
  894.     {
  895.  
  896.         /* This should NOT be done... if either ports are in use */
  897.         /* for ANYTHING */
  898.         Twin_write_scc(sp->zhwmap.ctl,R9,(sp->wr9 = FHWRES));     
  899.  
  900.         /* Restore original interrupt vector */
  901.         setirq(Twin_vector,(INTERRUPT (*)())udcbp->prev_vec1);
  902.  
  903.         /* Disable our board from generating ints... */
  904.         outportb(Twin_io_base+INT_CFG,(Twin_sercfg &= (~PKTWIN_EI)));
  905.     }
  906.  
  907.     /*
  908.      * Reset the individual channel.  Handles cases of re-attaching
  909.      * channels and first attachment.
  910.      *
  911.      */
  912.  
  913.     if ( sp->dev == TWINCOMM1 )
  914.     {
  915.         Twin_write_scc(sp->zhwmap.ctl,R9,(sp->wr9 = 0x88));    
  916.  
  917.         /* Drop DTR to indicate we are gone...*/
  918.         outportb(Twin_io_base+SERIAL_CFG,(Twin_sercfg &= (~PKTWIN_DTRA_ON)));
  919.     }
  920.     else    
  921.     {
  922.         Twin_write_scc(sp->zhwmap.ctl,R9,(sp->wr9 = 0x48));    
  923.         /* Drop DTR to indicate we are gone...*/
  924.         outportb(Twin_io_base+SERIAL_CFG,(Twin_sercfg &= (~PKTWIN_DTRB_ON)));
  925.     }
  926.  
  927.     restore(i_state);
  928.  
  929.     /* 
  930.      * Flush all buffers and queue's
  931.        */
  932.  
  933.     /* Now free all preallocated rx buffers on the rx available queue */    
  934.     while((tmpbufp = f_dequeavail(&sp->rxavailq,&sp->rxavailcount)) != NULLBUF)
  935.         free(tmpbufp);        /* these mbuf's are one contigous */
  936.                     /* chunk of memory */
  937.  
  938.  
  939.     if ( sp->rxbufp != NULLBUF )
  940.          free(sp->rxbufp);
  941.  
  942.     /* free up any pending transmit buffers... */
  943.     while(sp->xmtq != (struct drvbuf *)NULLBUF)
  944.     {
  945.         tmpptr = sp->xmtq->next;
  946.         free(sp->xmtq);
  947.         sp->xmtq = tmpptr;
  948.     }
  949.  
  950.     /* Free any previously sent frames, which are in the waiting to be */
  951.     /* free'd queue */
  952.  
  953.     /* disable ints here to get queue head... */
  954.     i_state = dirps();            /* seems unecessary milt */
  955.     xbufp = sp->freem;
  956.     sp->freem = (struct drvbuf *)NULLBUF;
  957.     restore(i_state);
  958.  
  959.     /* Here xbufp is a "to be free'd"  */
  960.     /* queue pointer" */
  961.     /* now free memory of all the xmitted messages */
  962.     while ( xbufp != (struct drvbuf *)NULLBUF )
  963.     {
  964.         tmpptr = xbufp->next;
  965.         free((char *)xbufp);
  966.         xbufp = tmpptr;
  967.     }
  968.  
  969.  
  970.  
  971.     /*
  972.      * Deallocate other driver related memory structures 
  973.      */
  974.     free(sp->timer1);
  975.     free(sp->ioctlparams);
  976.     free(sp);
  977.  
  978.     return(0);
  979. }
  980.  
  981.  
  982. /* 
  983.  * Display a PackeTwin SYNCHRONOUS channel's statistics.
  984.  */
  985. int
  986. do_tsync_stat()    
  987. {
  988.     DCB *dcbp;
  989.     UNI_DCB *udcbp;
  990.     int16 dev;
  991.     unsigned long rxerrcnt;
  992.     bool hd8530;
  993.  
  994.     /* Header for all the Synchronous channel's on the card */
  995.     tprintf("                    PackeTwin Synchronous Driver Release %s\n\n"
  996.                                                             ,Twin_dvr_version);
  997.  
  998.     hd8530 = FALSE;
  999.     for (dev=0, udcbp = &Twin_udcb[0]; dev < 2 ; udcbp++, dev++) 
  1000.     {
  1001.         if ( udcbp->type == SYNC_8530 )
  1002.         {
  1003.             if ( udcbp->attached == TRUE )
  1004.             {
  1005.                 if ( !hd8530 )
  1006.                 {
  1007.             tprintf("\n");
  1008.             tprintf("8530   RxChars   RxPacks  Rxerrs  RxBf   Txchars   TxPacks TxUns  RxNoBf\n");
  1009.             tprintf("----- ---------  -------  ------  ----  ---------  ------- -----  ------\n");
  1010.                     hd8530 = TRUE;
  1011.                 }
  1012.  
  1013.                 dcbp = (DCB *)udcbp->dcbp;
  1014.                 /* total receiver error count */
  1015.                 rxerrcnt = dcbp->rxcrcerrcnt + dcbp->rxovercnt;
  1016.  
  1017.             tprintf(" %4.1d %#9lu  %#7lu  %#6lu  %#4lu  %#9lu  %#7lu %#5lu  %#6lu\n",
  1018.                        dev, dcbp->rxbytecnt,
  1019.                        dcbp->rxpackcnt,
  1020.                        rxerrcnt, 
  1021.                        dcbp->rxavailcount,
  1022.                     dcbp->txbytecnt,
  1023.                     dcbp->txpackcnt,
  1024.                        dcbp->txunderun,
  1025.                     dcbp->nobufs);
  1026.  
  1027. #ifdef TSYNC_DEBUG_PRT
  1028. printf("Crc's: %lx Overruns: %lx\n",dcbp->rxcrcerrcnt,dcbp->rxovercnt);
  1029. printf("DCB ptr: %p\n",dcbp);
  1030. printf("rxcurp: %p  rxbufp: %p  rxbufp->cnt: %d\n",dcbp->rxcurp,
  1031.                                                       dcbp->rxbufp,
  1032.                                                       dcbp->rxbufp->cnt);
  1033.  
  1034. #endif
  1035.             }
  1036.         }
  1037.         
  1038.     }  /* end of for loop */
  1039.  
  1040.     for (dev=0, udcbp = &Twin_udcb[0]; dev < 2; udcbp++, dev++) 
  1041.     {
  1042.         if ( udcbp->attached == FALSE )
  1043.             tprintf("\nChannel %d is UN-attached", dev);
  1044.     }
  1045.  
  1046.     tprintf("\n");
  1047.     return(0);
  1048. }
  1049.  
  1050. /* Subroutine to set kiss params in channel tables */
  1051. int32
  1052. tsync_ioctl(iface,cmd,set,val)
  1053. struct iface *iface;
  1054. int cmd;
  1055. int set;
  1056. int32 val;
  1057. {
  1058.     DCB *dcbp;
  1059.  
  1060.     dcbp = (DCB *)Twin_udcb[iface->dev].dcbp;
  1061.  
  1062.     switch(cmd){
  1063.     case PARAM_TXDELAY:
  1064.         if(set)
  1065.             dcbp->ioctlparams->xmitdelay = (int16)val;
  1066.         return dcbp->ioctlparams->xmitdelay;
  1067.  
  1068.     case PARAM_PERSIST:
  1069.         if(set)
  1070.             dcbp->ioctlparams->persist = (uchar)val;
  1071.         return uchar(dcbp->ioctlparams->persist);
  1072.     case PARAM_SLOTTIME:
  1073.         if(set)
  1074.             dcbp->ioctlparams->slotime = (int16)val;
  1075.         return dcbp->ioctlparams->slotime;
  1076.     case PARAM_TXTAIL:
  1077.         if(set)
  1078.             dcbp->ioctlparams->squelch = (int16)val;
  1079.         return dcbp->ioctlparams->squelch;
  1080.  
  1081.     case PARAM_RXBUFS:
  1082.         if(set)
  1083.             dcbp->ioctlparams->rxavailbufs = (int16)val;
  1084.         return dcbp->ioctlparams->rxavailbufs;
  1085.  
  1086.     }
  1087.     return -1;
  1088. }
  1089.  
  1090. /* 
  1091.  * Initialize the SZ driver's hardware for SDLC, i.e. the 85c30 SCC.
  1092.  */ 
  1093. int
  1094. tsync_hwinit(dcbp)
  1095. register DCB *dcbp;
  1096. {
  1097.     char i_state;        /* for PackeTwin this is 2 bytes */
  1098.     int16 tc;        /* time constant for 8530 */
  1099.     int    i;
  1100.     bool    baudclk_flg;
  1101.     bool    both_clocks_internal;
  1102.     void tsync_loopback();
  1103.     void enable_escc();
  1104.     int    nop1 = 0;
  1105.  
  1106. #define nop nop1++;
  1107.  
  1108.  
  1109. #ifdef TSYNC_DEBUG_PRT
  1110.     printf("Initializing TSYNC_DRIVER device num = %d\n", dcbp->dev);
  1111. #endif
  1112.     i_state = dirps();
  1113.  
  1114.  
  1115.     /* if both clocks are specified as internal, then override the */
  1116.     /* specified data coding scheme, and MAKE it NRZI */
  1117.     if((dcbp->rxclk_extrn == FALSE) && (dcbp->txclk_extrn == FALSE))
  1118.     {
  1119.         dcbp->nrzi_flg = TRUE;
  1120.         both_clocks_internal = TRUE;
  1121.     }
  1122.     else 
  1123.         both_clocks_internal = FALSE;
  1124.  
  1125.     /* If we are not using DMA, then try to enable the extended TX FIFO */
  1126.     if(!(dcbp->dma_flg)) enable_escc(dcbp);
  1127.  
  1128.     /* times 1 x clock, SDLC mode */
  1129.     /* always set R4 before R1, R3, R6, and R7 */
  1130.     Twin_write_scc(dcbp->zhwmap.ctl,R4,(dcbp->wr4 = 0x20));           
  1131.  
  1132.     /* mask-off all interrupt types */
  1133.     /* No DMA, No Ints... */
  1134.     Twin_write_scc(dcbp->zhwmap.ctl,R1,(dcbp->wr1 = 0));
  1135.  
  1136.     /* Rx 8 bit/chars, enter hunt mode, CRC enable */
  1137.     Twin_write_scc(dcbp->zhwmap.ctl,R3,(dcbp->wr3 = 0xd8));            
  1138.  
  1139.     /* DTR, Tx 8 bit/chars and Tx disabled */
  1140.     Twin_write_scc(dcbp->zhwmap.ctl,R5,(dcbp->wr5 = 0x60));
  1141.  
  1142.     /* no SDLC transmit secondary address */
  1143.     Twin_write_scc(dcbp->zhwmap.ctl,R6,(dcbp->wr6 = 0));
  1144.  
  1145.     /* Set SDLC flag */
  1146.     Twin_write_scc(dcbp->zhwmap.ctl,R7,(dcbp->wr7 = FLAG));
  1147.  
  1148.     if(dcbp->nrzi_flg != TRUE)
  1149.     {
  1150.         /* Preset Tx CRC, NRZ Mode, flags on idle and */
  1151.         /* underrun 8 bit sync mode */
  1152.         Twin_write_scc(dcbp->zhwmap.ctl,R10,(dcbp->wr10 = 0x84));
  1153.     }
  1154.  
  1155.     else
  1156.     {
  1157.         /* Preset Tx CRC, NRZI Mode, flags on idle and */
  1158.         /* aborts on underrun 8 bit sync mode */
  1159.         Twin_write_scc(dcbp->zhwmap.ctl,R10,(dcbp->wr10 = 0xa4));
  1160.     }
  1161.  
  1162.     /* Set up BRG and DPLL multiplexers */
  1163.  
  1164.     /* Case where only the Rx clock is supplied externally */
  1165.     if((dcbp->rxclk_extrn == TRUE) && (dcbp->txclk_extrn != TRUE))
  1166.     {
  1167.         /* Tx Clk from BRG. Rcv Clk external on RTxC, */
  1168.         /* TRxC pin outputs BRgen */
  1169.         Twin_write_scc(dcbp->zhwmap.ctl,R11,(dcbp->wr11 = 0x16));
  1170.         tc = ( (XTAL) / (dcbp->baud *2))-2;
  1171.         baudclk_flg = TRUE;
  1172.  
  1173.         /* disable the external TX clock receiver input */
  1174.         if(dcbp->dev == TWINCOMM1) outportb(Twin_io_base+SERIAL_CFG,(Twin_sercfg &= (~PKTWIN_EXTCLKA)));    
  1175.         else outportb(Twin_io_base+SERIAL_CFG,(Twin_sercfg &= (~PKTWIN_EXTCLKB)));
  1176.     }
  1177.  
  1178.     /* Case where only the Tx clock is supplied externally */
  1179.     if((dcbp->txclk_extrn == TRUE) && (dcbp->rxclk_extrn != TRUE))
  1180.     {
  1181.         /* Tx Clk external on TRxC,  Rcv Clk internal BRgen, */
  1182.         /* TRxC pin is input TX clock */
  1183.         Twin_write_scc(dcbp->zhwmap.ctl,R11,(dcbp->wr11 = 0x4a));
  1184.         tc = ( (XTAL) /(dcbp->baud *2))-2;
  1185.         baudclk_flg = TRUE;
  1186.  
  1187.         /* enable the external TX clock receiver input */
  1188.         if(dcbp->dev == TWINCOMM1) outportb(Twin_io_base+SERIAL_CFG,(Twin_sercfg |= PKTWIN_EXTCLKA));    
  1189.         else outportb(Twin_io_base+SERIAL_CFG,(Twin_sercfg |= PKTWIN_EXTCLKB));    
  1190.     }
  1191.  
  1192.     /* Case where both clocks are supplied externally */
  1193.     if((dcbp->txclk_extrn == TRUE) && (dcbp->rxclk_extrn == TRUE))
  1194.     {
  1195.         /* Tx Clk external on TRxC,  Rcv Clk external on RTxC, */
  1196.         /* TRxC pin is input TX clock */
  1197.         Twin_write_scc(dcbp->zhwmap.ctl,R11,(dcbp->wr11 = 0x0a));
  1198.         baudclk_flg = FALSE;
  1199.  
  1200.         /* enable the external TX clock receiver input */
  1201.         if(dcbp->dev == TWINCOMM1) outportb(Twin_io_base+SERIAL_CFG,(Twin_sercfg |= PKTWIN_EXTCLKA));    
  1202.         else outportb(Twin_io_base+SERIAL_CFG,(Twin_sercfg |= PKTWIN_EXTCLKB));    
  1203.  
  1204.         /*DTR is in REQ mode for possible DMA */
  1205.         if(dcbp->dma_flg)Twin_write_scc(dcbp->zhwmap.ctl,R14,(dcbp->wr14 = 0x04));
  1206.         else Twin_write_scc(dcbp->zhwmap.ctl,R14,(dcbp->wr14 = 0x00));         
  1207.     }
  1208.  
  1209.     if(both_clocks_internal == TRUE)
  1210.     {
  1211.         /* Tx Clk from BRG. Rcv Clk from DPLL, TRxC pin outputs DPLL */
  1212.         Twin_write_scc(dcbp->zhwmap.ctl,R11,(dcbp->wr11 = 0x77));
  1213.  
  1214.         /* time constant 32X BRG divisor */
  1215.         tc = ((XTAL/32)/(dcbp->baud * 2))-2;    
  1216.         /* DGL... fix a cut and paste error... */
  1217.         /* baudclk_flg = FALSE; */
  1218.         baudclk_flg = TRUE; 
  1219.  
  1220.         /* disable the external TX clock receiver input */
  1221.         if(dcbp->dev == TWINCOMM1) outportb(Twin_io_base+SERIAL_CFG,(Twin_sercfg &= (~PKTWIN_EXTCLKA)));    
  1222.         else outportb(Twin_io_base+SERIAL_CFG,(Twin_sercfg &= (~PKTWIN_EXTCLKB)));    
  1223.  
  1224.     }
  1225.  
  1226.     if(baudclk_flg == TRUE)
  1227.     {
  1228.  
  1229.         /* lower byte */
  1230.         Twin_write_scc(dcbp->zhwmap.ctl,R12,(dcbp->wr12 = (tc&0xFF)));      
  1231.  
  1232.         /* upper byte */
  1233.         Twin_write_scc(dcbp->zhwmap.ctl,R13,(dcbp->wr13 = ((tc>>8)&0xFF))); 
  1234.  
  1235.         /* enable the BR generator... */
  1236.         /*DTR is in REQ mode for possible DMA */
  1237.         if(dcbp->dma_flg)Twin_write_scc(dcbp->zhwmap.ctl,R14,(dcbp->wr14 = 0x07));
  1238.         else Twin_write_scc(dcbp->zhwmap.ctl,R14,(dcbp->wr14 = 0x03));         
  1239.     }
  1240.  
  1241.  
  1242.     if(both_clocks_internal == TRUE)
  1243.     {
  1244.  
  1245.         /* BRG off, Enter Search mode */
  1246.         /*DTR is in REQ mode if possible DMA */
  1247.         if(dcbp->dma_flg)Twin_write_scc(dcbp->zhwmap.ctl,R14,(dcbp->wr14 = 0x26));
  1248.         else Twin_write_scc(dcbp->zhwmap.ctl,R14,(dcbp->wr14 = 0x22));
  1249.  
  1250.         /* Set DPLL source to BRGEN */
  1251.         /*DTR is in REQ mode for possible DMA */
  1252.         if(dcbp->dma_flg)Twin_write_scc(dcbp->zhwmap.ctl,R14,(dcbp->wr14 = 0x86));
  1253.         else Twin_write_scc(dcbp->zhwmap.ctl,R14,(dcbp->wr14 = 0x82));
  1254.  
  1255.         /* Set DPLL mode to NRZI */
  1256.         /*DTR is in REQ mode for possible DMA */
  1257.         if(dcbp->dma_flg)Twin_write_scc(dcbp->zhwmap.ctl,R14,(dcbp->wr14 = 0xe6));
  1258.         else Twin_write_scc(dcbp->zhwmap.ctl,R14,(dcbp->wr14 = 0xe2));
  1259.  
  1260.  
  1261.  
  1262. /* At this point; the DPLL is searching for a data edge to begin clocking */
  1263. /*           The baud rate gen is set to 32 times the desired rate.. */
  1264. /*          The transmitter is based on the BRGEN. (i.e. 32x )      */
  1265. /*                                                                        */
  1266. /* Procedure here; Set up an external loopback, then send aborts, to      */
  1267. /*            trigger and sync up the DPLL.                */
  1268. /*            After the DPLL is running, then reprogram the Xmitter  */
  1269. /*            to use the DPLL output as it's transmitter clock.      */
  1270. /*            This saves us having to reprogram the BRG whenever we  */
  1271. /*           switch from RECV to TX and back.                       */
  1272. /*          
  1273.  
  1274.         /* Turn on the recvr */    
  1275.         /* Rx 8 bit/chars, enter hunt mode, CRC enable */
  1276.         Twin_write_scc(dcbp->zhwmap.ctl,R3,(dcbp->wr3 = 0xd9));
  1277.  
  1278.         /* Turn on the transmitter */
  1279.         /* DTR, Tx 8 bit/chars and Tx enabled */
  1280.         Twin_write_scc(dcbp->zhwmap.ctl,R5,(dcbp->wr5 = 0x68));         
  1281.  
  1282.         /* reset TX CRC */
  1283.         Twin_write_scc(dcbp->zhwmap.ctl,R0,(dcbp->wr0 = 0x80));         
  1284.  
  1285.         /* enable the BR generator to start things up...*/
  1286.         /*DTR is in REQ mode for possible DMA */
  1287.         if(dcbp->dma_flg)Twin_write_scc(dcbp->zhwmap.ctl,R14,(dcbp->wr14 = 0x07));
  1288.         else Twin_write_scc(dcbp->zhwmap.ctl,R14,(dcbp->wr14 = 0x03));
  1289.  
  1290.  
  1291.         /* OK now turn on the loopback */
  1292.         tsync_loopback(dcbp,ON);
  1293.  
  1294.         /* Now send sum aborts... */
  1295.  
  1296.         for(i=0;i<25;i++)
  1297.         {
  1298.  
  1299.             /* read and toss any  data */
  1300.             inportb(dcbp->zhwmap.data);
  1301.             inportb(dcbp->zhwmap.data);
  1302.             inportb(dcbp->zhwmap.data);
  1303.             inportb(dcbp->zhwmap.data);
  1304.  
  1305.             Twin_write_scc(dcbp->zhwmap.ctl,R0,(dcbp->wr0 = 0x18));         /* send abort */
  1306.         }
  1307.  
  1308.         /* OK, now the DPLL should be running at ~32 * baudrate requested */
  1309.         /* Turn off the loopback... */
  1310.  
  1311.         tsync_loopback(dcbp,OFF);
  1312.  
  1313.  
  1314.         /* Now reprogram the transmitter clock to use the DPLL output */
  1315.  
  1316.         /* TX clk is DPLL, RX clk is DPLL, TRxc is DPLL OUT */
  1317.         Twin_write_scc(dcbp->zhwmap.ctl,R11,(dcbp->wr11 = 0x7f));
  1318.  
  1319.         /* dgl for G3RUH modems... I need to do AUTO-ENABLES... */
  1320.         Twin_write_scc(dcbp->zhwmap.ctl,R3,(dcbp->wr3 = 0xf9));         
  1321.  
  1322.  
  1323.     }
  1324.  
  1325.     else
  1326.     {
  1327.  
  1328.         /* Turn on the recvr */    
  1329.         /* Rx 8 bit/chars, enter hunt mode, CRC enable */
  1330.  
  1331.         /*  no autoenables */
  1332.         /*
  1333.         Twin_write_scc(dcbp->zhwmap.ctl,R3,(dcbp->wr3 = 0xd9));         
  1334.         */
  1335.  
  1336.         /* dgl for G3RUH modems... I need to do AUTO-ENABLES... */
  1337.         Twin_write_scc(dcbp->zhwmap.ctl,R3,(dcbp->wr3 = 0xf9));         
  1338.  
  1339.     }    
  1340.  
  1341.     /* Turn off external interrupts (like CTS/CD) */
  1342.     Twin_write_scc(dcbp->zhwmap.ctl,R15,(dcbp->wr15 = 0x00));
  1343.  
  1344.     
  1345.     /* TRANSMITTER OFF */
  1346.     Twin_write_scc(dcbp->zhwmap.ctl,R5,(dcbp->wr5 = 0x60)); /* TX off now */
  1347.     Twin_write_scc(dcbp->zhwmap.ctl,R0,(dcbp->wr0 = 0x80)); /* reset TX CRC generator */
  1348.     Twin_write_scc(dcbp->zhwmap.ctl,R0,(dcbp->wr0 = 0x40)); /* reset RX CRC checker */
  1349.  
  1350.     Twin_write_scc(dcbp->zhwmap.ctl,R0,(dcbp->wr0 = 0x28)); /* reset TX int pending */
  1351.     Twin_write_scc(dcbp->zhwmap.ctl,R0,(dcbp->wr0 = 0x28)); /* reset TX int pending */
  1352.     
  1353.  
  1354.     /* reset extrn/sts ints... twice */
  1355.     Twin_write_scc(dcbp->zhwmap.ctl,R0,(dcbp->wr0 = 0x10));
  1356.     Twin_write_scc(dcbp->zhwmap.ctl,R0,(dcbp->wr0 = 0x10));
  1357.  
  1358.     /* if we are interrupt driven only: then allow ints for ALL RCV cndxs,
  1359.     */
  1360.     if(dcbp->dma_flg == FALSE)
  1361.         Twin_write_scc(dcbp->zhwmap.ctl,R1,(dcbp->wr1 = 0x11));
  1362.  
  1363.     /* otherwise interrupt on special rcv cdx only */
  1364.     /* DMA req mode Req on rcv, Req enabled */
  1365.     else  Twin_write_scc(dcbp->zhwmap.ctl,R1,(dcbp->wr1 = 0xf9));
  1366.  
  1367.     Twin_write_scc(dcbp->zhwmap.ctl,R0,(dcbp->wr0 = 0x30)); /* reset error bits */
  1368.     Twin_write_scc(dcbp->zhwmap.ctl,R0,(dcbp->wr0 = 0x30)); /* twice superstition */
  1369.  
  1370.     /* If neither of the PKTwin's ports are currently attached*/
  1371.     /* Then set up the prescaler timer */
  1372.     if ( (Twin_udcb[TWINCOMM2].attached == FALSE) && 
  1373.          (Twin_udcb[TWINCOMM1].attached == FALSE) )
  1374.     {
  1375.         inportb(Twin_io_base+CLR_TMR1);
  1376.         nop;
  1377.         inportb(Twin_io_base+CLR_TMR2);
  1378.         nop;
  1379.  
  1380.         /* Timer counter channel 0 */
  1381.         /* 1 ms period */
  1382.         outportb(Twin_io_base+TMR_CTRL,(unsigned char)0x36);
  1383.         nop;
  1384.         outportb(Twin_io_base+TMR_CNT0,(unsigned char)0x00);
  1385.         nop;
  1386.         outportb(Twin_io_base+TMR_CNT0,(unsigned char)0x18);
  1387.         nop;
  1388.  
  1389.         outportb(Twin_io_base+TMR_CTRL,(unsigned char)0x70);
  1390.         nop;
  1391.         inportb(Twin_io_base+CLR_TMR1);
  1392.         nop;
  1393.  
  1394.         outportb(Twin_io_base+TMR_CTRL,(unsigned char)0xB0);
  1395.         nop;
  1396.         inportb(Twin_io_base+CLR_TMR2);
  1397.         nop;
  1398.     }
  1399.  
  1400.     if(dcbp->dev == TWINCOMM1)
  1401.     {
  1402.         /* mode setup for this channel's driver timer */
  1403.         /* Set it's timer for 1 tick and let it expire */
  1404.         outportb(Twin_io_base+TMR_CTRL,(unsigned char)0x70);
  1405.         nop;
  1406.         inportb(Twin_io_base+CLR_TMR1);
  1407.         nop;
  1408.  
  1409.  
  1410.         /* If the timer hasn't gone off, the hardware is either */
  1411.         /* not present, or broken... */
  1412.         if(!inportb(Twin_io_base+INT_REG) & 0x02)
  1413.         {
  1414.             restore(i_state);
  1415.             return(-1);
  1416.         }
  1417.  
  1418.         /* Assert DTR to indicate we are alive...*/
  1419.         outportb(Twin_io_base+SERIAL_CFG,(Twin_sercfg |= PKTWIN_DTRA_ON));
  1420.         
  1421.     }
  1422.     if(dcbp->dev == TWINCOMM2)
  1423.     {
  1424.         /* mode setup for this channel's driver timer */
  1425.         outportb(Twin_io_base+TMR_CTRL,(unsigned char)0xb0);
  1426.         nop;
  1427.         inportb(Twin_io_base+CLR_TMR2);
  1428.         nop;
  1429.         /* If the timer hasn't gone off, the hardware is either */
  1430.         /* not present, or broken... */
  1431.         if(!inportb(Twin_io_base+INT_REG) & 0x04)
  1432.         {
  1433.             restore(i_state);
  1434.             return(-1);
  1435.         }
  1436.         nop;
  1437.         /* Assert DTR to indicate we are alive...*/
  1438.         outportb(Twin_io_base+SERIAL_CFG,(Twin_sercfg |= PKTWIN_DTRB_ON));
  1439.     }
  1440.  
  1441.     if(dcbp->dma_flg == TRUE)
  1442.     {
  1443.         /* mask off the DMA channel(s) */
  1444.         outportb(DMAWSMR,(dcbp->dma_rx_chan | 0x04));
  1445.         outportb(DMAWSMR,(dcbp->dma_tx_chan | 0x04));
  1446.  
  1447.         outportb(Twin_io_base+DMA_CLR_FF,0x00);    /* Initially clear the REQ's */    
  1448.                         /* This is the PackeTwin reg..*/
  1449.                         /* NOT the 8237 reg... */                    
  1450.         outportb(DMAMODE,dcbp->dma_rx_chan |  RX_DMA);
  1451.  
  1452.         if(dcbp->hduplex == FALSE)
  1453.         {
  1454.             outportb(DMAMODE,dcbp->dma_rx_chan |  RX_DMA);
  1455.             outportb(DMAMODE,dcbp->dma_tx_chan |  TX_DMA);
  1456.             /* tx dma, enabled, fdx, chan3*/
  1457.             /* rx dma, enabled, fdx, chan1*/
  1458.             outportb(Twin_io_base+DMA_CFG,dcbp->dma_tx_mode);
  1459.  
  1460.         }
  1461.         else
  1462.         {
  1463.             outportb(DMAMODE,dcbp->dma_rx_chan |  RX_DMA);
  1464.             /* rx dma,hdx, enabled, chan 1*/
  1465.             outportb(Twin_io_base+DMA_CFG,dcbp->dma_rx_mode);
  1466.         }
  1467.         outportb(DMAFFCL,0x00);        /* This is the 8237 reg */
  1468.  
  1469.         rxprime_dma(dcbp,1);        /* buglet... 9/12/92 */
  1470.                                     /* {dgl} */
  1471.     }
  1472.  
  1473.     /* reset Tx int pending */
  1474.     /* This should keep the chip from underrunning, as */
  1475.     /* well as clearing any pending txempty interrupt */
  1476.     Twin_write_scc(dcbp->zhwmap.ctl,R0,(dcbp->wr0 = 0x28));
  1477.  
  1478.     /* reset external status latch */
  1479.     /* clear any pending ext sts bits */
  1480.     /* TWICE for good measure */
  1481.     Twin_write_scc(dcbp->zhwmap.ctl,R0,(dcbp->wr0 = RES_EXT_INT));
  1482.     Twin_write_scc(dcbp->zhwmap.ctl,R0,(dcbp->wr0 = RES_EXT_INT));
  1483.  
  1484.     /* Reset Underrun/EOM latch */
  1485.     /* clear the latch... it should stay that way...*/
  1486.     /* at least till we send feed some data to the tx fifo */
  1487.     Twin_write_scc(dcbp->zhwmap.ctl,R0,(dcbp->wr0 = (RES_EOM_L | RES_EXT_INT)));
  1488.  
  1489.     /* Turn on DCD interrupt */
  1490.     Twin_write_scc(dcbp->zhwmap.ctl,R15,(dcbp->wr15 = CTSIE|DCDIE));
  1491.  
  1492.     /* save this initial state of RR0 */
  1493.      dcbp->extreg = Twin_read_scc(dcbp->zhwmap.ctl,R0);    
  1494.     dcbp->extreg = dcbp->extreg |= TxEOM;
  1495.  
  1496.     /* if we are interrupt driven only: then allow ints for ALL RCV cndxs,
  1497.     */
  1498.     if(dcbp->dma_flg == FALSE)
  1499.         Twin_write_scc(dcbp->zhwmap.ctl,R1,(dcbp->wr1 = 0x13));
  1500.  
  1501.     /* otherwise interrupt on special rcv cdx only */
  1502.     /* DMA req mode Req on rcv, Req enabled */
  1503.     else  Twin_write_scc(dcbp->zhwmap.ctl,R1,(dcbp->wr1 = 0xf9));
  1504.  
  1505.     /* master interrupt enable  the channel */
  1506.     Twin_write_scc(dcbp->zhwmap.ctl,R9,(dcbp->wr9 = (MIE|DLC|NV))); 
  1507.  
  1508.     restore(i_state);
  1509.     return(0);
  1510. }
  1511.  
  1512. void
  1513. tsync_loopback(dcbp,flag)
  1514. DCB     *dcbp;
  1515. char    flag;
  1516. {
  1517.     if(flag == ON)
  1518.     {
  1519.         switch(dcbp->dev)
  1520.         {
  1521.             case TWINCOMM1: outportb(Twin_io_base+SERIAL_CFG,(Twin_sercfg |= PKTWIN_LOOPA_ON));
  1522.                                  break;
  1523.  
  1524.             case TWINCOMM2: outportb(Twin_io_base+SERIAL_CFG,(Twin_sercfg |= PKTWIN_LOOPB_ON));
  1525.                             break;
  1526.         }
  1527.     }
  1528.     else
  1529.     {
  1530.         switch(dcbp->dev)
  1531.         {
  1532.             case TWINCOMM1: outportb(Twin_io_base+SERIAL_CFG,(Twin_sercfg &= (~PKTWIN_LOOPA_ON)));
  1533.                                      break;
  1534.  
  1535.             case TWINCOMM2: outportb(Twin_io_base+SERIAL_CFG,(Twin_sercfg &= (~PKTWIN_LOOPB_ON)));
  1536.                             break;
  1537.         }
  1538.     }
  1539.  
  1540. }
  1541.  
  1542.  
  1543. void
  1544. tsync_reset_8530()
  1545. {
  1546.  
  1547. int16    ctl;
  1548.  
  1549.     ctl = (int16)(Twin_io_base+SCCA_CMD);
  1550.     Twin_write_scc(ctl,R9,FHWRES);     
  1551.  
  1552. }
  1553.  
  1554. /*
  1555.           1         2         3         4         5         6         7
  1556. 01234567890123456789012345678901234567890123456789012345678901234567890123456789
  1557. /* 
  1558.  * Display a PackeTwin SYNCHRONOUS channel's internal state
  1559.  */
  1560. int
  1561. do_tsync_dump(argc,argv,p)
  1562. int argc;            
  1563. char *argv[];
  1564. void *p;                /* new for NOS */
  1565. {
  1566.     DCB *dcbp;
  1567.     UNI_DCB *udcbp;
  1568.     int16 dev;
  1569.     char    tmpstr[40];
  1570.  
  1571.     if(argc < 2)
  1572.     {
  1573.         tprintf("Usage: tsydump channel#\n");
  1574.         return 1;
  1575.     }
  1576.  
  1577.     dev = htoi(argv[1]);        /* get port number to look at */
  1578.  
  1579.     tprintf("                PackeTwin Synchronous Channel Internals\n\n");
  1580.  
  1581.     udcbp = &Twin_udcb[dev];
  1582.     if ( udcbp->type == SYNC_8530 )
  1583.     {
  1584.         if ( udcbp->attached == TRUE )
  1585.         {
  1586.             dcbp = (DCB *)udcbp->dcbp;
  1587.             tprintf("\n");
  1588.             tprintf(" RECEIVER STATUS: \n");
  1589.             tprintf(" Packcnt       Nqued     Bytecnt  Availcount      Nobufs\n");
  1590.             tprintf("%#8ld    %#8ld    %#8ld    %#8ld    %#8ld\n",
  1591.                             dcbp->rxpackcnt,dcbp->rxnqued,
  1592.                             dcbp->rxbytecnt,dcbp->rxavailcount,dcbp->nobufs);
  1593.  
  1594.             tprintf("\n");    /* blank line */
  1595.             tprintf(" Overcnt    Abortcnt   Crcerrcnt     Truncnt\n");
  1596.             tprintf("%#8ld    %#8ld    %#8ld    %#8ld\n",
  1597.                             dcbp->rxovercnt,dcbp->rxabortcnt,
  1598.                             dcbp->rxcrcerrcnt,dcbp->rxtruncnt);
  1599.  
  1600.             tprintf("\n");    /* blank line */
  1601.  
  1602.             switch(dcbp->txstate)
  1603.             {
  1604.                 case    IDLE:
  1605.                                 strcpy(tmpstr,"IDLE");
  1606.                                 break;
  1607.  
  1608.                 case    DEFER:
  1609.                                 strcpy(tmpstr,"DEFER");
  1610.                                 break;
  1611.  
  1612.                 case    TX_ACTIVE:
  1613.                                 strcpy(tmpstr,"TX_ACTIVE");
  1614.                                 break;
  1615.  
  1616.                 case    KEYED_UP:
  1617.                                 strcpy(tmpstr,"KEYED_UP");
  1618.                                 break;
  1619.  
  1620.                 case    CRCING:
  1621.                                 strcpy(tmpstr,"CRCING");
  1622.                                 break;
  1623.  
  1624.                 case    TX_KEYUP_DELAY:
  1625.                                     strcpy(tmpstr,"TX_KEYUP_DELAY");
  1626.                                     break;
  1627.  
  1628.                 case    TX_KEYDOWN_DELAY:
  1629.                                     strcpy(tmpstr,"TX_KEYDOWN_DELAY");
  1630.                                     break;
  1631.  
  1632.                 case    TX_PERSIST:
  1633.                                     strcpy(tmpstr,"TX_PERSIST");
  1634.                                     break;
  1635.  
  1636.                 case    TX_DONE:
  1637.                                 strcpy(tmpstr,"TX_DONE");
  1638.                                 break;
  1639.  
  1640.                 default:
  1641.                                 strcpy(tmpstr,"UNKNOWN STATE");
  1642.                                 break;
  1643.  
  1644.             }
  1645.  
  1646.             tprintf(" TRANSMITTER STATUS:\n");
  1647.             tprintf(" Packcnt     Bytecnt    Underrun    Cur_xbufp   Cur_xbytes  MxFIFO  TX STATE\n");
  1648.  
  1649.             tprintf("%8ld    %8ld    %8ld    %8lx    %8d      %2.2d    ",
  1650.                     dcbp->txpackcnt,dcbp->txbytecnt,
  1651.                     dcbp->txunderun,dcbp->cur_xbufp,
  1652.                     dcbp->cur_xbytes,dcbp->maxtxbytes);
  1653.             tprintf("%s\n",tmpstr);
  1654.  
  1655.             tprintf("\n");    /* blank line */
  1656.             tprintf(" CTSlost: %d\n",dcbp->txctslost);
  1657.             tprintf("\n");    /* blank line */
  1658.  
  1659.             tprintf( "WR0  WR1  WR2  WR3  WR4  WR5  WR6  WR7  WR8  WR9  WR10 WR11 WR12 WR13 WR14 WR15");
  1660.  
  1661.  
  1662.             tprintf(" %2.2x   %2.2x   %2.2x   %2.2x   %2.2x   %2.2x   %2.2x   %2.2x   %2.2x   %2.2x   %2.2x   %2.2x   %2.2x   %2.2x   %2.2x   %2.2x",
  1663.                     dcbp->wr0,dcbp->wr1,dcbp->wr2,dcbp->wr3,dcbp->wr4,
  1664.                     dcbp->wr5,dcbp->wr6,dcbp->wr7,0,dcbp->wr9,
  1665.                     dcbp->wr10,dcbp->wr11,dcbp->wr12,dcbp->wr13,dcbp->wr14,
  1666.                     dcbp->wr15);
  1667.  
  1668.             tprintf("\n");
  1669.             tprintf("\n");
  1670.  
  1671. tprintf("Extsts  Extreg  Hduplex  Dma_flg  Txclk_extrn  Rxclk_extrn  Nrzi_flg\n");
  1672.             tprintf("  %2.2x      %2.2x      %2.2x       %2.2x         %2.2x           %2.2x           %2.2x\n",
  1673.                     dcbp->extsts,dcbp->extreg,dcbp->hduplex,
  1674.                     dcbp->dma_flg,dcbp->txclk_extrn,
  1675.                     dcbp->rxclk_extrn,dcbp->nrzi_flg);
  1676.  
  1677.  
  1678.             tprintf("\n");
  1679.  
  1680.             tprintf("Dma_rx_chan  Dma_rx_mode  Dma_rx_pagereg  Dma_rx_cnt_reg  Dma_rx_addr_reg\n");
  1681.  
  1682.             tprintf( "    %2.2x           %2.2x           %2.2x              %2.2x              %2.2x\n",
  1683.                         dcbp->dma_rx_chan,dcbp->dma_rx_mode,
  1684.                         dcbp->dma_rx_pagereg,dcbp->dma_rx_cnt_reg,
  1685.                         dcbp->dma_rx_addr_reg);
  1686.  
  1687.             tprintf("Dma_tx_chan  Dma_tx_mode  Dma_tx_pagereg  Dma_tx_cnt_reg  Dma_tx_addr_reg\n");
  1688.             tprintf( "    %2.2x           %2.2x           %2.2x              %2.2x              %2.2x\n",
  1689.                         dcbp->dma_tx_chan,dcbp->dma_tx_mode,
  1690.                         dcbp->dma_tx_pagereg,dcbp->dma_tx_cnt_reg,
  1691.                         dcbp->dma_tx_addr_reg);
  1692.  
  1693.         }
  1694.         else tprintf("Channel %d: is UN-attached!\n",dev);
  1695.     }
  1696.         
  1697.  
  1698.     tprintf("\n");
  1699.     return(0);
  1700. }
  1701.  
  1702. /* 85230 Mods: Call this routine to enable the Deeper TX fifo... */
  1703. /* Do it BEFORE you set up WR7 (sync char), cause it will trash  */
  1704. /* WR7 if the installed chip is actually an 85c30 or 8530 instead*/
  1705. /* of an 85230 */
  1706. void
  1707. enable_escc(dcbp)
  1708. register DCB *dcbp;
  1709. {
  1710.  
  1711.     /* try to enable the escc extended registers */
  1712.     Twin_write_scc(dcbp->zhwmap.ctl,R15,0x01);
  1713.  
  1714.     /* Set up the TX FIFO to generate an interrupt as soon */
  1715.     /* as there is ANY room in the FIFO.  Rather than the default */
  1716.     /* of when the FIFO is empty. */
  1717.  
  1718.     /* If this is just an SCC, then the R7 will be overwritten */
  1719.     /* by the real init code later..., but if not, */
  1720.     /* then this is R7' for FIFO control */
  1721.     Twin_write_scc(dcbp->zhwmap.ctl,R7,0x00);
  1722.  
  1723.     /* restore the WR15 to an acceptable value for an 8530 */
  1724.     Twin_write_scc(dcbp->zhwmap.ctl,R15,0x00);
  1725. }    
  1726.