/* | |
* Copyright (c) 1993,1994 | |
* Texas A&M University. All rights reserved. | |
* | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions | |
* are met: | |
* 1. Redistributions of source code must retain the above copyright | |
* notice, this list of conditions and the following disclaimer. | |
* 2. Redistributions in binary form must reproduce the above copyright | |
* notice, this list of conditions and the following disclaimer in the | |
* documentation and/or other materials provided with the distribution. | |
* 3. All advertising materials mentioning features or use of this software | |
* must display the following acknowledgement: | |
* This product includes software developed by Texas A&M University | |
* and its contributors. | |
* 4. Neither the name of the University nor the names of its contributors | |
* may be used to endorse or promote products derived from this software | |
* without specific prior written permission. | |
* | |
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND | |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE | |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
* SUCH DAMAGE. | |
* | |
* Developers: | |
* David K. Hess, Douglas Lee Schales, David R. Safford | |
* | |
* Heavily modified for Metaware HighC + GNU C 2.8+ | |
* Gisle Vanem 1998 | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <dos.h> | |
#include <io.h> | |
#include <fcntl.h> | |
#include <malloc.h> | |
#include <string.h> | |
#include "pcap-dos.h" | |
#include "pcap-int.h" | |
#include "msdos/ndis2.h" | |
#if defined(USE_NDIS2) | |
/* | |
* Packet buffer handling | |
*/ | |
extern int FreePktBuf (PktBuf *buf); | |
extern int EnquePktBuf (PktBuf *buf); | |
extern PktBuf* AllocPktBuf (void); | |
/* | |
* Various defines | |
*/ | |
#define MAX_NUM_DEBUG_STRINGS 90 | |
#define DEBUG_STRING_LENGTH 80 | |
#define STACK_POOL_SIZE 6 | |
#define STACK_SIZE 256 | |
#define MEDIA_FDDI 1 | |
#define MEDIA_ETHERNET 2 | |
#define MEDIA_TOKEN 3 | |
static int startDebug = 0; | |
static int stopDebug = 0; | |
static DWORD droppedPackets = 0L; | |
static WORD frameSize = 0; | |
static WORD headerSize = 0; | |
static int mediaType = 0; | |
static char *lastErr = NULL; | |
static BYTE debugStrings [MAX_NUM_DEBUG_STRINGS][DEBUG_STRING_LENGTH]; | |
static BYTE *freeStacks [STACK_POOL_SIZE]; | |
static int freeStackPtr = STACK_POOL_SIZE - 1; | |
static ProtMan protManEntry = NULL; | |
static WORD protManDS = 0; | |
static volatile int xmitPending; | |
static struct _PktBuf *txBufPending; | |
static struct _CardHandle *handle; | |
static struct _CommonChars common; | |
static struct _ProtocolChars protChars; | |
static struct _ProtDispatch lowerTable; | |
static struct _FailingModules failingModules; | |
static struct _BindingsList bindings; | |
static struct { | |
WORD err_num; | |
char *err_text; | |
} ndis_errlist[] = { | |
{ ERR_SUCCESS, | |
"The function completed successfully.\n" }, | |
{ ERR_WAIT_FOR_RELEASE, | |
"The ReceiveChain completed successfully but the protocol has\n" | |
"retained control of the buffer.\n" }, | |
{ ERR_REQUEST_QUEUED, | |
"The current request has been queued.\n" }, | |
{ ERR_FRAME_NOT_RECOGNIZED, | |
"Frame not recognized.\n" }, | |
{ ERR_FRAME_REJECTED, | |
"Frame was discarded.\n" }, | |
{ ERR_FORWARD_FRAME, | |
"Protocol wishes to forward frame to another protocol.\n" }, | |
{ ERR_OUT_OF_RESOURCE, | |
"Out of resource.\n" }, | |
{ ERR_INVALID_PARAMETER, | |
"Invalid parameter.\n" }, | |
{ ERR_INVALID_FUNCTION, | |
"Invalid function.\n" }, | |
{ ERR_NOT_SUPPORTED, | |
"Not supported.\n" }, | |
{ ERR_HARDWARE_ERROR, | |
"Hardware error.\n" }, | |
{ ERR_TRANSMIT_ERROR, | |
"The packet was not transmitted due to an error.\n" }, | |
{ ERR_NO_SUCH_DESTINATION, | |
"Token ring packet was not recognized when transmitted.\n" }, | |
{ ERR_BUFFER_TOO_SMALL, | |
"Provided buffer was too small.\n" }, | |
{ ERR_ALREADY_STARTED, | |
"Network drivers already started.\n" }, | |
{ ERR_INCOMPLETE_BINDING, | |
"Protocol driver could not complete its bindings.\n" }, | |
{ ERR_DRIVER_NOT_INITIALIZED, | |
"MAC did not initialize properly.\n" }, | |
{ ERR_HARDWARE_NOT_FOUND, | |
"Hardware not found.\n" }, | |
{ ERR_HARDWARE_FAILURE, | |
"Hardware failure.\n" }, | |
{ ERR_CONFIGURATION_FAILURE, | |
"Configuration failure.\n" }, | |
{ ERR_INTERRUPT_CONFLICT, | |
"Interrupt conflict.\n" }, | |
{ ERR_INCOMPATIBLE_MAC, | |
"The MAC is not compatible with the protocol.\n" }, | |
{ ERR_INITIALIZATION_FAILED, | |
"Initialization failed.\n" }, | |
{ ERR_NO_BINDING, | |
"Binding did not occur.\n" }, | |
{ ERR_NETWORK_MAY_NOT_BE_CONNECTED, | |
"The network may not be connected to the adapter.\n" }, | |
{ ERR_INCOMPATIBLE_OS_VERSION, | |
"The version of the operating system is incompatible with the protocol.\n" }, | |
{ ERR_ALREADY_REGISTERED, | |
"The protocol is already registered.\n" }, | |
{ ERR_PATH_NOT_FOUND, | |
"PROTMAN.EXE could not be found.\n" }, | |
{ ERR_INSUFFICIENT_MEMORY, | |
"Insufficient memory.\n" }, | |
{ ERR_INFO_NOT_FOUND, | |
"Protocol Mananger info structure is lost or corrupted.\n" }, | |
{ ERR_GENERAL_FAILURE, | |
"General failure.\n" } | |
}; | |
/* | |
* Some handy macros | |
*/ | |
#define PERROR(str) printf("%s (%d): %s\n", __FILE__,__LINE__,str) | |
#define DEBUG_RING() (debugStrings[stopDebug+1 == MAX_NUM_DEBUG_STRINGS ? \ | |
stopDebug = 0 : ++stopDebug]) | |
/* | |
* needs rewrite for DOSX | |
*/ | |
#define MAC_DISPATCH(hnd) ((struct _MacUpperDispatch*)(hnd)->common->upperDispatchTable) | |
#define MAC_STATUS(hnd) ((struct _MacStatusTable*) (hnd)->common->serviceStatus) | |
#define MAC_CHAR(hnd) ((struct _MacChars*) (hnd)->common->serviceChars) | |
#ifdef NDIS_DEBUG | |
#define DEBUG0(str) printf (str) | |
#define DEBUG1(fmt,a) printf (fmt,a) | |
#define DEBUG2(fmt,a,b) printf (fmt,a,b) | |
#define TRACE0(str) sprintf (DEBUG_RING(),str) | |
#define TRACE1(fmt,a) sprintf (DEBUG_RING(),fmt,a) | |
#else | |
#define DEBUG0(str) ((void)0) | |
#define DEBUG1(fmt,a) ((void)0) | |
#define DEBUG2(fmt,a,b) ((void)0) | |
#define TRACE0(str) ((void)0) | |
#define TRACE1(fmt,a) ((void)0) | |
#endif | |
/* | |
* This routine is called from both threads | |
*/ | |
void NdisFreeStack (BYTE *aStack) | |
{ | |
GUARD(); | |
if (freeStackPtr == STACK_POOL_SIZE - 1) | |
PERROR ("tried to free too many stacks"); | |
freeStacks[++freeStackPtr] = aStack; | |
if (freeStackPtr == 0) | |
TRACE0 ("freeStackPtr went positive\n"); | |
UNGUARD(); | |
} | |
/* | |
* This routine is called from callbacks to allocate local data | |
*/ | |
BYTE *NdisAllocStack (void) | |
{ | |
BYTE *stack; | |
GUARD(); | |
if (freeStackPtr < 0) | |
{ | |
/* Ran out of stack buffers. Return NULL which will start | |
* dropping packets | |
*/ | |
TRACE0 ("freeStackPtr went negative\n"); | |
stack = 0; | |
} | |
else | |
stack = freeStacks[freeStackPtr--]; | |
UNGUARD(); | |
return (stack); | |
} | |
CALLBACK (NdisSystemRequest (DWORD param1, DWORD param2, WORD param3, | |
WORD opcode, WORD targetDS)) | |
{ | |
static int bindEntry = 0; | |
struct _CommonChars *macCommon; | |
volatile WORD result; | |
switch (opcode) | |
{ | |
case REQ_INITIATE_BIND: | |
macCommon = (struct _CommonChars*) param2; | |
if (macCommon == NULL) | |
{ | |
printf ("There is an NDIS misconfiguration.\n"); | |
result = ERR_GENERAL_FAILURE; | |
break; | |
} | |
DEBUG2 ("module name %s\n" | |
"module type %s\n", | |
macCommon->moduleName, | |
((MacChars*) macCommon->serviceChars)->macName); | |
/* Binding to the MAC */ | |
result = macCommon->systemRequest ((DWORD)&common, (DWORD)&macCommon, | |
0, REQ_BIND, | |
macCommon->moduleDS); | |
if (!strcmp(bindings.moduleName[bindEntry], handle->moduleName)) | |
handle->common = macCommon; | |
else PERROR ("unknown module"); | |
++bindEntry; | |
break; | |
case REQ_INITIATE_UNBIND: | |
macCommon = (struct _CommonChars*) param2; | |
result = macCommon->systemRequest ((DWORD)&common, 0, | |
0, REQ_UNBIND, | |
macCommon->moduleDS); | |
break; | |
default: | |
result = ERR_GENERAL_FAILURE; | |
break; | |
} | |
ARGSUSED (param1); | |
ARGSUSED (param3); | |
ARGSUSED (targetDS); | |
return (result); | |
} | |
CALLBACK (NdisRequestConfirm (WORD protId, WORD macId, WORD reqHandle, | |
WORD status, WORD request, WORD protDS)) | |
{ | |
ARGSUSED (protId); ARGSUSED (macId); | |
ARGSUSED (reqHandle); ARGSUSED (status); | |
ARGSUSED (request); ARGSUSED (protDS); | |
return (ERR_SUCCESS); | |
} | |
CALLBACK (NdisTransmitConfirm (WORD protId, WORD macId, WORD reqHandle, | |
WORD status, WORD protDS)) | |
{ | |
xmitPending--; | |
FreePktBuf (txBufPending); /* Add passed ECB back to the free list */ | |
ARGSUSED (reqHandle); | |
ARGSUSED (status); | |
ARGSUSED (protDS); | |
return (ERR_SUCCESS); | |
} | |
/* | |
* The primary function for receiving packets | |
*/ | |
CALLBACK (NdisReceiveLookahead (WORD macId, WORD frameSize, | |
WORD bytesAvail, BYTE *buffer, | |
BYTE *indicate, WORD protDS)) | |
{ | |
int result; | |
PktBuf *pktBuf; | |
WORD bytesCopied; | |
struct _TDBufDescr tDBufDescr; | |
#if 0 | |
TRACE1 ("lookahead length = %d, ", bytesAvail); | |
TRACE1 ("ecb = %08lX, ", *ecb); | |
TRACE1 ("count = %08lX\n", count); | |
TRACE1 ("offset = %08lX, ", offset); | |
TRACE1 ("timesAllowed = %d, ", timesAllowed); | |
TRACE1 ("packet size = %d\n", look->dataLookAheadLen); | |
#endif | |
/* Allocate a buffer for the packet | |
*/ | |
if ((pktBuf = AllocPktBuf()) == NULL) | |
{ | |
droppedPackets++; | |
return (ERR_FRAME_REJECTED); | |
} | |
/* | |
* Now kludge things. Note we will have to undo this later. This will | |
* make the packet contiguous after the MLID has done the requested copy. | |
*/ | |
tDBufDescr.tDDataCount = 1; | |
tDBufDescr.tDBufDescrRec[0].tDPtrType = NDIS_PTR_PHYSICAL; | |
tDBufDescr.tDBufDescrRec[0].tDDataPtr = pktBuf->buffer; | |
tDBufDescr.tDBufDescrRec[0].tDDataLen = pktBuf->length; | |
tDBufDescr.tDBufDescrRec[0].dummy = 0; | |
result = MAC_DISPATCH(handle)->transferData (&bytesCopied, 0, &tDBufDescr, | |
handle->common->moduleDS); | |
pktBuf->packetLength = bytesCopied; | |
if (result == ERR_SUCCESS) | |
EnquePktBuf(pktBuf); | |
else FreePktBuf (pktBuf); | |
ARGSUSED (frameSize); | |
ARGSUSED (bytesAvail); | |
ARGSUSED (indicate); | |
ARGSUSED (protDS); | |
return (ERR_SUCCESS); | |
} | |
CALLBACK (NdisIndicationComplete (WORD macId, WORD protDS)) | |
{ | |
ARGSUSED (macId); | |
ARGSUSED (protDS); | |
/* We don't give a hoot about these. Just return | |
*/ | |
return (ERR_SUCCESS); | |
} | |
/* | |
* This is the OTHER way we may receive packets | |
*/ | |
CALLBACK (NdisReceiveChain (WORD macId, WORD frameSize, WORD reqHandle, | |
struct _RxBufDescr *rxBufDescr, | |
BYTE *indicate, WORD protDS)) | |
{ | |
struct _PktBuf *pktBuf; | |
int i; | |
/* | |
* For now we copy the entire packet over to a PktBuf structure. This may be | |
* a performance hit but this routine probably isn't called very much, and | |
* it is a lot of work to do it otherwise. Also if it is a filter protocol | |
* packet we could end up sucking up MAC buffes. | |
*/ | |
if ((pktBuf = AllocPktBuf()) == NULL) | |
{ | |
droppedPackets++; | |
return (ERR_FRAME_REJECTED); | |
} | |
pktBuf->packetLength = 0; | |
/* Copy the packet to the buffer | |
*/ | |
for (i = 0; i < rxBufDescr->rxDataCount; ++i) | |
{ | |
struct _RxBufDescrRec *rxDescr = &rxBufDescr->rxBufDescrRec[i]; | |
memcpy (pktBuf->buffer + pktBuf->packetLength, | |
rxDescr->rxDataPtr, rxDescr->rxDataLen); | |
pktBuf->packetLength += rxDescr->rxDataLen; | |
} | |
EnquePktBuf (pktBuf); | |
ARGSUSED (frameSize); | |
ARGSUSED (reqHandle); | |
ARGSUSED (indicate); | |
ARGSUSED (protDS); | |
/* This frees up the buffer for the MAC to use | |
*/ | |
return (ERR_SUCCESS); | |
} | |
CALLBACK (NdisStatusProc (WORD macId, WORD param1, BYTE *indicate, | |
WORD opcode, WORD protDS)) | |
{ | |
switch (opcode) | |
{ | |
case STATUS_RING_STATUS: | |
break; | |
case STATUS_ADAPTER_CHECK: | |
break; | |
case STATUS_START_RESET: | |
break; | |
case STATUS_INTERRUPT: | |
break; | |
case STATUS_END_RESET: | |
break; | |
default: | |
break; | |
} | |
ARGSUSED (macId); | |
ARGSUSED (param1); | |
ARGSUSED (indicate); | |
ARGSUSED (opcode); | |
ARGSUSED (protDS); | |
/* We don't need to do anything about this stuff yet | |
*/ | |
return (ERR_SUCCESS); | |
} | |
/* | |
* Tell the NDIS driver to start the delivery of the packet | |
*/ | |
int NdisSendPacket (struct _PktBuf *pktBuf, int macId) | |
{ | |
struct _TxBufDescr txBufDescr; | |
int result; | |
xmitPending++; | |
txBufPending = pktBuf; /* we only have 1 pending Tx at a time */ | |
txBufDescr.txImmedLen = 0; | |
txBufDescr.txImmedPtr = NULL; | |
txBufDescr.txDataCount = 1; | |
txBufDescr.txBufDescrRec[0].txPtrType = NDIS_PTR_PHYSICAL; | |
txBufDescr.txBufDescrRec[0].dummy = 0; | |
txBufDescr.txBufDescrRec[0].txDataLen = pktBuf->packetLength; | |
txBufDescr.txBufDescrRec[0].txDataPtr = pktBuf->buffer; | |
result = MAC_DISPATCH(handle)->transmitChain (common.moduleId, | |
pktBuf->handle, | |
&txBufDescr, | |
handle->common->moduleDS); | |
switch (result) | |
{ | |
case ERR_OUT_OF_RESOURCE: | |
/* Note that this should not happen but if it does there is not | |
* much we can do about it | |
*/ | |
printf ("ERROR: transmit queue overflowed\n"); | |
return (0); | |
case ERR_SUCCESS: | |
/* Everything was hunky dory and synchronous. Free up the | |
* packet buffer | |
*/ | |
xmitPending--; | |
FreePktBuf (pktBuf); | |
return (1); | |
case ERR_REQUEST_QUEUED: | |
/* Everything was hunky dory and asynchronous. Do nothing | |
*/ | |
return (1); | |
default: | |
printf ("Tx fail, code = %04X\n", result); | |
return (0); | |
} | |
} | |
static int ndis_nerr = sizeof(ndis_errlist) / sizeof(ndis_errlist[0]); | |
static char *Ndis_strerror (WORD errorCode) | |
{ | |
static char buf[30]; | |
int i; | |
for (i = 0; i < ndis_nerr; i++) | |
if (errorCode == ndis_errlist[i].err_num) | |
return (ndis_errlist[i].err_text); | |
sprintf (buf,"unknown error %d",errorCode); | |
return (buf); | |
} | |
char *NdisLastError (void) | |
{ | |
char *errStr = lastErr; | |
lastErr = NULL; | |
return (errStr); | |
} | |
int NdisOpen (void) | |
{ | |
struct _ReqBlock reqBlock; | |
int result; | |
int ndisFd = open (NDIS_PATH, O_RDONLY); | |
if (ndisFd < 0) | |
{ | |
printf ("Could not open NDIS Protocol Manager device.\n"); | |
return (0); | |
} | |
memset (&reqBlock, 0, sizeof(ReqBlock)); | |
reqBlock.opcode = PM_GET_PROTOCOL_MANAGER_LINKAGE; | |
result = NdisGetLinkage (ndisFd, (char*)&reqBlock, sizeof(ReqBlock)); | |
if (result != 0) | |
{ | |
printf ("Could not get Protocol Manager linkage.\n"); | |
close (ndisFd); | |
return (0); | |
} | |
close (ndisFd); | |
protManEntry = (ProtMan) reqBlock.pointer1; | |
protManDS = reqBlock.word1; | |
DEBUG2 ("Entry Point = %04X:%04X\n", FP_SEG(protManEntry),FP_OFF(protManEntry)); | |
DEBUG1 ("ProtMan DS = %04X\n", protManDS); | |
return (1); | |
} | |
int NdisRegisterAndBind (int promis) | |
{ | |
struct _ReqBlock reqBlock; | |
WORD result; | |
memset (&common,0,sizeof(common)); | |
common.tableSize = sizeof (common); | |
common.majorNdisVersion = 2; | |
common.minorNdisVersion = 0; | |
common.majorModuleVersion = 2; | |
common.minorModuleVersion = 0; | |
/* Indicates binding from below and dynamically loaded | |
*/ | |
common.moduleFlags = 0x00000006L; | |
strcpy (common.moduleName, "PCAP"); | |
common.protocolLevelUpper = 0xFF; | |
common.protocolLevelLower = 1; | |
common.interfaceLower = 1; | |
#ifdef __DJGPP__ | |
common.moduleDS = _dos_ds; /* the callback data segment */ | |
#else | |
common.moduleDS = _DS; | |
#endif | |
common.systemRequest = (SystemRequest) systemRequestGlue; | |
common.serviceChars = (BYTE*) &protChars; | |
common.serviceStatus = NULL; | |
common.upperDispatchTable = NULL; | |
common.lowerDispatchTable = (BYTE*) &lowerTable; | |
protChars.length = sizeof (protChars); | |
protChars.name[0] = 0; | |
protChars.type = 0; | |
lowerTable.backPointer = &common; | |
lowerTable.requestConfirm = requestConfirmGlue; | |
lowerTable.transmitConfirm = transmitConfirmGlue; | |
lowerTable.receiveLookahead = receiveLookaheadGlue; | |
lowerTable.indicationComplete = indicationCompleteGlue; | |
lowerTable.receiveChain = receiveChainGlue; | |
lowerTable.status = statusGlue; | |
lowerTable.flags = 3; | |
if (promis) | |
lowerTable.flags |= 4; /* promiscous mode (receive everything) */ | |
bindings.numBindings = 1; | |
strcpy (bindings.moduleName[0], handle->moduleName); | |
/* Register ourselves with NDIS | |
*/ | |
reqBlock.opcode = PM_REGISTER_MODULE; | |
reqBlock.pointer1 = (BYTE FAR*) &common; | |
reqBlock.pointer2 = (BYTE FAR*) &bindings; | |
result = (*protManEntry) (&reqBlock, protManDS); | |
if (result) | |
{ | |
printf ("Protman registering failed: %s\n", Ndis_strerror(result)); | |
return (0); | |
} | |
/* Start the binding process | |
*/ | |
reqBlock.opcode = PM_BIND_AND_START; | |
reqBlock.pointer1 = (BYTE FAR*) &failingModules; | |
result = (*protManEntry) (&reqBlock, protManDS); | |
if (result) | |
{ | |
printf ("Start binding failed: %s\n", Ndis_strerror(result)); | |
return (0); | |
} | |
return (1); | |
} | |
static int CheckMacFeatures (CardHandle *card) | |
{ | |
DWORD serviceFlags; | |
BYTE _far *mediaString; | |
BYTE _far *mac_addr; | |
DEBUG2 ("checking card features\n" | |
"common table address = %08lX, macId = %d\n", | |
card->common, card->common->moduleId); | |
serviceFlags = MAC_CHAR (handle)->serviceFlags; | |
if ((serviceFlags & SF_PROMISCUOUS) == 0) | |
{ | |
printf ("The MAC %s does not support promiscuous mode.\n", | |
card->moduleName); | |
return (0); | |
} | |
mediaString = MAC_CHAR (handle)->macName; | |
DEBUG1 ("media type = %s\n",mediaString); | |
/* Get the media type. And set the header size | |
*/ | |
if (!strncmp(mediaString,"802.3",5) || | |
!strncmp(mediaString,"DIX",3) || | |
!strncmp(mediaString,"DIX+802.3",9)) | |
headerSize = sizeof (EthernetIIHeader); | |
else if (!strncmp(mediaString,"FDDI",4)) | |
headerSize = sizeof (FddiHeader) + | |
sizeof (Ieee802Dot2SnapHeader); | |
else | |
{ | |
printf ("Unsupported MAC type: `%s'\n", mediaString); | |
return (0); | |
} | |
frameSize = MAC_CHAR (handle)->maxFrameSize; | |
mac_addr = MAC_CHAR (handle)->currentAddress; | |
printf ("Hardware address: %02X:%02X:%02X:%02X:%02X:%02X\n", | |
mac_addr[0], mac_addr[1], mac_addr[2], | |
mac_addr[3], mac_addr[4], mac_addr[5]); | |
return (1); | |
} | |
static int NdisStartMac (CardHandle *card) | |
{ | |
WORD result; | |
/* Set the lookahead length | |
*/ | |
result = MAC_DISPATCH(handle)->request (common.moduleId, 0, | |
headerSize, 0, | |
REQ_SET_LOOKAHEAD, | |
card->common->moduleDS); | |
/* We assume that if we got INVALID PARAMETER then either this | |
* is not supported or will work anyway. NE2000 does this. | |
*/ | |
if (result != ERR_SUCCESS && result != ERR_INVALID_PARAMETER) | |
{ | |
DEBUG1 ("Set lookahead failed: %s\n", Ndis_strerror(result)); | |
return (0); | |
} | |
/* Set the packet filter. Note that for some medias and drivers we | |
* must specify all three flags or the card(s) will not operate correctly. | |
*/ | |
result = MAC_DISPATCH(handle)->request (common.moduleId, 0, | |
/* all packets */ FILTER_PROMISCUOUS | | |
/* packets to us */ FILTER_DIRECTED | | |
/* broadcasts */ FILTER_BROADCAST, | |
0, REQ_SET_PACKET_FILTER, | |
card->common->moduleDS); | |
if (result != ERR_SUCCESS) | |
{ | |
DEBUG1 ("Set packet filter failed: %s\n", Ndis_strerror(result)); | |
return (0); | |
} | |
/* If OPEN/CLOSE supported then open the adapter | |
*/ | |
if (MAC_CHAR(handle)->serviceFlags & SF_OPEN_CLOSE) | |
{ | |
result = MAC_DISPATCH(handle)->request (common.moduleId, 0, 0, NULL, | |
REQ_OPEN_ADAPTER, | |
card->common->moduleDS); | |
if (result != ERR_SUCCESS) | |
{ | |
DEBUG1 ("Opening the MAC failed: %s\n", Ndis_strerror(result)); | |
return (0); | |
} | |
} | |
return (1); | |
} | |
void NdisShutdown (void) | |
{ | |
struct _ReqBlock reqBlock; | |
int result, i; | |
if (!handle) | |
return; | |
/* If the adapters support open and are open then close them | |
*/ | |
if ((MAC_CHAR(handle)->serviceFlags & SF_OPEN_CLOSE) && | |
(MAC_STATUS(handle)->macStatus & MAC_OPEN)) | |
{ | |
result = MAC_DISPATCH(handle)->request (common.moduleId, 0, 0, 0, | |
REQ_CLOSE_ADAPTER, | |
handle->common->moduleDS); | |
if (result != ERR_SUCCESS) | |
{ | |
printf ("Closing the MAC failed: %s\n", Ndis_strerror(result)); | |
return; | |
} | |
} | |
/* Tell the Protocol Manager to unbind and stop | |
*/ | |
reqBlock.opcode = PM_UNBIND_AND_STOP; | |
reqBlock.pointer1 = (BYTE FAR*) &failingModules; | |
reqBlock.pointer2 = NULL; | |
result = (*protManEntry) (&reqBlock, protManDS); | |
if (result) | |
printf ("Unbind failed: %s\n", Ndis_strerror(result)); | |
for (i = 0; i < STACK_POOL_SIZE; ++i) | |
free (freeStacks[i] - STACK_SIZE); | |
handle = NULL; | |
} | |
int NdisInit (int promis) | |
{ | |
int i, result; | |
/* Allocate the real mode stacks used for NDIS callbacks | |
*/ | |
for (i = 0; i < STACK_POOL_SIZE; ++i) | |
{ | |
freeStacks[i] = malloc (STACK_SIZE); | |
if (!freeStacks[i]) | |
return (0); | |
freeStacks[i] += STACK_SIZE; | |
} | |
if (!NdisOpen()) | |
return (0); | |
if (!NdisRegisterAndBind(promis)) | |
return (0); | |
DEBUG1 ("My module id: %d\n", common.moduleId); | |
DEBUG1 ("Handle id; %d\n", handle->common->moduleId); | |
DEBUG1 ("MAC card: %-16s - ", handle->moduleName); | |
atexit (NdisShutdown); | |
if (!CheckMacFeatures(&handle)) | |
return (0); | |
switch (mediaType) | |
{ | |
case MEDIA_FDDI: | |
DEBUG0 ("Media type: FDDI"); | |
break; | |
case MEDIA_ETHERNET: | |
DEBUG0 ("Media type: ETHERNET"); | |
break; | |
default: | |
DEBUG0 ("Unsupported media.\n"); | |
return (0); | |
} | |
DEBUG1 (" - Frame size: %d\n", frameSize); | |
if (!NdisStartMac(&handle)) | |
return (0); | |
return (1); | |
} | |
#endif /* USE_NDIS2 */ | |