home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / andistkt.zip / MACINIT.C < prev    next >
Text File  |  1995-04-19  |  38KB  |  845 lines

  1. /*****************************************************************************/
  2. /*                                                                           */
  3. /*   Component   : Sample ANDIS MAC Driver                                   */
  4. /*                                                                           */
  5. /*   Module      : MACINIT.C                                                 */
  6. /*                                                                           */
  7. /*   Description : This module contains the routines that initialize the     */
  8. /*                 MAC.  These routines include the device driver strategy   */
  9. /*                 routine and routines that process PROTOCOL.INI config     */
  10. /*                 data.                                                     */
  11. /*                                                                           */
  12. /*****************************************************************************/
  13.  
  14. #define INCL_DOS
  15. #include <os2.h>
  16. #include "typedef.h"
  17. #include "ndis.h"
  18. #include "andis.h"
  19. #include "macdef.h"
  20. #include "macproto.h"
  21.  
  22.  
  23. extern USHORT EndofData;
  24.  
  25.  
  26. /* All global variables should be initialized. */
  27. /* This puts them in the _DATA segment.        */
  28.  
  29. PFN      pDevHelp     = NULL;   /* Address of DevHelp routine          */
  30. PMODULE  pModuleList  = NULL;   /* Linked list of Modules              */
  31. PHYSADDR FirstModPhys = {0,0};  /* Physical address of first Module    */
  32. USHORT   PMHandle     = 0;      /* Handle to PROTMAN device driver     */
  33. USHORT   LogHandle    = 0;      /* Handle to LAN message device driver */
  34.  
  35.  
  36. /*****************************************************************************/
  37. /*                                                                           */
  38. /*   Routine     : Strategy                                                  */
  39. /*                                                                           */
  40. /*   Description : This routine is the C language stragegy routine for the   */
  41. /*                 device driver.  This routine is called from the assembly  */
  42. /*                 language strategy routine, stragegy_asm.                  */
  43. /*                                                                           */
  44. /*                 If an initialization request packet is received then      */
  45. /*                 the Initialize routine is called, else an error is        */
  46. /*                 returned.                                                 */
  47. /*                                                                           */
  48. /*****************************************************************************/
  49.  
  50. VOID NEAR Strategy( PREQPKT pRequestPacket )
  51. {
  52.    pRequestPacket->Status = STATUS_SUCCESS;
  53.  
  54.    if ( pRequestPacket->Command == COMMAND_INIT )
  55.       Initialize( (PININITRP)pRequestPacket );
  56.    else
  57.       pRequestPacket->Status = STATUS_ERROR + STATUS_UNKNOWN;
  58.  
  59.    pRequestPacket->Status |= STATUS_DONE;
  60. }
  61.  
  62.  
  63. /*****************************************************************************/
  64. /*                                                                           */
  65. /*   Routine     : EndofCode                                                 */
  66. /*                                                                           */
  67. /*   Description : This routine is the first routine in the INITCODE         */
  68. /*                 segment.  The INITCODE segment will be discarded          */
  69. /*                 when initialization is complete.  The purpose of this     */
  70. /*                 routine is to mark the end of the code segment that is    */
  71. /*                 left when initialization is complete.  All initiali-      */
  72. /*                 zation routines should be in this file following this     */
  73. /*                 routine and should be placed in the INITCODE segment      */
  74. /*                 (using the alloc_text pragma).                            */
  75. /*                                                                           */
  76. /*****************************************************************************/
  77.  
  78. #pragma alloc_text( INITCODE, EndofCode )
  79.  
  80. VOID NEAR EndofCode(){}
  81.  
  82.  
  83. /*****************************************************************************/
  84. /*                                                                           */
  85. /*   Routine     : Initialize                                                */
  86. /*                                                                           */
  87. /*   Description : This routine is the highest level initialization routine. */
  88. /*                 This routine:                                             */
  89. /*                    - Saves the DevHelp address                            */
  90. /*                    - Opens the LAN message device driver                  */
  91. /*                    - Displays the install message                         */
  92. /*                    - Opens PROTMAN device driver                          */
  93. /*                    - Gets config data from PROTMAN                        */
  94. /*                    - Calls ProcessConfigData                              */
  95. /*                    - Fills in the initializaion request block             */
  96. /*                                                                           */
  97. /*****************************************************************************/
  98.  
  99. #pragma alloc_text( INITCODE, Initialize )
  100.  
  101. VOID FAR Initialize( PININITRP pInInitRP )
  102. {
  103.    POUTINITRP pOutInitRP = (POUTINITRP)pInInitRP;
  104.    BOOL Initialization = SUCCESS;
  105.    USHORT Action;
  106.    struct RqBlk ReqBlock;
  107.  
  108.    /* Save the DevHelp address */
  109.    pDevHelp = pInInitRP->pDevHelp;
  110.  
  111.    /* Open the LAN message device driver */
  112.    if ( DosOpen("\\DEV\\LANMSG$$",&LogHandle,&Action,0L,0,1,0x2042,0L) )
  113.       LogHandle = 0;
  114.  
  115.    /* Display the install message */
  116.    Display("\r\n");  /* Start with a blank line */
  117.    if ( DisplayMsg( 0, NULL ) == FAILURE )
  118.       Display("Installing ANDISMAC\r\n");
  119.  
  120.    /* Open PROTMAN */
  121.    if ( !DosOpen("\\DEV\\PROTMAN$",&PMHandle,&Action,0L,0,1,0x2042,0L) )
  122.       {
  123.          /* Get PROTOCOL.INI config data from PROTMAN */
  124.          ReqBlock.Opcode = GetPMInfo;
  125.          if ( !DosDevIOCtl(NULL,&ReqBlock,0x58,0x81,PMHandle) )
  126.             {
  127.                if ( ReqBlock.Status == SUCCESS )
  128.                   {
  129.                      /* Process the PROTOCOL.INI config data and register */
  130.                      /* modules to PROTMAN.                               */
  131.                      if ( ProcessConfigData(ReqBlock.Pointer1) != SUCCESS )
  132.                         Initialization = FAILURE;
  133.                   }
  134.                else  /* GetPMInfo failed */
  135.                   {
  136.                      /* Error getting config data */
  137.                      DisplayMsg( 4, NULL );
  138.                      Initialization = FAILURE;
  139.                   }
  140.             }
  141.          else  /* DosDevIOCtl for GetPMInfo failed */
  142.             {
  143.                /* Error getting config data */
  144.                DisplayMsg( 4, NULL );
  145.                Initialization = FAILURE;
  146.             }
  147.  
  148.          /* Close PROTMAN */
  149.          DosClose( PMHandle );
  150.       }
  151.    else  /* Could not open PROTMAN */
  152.       {
  153.          DisplayMsg( 3, NULL );
  154.          Initialization = FAILURE;
  155.       }
  156.  
  157.    if ( Initialization == SUCCESS )
  158.       {
  159.          /* ANDISMAC is installed */
  160.          DisplayMsg( 1, NULL );
  161.          pOutInitRP->CodeEnd = (USHORT)EndofCode;
  162.          pOutInitRP->DataEnd = (USHORT)&EndofData;
  163.       }
  164.    else  /* Initialization failed */
  165.       {
  166.          /* ANDISMAC failed to install */
  167.          DisplayMsg( 2, NULL );
  168.          pOutInitRP->Status  = STATUS_ERROR + STATUS_GENFAIL;
  169.          pOutInitRP->CodeEnd = 0;
  170.          pOutInitRP->DataEnd = 0;
  171.       }
  172.  
  173.    pOutInitRP->Unit = 0;
  174.    pOutInitRP->pBPB = NULL;
  175.  
  176.    Display("\r\n");  /* Finish with a blank line */
  177.  
  178.    /* Close the LAN message device driver if it was opened */
  179.    if ( LogHandle != 0 ) DosClose( LogHandle );
  180. }
  181.  
  182.  
  183. /*****************************************************************************/
  184. /*                                                                           */
  185. /*   Routine     : ProcessConfigData                                         */
  186. /*                                                                           */
  187. /*   Description : This routine scans through the PROTOCOL.INI config data   */
  188. /*                 that we got from PROTMAN.  This routine calls             */
  189. /*                 CreateModule for each section that is found which         */
  190. /*                 contains "DriverName = ANDISMC$".  Notice that            */
  191. /*                 "ANDISMC$" is the device name for this device driver      */
  192. /*                 (specified in the device driver header).                  */
  193. /*                                                                           */
  194. /*****************************************************************************/
  195.  
  196. #pragma alloc_text( INITCODE, ProcessConfigData )
  197.  
  198. BOOL NEAR ProcessConfigData( struct ModCfg *pConfigData )
  199. {
  200.    struct ModCfg *pModCfg;
  201.    struct KeywordEntry *pKE;
  202.  
  203.    /* For each section in PROTOCOL.INI that contains "DriverName = ANDISMC$" */
  204.    /*    create a new module                                                 */
  205.    for ( pModCfg=pConfigData; pModCfg!=NULL; pModCfg=pModCfg->NextModCfg )
  206.       for ( pKE=pModCfg->KE; pKE!=NULL; pKE=pKE->NextKeywordEntry )
  207.          if ( StringsEqual(pKE->KeyWord,"DRIVERNAME") )
  208.             if ( StringsEqual(pKE->Params[0].ParVal.ParStr,"ANDISMC$") )
  209.                CreateModule( pModCfg );
  210.  
  211.    /* If no modules were successfully created then fail initialization */
  212.    if ( pModuleList == NULL )
  213.       return FAILURE;
  214.    else
  215.       return SUCCESS;
  216. }
  217.  
  218.  
  219. /*****************************************************************************/
  220. /*                                                                           */
  221. /*   Routine     : CreateModule                                              */
  222. /*                                                                           */
  223. /*   Description : This routine will create a new Module.  A "Module" is     */
  224. /*                 a data segment where all the variables and tables for     */
  225. /*                 an instance of the MAC are kept.                          */
  226. /*                                                                           */
  227. /*                 This routine:                                             */
  228. /*                    - Allocates physical memory for the Module             */
  229. /*                    - Gets a GDT selector and maps it to the Module        */
  230. /*                    - Gets a virtual address for the Module                */
  231. /*                    - Initializes the variables in the Module              */
  232. /*                    - Calls ProcessKeywords to process remaining config    */
  233. /*                    - Calls InitNDISTables and InitANDISTables             */
  234. /*                    - Registers the Module to PROTMAN                      */
  235. /*                    - Adds the Module to the end of the module list        */
  236. /*                                                                           */
  237. /*                 Note: A GDT selector is needed so that the Module and     */
  238. /*                 its tables can be addressed at post-initializaton time.   */
  239. /*                 However, a virtual address is needed at initialization    */
  240. /*                 time to read and write to the Module.                     */
  241. /*                                                                           */
  242. /*****************************************************************************/
  243.  
  244. #pragma alloc_text( INITCODE, CreateModule )
  245.  
  246. VOID NEAR CreateModule( struct ModCfg *pModCfg )
  247. {
  248.    REGS     Regs;
  249.    PHYSADDR PhysAddr;
  250.    PMODULE  pModule;
  251.    USHORT   GDTSel;
  252.    PUSHORT  pGDTSel = &GDTSel;
  253.    struct RqBlk ReqBlock;
  254.    BOOL Result = SUCCESS;
  255.  
  256.    /* Display which port is being initialized */
  257.    DisplayMsg( 5, pModCfg->ModName );
  258.  
  259.    /* Get some physical memory for the new module */
  260.    Regs.Word.BX = sizeof(MODULE);
  261.    Regs.Word.AX = 0;
  262.    Regs.Byte.DH = 1;  /* Low Memory */
  263.    Regs.Byte.DL = DEVHELP_ALLOCPHYS;
  264.    Regs.Word.ES = 0L;
  265.    if ( !DevHelper(&Regs) )
  266.       {
  267.          /* Save the address of the physical memory */
  268.          PhysAddr.High = Regs.Word.AX;
  269.          PhysAddr.Low  = Regs.Word.BX;
  270.  
  271.          /* Get a GDT Selector */
  272.          Regs.Word.ES = SELECTOROF( pGDTSel );
  273.          Regs.Word.DI = OFFSETOF( pGDTSel );
  274.          Regs.Word.CX = 1;  /* Only one selector */
  275.          Regs.Byte.DL = DEVHELP_ALLOCGDTSELECTOR;
  276.          if ( !DevHelper(&Regs) )
  277.             {
  278.                /* Point the GDT selector to the physical memory */
  279.                Regs.Word.AX = PhysAddr.High;
  280.                Regs.Word.BX = PhysAddr.Low;
  281.                Regs.Word.CX = sizeof(MODULE);
  282.                Regs.Word.SI = GDTSel;
  283.                Regs.Byte.DL = DEVHELP_PHYSTOGDTSELECTOR;
  284.                Regs.Word.ES = 0L;
  285.                if ( !DevHelper(&Regs) )
  286.                   {
  287.                      /* Get a virtual address for the physical memory */
  288.                      pModule = VirtualAddr( &PhysAddr );
  289.                      if ( pModule != NULL )
  290.                         {
  291.                            /* Initialize the new module */
  292.                            pModule->pNextModule      = NULL;
  293.                            pModule->NextModPhys.High = 0;
  294.                            pModule->NextModPhys.Low  = 0;
  295.                            StringCopy( pModule->Name, pModCfg->ModName, NAME_LEN );
  296.                            pModule->ProtDS           = 0;
  297.                            pModule->pProtCCT         = NULL;
  298.  
  299.                            /* Process config data keywords for this module */
  300.                            if ( ProcessKeywords( pModCfg->KE, pModule ) == SUCCESS )
  301.                               {
  302.                                  /* Initialize tables */
  303.                                  InitNDISTables(  pModule, GDTSel );
  304.                                  InitANDISTables( pModule, GDTSel );
  305.  
  306.                                  /* Register to PROTMAN */
  307.                                  ReqBlock.Opcode   = RegisterModule;
  308.                                  ReqBlock.Pointer1 = pModule->UDT.MudCCp;
  309.                                  ReqBlock.Pointer2 = NULL;
  310.                                  if ( !DosDevIOCtl(NULL,&ReqBlock,0x58,0x81,PMHandle) )
  311.                                     {
  312.                                        if ( ReqBlock.Status == SUCCESS )
  313.                                           {
  314.                                              /* Add the module to the end of the module list */
  315.                                              if ( AddModule( GDTSel, &PhysAddr ) == FAILURE )
  316.                                                 {
  317.                                                    /* Internal Error */
  318.                                                    DisplayMsg( 7, NULL );
  319.                                                    Result = FAILURE;
  320.                                                 }
  321.                                           }
  322.                                        else  /* Could not register to PROTMAN */
  323.                                           {
  324.                                              DisplayMsg( 6, NULL );
  325.                                              Result = FAILURE;
  326.                                           }
  327.                                     }
  328.                                  else  /* DosDevIOCtl failed */
  329.                                     {
  330.                                        DisplayMsg( 6, NULL );
  331.                                        Result = FAILURE;
  332.                                     }
  333.                               }
  334.                            else  /* Error processing the rest of config data */
  335.                               {
  336.                                  Result = FAILURE;
  337.                               }
  338.                         }
  339.                      else  /* Could not get a virtual address */
  340.                         {
  341.                            Result = FAILURE;
  342.                         }
  343.                   }
  344.                else  /* Could not map the GDT to the physical memory */
  345.                   {
  346.                      /* Internal Error */
  347.                      DisplayMsg( 7, NULL );
  348.                      Result = FAILURE;
  349.                   }
  350.  
  351.                if ( Result == FAILURE )
  352.                   {
  353.                      /* Free the GDT selector */
  354.                      Regs.Word.AX = GDTSel;
  355.                      Regs.Byte.DL = DEVHELP_FREEGDTSELECTOR;
  356.                      Regs.Word.ES = 0L;
  357.                      DevHelper( &Regs );
  358.                   }
  359.             }
  360.          else  /* Could not get a GDT selector */
  361.             {
  362.                /* Internal Error */
  363.                DisplayMsg( 7, NULL );
  364.                Result = FAILURE;
  365.             }
  366.  
  367.          if ( Result == FAILURE )
  368.             {
  369.                /* Free the physical memory */
  370.                Regs.Word.AX = PhysAddr.High;
  371.                Regs.Word.BX = PhysAddr.Low;
  372.                Regs.Byte.DL = DEVHELP_FREEPHYS;
  373.                Regs.Word.ES = 0L;
  374.                DevHelper( &Regs );
  375.             }
  376.       }
  377.    else  /* Could not get physical memory */
  378.       {
  379.          /* Internal Error */
  380.          DisplayMsg( 7, NULL );
  381.       }
  382. }
  383.  
  384.  
  385. /*****************************************************************************/
  386. /*                                                                           */
  387. /*   Routine     : ProcessKeywords                                           */
  388. /*                                                                           */
  389. /*   Description : This is a place holder routine.  This routine will        */
  390. /*                 process the config data for a section in PROTOCOL.INI     */
  391. /*                 and initialize varibles in the newly created Module.      */
  392. /*                 If there is an error processing the config data then      */
  393. /*                 then routine returns FAILURE else it returns SUCCESS.     */
  394. /*                                                                           */
  395. /*****************************************************************************/
  396.  
  397. #pragma alloc_text( INITCODE, ProcessKeywords )
  398.  
  399. BOOL NEAR ProcessKeywords( struct KeywordEntry *pKEList, PMODULE pModule )
  400. {
  401.    struct KeywordEntry *pKE;
  402.  
  403.    for ( pKE=pKEList; pKE!=NULL; pKE=pKE->NextKeywordEntry )
  404.       {
  405.          /* Process keywords in this section of the PROTOCOL.INI file */
  406.          /* and set variables in the new module data structure.       */
  407.       }
  408.  
  409.    return SUCCESS;
  410. }
  411.  
  412.  
  413. /*****************************************************************************/
  414. /*                                                                           */
  415. /*   Routine     : AddModule                                                 */
  416. /*                                                                           */
  417. /*   Description : This routine adds the newly created Module to the end     */
  418. /*                 of the linked list of Modules.                            */
  419. /*                                                                           */
  420. /*                 Strictly speaking, a linked list of Modules is not        */
  421. /*                 needed because the GDT selector for a module is passed    */
  422. /*                 to the MAC (in MACDS) on each NDIS and ANDIS call to      */
  423. /*                 the MAC.  I just like to have all my allocated data       */
  424. /*                 segments tethered together so I can get to them if I      */
  425. /*                 need to.                                                  */
  426. /*                                                                           */
  427. /*****************************************************************************/
  428.  
  429. #pragma alloc_text( INITCODE, AddModule )
  430.  
  431. BOOL NEAR AddModule( USHORT GDTSel, PPHYSADDR pPhysAddr )
  432. {
  433.    PMODULE pModule;
  434.  
  435.    if ( pModuleList == NULL )   /* If the module list is empty */
  436.       {
  437.          /* Add the new module to the head of the list */
  438.          pModuleList = MAKEP( GDTSel, 0 );
  439.          FirstModPhys.High = pPhysAddr->High;
  440.          FirstModPhys.Low  = pPhysAddr->Low;
  441.       }
  442.    else  /* The module list is not empty */
  443.       {
  444.          /* Get a virtual address for the first module */
  445.          pModule = VirtualAddr( &FirstModPhys );
  446.          if ( pModule == NULL ) return FAILURE;
  447.  
  448.          /* Find the last module in the list */
  449.          while ( pModule->pNextModule != NULL )
  450.             {
  451.                /* Get a virtual address for the next module */
  452.                pModule = VirtualAddr( &(pModule->NextModPhys) );
  453.                if ( pModule == NULL ) return FAILURE;
  454.             }
  455.  
  456.          /* Add the new module to the end of the list */
  457.          pModule->pNextModule = MAKEP( GDTSel, 0 );
  458.          pModule->NextModPhys.High = pPhysAddr->High;
  459.          pModule->NextModPhys.Low  = pPhysAddr->Low;
  460.       }
  461.  
  462.    return SUCCESS;
  463. }
  464.  
  465.  
  466. /*****************************************************************************/
  467. /*                                                                           */
  468. /*   Routine     : VirtualAddr                                               */
  469. /*                                                                           */
  470. /*   Description : This routine calls DevHelp to create a virtual address    */
  471. /*                 for the specified physical memory.                        */
  472. /*                                                                           */
  473. /*****************************************************************************/
  474.  
  475. #pragma alloc_text( INITCODE, VirtualAddr )
  476.  
  477. PMODULE NEAR VirtualAddr( PPHYSADDR pPhysAddr )
  478. {
  479.    REGS Regs;
  480.  
  481.    /* Get a virtual address for the physical memory */
  482.    Regs.Word.AX = pPhysAddr->High;
  483.    Regs.Word.BX = pPhysAddr->Low;
  484.    Regs.Word.CX = sizeof(MODULE);
  485.    Regs.Byte.DH = 1;  /* Put virtual address in ES:DI */
  486.    Regs.Byte.DL = DEVHELP_PHYSTOVIRT;
  487.    Regs.Word.ES = 0L;
  488.    if ( DevHelper(&Regs) )
  489.       {
  490.          /* Internal Error */
  491.          DisplayMsg( 7, NULL );
  492.          return NULL;
  493.       }
  494.  
  495.    return MAKEP( Regs.Word.ES, Regs.Word.DI );
  496. }
  497.  
  498.  
  499. /*****************************************************************************/
  500. /*                                                                           */
  501. /*   Routine     : InitNDISTables                                            */
  502. /*                                                                           */
  503. /*   Description : This routine initializes the tables used by the NDIS      */
  504. /*                 interface.  The ANDIS extentions are enabled by setting   */
  505. /*                 bit 17 of the Service Flags field in the Service          */
  506. /*                 Specific Characteristics table and the first reserved     */
  507. /*                 pointer of the Common Characteristics table is set to     */
  508. /*                 point to the ANDIS PPAT table.                            */
  509. /*                                                                           */
  510. /*                 Note: This is a very quick and simple initialization.     */
  511. /*                 A MAC developer should carefully consider the correct     */
  512. /*                 values for each parameter.                                */
  513. /*                                                                           */
  514. /*****************************************************************************/
  515.  
  516. #pragma alloc_text( INITCODE, InitNDISTables )
  517.  
  518. VOID NEAR InitNDISTables( PMODULE pModule, USHORT GDTSel )
  519. {
  520.    struct CommChar    *pCCT  = &(pModule->CCT);
  521.    struct MACSpecChar *pSSCT = &(pModule->SSCT);
  522.    struct MACSpecStat *pSSST = &(pModule->SSST);
  523.    struct MACUprDisp  *pUDT  = &(pModule->UDT);
  524.    PXVPPAT             pPPAT = &(pModule->PPAT);
  525.  
  526.    /* Initialize the Common Characteristics Table */
  527.    pModule->CCT.CcSize     = sizeof(struct CommChar);
  528.    pModule->CCT.CcLvlMjr   = MAJOR_NDIS_VERSION;
  529.    pModule->CCT.CcLvlMnr   = MINOR_NDIS_VERSION;
  530.    pModule->CCT.CcSpLvl    = 0;
  531.    pModule->CCT.CcMjrVer   = 1;
  532.    pModule->CCT.CcMnrVer   = 0;
  533.    pModule->CCT.CcBindFnc  = 1L;
  534.    StringCopy( pModule->CCT.CcName, pModule->Name, NAME_LEN );
  535.    pModule->CCT.CcUPLevel  = MACLvl;
  536.    pModule->CCT.CcUIType   = MACTyp;
  537.    pModule->CCT.CcLPLevel  = 0;
  538.    pModule->CCT.CcLIType   = 0;
  539.    pModule->CCT.CcModuleID = 0;
  540.    pModule->CCT.CcDataSeg  = GDTSel;
  541.    pModule->CCT.CcSysReq   = (PUCHAR)SystemRequest;
  542.    pModule->CCT.CcSCp      = MAKEP(GDTSel,OFFSETOF(pSSCT)-OFFSETOF(pModule));
  543.    pModule->CCT.CcSSp      = MAKEP(GDTSel,OFFSETOF(pSSST)-OFFSETOF(pModule));
  544.    pModule->CCT.CcUDp      = MAKEP(GDTSel,OFFSETOF(pUDT) -OFFSETOF(pModule));
  545.    pModule->CCT.CcLDp      = NULL;
  546.    /* Put the address of the PPAT in the first reserved pointer */
  547.    pModule->CCT.CcRsv1     = (ULONG)MAKEP(GDTSel,OFFSETOF(pPPAT)-OFFSETOF(pModule));
  548.    pModule->CCT.CcRsv2     = 0L;
  549.  
  550.    /* Initialize the Service Specific Characteristics Table */
  551.    pModule->SSCT.MscSize = sizeof(struct MACSpecChar);
  552.    StringCopy( pModule->SSCT.MscType, "HDLC", NAME_LEN );
  553.    pModule->SSCT.MscStnAdrSz       = ADDR_SIZE;
  554.    pModule->SSCT.MscPermStnAdr[0]  = 0;
  555.    pModule->SSCT.MscCurrStnAdr[0]  = 0;
  556.    pModule->SSCT.MscCurrFncAdr     = 0L;
  557.    pModule->SSCT.MscMCp            = NULL;
  558.    pModule->SSCT.MscLinkSpd        = 9600L;
  559.    /* Set bit 17 (SV_ANDIS) to indicate that this is an ANDIS MAC */
  560.    pModule->SSCT.MscService        = SV_ANDIS;
  561.    pModule->SSCT.MscMaxFrame       = 0;
  562.    pModule->SSCT.MscTBufCap        = 0;
  563.    pModule->SSCT.MscTBlkSz         = 0;
  564.    pModule->SSCT.MscRBufCap        = 0;
  565.    pModule->SSCT.MscRBlkSz         = 0;
  566.    pModule->SSCT.MscVenCode[0]     = 0xFF;
  567.    pModule->SSCT.MscVenCode[1]     = 0xFF;
  568.    pModule->SSCT.MscVenCode[2]     = 0xFF;
  569.    pModule->SSCT.MscVenAdapter     = 0;
  570.    pModule->SSCT.MscVenAdaptDesc   = NULL;
  571.    pModule->SSCT.MscInterrupt      = 3;
  572.    pModule->SSCT.MscTxQDepth       = 1;
  573.    pModule->SSCT.MscMaxNumDataBlks = 1;
  574.  
  575.    /* Initialize the Service Specific Status Table */
  576.    pModule->SSST.MssSize    = sizeof(struct MACSpecStat);
  577.    pModule->SSST.MssDiagDT  = 0xFFFFFFFFL;
  578.    pModule->SSST.MssStatus  = 0L;
  579.    pModule->SSST.MssFilter  = 0;
  580.    pModule->SSST.MssM8Sp    = NULL;
  581.    pModule->SSST.MssClearDT = 0xFFFFFFFFL;
  582.    pModule->SSST.MssFR      = 0xFFFFFFFFL;
  583.    pModule->SSST.MssRFCRC   = 0xFFFFFFFFL;
  584.    pModule->SSST.MssFRByt   = 0xFFFFFFFFL;
  585.    pModule->SSST.MssRFLack  = 0xFFFFFFFFL;
  586.    pModule->SSST.MssFRMC    = 0xFFFFFFFFL;
  587.    pModule->SSST.MssFRBC    = 0xFFFFFFFFL;
  588.    pModule->SSST.MssRFErr   = 0xFFFFFFFFL;
  589.    pModule->SSST.MssRFMax   = 0xFFFFFFFFL;
  590.    pModule->SSST.MssRFMin   = 0xFFFFFFFFL;
  591.    pModule->SSST.MssFRMCByt = 0xFFFFFFFFL;
  592.    pModule->SSST.MssFRBCByt = 0xFFFFFFFFL;
  593.    pModule->SSST.MssRFHW    = 0xFFFFFFFFL;
  594.    pModule->SSST.MssFS      = 0xFFFFFFFFL;
  595.    pModule->SSST.MssFSByt   = 0xFFFFFFFFL;
  596.    pModule->SSST.MssFSMC    = 0xFFFFFFFFL;
  597.    pModule->SSST.MssFSBC    = 0xFFFFFFFFL;
  598.    pModule->SSST.MssFSBCByt = 0xFFFFFFFFL;
  599.    pModule->SSST.MssFSMCByt = 0xFFFFFFFFL;
  600.    pModule->SSST.MssSFTime  = 0xFFFFFFFFL;
  601.    pModule->SSST.MssSFHW    = 0xFFFFFFFFL;
  602.  
  603.    /* Initialize the MAC Upper Dispatch Table */
  604.    pModule->UDT.MudCCp        = MAKEP(GDTSel,OFFSETOF(pCCT)-OFFSETOF(pModule));
  605.    pModule->UDT.MudGReq       = (PUCHAR)GeneralRequest;
  606.    pModule->UDT.MudXmitChain  = (PUCHAR)TransmitChain;
  607.    pModule->UDT.MudXferData   = (PUCHAR)TransferData;
  608.    pModule->UDT.MudRcvRelease = (PUCHAR)ReceiveRelease;
  609.    pModule->UDT.MudIndOn      = (PUCHAR)IndicationsOn;
  610.    pModule->UDT.MudIndOff     = (PUCHAR)IndicationsOff;
  611.  
  612.    /* Initialize the Protocol Lower Dispatch Table */
  613.    pModule->ProtLDT.PldCCp         = NULL;
  614.    pModule->ProtLDT.PldIFF         = 0L;
  615.    pModule->ProtLDT.PldReqConfirm  = NULL;
  616.    pModule->ProtLDT.PldXmitConfirm = NULL;
  617.    pModule->ProtLDT.PldRcvLkAhead  = NULL;
  618.    pModule->ProtLDT.PldIndComplete = NULL;
  619.    pModule->ProtLDT.PldRcvChain    = NULL;
  620.    pModule->ProtLDT.PldStatInd     = NULL;
  621. }
  622.  
  623.  
  624. /*****************************************************************************/
  625. /*                                                                           */
  626. /*   Routine     : InitANDISTables                                           */
  627. /*                                                                           */
  628. /*   Description : This routine initalizes the tables used by the ANDIS      */
  629. /*                 interface.  This is mainly the PPAT table.                */
  630. /*                                                                           */
  631. /*                 Note: This is a very quick and simple initialization.     */
  632. /*                 A MAC developer should carefully consider the correct     */
  633. /*                 values for each parameter.                                */
  634. /*                                                                           */
  635. /*****************************************************************************/
  636.  
  637. #pragma alloc_text( INITCODE, InitANDISTables )
  638.  
  639. VOID NEAR InitANDISTables( PMODULE pModule, USHORT GDTSel )
  640. {
  641.    /* Initialize the PPAT header */
  642.    pModule->PPAT.Header.PPAT_Length            = sizeof(XVPPAT);
  643.    pModule->PPAT.Header.PPAT_Ver_Major         = 1;
  644.    pModule->PPAT.Header.PPAT_Ver_Minor         = 0;
  645.    pModule->PPAT.Header.Port_Interface_Type    = 1;
  646.    pModule->PPAT.Header.Port_Interface_Version = 1;
  647.    pModule->PPAT.Header.Conn_Type              = 2;
  648.    pModule->PPAT.Header.Phys_Conn_State        = 0;
  649.    pModule->PPAT.Header.ANDIS_MAC_Mode         = 0;
  650.    pModule->PPAT.Header.ANDIS_MAC_DS           = GDTSel;
  651.    pModule->PPAT.Header.MAC_CCT_ptr            = pModule->UDT.MudCCp;
  652.    StringCopy( pModule->PPAT.Header.Port_Name, pModule->Name, NAME_LEN );
  653.    StringCopy( pModule->PPAT.Header.Phys_Interface, "RS232D", NAME_LEN );
  654.    pModule->PPAT.Header.MAC_PPAT_Mgmt          = PPATManagement;
  655.    pModule->PPAT.Header.PPAT_Mgmt              = NULL;/* Filled in by PROTMAN */
  656.    pModule->PPAT.Header.Port_Mgmt              = PortManagement;
  657.    pModule->PPAT.Header.Xmit_Imm               = TransmitImmData;
  658.    pModule->PPAT.Header.Rcv_Imm_Cnf            = ReceiveImmDataConfirm;
  659.    pModule->PPAT.Header.Port_Log_ptr           = NULL;
  660.    pModule->PPAT.Header.Max_Speed              = 0L;
  661.    pModule->PPAT.Header.Max_Xmit_Buff          = 0L;
  662.    pModule->PPAT.Header.Port_ID                = 0;
  663.    pModule->PPAT.Header.Slot_Number            = 0;
  664.    pModule->PPAT.Header.Port_Number            = 0;
  665.    pModule->PPAT.Header.Channel_Number         = 0;
  666.    pModule->PPAT.Header.ANDIS_Align            = 0;
  667.    pModule->PPAT.Header.ANDIS_Reserve[0]       = 0;
  668.    pModule->PPAT.Header.ANDIS_Reserve[1]       = 0;
  669.    pModule->PPAT.Header.ANDIS_Reserve[2]       = 0;
  670.    pModule->PPAT.Header.ANDIS_Reserve[3]       = 0;
  671.    pModule->PPAT.Header.ANDIS_Reserve[4]       = 0;
  672.    pModule->PPAT.Header.ANDIS_Reserve[5]       = 0;
  673.  
  674.    /* Initialize the rest of the PPAT */
  675.    pModule->PPAT.PPI_Status      = 0;
  676.    pModule->PPAT.Port_Attribs    = 1L;
  677.    pModule->PPAT.Clock_Type      = 1;
  678.    pModule->PPAT.XVRESERVE_1     = 0;
  679.    pModule->PPAT.Xmit_Speed      = 9600L;
  680.    pModule->PPAT.Rcv_Speed       = 9600L;
  681.    pModule->PPAT.Comm_Type       = 2;
  682.    pModule->PPAT.Port_Mode       = 1;
  683.    pModule->PPAT.Transparency    = 2;
  684.    pModule->PPAT.Hard_Hand       = 0x0C;
  685.    pModule->PPAT.XOFF_Char       = 0x13;
  686.    pModule->PPAT.XON_Char        = 0x11;
  687.    pModule->PPAT.Port_Trans_Mode = 8;
  688.    pModule->PPAT.Signal_Mask     = 0;
  689.    pModule->PPAT.Hw_Err_Mask     = 0;
  690.  
  691.    /* Initialize PCM Entry Table */
  692.    pModule->PCMEntryTbl.PortMgmtInd    = NULL;
  693.    pModule->PCMEntryTbl.RecvImmData    = NULL;
  694.    pModule->PCMEntryTbl.XmitImmDataCnf = NULL;
  695.    pModule->PCMEntryTbl.pcm_ds         = 0;
  696. }
  697.  
  698.  
  699. /*****************************************************************************/
  700. /*                                                                           */
  701. /*   Routine     : DisplayMsg                                                */
  702. /*                                                                           */
  703. /*   Description : This routine displays a message, with an optional         */
  704. /*                 insertion string, on the screen.  The message is also     */
  705. /*                 put in the LAN message log file.                          */
  706. /*                                                                           */
  707. /*                 If there is an error then FAILURE is returned.  This      */
  708. /*                 allows the Initialze routine to put the name of this      */
  709. /*                 MAC on the screen even if the message file is not found.  */
  710. /*                                                                           */
  711. /*****************************************************************************/
  712.  
  713. #pragma alloc_text( INITCODE, DisplayMsg )
  714.  
  715. BOOL NEAR DisplayMsg( USHORT MsgNumber, PCHAR pIvString )
  716. {
  717.    CHAR   MsgBuffer[256];
  718.    USHORT MsgLength,IvCount;
  719.    BOOL   Result = SUCCESS;
  720.  
  721.    /* If there is an insertion string then set IvCount to 1 */
  722.    if ( pIvString == NULL )
  723.       IvCount = 0;
  724.    else
  725.       IvCount = 1;
  726.  
  727.    /* Get the message from the message file */
  728.    if ( DosGetMessage( &pIvString, IvCount, MsgBuffer, 256, MsgNumber,
  729.          "ADS.MSG", &MsgLength ) )
  730.       {
  731.          Result = FAILURE;
  732.       }
  733.  
  734.    /* Display the message on the screen */
  735.    if ( DosPutMessage( 0, MsgLength, MsgBuffer ) )
  736.       {
  737.          Result = FAILURE;
  738.       }
  739.  
  740.    /* Put the message in the LANTRAN.LOG file */
  741.    LogMsg( MsgNumber, IvCount, pIvString );
  742.  
  743.    return Result;
  744. }
  745.  
  746.  
  747. /*****************************************************************************/
  748. /*                                                                           */
  749. /*   Routine     : LogMsg                                                    */
  750. /*                                                                           */
  751. /*   Description : This routine sends a message to the LAN message file      */
  752. /*                 (LANTRAN.LOG).  If the LAN message device driver was      */
  753. /*                 not successfully opened then this routine does nothing.   */
  754. /*                                                                           */
  755. /*****************************************************************************/
  756.  
  757. #pragma alloc_text( INITCODE, LogMsg )
  758.  
  759. VOID NEAR LogMsg( USHORT MsgNumber, USHORT IvCount, PCHAR pIvString )
  760. {
  761.    LANMSG LANMsg;
  762.    CHAR   MsgOut[8];
  763.  
  764.    if ( LogHandle != 0 )
  765.       {
  766.          LANMsg.pCompID   = "ANDISMC$";
  767.          LANMsg.pIvArray  = &pIvString;
  768.          LANMsg.IvCount   = IvCount;
  769.          LANMsg.MsgNumber = MsgNumber;
  770.          LANMsg.pMsgFile  = "ADS.MSG";
  771.          LANMsg.MsgType   = 0x4900;
  772.          LANMsg.Display   = FALSE;
  773.          LANMsg.pLogPath  = NULL;
  774.  
  775.          DosDevIOCtl( &MsgOut, &LANMsg, 1, 0x90, LogHandle );
  776.       }
  777. }
  778.  
  779.  
  780. /*****************************************************************************/
  781. /*                                                                           */
  782. /*   Routine     : Display                                                   */
  783. /*                                                                           */
  784. /*   Description : This routine displays a string on the screen.             */
  785. /*                                                                           */
  786. /*****************************************************************************/
  787.  
  788. #pragma alloc_text( INITCODE, Display )
  789.  
  790. VOID NEAR Display( PCHAR pString )
  791. {
  792.    PCHAR  pEnd = pString;
  793.    USHORT BytesWritten;
  794.  
  795.    /* Move pEnd to the terminating null byte */
  796.    while ( *pEnd != 0 ) pEnd++;
  797.  
  798.    /* Write the string to the screen */
  799.    DosWrite( 0, pString, pEnd-pString, &BytesWritten );
  800. }
  801.  
  802.  
  803. /*****************************************************************************/
  804. /*                                                                           */
  805. /*   Routine     : StringsEqual                                              */
  806. /*                                                                           */
  807. /*   Description : This routine returns TRUE is two strings are exactly      */
  808. /*                 equal, else it returns FALSE.  The compare is case        */
  809. /*                 sensitive and the strings must be the same length.        */
  810. /*                                                                           */
  811. /*****************************************************************************/
  812.  
  813. #pragma alloc_text( INITCODE, StringsEqual )
  814.  
  815. BOOL NEAR StringsEqual( PUCHAR pFirst, PUCHAR pSecond )
  816. {
  817.    for ( ; *pFirst == *pSecond; pFirst++, pSecond++ )
  818.       if ( *pFirst == 0 ) return TRUE;
  819.  
  820.    return FALSE;
  821. }
  822.  
  823.  
  824. /*****************************************************************************/
  825. /*                                                                           */
  826. /*   Routine     : StringCopy                                                */
  827. /*                                                                           */
  828. /*   Description : This routine copies a string.                             */
  829. /*                                                                           */
  830. /*****************************************************************************/
  831.  
  832. #pragma alloc_text( INITCODE, StringCopy )
  833.  
  834. BOOL NEAR StringCopy( UCHAR Dest[], UCHAR Source[], USHORT DestSize )
  835. {
  836.    register USHORT x;
  837.  
  838.    for ( x=0; x<DestSize; x++ )
  839.       if ( (Dest[x] = Source[x]) == 0 ) return FALSE;  /* Good return */
  840.  
  841.    return TRUE;   /* Error: Overflowed the destination buffer */
  842. }
  843.  
  844.  
  845.