update for HEAD-2003050101
[reactos.git] / drivers / net / ndis / ndis / miniport.c
1 /*
2  * COPYRIGHT:   See COPYING in the top level directory
3  * PROJECT:     ReactOS NDIS library
4  * FILE:        ndis/miniport.c
5  * PURPOSE:     Routines used by NDIS miniport drivers
6  * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7  * REVISIONS:
8  *   CSH 01/08-2000 Created
9  */
10 #define DBG
11 #include <miniport.h>
12 #include <protocol.h>
13 #ifdef DBG
14 #include <buffer.h>
15 #endif /* DBG */
16
17 #ifdef DBG
18 /* See debug.h for debug/trace constants */
19 //ULONG DebugTraceLevel = MIN_TRACE;
20 ULONG DebugTraceLevel = (MAX_TRACE + DEBUG_MINIPORT);
21 #endif /* DBG */
22
23
24 /* Number of media we know */
25 #define MEDIA_ARRAY_SIZE    15
26
27 static NDIS_MEDIUM MediaArray[MEDIA_ARRAY_SIZE] = {
28     NdisMedium802_3,
29     NdisMedium802_5,
30     NdisMediumFddi,
31     NdisMediumWan,
32     NdisMediumLocalTalk,
33     NdisMediumDix,
34     NdisMediumArcnetRaw,
35     NdisMediumArcnet878_2,
36     NdisMediumAtm,
37     NdisMediumWirelessWan,
38     NdisMediumIrda,
39     NdisMediumBpc,
40     NdisMediumCoWan,
41     NdisMedium1394,
42     NdisMediumMax
43 };
44
45
46 LIST_ENTRY MiniportListHead;
47 KSPIN_LOCK MiniportListLock;
48 LIST_ENTRY AdapterListHead;
49 KSPIN_LOCK AdapterListLock;
50
51
52 #ifdef DBG
53 VOID
54 MiniDisplayPacket(
55     PNDIS_PACKET Packet)
56 {
57     ULONG i, Length;
58     UCHAR Buffer[64];
59 #if 0
60     if ((DebugTraceLevel | DEBUG_PACKET) > 0) {
61         Length = CopyPacketToBuffer(
62             (PUCHAR)&Buffer,
63             Packet,
64             0,
65             64);
66
67         DbgPrint("*** PACKET START ***");
68
69         for (i = 0; i < Length; i++) {
70             if (i % 12 == 0)
71                 DbgPrint("\n%04X ", i);
72             DbgPrint("%02X ", Buffer[i]);
73         }
74
75         DbgPrint("*** PACKET STOP ***\n");
76     }
77 #endif
78 }
79 #endif /* DBG */
80
81
82 VOID
83 MiniIndicateData(
84     PLOGICAL_ADAPTER    Adapter,
85     NDIS_HANDLE         MacReceiveContext,
86     PVOID               HeaderBuffer,
87     UINT                HeaderBufferSize,
88     PVOID               LookaheadBuffer,
89     UINT                LookaheadBufferSize,
90     UINT                PacketSize)
91 /*
92  * FUNCTION: Indicate received data to bound protocols
93  * ARGUMENTS:
94  *     Adapter             = Pointer to logical adapter
95  *     MacReceiveContext   = MAC receive context handle
96  *     HeaderBuffer        = Pointer to header buffer
97  *     HeaderBufferSize    = Size of header buffer
98  *     LookaheadBuffer     = Pointer to lookahead buffer
99  *     LookaheadBufferSize = Size of lookahead buffer
100  *     PacketSize          = Total size of received packet
101  */
102 {
103     KIRQL OldIrql;
104     PLIST_ENTRY CurrentEntry;
105     PADAPTER_BINDING AdapterBinding;
106
107     NDIS_DbgPrint(DEBUG_MINIPORT, ("Called. Adapter (0x%X)  HeaderBuffer (0x%X)  "
108         "HeaderBufferSize (0x%X)  LookaheadBuffer (0x%X)  LookaheadBufferSize (0x%X).\n",
109         Adapter, HeaderBuffer, HeaderBufferSize, LookaheadBuffer, LookaheadBufferSize));
110
111 #ifdef DBG
112 #if 0
113     if ((DebugTraceLevel | DEBUG_PACKET) > 0) {
114         ULONG i, Length;
115         PUCHAR p;
116
117         DbgPrint("*** RECEIVE PACKET START ***\n");
118         DbgPrint("HEADER:");
119         p = HeaderBuffer;
120         for (i = 0; i < HeaderBufferSize; i++) {
121             if (i % 16 == 0)
122                 DbgPrint("\n%04X ", i);
123             DbgPrint("%02X ", *p);
124             (ULONG_PTR)p += 1;
125         }
126
127         DbgPrint("\nFRAME:");
128
129         p = LookaheadBuffer;
130         Length = (LookaheadBufferSize < 64)? LookaheadBufferSize : 64;
131         for (i = 0; i < Length; i++) {
132             if (i % 16 == 0)
133                 DbgPrint("\n%04X ", i);
134             DbgPrint("%02X ", *p);
135             (ULONG_PTR)p += 1;
136         }
137
138         DbgPrint("\n*** RECEIVE PACKET STOP ***\n");
139     }
140 #endif
141 #endif /* DBG */
142
143     KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
144     CurrentEntry = Adapter->ProtocolListHead.Flink;
145
146     if (CurrentEntry == &Adapter->ProtocolListHead) {
147         NDIS_DbgPrint(DEBUG_MINIPORT, ("WARNING: No upper protocol layer.\n"));
148     }
149
150     while (CurrentEntry != &Adapter->ProtocolListHead) {
151             AdapterBinding = CONTAINING_RECORD(CurrentEntry,
152                                            ADAPTER_BINDING,
153                                            AdapterListEntry);
154
155         KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
156
157         (*AdapterBinding->ProtocolBinding->Chars.u4.ReceiveHandler)(
158             AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
159             MacReceiveContext,
160             HeaderBuffer,
161             HeaderBufferSize,
162             LookaheadBuffer,
163             LookaheadBufferSize,
164             PacketSize);
165
166         KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
167
168         CurrentEntry = CurrentEntry->Flink;
169     }
170     KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
171 }
172
173
174 VOID
175 MiniEthReceiveComplete(
176     IN  PETH_FILTER Filter)
177 /*
178  * FUNCTION: Receive indication complete function for Ethernet devices
179  * ARGUMENTS:
180  *     Filter = Pointer to Ethernet filter
181  */
182 {
183     KIRQL OldIrql;
184     PLIST_ENTRY CurrentEntry;
185     PLOGICAL_ADAPTER Adapter;
186     PADAPTER_BINDING AdapterBinding;
187
188     NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
189
190     Adapter = (PLOGICAL_ADAPTER)Filter->Miniport;
191
192     KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
193     CurrentEntry = Adapter->ProtocolListHead.Flink;
194     while (CurrentEntry != &Adapter->ProtocolListHead) {
195             AdapterBinding = CONTAINING_RECORD(CurrentEntry,
196                                            ADAPTER_BINDING,
197                                            AdapterListEntry);
198
199         KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
200
201         (*AdapterBinding->ProtocolBinding->Chars.ReceiveCompleteHandler)(
202             AdapterBinding->NdisOpenBlock.ProtocolBindingContext);
203
204         KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
205
206         CurrentEntry = CurrentEntry->Flink;
207     }
208     KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
209 }
210
211
212 VOID
213 MiniEthReceiveIndication(
214     IN  PETH_FILTER Filter,
215     IN  NDIS_HANDLE MacReceiveContext,
216     IN  PCHAR       Address,
217     IN  PVOID       HeaderBuffer,
218     IN  UINT        HeaderBufferSize,
219     IN  PVOID       LookaheadBuffer,
220     IN  UINT        LookaheadBufferSize,
221     IN  UINT        PacketSize)
222 /*
223  * FUNCTION: Receive indication function for Ethernet devices
224  * ARGUMENTS:
225  *     Filter              = Pointer to Ethernet filter
226  *     MacReceiveContext   = MAC receive context handle
227  *     Address             = Pointer to destination Ethernet address
228  *     HeaderBuffer        = Pointer to Ethernet header buffer
229  *     HeaderBufferSize    = Size of Ethernet header buffer
230  *     LookaheadBuffer     = Pointer to lookahead buffer
231  *     LookaheadBufferSize = Size of lookahead buffer
232  *     PacketSize          = Total size of received packet
233  */
234 {
235     MiniIndicateData((PLOGICAL_ADAPTER)Filter->Miniport,
236                      MacReceiveContext,
237                      HeaderBuffer,
238                      HeaderBufferSize,
239                      LookaheadBuffer,
240                      LookaheadBufferSize,
241                      PacketSize);
242 }
243
244
245 VOID
246 MiniResetComplete(
247     IN  NDIS_HANDLE MiniportAdapterHandle,
248     IN  NDIS_STATUS Status,
249     IN  BOOLEAN     AddressingReset)
250 {
251     UNIMPLEMENTED
252 }
253
254
255 VOID
256 MiniSendComplete(
257     IN  NDIS_HANDLE     MiniportAdapterHandle,
258     IN  PNDIS_PACKET    Packet,
259     IN  NDIS_STATUS     Status)
260 /*
261  * FUNCTION: Forwards a message to the initiating protocol saying
262  *           that a packet was handled
263  * ARGUMENTS:
264  *     NdisAdapterHandle = Handle input to MiniportInitialize
265  *     Packet            = Pointer to NDIS packet that was sent
266  *     Status            = Status of send operation
267  */
268 {
269     PADAPTER_BINDING AdapterBinding;
270
271     NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
272
273     AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[0];
274
275     (*AdapterBinding->ProtocolBinding->Chars.u2.SendCompleteHandler)(
276         AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
277         Packet,
278         Status);
279 }
280
281
282 VOID
283 MiniSendResourcesAvailable(
284     IN  NDIS_HANDLE MiniportAdapterHandle)
285 {
286     UNIMPLEMENTED
287 }
288
289
290 VOID
291 MiniTransferDataComplete(
292     IN  NDIS_HANDLE     MiniportAdapterHandle,
293     IN  PNDIS_PACKET    Packet,
294     IN  NDIS_STATUS     Status,
295     IN  UINT            BytesTransferred)
296 {
297     PLOGICAL_ADAPTER Adapter        = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
298     PADAPTER_BINDING AdapterBinding = Adapter->MiniportAdapterBinding;
299
300     NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
301
302     (*AdapterBinding->ProtocolBinding->Chars.u3.TransferDataCompleteHandler)(
303         AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
304         Packet,
305         Status,
306         BytesTransferred);
307 }
308
309
310 BOOLEAN
311 MiniAdapterHasAddress(
312     PLOGICAL_ADAPTER Adapter,
313     PNDIS_PACKET Packet)
314 /*
315  * FUNCTION: Determines wether a packet has the same destination address as an adapter
316  * ARGUMENTS:
317  *     Adapter = Pointer to logical adapter object
318  *     Packet  = Pointer to NDIS packet
319  * RETURNS:
320  *     TRUE if the destination address is that of the adapter, FALSE if not
321  */
322 {
323     UINT Length;
324     PUCHAR Start1;
325     PUCHAR Start2;
326     PNDIS_BUFFER NdisBuffer;
327     UINT BufferLength;
328
329     Start1 = (PUCHAR)&Adapter->Address;
330     NdisQueryPacket(Packet, NULL, NULL, &NdisBuffer, NULL);
331     if (!NdisBuffer) {
332         NDIS_DbgPrint(MID_TRACE, ("Packet contains no buffers.\n"));
333         return FALSE;
334     }
335
336     NdisQueryBuffer(NdisBuffer, (PVOID)&Start2, &BufferLength);
337
338     /* FIXME: Should handle fragmented packets */
339
340     switch (Adapter->NdisMiniportBlock.MediaType) {
341     case NdisMedium802_3:
342         Length = ETH_LENGTH_OF_ADDRESS;
343         /* Destination address is the first field */
344         break;
345
346     default:
347         NDIS_DbgPrint(MIN_TRACE, ("Adapter has unsupported media type (0x%X).\n",
348             Adapter->NdisMiniportBlock.MediaType));
349         return FALSE;
350     }
351
352     if (BufferLength < Length) {
353         NDIS_DbgPrint(MID_TRACE, ("Buffer is too small.\n"));
354         return FALSE;
355     }
356
357     return (RtlCompareMemory((PVOID)Start1, (PVOID)Start2, Length) == Length);
358 }
359
360
361 PLOGICAL_ADAPTER
362 MiniLocateDevice(
363     PNDIS_STRING AdapterName)
364 /*
365  * FUNCTION: Returns the logical adapter object for a specific adapter
366  * ARGUMENTS:
367  *     AdapterName = Pointer to name of adapter
368  * RETURNS:
369  *     Pointer to logical adapter object, or NULL if none was found.
370  *     If found, the adapter is referenced for the caller. The caller
371  *     is responsible for dereferencing after use
372  */
373 {
374     KIRQL OldIrql;
375     PLIST_ENTRY CurrentEntry;
376     PLOGICAL_ADAPTER Adapter;
377
378     NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
379
380     KeAcquireSpinLock(&AdapterListLock, &OldIrql);
381     CurrentEntry = AdapterListHead.Flink;
382     while (CurrentEntry != &AdapterListHead) {
383             Adapter = CONTAINING_RECORD(CurrentEntry, LOGICAL_ADAPTER, ListEntry);
384
385         if (RtlCompareUnicodeString(AdapterName, &Adapter->DeviceName, TRUE) == 0) {
386             ReferenceObject(Adapter);
387             KeReleaseSpinLock(&AdapterListLock, OldIrql);
388
389             NDIS_DbgPrint(DEBUG_MINIPORT, ("Leaving. Adapter found at (0x%X).\n", Adapter));
390
391             return Adapter;
392         }
393
394         CurrentEntry = CurrentEntry->Flink;
395     }
396     KeReleaseSpinLock(&AdapterListLock, OldIrql);
397
398     NDIS_DbgPrint(DEBUG_MINIPORT, ("Leaving (adapter not found).\n"));
399
400     return NULL;
401 }
402
403
404 NDIS_STATUS
405 MiniQueryInformation(
406     PLOGICAL_ADAPTER    Adapter,
407     NDIS_OID            Oid,
408     ULONG               Size,
409     PULONG              BytesWritten)
410 /*
411  * FUNCTION: Queries a logical adapter for properties
412  * ARGUMENTS:
413  *     Adapter      = Pointer to the logical adapter object to query
414  *     Oid          = Specifies the Object ID to query for
415  *     Size         = If non-zero overrides the length in the adapter object
416  *     BytesWritten = Address of buffer to place number of bytes written
417  * NOTES:
418  *     If the specified buffer is too small, a new buffer is allocated,
419  *     and the query is attempted again
420  * RETURNS:
421  *     Status of operation
422  */
423 {
424     NDIS_STATUS NdisStatus;
425     ULONG BytesNeeded;
426
427     if (Adapter->QueryBufferLength == 0) {
428         Adapter->QueryBuffer = ExAllocatePool(NonPagedPool, (Size == 0)? 32 : Size);
429
430         if (!Adapter->QueryBuffer) {
431             NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
432             return NDIS_STATUS_RESOURCES;
433         }
434
435         Adapter->QueryBufferLength = (Size == 0)? 32 : Size;
436     }
437
438     BytesNeeded = (Size == 0)? Adapter->QueryBufferLength : Size;
439
440     NdisStatus = (*Adapter->Miniport->Chars.QueryInformationHandler)(
441         Adapter->NdisMiniportBlock.MiniportAdapterContext,
442         Oid,
443         Adapter->QueryBuffer,
444         BytesNeeded,
445         BytesWritten,
446         &BytesNeeded);
447
448     if ((NT_SUCCESS(NdisStatus)) || (NdisStatus == NDIS_STATUS_PENDING)) {
449         NDIS_DbgPrint(DEBUG_MINIPORT, ("Miniport returned status (0x%X).\n", NdisStatus));
450         return NdisStatus;
451     }
452
453     if (NdisStatus == NDIS_STATUS_INVALID_LENGTH) {
454         ExFreePool(Adapter->QueryBuffer);
455
456         Adapter->QueryBufferLength += BytesNeeded;
457         Adapter->QueryBuffer = ExAllocatePool(NonPagedPool,
458                                               Adapter->QueryBufferLength);
459
460         if (!Adapter->QueryBuffer) {
461             NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
462             return NDIS_STATUS_RESOURCES;
463         }
464
465         NdisStatus = (*Adapter->Miniport->Chars.QueryInformationHandler)(
466             Adapter->NdisMiniportBlock.MiniportAdapterContext,
467             Oid,
468             Adapter->QueryBuffer,
469             Size,
470             BytesWritten,
471             &BytesNeeded);
472     }
473
474     return NdisStatus;
475 }
476
477
478 NDIS_STATUS
479 FASTCALL
480 MiniQueueWorkItem(
481     PLOGICAL_ADAPTER    Adapter,
482     NDIS_WORK_ITEM_TYPE WorkItemType,
483     PVOID               WorkItemContext,
484     NDIS_HANDLE         Initiator)
485 /*
486  * FUNCTION: Queues a work item for execution at a later time
487  * ARGUMENTS:
488  *     Adapter         = Pointer to the logical adapter object to queue work item on
489  *     WorkItemType    = Type of work item to queue
490  *     WorkItemContext = Pointer to context information for work item
491  *     Initiator       = Pointer to ADAPTER_BINDING structure of initiating protocol
492  * NOTES:
493  *     Adapter lock must be held when called
494  * RETURNS:
495  *     Status of operation
496  */
497 {
498     PNDIS_MINIPORT_WORK_ITEM Item;
499
500     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
501
502     if (Adapter->WorkQueueLevel < NDIS_MINIPORT_WORK_QUEUE_SIZE - 1) {
503         Item = &Adapter->WorkQueue[Adapter->WorkQueueLevel];
504         Adapter->WorkQueueLevel++;
505     } else {
506         Item = ExAllocatePool(NonPagedPool, sizeof(NDIS_MINIPORT_WORK_ITEM));
507         if (Item) {
508             /* Set flag so we know that the buffer should be freed
509                when work item is dequeued */
510             Item->Allocated = TRUE;
511         } else {
512             NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
513             return NDIS_STATUS_RESOURCES;
514         }
515     }
516
517     Item->WorkItemType    = WorkItemType;
518     Item->WorkItemContext = WorkItemContext;
519     Item->Initiator       = Initiator;
520
521     Item->Link.Next = NULL;
522     if (!Adapter->WorkQueueHead) {
523         Adapter->WorkQueueHead = Item;
524     } else {
525         Adapter->WorkQueueTail->Link.Next = (PSINGLE_LIST_ENTRY)Item;
526     }
527
528     KeInsertQueueDpc(&Adapter->MiniportDpc, NULL, NULL);
529
530     return NDIS_STATUS_SUCCESS;
531 }
532
533
534 NDIS_STATUS
535 FASTCALL
536 MiniDequeueWorkItem(
537     PLOGICAL_ADAPTER    Adapter,
538     NDIS_WORK_ITEM_TYPE *WorkItemType,
539     PVOID               *WorkItemContext,
540     NDIS_HANDLE         *Initiator)
541 /*
542  * FUNCTION: Dequeues a work item from the work queue of a logical adapter
543  * ARGUMENTS:
544  *     Adapter         = Pointer to the logical adapter object to dequeue work item from
545  *     WorkItemType    = Address of buffer for work item type
546  *     WorkItemContext = Address of buffer for pointer to context information
547  *     Initiator       = Address of buffer for initiator of the work (ADAPTER_BINDING)
548  * NOTES:
549  *     Adapter lock must be held when called
550  * RETURNS:
551  *     Status of operation
552  */
553 {
554     PNDIS_MINIPORT_WORK_ITEM Item;
555
556     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
557
558     Item = Adapter->WorkQueueHead;
559     if (Item) {
560         Adapter->WorkQueueHead = (PNDIS_MINIPORT_WORK_ITEM)Item->Link.Next;
561         if (Item == Adapter->WorkQueueTail)
562             Adapter->WorkQueueTail = NULL;
563
564         *WorkItemType    = Item->WorkItemType;
565         *WorkItemContext = Item->WorkItemContext;
566         *Initiator       = Item->Initiator;
567
568         if (Item->Allocated) {
569             ExFreePool(Item);
570         } else {
571             Adapter->WorkQueueLevel--;
572 #ifdef DBG
573             if (Adapter->WorkQueueLevel < 0) {
574                 NDIS_DbgPrint(MIN_TRACE, ("Adapter->WorkQueueLevel is < 0 (should be >= 0).\n"));
575             }
576 #endif
577         }
578
579         return NDIS_STATUS_SUCCESS;
580     }
581
582     return NDIS_STATUS_FAILURE;
583 }
584
585
586 NDIS_STATUS
587 MiniDoRequest(
588     PLOGICAL_ADAPTER Adapter,
589     PNDIS_REQUEST NdisRequest)
590 /*
591  * FUNCTION: Sends a request to a miniport
592  * ARGUMENTS:
593  *     Adapter     = Pointer to logical adapter object
594  *     NdisRequest = Pointer to NDIS request structure describing request
595  * RETURNS:
596  *     Status of operation
597  */
598 {
599     Adapter->NdisMiniportBlock.MediaRequest = NdisRequest;
600
601     switch (NdisRequest->RequestType) {
602     case NdisRequestQueryInformation:
603         return (*Adapter->Miniport->Chars.QueryInformationHandler)(
604             Adapter->NdisMiniportBlock.MiniportAdapterContext,
605             NdisRequest->DATA.QUERY_INFORMATION.Oid,
606             NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
607             NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength,
608             (PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesWritten,
609             (PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded);
610         break;
611
612     case NdisRequestSetInformation:
613         return (*Adapter->Miniport->Chars.SetInformationHandler)(
614             Adapter->NdisMiniportBlock.MiniportAdapterContext,
615             NdisRequest->DATA.SET_INFORMATION.Oid,
616             NdisRequest->DATA.SET_INFORMATION.InformationBuffer,
617             NdisRequest->DATA.SET_INFORMATION.InformationBufferLength,
618             (PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesRead,
619             (PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesNeeded);
620         break;
621
622     default:
623         return NDIS_STATUS_FAILURE;
624     }
625 }
626
627
628 VOID STDCALL MiniportDpc(
629     IN PKDPC Dpc,
630     IN PVOID DeferredContext,
631     IN PVOID SystemArgument1,
632     IN PVOID SystemArgument2)
633 /*
634  * FUNCTION: Deferred routine to handle serialization
635  * ARGUMENTS:
636  *     Dpc             = Pointer to DPC object
637  *     DeferredContext = Pointer to context information (LOGICAL_ADAPTER)
638  *     SystemArgument1 = Unused
639  *     SystemArgument2 = Unused
640  */
641 {
642     NDIS_STATUS NdisStatus;
643     PVOID WorkItemContext;
644     NDIS_WORK_ITEM_TYPE WorkItemType;
645     PADAPTER_BINDING AdapterBinding;
646     PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(DeferredContext);
647
648     NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
649
650     NdisStatus = MiniDequeueWorkItem(Adapter,
651                                      &WorkItemType,
652                                      &WorkItemContext,
653                                      (PNDIS_HANDLE)&AdapterBinding);
654     if (NdisStatus == NDIS_STATUS_SUCCESS) {
655         Adapter->MiniportAdapterBinding = AdapterBinding;
656         switch (WorkItemType) {
657         case NdisWorkItemSend:
658 #ifdef DBG
659             MiniDisplayPacket((PNDIS_PACKET)WorkItemContext);
660 #endif
661             NdisStatus = (*Adapter->Miniport->Chars.u1.SendHandler)(
662                 Adapter->NdisMiniportBlock.MiniportAdapterContext,
663                 (PNDIS_PACKET)WorkItemContext,
664                 0);
665             if (NdisStatus != NDIS_STATUS_PENDING) {
666                 MiniSendComplete((NDIS_HANDLE)Adapter,
667                                  (PNDIS_PACKET)WorkItemContext,
668                                  NdisStatus);
669             }
670             break;
671
672         case NdisWorkItemSendLoopback:
673             NdisStatus = ProIndicatePacket(Adapter,
674                                            (PNDIS_PACKET)WorkItemContext);
675             MiniSendComplete((NDIS_HANDLE)Adapter,
676                              (PNDIS_PACKET)WorkItemContext,
677                              NdisStatus);
678             break;
679
680         case NdisWorkItemReturnPackets:
681             break;
682
683         case NdisWorkItemResetRequested:
684             break;
685
686         case NdisWorkItemResetInProgress:
687             break;
688
689         case NdisWorkItemHalt:
690             break;
691
692         case NdisWorkItemMiniportCallback:
693             break;
694
695         case NdisWorkItemRequest:
696             NdisStatus = MiniDoRequest(Adapter, (PNDIS_REQUEST)WorkItemContext);
697
698             if (NdisStatus == NDIS_STATUS_PENDING)
699                 break;
700
701             switch (((PNDIS_REQUEST)WorkItemContext)->RequestType) {
702             case NdisRequestQueryInformation:
703                 NdisMQueryInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
704                 break;
705
706             case NdisRequestSetInformation:
707                 NdisMSetInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
708                 break;
709
710             default:
711                 NDIS_DbgPrint(MIN_TRACE, ("Unknown NDIS request type.\n"));
712                 break;
713             }
714             break;
715
716         default:
717             NDIS_DbgPrint(MIN_TRACE, ("Unknown NDIS work item type (%d).\n", WorkItemType));
718             break;
719         }
720     }
721 }
722
723
724 VOID
725 EXPORT
726 NdisMCloseLog(
727     IN  NDIS_HANDLE LogHandle)
728 {
729     UNIMPLEMENTED
730 }
731
732
733 NDIS_STATUS
734 EXPORT
735 NdisMCreateLog(
736     IN  NDIS_HANDLE     MiniportAdapterHandle,
737     IN  UINT            Size,
738     OUT PNDIS_HANDLE    LogHandle)
739 {
740     UNIMPLEMENTED
741
742         return NDIS_STATUS_FAILURE;
743 }
744
745
746 VOID
747 EXPORT
748 NdisMDeregisterAdapterShutdownHandler(
749     IN  NDIS_HANDLE MiniportHandle)
750 {
751     UNIMPLEMENTED
752 }
753
754
755 VOID
756 EXPORT
757 NdisMFlushLog(
758     IN  NDIS_HANDLE LogHandle)
759 {
760     UNIMPLEMENTED
761 }
762
763
764 VOID
765 EXPORT
766 NdisMIndicateStatus(
767     IN  NDIS_HANDLE MiniportAdapterHandle,
768     IN  NDIS_STATUS GeneralStatus,
769     IN  PVOID       StatusBuffer,
770     IN  UINT        StatusBufferSize)
771 {
772     UNIMPLEMENTED
773 }
774
775
776 VOID
777 EXPORT
778 NdisMIndicateStatusComplete(
779     IN  NDIS_HANDLE MiniportAdapterHandle)
780 {
781     UNIMPLEMENTED
782 }
783
784
785 VOID
786 EXPORT
787 NdisInitializeWrapper(
788     OUT PNDIS_HANDLE    NdisWrapperHandle,
789     IN  PVOID           SystemSpecific1,
790     IN  PVOID           SystemSpecific2,
791     IN  PVOID           SystemSpecific3)
792 /*
793  * FUNCTION: Notifies the NDIS library that a new miniport is initializing
794  * ARGUMENTS:
795  *     NdisWrapperHandle = Address of buffer to place NDIS wrapper handle
796  *     SystemSpecific1   = Pointer to the driver's driver object
797  *     SystemSpecific2   = Pointer to the driver's registry path
798  *     SystemSpecific3   = Always NULL
799  */
800 {
801     PMINIPORT_DRIVER Miniport;
802
803     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
804
805     Miniport = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_DRIVER));
806     if (!Miniport) {
807         NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
808         *NdisWrapperHandle = NULL;
809         return;
810     }
811
812     RtlZeroMemory(Miniport, sizeof(MINIPORT_DRIVER));
813
814     KeInitializeSpinLock(&Miniport->Lock);
815
816     Miniport->RefCount = 1;
817
818     Miniport->DriverObject = (PDRIVER_OBJECT)SystemSpecific1;
819
820     InitializeListHead(&Miniport->AdapterListHead);
821
822     /* Put miniport in global miniport list */
823     ExInterlockedInsertTailList(&MiniportListHead,
824                                 &Miniport->ListEntry,
825                                 &MiniportListLock);
826
827     *NdisWrapperHandle = Miniport;
828 }
829
830
831 VOID
832 EXPORT
833 NdisMQueryInformationComplete(
834     IN  NDIS_HANDLE MiniportAdapterHandle,
835     IN  NDIS_STATUS Status)
836 {
837     PLOGICAL_ADAPTER Adapter        = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
838     PADAPTER_BINDING AdapterBinding = (PADAPTER_BINDING)Adapter->MiniportAdapterBinding;
839
840     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
841
842     (*AdapterBinding->ProtocolBinding->Chars.RequestCompleteHandler)(
843         AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
844         Adapter->NdisMiniportBlock.MediaRequest,
845         Status);
846 }
847
848
849 VOID
850 EXPORT
851 NdisMRegisterAdapterShutdownHandler(
852     IN  NDIS_HANDLE                 MiniportHandle,
853     IN  PVOID                       ShutdownContext,
854     IN  ADAPTER_SHUTDOWN_HANDLER    ShutdownHandler)
855 {
856     UNIMPLEMENTED
857 }
858
859
860 NDIS_STATUS
861 DoQueries(
862     PLOGICAL_ADAPTER Adapter,
863     NDIS_OID AddressOID)
864 /*
865  * FUNCTION: Queries miniport for information
866  * ARGUMENTS:
867  *     Adapter    = Pointer to logical adapter
868  *     AddressOID = OID to use to query for current address
869  * RETURNS:
870  *     Status of operation
871  */
872 {
873     ULONG BytesWritten;
874     NDIS_STATUS NdisStatus;
875
876     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
877
878     /* Get MAC options for adapter */
879     NdisStatus = MiniQueryInformation(Adapter,
880                                       OID_GEN_MAC_OPTIONS,
881                                       0,
882                                       &BytesWritten);
883     if (NdisStatus != NDIS_STATUS_SUCCESS) {
884         NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAC_OPTIONS failed. NdisStatus (0x%X).\n", NdisStatus));
885         return NdisStatus;
886     }
887
888     RtlCopyMemory(&Adapter->NdisMiniportBlock.MacOptions, Adapter->QueryBuffer, sizeof(UINT));
889
890     NDIS_DbgPrint(DEBUG_MINIPORT, ("MacOptions (0x%X).\n", Adapter->NdisMiniportBlock.MacOptions));
891
892     /* Get current hardware address of adapter */
893     NdisStatus = MiniQueryInformation(Adapter,
894                                       AddressOID,
895                                       0,
896                                       &BytesWritten);
897     if (NdisStatus != NDIS_STATUS_SUCCESS) {
898         NDIS_DbgPrint(MIN_TRACE, ("Address OID (0x%X) failed. NdisStatus (0x%X).\n",
899             AddressOID, NdisStatus));
900         return NdisStatus;
901     }
902
903     RtlCopyMemory(&Adapter->Address, Adapter->QueryBuffer, Adapter->AddressLength);
904 #ifdef DBG
905     {
906         /* 802.3 only */
907
908         PUCHAR A = (PUCHAR)&Adapter->Address.Type.Medium802_3;
909
910         NDIS_DbgPrint(MAX_TRACE, ("Adapter address is (%02X %02X %02X %02X %02X %02X).\n",
911             A[0], A[1], A[2], A[3], A[4], A[5]));
912     }
913 #endif /* DBG */
914
915     /* Get maximum lookahead buffer size of adapter */
916     NdisStatus = MiniQueryInformation(Adapter,
917                                       OID_GEN_MAXIMUM_LOOKAHEAD,
918                                       0,
919                                       &BytesWritten);
920     if (NdisStatus != NDIS_STATUS_SUCCESS) {
921         NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAXIMUM_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus));
922         return NdisStatus;
923     }
924
925     Adapter->MaxLookaheadLength = *((PULONG)Adapter->QueryBuffer);
926
927     NDIS_DbgPrint(DEBUG_MINIPORT, ("MaxLookaheadLength (0x%X).\n", Adapter->MaxLookaheadLength));
928
929     /* Get current lookahead buffer size of adapter */
930     NdisStatus = MiniQueryInformation(Adapter,
931                                       OID_GEN_CURRENT_LOOKAHEAD,
932                                       0,
933                                       &BytesWritten);
934     if (NdisStatus != NDIS_STATUS_SUCCESS) {
935         NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_CURRENT_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus));
936         return NdisStatus;
937     }
938
939     Adapter->CurLookaheadLength = *((PULONG)Adapter->QueryBuffer);
940
941     NDIS_DbgPrint(DEBUG_MINIPORT, ("CurLookaheadLength (0x%X).\n", Adapter->CurLookaheadLength));
942
943     if (Adapter->MaxLookaheadLength != 0) {
944         Adapter->LookaheadLength = Adapter->MaxLookaheadLength +
945                                    Adapter->MediumHeaderSize;
946         Adapter->LookaheadBuffer = ExAllocatePool(NonPagedPool,
947                                                   Adapter->LookaheadLength);
948         if (!Adapter->LookaheadBuffer)
949             return NDIS_STATUS_RESOURCES;
950     }
951
952     return STATUS_SUCCESS;
953 }
954
955
956 NDIS_STATUS
957 EXPORT
958 NdisMRegisterMiniport(
959     IN  NDIS_HANDLE                     NdisWrapperHandle,
960     IN  PNDIS_MINIPORT_CHARACTERISTICS  MiniportCharacteristics,
961     IN  UINT                            CharacteristicsLength)
962 /*
963  * FUNCTION: Registers a miniport's MiniportXxx entry points with the NDIS library
964  * ARGUMENTS:
965  *     NdisWrapperHandle       = Pointer to handle returned by NdisMInitializeWrapper
966  *     MiniportCharacteristics = Pointer to a buffer with miniport characteristics
967  *     CharacteristicsLength   = Number of bytes in characteristics buffer
968  * RETURNS:
969  *     Status of operation
970  */
971 {
972     UINT MinSize;
973     KIRQL OldIrql;
974     NTSTATUS Status;
975     NDIS_STATUS NdisStatus;
976     NDIS_STATUS OpenErrorStatus;
977     UINT SelectedMediumIndex;
978     PLOGICAL_ADAPTER Adapter;
979     NDIS_OID AddressOID;
980     BOOLEAN MemError          = FALSE;
981     PMINIPORT_DRIVER Miniport = GET_MINIPORT_DRIVER(NdisWrapperHandle);
982
983     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
984
985     switch (MiniportCharacteristics->MajorNdisVersion) {
986     case 0x03:
987         MinSize = sizeof(NDIS30_MINIPORT_CHARACTERISTICS_S);
988         break;
989
990     case 0x04:
991         MinSize = sizeof(NDIS40_MINIPORT_CHARACTERISTICS_S);
992         break;
993
994     case 0x05:
995         MinSize = sizeof(NDIS50_MINIPORT_CHARACTERISTICS_S);
996         break;
997
998     default:
999         NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics version.\n"));
1000         return NDIS_STATUS_BAD_VERSION;
1001     }
1002
1003     if (CharacteristicsLength < MinSize) {
1004         NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
1005         return NDIS_STATUS_BAD_CHARACTERISTICS;
1006     }
1007
1008     /* Check if mandatory MiniportXxx functions are specified */
1009     if ((!MiniportCharacteristics->HaltHandler) ||
1010         (!MiniportCharacteristics->InitializeHandler)||
1011         (!MiniportCharacteristics->QueryInformationHandler) ||
1012         (!MiniportCharacteristics->ResetHandler) ||
1013         (!MiniportCharacteristics->SetInformationHandler)) {
1014         NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
1015         return NDIS_STATUS_BAD_CHARACTERISTICS;
1016     }
1017
1018     if (MiniportCharacteristics->MajorNdisVersion == 0x03) {
1019         if (!MiniportCharacteristics->u1.SendHandler) {
1020             NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
1021             return NDIS_STATUS_BAD_CHARACTERISTICS;
1022         }
1023     } else if (MiniportCharacteristics->MajorNdisVersion >= 0x04) {
1024         /* NDIS 4.0+ */
1025         if ((!MiniportCharacteristics->u1.SendHandler) &&
1026             (!MiniportCharacteristics->SendPacketsHandler)) {
1027             NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
1028             return NDIS_STATUS_BAD_CHARACTERISTICS;
1029         }
1030     }
1031
1032     RtlCopyMemory(&Miniport->Chars, MiniportCharacteristics, MinSize);
1033
1034     Adapter = ExAllocatePool(NonPagedPool, sizeof(LOGICAL_ADAPTER));
1035     if (!Adapter) {
1036         NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1037         return NDIS_STATUS_RESOURCES;
1038     }
1039
1040     /* This is very important */
1041     RtlZeroMemory(Adapter, sizeof(LOGICAL_ADAPTER));
1042
1043     /* Create the device object for this adapter */
1044     /* FIXME: Use GUIDs */
1045     RtlInitUnicodeStringFromLiteral(&Adapter->DeviceName, L"\\Device\\ne2000");
1046     Status = IoCreateDevice(Miniport->DriverObject,
1047                             0,
1048                             &Adapter->DeviceName,
1049                             FILE_DEVICE_PHYSICAL_NETCARD,
1050                             0,
1051                             FALSE,
1052                             &Adapter->NdisMiniportBlock.DeviceObject);
1053     if (!NT_SUCCESS(Status)) {
1054         NDIS_DbgPrint(MIN_TRACE, ("Could not create device object.\n"));
1055         ExFreePool(Adapter);
1056         return NDIS_STATUS_FAILURE;
1057     }
1058
1059     /* Initialize adapter object */
1060
1061     KeInitializeSpinLock(&Adapter->NdisMiniportBlock.Lock);
1062
1063     InitializeListHead(&Adapter->ProtocolListHead);
1064
1065     Adapter->RefCount = 1;
1066
1067     Adapter->Miniport = Miniport;
1068
1069     /* Set handlers (some NDIS macros require these) */
1070
1071     Adapter->NdisMiniportBlock.EthRxCompleteHandler = MiniEthReceiveComplete;
1072     Adapter->NdisMiniportBlock.EthRxIndicateHandler = MiniEthReceiveIndication;
1073
1074     Adapter->NdisMiniportBlock.SendCompleteHandler  = MiniSendComplete;
1075     Adapter->NdisMiniportBlock.SendResourcesHandler = MiniSendResourcesAvailable;
1076     Adapter->NdisMiniportBlock.ResetCompleteHandler = MiniResetComplete;
1077     Adapter->NdisMiniportBlock.TDCompleteHandler    = MiniTransferDataComplete;
1078
1079
1080     KeInitializeDpc(&Adapter->MiniportDpc, MiniportDpc, (PVOID)Adapter);
1081
1082     /* Put adapter in adapter list for this miniport */
1083     ExInterlockedInsertTailList(&Miniport->AdapterListHead,
1084                                 &Adapter->MiniportListEntry,
1085                                 &Miniport->Lock);
1086
1087     /* Put adapter in global adapter list */
1088     ExInterlockedInsertTailList(&AdapterListHead,
1089                                 &Adapter->ListEntry,
1090                                 &AdapterListLock);
1091
1092     /* Call MiniportInitialize */
1093     NdisStatus = (*Miniport->Chars.InitializeHandler)(
1094         &OpenErrorStatus,
1095         &SelectedMediumIndex,
1096         &MediaArray[0],
1097         MEDIA_ARRAY_SIZE,
1098         Adapter,
1099         NULL /* FIXME: WrapperConfigurationContext */);
1100
1101     if ((NdisStatus == NDIS_STATUS_SUCCESS) &&
1102         (SelectedMediumIndex < MEDIA_ARRAY_SIZE)) {
1103         
1104         Adapter->NdisMiniportBlock.MediaType = MediaArray[SelectedMediumIndex];
1105
1106         switch (Adapter->NdisMiniportBlock.MediaType) {
1107         case NdisMedium802_3:
1108             Adapter->MediumHeaderSize = 14;
1109             AddressOID = OID_802_3_CURRENT_ADDRESS;
1110             Adapter->AddressLength = ETH_LENGTH_OF_ADDRESS;
1111
1112             Adapter->NdisMiniportBlock.FilterDbs.u.EthDB = ExAllocatePool(NonPagedPool,
1113                                                         sizeof(ETH_FILTER));
1114             if (Adapter->NdisMiniportBlock.FilterDbs.u.EthDB) {
1115                 RtlZeroMemory(Adapter->NdisMiniportBlock.FilterDbs.u.EthDB, sizeof(ETH_FILTER));
1116                 Adapter->NdisMiniportBlock.FilterDbs.u.EthDB->Miniport = (PNDIS_MINIPORT_BLOCK)Adapter;
1117             } else
1118                 MemError = TRUE;
1119             break;
1120
1121         default:
1122             /* FIXME: Support other types of medias */
1123             ASSERT(FALSE);
1124             return NDIS_STATUS_FAILURE;
1125         }
1126
1127         NdisStatus = DoQueries(Adapter, AddressOID);
1128     }
1129
1130     if ((MemError) ||
1131         (NdisStatus != NDIS_STATUS_SUCCESS) ||
1132         (SelectedMediumIndex >= MEDIA_ARRAY_SIZE)) {
1133
1134         /* Remove adapter from adapter list for this miniport */
1135         KeAcquireSpinLock(&Miniport->Lock, &OldIrql);
1136         RemoveEntryList(&Adapter->MiniportListEntry);
1137         KeReleaseSpinLock(&Miniport->Lock, OldIrql);
1138
1139         /* Remove adapter from global adapter list */
1140         KeAcquireSpinLock(&AdapterListLock, &OldIrql);
1141         RemoveEntryList(&Adapter->ListEntry);
1142         KeReleaseSpinLock(&AdapterListLock, OldIrql);
1143
1144         if (Adapter->LookaheadBuffer)
1145             ExFreePool(Adapter->LookaheadBuffer);
1146
1147         IoDeleteDevice(Adapter->NdisMiniportBlock.DeviceObject);
1148         ExFreePool(Adapter);
1149         return NDIS_STATUS_FAILURE;
1150     }
1151
1152     return NDIS_STATUS_SUCCESS;
1153 }
1154
1155
1156 VOID
1157 EXPORT
1158 NdisMResetComplete(
1159     IN NDIS_HANDLE MiniportAdapterHandle,
1160     IN NDIS_STATUS Status,
1161     IN BOOLEAN     AddressingReset)
1162 {
1163     MiniResetComplete(MiniportAdapterHandle,
1164                       Status,
1165                       AddressingReset);
1166 }
1167
1168
1169 VOID
1170 EXPORT
1171 NdisMSendComplete(
1172     IN  NDIS_HANDLE     MiniportAdapterHandle,
1173     IN  PNDIS_PACKET    Packet,
1174     IN  NDIS_STATUS     Status)
1175 /*
1176  * FUNCTION: Forwards a message to the initiating protocol saying
1177  *           that a packet was handled
1178  * ARGUMENTS:
1179  *     NdisAdapterHandle = Handle input to MiniportInitialize
1180  *     Packet            = Pointer to NDIS packet that was sent
1181  *     Status            = Status of send operation
1182  */
1183 {
1184     MiniSendComplete(MiniportAdapterHandle,
1185                      Packet,
1186                      Status);
1187 }
1188
1189
1190 VOID
1191 EXPORT
1192 NdisMSendResourcesAvailable(
1193     IN  NDIS_HANDLE MiniportAdapterHandle)
1194 {
1195     MiniSendResourcesAvailable(MiniportAdapterHandle);
1196 }
1197
1198
1199 VOID
1200 EXPORT
1201 NdisMTransferDataComplete(
1202     IN  NDIS_HANDLE     MiniportAdapterHandle,
1203     IN  PNDIS_PACKET    Packet,
1204     IN  NDIS_STATUS     Status,
1205     IN  UINT            BytesTransferred)
1206 {
1207     MiniTransferDataComplete(MiniportAdapterHandle,
1208                              Packet,
1209                              Status,
1210                              BytesTransferred);
1211 }
1212
1213
1214 VOID
1215 EXPORT
1216 NdisMSetInformationComplete(
1217     IN  NDIS_HANDLE MiniportAdapterHandle,
1218     IN  NDIS_STATUS Status)
1219 {
1220     PLOGICAL_ADAPTER Adapter        = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
1221     PADAPTER_BINDING AdapterBinding = (PADAPTER_BINDING)Adapter->MiniportAdapterBinding;
1222
1223     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1224
1225     (*AdapterBinding->ProtocolBinding->Chars.RequestCompleteHandler)(
1226         AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
1227         Adapter->NdisMiniportBlock.MediaRequest,
1228         Status);
1229 }
1230
1231
1232 VOID
1233 EXPORT
1234 NdisMSetAttributes(
1235     IN  NDIS_HANDLE         MiniportAdapterHandle,
1236     IN  NDIS_HANDLE         MiniportAdapterContext,
1237     IN  BOOLEAN             BusMaster,
1238     IN  NDIS_INTERFACE_TYPE AdapterType)
1239 /*
1240  * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
1241  * ARGUMENTS:
1242  *     MiniportAdapterHandle  = Handle input to MiniportInitialize
1243  *     MiniportAdapterContext = Pointer to context information
1244  *     BusMaster              = Specifies TRUE if the caller's NIC is a busmaster DMA device
1245  *     AdapterType            = Specifies the I/O bus interface of the caller's NIC
1246  */
1247 {
1248     PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
1249
1250     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1251
1252     Adapter->NdisMiniportBlock.MiniportAdapterContext = MiniportAdapterContext;
1253     Adapter->Attributes    = BusMaster? NDIS_ATTRIBUTE_BUS_MASTER : 0;
1254     Adapter->NdisMiniportBlock.AdapterType   = AdapterType;
1255     Adapter->AttributesSet = TRUE;
1256 }
1257
1258
1259 VOID
1260 EXPORT
1261 NdisMSetAttributesEx(
1262     IN  NDIS_HANDLE         MiniportAdapterHandle,
1263     IN  NDIS_HANDLE         MiniportAdapterContext,
1264     IN  UINT                CheckForHangTimeInSeconds   OPTIONAL,
1265     IN  ULONG               AttributeFlags,
1266     IN  NDIS_INTERFACE_TYPE     AdapterType)
1267 /*
1268  * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
1269  * ARGUMENTS:
1270  *     MiniportAdapterHandle     = Handle input to MiniportInitialize
1271  *     MiniportAdapterContext    = Pointer to context information
1272  *     CheckForHangTimeInSeconds = Specifies interval in seconds at which
1273  *                                 MiniportCheckForHang should be called
1274  *     AttributeFlags            = Bitmask that indicates specific attributes
1275  *     AdapterType               = Specifies the I/O bus interface of the caller's NIC
1276  */
1277 {
1278         // Currently just like NdisMSetAttributesEx
1279         // TODO: Take CheckForHandTimeInSeconds into account!
1280         PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
1281
1282     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1283     NDIS_DbgPrint(MIN_TRACE, ("NdisMSetAttributesEx() is partly-implemented."));
1284
1285     Adapter->NdisMiniportBlock.MiniportAdapterContext = MiniportAdapterContext;
1286         Adapter->Attributes = AttributeFlags & NDIS_ATTRIBUTE_BUS_MASTER;
1287         Adapter->NdisMiniportBlock.AdapterType   = AdapterType;
1288     Adapter->AttributesSet = TRUE;
1289 }
1290
1291
1292 VOID
1293 EXPORT
1294 NdisMSleep(
1295     IN  ULONG   MicrosecondsToSleep)
1296 {
1297     UNIMPLEMENTED
1298 }
1299
1300
1301 BOOLEAN
1302 EXPORT
1303 NdisMSynchronizeWithInterrupt(
1304     IN  PNDIS_MINIPORT_INTERRUPT    Interrupt,
1305     IN  PVOID                       SynchronizeFunction,
1306     IN  PVOID                       SynchronizeContext)
1307 {
1308     UNIMPLEMENTED
1309
1310     return FALSE;
1311 }
1312
1313
1314 NDIS_STATUS
1315 EXPORT
1316 NdisMWriteLogData(
1317     IN  NDIS_HANDLE LogHandle,
1318     IN  PVOID       LogBuffer,
1319     IN  UINT        LogBufferSize)
1320 {
1321     UNIMPLEMENTED
1322
1323         return NDIS_STATUS_FAILURE;
1324 }
1325
1326
1327 VOID
1328 EXPORT
1329 NdisTerminateWrapper(
1330     IN  NDIS_HANDLE NdisWrapperHandle,
1331     IN  PVOID       SystemSpecific)
1332 /*
1333  * FUNCTION: Releases resources allocated by a call to NdisInitializeWrapper
1334  * ARGUMENTS:
1335  *     NdisWrapperHandle = Handle returned by NdisInitializeWrapper (MINIPORT_DRIVER)
1336  *     SystemSpecific    = Always NULL
1337  */
1338 {
1339     PMINIPORT_DRIVER Miniport = GET_MINIPORT_DRIVER(NdisWrapperHandle);
1340
1341     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1342
1343     ExFreePool(Miniport);
1344 }
1345
1346 /* EOF */