home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ibmtool.zip / prim.c < prev    next >
Text File  |  1997-11-07  |  30KB  |  929 lines

  1. /******************************************************************************/
  2. /*                                                                            */
  3. /*      FILE: PRIM.C                                                          */
  4. /*                                                                            */
  5. /*   PURPOSE: This file contains the MAC Primitive processing.                */
  6. /*                                                                            */
  7. /* FUNCTIONS: InitXmit                                                        */
  8. /*            TTUseGDT                                                        */
  9. /*            TTSetTxBuffSize                                                 */
  10. /*            TTEditBuffer                                                    */
  11. /*            TTDispXmitBuf                                                   */
  12. /*            TTXmit                                                          */
  13. /*            TTMultipleXmit                                                  */
  14. /*            TTIndicationsOff                                                */
  15. /*            TTIndicationsOn                                                 */
  16. /*            SendControlFrame                                                */
  17. /*            PrimEcho                                                        */
  18. /*                                                                            */
  19. /* GLOBAL DATA ACCESSED                                                       */
  20. /*      char       *RetStr[]                                                  */
  21. /*      BOOLEAN     TokenRing                                                 */
  22. /*      BOOLEAN     Debug                                                     */
  23. /*      USHORT      ReqHandle                                                 */
  24. /*      USHORT      LastStatus                                                */
  25. /*      USHORT      DOSVersion                                                */
  26. /*      WORD        LastFrameSize                                             */
  27. /*      ULONG       hWedge                                                    */
  28. /*      SERVICECHAR MACMSC                                                    */
  29. /*      CTRLFRAME   ControlFrame                                              */
  30. /*                                                                            */
  31. /******************************************************************************/
  32.  
  33. #define INCL_SUB
  34. #define INCL_BASE
  35. #define INCL_DOS
  36. #include <os2.h>
  37. #include <stdio.h>
  38. #include <stdarg.h>
  39. #include <malloc.h>
  40. #include <stdlib.h>
  41. #include <string.h>
  42. #include <ctype.h>
  43. #include "ndis.h"
  44. #include "ibmtool.h"
  45. #include "ioctl.h"
  46.  
  47. #define PHYS_ADDR           0
  48. #define GDT_ADDR            2
  49.  
  50. #define TRAN                0
  51. #define MTRAN               1
  52. #define CTRL                2
  53.  
  54. #define ONEK                1024
  55. #define SEGSIZE             0xFFFF
  56. #define HALFSEG             SEGSIZE >> 1
  57. #define HALFSEGPLUS         HALFSEG + ONEK
  58.  
  59. typedef struct _TXDESC {
  60.   BYTE far  *pDest;
  61.   BYTE far  *pSrc;
  62.   BYTE far  *pLen;
  63.   BYTE far  *pOpCode;
  64.   BYTE far  *pData;
  65.   TXBUFDESC  TxBufDesc;
  66. } TXDESC;
  67.  
  68. typedef struct _TXCHAINSTR {
  69.   WORD           ReqHandle;
  70.   TXBUFDESC far *TxBuffDescPtr;
  71. } TXCHAINSTR;
  72. TXCHAINSTR TxChain;
  73.  
  74. TXDESC TxDesc[3];
  75.  
  76. BYTE BroadcastAddr[ADDR_LEN];
  77.  
  78. int InitXmit ()
  79. {
  80.   int            i, offset;
  81.   IOCTLDATA      IOData;
  82.   IOCTLDATA far *IODataPtr = &IOData;
  83.  
  84.   /* initialize the broadcast address */
  85.   for (i=0; i<ADDR_LEN; ++i) BroadcastAddr[i] = 0xFF;
  86.  
  87.   /*** initialize the TRAN Tx Buffer Descriptor ***/
  88.  
  89.   TxDesc[TRAN].TxBufDesc.TxImmedLen = MAX_IMMED_LEN;
  90.   TxDesc[TRAN].TxBufDesc.TxImmedPtr =
  91.        (BYTE far *) _fcalloc (MAX_IMMED_LEN, sizeof (BYTE));
  92.   _fmemset ((void far *) TxDesc[TRAN].TxBufDesc.TxImmedPtr, 0, MAX_IMMED_LEN);
  93.  
  94.   for (i=0; i<MAX_TX_DATABLK; ++i)
  95.      TxDesc[TRAN].TxBufDesc.TxDataBlk[i].TxRsvdByte = 0;
  96.  
  97.   TxDesc[TRAN].TxBufDesc.TxDataCnt = 0;
  98.  
  99.   offset = 0;
  100.   if (TokenRing) offset = 2;
  101.   TxDesc[TRAN].pDest = (TxDesc[TRAN].TxBufDesc.TxImmedPtr + offset);
  102.   TxDesc[TRAN].pSrc  = (TxDesc[TRAN].TxBufDesc.TxImmedPtr + offset +
  103.                          MACMSC.MscStnAdrSz);
  104.   TxDesc[TRAN].pLen = TxDesc[TRAN].pSrc + MACMSC.MscStnAdrSz;
  105.  
  106.   /*** initialize the MTRAN Tx Buffer Descriptor ***/
  107.  
  108.   TxDesc[MTRAN].TxBufDesc.TxImmedLen = WedgeCommon->HeaderLen;
  109.   TxDesc[MTRAN].TxBufDesc.TxImmedPtr =
  110.        (BYTE far *) _fcalloc (MACMSC.MscMaxFrame, sizeof (BYTE));
  111.   TxDesc[MTRAN].TxBufDesc.TxDataCnt = 1;
  112.   TxDesc[MTRAN].TxBufDesc.TxDataBlk[0].TxRsvdByte = 0;
  113.   TxDesc[MTRAN].pData = TxDesc[MTRAN].TxBufDesc.TxDataBlk[0].TxDataPtr =
  114.        TxDesc[MTRAN].TxBufDesc.TxImmedPtr + WedgeCommon->HeaderLen;
  115.  
  116.   for (i=0; i<MACMSC.MscMaxFrame; ++i)
  117.      TxDesc[MTRAN].TxBufDesc.TxImmedPtr[MACMSC.MscMaxFrame-i-1] =
  118.                                             (BYTE) ((i + 1) & 0xFF);
  119.  
  120.   offset = 0;
  121.   if (TokenRing)
  122.     {
  123.      TxDesc[MTRAN].TxBufDesc.TxImmedPtr[offset++] = 0x10;
  124.      TxDesc[MTRAN].TxBufDesc.TxImmedPtr[offset++] = 0x40;
  125.     }
  126.   TxDesc[MTRAN].pDest = (TxDesc[MTRAN].TxBufDesc.TxImmedPtr + offset);
  127.   TxDesc[MTRAN].pSrc  = (TxDesc[MTRAN].TxBufDesc.TxImmedPtr + offset +
  128.                          MACMSC.MscStnAdrSz);
  129.   TxDesc[MTRAN].pLen = TxDesc[MTRAN].pSrc + MACMSC.MscStnAdrSz;
  130.  
  131.   // restore the GDT address
  132.   TxDesc[MTRAN].TxBufDesc.TxDataBlk[0].TxDataPtr = TxDesc[MTRAN].pData;
  133.  
  134.   // put in the Broadcast Address as the Destination
  135.   _fmemcpy ((void far *) TxDesc[MTRAN].pDest,
  136.             (void far *) BroadcastAddr, 6);
  137.  
  138.   /* initialize the CTRL Tx Buffer Descriptor */
  139.   TxDesc[CTRL].TxBufDesc.TxImmedLen = MAX_IMMED_LEN;
  140.   TxDesc[CTRL].TxBufDesc.TxImmedPtr =
  141.        (BYTE far *) _fcalloc (MAX_IMMED_LEN, sizeof (BYTE));
  142.   TxDesc[CTRL].TxBufDesc.TxDataCnt = 0;
  143.   TxDesc[CTRL].TxBufDesc.TxDataBlk[0].TxPtrType = 0;
  144.   TxDesc[CTRL].TxBufDesc.TxDataBlk[0].TxRsvdByte = 0;
  145.   TxDesc[CTRL].TxBufDesc.TxDataBlk[0].TxDataPtr = NULL;
  146.  
  147.   offset = 0;
  148.   if (TokenRing)
  149.     {
  150.      TxDesc[CTRL].TxBufDesc.TxImmedPtr[offset++] = 0x10;
  151.      TxDesc[CTRL].TxBufDesc.TxImmedPtr[offset++] = 0x40;
  152.     }
  153.   TxDesc[CTRL].pDest = (TxDesc[CTRL].TxBufDesc.TxImmedPtr + offset);
  154.   TxDesc[CTRL].pSrc  = (TxDesc[CTRL].TxBufDesc.TxImmedPtr + offset +
  155.                         MACMSC.MscStnAdrSz);
  156.   TxDesc[CTRL].pData = (TxDesc[CTRL].TxBufDesc.TxImmedPtr +
  157.                         WedgeCommon->HeaderLen);
  158.   strcpy ((char *) TxDesc[CTRL].pData, CTRLID);
  159.   TxDesc[CTRL].pOpCode = TxDesc[CTRL].pData + strlen (CTRLID);
  160.  
  161. }
  162.  
  163. int TTUseGDT ()
  164. {
  165.   // USEGDT
  166.  
  167.   if (DOSVersion == OS2)
  168.      WedgeCommon->UseGDT = (WedgeCommon->UseGDT) ? FALSE : TRUE;
  169.  
  170.   if (WedgeCommon->UseGDT)
  171.      aprintf (0, 77, 0x74, "G");
  172.   else
  173.      aprintf (0, 77, 0x70, " ");
  174.  
  175.   return SUCCESS;
  176. }
  177.  
  178. int TTSetTxBuffSize ()
  179. {
  180.   // TXSIZE *<Size>
  181.   //        if no parameters given, then display buffer sizes
  182.  
  183.   char *token;
  184.   WORD  i, BlkCnt, BlkSize, TotalSize = 0;
  185.  
  186.   token = strtok (NULL, "\n\t ");
  187.   if (token)
  188.     {
  189.      // free up the previous buffers
  190.      _ffree ((void far *) TxDesc[TRAN].TxBufDesc.TxImmedPtr);
  191.      for (i=0; i<TxDesc[TRAN].TxBufDesc.TxDataCnt; ++i)
  192.         _ffree ((void far *) TxDesc[TRAN].TxBufDesc.TxDataBlk[i].TxDataPtr);
  193.  
  194.      // reset the block count
  195.      BlkCnt = TxDesc[TRAN].TxBufDesc.TxDataCnt = 0;
  196.  
  197.      // get the immediate buffer size
  198.      if ((TxDesc[TRAN].TxBufDesc.TxImmedLen = (int) GetNumericParm (token)) < 0)
  199.         return TT_INVALID_PARAMETER;
  200.  
  201.      /* attempt to allocate each buffer (Immediate and Data)  */
  202.      /* in a different segment                                */
  203.  
  204.      // allocate the immediate buffer
  205.      TxDesc[TRAN].TxBufDesc.TxImmedPtr =
  206.           (BYTE far *) calloc (TxDesc[TRAN].TxBufDesc.TxImmedLen, sizeof (BYTE));
  207.  
  208.      if (!TxDesc[TRAN].TxBufDesc.TxImmedPtr)
  209.         TxDesc[TRAN].TxBufDesc.TxImmedPtr =
  210.              (BYTE far *) calloc (MAX_IMMED_LEN, sizeof (BYTE));
  211.  
  212.      // loop to get the data block sizes and allocate the buffers
  213.      while ((token = strtok (NULL, "\n\t ")) != NULL)
  214.        {
  215.         if ((BlkSize = (WORD) GetNumericParm (token)) < 0)
  216.            return TT_INVALID_PARAMETER;
  217.         TxDesc[TRAN].TxBufDesc.TxDataBlk[BlkCnt].TxDataLen = BlkSize;
  218.         TxDesc[TRAN].TxBufDesc.TxDataBlk[BlkCnt].TxDataPtr =
  219.              (BYTE far *) _fcalloc ((USHORT) HALFSEGPLUS, sizeof (BYTE));
  220.         if (!TxDesc[TRAN].TxBufDesc.TxDataBlk[BlkCnt].TxDataPtr)
  221.            TxDesc[TRAN].TxBufDesc.TxDataBlk[BlkCnt].TxDataPtr =
  222.                 (BYTE far *) _fcalloc (BlkSize, sizeof (BYTE));
  223.         BlkCnt = ++TxDesc[TRAN].TxBufDesc.TxDataCnt;
  224.        }
  225.     }
  226.   else
  227.     {
  228.      PrintMsg (0, "Immediate Length: %d", TxDesc[TRAN].TxBufDesc.TxImmedLen);
  229.      for (i=0; i<TxDesc[TRAN].TxBufDesc.TxDataCnt; ++i)
  230.         PrintMsg (0, "Tx Data Block %d Length: %d",
  231.                   i, TxDesc[TRAN].TxBufDesc.TxDataBlk[i].TxDataLen);
  232.     }
  233.  
  234.   return SUCCESS;
  235. }
  236.  
  237. int TTEditBuffer ()
  238. {
  239.   // EDITBUF {I | # | R} <Data>
  240.  
  241.   char *token, *s;
  242.   int  i = 0, j, bufno, cnt, max;
  243.   USHORT data;
  244.  
  245.   token = strtok (NULL, "\n\t ");
  246.   if (!token) return TT_INVALID_PARAMETER;
  247.  
  248.   if (*token == 'I')
  249.     {
  250.      while ((token = strtok (NULL, "\n\t ")) != NULL)
  251.        {
  252.         if ((s = strstr (token, "*")))
  253.           {
  254.            *s++ = '\0';
  255.            if (sscanf (token, "%d", &cnt) != 1)
  256.               return TT_INVALID_PARAMETER;
  257.            if (sscanf (s, "%02X", &data) != 1)
  258.               return TT_INVALID_PARAMETER;
  259.            max = (cnt > TxDesc[TRAN].TxBufDesc.TxImmedLen) ?
  260.                       TxDesc[TRAN].TxBufDesc.TxImmedLen : cnt;
  261.            for (j=0; j<max; ++j)
  262.               TxDesc[TRAN].TxBufDesc.TxImmedPtr[i++] = data;
  263.           }
  264.         else
  265.           {
  266.            if (sscanf (token, "%02X", &data) != 1)
  267.               return TT_INVALID_PARAMETER;
  268.            TxDesc[TRAN].TxBufDesc.TxImmedPtr[i++] = data;
  269.           }
  270.        }
  271.     }
  272.   else if (*token == 'R')
  273.     {
  274.      return (TTEditTMBuffer ());
  275.     }
  276.   else if (token)
  277.     {
  278.      if (sscanf (token, "%d", &bufno) != 1)
  279.         return TT_INVALID_PARAMETER;
  280.      if (bufno < TxDesc[TRAN].TxBufDesc.TxDataCnt)
  281.         while ((token = strtok (NULL, "\n\t ")) != NULL &&
  282.                i < TxDesc[TRAN].TxBufDesc.TxDataBlk[bufno].TxDataLen)
  283.           {
  284.            if ((s = strstr (token, "*")))
  285.              {
  286.               *s++ = '\0';
  287.               if (sscanf (token, "%d", &cnt) != 1)
  288.                  return TT_INVALID_PARAMETER;
  289.               if (sscanf (s, "%02X", &data) != 1)
  290.                  return TT_INVALID_PARAMETER;
  291.               max = (cnt > TxDesc[TRAN].TxBufDesc.TxDataBlk[bufno].TxDataLen) ?
  292.                       TxDesc[TRAN].TxBufDesc.TxDataBlk[bufno].TxDataLen : cnt;
  293.               for (j=0; j<max; ++j)
  294.                  TxDesc[TRAN].TxBufDesc.TxDataBlk[bufno].TxDataPtr[i++] = data;
  295.              }
  296.            else
  297.              {
  298.               if (sscanf (token, "%02X", &data) != 1)
  299.                  return TT_INVALID_PARAMETER;
  300.               TxDesc[TRAN].TxBufDesc.TxDataBlk[bufno].TxDataPtr[i++] = data;
  301.              }
  302.           }
  303.      else
  304.         return TT_INVALID_PARAMETER;
  305.     } /* endif */
  306.  
  307.   return SUCCESS;
  308. }
  309.  
  310. int TTDispXmitBuf ()
  311. {
  312.   // TXBUF
  313.  
  314.   char    *token;
  315.   int      i;
  316.   BOOLEAN  pause = FALSE;
  317.  
  318.   PrintMsg (0, "Immediate Buffer");
  319.   if ((token = strtok (NULL, "\n\t ")))
  320.      if (*token == 'P') pause = TRUE;
  321.  
  322.   hexprint (TxDesc[TRAN].TxBufDesc.TxImmedPtr,
  323.             TxDesc[TRAN].TxBufDesc.TxImmedLen, pause);
  324.  
  325.   for (i=0; i<TxDesc[TRAN].TxBufDesc.TxDataCnt; ++i)
  326.     {
  327.      PrintMsg (0, "Data Buffer %d", i);
  328.      hexprint (TxDesc[TRAN].TxBufDesc.TxDataBlk[i].TxDataPtr,
  329.                TxDesc[TRAN].TxBufDesc.TxDataBlk[i].TxDataLen, pause);
  330.     }
  331.  
  332.   return SUCCESS;
  333. }
  334.  
  335. int TTXmit ()
  336. {
  337.   // TRAN [<Return>]
  338.  
  339.   char          *RetCode;
  340.   int            i, ExpRC;
  341.   TXDESC         TempTxDesc;                // saves the GDT pointers
  342.   IOCTLDATA      IOData;
  343.   IOCTLDATA far *IODataPtr = &IOData;
  344.  
  345.   if (Debug)
  346.     {
  347.      RetCode = strtok (NULL, "\n\t ");
  348.      if (!RetCode) return TT_INVALID_PARAMETER;
  349.  
  350.      if ((ExpRC = GetRCInt (RetCode)) < 0)
  351.         return TT_INVALID_PARAMETER;
  352.  
  353.      TMSetResult (ExpRC);
  354.     }
  355.  
  356.   // Put the Current Station Address in the frame header
  357.   _fmemcpy ((void far *) TxDesc[TRAN].pSrc,
  358.             (void far *) MACMSC.MscCurrStnAdr, MACMSC.MscStnAdrSz);
  359.  
  360.   // save GDT pointers
  361.   TempTxDesc = TxDesc[TRAN];
  362.  
  363.   TxChain.ReqHandle = ++ReqHandle;
  364.   for (i=0; i<TxDesc[TRAN].TxBufDesc.TxDataCnt; ++i)
  365.     {
  366.      TxDesc[TRAN].TxBufDesc.TxDataBlk[i].TxPtrType = GDT_ADDR;
  367.      if (!WedgeCommon->UseGDT)
  368.        {
  369.         TxDesc[TRAN].TxBufDesc.TxDataBlk[i].TxPtrType = PHYS_ADDR;
  370.         IOData.ReqCode = VIRT_TO_PHYS;
  371.         IOData.Length  = 0;
  372.         IOData.SrcDataPtr =
  373.              (void far *) TxDesc[TRAN].TxBufDesc.TxDataBlk[i].TxDataPtr;
  374.         IOData.DestDataPtr = NULL;
  375.         GenIoctl ((void far *) IODataPtr, hWedge);
  376.         TxDesc[TRAN].TxBufDesc.TxDataBlk[i].TxDataPtr = IOData.SrcDataPtr;
  377.        }
  378.     }
  379.   TxChain.TxBuffDescPtr = (void far *) &TxDesc[TRAN].TxBufDesc;
  380.  
  381.   IOData.ReqCode = MACCMD;
  382.   IOData.Length  = TRANSMITCHAIN;
  383.   IOData.SrcDataPtr = (void far *) &TxChain;
  384.   IOData.DestDataPtr = NULL;
  385.   GenIoctl ((void far *) IODataPtr, hWedge);
  386.   LastStatus = IOData.ReqCode;
  387.  
  388.   // restore GDT pointers
  389.   TxDesc[TRAN] = TempTxDesc;
  390.  
  391.   PrintMsg (0, "TransmitChain:  %s", RetStr[LastStatus]);
  392.  
  393.   return SUCCESS;
  394.  
  395. }
  396.  
  397. int TTMultipleXmit ()
  398. {
  399.   // MULTRAN [Cnt] [<Min> <Max>] [<Type> [<NetAddr>]]
  400.  
  401.   char          *token;
  402.   int            i, parmcnt = 0,
  403.                  Min = WedgeCommon->HeaderLen,
  404.                  Max = MACMSC.MscMaxFrame,
  405.                  MaxDataLen = MACMSC.MscMaxFrame - WedgeCommon->HeaderLen,
  406.                  DataLen,
  407.                  Type = BROADCAST,
  408.                  tempaddr,
  409.                  Inc = 0;
  410.   ULONG          Cnt = 50L;
  411.   IOCTLDATA      IOData, PhysIOData;
  412.   IOCTLDATA far *IODataPtr = &IOData, *PhysIODataPtr = &PhysIOData;
  413.  
  414.   // get the number of frames to transmit
  415.   if ((token = strtok (NULL, "\n\t ")))
  416.     {
  417.      if ((Cnt = GetNumericParm (token)) < 0)
  418.         return TT_INVALID_PARAMETER;
  419.      if (!Cnt) Cnt = 1;
  420.      ++parmcnt;
  421.     }
  422.  
  423.   // get the minimum length of the frames (optional)
  424.   if ((token = strtok (NULL, "\n\t ")))
  425.     {
  426.      if ((Min = (int) GetNumericParm (token)) < 0)
  427.         return TT_INVALID_PARAMETER;
  428.      ++parmcnt;
  429.     }
  430.  
  431.   if (Min > MACMSC.MscMaxFrame)
  432.      Min = MACMSC.MscMaxFrame;
  433.   else if (Min < WedgeCommon->HeaderLen)
  434.      Min = WedgeCommon->HeaderLen;
  435.  
  436.   // get the maximum length of the frames (optional)
  437.   if ((token = strtok (NULL, "\n\t ")))
  438.     {
  439.      if ((Max = (int) GetNumericParm (token)) < 0)
  440.         return TT_INVALID_PARAMETER;
  441.      if (Max > MACMSC.MscMaxFrame)
  442.         Max = MACMSC.MscMaxFrame;
  443.      if (Max < Min) Max = Min;
  444.      ++parmcnt;
  445.     }
  446.  
  447.   if (parmcnt != 2 && Min != Max)
  448.     {
  449.      if (Cnt >= 2)
  450.        {
  451.         Inc = (Max - Min) / (Cnt - 1);
  452.         if (!Inc) Inc = 1;
  453.        }
  454.      else Min = MAX_IMMED_LEN;
  455.     }
  456.  
  457.   // get the type of the frame (optional)
  458.   if ((token = strtok (NULL, "\n\t ")))
  459.     {
  460.      if ((Type = (int) GetNumericParm (token)) < 0)
  461.         return TT_INVALID_PARAMETER;
  462.     }
  463.  
  464.   switch (Type)
  465.     {
  466.      case BROADCAST:
  467.        _fmemcpy ((void far *) TxDesc[MTRAN].pDest,
  468.                  (void far *) BroadcastAddr, MACMSC.MscStnAdrSz);
  469.        break;
  470.      case DIRECTED:
  471.      case DIRECTED_TO_WKSTA:
  472.        // get the destination address of the frame (required at this point)
  473.        for (i=0; i<MACMSC.MscStnAdrSz; ++i)
  474.          {
  475.           if (!(token = strtok (NULL, "\n\t ")))
  476.              return TT_INVALID_PARAMETER;
  477.           if ((sscanf (token, "%02X", &tempaddr) != 1))
  478.              return TT_INVALID_PARAMETER;
  479.           TxDesc[MTRAN].pDest[i] = (BYTE) tempaddr;
  480.          } /* endfor */
  481.        break;
  482.      case DIRECTED_TO_SERVER:
  483.        _fmemcpy ((void far *) TxDesc[MTRAN].pDest,
  484.                  (void far *) WedgeCommon->ServerAddr, MACMSC.MscStnAdrSz);
  485.        break;
  486.     } /* endswitch */
  487.  
  488.   // put in the Source Address
  489.   _fmemcpy ((void far *) TxDesc[MTRAN].pSrc,
  490.             (void far *) MACMSC.MscCurrStnAdr, MACMSC.MscStnAdrSz);
  491.  
  492.   // put frame length in the frame data
  493.   DataLen = Min - WedgeCommon->HeaderLen;
  494.   TxDesc[MTRAN].TxBufDesc.TxDataBlk[0].TxDataLen = DataLen;
  495.   *(WORD *) TxDesc[MTRAN].pLen = DataLen;
  496.  
  497.   // determine where the TxDataPtr should be
  498.   TxDesc[MTRAN].TxBufDesc.TxDataBlk[0].TxDataPtr =
  499.        &TxDesc[MTRAN].TxBufDesc.TxImmedPtr[MACMSC.MscMaxFrame - DataLen];
  500.  
  501.   TxChain.ReqHandle = 0;
  502.  
  503.   TxDesc[MTRAN].TxBufDesc.TxDataBlk[0].TxPtrType = GDT_ADDR;
  504.   if (!WedgeCommon->UseGDT)
  505.     {
  506.      TxDesc[MTRAN].TxBufDesc.TxDataBlk[0].TxPtrType = PHYS_ADDR;
  507.  
  508.      // get the MTRAN Data Block physical address
  509.      PhysIOData.ReqCode = VIRT_TO_PHYS;
  510.      PhysIOData.SrcDataPtr =
  511.           (void far *) TxDesc[MTRAN].TxBufDesc.TxDataBlk[0].TxDataPtr;
  512.      GenIoctl ((void far *) PhysIODataPtr, hWedge);
  513.      TxDesc[MTRAN].TxBufDesc.TxDataBlk[0].TxDataPtr = PhysIOData.SrcDataPtr;
  514.     }
  515.  
  516.   TxChain.TxBuffDescPtr = (void far *) &TxDesc[MTRAN].TxBufDesc;
  517.  
  518.   IOData.ReqCode = MACCMD;
  519.   IOData.Length  = TRANSMITCHAIN;
  520.   IOData.SrcDataPtr = (void far *) &TxChain;
  521.   IOData.DestDataPtr = NULL;
  522.  
  523. //hexprint (TxDesc[MTRAN].TxBufDesc.TxImmedPtr, MAX_IMMED_LEN, 0);
  524. //getch ();
  525.  
  526.   for (i=0; i<Cnt - 1; ++i)
  527.     {
  528.      // Transmit the frame
  529.      GenIoctl ((void far *) IODataPtr, hWedge);
  530.  
  531.      PrintMsg (0, "TransmitChain:  %s", RetStr[IOData.ReqCode]);
  532.  
  533.      // check for indications (like ReceiveLookahead or ReceiveChain)
  534.      CheckIndications ();
  535.  
  536.      // increment the DataLen if necessary
  537.      if (Cnt > 1 && i == Cnt - 2)
  538.        {
  539.         // last frame should be Max FrameSize or Max parameter
  540.         if (parmcnt < 2)
  541.            DataLen = MaxDataLen;
  542.         else if (parmcnt == 3)
  543.            DataLen = Max - WedgeCommon->HeaderLen;
  544.        }
  545.      else
  546.         DataLen += Inc;
  547.  
  548.      // bounds check
  549.      if (DataLen > MaxDataLen) DataLen = MaxDataLen;
  550.  
  551.      TxDesc[MTRAN].TxBufDesc.TxDataBlk[0].TxDataLen = DataLen;
  552.  
  553.      // put the DataLen in as the first word of data
  554.      *(WORD *) TxDesc[MTRAN].pLen = DataLen;
  555.  
  556.      // determine where the TxDataPtr should be
  557.      TxDesc[MTRAN].TxBufDesc.TxDataBlk[0].TxDataPtr =
  558.           &TxDesc[MTRAN].TxBufDesc.TxImmedPtr[MACMSC.MscMaxFrame - DataLen];
  559.  
  560.      if (!WedgeCommon->UseGDT)
  561.        {
  562.         // get the MTRAN Data Block physical address -- again
  563.         PhysIOData.ReqCode = VIRT_TO_PHYS;
  564.         PhysIOData.SrcDataPtr = TxDesc[MTRAN].TxBufDesc.TxDataBlk[0].TxDataPtr;
  565.         GenIoctl ((void far *) PhysIODataPtr, hWedge);
  566.         TxDesc[MTRAN].TxBufDesc.TxDataBlk[0].TxDataPtr = PhysIOData.SrcDataPtr;
  567.        }
  568.  
  569.      // reset the Request Code because it came back as the Status
  570.      IOData.ReqCode = MACCMD;
  571.     } /* endfor */
  572.  
  573.   // Transmit the last frame or the only frame
  574.   GenIoctl ((void far *) IODataPtr, hWedge);
  575.  
  576.   PrintMsg (0, "TransmitChain:  %s", RetStr[IOData.ReqCode]);
  577.  
  578.   return SUCCESS;
  579. }
  580.  
  581. int TTIndicationsOff ()
  582. {
  583.   // INDICOFF [<Return>]
  584.  
  585.   IOCTLDATA      IOData;
  586.   IOCTLDATA far *IODataPtr = &IOData;
  587.  
  588.   if (GetRetCodes ()) return TT_INVALID_PARAMETER;
  589.  
  590.   IOData.ReqCode = MACCMD;
  591.   IOData.Length  = INDICATIONOFF;
  592.   IOData.SrcDataPtr = NULL;
  593.   IOData.DestDataPtr = NULL;
  594.   GenIoctl ((void far *) IODataPtr, hWedge);
  595.   LastStatus = IOData.ReqCode;
  596.  
  597.   PrintMsg (0, "Indications Off:  %s", RetStr[LastStatus]);
  598.  
  599.   return SUCCESS;
  600. }
  601.  
  602. int TTIndicationsOn ()
  603. {
  604.   // INDICON [<Return>]
  605.  
  606.   IOCTLDATA      IOData;
  607.   IOCTLDATA far *IODataPtr = &IOData;
  608.  
  609.   if (GetRetCodes ()) return TT_INVALID_PARAMETER;
  610.  
  611.   IOData.ReqCode = MACCMD;
  612.   IOData.Length  = INDICATIONON;
  613.   IOData.SrcDataPtr = NULL;
  614.   IOData.DestDataPtr = NULL;
  615.   GenIoctl ((void far *) IODataPtr, hWedge);
  616.   LastStatus = IOData.ReqCode;
  617.  
  618.   PrintMsg (0, "Indications On:  %s", RetStr[LastStatus]);
  619.  
  620.   return SUCCESS;
  621. }
  622.  
  623. USHORT SendControlFrame (int CFCode)
  624. {
  625.   char          *token;
  626.   int            i;
  627.   BYTE      far *data;
  628.   WORD           tempaddr;
  629.   WORD           Type = BROADCAST;
  630.   ULONG          Cnt, Min, Max;
  631.   IOCTLDATA      IOData;
  632.   IOCTLDATA far *IODataPtr = &IOData;
  633.  
  634.   switch (CFCode)
  635.     {
  636.      case CCWKSTA:
  637.        /* send a broadcast frame out to find a server */
  638.  
  639.        // put in the broadcast address
  640.        _fmemcpy ((void far *) TxDesc[CTRL].pDest,
  641.                  (void far *) BroadcastAddr,
  642.                  MACMSC.MscStnAdrSz);
  643.  
  644.        // put in the source address
  645.        _fmemcpy ((void far *) TxDesc[CTRL].pSrc,
  646.                  (void far *) MACMSC.MscCurrStnAdr,
  647.                  MACMSC.MscStnAdrSz);
  648.  
  649.        // put in the Control Code
  650.        *(WORD *) TxDesc[CTRL].pOpCode = CFCode;
  651.  
  652.        // no data required
  653.  
  654.        break;
  655.  
  656.      case CCSERVER:
  657.        // send a directed frame to a workstation
  658.  
  659.        // put in the workstation address
  660.        _fmemcpy ((void far *) TxDesc[CTRL].pDest,
  661.                  (void far *) ControlFrame.pSrc,
  662.                  MACMSC.MscStnAdrSz);
  663.  
  664.        // put in the source address
  665.        _fmemcpy ((void far *) TxDesc[CTRL].pSrc,
  666.                  (void far *) MACMSC.MscCurrStnAdr,
  667.                  MACMSC.MscStnAdrSz);
  668.  
  669.        // put in the Control Code
  670.        *(WORD *) TxDesc[CTRL].pOpCode = CFCode;
  671.  
  672.        // no data required
  673.  
  674.        PrintMsg (RED, "CCSERVER sent");
  675.        hexprint (TxDesc[CTRL].pDest, 64, 0);
  676.  
  677.        break;
  678.  
  679.      case CCSTRESS:
  680.        // send a broadcast frame to tell workstations to start stressing
  681.      case CCSRVSTOP:
  682.        // send a broadcast frame to tell workstations that server has
  683.        // quit the stress test
  684.  
  685.        // put in the broadcast address
  686.        _fmemcpy ((void far *) TxDesc[CTRL].pDest,
  687.                  (void far *) BroadcastAddr,
  688.                  MACMSC.MscStnAdrSz);
  689.  
  690.        // put in the source address
  691.        _fmemcpy ((void far *) TxDesc[CTRL].pSrc,
  692.                  (void far *) MACMSC.MscCurrStnAdr,
  693.                  MACMSC.MscStnAdrSz);
  694.  
  695.        // put in the Control Code
  696.        data = (BYTE far *) TxDesc[CTRL].pOpCode;
  697.        *(WORD *) data = (WORD) CFCode;
  698.        if (CFCode == CCSTRESS)
  699.          {
  700.           data += sizeof (WORD);
  701.           // put in the the stress parameters
  702.           PutStressParms (data);
  703.          }
  704.  
  705.        if (CFCode == CCSTRESS)
  706.           PrintMsg (RED, "CCSTRESS sent");
  707.        else
  708.           PrintMsg (RED, "CCSRVSTOP sent");
  709.        hexprint (TxDesc[CTRL].pDest, 30, 0);
  710.  
  711.        break;
  712.  
  713.      case CCXMIT:
  714.        // send a directed frame to the server telling him
  715.        // to do a MULTRAN with the current command parameters
  716.  
  717.        // put in the server address
  718.        _fmemcpy ((void far *) TxDesc[CTRL].pDest,
  719.                  (void far *) ControlFrame.pSrc,
  720.                  MACMSC.MscStnAdrSz);
  721.  
  722.        // put in the source address
  723.        _fmemcpy ((void far *) TxDesc[CTRL].pSrc,
  724.                  (void far *) MACMSC.MscCurrStnAdr,
  725.                  MACMSC.MscStnAdrSz);
  726.  
  727.        // put in the Control Code
  728.        data = (BYTE far *) TxDesc[CTRL].pOpCode;
  729.        *(WORD *) data = (WORD) CFCode;
  730.        data += sizeof (WORD);
  731.  
  732.        /* parse the data out */
  733.        // get the count (number of frames to transmit - required)
  734.        if (!(token = strtok (NULL, "\n\t ")))
  735.           return TT_INVALID_PARAMETER;
  736.         if ((Cnt = GetNumericParm (token)) < 0)
  737.            return TT_INVALID_PARAMETER;
  738.         *(DWORD *) data = Cnt;
  739.         data += sizeof (DWORD);
  740.  
  741.         // get the Min and Max parameters (required)
  742.        if (!(token = strtok (NULL, "\n\t ")))
  743.           return TT_INVALID_PARAMETER;
  744.         if ((Min = GetNumericParm (token)) < 0)
  745.            return TT_INVALID_PARAMETER;
  746.         *(DWORD *) data = Min;
  747.         data += sizeof (DWORD);
  748.  
  749.        if (!(token = strtok (NULL, "\n\t ")))
  750.           return TT_INVALID_PARAMETER;
  751.        if ((Max = GetNumericParm (token)) < 0)
  752.           return TT_INVALID_PARAMETER;
  753.        *(DWORD *) data = Max;
  754.        data += sizeof (DWORD);
  755.  
  756.        // get the frame type (optional)
  757.        if ((token = strtok (NULL, "\n\t ")))
  758.          {
  759.           if ((Type = (WORD) GetNumericParm (token)) < 0)
  760.              return TT_INVALID_PARAMETER;
  761.          }
  762.        *(WORD *) data = Type;
  763.        data += sizeof (WORD);
  764.  
  765.        switch (Type)
  766.          {
  767.           case BROADCAST:
  768.           case DIRECTED_TO_WKSTA:
  769.           case DIRECTED_TO_SERVER:
  770.             break;
  771.           case DIRECTED:
  772.             // get the destination address of the frame (required at this point)
  773.             for (i=0; i<MACMSC.MscStnAdrSz; ++i)
  774.               {
  775.                if (!(token = strtok (NULL, "\n\t ")))
  776.                   return TT_INVALID_PARAMETER;
  777.                if ((sscanf (token, "%02X", &tempaddr) != 1))
  778.                   return TT_INVALID_PARAMETER;
  779.                *(BYTE *) data++ = (BYTE) tempaddr;
  780.               } /* endfor */
  781.             break;
  782.           default:
  783.             return TT_INVALID_PARAMETER;
  784.             break;
  785.          } /* endswitch */
  786.  
  787.        break;
  788.  
  789.      case CCDELWKSTA:
  790.      case CCENDSTRESS:
  791.      case CCQUERYACK:
  792.  
  793.        // put in the server address
  794.        _fmemcpy ((void far *) TxDesc[CTRL].pDest,
  795.                  (void far *) WedgeCommon->ServerAddr,
  796.                  MACMSC.MscStnAdrSz);
  797.  
  798.        // put in the source address
  799.        _fmemcpy ((void far *) TxDesc[CTRL].pSrc,
  800.                  (void far *) MACMSC.MscCurrStnAdr,
  801.                  MACMSC.MscStnAdrSz);
  802.  
  803.        // put in the Control Code
  804.        *(WORD far *) TxDesc[CTRL].pOpCode = (WORD) CFCode;
  805.  
  806.        // no data required
  807.  
  808.        if (CFCode == CCDELWKSTA)
  809.           PrintMsg (RED, "CCDELWKSTA sent");
  810.        else if (CFCode == CCENDSTRESS)
  811.           PrintMsg (RED, "CCENDSTRESS sent");
  812.        else
  813.           PrintMsg (RED, "CCQUERYACK sent");
  814.        hexprint (TxDesc[CTRL].pDest, 64, 0);
  815.  
  816.        break;
  817.  
  818.      case CCENDSTRESSACK:
  819.      case CCQUERYWKSTA:
  820.  
  821.        // put in the workstation's address
  822.        _fmemcpy ((void far *) TxDesc[CTRL].pDest,
  823.                  (void far *) ControlFrame.pSrc,
  824.                  MACMSC.MscStnAdrSz);
  825.  
  826.        // put in the source address
  827.        _fmemcpy ((void far *) TxDesc[CTRL].pSrc,
  828.                  (void far *) MACMSC.MscCurrStnAdr,
  829.                  MACMSC.MscStnAdrSz);
  830.  
  831.        // put in the Control Code
  832.        *(WORD far *) TxDesc[CTRL].pOpCode = (WORD) CFCode;
  833.  
  834.        // no data required
  835.  
  836.        if (CFCode == CCENDSTRESSACK)
  837.           PrintMsg (RED, "CCENDSTRESSACK sent");
  838.        else
  839.           PrintMsg (RED, "CCQUERYWKSTA sent");
  840.        hexprint (TxDesc[CTRL].pDest, 64, 0);
  841.  
  842.        break;
  843.  
  844.     } /* endswitch */
  845.  
  846.   // do the Ioctl
  847.   TxChain.TxBuffDescPtr = (void far *) &TxDesc[CTRL].TxBufDesc;
  848.   IOData.ReqCode = MACCMD;
  849.   IOData.Length  = TRANSMITCHAIN;
  850.   IOData.SrcDataPtr = (void far *) &TxChain;
  851.   IOData.DestDataPtr = NULL;
  852.   GenIoctl ((void far *) IODataPtr, hWedge);
  853.   LastStatus = IOData.ReqCode;
  854.  
  855.   return SUCCESS;
  856. }
  857.  
  858. void PrimEcho ()
  859. {
  860.   int            BlkSize;
  861.   IOCTLDATA      IOData;
  862.   IOCTLDATA far *IODataPtr = &IOData;
  863.   TXDESC         TempTxDesc;                // saves the GDT pointers
  864.  
  865.   // save GDT pointers
  866.   TempTxDesc = TxDesc[MTRAN];
  867.  
  868.   /*** set up the MTRAN Buffer Descriptor ***/
  869.  
  870.   // copy received data
  871.   _fmemcpy ((void far *) TxDesc[MTRAN].TxBufDesc.TxImmedPtr,
  872.             (void far *) WedgeCommon->RcvData, LastFrameSize);
  873.  
  874.   // set the immediate length
  875.   TxDesc[MTRAN].TxBufDesc.TxImmedLen = MAX_IMMED_LEN;
  876.  
  877.   // set the data block length
  878.   BlkSize = LastFrameSize - MAX_IMMED_LEN;
  879.   TxDesc[MTRAN].TxBufDesc.TxDataBlk[0].TxDataLen =
  880.        (BlkSize > 0) ? BlkSize : 0;
  881.  
  882.   // set the data block ptr
  883.   TxDesc[MTRAN].TxBufDesc.TxDataBlk[0].TxDataPtr =
  884.        TxDesc[MTRAN].TxBufDesc.TxImmedPtr + (LastFrameSize - MAX_IMMED_LEN);
  885.  
  886.   // replace destination address with source address
  887.   _fmemcpy ((void far *) TxDesc[MTRAN].pDest,
  888.             (void far *) TxDesc[MTRAN].pSrc, MACMSC.MscStnAdrSz);
  889.  
  890.   // put the Current Station Address in as the source address
  891.   _fmemcpy ((void far *) TxDesc[MTRAN].pSrc,
  892.             (void far *) MACMSC.MscCurrStnAdr, MACMSC.MscStnAdrSz);
  893.  
  894.   TxChain.ReqHandle = ++ReqHandle;
  895.   TxDesc[MTRAN].TxBufDesc.TxDataBlk[0].TxPtrType = GDT_ADDR;
  896.   if (!WedgeCommon->UseGDT)
  897.     {
  898.      TxDesc[MTRAN].TxBufDesc.TxDataBlk[0].TxPtrType = PHYS_ADDR;
  899.      IOData.ReqCode = VIRT_TO_PHYS;
  900.      IOData.Length  = 0;
  901.      IOData.SrcDataPtr =
  902.           (void far *) TxDesc[MTRAN].TxBufDesc.TxDataBlk[0].TxDataPtr;
  903.      IOData.DestDataPtr = NULL;
  904.      GenIoctl ((void far *) IODataPtr, hWedge);
  905.      TxDesc[MTRAN].TxBufDesc.TxDataBlk[0].TxDataPtr = IOData.SrcDataPtr;
  906.     }
  907.   TxChain.TxBuffDescPtr = (void far *) &TxDesc[MTRAN].TxBufDesc;
  908.  
  909.   IOData.ReqCode = MACCMD;
  910.   IOData.Length  = TRANSMITCHAIN;
  911.   IOData.SrcDataPtr = (void far *) &TxChain;
  912.   IOData.DestDataPtr = NULL;
  913.   GenIoctl ((void far *) IODataPtr, hWedge);
  914.   LastStatus = IOData.ReqCode;
  915.  
  916.   // restore GDT pointers
  917.   TxDesc[MTRAN] = TempTxDesc;
  918.  
  919.   PrintMsg (0, "TransmitChain:  %s", RetStr[LastStatus]);
  920.  
  921.   // restore MTRAN's normal immediate length
  922.   TxDesc[MTRAN].TxBufDesc.TxImmedLen = WedgeCommon->HeaderLen;
  923.  
  924.   // restore the Broadcast Address as the Destination for MTRAN
  925.   _fmemcpy ((void far *) TxDesc[MTRAN].pDest,
  926.             (void far *) BroadcastAddr, 6);
  927. }
  928.  
  929.