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 */
NdisFreeStack(BYTE * aStack)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 */
NdisAllocStack(void)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
CALLBACK(NdisSystemRequest (DWORD param1,DWORD param2,WORD param3,WORD opcode,WORD targetDS))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
CALLBACK(NdisRequestConfirm (WORD protId,WORD macId,WORD reqHandle,WORD status,WORD request,WORD protDS))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
CALLBACK(NdisTransmitConfirm (WORD protId,WORD macId,WORD reqHandle,WORD status,WORD protDS))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 */
CALLBACK(NdisReceiveLookahead (WORD macId,WORD frameSize,WORD bytesAvail,BYTE * buffer,BYTE * indicate,WORD protDS))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
CALLBACK(NdisIndicationComplete (WORD macId,WORD protDS))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 */
CALLBACK(NdisReceiveChain (WORD macId,WORD frameSize,WORD reqHandle,struct _RxBufDescr * rxBufDescr,BYTE * indicate,WORD protDS))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
CALLBACK(NdisStatusProc (WORD macId,WORD param1,BYTE * indicate,WORD opcode,WORD protDS))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 */
NdisSendPacket(struct _PktBuf * pktBuf,int macId)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
Ndis_strerror(WORD errorCode)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
NdisLastError(void)552 char *NdisLastError (void)
553 {
554 char *errStr = lastErr;
555 lastErr = NULL;
556 return (errStr);
557 }
558
NdisOpen(void)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
NdisRegisterAndBind(int promis)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
CheckMacFeatures(CardHandle * card)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
NdisStartMac(CardHandle * card)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
NdisShutdown(void)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
NdisInit(int promis)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