2 * Copyright (c) 1999, 2000
3 * Politecnico di Torino. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the Politecnico
13 * di Torino, and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27 #include <ddk/ntddk.h>
28 //#include <net/miniport.h>
35 static NDIS_MEDIUM MediumArray
[] = {
39 NdisMediumArcnet878_2
,
44 ULONG NamedEventsCounter
=0;
46 #define NUM_NDIS_MEDIA (sizeof MediumArray / sizeof MediumArray[0])
49 //Itoa. Replaces the buggy RtlIntegerToUnicodeString
50 void PacketItoa(UINT n
,PUCHAR buf
){
63 PacketOpen(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
)
66 PDEVICE_EXTENSION DeviceExtension
;
70 PIO_STACK_LOCATION IrpSp
;
73 NDIS_STATUS ErrorStatus
;
77 PLIST_ENTRY PacketListEntry
;
78 LARGE_INTEGER TimeFreq
;
79 LARGE_INTEGER SystemTime
;
83 IF_LOUD(DbgPrint("Packet: OpenAdapter\n");)
85 DeviceExtension
= DeviceObject
->DeviceExtension
;
88 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
92 // allocate some memory for the open structure
94 Open
=ExAllocatePool(NonPagedPool
,sizeof(OPEN_INSTANCE
));
101 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
102 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
103 return STATUS_INSUFFICIENT_RESOURCES
;
108 sizeof(OPEN_INSTANCE
)
112 EvName
=ExAllocatePool(NonPagedPool
, sizeof(L
"\\BaseNamedObjects\\NPF0000000000") );
119 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
120 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
121 return STATUS_INSUFFICIENT_RESOURCES
;
127 IrpSp
->FileObject
->FsContext
=Open
;
129 Open
->DeviceExtension
=DeviceExtension
;
133 // Save the Irp here for the completeion routine to retrieve
135 Open
->OpenCloseIrp
=Irp
;
138 // Allocate a packet pool for our xmit and receive packets
140 NdisAllocatePacketPool(
144 sizeof(PACKET_RESERVED
));
147 if (Status
!= NDIS_STATUS_SUCCESS
) {
149 IF_LOUD(DbgPrint("Packet: Failed to allocate packet pool\n");)
153 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
154 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
155 return STATUS_INSUFFICIENT_RESOURCES
;
159 RtlCopyBytes(EvName
,L
"\\BaseNamedObjects\\NPF0000000000",sizeof(L
"\\BaseNamedObjects\\NPF0000000000"));
161 //Create the string containing the name of the read event
162 RtlInitUnicodeString(&Open
->ReadEventName
,(PCWSTR
) EvName
);
163 PacketItoa(NamedEventsCounter
,(PUCHAR
)(Open
->ReadEventName
.Buffer
+21));
165 InterlockedIncrement(&NamedEventsCounter
);
167 IF_LOUD(DbgPrint("\nCreated the named event for the read; name=%ws, counter=%d\n", Open
->ReadEventName
.Buffer
,NamedEventsCounter
-1);)
169 //allocate the event objects
170 Open
->ReadEvent
=IoCreateNotificationEvent(&Open
->ReadEventName
,&Open
->ReadEventHandle
);
171 if(Open
->ReadEvent
==NULL
){
173 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
174 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
175 return STATUS_INSUFFICIENT_RESOURCES
;
178 KeInitializeEvent(Open
->ReadEvent
, NotificationEvent
, FALSE
);
179 KeClearEvent(Open
->ReadEvent
);
180 NdisInitializeEvent(&Open
->WriteEvent
);
181 NdisInitializeEvent(&Open
->IOEvent
);
184 // list to hold irp's want to reset the adapter
186 InitializeListHead(&Open
->ResetIrpList
);
190 // Initialize list for holding pending read requests
192 KeInitializeSpinLock(&Open
->RcvQSpinLock
);
193 InitializeListHead(&Open
->RcvList
);
196 // Initialize the request list
198 KeInitializeSpinLock(&Open
->RequestSpinLock
);
199 InitializeListHead(&Open
->RequestList
);
202 // get the absolute value of the system boot time.
203 PTime
=KeQueryPerformanceCounter(&TimeFreq
);
204 KeQuerySystemTime(&SystemTime
);
205 #ifndef __NTDRIVER__ // robert
206 Open
->StartTime
.QuadPart
=(((SystemTime
.QuadPart
)%10000000)*TimeFreq
.QuadPart
)/10000000;
207 SystemTime
.QuadPart
=SystemTime
.QuadPart
/10000000-11644473600;
209 Open
->StartTime
.QuadPart
+=(SystemTime
.QuadPart
)*TimeFreq
.QuadPart
-PTime
.QuadPart
;
210 //initalize the open instance
216 Open
->Dropped
=0; //reset the dropped packets counter
217 Open
->Received
=0; //reset the received packets counter
218 Open
->bpfprogram
=NULL
; //reset the filter
219 Open
->mode
=MODE_CAPT
;
220 Open
->Nbytes
.QuadPart
=0;
221 Open
->Npackets
.QuadPart
=0;
223 Open
->Multiple_Write_Counter
=0;
225 Open
->TimeOut
.QuadPart
=(LONGLONG
)1;
228 //allocate the spinlock for the statistic counters
229 NdisAllocateSpinLock(&Open
->CountersLock
);
231 //allocate the spinlock for the buffer pointers
232 NdisAllocateSpinLock(&Open
->BufLock
);
235 // link up the request stored in our open block
237 for (i
=0;i
<MAX_REQUESTS
;i
++) {
238 ExInterlockedInsertTailList(
240 &Open
->Requests
[i
].ListElement
,
241 &Open
->RequestSpinLock
);
246 IoMarkIrpPending(Irp
);
250 // Try to open the MAC
252 IF_LOUD(DbgPrint("Packet: Openinig the device %ws, BindingContext=%d\n",DeviceExtension
->AdapterName
.Buffer
, Open
);)
257 &Open
->AdapterHandle
,
261 DeviceExtension
->NdisProtocolHandle
,
263 &DeviceExtension
->AdapterName
,
267 IF_LOUD(DbgPrint("Packet: Opened the device, Status=%x\n",Status
);)
269 if (Status
!= NDIS_STATUS_PENDING
)
271 PacketOpenAdapterComplete(Open
,Status
,NDIS_STATUS_SUCCESS
);
274 return(STATUS_PENDING
);
277 //-------------------------------------------------------------------
279 VOID
PacketOpenAdapterComplete(
280 IN NDIS_HANDLE ProtocolBindingContext
,
281 IN NDIS_STATUS Status
,
282 IN NDIS_STATUS OpenErrorStatus
)
288 IF_LOUD(DbgPrint("Packet: OpenAdapterComplete\n");)
290 Open
= (POPEN_INSTANCE
)ProtocolBindingContext
;
295 Irp
=Open
->OpenCloseIrp
;
297 if (Status
!= NDIS_STATUS_SUCCESS
) {
299 IF_LOUD(DbgPrint("Packet: OpenAdapterComplete-FAILURE\n");)
301 NdisFreePacketPool(Open
->PacketPool
);
303 ExFreePool(Open
->ReadEventName
.Buffer
);
308 Irp
->IoStatus
.Status
= Status
;
309 Irp
->IoStatus
.Information
= 0;
310 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
316 //-------------------------------------------------------------------
319 PacketClose(IN PDEVICE_OBJECT DeviceObject
,IN PIRP Irp
)
324 PIO_STACK_LOCATION IrpSp
;
327 IF_LOUD(DbgPrint("Packet: CloseAdapter\n");)
329 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
331 Open
=IrpSp
->FileObject
->FsContext
;
333 if( Open
->Bound
== FALSE
){
335 NdisWaitEvent(&Open
->IOEvent
,10000);
337 //free the bpf program
338 if(Open
->bpfprogram
!=NULL
)ExFreePool(Open
->bpfprogram
);
342 if(Open
->Buffer
!=NULL
)ExFreePool(Open
->Buffer
);
344 NdisFreePacketPool(Open
->PacketPool
);
346 ExFreePool(Open
->ReadEventName
.Buffer
);
349 Irp
->IoStatus
.Information
= 0;
350 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
351 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
353 return(STATUS_SUCCESS
);
356 // Eventually unfreeze PacketRead
357 KeSetEvent(Open
->ReadEvent
,0,FALSE
);
359 // Destroy the read Event
360 ZwClose(Open
->ReadEventHandle
);
363 Open
->OpenCloseIrp
=Irp
;
365 IoMarkIrpPending(Irp
);
373 if (Status
!= NDIS_STATUS_PENDING
) {
375 PacketCloseAdapterComplete(
379 return STATUS_SUCCESS
;
383 return(STATUS_PENDING
);
386 //-------------------------------------------------------------------
389 PacketCloseAdapterComplete(IN NDIS_HANDLE ProtocolBindingContext
,IN NDIS_STATUS Status
)
394 IF_LOUD(DbgPrint("Packet: CloseAdapterComplete\n");)
396 Open
= (POPEN_INSTANCE
)ProtocolBindingContext
;
398 // free the allocated structures only if the instance is still bound to the adapter
399 if(Open
->Bound
== TRUE
){
401 //free the bpf program
402 if(Open
->bpfprogram
!=NULL
)ExFreePool(Open
->bpfprogram
);
406 if(Open
->Buffer
!=NULL
)ExFreePool(Open
->Buffer
);
408 NdisFreePacketPool(Open
->PacketPool
);
410 Irp
=Open
->OpenCloseIrp
;
412 ExFreePool(Open
->ReadEventName
.Buffer
);
415 // Complete the request only if the instance is still bound to the adapter
416 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
417 Irp
->IoStatus
.Information
= 0;
418 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
421 NdisSetEvent(&Open
->IOEvent
);
428 //-------------------------------------------------------------------
432 OUT PNDIS_STATUS Status
,
433 IN NDIS_HANDLE BindContext
,
434 IN PNDIS_STRING DeviceName
,
435 IN PVOID SystemSpecific1
,
436 IN PVOID SystemSpecific2
439 IF_LOUD(DbgPrint("Packet: PacketBindAdapter\n");)
442 //-------------------------------------------------------------------
446 OUT PNDIS_STATUS Status
,
447 IN NDIS_HANDLE ProtocolBindingContext
,
448 IN NDIS_HANDLE UnbindContext
451 POPEN_INSTANCE Open
=(POPEN_INSTANCE
)ProtocolBindingContext
;
454 IF_LOUD(DbgPrint("Packet: PacketUNBindAdapter\n");)
456 NdisResetEvent(&Open
->IOEvent
);
458 // This open instance is no more bound to the adapter, set Bound to False
459 InterlockedExchange( (PLONG
) &Open
->Bound
, FALSE
);
461 // Awake a possible pending read on this instance
462 KeSetEvent(Open
->ReadEvent
,0,FALSE
);
464 // Destroy the read Event
465 ZwClose(Open
->ReadEventHandle
);
473 if (lStatus
!= NDIS_STATUS_PENDING
) {
475 PacketCloseAdapterComplete(
480 *Status
= NDIS_STATUS_SUCCESS
;
485 *Status
= NDIS_STATUS_SUCCESS
;
489 //-------------------------------------------------------------------
492 PacketResetComplete(IN NDIS_HANDLE ProtocolBindingContext
,IN NDIS_STATUS Status
)
498 PLIST_ENTRY ResetListEntry
;
500 IF_LOUD(DbgPrint("Packet: PacketResetComplte\n");)
502 Open
= (POPEN_INSTANCE
)ProtocolBindingContext
;
506 // remove the reset IRP from the list
508 ResetListEntry
=ExInterlockedRemoveHeadList(
510 &Open
->RequestSpinLock
514 if (ResetListEntry
== NULL
) {
520 Irp
=CONTAINING_RECORD(ResetListEntry
,IRP
,Tail
.Overlay
.ListEntry
);
522 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
523 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
525 IF_LOUD(DbgPrint("Packet: PacketResetComplte exit\n");)