mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2148 lines
70 KiB
2148 lines
70 KiB
//**********************************************************************
|
|
//**********************************************************************
|
|
//
|
|
// File Name: REQUEST.C
|
|
//
|
|
// Program Name: NetFlex NDIS 3.0 Miniport Driver
|
|
//
|
|
// Companion Files: None
|
|
//
|
|
// Function: This module contains the NetFlex Miniport Driver
|
|
// interface routines called by the Wrapper and the
|
|
// configuration manager.
|
|
//
|
|
// (c) Compaq Computer Corporation, 1992,1993,1994
|
|
//
|
|
// This file is licensed by Compaq Computer Corporation to Microsoft
|
|
// Corporation pursuant to the letter of August 20, 1992 from
|
|
// Gary Stimac to Mark Baber.
|
|
//
|
|
// History:
|
|
//
|
|
// 04/15/94 Robert Van Cleve - Converted from NDIS Mac Driver
|
|
//
|
|
//**********************************************************************
|
|
//**********************************************************************
|
|
|
|
|
|
//-------------------------------------
|
|
// Include all general companion files
|
|
//-------------------------------------
|
|
#include <ndis.h>
|
|
#include "tmsstrct.h"
|
|
#include "macstrct.h"
|
|
#include "adapter.h"
|
|
#include "protos.h"
|
|
|
|
|
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
//
|
|
// Routine Name: NetFlexAddMulticasts
|
|
//
|
|
// Description:
|
|
// This routine adds a Multicast address to
|
|
// the adapter if it has not already been added.
|
|
//
|
|
// Input:
|
|
// acb - Our Driver Context for this adapter or head.
|
|
//
|
|
// Output:
|
|
//
|
|
// Called By: NetFlexSetInformation
|
|
//
|
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
NDIS_STATUS NetFlexAddMulticasts(
|
|
PACB acb,
|
|
PSCBREQ *ScbHead,
|
|
PSCBREQ *ScbTail
|
|
)
|
|
{
|
|
NDIS_STATUS Status;
|
|
PETH_OBJS ethobjs;
|
|
PSCBREQ scbreq;
|
|
USHORT j;
|
|
PUCHAR addr;
|
|
|
|
//
|
|
// Set ethobjs to the special objects...
|
|
//
|
|
ethobjs = (PETH_OBJS)acb->acb_spec_objs;
|
|
|
|
//
|
|
// Loop through the multicast table, and send them to the card
|
|
//
|
|
for (j = 0; j < ethobjs->NumberOfEntries; j++)
|
|
{
|
|
//
|
|
// Get an SCB.
|
|
//
|
|
Status = NetFlexDequeue_OnePtrQ_Head(
|
|
(PVOID *)(&acb->acb_scbreq_free),
|
|
(PVOID *)&scbreq
|
|
);
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
DebugPrint(
|
|
0,
|
|
("NF(%d): Add Multicast, Ran out of SCB's!\n",
|
|
acb->anum)
|
|
);
|
|
|
|
return(NDIS_STATUS_FAILURE);
|
|
}
|
|
|
|
//
|
|
// Add Multicast entry to card
|
|
//
|
|
addr = ethobjs->MulticastEntries + (j * NET_ADDR_SIZE);
|
|
|
|
DebugPrint(
|
|
1, ("NF(%d): Adding %02x-%02x-%02x-%02x-%02x-%02x to Multicast Table\n",
|
|
acb->anum, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]));
|
|
|
|
scbreq->req_scb.SCB_Cmd = TMS_MULTICAST;
|
|
scbreq->req_macreq = NULL;
|
|
scbreq->req_multi.MB_Option = MPB_ADD_ADDRESS;
|
|
scbreq->req_multi.MB_Addr_Hi = *((PUSHORT) addr);
|
|
scbreq->req_multi.MB_Addr_Med = *((PUSHORT)(addr + 2));
|
|
scbreq->req_multi.MB_Addr_Lo = *((PUSHORT)(addr + 4));
|
|
|
|
//
|
|
// Queue the scb.
|
|
//
|
|
NetFlexEnqueue_TwoPtrQ_Tail(ScbHead, ScbTail, scbreq);
|
|
}
|
|
|
|
return(NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
//
|
|
// Routine Name: NetFlexDeleteMulticast
|
|
//
|
|
// Description:
|
|
// This routine removes the multicast address from the
|
|
// enabled multicast lists.
|
|
//
|
|
// Input:
|
|
// acb - Our Driver Context for this adapter or head.
|
|
//
|
|
// Output:
|
|
// Status - SUCCESS | FAILURE
|
|
//
|
|
// Called By:
|
|
// NetFlexSetInformation
|
|
//
|
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
NDIS_STATUS NetFlexDeleteMulticast(
|
|
PACB acb,
|
|
PSCBREQ *ScbHead,
|
|
PSCBREQ *ScbTail
|
|
)
|
|
{
|
|
NDIS_STATUS Status;
|
|
PSCBREQ scbreq;
|
|
|
|
DebugPrint(1, ("NF(%d): Delete Multicast Table\n", acb->anum));
|
|
|
|
//
|
|
// Get a free SCBReq block.
|
|
//
|
|
Status = NetFlexDequeue_OnePtrQ_Head(
|
|
(PVOID *)&(acb->acb_scbreq_free),
|
|
(PVOID *)&scbreq
|
|
);
|
|
if (Status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
// Queue SCB to process request
|
|
//
|
|
scbreq->req_scb.SCB_Cmd = TMS_MULTICAST;
|
|
scbreq->req_macreq = NULL;
|
|
scbreq->req_multi.MB_Option = MPB_CLEAR_ALL;
|
|
|
|
NetFlexEnqueue_TwoPtrQ_Tail(ScbHead, ScbTail, scbreq);
|
|
}
|
|
else
|
|
{
|
|
DebugPrint(0,("NF(%d): Delete Multicast Table, Ran out of SCB's!\n",acb->anum));
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
NDIS_STATUS PromiscuousFilterChanged(
|
|
PACB acb,
|
|
ULONG Filter,
|
|
PSCBREQ *ScbHead,
|
|
PSCBREQ *ScbTail
|
|
)
|
|
{
|
|
NDIS_STATUS Status;
|
|
PSCBREQ scbreq;
|
|
ULONG open_options;
|
|
|
|
// Modify the open options to set COPY ALL FRAMES (promiscuous)
|
|
//
|
|
Status = NetFlexDequeue_OnePtrQ_Head(
|
|
(PVOID *)&(acb->acb_scbreq_free),
|
|
(PVOID *)&scbreq
|
|
);
|
|
if (Status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
//
|
|
// Queue SCB to process request
|
|
//
|
|
scbreq->req_scb.SCB_Cmd = TMS_MODIFYOPEN;
|
|
scbreq->req_macreq = NULL;
|
|
|
|
//
|
|
// Set the open options for ethernet and token ring.
|
|
//
|
|
open_options = OOPTS_CNMAC;
|
|
if (acb->acb_gen_objs.media_type_in_use == NdisMedium802_5)
|
|
open_options |= OOPTS_CMAC;
|
|
|
|
//
|
|
// If we are turning it on, set the copy all frame bit
|
|
// bit, else turn it off.
|
|
//
|
|
if (Filter & NDIS_PACKET_TYPE_PROMISCUOUS)
|
|
{
|
|
//
|
|
// Turn on promiscuous mode.
|
|
//
|
|
acb->acb_opnblk_virtptr->OPEN_Options |= SWAPS((USHORT)open_options);
|
|
scbreq->req_scb.SCB_Ptr = acb->acb_opnblk_virtptr->OPEN_Options;
|
|
|
|
DebugPrint(1,("NF(%d): FilterChanged: Turn Promiscous Mode ON...\n",acb->anum));
|
|
acb->acb_promiscuousmode++;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Turn off promiscuous mode.
|
|
//
|
|
acb->acb_opnblk_virtptr->OPEN_Options &= SWAPS((USHORT)~open_options);
|
|
scbreq->req_scb.SCB_Ptr = acb->acb_opnblk_virtptr->OPEN_Options;
|
|
|
|
DebugPrint(1,("NF(%d): FilterChanged: Turn Promiscous Mode OFF...\n",acb->anum));
|
|
acb->acb_promiscuousmode--;
|
|
}
|
|
|
|
//
|
|
// Queue the scb to be sent.
|
|
//
|
|
NetFlexEnqueue_TwoPtrQ_Tail(ScbHead, ScbTail, scbreq);
|
|
}
|
|
else
|
|
{
|
|
DebugPrint(0, ("NF(%d): Change Promiscuous mode, ran out of SCB's\n", acb->anum));
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
NDIS_STATUS AllMulticastFilterChanged(
|
|
PACB acb,
|
|
ULONG Filter,
|
|
PSCBREQ *ScbHead,
|
|
PSCBREQ *ScbTail
|
|
)
|
|
{
|
|
NDIS_STATUS Status;
|
|
PSCBREQ scbreq;
|
|
PETH_OBJS ethobjs = acb->acb_spec_objs;
|
|
|
|
//
|
|
// Get a free SCBReq block.
|
|
//
|
|
Status = NetFlexDequeue_OnePtrQ_Head(
|
|
(PVOID *)&(acb->acb_scbreq_free),
|
|
(PVOID *)&scbreq
|
|
);
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
DebugPrint(0, ("NF(%d): AllMulticastFilterChanged(), Ran out of SCB's!\n",acb->anum));
|
|
return(Status);
|
|
}
|
|
|
|
//
|
|
// Turning All_Multicast On?
|
|
//
|
|
if (Filter & NDIS_PACKET_TYPE_ALL_MULTICAST)
|
|
{
|
|
DebugPrint(1,("NF(%d): FilterChanged: Turn ALL_Multicast ON...\n",acb->anum));
|
|
|
|
// Queue SCB to process request
|
|
//
|
|
scbreq->req_scb.SCB_Cmd = TMS_MULTICAST;
|
|
scbreq->req_macreq = NULL;
|
|
scbreq->req_multi.MB_Option = MPB_SET_ALL;
|
|
|
|
//
|
|
// Queue the scb to be sent.
|
|
//
|
|
NetFlexEnqueue_TwoPtrQ_Tail(ScbHead, ScbTail, scbreq);
|
|
}
|
|
else
|
|
{
|
|
// Turn All_Multicast Off.
|
|
//
|
|
DebugPrint(1,("NF(%d): FilterChanged: Turn ALL_Multicast OFF, delete all\n",acb->anum));
|
|
|
|
//
|
|
// Set up the scb to turn off ALL_MULTICAST.
|
|
//
|
|
scbreq->req_scb.SCB_Cmd = TMS_MULTICAST;
|
|
scbreq->req_macreq = NULL;
|
|
scbreq->req_multi.MB_Option = MPB_CLEAR_ALL;
|
|
|
|
//
|
|
// Queue the scb to be sent.
|
|
//
|
|
NetFlexEnqueue_TwoPtrQ_Tail(ScbHead, ScbTail, scbreq);
|
|
|
|
//
|
|
// Is Multicast on?
|
|
//
|
|
if (Filter & NDIS_PACKET_TYPE_MULTICAST)
|
|
{
|
|
//
|
|
// Yes, we need to re-enable all of the entries...
|
|
// The call to delete the multicast address above
|
|
// will determine if a completion is queued.
|
|
//
|
|
if (ethobjs->NumberOfEntries > 0)
|
|
NetFlexAddMulticasts(acb, ScbHead, ScbTail);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Multicast isn't enabled, and we deleted them, so indicate
|
|
// that we also removed the multicast entries.
|
|
//
|
|
ethobjs->NumberOfEntries = 0;
|
|
}
|
|
}
|
|
|
|
return(NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
NDIS_STATUS MulticastFilterChanged(
|
|
PACB acb,
|
|
ULONG Filter,
|
|
PSCBREQ *ScbHead,
|
|
PSCBREQ *ScbTail
|
|
)
|
|
{
|
|
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
|
PSCBREQ scbreq;
|
|
PETH_OBJS ethobjs;
|
|
|
|
//
|
|
// If the ALL_MULTICAST filter bit is set then we don't need to
|
|
// turn on/off the MULTICAST crap. We will save the current filter
|
|
// options with the ACB in the calling routine so that we know
|
|
// to turn on the MULTICAST addresses when the ALL_MULTICAST bit
|
|
// is cleared.
|
|
//
|
|
if (Filter & NDIS_PACKET_TYPE_ALL_MULTICAST)
|
|
return(NDIS_STATUS_SUCCESS);
|
|
|
|
//
|
|
// Get a pointer to the ethernet objecst.
|
|
//
|
|
ethobjs = acb->acb_spec_objs;
|
|
|
|
//
|
|
// Are we turning the MULTICAST bit on or off?
|
|
//
|
|
if (Filter & NDIS_PACKET_TYPE_MULTICAST)
|
|
{
|
|
DebugPrint(1,("NF(%d): FilterChanged: Turn multicast ON...\n",acb->anum));
|
|
|
|
//
|
|
// Do we have any entries to enable?
|
|
//
|
|
if (ethobjs->NumberOfEntries > 0)
|
|
Status = NetFlexAddMulticasts(acb, ScbHead, ScbTail);
|
|
}
|
|
else
|
|
{
|
|
DebugPrint(1,("NF(%d): FilterChanged: Turn multicast OFF, delete all\n", acb->anum));
|
|
|
|
//
|
|
// Have any to delete?
|
|
//
|
|
if (ethobjs->NumberOfEntries > 0)
|
|
Status = NetFlexDeleteMulticast(acb, ScbHead, ScbTail);
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
//
|
|
// Routine Name: NetFlexSetInformation
|
|
//
|
|
// Description:
|
|
// NetFlexSetInformation handles a set operation for a
|
|
// single OID.
|
|
//
|
|
// Input:
|
|
// MiniportAdapterContext - Our Driver Context for
|
|
// this adapter or head.
|
|
//
|
|
// Oid - The OID of the set.
|
|
//
|
|
// InformationBuffer - Holds the data to be set.
|
|
//
|
|
// InformationBufferLength - The length of InformationBuffer.
|
|
//
|
|
// Output:
|
|
//
|
|
// BytesRead - If the call is successful, returns the number
|
|
// of bytes read from InformationBuffer.
|
|
//
|
|
// BytesNeeded - If there is not enough data in OvbBuffer
|
|
// to satisfy the OID, returns the amount of
|
|
// storage needed.
|
|
// Status
|
|
//
|
|
// Called By:
|
|
// Miniport Wrapper
|
|
//
|
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
NDIS_STATUS NetFlexSetInformation(
|
|
IN NDIS_HANDLE MiniportAdapterContext,
|
|
IN NDIS_OID Oid,
|
|
IN PVOID InformationBuffer,
|
|
IN ULONG InformationBufferLength,
|
|
OUT PULONG BytesRead,
|
|
OUT PULONG BytesNeeded
|
|
)
|
|
{
|
|
ULONG value;
|
|
PMACREQ macreq;
|
|
PETH_OBJS ethobjs;
|
|
PTR_OBJS trobjs;
|
|
PSCBREQ scbreq;
|
|
PSCBREQ ScbHead = NULL;
|
|
PSCBREQ ScbTail = NULL;
|
|
ULONG Filter;
|
|
ULONG BadFilter;
|
|
BOOLEAN QueueCompletion = FALSE;
|
|
BOOLEAN QueueCleanup = FALSE;
|
|
|
|
PACB acb = (PACB) MiniportAdapterContext;
|
|
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
|
|
|
*BytesRead = 0;
|
|
*BytesNeeded = 0;
|
|
|
|
if (acb->acb_state == AS_RESETTING)
|
|
{
|
|
return(NDIS_STATUS_RESET_IN_PROGRESS);
|
|
}
|
|
|
|
if (acb->RequestInProgress)
|
|
{
|
|
DebugPrint(0,("NF(%d): SetOID: Aready have RequestInProcess!\n",acb->anum));
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
acb->RequestInProgress = TRUE;
|
|
|
|
//
|
|
// Save the information about the request
|
|
//
|
|
acb->BytesRead = BytesRead;
|
|
acb->BytesNeeded = BytesNeeded;
|
|
acb->Oid = Oid;
|
|
acb->InformationBuffer = InformationBuffer;
|
|
acb->InformationBufferLength = InformationBufferLength;
|
|
|
|
switch (Oid)
|
|
{
|
|
case OID_GEN_CURRENT_PACKET_FILTER:
|
|
if (InformationBufferLength != sizeof(ULONG))
|
|
{
|
|
DebugPrint(0,("NF(%d): Bad Packet Filter\n",acb->anum));
|
|
acb->RequestInProgress = FALSE;
|
|
|
|
return(NDIS_STATUS_INVALID_DATA);
|
|
}
|
|
|
|
Filter = *(PULONG)(InformationBuffer);
|
|
DebugPrint(1,("NF(%d): OidSet: GEN_CURRENT_PACKET_FILTER = %x\n",acb->anum,Filter));
|
|
|
|
//-------------------------------------------
|
|
// Filters Common to TokenRing and Ethernet
|
|
//-------------------------------------------
|
|
|
|
#if (DBG || DBGPRINT)
|
|
if (Filter & NDIS_PACKET_TYPE_DIRECTED)
|
|
DebugPrint(1,("NF(%d): FilterChangeAction: Directed\n",acb->anum));
|
|
#endif
|
|
//
|
|
// Verify Filter
|
|
//
|
|
if ( acb->acb_gen_objs.media_type_in_use == NdisMedium802_3)
|
|
{
|
|
//--------------------------------
|
|
// Ethernet Specific Filters...
|
|
//--------------------------------
|
|
//
|
|
// accept only the following:
|
|
//
|
|
BadFilter = (ULONG)~(NDIS_PACKET_TYPE_DIRECTED |
|
|
NDIS_PACKET_TYPE_MULTICAST |
|
|
NDIS_PACKET_TYPE_ALL_MULTICAST |
|
|
NDIS_PACKET_TYPE_BROADCAST |
|
|
(acb->FullDuplexEnabled ?
|
|
0 : NDIS_PACKET_TYPE_PROMISCUOUS)
|
|
);
|
|
if (Filter & BadFilter)
|
|
{
|
|
DebugPrint(1,("NF(%d): PacketFilter Not Supported\n",acb->anum));
|
|
|
|
*BytesRead = sizeof(ULONG);
|
|
acb->RequestInProgress = FALSE;
|
|
|
|
Status = NDIS_STATUS_NOT_SUPPORTED;
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Did the state of the ALL_MULTICAST bit change?
|
|
//
|
|
if ((acb->acb_gen_objs.cur_filter & NDIS_PACKET_TYPE_ALL_MULTICAST) ^
|
|
(Filter & NDIS_PACKET_TYPE_ALL_MULTICAST)
|
|
)
|
|
{
|
|
Status = AllMulticastFilterChanged(
|
|
acb,
|
|
Filter,
|
|
&ScbHead,
|
|
&ScbTail
|
|
);
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
//
|
|
// We might need to cleanup the local
|
|
// queue of SCBs.
|
|
//
|
|
QueueCleanup = TRUE;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// We successfully changed the ALL_MULTICAST bit.
|
|
//
|
|
QueueCompletion = TRUE;
|
|
}
|
|
|
|
//
|
|
// Did the state of the MULTICAST bit change?
|
|
//
|
|
if ((acb->acb_gen_objs.cur_filter & NDIS_PACKET_TYPE_MULTICAST) ^
|
|
(Filter & NDIS_PACKET_TYPE_MULTICAST)
|
|
)
|
|
{
|
|
Status = MulticastFilterChanged(
|
|
acb,
|
|
Filter,
|
|
&ScbHead,
|
|
&ScbTail
|
|
);
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
//
|
|
// We might need to cleanup the local
|
|
// queue of SCBs.
|
|
//
|
|
QueueCleanup = TRUE;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// We successfully changed the MULTICAST bit.
|
|
//
|
|
QueueCompletion = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//-------------------------------
|
|
// Token Ring Specific Filters...
|
|
//-------------------------------
|
|
//
|
|
// accept all of the following:
|
|
//
|
|
BadFilter = (ULONG)~(NDIS_PACKET_TYPE_FUNCTIONAL |
|
|
NDIS_PACKET_TYPE_ALL_FUNCTIONAL |
|
|
NDIS_PACKET_TYPE_GROUP |
|
|
NDIS_PACKET_TYPE_DIRECTED |
|
|
NDIS_PACKET_TYPE_BROADCAST |
|
|
NDIS_PACKET_TYPE_PROMISCUOUS
|
|
);
|
|
if (Filter & BadFilter)
|
|
{
|
|
DebugPrint(1,("NF(%d): PacketFilter Not Supported\n",acb->anum));
|
|
|
|
*BytesRead = sizeof(ULONG);
|
|
|
|
acb->RequestInProgress = FALSE;
|
|
|
|
Status = NDIS_STATUS_NOT_SUPPORTED;
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Are we turning the All Functional address filter on or off?
|
|
//
|
|
if (((acb->acb_gen_objs.cur_filter & NDIS_PACKET_TYPE_ALL_FUNCTIONAL) ^
|
|
(Filter & NDIS_PACKET_TYPE_ALL_FUNCTIONAL)) ||
|
|
((acb->acb_gen_objs.cur_filter & NDIS_PACKET_TYPE_FUNCTIONAL) ^
|
|
(Filter & NDIS_PACKET_TYPE_FUNCTIONAL))
|
|
)
|
|
{
|
|
//
|
|
// We are changing it. Are we turning it on?
|
|
// Set functional address to all functional address
|
|
//
|
|
// Get a free SCBReq block.
|
|
//
|
|
Status = NetFlexDequeue_OnePtrQ_Head(
|
|
(PVOID *)&(acb->acb_scbreq_free),
|
|
(PVOID *)&scbreq
|
|
);
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
//
|
|
// We failed to get an scb. We don't need
|
|
// to cleanup the scb queue since this is the
|
|
// first one.
|
|
//
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Queue SCB to process request
|
|
//
|
|
scbreq->req_scb.SCB_Cmd = TMS_SETFUNCT;
|
|
scbreq->req_macreq = NULL;
|
|
|
|
//
|
|
// If we are turning it on, set the functional address
|
|
// to all ones, else set it to the acb's functional
|
|
// address.
|
|
//
|
|
if (Filter & NDIS_PACKET_TYPE_ALL_FUNCTIONAL)
|
|
{
|
|
scbreq->req_scb.SCB_Ptr = SWAPL(0x7fffffff);
|
|
}
|
|
else
|
|
{
|
|
if (Filter & NDIS_PACKET_TYPE_FUNCTIONAL)
|
|
{
|
|
scbreq->req_scb.SCB_Ptr =
|
|
*((PLONG)(((PTR_OBJS)(acb->acb_spec_objs))->cur_func_addr));
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// clear it
|
|
//
|
|
scbreq->req_scb.SCB_Ptr = 0;
|
|
}
|
|
}
|
|
|
|
DebugPrint(1,("NF(%d): FilterChanged: Setting Functional Address =0x%x\n",acb->anum,scbreq->req_scb.SCB_Ptr));
|
|
|
|
//
|
|
// Queue the scb.
|
|
//
|
|
NetFlexEnqueue_TwoPtrQ_Tail(&ScbHead, &ScbTail, scbreq);
|
|
|
|
//
|
|
// Indicate we need to QueueCompletion MacReq
|
|
//
|
|
QueueCompletion = TRUE;
|
|
}
|
|
|
|
//
|
|
// Changing Group?
|
|
//
|
|
if ((acb->acb_gen_objs.cur_filter & NDIS_PACKET_TYPE_GROUP) ^
|
|
(Filter & NDIS_PACKET_TYPE_GROUP)
|
|
)
|
|
{
|
|
// Get a free SCBReq block.
|
|
//
|
|
Status = NetFlexDequeue_OnePtrQ_Head(
|
|
(PVOID *)&(acb->acb_scbreq_free),
|
|
(PVOID *)&scbreq
|
|
);
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
//
|
|
// We might need to cleanup the local
|
|
// queue of SCBs.
|
|
//
|
|
QueueCleanup = TRUE;
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Queue SCB to process request
|
|
//
|
|
scbreq->req_scb.SCB_Cmd = TMS_SETGROUP;
|
|
scbreq->req_macreq = NULL;
|
|
|
|
//
|
|
// Set or Clear the Group Address?
|
|
//
|
|
if (Filter & NDIS_PACKET_TYPE_GROUP)
|
|
{
|
|
scbreq->req_scb.SCB_Ptr =
|
|
*((PLONG)(((PTR_OBJS)(acb->acb_spec_objs))->cur_grp_addr));
|
|
}
|
|
else
|
|
{
|
|
scbreq->req_scb.SCB_Ptr = 0;
|
|
}
|
|
|
|
DebugPrint(1,("NF(%d): FilterChanged: Setting Group Address =0x%x\n",acb->anum,scbreq->req_scb.SCB_Ptr));
|
|
|
|
//
|
|
// Queue the scb.
|
|
//
|
|
NetFlexEnqueue_TwoPtrQ_Tail(&ScbHead, &ScbTail, scbreq);
|
|
|
|
//
|
|
// Indicate we need to QueueCompletion MacReq
|
|
//
|
|
QueueCompletion = TRUE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Did the state of the PROMISCUOUS flag change?
|
|
//
|
|
if ((acb->acb_gen_objs.cur_filter & NDIS_PACKET_TYPE_PROMISCUOUS) ^
|
|
(Filter & NDIS_PACKET_TYPE_PROMISCUOUS)
|
|
)
|
|
{
|
|
Status = PromiscuousFilterChanged(
|
|
acb,
|
|
Filter,
|
|
&ScbHead,
|
|
&ScbTail
|
|
);
|
|
if (NDIS_STATUS_SUCCESS != Status)
|
|
{
|
|
//
|
|
// We might need to cleanup the local
|
|
// queue of SCBs.
|
|
//
|
|
QueueCleanup = TRUE;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// We successfully changed the PROMISCUOUS bit.
|
|
//
|
|
QueueCompletion = TRUE;
|
|
}
|
|
|
|
acb->acb_gen_objs.cur_filter = Filter;
|
|
*BytesRead = InformationBufferLength;
|
|
|
|
break;
|
|
|
|
case OID_802_3_MULTICAST_LIST:
|
|
|
|
//
|
|
// Is the adapter setup for token ring?
|
|
//
|
|
if (acb->acb_gen_objs.media_type_in_use == NdisMedium802_5 )
|
|
{
|
|
//
|
|
// Token ring does not support multicast.
|
|
//
|
|
DebugPrint(0,("NF(%d): MULTICAST LIST INVALID OID\n",acb->anum));
|
|
*BytesRead = 0;
|
|
acb->RequestInProgress = FALSE;
|
|
|
|
Status = NDIS_STATUS_NOT_SUPPORTED;
|
|
|
|
break;
|
|
}
|
|
|
|
if (InformationBufferLength % NET_ADDR_SIZE != 0)
|
|
{
|
|
//
|
|
// The data must be a multiple of the Ethernet address size.
|
|
//
|
|
DebugPrint(0,("NF(%d): MULTICAST LIST INVALID LENGTH\n",acb->anum));
|
|
|
|
*BytesNeeded = InformationBufferLength + (NET_ADDR_SIZE - (InformationBufferLength % NET_ADDR_SIZE));
|
|
acb->RequestInProgress = FALSE;
|
|
|
|
Status = NDIS_STATUS_INVALID_DATA;
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Get a pointer to the ethernet objects.
|
|
//
|
|
ethobjs = (PETH_OBJS)(acb->acb_spec_objs);
|
|
scbreq = NULL;
|
|
|
|
value = (InformationBufferLength / NET_ADDR_SIZE );
|
|
|
|
if (value > ethobjs->MaxMulticast)
|
|
{
|
|
DebugPrint(0,("NF(%d): TOO MANY MULTICAST ADDRESSES\n",acb->anum));
|
|
|
|
//
|
|
// There are too many, but add as many as we can.
|
|
//
|
|
acb->RequestInProgress = FALSE;
|
|
|
|
Status = NDIS_STATUS_MULTICAST_FULL;
|
|
|
|
break;
|
|
}
|
|
|
|
DebugPrint(1, ("NF(%d): Saving multicast address\n", acb->anum));
|
|
|
|
//
|
|
// Save entries in the table.
|
|
//
|
|
NdisMoveMemory(
|
|
ethobjs->MulticastEntries,
|
|
InformationBuffer,
|
|
value * NET_ADDR_SIZE
|
|
);
|
|
|
|
//
|
|
// If we have any entries enabled, delete them,
|
|
// unless NDIS_PACKET_TYPE_ALL_MULTICAST is set.
|
|
//
|
|
if (!(acb->acb_gen_objs.cur_filter & NDIS_PACKET_TYPE_ALL_MULTICAST) &&
|
|
(ethobjs->NumberOfEntries > 0)
|
|
)
|
|
{
|
|
//
|
|
// Get a free SCBReq block.
|
|
//
|
|
Status = NetFlexDequeue_OnePtrQ_Head(
|
|
(PVOID *)&(acb->acb_scbreq_free),
|
|
(PVOID *)&scbreq
|
|
);
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
DebugPrint(0,("NF(%d): MULTICAST_LIST: out of SCBs\n", acb->anum));
|
|
|
|
//
|
|
// Since this is the first SCB, and it failed,
|
|
// we don't need to clean up.
|
|
//
|
|
break;
|
|
}
|
|
|
|
DebugPrint(1,("NF(%d): MULTICAST_LIST: clearing current list\n", acb->anum));
|
|
|
|
// Queue SCB to process request
|
|
//
|
|
scbreq->req_scb.SCB_Cmd = TMS_MULTICAST;
|
|
scbreq->req_macreq = NULL;
|
|
scbreq->req_multi.MB_Option = MPB_CLEAR_ALL;
|
|
|
|
//
|
|
// Queue the scb.
|
|
//
|
|
NetFlexEnqueue_TwoPtrQ_Tail(&ScbHead, &ScbTail, scbreq);
|
|
|
|
//
|
|
// Indicate we need to a Queue MacReq Completion
|
|
//
|
|
QueueCompletion = TRUE;
|
|
}
|
|
|
|
//
|
|
// Save number of entrys
|
|
//
|
|
ethobjs->NumberOfEntries = (SHORT)value;
|
|
|
|
//
|
|
// If filter has NDIS_PACKET_TYPE_MULTICAST, but NOT
|
|
// NDIS_PACKET_TYPE_ALL_MULTICAST, then enable these entries now.
|
|
//
|
|
if ((acb->acb_gen_objs.cur_filter & NDIS_PACKET_TYPE_MULTICAST) &&
|
|
!(acb->acb_gen_objs.cur_filter & NDIS_PACKET_TYPE_ALL_MULTICAST)
|
|
)
|
|
{
|
|
if (ethobjs->NumberOfEntries > 0)
|
|
{
|
|
Status = NetFlexAddMulticasts(acb, &ScbHead, &ScbTail);
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
//
|
|
// Cleanup the local SCB queue.
|
|
//
|
|
QueueCleanup = TRUE;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Indicate we need to a Queue MacReq Completion
|
|
//
|
|
QueueCompletion = TRUE;
|
|
}
|
|
}
|
|
|
|
*BytesRead = InformationBufferLength;
|
|
|
|
break;
|
|
|
|
case OID_GEN_CURRENT_LOOKAHEAD:
|
|
//
|
|
// We don't set anything, just return ok. - RVC true?
|
|
//
|
|
*BytesRead = 4;
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
DebugPrint(1,("NF(%d): OID_GEN_CURRENT_LOOKAHEAD...\n",acb->anum));
|
|
|
|
break;
|
|
|
|
|
|
case OID_802_5_CURRENT_FUNCTIONAL:
|
|
if (acb->acb_gen_objs.media_type_in_use == NdisMedium802_3)
|
|
{
|
|
//
|
|
// If we are running Ethernet, a call for this oid is an error.
|
|
//
|
|
acb->RequestInProgress = FALSE;
|
|
|
|
Status = NDIS_STATUS_NOT_SUPPORTED;
|
|
|
|
break;
|
|
}
|
|
|
|
if (InformationBufferLength != TR_LENGTH_OF_FUNCTIONAL )
|
|
{
|
|
DebugPrint(0,("NF(%d): Oid_Set Functional Address bad\n",acb->anum));
|
|
*BytesNeeded = TR_LENGTH_OF_FUNCTIONAL - InformationBufferLength;
|
|
|
|
acb->RequestInProgress = FALSE;
|
|
|
|
Status = NDIS_STATUS_INVALID_LENGTH;
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Get the oid info.
|
|
//
|
|
NdisMoveMemory(
|
|
(PVOID)&value,
|
|
InformationBuffer,
|
|
TR_LENGTH_OF_FUNCTIONAL
|
|
);
|
|
|
|
//
|
|
// Get a pointer to the token ring objects.
|
|
//
|
|
trobjs = (PTR_OBJS)(acb->acb_spec_objs);
|
|
|
|
*((PULONG)(trobjs->cur_func_addr)) = value;
|
|
|
|
DebugPrint(1,("NF(%d): OidSet Functional Address = %08x\n",acb->anum,value));
|
|
|
|
//
|
|
// Update filter if the funcational address has been set in
|
|
// the packet filter.
|
|
//
|
|
if (!(acb->acb_gen_objs.cur_filter & NDIS_PACKET_TYPE_ALL_FUNCTIONAL) &&
|
|
(acb->acb_gen_objs.cur_filter & NDIS_PACKET_TYPE_FUNCTIONAL)
|
|
)
|
|
{
|
|
//
|
|
// Get an scb.
|
|
//
|
|
Status = NetFlexDequeue_OnePtrQ_Head(
|
|
(PVOID *)&(acb->acb_scbreq_free),
|
|
(PVOID *)&scbreq
|
|
);
|
|
if (Status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
scbreq->req_scb.SCB_Cmd = TMS_SETFUNCT;
|
|
scbreq->req_macreq = NULL;
|
|
scbreq->req_scb.SCB_Ptr = value;
|
|
|
|
//
|
|
// Queue the scb.
|
|
//
|
|
NetFlexEnqueue_TwoPtrQ_Tail(&ScbHead, &ScbTail, scbreq);
|
|
|
|
QueueCompletion = TRUE;
|
|
}
|
|
}
|
|
|
|
*BytesRead = TR_LENGTH_OF_FUNCTIONAL;
|
|
break;
|
|
|
|
case OID_802_5_CURRENT_GROUP:
|
|
if (acb->acb_gen_objs.media_type_in_use == NdisMedium802_3 )
|
|
{
|
|
// If we are running Ethernet, a call for this oid is an error.
|
|
//
|
|
acb->RequestInProgress = FALSE;
|
|
|
|
Status = NDIS_STATUS_NOT_SUPPORTED;
|
|
|
|
break;
|
|
}
|
|
|
|
if (InformationBufferLength != TR_LENGTH_OF_FUNCTIONAL)
|
|
{
|
|
DebugPrint(0,("NF(%d): OidSet Group Address BAD\n",acb->anum));
|
|
*BytesNeeded = TR_LENGTH_OF_FUNCTIONAL - InformationBufferLength;
|
|
|
|
acb->RequestInProgress = FALSE;
|
|
Status = NDIS_STATUS_INVALID_LENGTH;
|
|
|
|
break;
|
|
}
|
|
|
|
NdisMoveMemory(
|
|
(PVOID)&value,
|
|
InformationBuffer,
|
|
TR_LENGTH_OF_FUNCTIONAL
|
|
);
|
|
|
|
trobjs = (PTR_OBJS)(acb->acb_spec_objs);
|
|
|
|
*((PULONG)(trobjs->cur_grp_addr)) = value;
|
|
|
|
DebugPrint(1,("NF(%d): OidSet Group Address = %08x\n",acb->anum,value));
|
|
|
|
//
|
|
// Update filter if the group address has been set in
|
|
// the packet filter.
|
|
//
|
|
if ((acb->acb_gen_objs.cur_filter & NDIS_PACKET_TYPE_GROUP) != 0)
|
|
{
|
|
Status = NetFlexDequeue_OnePtrQ_Head(
|
|
(PVOID *)&(acb->acb_scbreq_free),
|
|
(PVOID *)&scbreq
|
|
);
|
|
if (Status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
scbreq->req_scb.SCB_Cmd = TMS_SETGROUP;
|
|
scbreq->req_macreq = NULL;
|
|
scbreq->req_scb.SCB_Ptr = value;
|
|
|
|
//
|
|
// Queue the scb.
|
|
//
|
|
NetFlexEnqueue_TwoPtrQ_Tail(&ScbHead, &ScbTail, scbreq);
|
|
|
|
QueueCompletion = TRUE;
|
|
}
|
|
}
|
|
|
|
*BytesRead = TR_LENGTH_OF_FUNCTIONAL;
|
|
break;
|
|
|
|
default:
|
|
|
|
Status = NDIS_STATUS_INVALID_OID;
|
|
break;
|
|
|
|
}
|
|
|
|
if (QueueCleanup)
|
|
{
|
|
DebugPrint(1,("NF(%d): Error Setting OID (0x%x)\n",acb->anum, Oid));
|
|
|
|
//
|
|
// There was an error trying to get sufficent SCBs to
|
|
// complete the request.
|
|
//
|
|
while (ScbHead != NULL)
|
|
{
|
|
NetFlexDequeue_OnePtrQ_Head(&ScbHead, &scbreq);
|
|
|
|
NetFlexEnqueue_OnePtrQ_Head(
|
|
(PVOID *)&acb->acb_scbreq_free,
|
|
scbreq
|
|
);
|
|
}
|
|
|
|
QueueCompletion = FALSE;
|
|
}
|
|
|
|
if (QueueCompletion)
|
|
{
|
|
//
|
|
// Was there actually an scb queued?
|
|
//
|
|
if (NULL != ScbHead)
|
|
{
|
|
//
|
|
// We should have a local list of scb's to send.
|
|
//
|
|
do
|
|
{
|
|
//
|
|
// Get a pointer to the next scb to process.
|
|
//
|
|
scbreq = ScbHead->req_next;
|
|
|
|
//
|
|
// Are we on the last scb?
|
|
//
|
|
if (NULL == scbreq)
|
|
{
|
|
//
|
|
// Get a mac request in case we need the completeion
|
|
//
|
|
NetFlexDequeue_OnePtrQ_Head(
|
|
(PVOID *)&(acb->acb_macreq_free),
|
|
(PVOID *)¯eq
|
|
);
|
|
|
|
//
|
|
// Initialize the completion request.
|
|
//
|
|
macreq->req_next = NULL;
|
|
macreq->req_type = REQUEST_CMP;
|
|
macreq->req_status = NDIS_STATUS_SUCCESS;
|
|
|
|
//
|
|
// Setup the last scb to be sent to the card.
|
|
//
|
|
ScbHead->req_macreq = macreq;
|
|
|
|
//
|
|
// put the macreq on the macreq queue
|
|
//
|
|
NetFlexEnqueue_TwoPtrQ_Tail(
|
|
(PVOID *)&(acb->acb_macreq_head),
|
|
(PVOID *)&(acb->acb_macreq_tail),
|
|
(PVOID)macreq
|
|
);
|
|
}
|
|
|
|
//
|
|
// Send the scb down to the card
|
|
//
|
|
NetFlexQueueSCB(acb, ScbHead);
|
|
|
|
ScbHead = scbreq;
|
|
|
|
} while (NULL != scbreq);
|
|
|
|
return(NDIS_STATUS_PENDING);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Request was aborted due to error.
|
|
//
|
|
acb->RequestInProgress = FALSE;
|
|
|
|
return(Status);
|
|
}
|
|
|
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
//
|
|
// Routine Name: NetFlexQueryInformation
|
|
//
|
|
// Description:
|
|
// The NetFlexQueryInformation process a Query request for
|
|
// NDIS_OIDs that are specific about the Driver.
|
|
//
|
|
// Input:
|
|
// MiniportAdapterContext - Our Driver Context for this
|
|
// adapter or head.
|
|
//
|
|
// Oid - the NDIS_OID to process.
|
|
//
|
|
// InformationBuffer - a pointer into the NdisRequest->InformationBuffer
|
|
// into which store the result of the query.
|
|
//
|
|
// InformationBufferLength - a pointer to the number of bytes left in the
|
|
// InformationBuffer.
|
|
//
|
|
// Output:
|
|
// BytesWritten - a pointer to the number of bytes written into the
|
|
// InformationBuffer.
|
|
//
|
|
// BytesNeeded - If there is not enough room in the information buffer
|
|
// then this will contain the number of bytes needed to complete the
|
|
// request.
|
|
//
|
|
// Status - The function value is the Status of the operation.
|
|
//
|
|
// Called By:
|
|
// Miniport Wrapper
|
|
//
|
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
NDIS_STATUS
|
|
NetFlexQueryInformation(
|
|
IN NDIS_HANDLE MiniportAdapterContext,
|
|
IN NDIS_OID Oid,
|
|
IN PVOID InformationBuffer,
|
|
IN ULONG InformationBufferLength,
|
|
OUT PULONG BytesWritten,
|
|
OUT PULONG BytesNeeded
|
|
)
|
|
{
|
|
PACB acb = (PACB) MiniportAdapterContext;
|
|
PMACREQ macreq;
|
|
ULONG lvalue;
|
|
USHORT svalue;
|
|
PTR_OBJS trobjs;
|
|
PETH_OBJS ethobjs;
|
|
PUCHAR srcptr;
|
|
PUCHAR copyptr = NULL;
|
|
PSCBREQ scbreq;
|
|
UCHAR vendorid[4];
|
|
SHORT copylen = (SHORT)sizeof(ULONG); // Most common length
|
|
|
|
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
|
BOOLEAN needcopy = TRUE;
|
|
|
|
if (acb->acb_state == AS_RESETTING)
|
|
{
|
|
return(NDIS_STATUS_RESET_IN_PROGRESS);
|
|
}
|
|
|
|
//
|
|
// Initialize the result
|
|
//
|
|
*BytesWritten = 0;
|
|
*BytesNeeded = 0;
|
|
|
|
//
|
|
// General Objects Characteristics
|
|
//
|
|
|
|
switch (Oid)
|
|
{
|
|
case OID_GEN_SUPPORTED_LIST:
|
|
copyptr = (PUCHAR)acb->acb_gbl_oid_list;
|
|
copylen = (SHORT)acb->acb_gbl_oid_list_size;
|
|
DebugPrint(2,("NF: Query OID_GEN_SUPPORTED_LIST...\n",acb->anum));
|
|
break;
|
|
|
|
case OID_GEN_HARDWARE_STATUS:
|
|
lvalue = NdisHardwareStatusNotReady;
|
|
switch (acb->acb_state)
|
|
{
|
|
case AS_OPENED:
|
|
lvalue = NdisHardwareStatusReady;
|
|
DebugPrint(1,("NF(%d):Query HW Status - AS_OPENED\n",acb->anum));
|
|
break;
|
|
case AS_CLOSING:
|
|
lvalue = NdisHardwareStatusClosing;
|
|
DebugPrint(1,("NF(%d):Query HW Status - AS_CLOSING\n",acb->anum));
|
|
break;
|
|
case AS_RESETTING:
|
|
case AS_RESET_HOLDING:
|
|
DebugPrint(1,("NF(%d):Query HW Status - AS_RESETTING\n",acb->anum));
|
|
lvalue = NdisHardwareStatusReset;
|
|
break;
|
|
case AS_INITIALIZING:
|
|
DebugPrint(1,("NF(%d):Query HW Status - AS_INITIALIZING\n",acb->anum));
|
|
lvalue = NdisHardwareStatusInitializing;
|
|
break;
|
|
default:
|
|
DebugPrint(1,("NF(%d):NetFlexQueryInformation: Undefinded State - 0x%x",acb->anum,acb->acb_state));
|
|
break;
|
|
}
|
|
copyptr = (PUCHAR)&lvalue;
|
|
DebugPrint(2,("NF(%d): Query OID_GEN_HARDWARE_STATUS 0x%x...\n",acb->anum,lvalue));
|
|
break;
|
|
|
|
case OID_GEN_MEDIA_SUPPORTED:
|
|
case OID_GEN_MEDIA_IN_USE:
|
|
copyptr = (PUCHAR)&acb->acb_gen_objs.media_type_in_use;
|
|
DebugPrint(2,("NF(%d): Query OID_GEN_MEDIA_IN_USE 0x%x...\n",acb->anum,
|
|
acb->acb_gen_objs.media_type_in_use));
|
|
break;
|
|
|
|
case OID_GEN_MAXIMUM_LOOKAHEAD:
|
|
case OID_GEN_CURRENT_LOOKAHEAD:
|
|
case OID_GEN_TRANSMIT_BLOCK_SIZE:
|
|
case OID_GEN_RECEIVE_BLOCK_SIZE:
|
|
case OID_GEN_MAXIMUM_TOTAL_SIZE:
|
|
copyptr = (PUCHAR)&acb->acb_gen_objs.max_frame_size;
|
|
break;
|
|
|
|
case OID_GEN_MAXIMUM_FRAME_SIZE:
|
|
// Frame size is the max frame size minus the minimum header size.
|
|
//
|
|
lvalue = acb->acb_gen_objs.max_frame_size - 14;
|
|
copyptr = (PUCHAR)&lvalue;
|
|
break;
|
|
|
|
case OID_GEN_LINK_SPEED:
|
|
lvalue = acb->acb_gen_objs.link_speed * 10000;
|
|
copyptr = (PUCHAR)&lvalue;
|
|
break;
|
|
|
|
case OID_GEN_TRANSMIT_BUFFER_SPACE:
|
|
lvalue = acb->acb_gen_objs.max_frame_size * acb->acb_maxtrans;
|
|
copyptr = (PUCHAR)&lvalue;
|
|
break;
|
|
|
|
case OID_GEN_RECEIVE_BUFFER_SPACE:
|
|
lvalue = acb->acb_gen_objs.max_frame_size * acb->acb_maxrcvs;
|
|
copyptr = (PUCHAR)&lvalue;
|
|
break;
|
|
|
|
case OID_GEN_VENDOR_ID:
|
|
NdisMoveMemory(vendorid,acb->acb_gen_objs.perm_staddr,3);
|
|
vendorid[3] = 0x0;
|
|
copyptr = (PUCHAR)vendorid;
|
|
break;
|
|
|
|
case OID_GEN_VENDOR_DESCRIPTION:
|
|
copyptr = (PUCHAR)"Compaq NetFlex Driver, Version 1.10"; // RVC: move to string...
|
|
copylen = (USHORT)36;
|
|
break;
|
|
|
|
case OID_GEN_DRIVER_VERSION:
|
|
svalue = 0x0300;
|
|
copyptr = (PUCHAR)&svalue;
|
|
copylen = (SHORT)sizeof(USHORT);
|
|
break;
|
|
|
|
case OID_GEN_CURRENT_PACKET_FILTER:
|
|
lvalue = acb->acb_gen_objs.cur_filter;
|
|
copyptr = (PUCHAR)&lvalue;
|
|
DebugPrint(2,("NF(%d): Query OID_GEN_CURRENT_PACKET_FILTER = 0x%x\n",acb->anum,lvalue));
|
|
break;
|
|
|
|
case OID_GEN_MAC_OPTIONS:
|
|
lvalue = NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
|
|
NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
|
|
NDIS_MAC_OPTION_RECEIVE_SERIALIZED;
|
|
|
|
//
|
|
// Indicate we need loop back if running Full Duplex
|
|
//
|
|
if (acb->FullDuplexEnabled)
|
|
{
|
|
lvalue |= NDIS_MAC_OPTION_NO_LOOPBACK |
|
|
NDIS_MAC_OPTION_FULL_DUPLEX;
|
|
}
|
|
copyptr = (PUCHAR)&lvalue;
|
|
break;
|
|
|
|
//
|
|
// GENERAL STATISTICS (Mandatory)
|
|
//
|
|
|
|
case OID_GEN_XMIT_OK:
|
|
copyptr = (PUCHAR)&acb->acb_gen_objs.frames_xmitd_ok;
|
|
break;
|
|
|
|
case OID_GEN_RCV_OK:
|
|
copyptr = (PUCHAR)&acb->acb_gen_objs.frames_rcvd_ok;
|
|
break;
|
|
|
|
case OID_GEN_XMIT_ERROR:
|
|
copyptr = (PUCHAR)&acb->acb_gen_objs.frames_xmitd_err;
|
|
break;
|
|
|
|
case OID_GEN_RCV_ERROR:
|
|
copyptr = (PUCHAR)&acb->acb_gen_objs.frames_rcvd_err;
|
|
break;
|
|
|
|
case OID_NF_INTERRUPT_COUNT:
|
|
copyptr = (PUCHAR)&acb->acb_gen_objs.interrupt_count;
|
|
break;
|
|
|
|
case OID_NF_INTERRUPT_RATIO:
|
|
copyptr = (PUCHAR)&acb->RcvIntRatio;
|
|
break;
|
|
|
|
case OID_NF_INTERRUPT_RATIO_CHANGES:
|
|
copyptr = (PUCHAR)&acb->acb_gen_objs.interrupt_ratio_changes;
|
|
break;
|
|
|
|
} // end of general
|
|
|
|
if (copyptr == NULL)
|
|
{
|
|
if (acb->acb_gen_objs.media_type_in_use == NdisMedium802_3 )
|
|
{
|
|
//---------------------------------------
|
|
// Ethernet Specific Oid's
|
|
//---------------------------------------
|
|
//
|
|
|
|
switch (Oid)
|
|
{
|
|
//-------------------------------------
|
|
// 802.3 OPERATIONAL CHARACTERISTICS
|
|
//-------------------------------------
|
|
|
|
case OID_802_3_PERMANENT_ADDRESS:
|
|
srcptr = acb->acb_gen_objs.perm_staddr;
|
|
copyptr = (PUCHAR)srcptr;
|
|
copylen = (SHORT)NET_ADDR_SIZE;
|
|
|
|
case OID_802_3_CURRENT_ADDRESS:
|
|
srcptr = acb->acb_gen_objs.current_staddr;
|
|
copyptr = (PUCHAR)srcptr;
|
|
copylen = (SHORT)NET_ADDR_SIZE;
|
|
break;
|
|
|
|
case OID_802_3_MULTICAST_LIST:
|
|
DebugPrint(2,("NF(%d): Query OID_802_3_MULTICAST_LIST\n",acb->anum));
|
|
ethobjs = (PETH_OBJS)(acb->acb_spec_objs);
|
|
|
|
needcopy = TRUE;
|
|
copylen = ethobjs->NumberOfEntries * NET_ADDR_SIZE;
|
|
copyptr = (PVOID) ðobjs->NumberOfEntries;
|
|
break;
|
|
|
|
case OID_802_3_MAXIMUM_LIST_SIZE:
|
|
ethobjs = (PETH_OBJS)(acb->acb_spec_objs);
|
|
lvalue = ethobjs->MaxMulticast;
|
|
copyptr = (PUCHAR)&lvalue;
|
|
DebugPrint(2,("NF(%d): Query OID_802_3_MAXIMUM_LIST_SIZE = 0x%x\n",acb->anum,lvalue));
|
|
break;
|
|
|
|
//-------------------------------
|
|
// 802.3 STATISTICS (Mandatory)
|
|
//-------------------------------
|
|
|
|
case OID_GEN_RCV_NO_BUFFER:
|
|
lvalue = 0;
|
|
copyptr = (PUCHAR)&lvalue;
|
|
break;
|
|
|
|
case OID_802_3_RCV_ERROR_ALIGNMENT:
|
|
case OID_802_3_XMIT_ONE_COLLISION:
|
|
case OID_802_3_XMIT_MORE_COLLISIONS:
|
|
case OID_802_3_XMIT_DEFERRED:
|
|
case OID_802_3_XMIT_LATE_COLLISIONS:
|
|
case OID_802_3_XMIT_MAX_COLLISIONS:
|
|
case OID_802_3_XMIT_TIMES_CRS_LOST:
|
|
case OID_GEN_RCV_CRC_ERROR:
|
|
if (acb->acb_logbuf_valid)
|
|
{
|
|
ethobjs = (PETH_OBJS)(acb->acb_spec_objs);
|
|
|
|
switch (Oid)
|
|
{
|
|
case OID_802_3_RCV_ERROR_ALIGNMENT:
|
|
lvalue = ethobjs->RSL_AlignmentErr;
|
|
break;
|
|
case OID_802_3_XMIT_ONE_COLLISION:
|
|
lvalue = ethobjs->RSL_1_Collision;
|
|
break;
|
|
case OID_802_3_XMIT_MORE_COLLISIONS:
|
|
lvalue = ethobjs->RSL_More_Collision;
|
|
break;
|
|
case OID_802_3_XMIT_DEFERRED:
|
|
lvalue = ethobjs->RSL_DeferredXmit;
|
|
break;
|
|
case OID_802_3_XMIT_LATE_COLLISIONS:
|
|
lvalue = ethobjs->RSL_LateCollision;
|
|
break;
|
|
case OID_802_3_XMIT_MAX_COLLISIONS:
|
|
case OID_802_3_XMIT_TIMES_CRS_LOST:
|
|
lvalue = ethobjs->RSL_Excessive;
|
|
break;
|
|
default:
|
|
lvalue = ethobjs->RSL_FrameCheckSeq;
|
|
break;
|
|
}
|
|
copyptr = (PUCHAR)&lvalue;
|
|
}
|
|
else
|
|
{
|
|
needcopy = FALSE;
|
|
Status = NetFlexDequeue_OnePtrQ_Head(
|
|
(PVOID *)&(acb->acb_scbreq_free),
|
|
(PVOID *)&scbreq);
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
Status = NDIS_STATUS_RESOURCES;
|
|
}
|
|
else
|
|
{
|
|
// Save the information about the request
|
|
//
|
|
if (acb->RequestInProgress)
|
|
{
|
|
DebugPrint(0,("NF(%d): Query OID: Aready have RequestInProcess!\n",acb->anum));
|
|
// return NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
acb->RequestInProgress = TRUE;
|
|
|
|
acb->BytesWritten = BytesWritten;
|
|
acb->BytesNeeded = BytesNeeded;
|
|
acb->Oid = Oid;
|
|
acb->InformationBuffer = InformationBuffer;
|
|
acb->InformationBufferLength = InformationBufferLength;
|
|
|
|
DebugPrint(2,("NF(%d): Queue Up Request to get OID (0x%x) info\n",acb->anum,Oid));
|
|
|
|
NetFlexDequeue_OnePtrQ_Head( (PVOID *)&(acb->acb_macreq_free),
|
|
(PVOID *)¯eq);
|
|
macreq->req_next = NULL;
|
|
macreq->req_type = QUERY_CMP;
|
|
macreq->req_status = NDIS_STATUS_SUCCESS;
|
|
|
|
scbreq->req_scb.SCB_Cmd = TMS_READLOG;
|
|
scbreq->req_macreq = macreq;
|
|
scbreq->req_scb.SCB_Ptr = SWAPL(CTRL_ADDR(NdisGetPhysicalAddressLow(acb->acb_logbuf_physptr)));
|
|
|
|
//
|
|
// put the macreq on the macreq queue
|
|
//
|
|
NetFlexEnqueue_TwoPtrQ_Tail( (PVOID *)&(acb->acb_macreq_head),
|
|
(PVOID *)&(acb->acb_macreq_tail),
|
|
(PVOID)macreq);
|
|
|
|
NetFlexQueueSCB(acb, scbreq);
|
|
Status = NDIS_STATUS_PENDING;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
DebugPrint(1,("NF(%d): (ETH) Invalid Query or Unsupported OID, %x\n",acb->anum,Oid));
|
|
Status = NDIS_STATUS_NOT_SUPPORTED;
|
|
needcopy = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//---------------------------------------
|
|
// Token Ring Specific Oid's
|
|
//---------------------------------------
|
|
//
|
|
switch (Oid)
|
|
{
|
|
// We added the 802.5 stats here as well because of the
|
|
// read error log buffer.
|
|
//
|
|
case OID_802_5_LINE_ERRORS:
|
|
case OID_802_5_LOST_FRAMES:
|
|
case OID_802_5_BURST_ERRORS:
|
|
case OID_802_5_AC_ERRORS:
|
|
case OID_802_5_CONGESTION_ERRORS:
|
|
case OID_802_5_FRAME_COPIED_ERRORS:
|
|
case OID_802_5_TOKEN_ERRORS:
|
|
case OID_GEN_RCV_NO_BUFFER:
|
|
if (acb->acb_logbuf_valid)
|
|
{
|
|
trobjs = (PTR_OBJS)(acb->acb_spec_objs);
|
|
switch (Oid)
|
|
{
|
|
case OID_GEN_RCV_NO_BUFFER:
|
|
lvalue = trobjs->REL_Congestion;
|
|
break;
|
|
case OID_802_5_LINE_ERRORS:
|
|
lvalue = trobjs->REL_LineError;
|
|
break;
|
|
case OID_802_5_LOST_FRAMES:
|
|
lvalue = trobjs->REL_LostError;
|
|
break;
|
|
case OID_802_5_BURST_ERRORS:
|
|
lvalue = trobjs->REL_BurstError;
|
|
break;
|
|
case OID_802_5_AC_ERRORS:
|
|
lvalue = trobjs->REL_ARIFCIError;
|
|
break;
|
|
case OID_802_5_CONGESTION_ERRORS:
|
|
lvalue = trobjs->REL_Congestion;
|
|
break;
|
|
case OID_802_5_FRAME_COPIED_ERRORS:
|
|
lvalue = trobjs->REL_CopiedError;
|
|
break;
|
|
case OID_802_5_TOKEN_ERRORS:
|
|
lvalue = trobjs->REL_TokenError;
|
|
break;
|
|
default:
|
|
DebugPrint(0,("NetFlexQueryInformation: Undefinded OID - 0x%x",Oid));
|
|
break;
|
|
}
|
|
copyptr = (PUCHAR)&lvalue;
|
|
}
|
|
else
|
|
{
|
|
needcopy = FALSE;
|
|
Status = NetFlexDequeue_OnePtrQ_Head((PVOID *)&(acb->acb_scbreq_free),
|
|
(PVOID *)&scbreq);
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
Status = NDIS_STATUS_RESOURCES;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Save the information about the request
|
|
//
|
|
if (acb->RequestInProgress)
|
|
{
|
|
DebugPrint(0,("NF(%d): Query OID: Aready have RequestInProcess!\n",acb->anum));
|
|
//return NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
acb->RequestInProgress = TRUE;
|
|
|
|
acb->BytesWritten = BytesWritten;
|
|
acb->BytesNeeded = BytesNeeded;
|
|
acb->Oid = Oid;
|
|
acb->InformationBuffer = InformationBuffer;
|
|
acb->InformationBufferLength = InformationBufferLength;
|
|
|
|
DebugPrint(2,("NF(%d): Queue Up Request to get OID (0x%x) info\n",acb->anum,Oid));
|
|
|
|
NetFlexDequeue_OnePtrQ_Head( (PVOID *)&(acb->acb_macreq_free),
|
|
(PVOID *)¯eq);
|
|
macreq->req_next = NULL;
|
|
macreq->req_type = QUERY_CMP;
|
|
macreq->req_status = NDIS_STATUS_SUCCESS;
|
|
|
|
scbreq->req_scb.SCB_Cmd = TMS_READLOG;
|
|
scbreq->req_macreq = macreq;
|
|
scbreq->req_scb.SCB_Ptr = SWAPL(CTRL_ADDR(NdisGetPhysicalAddressLow(acb->acb_logbuf_physptr)));
|
|
//
|
|
// put the macreq on the macreq queue
|
|
//
|
|
NetFlexEnqueue_TwoPtrQ_Tail( (PVOID *)&(acb->acb_macreq_head),
|
|
(PVOID *)&(acb->acb_macreq_tail),
|
|
(PVOID)macreq);
|
|
|
|
NetFlexQueueSCB(acb, scbreq);
|
|
Status = NDIS_STATUS_PENDING;
|
|
}
|
|
}
|
|
break;
|
|
|
|
//------------------------------------
|
|
// 802.5 OPERATIONAL CHARACTERISTICS
|
|
//------------------------------------
|
|
|
|
case OID_802_5_PERMANENT_ADDRESS:
|
|
srcptr = acb->acb_gen_objs.perm_staddr;
|
|
copyptr = (PUCHAR)srcptr;
|
|
copylen = (SHORT)NET_ADDR_SIZE;
|
|
break;
|
|
|
|
case OID_802_5_CURRENT_ADDRESS:
|
|
srcptr = acb->acb_gen_objs.current_staddr;
|
|
copyptr = (PUCHAR)srcptr;
|
|
copylen = (SHORT)NET_ADDR_SIZE;
|
|
break;
|
|
|
|
case OID_802_5_UPSTREAM_ADDRESS:
|
|
NetFlexGetUpstreamAddress(acb);
|
|
srcptr = ((PTR_OBJS)acb->acb_spec_objs)->upstream_addr;
|
|
copyptr = (PUCHAR)srcptr;
|
|
copylen = (SHORT)NET_ADDR_SIZE;
|
|
break;
|
|
|
|
case OID_802_5_CURRENT_FUNCTIONAL:
|
|
lvalue = *( (PULONG)(((PTR_OBJS)(acb->acb_spec_objs))->cur_func_addr));
|
|
copyptr = (PUCHAR)&lvalue;
|
|
copylen = (SHORT)NET_GROUP_SIZE;
|
|
break;
|
|
|
|
case OID_802_5_CURRENT_GROUP:
|
|
lvalue = *( (PULONG)(((PTR_OBJS)(acb->acb_spec_objs))->cur_grp_addr));
|
|
copylen = (lvalue == 0) ? 0 : NET_GROUP_SIZE;
|
|
copyptr = (PUCHAR)&lvalue;
|
|
break;
|
|
|
|
case OID_802_5_LAST_OPEN_STATUS:
|
|
lvalue = acb->acb_lastopenstat;
|
|
copyptr = (PUCHAR)&lvalue;
|
|
break;
|
|
|
|
case OID_802_5_CURRENT_RING_STATUS:
|
|
lvalue = acb->acb_lastringstatus;
|
|
copyptr = (PUCHAR)&lvalue;
|
|
break;
|
|
|
|
case OID_802_5_CURRENT_RING_STATE:
|
|
lvalue = acb->acb_lastringstate;
|
|
copyptr = (PUCHAR)&lvalue;
|
|
break;
|
|
|
|
default:
|
|
DebugPrint(1,("NF(%d): (TR) Invalid Query or Unsupported OID, %x\n",acb->anum,Oid));
|
|
Status = NDIS_STATUS_NOT_SUPPORTED;
|
|
needcopy = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (needcopy)
|
|
{
|
|
// Do we have enough space for the list + the oid value + the length?
|
|
//
|
|
if (InformationBufferLength < (USHORT) copylen)
|
|
{
|
|
DebugPrint(1,("NF(%d): Tell the user of the bytes needed\n",acb->anum));
|
|
*BytesNeeded = copylen - InformationBufferLength;
|
|
Status = NDIS_STATUS_INVALID_LENGTH;
|
|
}
|
|
else
|
|
{
|
|
// Copy the data bytes
|
|
//
|
|
NdisMoveMemory( InformationBuffer,
|
|
copyptr,
|
|
copylen);
|
|
//
|
|
// Update the information pointer and size.
|
|
//
|
|
*BytesWritten += copylen;
|
|
}
|
|
}
|
|
|
|
acb->RequestInProgress = Status == NDIS_STATUS_PENDING;
|
|
|
|
return Status;
|
|
}
|
|
|
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
//
|
|
// Routine Name: NetFlexFinishQueryInformation
|
|
//
|
|
// Description:
|
|
// The NetFlexFinishQueryInformation finish processing a Query request for
|
|
// NDIS_OIDs that are specific about the Driver which we had to update
|
|
// before returning.
|
|
//
|
|
// Input:
|
|
// acb - Our Driver Context for this adapter or head.
|
|
//
|
|
// Output:
|
|
// The function value is the Status of the operation.
|
|
//
|
|
// Called By:
|
|
//
|
|
//
|
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
VOID
|
|
NetFlexFinishQueryInformation(
|
|
PACB acb,
|
|
NDIS_STATUS Status
|
|
)
|
|
{
|
|
ULONG lvalue;
|
|
PTR_OBJS trobjs;
|
|
PETH_OBJS ethobjs;
|
|
BOOLEAN needcopy = TRUE;
|
|
PUCHAR copyptr;
|
|
SHORT copylen = (SHORT)sizeof(ULONG); // Most common length
|
|
|
|
//
|
|
// Get the saved information about the request.
|
|
//
|
|
|
|
PUINT BytesWritten = acb->BytesWritten;
|
|
PUINT BytesNeeded = acb->BytesNeeded;
|
|
NDIS_OID Oid = acb->Oid;
|
|
PVOID InformationBuffer = acb->InformationBuffer;
|
|
UINT InformationBufferLength = acb->InformationBufferLength;
|
|
|
|
DebugPrint(2,("NF(%d): NetFlexFinishQueryInformation\n",acb->anum));
|
|
|
|
if (Status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
*BytesNeeded = 0;
|
|
|
|
switch (Oid)
|
|
{
|
|
|
|
case OID_GEN_RCV_NO_BUFFER:
|
|
case OID_802_5_LINE_ERRORS:
|
|
case OID_802_5_LOST_FRAMES:
|
|
case OID_802_5_BURST_ERRORS:
|
|
case OID_802_5_AC_ERRORS:
|
|
case OID_802_5_CONGESTION_ERRORS:
|
|
case OID_802_5_FRAME_COPIED_ERRORS:
|
|
case OID_802_5_TOKEN_ERRORS:
|
|
trobjs = (PTR_OBJS)(acb->acb_spec_objs);
|
|
switch (Oid)
|
|
{
|
|
case OID_GEN_RCV_NO_BUFFER:
|
|
lvalue = trobjs->REL_Congestion;
|
|
break;
|
|
case OID_802_5_LINE_ERRORS:
|
|
lvalue = trobjs->REL_LineError;
|
|
break;
|
|
case OID_802_5_LOST_FRAMES:
|
|
lvalue = trobjs->REL_LostError;
|
|
break;
|
|
case OID_802_5_BURST_ERRORS:
|
|
lvalue = trobjs->REL_BurstError;
|
|
break;
|
|
case OID_802_5_AC_ERRORS:
|
|
lvalue = trobjs->REL_ARIFCIError;
|
|
break;
|
|
case OID_802_5_CONGESTION_ERRORS:
|
|
lvalue = trobjs->REL_Congestion;
|
|
break;
|
|
case OID_802_5_FRAME_COPIED_ERRORS:
|
|
lvalue = trobjs->REL_CopiedError;
|
|
break;
|
|
case OID_802_5_TOKEN_ERRORS:
|
|
lvalue = trobjs->REL_TokenError;
|
|
break;
|
|
default:
|
|
DebugPrint(0,("NetFlexFinishQueryInformation: Undefinded OID - 0x%x",Oid));
|
|
break;
|
|
}
|
|
copyptr = (PUCHAR)&lvalue;
|
|
break;
|
|
|
|
case OID_802_3_RCV_ERROR_ALIGNMENT:
|
|
case OID_802_3_XMIT_ONE_COLLISION:
|
|
case OID_802_3_XMIT_MORE_COLLISIONS:
|
|
case OID_802_3_XMIT_DEFERRED:
|
|
case OID_802_3_XMIT_LATE_COLLISIONS:
|
|
case OID_802_3_XMIT_MAX_COLLISIONS:
|
|
case OID_802_3_XMIT_TIMES_CRS_LOST:
|
|
case OID_GEN_RCV_CRC_ERROR:
|
|
ethobjs = (PETH_OBJS)(acb->acb_spec_objs);
|
|
|
|
switch (Oid)
|
|
{
|
|
case OID_802_3_RCV_ERROR_ALIGNMENT:
|
|
lvalue = ethobjs->RSL_AlignmentErr;
|
|
break;
|
|
case OID_802_3_XMIT_ONE_COLLISION:
|
|
lvalue = ethobjs->RSL_1_Collision;
|
|
break;
|
|
case OID_802_3_XMIT_MORE_COLLISIONS:
|
|
lvalue = ethobjs->RSL_More_Collision;
|
|
break;
|
|
case OID_802_3_XMIT_DEFERRED:
|
|
lvalue = ethobjs->RSL_DeferredXmit;
|
|
break;
|
|
case OID_802_3_XMIT_LATE_COLLISIONS:
|
|
lvalue = ethobjs->RSL_LateCollision;
|
|
break;
|
|
case OID_802_3_XMIT_MAX_COLLISIONS:
|
|
case OID_802_3_XMIT_TIMES_CRS_LOST:
|
|
lvalue = ethobjs->RSL_Excessive;
|
|
break;
|
|
default:
|
|
lvalue = ethobjs->RSL_FrameCheckSeq;
|
|
break;
|
|
}
|
|
copyptr = (PUCHAR)&lvalue;
|
|
break;
|
|
|
|
default:
|
|
DebugPrint(1,("NF(%d): Invalid Query or Unsupported OID, %x\n",acb->anum,Oid));
|
|
Status = NDIS_STATUS_NOT_SUPPORTED;
|
|
needcopy = FALSE;
|
|
break;
|
|
}
|
|
|
|
if (needcopy)
|
|
{
|
|
// Do we have enough space for the list + the oid value + the length?
|
|
//
|
|
if (InformationBufferLength < (USHORT) copylen)
|
|
{
|
|
DebugPrint(1,("NF(%d): Tell the user of the bytes needed\n",acb->anum));
|
|
*BytesNeeded = copylen - InformationBufferLength;
|
|
Status = NDIS_STATUS_INVALID_LENGTH;
|
|
}
|
|
else
|
|
{
|
|
// Copy the data bytes
|
|
//
|
|
NdisMoveMemory( InformationBuffer,
|
|
copyptr,
|
|
copylen);
|
|
//
|
|
// Update the information pointer and size.
|
|
//
|
|
*BytesWritten += copylen;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Complete the request
|
|
//
|
|
NdisMQueryInformationComplete( acb->acb_handle,
|
|
Status );
|
|
acb->RequestInProgress = FALSE;
|
|
|
|
}
|
|
|
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
//
|
|
// Routine Name: NetFlexGetUpstreamAddress
|
|
//
|
|
// Description:
|
|
// This routine gets the upstream neighbor of
|
|
// the adapter in Token-Ring.
|
|
//
|
|
// Input:
|
|
// acb - Our Driver Context for this adapter or head.
|
|
//
|
|
// Output:
|
|
// Returns NDIS_STATUS_SUCCESS for a successful
|
|
// completion. Otherwise, an error code is returned.
|
|
//
|
|
// Called By:
|
|
// NetFlexBoardInitandReg
|
|
//
|
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
VOID
|
|
NetFlexGetUpstreamAddress(
|
|
PACB acb
|
|
)
|
|
{
|
|
USHORT value;
|
|
SHORT i;
|
|
|
|
NdisRawWritePortUshort(acb->SifAddrPort, acb->acb_upstreamaddrptr+4 );
|
|
|
|
for (i = 0; i < 3; i++)
|
|
{
|
|
NdisRawReadPortUshort(acb->SifDIncPort,(PUSHORT) &value);
|
|
|
|
((PTR_OBJS)(acb->acb_spec_objs))->upstream_addr[i*2] =
|
|
(UCHAR)(SWAPS(value));
|
|
((PTR_OBJS)(acb->acb_spec_objs))->upstream_addr[(i*2)+1] =
|
|
(UCHAR)value;
|
|
}
|
|
}
|
|
|
|
|
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
//
|
|
// Routine Name: NetFlexProcessMacReq
|
|
//
|
|
// Description:
|
|
// This routine completes a request which had to wait
|
|
// for a adapter command to complete.
|
|
//
|
|
// Input:
|
|
// acb - Our Driver Context for this adapter or head.
|
|
//
|
|
// Output:
|
|
// None
|
|
//
|
|
// Called By:
|
|
// NetFlexHandleInterrupt
|
|
//
|
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
VOID
|
|
NetFlexProcessMacReq(
|
|
PACB acb
|
|
)
|
|
{
|
|
|
|
NDIS_STATUS status;
|
|
PMACREQ macreq;
|
|
BOOLEAN ReceiveResult;
|
|
|
|
DebugPrint(1,("NF(%d): NetFlexProcessMacReq entered.\n", acb->anum));
|
|
|
|
while (acb->acb_confirm_qhead != NULL)
|
|
{
|
|
// We have command to complete.
|
|
//
|
|
macreq = acb->acb_confirm_qhead;
|
|
if ((acb->acb_confirm_qhead = macreq->req_next) == NULL)
|
|
{
|
|
acb->acb_confirm_qtail = NULL;
|
|
}
|
|
//
|
|
// what was the status...
|
|
//
|
|
status = macreq->req_status;
|
|
|
|
switch (macreq->req_type)
|
|
{
|
|
case OPENADAPTER_CMP:
|
|
|
|
//
|
|
// Cancel the Reset Timer, since the hardware seems to be working correctly
|
|
//
|
|
NdisMCancelTimer(&acb->ResetTimer,&ReceiveResult);
|
|
|
|
//
|
|
// Did the open complete successfully?
|
|
//
|
|
if (status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
// Yes, mark as opened.
|
|
//
|
|
acb->acb_lastopenstat = 0;
|
|
acb->acb_lastringstate = NdisRingStateOpened;
|
|
|
|
//
|
|
// If the open completed successfully, we need to
|
|
// issue the transmit and receive commands. Also,
|
|
// we need to set the state according to the status.
|
|
//
|
|
if (acb->acb_state == AS_OPENING)
|
|
{
|
|
acb->acb_state = AS_OPENED;
|
|
}
|
|
|
|
//
|
|
// Now lets finish the open by sending a receive command to the adapter.
|
|
//
|
|
acb->acb_rcv_whead = acb->acb_rcv_head;
|
|
|
|
//
|
|
// Now lets finish the open by sending a
|
|
// transmit and receive command to the adapter.
|
|
//
|
|
acb->acb_xmit_whead = acb->acb_xmit_wtail = acb->acb_xmit_head;
|
|
|
|
//
|
|
// If the adapter is ready for a command, call a
|
|
// routine that will kick off the transmit command.
|
|
//
|
|
if (acb->acb_scb_virtptr->SCB_Cmd == 0)
|
|
{
|
|
NetFlexSendNextSCB(acb);
|
|
}
|
|
else if (!acb->acb_scbclearout)
|
|
{
|
|
//
|
|
// Make sure we are interrupted when the SCB is
|
|
// available so that we can send the transmit command.
|
|
//
|
|
acb->acb_scbclearout = TRUE;
|
|
NdisRawWritePortUshort(
|
|
acb->SifIntPort,
|
|
(USHORT)SIFINT_SCBREQST);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Open failed.
|
|
// If we had an open error that is specific to TOKEN RING,
|
|
// set the last open status to the correct error code. Otherwise,
|
|
// just send the status as normal.
|
|
//
|
|
if (macreq->req_status == NDIS_STATUS_TOKEN_RING_OPEN_ERROR)
|
|
{
|
|
acb->acb_lastopenstat = (NDIS_STATUS)(macreq->req_info) |
|
|
NDIS_STATUS_TOKEN_RING_OPEN_ERROR;
|
|
}
|
|
else
|
|
{
|
|
acb->acb_lastopenstat = 0;
|
|
}
|
|
acb->acb_lastringstate = NdisRingStateOpenFailure;
|
|
|
|
if (acb->acb_state == AS_OPENING)
|
|
{
|
|
acb->acb_state = AS_INITIALIZED;
|
|
}
|
|
//
|
|
// Force a reset.
|
|
//
|
|
acb->ResetState = RESET_STAGE_4;
|
|
}
|
|
|
|
//
|
|
// Put Macreq back on free queue
|
|
//
|
|
NetFlexEnqueue_OnePtrQ_Head((PVOID *)&(acb->acb_macreq_free),
|
|
(PVOID)macreq);
|
|
|
|
|
|
//
|
|
//
|
|
// processed the open command.
|
|
//
|
|
|
|
if (acb->ResetState == RESET_STAGE_4)
|
|
{
|
|
//
|
|
// If this is the completion of a Reset, set the reset timer
|
|
// so it can be completed.
|
|
//
|
|
NdisMSetTimer(&acb->ResetTimer,10);
|
|
}
|
|
break;
|
|
|
|
case CLOSEADAPTER_CMP:
|
|
acb->acb_state = AS_CLOSING;
|
|
break;
|
|
|
|
case QUERY_CMP:
|
|
case REQUEST_CMP:
|
|
|
|
if (acb->RequestInProgress)
|
|
{
|
|
//
|
|
// Go process the request
|
|
// Is it a Query or a Set?
|
|
//
|
|
if (macreq->req_type == QUERY_CMP)
|
|
{
|
|
NetFlexFinishQueryInformation(acb,status);
|
|
}
|
|
else
|
|
{
|
|
DebugPrint(1,("NF(%d): NetFlexProcessMacReq: Completing request.\n", acb->anum));
|
|
|
|
acb->RequestInProgress = FALSE;
|
|
NdisMSetInformationComplete(acb->acb_handle, status);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DebugPrint(0,("NF(%d): Have macreq QUERY_CMP or REQUEST_CMP without RequestInProgress!\n",acb->anum));
|
|
}
|
|
|
|
NdisZeroMemory(macreq, sizeof(MACREQ));
|
|
NetFlexEnqueue_OnePtrQ_Head(
|
|
(PVOID *)&(acb->acb_macreq_free),
|
|
(PVOID)macreq
|
|
);
|
|
|
|
break;
|
|
|
|
default: // We should NEVER be here
|
|
DebugPrint(0,("NF(%d): ProcessMaqReq - No command - ERROR!\n",acb->anum));
|
|
break;
|
|
} // End of switch
|
|
} // End of while confirm q
|
|
}
|