2149 lines
70 KiB
C
2149 lines
70 KiB
C
//**********************************************************************
|
||
//**********************************************************************
|
||
//
|
||
// 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
|
||
}
|