[project] Rename winvblock__uint32 back to UINT32
[people/sha0/winvblock.git] / src / aoe / protocol.c
1 /**
2  * Copyright (C) 2009-2011, Shao Miller <shao.miller@yrdsb.edu.on.ca>.
3  * Copyright 2006-2008, V.
4  * For WinAoE contact information, see http://winaoe.org/
5  *
6  * This file is part of WinVBlock, derived from WinAoE.
7  *
8  * WinVBlock is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * WinVBlock is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with WinVBlock.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 /**
23  * @file
24  *
25  * Protocol specifics.
26  */
27
28 #include <ntddk.h>
29 #include <ndis.h>
30 #include <ntddndis.h>
31
32 #include "winvblock.h"
33 #include "wv_stdlib.h"
34 #include "wv_string.h"
35 #include "portable.h"
36 #include "driver.h"
37 #include "bus.h"
38 #include "device.h"
39 #include "disk.h"
40 #include "mount.h"
41 #include "aoe.h"
42 #include "protocol.h"
43 #include "debug.h"
44
45 #define AOEPROTOCOLID 0x88a2
46
47 /** From AoE module */
48 extern NTSTATUS STDCALL aoe__reply (
49   IN PUCHAR SourceMac,
50   IN PUCHAR DestinationMac,
51   IN PUCHAR Data,
52   IN UINT32 DataSize
53  );
54
55 /** In this file */
56 static void STDCALL Protocol_OpenAdapterComplete (
57   IN NDIS_HANDLE ProtocolBindingContext,
58   IN NDIS_STATUS Status,
59   IN NDIS_STATUS OpenErrorStatus
60  );
61 static void STDCALL Protocol_CloseAdapterComplete (
62   IN NDIS_HANDLE ProtocolBindingContext,
63   IN NDIS_STATUS Status
64  );
65 static void STDCALL Protocol_SendComplete (
66   IN NDIS_HANDLE ProtocolBindingContext,
67   IN PNDIS_PACKET Packet,
68   IN NDIS_STATUS Status
69  );
70 static void STDCALL Protocol_TransferDataComplete (
71   IN NDIS_HANDLE ProtocolBindingContext,
72   IN PNDIS_PACKET Packet,
73   IN NDIS_STATUS Status,
74   IN UINT32 BytesTransferred
75  );
76 static void STDCALL Protocol_ResetComplete (
77   IN NDIS_HANDLE ProtocolBindingContext,
78   IN NDIS_STATUS Status
79  );
80 static void STDCALL Protocol_RequestComplete (
81   IN NDIS_HANDLE ProtocolBindingContext,
82   IN PNDIS_REQUEST NdisRequest,
83   IN NDIS_STATUS Status
84  );
85 static NDIS_STATUS STDCALL Protocol_Receive (
86   IN NDIS_HANDLE ProtocolBindingContext,
87   IN NDIS_HANDLE MacReceiveContext,
88   IN void *HeaderBuffer,
89   IN UINT32 HeaderBufferSize,
90   IN void *LookAheadBuffer,
91   IN UINT32 LookaheadBufferSize,
92   IN UINT32 PacketSize
93  );
94 static void STDCALL Protocol_ReceiveComplete (
95   IN NDIS_HANDLE ProtocolBindingContext
96  );
97 static void STDCALL Protocol_Status (
98   IN NDIS_HANDLE ProtocolBindingContext,
99   IN NDIS_STATUS GeneralStatus,
100   IN void *StatusBuffer,
101   IN UINT32 StatusBufferSize
102  );
103 static void STDCALL Protocol_StatusComplete (
104   IN NDIS_HANDLE ProtocolBindingContext
105  );
106 static void STDCALL Protocol_BindAdapter (
107   OUT PNDIS_STATUS Status,
108   IN NDIS_HANDLE BindContext,
109   IN PNDIS_STRING DeviceName,
110   IN void *SystemSpecific1,
111   IN void *SystemSpecific2
112  );
113 static void STDCALL Protocol_UnbindAdapter (
114   OUT PNDIS_STATUS Status,
115   IN NDIS_HANDLE ProtocolBindingContext,
116   IN NDIS_HANDLE UnbindContext
117  );
118 static NDIS_STATUS STDCALL Protocol_PnPEvent (
119   IN NDIS_HANDLE ProtocolBindingContext,
120   IN PNET_PNP_EVENT NetPnPEvent
121  );
122 static PCHAR STDCALL Protocol_NetEventString (
123   IN NET_PNP_EVENT_CODE NetEvent
124  );
125
126 #ifdef _MSC_VER
127 #  pragma pack(1)
128 #endif
129 typedef struct _PROTOCOL_HEADER
130 {
131   UCHAR DestinationMac[6];
132   UCHAR SourceMac[6];
133   winvblock__uint16 Protocol;
134   UCHAR Data[];
135 } __attribute__ ( ( __packed__ ) ) PROTOCOL_HEADER, *PPROTOCOL_HEADER;
136 #ifdef _MSC_VER
137 #  pragma pack()
138 #endif
139
140 typedef struct _PROTOCOL_BINDINGCONTEXT
141 {
142   winvblock__bool Active;
143   UCHAR Mac[6];
144   UINT32 MTU;
145   NDIS_STATUS Status;
146   NDIS_HANDLE PacketPoolHandle;
147   NDIS_HANDLE BufferPoolHandle;
148   NDIS_HANDLE BindingHandle;
149   KEVENT Event;
150   winvblock__bool OutstandingRequest;
151   PWCHAR AdapterName;
152   PWCHAR DeviceName;
153   struct _PROTOCOL_BINDINGCONTEXT *Next;
154 } PROTOCOL_BINDINGCONTEXT,
155 *PPROTOCOL_BINDINGCONTEXT;
156
157 static KEVENT Protocol_Globals_StopEvent;
158 static KSPIN_LOCK Protocol_Globals_SpinLock;
159 static PPROTOCOL_BINDINGCONTEXT Protocol_Globals_BindingContextList = NULL;
160 static NDIS_HANDLE Protocol_Globals_Handle = NULL;
161 static winvblock__bool Protocol_Globals_Started = FALSE;
162
163 NTSTATUS
164 Protocol_Start (
165   void
166  )
167 {
168   NDIS_STATUS Status;
169   NDIS_STRING ProtocolName;
170   NDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics;
171
172   DBG ( "Entry\n" );
173   if ( Protocol_Globals_Started )
174     return STATUS_SUCCESS;
175   KeInitializeEvent ( &Protocol_Globals_StopEvent, SynchronizationEvent,
176                       FALSE );
177   KeInitializeSpinLock ( &Protocol_Globals_SpinLock );
178
179   RtlInitUnicodeString ( &ProtocolName, WVL_M_WLIT );
180   NdisZeroMemory ( &ProtocolCharacteristics,
181                    sizeof ( NDIS_PROTOCOL_CHARACTERISTICS ) );
182   ProtocolCharacteristics.MajorNdisVersion = 4;
183   ProtocolCharacteristics.MinorNdisVersion = 0;
184   ProtocolCharacteristics.Name = ProtocolName;
185   ProtocolCharacteristics.OpenAdapterCompleteHandler =
186     Protocol_OpenAdapterComplete;
187   ProtocolCharacteristics.CloseAdapterCompleteHandler =
188     Protocol_CloseAdapterComplete;
189   ProtocolCharacteristics.SendCompleteHandler = Protocol_SendComplete;
190   ProtocolCharacteristics.TransferDataCompleteHandler =
191     Protocol_TransferDataComplete;
192   ProtocolCharacteristics.ResetCompleteHandler = Protocol_ResetComplete;
193   ProtocolCharacteristics.RequestCompleteHandler = Protocol_RequestComplete;
194   ProtocolCharacteristics.ReceiveHandler = Protocol_Receive;
195   ProtocolCharacteristics.ReceiveCompleteHandler = Protocol_ReceiveComplete;
196   ProtocolCharacteristics.StatusHandler = Protocol_Status;
197   ProtocolCharacteristics.StatusCompleteHandler = Protocol_StatusComplete;
198   ProtocolCharacteristics.BindAdapterHandler = Protocol_BindAdapter;
199   ProtocolCharacteristics.UnbindAdapterHandler = Protocol_UnbindAdapter;
200   ProtocolCharacteristics.PnPEventHandler = Protocol_PnPEvent;
201   NdisRegisterProtocol ( ( PNDIS_STATUS ) & Status, &Protocol_Globals_Handle,
202                          &ProtocolCharacteristics,
203                          sizeof ( NDIS_PROTOCOL_CHARACTERISTICS ) );
204   if ( !NT_SUCCESS ( Status ) )
205     DBG ( "Protocol startup failure!\n" );
206   else
207     Protocol_Globals_Started = TRUE;
208   DBG ( "Exit\n" );
209   return Status;
210 }
211
212 void STDCALL
213 Protocol_Stop (
214   void
215  )
216 {
217   NDIS_STATUS Status;
218
219   DBG ( "Entry\n" );
220   if ( !Protocol_Globals_Started )
221     return;
222   KeResetEvent ( &Protocol_Globals_StopEvent );
223   NdisDeregisterProtocol ( &Status, Protocol_Globals_Handle );
224   if ( !NT_SUCCESS ( Status ) )
225     Error ( "NdisDeregisterProtocol", Status );
226   if ( Protocol_Globals_BindingContextList != NULL )
227     KeWaitForSingleObject ( &Protocol_Globals_StopEvent, Executive, KernelMode,
228                             FALSE, NULL );
229   Protocol_Globals_Started = FALSE;
230   DBG ( "Exit\n" );
231 }
232
233 winvblock__bool STDCALL
234 Protocol_SearchNIC (
235   IN PUCHAR Mac
236  )
237 {
238   PPROTOCOL_BINDINGCONTEXT Context = Protocol_Globals_BindingContextList;
239
240   while ( Context != NULL )
241     {
242       if (wv_memcmpeq(Mac, Context->Mac, 6)) break;
243       Context = Context->Next;
244     }
245   if ( Context != NULL )
246     return TRUE;
247   return FALSE;
248 }
249
250 UINT32 STDCALL
251 Protocol_GetMTU (
252   IN PUCHAR Mac
253  )
254 {
255   PPROTOCOL_BINDINGCONTEXT Context = Protocol_Globals_BindingContextList;
256
257   while ( Context != NULL )
258     {
259       if (wv_memcmpeq(Mac, Context->Mac, 6)) break;
260       Context = Context->Next;
261     }
262   if ( Context == NULL )
263     return 0;
264   return Context->MTU;
265 }
266
267 winvblock__bool STDCALL
268 Protocol_Send (
269   IN PUCHAR SourceMac,
270   IN PUCHAR DestinationMac,
271   IN PUCHAR Data,
272   IN UINT32 DataSize,
273   IN void *PacketContext
274  )
275 {
276   PPROTOCOL_BINDINGCONTEXT Context = Protocol_Globals_BindingContextList;
277   NDIS_STATUS Status;
278   PNDIS_PACKET Packet;
279   PNDIS_BUFFER Buffer;
280   PPROTOCOL_HEADER DataBuffer;
281 #if defined(DEBUGALLPROTOCOLCALLS)
282   DBG ( "Entry\n" );
283 #endif
284
285   if (wv_memcmpeq(SourceMac, "\xff\xff\xff\xff\xff\xff", 6)) {
286       while ( Context != NULL )
287         {
288           Protocol_Send ( Context->Mac, DestinationMac, Data, DataSize, NULL );
289           Context = Context->Next;
290         }
291       return TRUE;
292     }
293
294   while ( Context != NULL )
295     {
296       if (wv_memcmpeq(SourceMac, Context->Mac, 6)) break;
297       Context = Context->Next;
298     }
299   if ( Context == NULL )
300     {
301       DBG ( "Can't find NIC %02x:%02x:%02x:%02x:%02x:%02x\n", SourceMac[0],
302             SourceMac[1], SourceMac[2], SourceMac[3], SourceMac[4],
303             SourceMac[5] );
304       return FALSE;
305     }
306
307   if ( DataSize > Context->MTU )
308     {
309       DBG ( "Tried to send oversized packet (size: %d, MTU:)\n", DataSize,
310             Context->MTU );
311       return FALSE;
312     }
313
314   if ((DataBuffer = wv_malloc(sizeof *DataBuffer + DataSize)) == NULL) {
315       DBG("wv_malloc DataBuffer\n");
316       return FALSE;
317     }
318
319   RtlCopyMemory ( DataBuffer->SourceMac, SourceMac, 6 );
320   RtlCopyMemory ( DataBuffer->DestinationMac, DestinationMac, 6 );
321   DataBuffer->Protocol = htons ( AOEPROTOCOLID );
322   RtlCopyMemory ( DataBuffer->Data, Data, DataSize );
323
324   NdisAllocatePacket ( &Status, &Packet, Context->PacketPoolHandle );
325   if ( !NT_SUCCESS ( Status ) )
326     {
327       Error ( "Protocol_Send NdisAllocatePacket", Status );
328       wv_free(DataBuffer);
329       return FALSE;
330     }
331
332   NdisAllocateBuffer ( &Status, &Buffer, Context->BufferPoolHandle, DataBuffer,
333                        ( sizeof ( PROTOCOL_HEADER ) + DataSize ) );
334   if ( !NT_SUCCESS ( Status ) )
335     {
336       Error ( "Protocol_Send NdisAllocateBuffer", Status );
337       NdisFreePacket ( Packet );
338       wv_free(DataBuffer);
339       return FALSE;
340     }
341
342   NdisChainBufferAtFront ( Packet, Buffer );
343   *( void ** )Packet->ProtocolReserved = PacketContext;
344   NdisSend ( &Status, Context->BindingHandle, Packet );
345   if ( Status != NDIS_STATUS_PENDING )
346     Protocol_SendComplete ( Context, Packet, Status );
347 #if defined(DEBUGALLPROTOCOLCALLS)
348   DBG ( "Exit\n" );
349 #endif
350   return TRUE;
351 }
352
353 static void STDCALL
354 Protocol_OpenAdapterComplete (
355   IN NDIS_HANDLE ProtocolBindingContext,
356   IN NDIS_STATUS Status,
357   IN NDIS_STATUS OpenErrorStatus
358  )
359 {
360 #if !defined(DEBUGMOSTPROTOCOLCALLS) && !defined(DEBUGALLPROTOCOLCALLS)
361   if ( !NT_SUCCESS ( Status ) )
362 #endif
363     DBG ( "0x%08x 0x%08x\n", Status, OpenErrorStatus );
364 }
365
366 static void STDCALL
367 Protocol_CloseAdapterComplete (
368   IN NDIS_HANDLE ProtocolBindingContext,
369   IN NDIS_STATUS Status
370  )
371 {
372 #if !defined(DEBUGMOSTPROTOCOLCALLS) && !defined(DEBUGALLPROTOCOLCALLS)
373   if ( !NT_SUCCESS ( Status ) )
374 #endif
375     Error ( "Protocol_CloseAdapterComplete", Status );
376 }
377
378 static void STDCALL
379 Protocol_SendComplete (
380   IN NDIS_HANDLE ProtocolBindingContext,
381   IN PNDIS_PACKET Packet,
382   IN NDIS_STATUS Status
383  )
384 {
385   PNDIS_BUFFER Buffer;
386   PUCHAR DataBuffer;
387 #ifndef DEBUGALLPROTOCOLCALLS
388   if ( !NT_SUCCESS ( Status ) && Status != NDIS_STATUS_NO_CABLE )
389 #endif
390     Error ( "Protocol_SendComplete", Status );
391
392   NdisUnchainBufferAtFront ( Packet, &Buffer );
393   if ( Buffer != NULL )
394     {
395       DataBuffer = MmGetSystemAddressForMdlSafe ( Buffer, HighPagePriority );
396       wv_free(DataBuffer);
397       NdisFreeBuffer ( Buffer );
398     }
399   else
400     {
401       DBG ( "Buffer == NULL\n" );
402     }
403   NdisFreePacket ( Packet );
404 }
405
406 static void STDCALL
407 Protocol_TransferDataComplete (
408   IN NDIS_HANDLE ProtocolBindingContext,
409   IN PNDIS_PACKET Packet,
410   IN NDIS_STATUS Status,
411   IN UINT32 BytesTransferred
412  )
413 {
414   PNDIS_BUFFER Buffer;
415   PPROTOCOL_HEADER Header = NULL;
416   PUCHAR Data = NULL;
417   UINT32 HeaderSize,
418    DataSize;
419 #ifndef DEBUGALLPROTOCOLCALLS
420   if ( !NT_SUCCESS ( Status ) )
421 #endif
422     Error ( "Protocol_TransferDataComplete", Status );
423
424   NdisUnchainBufferAtFront ( Packet, &Buffer );
425   if ( Buffer != NULL )
426     {
427       NdisQueryBufferSafe ( Buffer, &Data, &DataSize, HighPagePriority );
428       NdisFreeBuffer ( Buffer );
429     }
430   else
431     {
432       DBG ( "Data (front) Buffer == NULL\n" );
433     }
434   NdisUnchainBufferAtBack ( Packet, &Buffer );
435   if ( Buffer != NULL )
436     {
437       NdisQueryBufferSafe ( Buffer, &Header, &HeaderSize, HighPagePriority );
438       NdisFreeBuffer ( Buffer );
439     }
440   else
441     {
442       DBG ( "Header (back) Buffer == NULL\n" );
443     }
444   if ( Header != NULL && Data != NULL )
445     aoe__reply ( Header->SourceMac, Header->DestinationMac, Data, DataSize );
446   if ( Header != NULL )
447     wv_free(Header);
448   if ( Data != NULL )
449     wv_free(Data);
450   NdisFreePacket ( Packet );
451 }
452
453 static void STDCALL
454 Protocol_ResetComplete (
455   IN NDIS_HANDLE ProtocolBindingContext,
456   IN NDIS_STATUS Status
457  )
458 {
459 #if !defined(DEBUGMOSTPROTOCOLCALLS) && !defined(DEBUGALLPROTOCOLCALLS)
460   if ( !NT_SUCCESS ( Status ) )
461 #endif
462     Error ( "Protocol_ResetComplete", Status );
463 }
464
465 static void STDCALL
466 Protocol_RequestComplete (
467   IN NDIS_HANDLE ProtocolBindingContext,
468   IN PNDIS_REQUEST NdisRequest,
469   IN NDIS_STATUS Status
470  )
471 {
472   PPROTOCOL_BINDINGCONTEXT Context =
473     ( PPROTOCOL_BINDINGCONTEXT ) ProtocolBindingContext;
474 #if !defined(DEBUGMOSTPROTOCOLCALLS) && !defined(DEBUGALLPROTOCOLCALLS)
475   if ( !NT_SUCCESS ( Status ) )
476 #endif
477     Error ( "Protocol_RequestComplete", Status );
478
479   Context->Status = Status;
480   KeSetEvent ( &Context->Event, 0, FALSE );
481 }
482
483 static NDIS_STATUS STDCALL
484 Protocol_Receive (
485   IN NDIS_HANDLE ProtocolBindingContext,
486   IN NDIS_HANDLE MacReceiveContext,
487   IN void *HeaderBuffer,
488   IN UINT32 HeaderBufferSize,
489   IN void *LookAheadBuffer,
490   IN UINT32 LookaheadBufferSize,
491   IN UINT32 PacketSize
492  )
493 {
494   PPROTOCOL_BINDINGCONTEXT Context =
495     ( PPROTOCOL_BINDINGCONTEXT ) ProtocolBindingContext;
496   NDIS_STATUS Status;
497   PNDIS_PACKET Packet;
498   PNDIS_BUFFER Buffer;
499   PPROTOCOL_HEADER Header;
500   PUCHAR HeaderCopy,
501    Data;
502   UINT32 BytesTransferred;
503 #ifdef DEBUGALLPROTOCOLCALLS
504   DBG ( "Entry\n" );
505 #endif
506
507   if ( HeaderBufferSize != sizeof ( PROTOCOL_HEADER ) )
508     {
509       DBG ( "HeaderBufferSize %d != sizeof(PROTOCOL_HEADER) %d\n" );
510       return NDIS_STATUS_NOT_ACCEPTED;
511     }
512   Header = ( PPROTOCOL_HEADER ) HeaderBuffer;
513   if ( ntohs ( Header->Protocol ) != AOEPROTOCOLID )
514     return NDIS_STATUS_NOT_ACCEPTED;
515
516   if ( LookaheadBufferSize == PacketSize )
517     {
518       aoe__reply ( Header->SourceMac, Header->DestinationMac, LookAheadBuffer,
519                    PacketSize );
520       return NDIS_STATUS_SUCCESS;
521     }
522
523   if ((HeaderCopy = wv_malloc(HeaderBufferSize)) == NULL) {
524       DBG("wv_malloc HeaderCopy\n");
525       return NDIS_STATUS_NOT_ACCEPTED;
526     }
527   RtlCopyMemory ( HeaderCopy, HeaderBuffer, HeaderBufferSize );
528   if ((Data = wv_malloc(PacketSize)) == NULL) {
529       DBG("wv_malloc HeaderData\n");
530       wv_free(HeaderCopy);
531       return NDIS_STATUS_NOT_ACCEPTED;
532     }
533   NdisAllocatePacket ( &Status, &Packet, Context->PacketPoolHandle );
534   if ( !NT_SUCCESS ( Status ) )
535     {
536       Error ( "Protocol_Receive NdisAllocatePacket", Status );
537       wv_free(Data);
538       wv_free(HeaderCopy);
539       return NDIS_STATUS_NOT_ACCEPTED;
540     }
541
542   NdisAllocateBuffer ( &Status, &Buffer, Context->BufferPoolHandle, Data,
543                        PacketSize );
544   if ( !NT_SUCCESS ( Status ) )
545     {
546       Error ( "Protocol_Receive NdisAllocateBuffer (Data)", Status );
547       NdisFreePacket ( Packet );
548       wv_free(Data);
549       wv_free(HeaderCopy);
550       return NDIS_STATUS_NOT_ACCEPTED;
551     }
552   NdisChainBufferAtFront ( Packet, Buffer );
553
554   NdisAllocateBuffer ( &Status, &Buffer, Context->BufferPoolHandle, HeaderCopy,
555                        PacketSize );
556   if ( !NT_SUCCESS ( Status ) )
557     {
558       Error ( "Protocol_Receive NdisAllocateBuffer (HeaderCopy)", Status );
559       NdisUnchainBufferAtFront ( Packet, &Buffer );
560       NdisFreeBuffer ( Buffer );
561       NdisFreePacket ( Packet );
562       wv_free(Data);
563       wv_free(HeaderCopy);
564       return NDIS_STATUS_NOT_ACCEPTED;
565     }
566   NdisChainBufferAtBack ( Packet, Buffer );
567
568   NdisTransferData ( &Status, Context->BindingHandle, MacReceiveContext, 0,
569                      PacketSize, Packet, &BytesTransferred );
570   if ( Status != NDIS_STATUS_PENDING )
571     Protocol_TransferDataComplete ( ProtocolBindingContext, Packet, Status,
572                                     BytesTransferred );
573 #if defined(DEBUGALLPROTOCOLCALLS)
574   DBG ( "Exit\n" );
575 #endif
576   return Status;
577 }
578
579 static void STDCALL
580 Protocol_ReceiveComplete (
581   IN NDIS_HANDLE ProtocolBindingContext
582  )
583 {
584 #ifdef DEBUGALLPROTOCOLCALLS
585   DBG ( "Entry\n" );
586 #endif
587 #if defined(DEBUGALLPROTOCOLCALLS)
588   DBG ( "Exit\n" );
589 #endif
590 }
591
592 static void STDCALL
593 Protocol_Status (
594   IN NDIS_HANDLE ProtocolBindingContext,
595   IN NDIS_STATUS GeneralStatus,
596   IN void *StatusBuffer,
597   IN UINT32 StatusBufferSize
598  )
599 {
600 #if !defined(DEBUGMOSTPROTOCOLCALLS) && !defined(DEBUGALLPROTOCOLCALLS)
601   if ( !NT_SUCCESS ( GeneralStatus ) )
602 #endif
603     Error ( "Protocol_Status", GeneralStatus );
604 }
605
606 static void STDCALL
607 Protocol_StatusComplete (
608   IN NDIS_HANDLE ProtocolBindingContext
609  )
610 {
611 #if defined(DEBUGMOSTPROTOCOLCALLS) || defined(DEBUGALLPROTOCOLCALLS)
612   DBG ( "Entry\n" );
613 #endif
614 #if defined(DEBUGALLPROTOCOLCALLS)
615   DBG ( "Exit\n" );
616 #endif
617 }
618
619 static void STDCALL
620 Protocol_BindAdapter (
621   OUT PNDIS_STATUS StatusOut,
622   IN NDIS_HANDLE BindContext,
623   IN PNDIS_STRING DeviceName,
624   IN void *SystemSpecific1,
625   IN void *SystemSpecific2
626  )
627 {
628   PPROTOCOL_BINDINGCONTEXT Context,
629    Walker;
630   NDIS_STATUS Status;
631   NDIS_STATUS OpenErrorStatus;
632   UINT32 SelectedMediumIndex,
633    MTU;
634   NDIS_MEDIUM MediumArray[] = { NdisMedium802_3 };
635   NDIS_STRING AdapterInstanceName;
636   NDIS_REQUEST Request;
637   UINT32 InformationBuffer = NDIS_PACKET_TYPE_DIRECTED;
638   UCHAR Mac[6];
639   KIRQL Irql;
640 #if defined(DEBUGMOSTPROTOCOLCALLS) || defined(DEBUGALLPROTOCOLCALLS)
641   DBG ( "Entry\n" );
642 #endif
643
644   if ((Context = wv_malloc(sizeof *Context)) == NULL) {
645       DBG("wv_malloc Context\n");
646       *StatusOut = NDIS_STATUS_RESOURCES;
647       return;
648     }
649   Context->Next = NULL;
650   KeInitializeEvent ( &Context->Event, SynchronizationEvent, FALSE );
651
652   NdisAllocatePacketPool ( &Status, &Context->PacketPoolHandle, POOLSIZE,
653                            ( 4 * sizeof ( void * ) ) );
654   if ( !NT_SUCCESS ( Status ) )
655     {
656       Error ( "Protocol_BindAdapter NdisAllocatePacketPool", Status );
657       wv_free(Context);
658       *StatusOut = NDIS_STATUS_RESOURCES;
659       return;
660     }
661
662   NdisAllocateBufferPool ( &Status, &Context->BufferPoolHandle, POOLSIZE );
663   if ( !NT_SUCCESS ( Status ) )
664     {
665       Error ( "Protocol_BindAdapter NdisAllocateBufferPool", Status );
666       NdisFreePacketPool ( Context->PacketPoolHandle );
667       wv_free(Context);
668       *StatusOut = NDIS_STATUS_RESOURCES;
669       return;
670     }
671
672   NdisOpenAdapter ( &Status, &OpenErrorStatus, &Context->BindingHandle,
673                     &SelectedMediumIndex, MediumArray,
674                     ( sizeof ( MediumArray ) / sizeof ( NDIS_MEDIUM ) ),
675                     Protocol_Globals_Handle, Context, DeviceName, 0, NULL );
676   if ( !NT_SUCCESS ( Status ) )
677     {
678       DBG ( "NdisOpenAdapter 0x%lx 0x%lx\n", Status, OpenErrorStatus );
679       NdisFreePacketPool ( Context->PacketPoolHandle );
680       NdisFreeBufferPool ( Context->BufferPoolHandle );
681       wv_free(Context->AdapterName);
682       wv_free(Context->DeviceName);
683       wv_free(Context);
684       *StatusOut = Status;
685       return;
686     }
687   if ( SelectedMediumIndex != 0 )
688     DBG ( "NdisOpenAdapter SelectedMediumIndex: %d\n", SelectedMediumIndex );
689
690   Context->AdapterName = NULL;
691   if ( NT_SUCCESS
692        ( Status =
693          NdisQueryAdapterInstanceName ( &AdapterInstanceName,
694                                         Context->BindingHandle ) ) )
695     {
696       Context->AdapterName = wv_mallocz(
697           AdapterInstanceName.Length +
698           sizeof (WCHAR)
699         );
700       if (Context->AdapterName == NULL) {
701         DBG("wv_mallocz AdapterName\n");
702         }
703       else
704         {
705           RtlCopyMemory ( Context->AdapterName, AdapterInstanceName.Buffer,
706                           AdapterInstanceName.Length );
707         }
708       NdisFreeMemory ( AdapterInstanceName.Buffer, 0, 0 );
709     }
710   else
711     {
712       Error ( "Protocol_BindAdapter NdisQueryAdapterInstanceName", Status );
713     }
714
715   Context->DeviceName = NULL;
716   if ( DeviceName->Length > 0 )
717     {
718       Context->DeviceName = wv_mallocz(DeviceName->Length + sizeof (WCHAR));
719       if (Context->DeviceName == NULL) {
720           DBG("wv_malloc DeviceName\n");
721         }
722       else
723         {
724           RtlCopyMemory ( Context->DeviceName, DeviceName->Buffer,
725                           DeviceName->Length );
726         }
727     }
728
729   if ( Context->AdapterName != NULL )
730     DBG ( "Adapter: %S\n", Context->AdapterName );
731   if ( Context->DeviceName != NULL )
732     DBG ( "Device Name: %S\n", Context->DeviceName );
733   if ( ( Context->AdapterName == NULL ) && ( Context->DeviceName == NULL ) )
734     DBG ( "Unnamed Adapter...\n" );
735
736   Request.RequestType = NdisRequestQueryInformation;
737   Request.DATA.QUERY_INFORMATION.Oid = OID_802_3_CURRENT_ADDRESS;
738   Request.DATA.QUERY_INFORMATION.InformationBuffer = Mac;
739   Request.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof ( Mac );
740
741   KeResetEvent ( &Context->Event );
742   NdisRequest ( &Status, Context->BindingHandle, &Request );
743   if ( Status == NDIS_STATUS_PENDING )
744     {
745       KeWaitForSingleObject ( &Context->Event, Executive, KernelMode, FALSE,
746                               NULL );
747       Status = Context->Status;
748     }
749   if ( !NT_SUCCESS ( Status ) )
750     {
751       Error ( "Protocol_BindAdapter NdisRequest (Mac)", Status );
752     }
753   else
754     {
755       RtlCopyMemory ( Context->Mac, Mac, 6 );
756       DBG ( "Mac: %02x:%02x:%02x:%02x:%02x:%02x\n", Mac[0], Mac[1], Mac[2],
757             Mac[3], Mac[4], Mac[5] );
758     }
759
760   Request.RequestType = NdisRequestQueryInformation;
761   Request.DATA.QUERY_INFORMATION.Oid = OID_GEN_MAXIMUM_FRAME_SIZE;
762   Request.DATA.QUERY_INFORMATION.InformationBuffer = &MTU;
763   Request.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof ( MTU );
764
765   KeResetEvent ( &Context->Event );
766   NdisRequest ( &Status, Context->BindingHandle, &Request );
767   if ( Status == NDIS_STATUS_PENDING )
768     {
769       KeWaitForSingleObject ( &Context->Event, Executive, KernelMode, FALSE,
770                               NULL );
771       Status = Context->Status;
772     }
773   if ( !NT_SUCCESS ( Status ) )
774     {
775       Error ( "Protocol_BindAdapter NdisRequest (MTU)", Status );
776     }
777   else
778     {
779       Context->MTU = MTU;
780       DBG ( "MTU: %d\n", MTU );
781     }
782
783   Request.RequestType = NdisRequestSetInformation;
784   Request.DATA.SET_INFORMATION.Oid = OID_GEN_CURRENT_PACKET_FILTER;
785   Request.DATA.SET_INFORMATION.InformationBuffer = &InformationBuffer;
786   Request.DATA.SET_INFORMATION.InformationBufferLength =
787     sizeof ( InformationBuffer );
788
789   KeResetEvent ( &Context->Event );
790   NdisRequest ( &Status, Context->BindingHandle, &Request );
791   if ( Status == NDIS_STATUS_PENDING )
792     {
793       KeWaitForSingleObject ( &Context->Event, Executive, KernelMode, FALSE,
794                               NULL );
795       Status = Context->Status;
796     }
797   if ( !NT_SUCCESS ( Status ) )
798     Error ( "ProtocolBindAdapter NdisRequest (filter)", Status );
799
800   KeAcquireSpinLock ( &Protocol_Globals_SpinLock, &Irql );
801   if ( Protocol_Globals_BindingContextList == NULL )
802     {
803       Protocol_Globals_BindingContextList = Context;
804     }
805   else
806     {
807       for ( Walker = Protocol_Globals_BindingContextList; Walker->Next != NULL;
808             Walker = Walker->Next );
809       Walker->Next = Context;
810     }
811   KeReleaseSpinLock ( &Protocol_Globals_SpinLock, Irql );
812
813   aoe__reset_probe (  );
814   *StatusOut = NDIS_STATUS_SUCCESS;
815 #if defined(DEBUGMOSTPROTOCOLCALLS) || defined(DEBUGALLPROTOCOLCALLS)
816   DBG ( "Exit\n" );
817 #endif
818 }
819
820 static void STDCALL
821 Protocol_UnbindAdapter (
822   OUT PNDIS_STATUS StatusOut,
823   IN NDIS_HANDLE ProtocolBindingContext,
824   IN NDIS_HANDLE UnbindContext
825  )
826 {
827   PPROTOCOL_BINDINGCONTEXT Context =
828     ( PPROTOCOL_BINDINGCONTEXT ) ProtocolBindingContext;
829   PPROTOCOL_BINDINGCONTEXT Walker,
830    PreviousContext;
831   NDIS_STATUS Status;
832   KIRQL Irql;
833 #if defined(DEBUGMOSTPROTOCOLCALLS) || defined(DEBUGALLPROTOCOLCALLS)
834   DBG ( "Entry\n" );
835 #endif
836
837   PreviousContext = NULL;
838   KeAcquireSpinLock ( &Protocol_Globals_SpinLock, &Irql );
839   for ( Walker = Protocol_Globals_BindingContextList;
840         Walker != Context && Walker != NULL; Walker = Walker->Next )
841     PreviousContext = Walker;
842   if ( Walker == NULL )
843     {
844       DBG ( "Context not found in Protocol_Globals_BindingContextList!!\n" );
845       KeReleaseSpinLock ( &Protocol_Globals_SpinLock, Irql );
846       return;
847     }
848   if ( PreviousContext == NULL )
849     {
850       Protocol_Globals_BindingContextList = Walker->Next;
851     }
852   else
853     {
854       PreviousContext->Next = Walker->Next;
855     }
856   KeReleaseSpinLock ( &Protocol_Globals_SpinLock, Irql );
857
858   NdisCloseAdapter ( &Status, Context->BindingHandle );
859   if ( !NT_SUCCESS ( Status ) )
860     Error ( "ProtocolUnbindAdapter NdisCloseAdapter", Status );
861   NdisFreePacketPool ( Context->PacketPoolHandle );
862   NdisFreeBufferPool ( Context->BufferPoolHandle );
863   wv_free(Context);
864   if ( Protocol_Globals_BindingContextList == NULL )
865     KeSetEvent ( &Protocol_Globals_StopEvent, 0, FALSE );
866   *StatusOut = NDIS_STATUS_SUCCESS;
867 #if defined(DEBUGMOSTPROTOCOLCALLS) || defined(DEBUGALLPROTOCOLCALLS)
868   DBG ( "Exit\n" );
869 #endif
870 }
871
872 static NDIS_STATUS STDCALL
873 Protocol_PnPEvent (
874   IN NDIS_HANDLE ProtocolBindingContext,
875   IN PNET_PNP_EVENT NetPnPEvent
876  )
877 {
878 #if defined(DEBUGMOSTPROTOCOLCALLS) || defined(DEBUGALLPROTOCOLCALLS)
879   DBG ( "%s\n", Protocol_NetEventString ( NetPnPEvent->NetEvent ) );
880 #endif
881   if ( ProtocolBindingContext == NULL
882        && NetPnPEvent->NetEvent == NetEventReconfigure )
883     {
884 #ifdef _MSC_VER
885       NdisReEnumerateProtocolBindings ( Protocol_Globals_Handle );
886 #else
887       DBG ( "No vector to NdisReEnumerateProtocolBindings\n" );
888 #endif
889     }
890   if ( NetPnPEvent->NetEvent == NetEventQueryRemoveDevice )
891     {
892       return NDIS_STATUS_FAILURE;
893     }
894   else
895     {
896       return NDIS_STATUS_SUCCESS;
897     }
898 }
899
900 static PCHAR STDCALL
901 Protocol_NetEventString (
902   IN NET_PNP_EVENT_CODE NetEvent
903  )
904 {
905   switch ( NetEvent )
906     {
907       case NetEventSetPower:
908         return "NetEventSetPower";
909       case NetEventQueryPower:
910         return "NetEventQueryPower";
911       case NetEventQueryRemoveDevice:
912         return "NetEventQueryRemoveDevice";
913       case NetEventCancelRemoveDevice:
914         return "NetEventCancelRemoveDevice";
915       case NetEventReconfigure:
916         return "NetEventReconfigure";
917       case NetEventBindList:
918         return "NetEventBindList";
919       case NetEventBindsComplete:
920         return "NetEventBindsComplete";
921       case NetEventPnPCapabilities:
922         return "NetEventPnPCapabilities";
923       default:
924         return "NetEventUnknown";
925     }
926 }