xref: /minix/external/bsd/libpcap/dist/msdos/ndis2.c (revision bb9622b5)
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