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.
986 lines
23 KiB
986 lines
23 KiB
/*++
|
|
|
|
Copyright (c) 1989-1993 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
stndis.c
|
|
|
|
Abstract:
|
|
|
|
This module contains code which implements the routines used to interface
|
|
ST and NDIS. All callback routines (except for Transfer Data,
|
|
Send Complete, and ReceiveIndication) are here, as well as those routines
|
|
called to initialize NDIS.
|
|
|
|
Environment:
|
|
|
|
Kernel mode
|
|
|
|
--*/
|
|
|
|
#include "st.h"
|
|
|
|
|
|
//
|
|
// This is a one-per-driver variable used in binding
|
|
// to the NDIS interface.
|
|
//
|
|
|
|
NDIS_HANDLE StNdisProtocolHandle = (NDIS_HANDLE)NULL;
|
|
|
|
NDIS_STATUS
|
|
StSubmitNdisRequest(
|
|
IN PDEVICE_CONTEXT DeviceContext,
|
|
IN PNDIS_REQUEST NdisRequest,
|
|
IN PNDIS_STRING AdapterString
|
|
);
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(INIT,StRegisterProtocol)
|
|
#pragma alloc_text(INIT,StSubmitNdisRequest)
|
|
#pragma alloc_text(INIT,StInitializeNdis)
|
|
#endif
|
|
|
|
|
|
NTSTATUS
|
|
StRegisterProtocol (
|
|
IN STRING *NameString
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine introduces this transport to the NDIS interface.
|
|
|
|
Arguments:
|
|
|
|
Irp - Pointer to the request packet representing the I/O request.
|
|
|
|
Return Value:
|
|
|
|
The function value is the status of the operation.
|
|
STATUS_SUCCESS if all goes well,
|
|
Failure status if we tried to register and couldn't,
|
|
STATUS_INSUFFICIENT_RESOURCES if we couldn't even try to register.
|
|
|
|
--*/
|
|
|
|
{
|
|
NDIS_STATUS ndisStatus;
|
|
|
|
NDIS_PROTOCOL_CHARACTERISTICS ProtChars; // Used temporarily to register
|
|
|
|
|
|
//
|
|
// Set up the characteristics of this protocol
|
|
//
|
|
|
|
ProtChars.MajorNdisVersion = 3;
|
|
ProtChars.MinorNdisVersion = 0;
|
|
|
|
ProtChars.Name.Length = NameString->Length;
|
|
ProtChars.Name.Buffer = (PVOID)NameString->Buffer;
|
|
|
|
ProtChars.OpenAdapterCompleteHandler = StOpenAdapterComplete;
|
|
ProtChars.CloseAdapterCompleteHandler = StCloseAdapterComplete;
|
|
ProtChars.ResetCompleteHandler = StResetComplete;
|
|
ProtChars.RequestCompleteHandler = StRequestComplete;
|
|
|
|
ProtChars.SendCompleteHandler = StSendCompletionHandler;
|
|
ProtChars.TransferDataCompleteHandler = StTransferDataComplete;
|
|
|
|
ProtChars.ReceiveHandler = StReceiveIndication;
|
|
ProtChars.ReceiveCompleteHandler = StReceiveComplete;
|
|
ProtChars.StatusHandler = StStatusIndication;
|
|
ProtChars.StatusCompleteHandler = StStatusComplete;
|
|
|
|
NdisRegisterProtocol (
|
|
&ndisStatus,
|
|
&StNdisProtocolHandle,
|
|
&ProtChars,
|
|
(UINT)sizeof(NDIS_PROTOCOL_CHARACTERISTICS) + NameString->Length);
|
|
|
|
if (ndisStatus != NDIS_STATUS_SUCCESS) {
|
|
return (NTSTATUS)ndisStatus;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
VOID
|
|
StDeregisterProtocol (
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine removes this transport to the NDIS interface.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
NDIS_STATUS ndisStatus;
|
|
|
|
if (StNdisProtocolHandle != (NDIS_HANDLE)NULL) {
|
|
NdisDeregisterProtocol (
|
|
&ndisStatus,
|
|
StNdisProtocolHandle);
|
|
StNdisProtocolHandle = (NDIS_HANDLE)NULL;
|
|
}
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
StSubmitNdisRequest(
|
|
IN PDEVICE_CONTEXT DeviceContext,
|
|
IN PNDIS_REQUEST NdisRequest,
|
|
IN PNDIS_STRING AdapterString
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine passed an NDIS_REQUEST to the MAC and waits
|
|
until it has completed before returning the final status.
|
|
|
|
Arguments:
|
|
|
|
DeviceContext - Pointer to the device context for this driver.
|
|
|
|
NdisRequest - Pointer to the NDIS_REQUEST to submit.
|
|
|
|
AdapterString - The name of the adapter, in case an error needs
|
|
to be logged.
|
|
|
|
Return Value:
|
|
|
|
The function value is the status of the operation.
|
|
|
|
--*/
|
|
{
|
|
NDIS_STATUS NdisStatus;
|
|
|
|
NdisRequest(
|
|
&NdisStatus,
|
|
DeviceContext->NdisBindingHandle,
|
|
NdisRequest);
|
|
|
|
if (NdisStatus == NDIS_STATUS_PENDING) {
|
|
|
|
//
|
|
// The completion routine will set NdisRequestStatus.
|
|
//
|
|
|
|
KeWaitForSingleObject(
|
|
&DeviceContext->NdisRequestEvent,
|
|
Executive,
|
|
KernelMode,
|
|
TRUE,
|
|
(PLARGE_INTEGER)NULL
|
|
);
|
|
|
|
NdisStatus = DeviceContext->NdisRequestStatus;
|
|
|
|
KeResetEvent(
|
|
&DeviceContext->NdisRequestEvent
|
|
);
|
|
|
|
}
|
|
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS) {
|
|
|
|
StWriteOidErrorLog(
|
|
DeviceContext,
|
|
NdisRequest->RequestType == NdisRequestSetInformation ?
|
|
EVENT_TRANSPORT_SET_OID_FAILED : EVENT_TRANSPORT_QUERY_OID_FAILED,
|
|
NdisStatus,
|
|
AdapterString->Buffer,
|
|
NdisRequest->DATA.QUERY_INFORMATION.Oid);
|
|
}
|
|
|
|
return NdisStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
StInitializeNdis (
|
|
IN PDEVICE_CONTEXT DeviceContext,
|
|
IN PCONFIG_DATA StConfig,
|
|
IN UINT ConfigInfoNameIndex
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine introduces this transport to the NDIS interface and sets up
|
|
any necessary NDIS data structures (Buffer pools and such). It will be
|
|
called for each adapter opened by this transport.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - Pointer to the device object for this driver.
|
|
|
|
Irp - Pointer to the request packet representing the I/O request.
|
|
|
|
Return Value:
|
|
|
|
The function value is the status of the operation.
|
|
|
|
--*/
|
|
{
|
|
ULONG SendPacketReservedLength;
|
|
ULONG ReceivePacketReservedLen;
|
|
ULONG SendPacketPoolSize;
|
|
ULONG ReceivePacketPoolSize;
|
|
NDIS_STATUS NdisStatus;
|
|
NDIS_STATUS OpenErrorStatus;
|
|
NDIS_MEDIUM StSupportedMedia[] = { NdisMedium802_3, NdisMedium802_5, NdisMediumFddi };
|
|
UINT SelectedMedium;
|
|
NDIS_REQUEST StRequest;
|
|
UCHAR StDataBuffer[6];
|
|
NDIS_OID StOid;
|
|
ULONG MinimumLookahead = 128 + sizeof(ST_HEADER);
|
|
ULONG ProtocolOptions, MacOptions;
|
|
PNDIS_STRING AdapterString;
|
|
|
|
//
|
|
// Initialize this adapter for ST use through NDIS
|
|
//
|
|
|
|
//
|
|
// This event is used in case any of the NDIS requests
|
|
// pend; we wait until it is set by the completion
|
|
// routine, which also sets NdisRequestStatus.
|
|
//
|
|
|
|
KeInitializeEvent(
|
|
&DeviceContext->NdisRequestEvent,
|
|
NotificationEvent,
|
|
FALSE
|
|
);
|
|
|
|
DeviceContext->NdisBindingHandle = NULL;
|
|
AdapterString = (PNDIS_STRING)&StConfig->Names[ConfigInfoNameIndex];
|
|
|
|
NdisOpenAdapter (
|
|
&NdisStatus,
|
|
&OpenErrorStatus,
|
|
&DeviceContext->NdisBindingHandle,
|
|
&SelectedMedium,
|
|
StSupportedMedia,
|
|
sizeof (StSupportedMedia) / sizeof(NDIS_MEDIUM),
|
|
StNdisProtocolHandle,
|
|
(NDIS_HANDLE)DeviceContext,
|
|
AdapterString,
|
|
0,
|
|
NULL);
|
|
|
|
if (NdisStatus == NDIS_STATUS_PENDING) {
|
|
|
|
//
|
|
// The completion routine will set NdisRequestStatus.
|
|
//
|
|
|
|
KeWaitForSingleObject(
|
|
&DeviceContext->NdisRequestEvent,
|
|
Executive,
|
|
KernelMode,
|
|
TRUE,
|
|
(PLARGE_INTEGER)NULL
|
|
);
|
|
|
|
NdisStatus = DeviceContext->NdisRequestStatus;
|
|
|
|
KeResetEvent(
|
|
&DeviceContext->NdisRequestEvent
|
|
);
|
|
|
|
}
|
|
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS) {
|
|
|
|
StWriteGeneralErrorLog(
|
|
DeviceContext,
|
|
EVENT_TRANSPORT_ADAPTER_NOT_FOUND,
|
|
807,
|
|
NdisStatus,
|
|
AdapterString->Buffer,
|
|
0,
|
|
NULL);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
|
|
//
|
|
// Get the information we need about the adapter, based on
|
|
// the media type.
|
|
//
|
|
|
|
MacInitializeMacInfo(
|
|
StSupportedMedia[SelectedMedium],
|
|
&DeviceContext->MacInfo);
|
|
|
|
|
|
//
|
|
// Set the multicast/functional addresses first so we avoid windows where we
|
|
// receive only part of the addresses.
|
|
//
|
|
|
|
MacSetMulticastAddress (
|
|
DeviceContext->MacInfo.MediumType,
|
|
DeviceContext->MulticastAddress.Address);
|
|
|
|
|
|
switch (DeviceContext->MacInfo.MediumType) {
|
|
|
|
case NdisMedium802_3:
|
|
|
|
//
|
|
// Fill in the data for our multicast list.
|
|
//
|
|
|
|
RtlCopyMemory(StDataBuffer, DeviceContext->MulticastAddress.Address, 6);
|
|
|
|
//
|
|
// Now fill in the NDIS_REQUEST.
|
|
//
|
|
|
|
StRequest.RequestType = NdisRequestSetInformation;
|
|
StRequest.DATA.SET_INFORMATION.Oid = OID_802_3_MULTICAST_LIST;
|
|
StRequest.DATA.SET_INFORMATION.InformationBuffer = &StDataBuffer;
|
|
StRequest.DATA.SET_INFORMATION.InformationBufferLength = 6;
|
|
|
|
break;
|
|
|
|
case NdisMedium802_5:
|
|
|
|
//
|
|
// For token-ring, we pass the last four bytes of the
|
|
// Netbios functional address.
|
|
//
|
|
|
|
//
|
|
// Fill in the data for our functional address.
|
|
//
|
|
|
|
RtlCopyMemory(StDataBuffer, ((PUCHAR)(DeviceContext->MulticastAddress.Address)) + 2, 4);
|
|
|
|
//
|
|
// Now fill in the NDIS_REQUEST.
|
|
//
|
|
|
|
StRequest.RequestType = NdisRequestSetInformation;
|
|
StRequest.DATA.SET_INFORMATION.Oid = OID_802_5_CURRENT_FUNCTIONAL;
|
|
StRequest.DATA.SET_INFORMATION.InformationBuffer = &StDataBuffer;
|
|
StRequest.DATA.SET_INFORMATION.InformationBufferLength = 4;
|
|
|
|
break;
|
|
|
|
case NdisMediumFddi:
|
|
|
|
//
|
|
// Fill in the data for our multicast list.
|
|
//
|
|
|
|
RtlCopyMemory(StDataBuffer, DeviceContext->MulticastAddress.Address, 6);
|
|
|
|
//
|
|
// Now fill in the NDIS_REQUEST.
|
|
//
|
|
|
|
StRequest.RequestType = NdisRequestSetInformation;
|
|
StRequest.DATA.SET_INFORMATION.Oid = OID_FDDI_LONG_MULTICAST_LIST;
|
|
StRequest.DATA.SET_INFORMATION.InformationBuffer = &StDataBuffer;
|
|
StRequest.DATA.SET_INFORMATION.InformationBufferLength = 6;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
NdisStatus = StSubmitNdisRequest (DeviceContext, &StRequest, AdapterString);
|
|
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS) {
|
|
StCloseNdis (DeviceContext);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
|
|
|
|
switch (DeviceContext->MacInfo.MediumType) {
|
|
|
|
case NdisMedium802_3:
|
|
|
|
StOid = OID_802_3_CURRENT_ADDRESS;
|
|
break;
|
|
|
|
case NdisMedium802_5:
|
|
|
|
StOid = OID_802_5_CURRENT_ADDRESS;
|
|
break;
|
|
|
|
case NdisMediumFddi:
|
|
|
|
StOid = OID_FDDI_LONG_CURRENT_ADDR;
|
|
break;
|
|
|
|
default:
|
|
|
|
NdisStatus = NDIS_STATUS_FAILURE;
|
|
break;
|
|
|
|
}
|
|
|
|
StRequest.RequestType = NdisRequestQueryInformation;
|
|
StRequest.DATA.QUERY_INFORMATION.Oid = StOid;
|
|
StRequest.DATA.QUERY_INFORMATION.InformationBuffer = DeviceContext->LocalAddress.Address;
|
|
StRequest.DATA.QUERY_INFORMATION.InformationBufferLength = 6;
|
|
|
|
NdisStatus = StSubmitNdisRequest (DeviceContext, &StRequest, AdapterString);
|
|
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS) {
|
|
StCloseNdis (DeviceContext);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
//
|
|
// Set up the reserved Netbios address.
|
|
//
|
|
|
|
RtlZeroMemory(DeviceContext->ReservedNetBIOSAddress, 10);
|
|
RtlCopyMemory(&DeviceContext->ReservedNetBIOSAddress[10], DeviceContext->LocalAddress.Address, 6);
|
|
|
|
|
|
//
|
|
// Now query the maximum packet sizes.
|
|
//
|
|
|
|
StRequest.RequestType = NdisRequestQueryInformation;
|
|
StRequest.DATA.QUERY_INFORMATION.Oid = OID_GEN_MAXIMUM_FRAME_SIZE;
|
|
StRequest.DATA.QUERY_INFORMATION.InformationBuffer = &(DeviceContext->MaxReceivePacketSize);
|
|
StRequest.DATA.QUERY_INFORMATION.InformationBufferLength = 4;
|
|
|
|
NdisStatus = StSubmitNdisRequest (DeviceContext, &StRequest, AdapterString);
|
|
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS) {
|
|
StCloseNdis (DeviceContext);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
|
|
StRequest.RequestType = NdisRequestQueryInformation;
|
|
StRequest.DATA.QUERY_INFORMATION.Oid = OID_GEN_MAXIMUM_TOTAL_SIZE;
|
|
StRequest.DATA.QUERY_INFORMATION.InformationBuffer = &(DeviceContext->MaxSendPacketSize);
|
|
StRequest.DATA.QUERY_INFORMATION.InformationBufferLength = 4;
|
|
|
|
NdisStatus = StSubmitNdisRequest (DeviceContext, &StRequest, AdapterString);
|
|
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS) {
|
|
StCloseNdis (DeviceContext);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
|
|
//
|
|
// Now set the minimum lookahead size.
|
|
//
|
|
|
|
StRequest.RequestType = NdisRequestSetInformation;
|
|
StRequest.DATA.QUERY_INFORMATION.Oid = OID_GEN_CURRENT_LOOKAHEAD;
|
|
StRequest.DATA.QUERY_INFORMATION.InformationBuffer = &MinimumLookahead;
|
|
StRequest.DATA.QUERY_INFORMATION.InformationBufferLength = 4;
|
|
|
|
NdisStatus = StSubmitNdisRequest (DeviceContext, &StRequest, AdapterString);
|
|
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS) {
|
|
StCloseNdis (DeviceContext);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
|
|
//
|
|
// Now query the link speed
|
|
//
|
|
|
|
StRequest.RequestType = NdisRequestQueryInformation;
|
|
StRequest.DATA.QUERY_INFORMATION.Oid = OID_GEN_LINK_SPEED;
|
|
StRequest.DATA.QUERY_INFORMATION.InformationBuffer = &(DeviceContext->MediumSpeed);
|
|
StRequest.DATA.QUERY_INFORMATION.InformationBufferLength = 4;
|
|
|
|
NdisStatus = StSubmitNdisRequest (DeviceContext, &StRequest, AdapterString);
|
|
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS) {
|
|
StCloseNdis (DeviceContext);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
|
|
//
|
|
// Now query the MAC's optional characteristics.
|
|
//
|
|
|
|
StRequest.RequestType = NdisRequestQueryInformation;
|
|
StRequest.DATA.QUERY_INFORMATION.Oid = OID_GEN_MAC_OPTIONS;
|
|
StRequest.DATA.QUERY_INFORMATION.InformationBuffer = &MacOptions;
|
|
StRequest.DATA.QUERY_INFORMATION.InformationBufferLength = 4;
|
|
|
|
NdisStatus = StSubmitNdisRequest (DeviceContext, &StRequest, AdapterString);
|
|
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS) {
|
|
StCloseNdis (DeviceContext);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
//
|
|
// Since the sample transport does not try to optimize for the
|
|
// cases where transfer data is always synchronous or indications
|
|
// are not reentered, we ignore those bits in MacOptions.
|
|
//
|
|
|
|
DeviceContext->MacInfo.CopyLookahead =
|
|
(BOOLEAN)((MacOptions & NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA) != 0);
|
|
|
|
|
|
//
|
|
// Now set our options if needed. We can only support
|
|
// partial indications if running over 802.3 where the
|
|
// real packet length can be obtained from the header.
|
|
//
|
|
|
|
if (DeviceContext->MacInfo.MediumType == NdisMedium802_3) {
|
|
|
|
ProtocolOptions = NDIS_PROT_OPTION_ESTIMATED_LENGTH;
|
|
|
|
StRequest.RequestType = NdisRequestSetInformation;
|
|
StRequest.DATA.QUERY_INFORMATION.Oid = OID_GEN_PROTOCOL_OPTIONS;
|
|
StRequest.DATA.QUERY_INFORMATION.InformationBuffer = &ProtocolOptions;
|
|
StRequest.DATA.QUERY_INFORMATION.InformationBufferLength = 4;
|
|
|
|
NdisStatus = StSubmitNdisRequest (DeviceContext, &StRequest, AdapterString);
|
|
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS) {
|
|
StCloseNdis (DeviceContext);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// Calculate the NDIS-related stuff.
|
|
//
|
|
|
|
SendPacketReservedLength = sizeof (SEND_PACKET_TAG);
|
|
ReceivePacketReservedLen = sizeof (RECEIVE_PACKET_TAG);
|
|
|
|
//
|
|
// The send packet pool is used for UI frames and regular packets.
|
|
//
|
|
|
|
SendPacketPoolSize = StConfig->SendPacketPoolSize;
|
|
|
|
//
|
|
// The receive packet pool is used in transfer data.
|
|
//
|
|
|
|
ReceivePacketPoolSize = StConfig->ReceivePacketPoolSize;
|
|
|
|
|
|
NdisAllocatePacketPool (
|
|
&NdisStatus,
|
|
&DeviceContext->SendPacketPoolHandle,
|
|
SendPacketPoolSize,
|
|
SendPacketReservedLength);
|
|
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS) {
|
|
DeviceContext->SendPacketPoolHandle = NULL;
|
|
StCloseNdis (DeviceContext);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
DeviceContext->MemoryUsage +=
|
|
(SendPacketPoolSize *
|
|
(sizeof(NDIS_PACKET) + SendPacketReservedLength));
|
|
|
|
|
|
NdisAllocatePacketPool(
|
|
&NdisStatus,
|
|
&DeviceContext->ReceivePacketPoolHandle,
|
|
ReceivePacketPoolSize,
|
|
ReceivePacketReservedLen);
|
|
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS) {
|
|
DeviceContext->ReceivePacketPoolHandle = NULL;
|
|
StCloseNdis (DeviceContext);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
DeviceContext->MemoryUsage +=
|
|
(ReceivePacketPoolSize *
|
|
(sizeof(NDIS_PACKET) + ReceivePacketReservedLen));
|
|
|
|
|
|
//
|
|
// Allocate the buffer pool; as an estimate, allocate
|
|
// one per send or receive packet.
|
|
//
|
|
|
|
NdisAllocateBufferPool (
|
|
&NdisStatus,
|
|
&DeviceContext->NdisBufferPoolHandle,
|
|
SendPacketPoolSize + ReceivePacketPoolSize);
|
|
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS) {
|
|
DeviceContext->NdisBufferPoolHandle = NULL;
|
|
StCloseNdis (DeviceContext);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
|
|
//
|
|
// Now that everything is set up, we enable the filter
|
|
// for packet reception.
|
|
//
|
|
|
|
//
|
|
// Fill in the OVB for packet filter.
|
|
//
|
|
|
|
switch (DeviceContext->MacInfo.MediumType) {
|
|
|
|
case NdisMedium802_3:
|
|
case NdisMediumFddi:
|
|
|
|
RtlStoreUlong((PULONG)StDataBuffer,
|
|
(NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_MULTICAST));
|
|
break;
|
|
|
|
case NdisMedium802_5:
|
|
|
|
RtlStoreUlong((PULONG)StDataBuffer,
|
|
(NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_FUNCTIONAL));
|
|
break;
|
|
|
|
default:
|
|
|
|
ASSERT (FALSE);
|
|
break;
|
|
|
|
}
|
|
|
|
//
|
|
// Now fill in the NDIS_REQUEST.
|
|
//
|
|
|
|
StRequest.RequestType = NdisRequestSetInformation;
|
|
StRequest.DATA.SET_INFORMATION.Oid = OID_GEN_CURRENT_PACKET_FILTER;
|
|
StRequest.DATA.SET_INFORMATION.InformationBuffer = &StDataBuffer;
|
|
StRequest.DATA.SET_INFORMATION.InformationBufferLength = sizeof(ULONG);
|
|
|
|
NdisStatus = StSubmitNdisRequest (DeviceContext, &StRequest, AdapterString);
|
|
|
|
if (NdisStatus != NDIS_STATUS_SUCCESS) {
|
|
StCloseNdis (DeviceContext);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
} /* StInitializeNdis */
|
|
|
|
|
|
VOID
|
|
StCloseNdis (
|
|
IN PDEVICE_CONTEXT DeviceContext
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine unbinds the transport from the NDIS interface and does
|
|
any other work required to undo what was done in StInitializeNdis.
|
|
It is written so that it can be called from within StInitializeNdis
|
|
if it fails partway through.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - Pointer to the device object for this driver.
|
|
|
|
Return Value:
|
|
|
|
The function value is the status of the operation.
|
|
|
|
--*/
|
|
{
|
|
NDIS_STATUS ndisStatus;
|
|
|
|
//
|
|
// Close the NDIS binding.
|
|
//
|
|
|
|
if (DeviceContext->NdisBindingHandle != (NDIS_HANDLE)NULL) {
|
|
|
|
//
|
|
// This event is used in case any of the NDIS requests
|
|
// pend; we wait until it is set by the completion
|
|
// routine, which also sets NdisRequestStatus.
|
|
//
|
|
|
|
KeInitializeEvent(
|
|
&DeviceContext->NdisRequestEvent,
|
|
NotificationEvent,
|
|
FALSE
|
|
);
|
|
|
|
NdisCloseAdapter(
|
|
&ndisStatus,
|
|
DeviceContext->NdisBindingHandle);
|
|
|
|
if (ndisStatus == NDIS_STATUS_PENDING) {
|
|
|
|
//
|
|
// The completion routine will set NdisRequestStatus.
|
|
//
|
|
|
|
KeWaitForSingleObject(
|
|
&DeviceContext->NdisRequestEvent,
|
|
Executive,
|
|
KernelMode,
|
|
TRUE,
|
|
(PLARGE_INTEGER)NULL
|
|
);
|
|
|
|
ndisStatus = DeviceContext->NdisRequestStatus;
|
|
|
|
KeResetEvent(
|
|
&DeviceContext->NdisRequestEvent
|
|
);
|
|
|
|
}
|
|
|
|
//
|
|
// We ignore ndisStatus.
|
|
//
|
|
|
|
}
|
|
|
|
if (DeviceContext->SendPacketPoolHandle != NULL) {
|
|
NdisFreePacketPool (DeviceContext->SendPacketPoolHandle);
|
|
}
|
|
|
|
if (DeviceContext->ReceivePacketPoolHandle != NULL) {
|
|
NdisFreePacketPool (DeviceContext->ReceivePacketPoolHandle);
|
|
}
|
|
|
|
if (DeviceContext->NdisBufferPoolHandle != NULL) {
|
|
NdisFreeBufferPool (DeviceContext->NdisBufferPoolHandle);
|
|
}
|
|
|
|
} /* StCloseNdis */
|
|
|
|
|
|
VOID
|
|
StOpenAdapterComplete (
|
|
IN NDIS_HANDLE BindingContext,
|
|
IN NDIS_STATUS NdisStatus,
|
|
IN NDIS_STATUS OpenErrorStatus
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called by NDIS to indicate that an open adapter
|
|
is complete. Since we only ever have one outstanding, and then only
|
|
during initialization, all we do is record the status and set
|
|
the event to signalled to unblock the initialization thread.
|
|
|
|
Arguments:
|
|
|
|
BindingContext - Pointer to the device object for this driver.
|
|
|
|
NdisStatus - The request completion code.
|
|
|
|
OpenErrorStatus - More status information.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEVICE_CONTEXT DeviceContext = (PDEVICE_CONTEXT)BindingContext;
|
|
|
|
DeviceContext->NdisRequestStatus = NdisStatus;
|
|
KeSetEvent(
|
|
&DeviceContext->NdisRequestEvent,
|
|
0L,
|
|
FALSE);
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
StCloseAdapterComplete (
|
|
IN NDIS_HANDLE BindingContext,
|
|
IN NDIS_STATUS NdisStatus
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called by NDIS to indicate that a close adapter
|
|
is complete. Currently we don't close adapters, so this is not
|
|
a problem.
|
|
|
|
Arguments:
|
|
|
|
BindingContext - Pointer to the device object for this driver.
|
|
|
|
NdisStatus - The request completion code.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEVICE_CONTEXT DeviceContext = (PDEVICE_CONTEXT)BindingContext;
|
|
|
|
DeviceContext->NdisRequestStatus = NdisStatus;
|
|
KeSetEvent(
|
|
&DeviceContext->NdisRequestEvent,
|
|
0L,
|
|
FALSE);
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
StResetComplete (
|
|
IN NDIS_HANDLE BindingContext,
|
|
IN NDIS_STATUS NdisStatus
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called by NDIS to indicate that a reset adapter
|
|
is complete. Currently we don't reset adapters, so this is not
|
|
a problem.
|
|
|
|
Arguments:
|
|
|
|
BindingContext - Pointer to the device object for this driver.
|
|
|
|
NdisStatus - The request completion code.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
UNREFERENCED_PARAMETER(BindingContext);
|
|
UNREFERENCED_PARAMETER(NdisStatus);
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
StRequestComplete (
|
|
IN NDIS_HANDLE BindingContext,
|
|
IN PNDIS_REQUEST NdisRequest,
|
|
IN NDIS_STATUS NdisStatus
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called by NDIS to indicate that a request is complete.
|
|
Since we only ever have one request outstanding, and then only
|
|
during initialization, all we do is record the status and set
|
|
the event to signalled to unblock the initialization thread.
|
|
|
|
Arguments:
|
|
|
|
BindingContext - Pointer to the device object for this driver.
|
|
|
|
NdisRequest - The object describing the request.
|
|
|
|
NdisStatus - The request completion code.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEVICE_CONTEXT DeviceContext = (PDEVICE_CONTEXT)BindingContext;
|
|
|
|
DeviceContext->NdisRequestStatus = NdisStatus;
|
|
KeSetEvent(
|
|
&DeviceContext->NdisRequestEvent,
|
|
0L,
|
|
FALSE);
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
StStatusIndication (
|
|
IN NDIS_HANDLE NdisBindingContext,
|
|
IN NDIS_STATUS NdisStatus,
|
|
IN PVOID StatusBuffer,
|
|
IN UINT StatusBufferSize
|
|
)
|
|
|
|
{
|
|
PDEVICE_CONTEXT DeviceContext;
|
|
|
|
DeviceContext = (PDEVICE_CONTEXT)NdisBindingContext;
|
|
|
|
switch (NdisStatus) {
|
|
|
|
//
|
|
// Handle various status codes here.
|
|
//
|
|
|
|
default:
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
StStatusComplete (
|
|
IN NDIS_HANDLE NdisBindingContext
|
|
)
|
|
{
|
|
UNREFERENCED_PARAMETER (NdisBindingContext);
|
|
|
|
}
|