Home | History | Annotate | Download | only in msdos
      1 /*
      2  * Copyright (c) 1993,1994
      3  *      Texas A&M University.  All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  * 3. All advertising materials mentioning features or use of this software
     14  *    must display the following acknowledgement:
     15  *      This product includes software developed by Texas A&M University
     16  *      and its contributors.
     17  * 4. Neither the name of the University nor the names of its contributors
     18  *    may be used to endorse or promote products derived from this software
     19  *    without specific prior written permission.
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
     22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
     25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     31  * SUCH DAMAGE.
     32  *
     33  * Developers:
     34  *             David K. Hess, Douglas Lee Schales, David R. Safford
     35  *
     36  * Heavily modified for Metaware HighC + GNU C 2.8+
     37  *             Gisle Vanem 1998
     38  */
     39 
     40 #include <stdio.h>
     41 #include <stdlib.h>
     42 #include <dos.h>
     43 #include <io.h>
     44 #include <fcntl.h>
     45 #include <malloc.h>
     46 #include <string.h>
     47 
     48 #include "pcap-dos.h"
     49 #include "pcap-int.h"
     50 #include "msdos/ndis2.h"
     51 
     52 #if defined(USE_NDIS2)
     53 
     54 /*
     55  *  Packet buffer handling
     56  */
     57 extern int     FreePktBuf  (PktBuf *buf);
     58 extern int     EnquePktBuf (PktBuf *buf);
     59 extern PktBuf* AllocPktBuf (void);
     60 
     61 /*
     62  *  Various defines
     63  */
     64 #define MAX_NUM_DEBUG_STRINGS 90
     65 #define DEBUG_STRING_LENGTH   80
     66 #define STACK_POOL_SIZE       6
     67 #define STACK_SIZE            256
     68 
     69 #define MEDIA_FDDI            1
     70 #define MEDIA_ETHERNET        2
     71 #define MEDIA_TOKEN           3
     72 
     73 static int     startDebug     = 0;
     74 static int     stopDebug      = 0;
     75 
     76 static DWORD   droppedPackets = 0L;
     77 static WORD    frameSize      = 0;
     78 static WORD    headerSize     = 0;
     79 static int     mediaType      = 0;
     80 static char   *lastErr        = NULL;
     81 
     82 static BYTE    debugStrings [MAX_NUM_DEBUG_STRINGS][DEBUG_STRING_LENGTH];
     83 static BYTE   *freeStacks   [STACK_POOL_SIZE];
     84 static int     freeStackPtr = STACK_POOL_SIZE - 1;
     85 
     86 static ProtMan protManEntry = NULL;
     87 static WORD    protManDS    = 0;
     88 static volatile int xmitPending;
     89 
     90 static struct _PktBuf        *txBufPending;
     91 static struct _CardHandle    *handle;
     92 static struct _CommonChars    common;
     93 static struct _ProtocolChars  protChars;
     94 static struct _ProtDispatch   lowerTable;
     95 
     96 static struct _FailingModules failingModules;
     97 static struct _BindingsList   bindings;
     98 
     99 static struct {
    100          WORD  err_num;
    101          char *err_text;
    102        } ndis_errlist[] = {
    103 
    104   { ERR_SUCCESS,
    105     "The function completed successfully.\n"  },
    106 
    107   { ERR_WAIT_FOR_RELEASE,
    108     "The ReceiveChain completed successfully but the protocol has\n"
    109     "retained control of the buffer.\n"  },
    110 
    111   { ERR_REQUEST_QUEUED,
    112     "The current request has been queued.\n"  },
    113 
    114   { ERR_FRAME_NOT_RECOGNIZED,
    115     "Frame not recognized.\n"  },
    116 
    117   { ERR_FRAME_REJECTED,
    118     "Frame was discarded.\n"  },
    119 
    120   { ERR_FORWARD_FRAME,
    121     "Protocol wishes to forward frame to another protocol.\n"  },
    122 
    123   { ERR_OUT_OF_RESOURCE,
    124     "Out of resource.\n"  },
    125 
    126   { ERR_INVALID_PARAMETER,
    127     "Invalid parameter.\n"  },
    128 
    129   { ERR_INVALID_FUNCTION,
    130     "Invalid function.\n"  },
    131 
    132   { ERR_NOT_SUPPORTED,
    133     "Not supported.\n"  },
    134 
    135   { ERR_HARDWARE_ERROR,
    136     "Hardware error.\n"  },
    137 
    138   { ERR_TRANSMIT_ERROR,
    139     "The packet was not transmitted due to an error.\n"  },
    140 
    141   { ERR_NO_SUCH_DESTINATION,
    142     "Token ring packet was not recognized when transmitted.\n"  },
    143 
    144   { ERR_BUFFER_TOO_SMALL,
    145     "Provided buffer was too small.\n"  },
    146 
    147   { ERR_ALREADY_STARTED,
    148     "Network drivers already started.\n"  },
    149 
    150   { ERR_INCOMPLETE_BINDING,
    151     "Protocol driver could not complete its bindings.\n"  },
    152 
    153   { ERR_DRIVER_NOT_INITIALIZED,
    154     "MAC did not initialize properly.\n"  },
    155 
    156   { ERR_HARDWARE_NOT_FOUND,
    157     "Hardware not found.\n"  },
    158 
    159   { ERR_HARDWARE_FAILURE,
    160     "Hardware failure.\n"  },
    161 
    162   { ERR_CONFIGURATION_FAILURE,
    163     "Configuration failure.\n"  },
    164 
    165   { ERR_INTERRUPT_CONFLICT,
    166     "Interrupt conflict.\n"  },
    167 
    168   { ERR_INCOMPATIBLE_MAC,
    169     "The MAC is not compatible with the protocol.\n"  },
    170 
    171   { ERR_INITIALIZATION_FAILED,
    172     "Initialization failed.\n"  },
    173 
    174   { ERR_NO_BINDING,
    175     "Binding did not occur.\n"  },
    176 
    177   { ERR_NETWORK_MAY_NOT_BE_CONNECTED,
    178     "The network may not be connected to the adapter.\n"  },
    179 
    180   { ERR_INCOMPATIBLE_OS_VERSION,
    181     "The version of the operating system is incompatible with the protocol.\n"  },
    182 
    183   { ERR_ALREADY_REGISTERED,
    184     "The protocol is already registered.\n"  },
    185 
    186   { ERR_PATH_NOT_FOUND,
    187     "PROTMAN.EXE could not be found.\n"  },
    188 
    189   { ERR_INSUFFICIENT_MEMORY,
    190     "Insufficient memory.\n"  },
    191 
    192   { ERR_INFO_NOT_FOUND,
    193     "Protocol Mananger info structure is lost or corrupted.\n"  },
    194 
    195   { ERR_GENERAL_FAILURE,
    196     "General failure.\n"  }
    197 };
    198 
    199 /*
    200  *  Some handy macros
    201  */
    202 #define PERROR(str)    printf("%s (%d): %s\n", __FILE__,__LINE__,str)
    203 #define DEBUG_RING()   (debugStrings[stopDebug+1 == MAX_NUM_DEBUG_STRINGS ? \
    204                         stopDebug = 0 : ++stopDebug])
    205 
    206 /*
    207  * needs rewrite for DOSX
    208  */
    209 #define MAC_DISPATCH(hnd)  ((struct _MacUpperDispatch*)(hnd)->common->upperDispatchTable)
    210 #define MAC_STATUS(hnd)    ((struct _MacStatusTable*)  (hnd)->common->serviceStatus)
    211 #define MAC_CHAR(hnd)      ((struct _MacChars*)        (hnd)->common->serviceChars)
    212 
    213 #ifdef NDIS_DEBUG
    214   #define DEBUG0(str)      printf (str)
    215   #define DEBUG1(fmt,a)    printf (fmt,a)
    216   #define DEBUG2(fmt,a,b)  printf (fmt,a,b)
    217   #define TRACE0(str)      sprintf (DEBUG_RING(),str)
    218   #define TRACE1(fmt,a)    sprintf (DEBUG_RING(),fmt,a)
    219 #else
    220   #define DEBUG0(str)      ((void)0)
    221   #define DEBUG1(fmt,a)    ((void)0)
    222   #define DEBUG2(fmt,a,b)  ((void)0)
    223   #define TRACE0(str)      ((void)0)
    224   #define TRACE1(fmt,a)    ((void)0)
    225 #endif
    226 
    227 /*
    228  * This routine is called from both threads
    229  */
    230 void NdisFreeStack (BYTE *aStack)
    231 {
    232   GUARD();
    233 
    234   if (freeStackPtr == STACK_POOL_SIZE - 1)
    235      PERROR ("tried to free too many stacks");
    236 
    237   freeStacks[++freeStackPtr] = aStack;
    238 
    239   if (freeStackPtr == 0)
    240      TRACE0 ("freeStackPtr went positive\n");
    241 
    242   UNGUARD();
    243 }
    244 
    245 /*
    246  * This routine is called from callbacks to allocate local data
    247  */
    248 BYTE *NdisAllocStack (void)
    249 {
    250   BYTE *stack;
    251 
    252   GUARD();
    253 
    254   if (freeStackPtr < 0)
    255   {
    256     /* Ran out of stack buffers. Return NULL which will start
    257      * dropping packets
    258      */
    259     TRACE0 ("freeStackPtr went negative\n");
    260     stack = 0;
    261   }
    262   else
    263     stack = freeStacks[freeStackPtr--];
    264 
    265   UNGUARD();
    266   return (stack);
    267 }
    268 
    269 CALLBACK (NdisSystemRequest (DWORD param1, DWORD param2, WORD param3,
    270                              WORD opcode, WORD targetDS))
    271 {
    272   static int            bindEntry = 0;
    273   struct _CommonChars  *macCommon;
    274   volatile WORD result;
    275 
    276   switch (opcode)
    277   {
    278     case REQ_INITIATE_BIND:
    279          macCommon = (struct _CommonChars*) param2;
    280          if (macCommon == NULL)
    281 	 {
    282            printf ("There is an NDIS misconfiguration.\n");
    283            result = ERR_GENERAL_FAILURE;
    284 	   break;
    285 	 }
    286          DEBUG2 ("module name %s\n"
    287                  "module type %s\n",
    288                  macCommon->moduleName,
    289                  ((MacChars*) macCommon->serviceChars)->macName);
    290 
    291          /* Binding to the MAC */
    292          result = macCommon->systemRequest ((DWORD)&common, (DWORD)&macCommon,
    293                                             0, REQ_BIND,
    294                                             macCommon->moduleDS);
    295 
    296          if (!strcmp(bindings.moduleName[bindEntry], handle->moduleName))
    297               handle->common = macCommon;
    298          else PERROR ("unknown module");
    299          ++bindEntry;
    300 	 break;
    301 
    302     case REQ_INITIATE_UNBIND:
    303          macCommon = (struct _CommonChars*) param2;
    304          result = macCommon->systemRequest ((DWORD)&common, 0,
    305                                             0, REQ_UNBIND,
    306                                             macCommon->moduleDS);
    307          break;
    308 
    309     default:
    310          result = ERR_GENERAL_FAILURE;
    311 	 break;
    312   }
    313   ARGSUSED (param1);
    314   ARGSUSED (param3);
    315   ARGSUSED (targetDS);
    316   return (result);
    317 }
    318 
    319 CALLBACK (NdisRequestConfirm (WORD protId, WORD macId,   WORD reqHandle,
    320                               WORD status, WORD request, WORD protDS))
    321 {
    322   ARGSUSED (protId);    ARGSUSED (macId);
    323   ARGSUSED (reqHandle); ARGSUSED (status);
    324   ARGSUSED (request);   ARGSUSED (protDS);
    325   return (ERR_SUCCESS);
    326 }
    327 
    328 CALLBACK (NdisTransmitConfirm (WORD protId, WORD macId, WORD reqHandle,
    329                                WORD status, WORD protDS))
    330 {
    331   xmitPending--;
    332   FreePktBuf (txBufPending);  /* Add passed ECB back to the free list */
    333 
    334   ARGSUSED (reqHandle);
    335   ARGSUSED (status);
    336   ARGSUSED (protDS);
    337   return (ERR_SUCCESS);
    338 }
    339 
    340 
    341 /*
    342  * The primary function for receiving packets
    343  */
    344 CALLBACK (NdisReceiveLookahead (WORD  macId,      WORD  frameSize,
    345                                 WORD  bytesAvail, BYTE *buffer,
    346                                 BYTE *indicate,   WORD  protDS))
    347 {
    348   int     result;
    349   PktBuf *pktBuf;
    350   WORD    bytesCopied;
    351   struct _TDBufDescr tDBufDescr;
    352 
    353 #if 0
    354   TRACE1 ("lookahead length = %d, ", bytesAvail);
    355   TRACE1 ("ecb = %08lX, ",          *ecb);
    356   TRACE1 ("count = %08lX\n",         count);
    357   TRACE1 ("offset = %08lX, ",        offset);
    358   TRACE1 ("timesAllowed = %d, ",     timesAllowed);
    359   TRACE1 ("packet size = %d\n",      look->dataLookAheadLen);
    360 #endif
    361 
    362   /* Allocate a buffer for the packet
    363    */
    364   if ((pktBuf = AllocPktBuf()) == NULL)
    365   {
    366     droppedPackets++;
    367     return (ERR_FRAME_REJECTED);
    368   }
    369 
    370   /*
    371    * Now kludge things. Note we will have to undo this later. This will
    372    * make the packet contiguous after the MLID has done the requested copy.
    373    */
    374 
    375   tDBufDescr.tDDataCount = 1;
    376   tDBufDescr.tDBufDescrRec[0].tDPtrType = NDIS_PTR_PHYSICAL;
    377   tDBufDescr.tDBufDescrRec[0].tDDataPtr = pktBuf->buffer;
    378   tDBufDescr.tDBufDescrRec[0].tDDataLen = pktBuf->length;
    379   tDBufDescr.tDBufDescrRec[0].dummy     = 0;
    380 
    381   result = MAC_DISPATCH(handle)->transferData (&bytesCopied, 0, &tDBufDescr,
    382                                                handle->common->moduleDS);
    383   pktBuf->packetLength = bytesCopied;
    384 
    385   if (result == ERR_SUCCESS)
    386        EnquePktBuf(pktBuf);
    387   else FreePktBuf (pktBuf);
    388 
    389   ARGSUSED (frameSize);
    390   ARGSUSED (bytesAvail);
    391   ARGSUSED (indicate);
    392   ARGSUSED (protDS);
    393 
    394   return (ERR_SUCCESS);
    395 }
    396 
    397 CALLBACK (NdisIndicationComplete (WORD macId, WORD protDS))
    398 {
    399   ARGSUSED (macId);
    400   ARGSUSED (protDS);
    401 
    402   /* We don't give a hoot about these. Just return
    403    */
    404   return (ERR_SUCCESS);
    405 }
    406 
    407 /*
    408  * This is the OTHER way we may receive packets
    409  */
    410 CALLBACK (NdisReceiveChain (WORD macId, WORD frameSize, WORD reqHandle,
    411                             struct _RxBufDescr *rxBufDescr,
    412                             BYTE *indicate, WORD protDS))
    413 {
    414   struct _PktBuf *pktBuf;
    415   int     i;
    416 
    417   /*
    418    * For now we copy the entire packet over to a PktBuf structure. This may be
    419    * a performance hit but this routine probably isn't called very much, and
    420    * it is a lot of work to do it otherwise. Also if it is a filter protocol
    421    * packet we could end up sucking up MAC buffes.
    422    */
    423 
    424   if ((pktBuf = AllocPktBuf()) == NULL)
    425   {
    426     droppedPackets++;
    427     return (ERR_FRAME_REJECTED);
    428   }
    429   pktBuf->packetLength = 0;
    430 
    431   /* Copy the packet to the buffer
    432    */
    433   for (i = 0; i < rxBufDescr->rxDataCount; ++i)
    434   {
    435     struct _RxBufDescrRec *rxDescr = &rxBufDescr->rxBufDescrRec[i];
    436 
    437     memcpy (pktBuf->buffer + pktBuf->packetLength,
    438             rxDescr->rxDataPtr, rxDescr->rxDataLen);
    439     pktBuf->packetLength += rxDescr->rxDataLen;
    440   }
    441 
    442   EnquePktBuf (pktBuf);
    443 
    444   ARGSUSED (frameSize);
    445   ARGSUSED (reqHandle);
    446   ARGSUSED (indicate);
    447   ARGSUSED (protDS);
    448 
    449   /* This frees up the buffer for the MAC to use
    450    */
    451   return (ERR_SUCCESS);
    452 }
    453 
    454 CALLBACK (NdisStatusProc (WORD macId,  WORD param1, BYTE *indicate,
    455                           WORD opcode, WORD protDS))
    456 {
    457   switch (opcode)
    458   {
    459     case STATUS_RING_STATUS:
    460 	 break;
    461     case STATUS_ADAPTER_CHECK:
    462 	 break;
    463     case STATUS_START_RESET:
    464 	 break;
    465     case STATUS_INTERRUPT:
    466 	 break;
    467     case STATUS_END_RESET:
    468 	 break;
    469     default:
    470 	 break;
    471   }
    472   ARGSUSED (macId);
    473   ARGSUSED (param1);
    474   ARGSUSED (indicate);
    475   ARGSUSED (opcode);
    476   ARGSUSED (protDS);
    477 
    478   /* We don't need to do anything about this stuff yet
    479    */
    480   return (ERR_SUCCESS);
    481 }
    482 
    483 /*
    484  * Tell the NDIS driver to start the delivery of the packet
    485  */
    486 int NdisSendPacket (struct _PktBuf *pktBuf, int macId)
    487 {
    488   struct _TxBufDescr txBufDescr;
    489   int     result;
    490 
    491   xmitPending++;
    492   txBufPending = pktBuf;    /* we only have 1 pending Tx at a time */
    493 
    494   txBufDescr.txImmedLen  = 0;
    495   txBufDescr.txImmedPtr  = NULL;
    496   txBufDescr.txDataCount = 1;
    497   txBufDescr.txBufDescrRec[0].txPtrType = NDIS_PTR_PHYSICAL;
    498   txBufDescr.txBufDescrRec[0].dummy     = 0;
    499   txBufDescr.txBufDescrRec[0].txDataLen = pktBuf->packetLength;
    500   txBufDescr.txBufDescrRec[0].txDataPtr = pktBuf->buffer;
    501 
    502   result = MAC_DISPATCH(handle)->transmitChain (common.moduleId,
    503                                                 pktBuf->handle,
    504                                                 &txBufDescr,
    505                                                 handle->common->moduleDS);
    506   switch (result)
    507   {
    508     case ERR_OUT_OF_RESOURCE:
    509          /* Note that this should not happen but if it does there is not
    510           * much we can do about it
    511           */
    512          printf ("ERROR: transmit queue overflowed\n");
    513          return (0);
    514 
    515     case ERR_SUCCESS:
    516          /* Everything was hunky dory and synchronous. Free up the
    517           * packet buffer
    518           */
    519          xmitPending--;
    520          FreePktBuf (pktBuf);
    521          return (1);
    522 
    523     case ERR_REQUEST_QUEUED:
    524          /* Everything was hunky dory and asynchronous. Do nothing
    525           */
    526          return (1);
    527 
    528     default:
    529          printf ("Tx fail, code = %04X\n", result);
    530          return (0);
    531   }
    532 }
    533 
    534 
    535 
    536 static int ndis_nerr = sizeof(ndis_errlist) / sizeof(ndis_errlist[0]);
    537 
    538 static char *Ndis_strerror (WORD errorCode)
    539 {
    540   static char buf[30];
    541   int    i;
    542 
    543   for (i = 0; i < ndis_nerr; i++)
    544       if (errorCode == ndis_errlist[i].err_num)
    545          return (ndis_errlist[i].err_text);
    546 
    547   sprintf (buf,"unknown error %d",errorCode);
    548   return (buf);
    549 }
    550 
    551 
    552 char *NdisLastError (void)
    553 {
    554   char *errStr = lastErr;
    555   lastErr = NULL;
    556   return (errStr);
    557 }
    558 
    559 int NdisOpen (void)
    560 {
    561   struct _ReqBlock reqBlock;
    562   int     result;
    563   int     ndisFd = open (NDIS_PATH, O_RDONLY);
    564 
    565   if (ndisFd < 0)
    566   {
    567     printf ("Could not open NDIS Protocol Manager device.\n");
    568     return (0);
    569   }
    570 
    571   memset (&reqBlock, 0, sizeof(ReqBlock));
    572 
    573   reqBlock.opcode = PM_GET_PROTOCOL_MANAGER_LINKAGE;
    574 
    575   result = NdisGetLinkage (ndisFd, (char*)&reqBlock, sizeof(ReqBlock));
    576   if (result != 0)
    577   {
    578     printf ("Could not get Protocol Manager linkage.\n");
    579     close (ndisFd);
    580     return (0);
    581   }
    582 
    583   close (ndisFd);
    584   protManEntry = (ProtMan) reqBlock.pointer1;
    585   protManDS    = reqBlock.word1;
    586 
    587   DEBUG2 ("Entry Point = %04X:%04X\n", FP_SEG(protManEntry),FP_OFF(protManEntry));
    588   DEBUG1 ("ProtMan DS  = %04X\n", protManDS);
    589   return (1);
    590 }
    591 
    592 
    593 int NdisRegisterAndBind (int promis)
    594 {
    595   struct _ReqBlock reqBlock;
    596   WORD    result;
    597 
    598   memset (&common,0,sizeof(common));
    599 
    600   common.tableSize = sizeof (common);
    601 
    602   common.majorNdisVersion   = 2;
    603   common.minorNdisVersion   = 0;
    604   common.majorModuleVersion = 2;
    605   common.minorModuleVersion = 0;
    606 
    607   /* Indicates binding from below and dynamically loaded
    608    */
    609   common.moduleFlags = 0x00000006L;
    610 
    611   strcpy (common.moduleName, "PCAP");
    612 
    613   common.protocolLevelUpper = 0xFF;
    614   common.protocolLevelLower = 1;
    615   common.interfaceLower     = 1;
    616 #ifdef __DJGPP__
    617   common.moduleDS           = _dos_ds; /* the callback data segment */
    618 #else
    619   common.moduleDS           = _DS;
    620 #endif
    621 
    622   common.systemRequest      = (SystemRequest) systemRequestGlue;
    623   common.serviceChars       = (BYTE*) &protChars;
    624   common.serviceStatus      = NULL;
    625   common.upperDispatchTable = NULL;
    626   common.lowerDispatchTable = (BYTE*) &lowerTable;
    627 
    628   protChars.length  = sizeof (protChars);
    629   protChars.name[0] = 0;
    630   protChars.type    = 0;
    631 
    632   lowerTable.backPointer        = &common;
    633   lowerTable.requestConfirm     = requestConfirmGlue;
    634   lowerTable.transmitConfirm    = transmitConfirmGlue;
    635   lowerTable.receiveLookahead   = receiveLookaheadGlue;
    636   lowerTable.indicationComplete = indicationCompleteGlue;
    637   lowerTable.receiveChain       = receiveChainGlue;
    638   lowerTable.status             = statusGlue;
    639   lowerTable.flags              = 3;
    640   if (promis)
    641      lowerTable.flags |= 4;   /* promiscous mode (receive everything) */
    642 
    643   bindings.numBindings = 1;
    644   strcpy (bindings.moduleName[0], handle->moduleName);
    645 
    646   /* Register ourselves with NDIS
    647    */
    648   reqBlock.opcode   = PM_REGISTER_MODULE;
    649   reqBlock.pointer1 = (BYTE FAR*) &common;
    650   reqBlock.pointer2 = (BYTE FAR*) &bindings;
    651 
    652   result = (*protManEntry) (&reqBlock, protManDS);
    653   if (result)
    654   {
    655     printf ("Protman registering failed: %s\n", Ndis_strerror(result));
    656     return (0);
    657   }
    658 
    659   /* Start the binding process
    660    */
    661   reqBlock.opcode   = PM_BIND_AND_START;
    662   reqBlock.pointer1 = (BYTE FAR*) &failingModules;
    663 
    664   result = (*protManEntry) (&reqBlock, protManDS);
    665   if (result)
    666   {
    667     printf ("Start binding failed: %s\n", Ndis_strerror(result));
    668     return (0);
    669   }
    670   return (1);
    671 }
    672 
    673 static int CheckMacFeatures (CardHandle *card)
    674 {
    675   DWORD      serviceFlags;
    676   BYTE _far *mediaString;
    677   BYTE _far *mac_addr;
    678 
    679   DEBUG2 ("checking card features\n"
    680           "common table address = %08lX, macId = %d\n",
    681           card->common, card->common->moduleId);
    682 
    683   serviceFlags = MAC_CHAR (handle)->serviceFlags;
    684 
    685   if ((serviceFlags & SF_PROMISCUOUS) == 0)
    686   {
    687     printf ("The MAC %s does not support promiscuous mode.\n",
    688             card->moduleName);
    689     return (0);
    690   }
    691 
    692   mediaString = MAC_CHAR (handle)->macName;
    693 
    694   DEBUG1 ("media type = %s\n",mediaString);
    695 
    696   /* Get the media type. And set the header size
    697    */
    698   if (!strncmp(mediaString,"802.3",5) ||
    699       !strncmp(mediaString,"DIX",3)   ||
    700       !strncmp(mediaString,"DIX+802.3",9))
    701        headerSize = sizeof (EthernetIIHeader);
    702 
    703   else if (!strncmp(mediaString,"FDDI",4))
    704        headerSize = sizeof (FddiHeader) +
    705                     sizeof (Ieee802Dot2SnapHeader);
    706   else
    707   {
    708     printf ("Unsupported MAC type: `%s'\n", mediaString);
    709     return (0);
    710   }
    711 
    712   frameSize = MAC_CHAR (handle)->maxFrameSize;
    713   mac_addr  = MAC_CHAR (handle)->currentAddress;
    714 
    715   printf ("Hardware address: %02X:%02X:%02X:%02X:%02X:%02X\n",
    716           mac_addr[0], mac_addr[1], mac_addr[2],
    717           mac_addr[3], mac_addr[4], mac_addr[5]);
    718   return (1);
    719 }
    720 
    721 static int NdisStartMac (CardHandle *card)
    722 {
    723   WORD result;
    724 
    725   /* Set the lookahead length
    726    */
    727   result = MAC_DISPATCH(handle)->request (common.moduleId, 0,
    728                                           headerSize, 0,
    729                                           REQ_SET_LOOKAHEAD,
    730                                           card->common->moduleDS);
    731 
    732   /* We assume that if we got INVALID PARAMETER then either this
    733    * is not supported or will work anyway. NE2000 does this.
    734    */
    735   if (result != ERR_SUCCESS && result != ERR_INVALID_PARAMETER)
    736   {
    737     DEBUG1 ("Set lookahead failed: %s\n", Ndis_strerror(result));
    738     return (0);
    739   }
    740 
    741   /* Set the packet filter. Note that for some medias and drivers we
    742    * must specify all three flags or the card(s) will not operate correctly.
    743    */
    744   result = MAC_DISPATCH(handle)->request (common.moduleId, 0,
    745                       /* all packets */   FILTER_PROMISCUOUS |
    746                       /* packets to us */ FILTER_DIRECTED    |
    747                       /* broadcasts */    FILTER_BROADCAST,
    748                                           0, REQ_SET_PACKET_FILTER,
    749                                           card->common->moduleDS);
    750   if (result != ERR_SUCCESS)
    751   {
    752     DEBUG1 ("Set packet filter failed: %s\n", Ndis_strerror(result));
    753     return (0);
    754   }
    755 
    756   /* If OPEN/CLOSE supported then open the adapter
    757    */
    758   if (MAC_CHAR(handle)->serviceFlags & SF_OPEN_CLOSE)
    759   {
    760     result = MAC_DISPATCH(handle)->request (common.moduleId, 0, 0, NULL,
    761                                             REQ_OPEN_ADAPTER,
    762                                             card->common->moduleDS);
    763     if (result != ERR_SUCCESS)
    764     {
    765       DEBUG1 ("Opening the MAC failed: %s\n", Ndis_strerror(result));
    766       return (0);
    767     }
    768   }
    769   return (1);
    770 }
    771 
    772 void NdisShutdown (void)
    773 {
    774   struct _ReqBlock reqBlock;
    775   int     result, i;
    776 
    777   if (!handle)
    778      return;
    779 
    780   /* If the adapters support open and are open then close them
    781    */
    782   if ((MAC_CHAR(handle)->serviceFlags & SF_OPEN_CLOSE) &&
    783       (MAC_STATUS(handle)->macStatus & MAC_OPEN))
    784   {
    785     result = MAC_DISPATCH(handle)->request (common.moduleId, 0, 0, 0,
    786                                             REQ_CLOSE_ADAPTER,
    787                                             handle->common->moduleDS);
    788     if (result != ERR_SUCCESS)
    789     {
    790       printf ("Closing the MAC failed: %s\n", Ndis_strerror(result));
    791       return;
    792     }
    793   }
    794 
    795   /* Tell the Protocol Manager to unbind and stop
    796    */
    797   reqBlock.opcode   = PM_UNBIND_AND_STOP;
    798   reqBlock.pointer1 = (BYTE FAR*) &failingModules;
    799   reqBlock.pointer2 = NULL;
    800 
    801   result = (*protManEntry) (&reqBlock, protManDS);
    802   if (result)
    803      printf ("Unbind failed: %s\n",  Ndis_strerror(result));
    804 
    805   for (i = 0; i < STACK_POOL_SIZE; ++i)
    806      free (freeStacks[i] - STACK_SIZE);
    807 
    808   handle = NULL;
    809 }
    810 
    811 int NdisInit (int promis)
    812 {
    813   int i, result;
    814 
    815   /* Allocate the real mode stacks used for NDIS callbacks
    816    */
    817   for (i = 0; i < STACK_POOL_SIZE; ++i)
    818   {
    819     freeStacks[i] = malloc (STACK_SIZE);
    820     if (!freeStacks[i])
    821        return (0);
    822     freeStacks[i] += STACK_SIZE;
    823   }
    824 
    825   if (!NdisOpen())
    826      return (0);
    827 
    828   if (!NdisRegisterAndBind(promis))
    829      return (0);
    830 
    831   DEBUG1 ("My module id: %d\n", common.moduleId);
    832   DEBUG1 ("Handle id;    %d\n", handle->common->moduleId);
    833   DEBUG1 ("MAC card:     %-16s - ", handle->moduleName);
    834 
    835   atexit (NdisShutdown);
    836 
    837   if (!CheckMacFeatures(&handle))
    838      return (0);
    839 
    840   switch (mediaType)
    841   {
    842     case MEDIA_FDDI:
    843          DEBUG0 ("Media type: FDDI");
    844 	 break;
    845     case MEDIA_ETHERNET:
    846          DEBUG0 ("Media type: ETHERNET");
    847 	 break;
    848     default:
    849          DEBUG0 ("Unsupported media.\n");
    850          return (0);
    851   }
    852 
    853   DEBUG1 (" - Frame size: %d\n", frameSize);
    854 
    855   if (!NdisStartMac(&handle))
    856      return (0);
    857   return (1);
    858 }
    859 #endif  /* USE_NDIS2 */
    860 
    861