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

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