#include "ndissys.h"
+#include <ndisguid.h>
+
/*
* Define to 1 to get a debugger breakpoint at the end of NdisInitializeWrapper
* for each new miniport starting up
while (CurrentEntry)
{
- if (CurrentEntry->WorkItemType == Type)
+ if (CurrentEntry->WorkItemType == Type || Type == NdisMaxWorkItems)
return CurrentEntry;
CurrentEntry = (PNDIS_MINIPORT_WORK_ITEM)CurrentEntry->Link.Next;
KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
- if (Type == NdisWorkItemRequest &&
- (Adapter->NdisMiniportBlock.PendingRequest || MiniGetFirstWorkItem(Adapter, NdisWorkItemRequest)))
+ if (MiniGetFirstWorkItem(Adapter, Type))
+ {
+ Busy = TRUE;
+ }
+ else if (Type == NdisWorkItemRequest && Adapter->NdisMiniportBlock.PendingRequest)
{
Busy = TRUE;
}
- else if (Type == NdisWorkItemSend &&
- (Adapter->NdisMiniportBlock.FirstPendingPacket || MiniGetFirstWorkItem(Adapter, NdisWorkItemSend)))
+ else if (Type == NdisWorkItemSend && Adapter->NdisMiniportBlock.FirstPendingPacket)
{
Busy = TRUE;
}
else if (Type == NdisWorkItemResetRequested &&
- (Adapter->NdisMiniportBlock.ResetStatus == NDIS_STATUS_PENDING || MiniGetFirstWorkItem(Adapter, NdisWorkItemResetRequested)))
+ Adapter->NdisMiniportBlock.ResetStatus == NDIS_STATUS_PENDING)
{
Busy = TRUE;
}
&NdisBufferVA,
&FirstBufferLength,
&TotalBufferLength);
-
+
HeaderSize = NDIS_GET_PACKET_HEADER_SIZE(PacketArray[i]);
LookAheadSize = TotalBufferLength - HeaderSize;
KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
return;
}
-
+
CopyBufferChainToBuffer(LookAheadBuffer,
NdisBuffer,
HeaderSize,
LookAheadSize);
-
+
NDIS_DbgPrint(MID_TRACE, ("Indicating packet to protocol's legacy Receive handler\n"));
(*AdapterBinding->ProtocolBinding->Chars.ReceiveHandler)(
AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
LookAheadBuffer,
LookAheadSize,
TotalBufferLength - HeaderSize);
-
+
ExFreePool(LookAheadBuffer);
}
}
MacBlock = (PNDIS_REQUEST_MAC_BLOCK)Request->MacReserved;
- if( MacBlock->Binding->RequestCompleteHandler ) {
- (*MacBlock->Binding->RequestCompleteHandler)(
- MacBlock->Binding->ProtocolBindingContext,
- Request,
- Status);
+ /* We may or may not be doing this request on behalf of an adapter binding */
+ if (MacBlock->Binding != NULL)
+ {
+ /* We are, so invoke its request complete handler */
+ if (MacBlock->Binding->RequestCompleteHandler != NULL)
+ {
+ (*MacBlock->Binding->RequestCompleteHandler)(
+ MacBlock->Binding->ProtocolBindingContext,
+ Request,
+ Status);
+ }
+ }
+ else
+ {
+ /* We are doing this internally, so we'll signal this event we've stashed in the MacBlock */
+ ASSERT(MacBlock->Unknown1 != NULL);
+ ASSERT(MacBlock->Unknown3 == NULL);
+ MacBlock->Unknown3 = (PVOID)Status;
+ KeSetEvent(MacBlock->Unknown1, IO_NO_INCREMENT, FALSE);
}
KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
Adapter->NdisMiniportBlock.PendingRequest = NULL;
KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
-
KeLowerIrql(OldIrql);
+
+ MiniWorkItemComplete(Adapter, NdisWorkItemRequest);
}
VOID NTAPI
Status);
KeLowerIrql(OldIrql);
+
+ MiniWorkItemComplete(Adapter, NdisWorkItemSend);
}
MiniSendResourcesAvailable(
IN NDIS_HANDLE MiniportAdapterHandle)
{
-/*
- UNIMPLEMENTED
-*/
+ /* Run the work if anything is waiting */
+ MiniWorkItemComplete((PLOGICAL_ADAPTER)MiniportAdapterHandle, NdisWorkItemSend);
}
KeAcquireSpinLock(&AdapterListLock, &OldIrql);
{
CurrentEntry = AdapterListHead.Flink;
-
+
while (CurrentEntry != &AdapterListHead)
{
Adapter = CONTAINING_RECORD(CurrentEntry, LOGICAL_ADAPTER, ListEntry);
{
NDIS_STATUS NdisStatus;
PNDIS_REQUEST NdisRequest;
+ KEVENT Event;
+ PNDIS_REQUEST_MAC_BLOCK MacBlock;
NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
NdisRequest->DATA.SET_INFORMATION.InformationBuffer = Buffer;
NdisRequest->DATA.SET_INFORMATION.InformationBufferLength = Size;
- NdisStatus = MiniDoRequest(Adapter, NdisRequest);
+ /* We'll need to give the completion routine some way of letting us know
+ * when it's finished. We'll stash a pointer to an event in the MacBlock */
+ KeInitializeEvent(&Event, NotificationEvent, FALSE);
+ MacBlock = (PNDIS_REQUEST_MAC_BLOCK)NdisRequest->MacReserved;
+ MacBlock->Unknown1 = &Event;
- /* FIXME: Wait in pending case! */
+ NdisStatus = MiniDoRequest(Adapter, NdisRequest);
- ASSERT(NdisStatus != NDIS_STATUS_PENDING);
+ if (NdisStatus == NDIS_STATUS_PENDING)
+ {
+ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+ NdisStatus = (NDIS_STATUS)MacBlock->Unknown3;
+ }
*BytesRead = NdisRequest->DATA.SET_INFORMATION.BytesRead;
{
NDIS_STATUS NdisStatus;
PNDIS_REQUEST NdisRequest;
+ KEVENT Event;
+ PNDIS_REQUEST_MAC_BLOCK MacBlock;
NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer = Buffer;
NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength = Size;
- NdisStatus = MiniDoRequest(Adapter, NdisRequest);
+ /* We'll need to give the completion routine some way of letting us know
+ * when it's finished. We'll stash a pointer to an event in the MacBlock */
+ KeInitializeEvent(&Event, NotificationEvent, FALSE);
+ MacBlock = (PNDIS_REQUEST_MAC_BLOCK)NdisRequest->MacReserved;
+ MacBlock->Unknown1 = &Event;
- /* FIXME: Wait in pending case! */
+ NdisStatus = MiniDoRequest(Adapter, NdisRequest);
- ASSERT(NdisStatus != NDIS_STATUS_PENDING);
+ if (NdisStatus == NDIS_STATUS_PENDING)
+ {
+ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+ NdisStatus = (NDIS_STATUS)MacBlock->Unknown3;
+ }
*BytesWritten = NdisRequest->DATA.QUERY_INFORMATION.BytesWritten;
NdisMIndicateStatus(Adapter, NDIS_STATUS_RESET_END, NULL, 0);
NdisMIndicateStatusComplete(Adapter);
+
+ MiniWorkItemComplete(Adapter, NdisWorkItemResetRequested);
}
return Status;
}
}
+VOID
+MiniWorkItemComplete(
+ PLOGICAL_ADAPTER Adapter,
+ NDIS_WORK_ITEM_TYPE WorkItemType)
+{
+ PIO_WORKITEM IoWorkItem;
+
+ /* Check if there's anything queued to run after this work item */
+ if (!MiniIsBusy(Adapter, WorkItemType))
+ return;
+
+ /* There is, so fire the worker */
+ IoWorkItem = IoAllocateWorkItem(Adapter->NdisMiniportBlock.DeviceObject);
+ if (IoWorkItem)
+ IoQueueWorkItem(IoWorkItem, MiniportWorker, DelayedWorkQueue, IoWorkItem);
+}
+
VOID
FASTCALL
MiniQueueWorkItem(
*/
{
PNDIS_MINIPORT_WORK_ITEM MiniportWorkItem;
- PIO_WORKITEM IoWorkItem;
KIRQL OldIrql;
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
}
}
- IoWorkItem = IoAllocateWorkItem(Adapter->NdisMiniportBlock.DeviceObject);
- if (IoWorkItem)
- IoQueueWorkItem(IoWorkItem, MiniportWorker, DelayedWorkQueue, IoWorkItem);
-
KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
}
}
KeLowerIrql(OldIrql);
+
+ if (Status != NDIS_STATUS_PENDING) {
+ MiniWorkItemComplete(Adapter, NdisWorkItemRequest);
+ }
+
return Status;
}
if (NdisStatus == NDIS_STATUS_PENDING)
break;
+ Adapter->NdisMiniportBlock.PendingRequest = (PNDIS_REQUEST)WorkItemContext;
switch (((PNDIS_REQUEST)WorkItemContext)->RequestType)
{
case NdisRequestQueryInformation:
- NdisMQueryInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
+ NdisMQueryInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
break;
case NdisRequestSetInformation:
NDIS_DbgPrint(MIN_TRACE, ("Unknown NDIS request type.\n"));
break;
}
+ Adapter->NdisMiniportBlock.PendingRequest = NULL;
break;
default:
NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
+ if (Adapter->BugcheckContext != NULL)
+ {
+ NDIS_DbgPrint(MIN_TRACE, ("Attempted to register again for a shutdown callback\n"));
+ return;
+ }
+
BugcheckContext = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_BUGCHECK_CONTEXT));
if(!BugcheckContext)
{
/*
* FUNCTION: Handle the PnP start device event
* ARGUMENTS:
- * DeviceObejct = Functional Device Object
+ * DeviceObject = Functional Device Object
* Irp = IRP_MN_START_DEVICE I/O request packet
* RETURNS:
* Status of operation
if (NdisStatus != NDIS_STATUS_SUCCESS)
{
- NDIS_DbgPrint(MIN_TRACE, ("MiniportInitialize() failed for an adapter.\n"));
+ NDIS_DbgPrint(MIN_TRACE, ("MiniportInitialize() failed for an adapter (%lx).\n", NdisStatus));
ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
if (Adapter->NdisMiniportBlock.Interrupt)
{
/*
* FUNCTION: Handle the PnP stop device event
* ARGUMENTS:
- * DeviceObejct = Functional Device Object
+ * DeviceObject = Functional Device Object
* Irp = IRP_MN_STOP_DEVICE I/O request packet
* RETURNS:
* Status of operation
PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
NDIS_STATUS Status = STATUS_NOT_SUPPORTED;
+ ULONG ControlCode;
ULONG Written;
Irp->IoStatus.Information = 0;
ASSERT(Adapter);
- switch (Stack->Parameters.DeviceIoControl.IoControlCode)
+ ControlCode = Stack->Parameters.DeviceIoControl.IoControlCode;
+ switch (ControlCode)
{
case IOCTL_NDIS_QUERY_GLOBAL_STATS:
Status = MiniQueryInformation(Adapter,
break;
default:
- ASSERT(FALSE);
+ NDIS_DbgPrint(MIN_TRACE, ("NdisIDeviceIoControl: unsupported control code 0x%lx\n", ControlCode));
break;
}
return IoCallDriver(Adapter->NdisMiniportBlock.NextDeviceObject, Irp);
}
+NTSTATUS
+NTAPI
+NdisIPower(
+ _In_ PDEVICE_OBJECT DeviceObject,
+ _In_ PIRP Irp)
+{
+ PLOGICAL_ADAPTER Adapter = DeviceObject->DeviceExtension;
+
+ PoStartNextPowerIrp(Irp);
+ IoSkipCurrentIrpStackLocation(Irp);
+ return PoCallDriver(Adapter->NdisMiniportBlock.NextDeviceObject, Irp);
+}
+
NTSTATUS
NTAPI
NdisIAddDevice(
* Get name of the Linkage registry key for our adapter. It's located under
* the driver key for our driver and so we have basicly two ways to do it.
* Either we can use IoOpenDriverRegistryKey or compose it using information
- * gathered by IoGetDeviceProperty. I choosed the second because
+ * gathered by IoGetDeviceProperty. I chose the second because
* IoOpenDriverRegistryKey wasn't implemented at the time of writing.
*/
if (DeviceObject->DeviceType == FILE_DEVICE_PHYSICAL_NETCARD)
{
if ((IrpSp->MajorFunction == IRP_MJ_CREATE) ||
- (IrpSp->MajorFunction == IRP_MJ_CLOSE))
+ (IrpSp->MajorFunction == IRP_MJ_CLOSE) ||
+ (IrpSp->MajorFunction == IRP_MJ_CLEANUP))
{
return NdisICreateClose(DeviceObject, Irp);
}
{
return NdisIDeviceIoControl(DeviceObject, Irp);
}
+ else if (IrpSp->MajorFunction == IRP_MJ_POWER)
+ {
+ return NdisIPower(DeviceObject, Irp);
+ }
+ NDIS_DbgPrint(MIN_TRACE, ("Unexpected IRP MajorFunction 0x%x\n", IrpSp->MajorFunction));
+ ASSERT(FALSE);
}
else if (DeviceObject->DeviceType == FILE_DEVICE_NETWORK)
{
case 0x00:
MinSize = sizeof(NDIS50_MINIPORT_CHARACTERISTICS);
break;
-
+
case 0x01:
MinSize = sizeof(NDIS51_MINIPORT_CHARACTERISTICS);
break;
-
+
default:
NDIS_DbgPrint(MIN_TRACE, ("Bad 5.x minor characteristics version.\n"));
return NDIS_STATUS_BAD_VERSION;
return NDIS_STATUS_BAD_VERSION;
}
- NDIS_DbgPrint(MIN_TRACE, ("Initializing an NDIS %u.%u miniport\n",
+ NDIS_DbgPrint(MID_TRACE, ("Initializing an NDIS %u.%u miniport\n",
MiniportCharacteristics->MajorNdisVersion,
MiniportCharacteristics->MinorNdisVersion));
if (AttributeFlags & NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER)
NDIS_DbgPrint(MIN_TRACE, ("Intermediate drivers not supported yet.\n"));
- NDIS_DbgPrint(MIN_TRACE, ("Miniport attribute flags: 0x%x\n", AttributeFlags));
+ NDIS_DbgPrint(MID_TRACE, ("Miniport attribute flags: 0x%x\n", AttributeFlags));
if (Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.AdapterShutdownHandler)
{
NDIS_DbgPrint(MIN_TRACE, ("IoCreateDevice failed (%x)\n", Status));
return Status;
}
-
+
Status = IoCreateSymbolicLink(SymbolicName, DeviceName);
if (!NT_SUCCESS(Status))
}
/* EOF */
-