b30c605ea260f02bef713682bbda0970caf2fba4
[reactos.git] / reactos / drivers / net / packet / openclos.c
1 /*
2 * Copyright (c) 1999, 2000
3 * Politecnico di Torino. All rights reserved.
4 *
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
16 * written permission.
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.
20 */
21
22 #ifdef _MSC_VER
23 #include "ntddk.h"
24 #include "ntiologc.h"
25 #include "ndis.h"
26 #else
27 #include <ddk/ntddk.h>
28 //#include <net/miniport.h>
29 #include <net/ndis.h>
30 #endif
31
32 #include "debug.h"
33 #include "packet.h"
34
35 static NDIS_MEDIUM MediumArray[] = {
36 NdisMedium802_3,
37 NdisMediumWan,
38 NdisMediumFddi,
39 NdisMediumArcnet878_2,
40 NdisMediumAtm,
41 NdisMedium802_5
42 };
43
44 ULONG NamedEventsCounter=0;
45
46 #define NUM_NDIS_MEDIA (sizeof MediumArray / sizeof MediumArray[0])
47
48
49 //Itoa. Replaces the buggy RtlIntegerToUnicodeString
50 void PacketItoa(UINT n,PUCHAR buf){
51 int i;
52
53 for(i=0;i<20;i+=2){
54 buf[18-i]=(n%10)+48;
55 buf[19-i]=0;
56 n/=10;
57 }
58
59 }
60
61
62 NTSTATUS STDCALL
63 PacketOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
64 {
65
66 PDEVICE_EXTENSION DeviceExtension;
67
68 POPEN_INSTANCE Open;
69
70 PIO_STACK_LOCATION IrpSp;
71
72 NDIS_STATUS Status;
73 NDIS_STATUS ErrorStatus;
74 UINT Medium;
75 UINT i;
76 PUCHAR tpointer;
77 PLIST_ENTRY PacketListEntry;
78 LARGE_INTEGER TimeFreq;
79 LARGE_INTEGER SystemTime;
80 LARGE_INTEGER PTime;
81 PCHAR EvName;
82
83 IF_LOUD(DbgPrint("Packet: OpenAdapter\n");)
84
85 DeviceExtension = DeviceObject->DeviceExtension;
86
87
88 IrpSp = IoGetCurrentIrpStackLocation(Irp);
89
90
91 //
92 // allocate some memory for the open structure
93 //
94 Open=ExAllocatePool(NonPagedPool,sizeof(OPEN_INSTANCE));
95
96
97 if (Open==NULL) {
98 //
99 // no memory
100 //
101 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
102 IoCompleteRequest(Irp, IO_NO_INCREMENT);
103 return STATUS_INSUFFICIENT_RESOURCES;
104 }
105
106 RtlZeroMemory(
107 Open,
108 sizeof(OPEN_INSTANCE)
109 );
110
111
112 EvName=ExAllocatePool(NonPagedPool, sizeof(L"\\BaseNamedObjects\\NPF0000000000") );
113
114 if (EvName==NULL) {
115 //
116 // no memory
117 //
118 ExFreePool(Open);
119 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
120 IoCompleteRequest(Irp, IO_NO_INCREMENT);
121 return STATUS_INSUFFICIENT_RESOURCES;
122 }
123
124 //
125 // Save or open here
126 //
127 IrpSp->FileObject->FsContext=Open;
128
129 Open->DeviceExtension=DeviceExtension;
130
131
132 //
133 // Save the Irp here for the completeion routine to retrieve
134 //
135 Open->OpenCloseIrp=Irp;
136
137 //
138 // Allocate a packet pool for our xmit and receive packets
139 //
140 NdisAllocatePacketPool(
141 &Status,
142 &Open->PacketPool,
143 TRANSMIT_PACKETS,
144 sizeof(PACKET_RESERVED));
145
146
147 if (Status != NDIS_STATUS_SUCCESS) {
148
149 IF_LOUD(DbgPrint("Packet: Failed to allocate packet pool\n");)
150
151 ExFreePool(Open);
152 ExFreePool(EvName);
153 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
154 IoCompleteRequest(Irp, IO_NO_INCREMENT);
155 return STATUS_INSUFFICIENT_RESOURCES;
156 }
157
158
159 RtlCopyBytes(EvName,L"\\BaseNamedObjects\\NPF0000000000",sizeof(L"\\BaseNamedObjects\\NPF0000000000"));
160
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));
164
165 InterlockedIncrement(&NamedEventsCounter);
166
167 IF_LOUD(DbgPrint("\nCreated the named event for the read; name=%ws, counter=%d\n", Open->ReadEventName.Buffer,NamedEventsCounter-1);)
168
169 //allocate the event objects
170 Open->ReadEvent=IoCreateNotificationEvent(&Open->ReadEventName,&Open->ReadEventHandle);
171 if(Open->ReadEvent==NULL){
172 ExFreePool(Open);
173 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
174 IoCompleteRequest(Irp, IO_NO_INCREMENT);
175 return STATUS_INSUFFICIENT_RESOURCES;
176 }
177
178 KeInitializeEvent(Open->ReadEvent, NotificationEvent, FALSE);
179 KeClearEvent(Open->ReadEvent);
180 NdisInitializeEvent(&Open->WriteEvent);
181 NdisInitializeEvent(&Open->IOEvent);
182
183 //
184 // list to hold irp's want to reset the adapter
185 //
186 InitializeListHead(&Open->ResetIrpList);
187
188
189 //
190 // Initialize list for holding pending read requests
191 //
192 KeInitializeSpinLock(&Open->RcvQSpinLock);
193 InitializeListHead(&Open->RcvList);
194
195 //
196 // Initialize the request list
197 //
198 KeInitializeSpinLock(&Open->RequestSpinLock);
199 InitializeListHead(&Open->RequestList);
200
201
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;
208 #endif
209 Open->StartTime.QuadPart+=(SystemTime.QuadPart)*TimeFreq.QuadPart-PTime.QuadPart;
210 //initalize the open instance
211 Open->BufSize=0;
212 Open->Buffer=NULL;
213 Open->Bhead=0;
214 Open->Btail=0;
215 Open->BLastByte=0;
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;
222 Open->Nwrites=1;
223 Open->Multiple_Write_Counter=0;
224 Open->MinToCopy=0;
225 Open->TimeOut.QuadPart=(LONGLONG)1;
226 Open->Bound=TRUE;
227
228 //allocate the spinlock for the statistic counters
229 NdisAllocateSpinLock(&Open->CountersLock);
230
231 //allocate the spinlock for the buffer pointers
232 NdisAllocateSpinLock(&Open->BufLock);
233
234 //
235 // link up the request stored in our open block
236 //
237 for (i=0;i<MAX_REQUESTS;i++) {
238 ExInterlockedInsertTailList(
239 &Open->RequestList,
240 &Open->Requests[i].ListElement,
241 &Open->RequestSpinLock);
242
243 }
244
245
246 IoMarkIrpPending(Irp);
247
248
249 //
250 // Try to open the MAC
251 //
252 IF_LOUD(DbgPrint("Packet: Openinig the device %ws, BindingContext=%d\n",DeviceExtension->AdapterName.Buffer, Open);)
253
254 NdisOpenAdapter(
255 &Status,
256 &ErrorStatus,
257 &Open->AdapterHandle,
258 &Medium,
259 MediumArray,
260 NUM_NDIS_MEDIA,
261 DeviceExtension->NdisProtocolHandle,
262 Open,
263 &DeviceExtension->AdapterName,
264 0,
265 NULL);
266
267 IF_LOUD(DbgPrint("Packet: Opened the device, Status=%x\n",Status);)
268
269 if (Status != NDIS_STATUS_PENDING)
270 {
271 PacketOpenAdapterComplete(Open,Status,NDIS_STATUS_SUCCESS);
272 }
273
274 return(STATUS_PENDING);
275 }
276
277 //-------------------------------------------------------------------
278
279 VOID PacketOpenAdapterComplete(
280 IN NDIS_HANDLE ProtocolBindingContext,
281 IN NDIS_STATUS Status,
282 IN NDIS_STATUS OpenErrorStatus)
283 {
284
285 PIRP Irp;
286 POPEN_INSTANCE Open;
287
288 IF_LOUD(DbgPrint("Packet: OpenAdapterComplete\n");)
289
290 Open= (POPEN_INSTANCE)ProtocolBindingContext;
291
292 //
293 // get the open irp
294 //
295 Irp=Open->OpenCloseIrp;
296
297 if (Status != NDIS_STATUS_SUCCESS) {
298
299 IF_LOUD(DbgPrint("Packet: OpenAdapterComplete-FAILURE\n");)
300
301 NdisFreePacketPool(Open->PacketPool);
302
303 ExFreePool(Open->ReadEventName.Buffer);
304
305 ExFreePool(Open);
306 }
307
308 Irp->IoStatus.Status = Status;
309 Irp->IoStatus.Information = 0;
310 IoCompleteRequest(Irp, IO_NO_INCREMENT);
311
312 return;
313
314 }
315
316 //-------------------------------------------------------------------
317
318 NTSTATUS STDCALL
319 PacketClose(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
320 {
321
322 POPEN_INSTANCE Open;
323 NDIS_STATUS Status;
324 PIO_STACK_LOCATION IrpSp;
325
326
327 IF_LOUD(DbgPrint("Packet: CloseAdapter\n");)
328
329 IrpSp = IoGetCurrentIrpStackLocation(Irp);
330
331 Open=IrpSp->FileObject->FsContext;
332
333 if( Open->Bound == FALSE){
334
335 NdisWaitEvent(&Open->IOEvent,10000);
336
337 //free the bpf program
338 if(Open->bpfprogram!=NULL)ExFreePool(Open->bpfprogram);
339
340 //free the buffer
341 Open->BufSize=0;
342 if(Open->Buffer!=NULL)ExFreePool(Open->Buffer);
343
344 NdisFreePacketPool(Open->PacketPool);
345
346 ExFreePool(Open->ReadEventName.Buffer);
347 ExFreePool(Open);
348
349 Irp->IoStatus.Information = 0;
350 Irp->IoStatus.Status = STATUS_SUCCESS;
351 IoCompleteRequest(Irp, IO_NO_INCREMENT);
352
353 return(STATUS_SUCCESS);
354 }
355
356 // Eventually unfreeze PacketRead
357 KeSetEvent(Open->ReadEvent,0,FALSE);
358
359 // Destroy the read Event
360 ZwClose(Open->ReadEventHandle);
361
362 // save the IRP
363 Open->OpenCloseIrp=Irp;
364
365 IoMarkIrpPending(Irp);
366
367 // close the adapter
368 NdisCloseAdapter(
369 &Status,
370 Open->AdapterHandle
371 );
372
373 if (Status != NDIS_STATUS_PENDING) {
374
375 PacketCloseAdapterComplete(
376 Open,
377 Status
378 );
379 return STATUS_SUCCESS;
380
381 }
382
383 return(STATUS_PENDING);
384 }
385
386 //-------------------------------------------------------------------
387
388 VOID
389 PacketCloseAdapterComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Status)
390 {
391 POPEN_INSTANCE Open;
392 PIRP Irp;
393
394 IF_LOUD(DbgPrint("Packet: CloseAdapterComplete\n");)
395
396 Open= (POPEN_INSTANCE)ProtocolBindingContext;
397
398 // free the allocated structures only if the instance is still bound to the adapter
399 if(Open->Bound == TRUE){
400
401 //free the bpf program
402 if(Open->bpfprogram!=NULL)ExFreePool(Open->bpfprogram);
403
404 //free the buffer
405 Open->BufSize=0;
406 if(Open->Buffer!=NULL)ExFreePool(Open->Buffer);
407
408 NdisFreePacketPool(Open->PacketPool);
409
410 Irp=Open->OpenCloseIrp;
411
412 ExFreePool(Open->ReadEventName.Buffer);
413 ExFreePool(Open);
414
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);
419 }
420 else
421 NdisSetEvent(&Open->IOEvent);
422
423
424 return;
425
426 }
427
428 //-------------------------------------------------------------------
429
430 VOID
431 PacketBindAdapter(
432 OUT PNDIS_STATUS Status,
433 IN NDIS_HANDLE BindContext,
434 IN PNDIS_STRING DeviceName,
435 IN PVOID SystemSpecific1,
436 IN PVOID SystemSpecific2
437 )
438 {
439 IF_LOUD(DbgPrint("Packet: PacketBindAdapter\n");)
440 }
441
442 //-------------------------------------------------------------------
443
444 VOID
445 PacketUnbindAdapter(
446 OUT PNDIS_STATUS Status,
447 IN NDIS_HANDLE ProtocolBindingContext,
448 IN NDIS_HANDLE UnbindContext
449 )
450 {
451 POPEN_INSTANCE Open =(POPEN_INSTANCE)ProtocolBindingContext;
452 NDIS_STATUS lStatus;
453
454 IF_LOUD(DbgPrint("Packet: PacketUNBindAdapter\n");)
455
456 NdisResetEvent(&Open->IOEvent);
457
458 // This open instance is no more bound to the adapter, set Bound to False
459 InterlockedExchange( (PLONG) &Open->Bound, FALSE );
460
461 // Awake a possible pending read on this instance
462 KeSetEvent(Open->ReadEvent,0,FALSE);
463
464 // Destroy the read Event
465 ZwClose(Open->ReadEventHandle);
466
467 // close the adapter
468 NdisCloseAdapter(
469 &lStatus,
470 Open->AdapterHandle
471 );
472
473 if (lStatus != NDIS_STATUS_PENDING) {
474
475 PacketCloseAdapterComplete(
476 Open,
477 lStatus
478 );
479
480 *Status = NDIS_STATUS_SUCCESS;
481 return;
482
483 }
484
485 *Status = NDIS_STATUS_SUCCESS;
486 return;
487 }
488
489 //-------------------------------------------------------------------
490
491 VOID
492 PacketResetComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Status)
493
494 {
495 POPEN_INSTANCE Open;
496 PIRP Irp;
497
498 PLIST_ENTRY ResetListEntry;
499
500 IF_LOUD(DbgPrint("Packet: PacketResetComplte\n");)
501
502 Open= (POPEN_INSTANCE)ProtocolBindingContext;
503
504
505 //
506 // remove the reset IRP from the list
507 //
508 ResetListEntry=ExInterlockedRemoveHeadList(
509 &Open->ResetIrpList,
510 &Open->RequestSpinLock
511 );
512
513 #if DBG
514 if (ResetListEntry == NULL) {
515 DbgBreakPoint();
516 return;
517 }
518 #endif
519
520 Irp=CONTAINING_RECORD(ResetListEntry,IRP,Tail.Overlay.ListEntry);
521
522 Irp->IoStatus.Status = STATUS_SUCCESS;
523 IoCompleteRequest(Irp, IO_NO_INCREMENT);
524
525 IF_LOUD(DbgPrint("Packet: PacketResetComplte exit\n");)
526
527 return;
528
529 }