6edd45ec8aa18e421eb1096f3c688639cf89cd38
[reactos.git] / reactos / 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 * Vizzini (vizzini@plasmic.com)
8 * REVISIONS:
9 * CSH 01/08-2000 Created
10 * 20 Aug 2003 vizzini - DMA support
11 * 3 Oct 2003 vizzini - SendPackets support
12 */
13 #include <roscfg.h>
14 #include "ndissys.h"
15
16 #ifdef DBG
17 #include <buffer.h>
18 #endif /* DBG */
19
20 /* Root of the scm database */
21 #define SERVICES_ROOT L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
22
23 /*
24 * Define to 1 to get a debugger breakpoint at the end of NdisInitializeWrapper
25 * for each new miniport starting up
26 */
27 #define BREAK_ON_MINIPORT_INIT 0
28
29 /*
30 * This has to be big enough to hold the results of querying the Route value
31 * from the Linkage key. Please re-code me to determine this dynamically.
32 */
33 #define ROUTE_DATA_SIZE 256
34
35 /* Number of media we know */
36 #define MEDIA_ARRAY_SIZE 15
37
38 static NDIS_MEDIUM MediaArray[MEDIA_ARRAY_SIZE] =
39 {
40 NdisMedium802_3,
41 NdisMedium802_5,
42 NdisMediumFddi,
43 NdisMediumWan,
44 NdisMediumLocalTalk,
45 NdisMediumDix,
46 NdisMediumArcnetRaw,
47 NdisMediumArcnet878_2,
48 NdisMediumAtm,
49 NdisMediumWirelessWan,
50 NdisMediumIrda,
51 NdisMediumBpc,
52 NdisMediumCoWan,
53 NdisMedium1394,
54 NdisMediumMax
55 };
56
57 /* global list and lock of Miniports NDIS has registered */
58 LIST_ENTRY MiniportListHead;
59 KSPIN_LOCK MiniportListLock;
60
61 /* global list and lock of adapters NDIS has registered */
62 LIST_ENTRY AdapterListHead;
63 KSPIN_LOCK AdapterListLock;
64
65 VOID
66 MiniDisplayPacket(
67 PNDIS_PACKET Packet)
68 {
69 //#ifdef DBG
70 #if 0
71 ULONG i, Length;
72 UCHAR Buffer[64];
73 if ((DebugTraceLevel | DEBUG_PACKET) > 0) {
74 Length = CopyPacketToBuffer(
75 (PUCHAR)&Buffer,
76 Packet,
77 0,
78 64);
79
80 DbgPrint("*** PACKET START ***");
81
82 for (i = 0; i < Length; i++) {
83 if (i % 12 == 0)
84 DbgPrint("\n%04X ", i);
85 DbgPrint("%02X ", Buffer[i]);
86 }
87
88 DbgPrint("*** PACKET STOP ***\n");
89 }
90 #endif /* DBG */
91 }
92
93 VOID
94 MiniDisplayPacket2(
95 PVOID HeaderBuffer,
96 UINT HeaderBufferSize,
97 PVOID LookaheadBuffer,
98 UINT LookaheadBufferSize)
99 {
100 #ifdef DBG
101 if ((DebugTraceLevel | DEBUG_PACKET) > 0) {
102 ULONG i, Length;
103 PUCHAR p;
104
105 DbgPrint("*** RECEIVE PACKET START ***\n");
106 DbgPrint("HEADER:");
107 p = HeaderBuffer;
108 for (i = 0; i < HeaderBufferSize; i++) {
109 if (i % 16 == 0)
110 DbgPrint("\n%04X ", i);
111 DbgPrint("%02X ", *p++);
112 }
113
114 DbgPrint("\nFRAME:");
115
116 p = LookaheadBuffer;
117 Length = (LookaheadBufferSize < 64)? LookaheadBufferSize : 64;
118 for (i = 0; i < Length; i++) {
119 if (i % 16 == 0)
120 DbgPrint("\n%04X ", i);
121 DbgPrint("%02X ", *p++);
122 }
123
124 DbgPrint("\n*** RECEIVE PACKET STOP ***\n");
125 }
126 #endif /* DBG */
127 }
128
129 \f
130 VOID
131 MiniIndicateData(
132 PLOGICAL_ADAPTER Adapter,
133 NDIS_HANDLE MacReceiveContext,
134 PVOID HeaderBuffer,
135 UINT HeaderBufferSize,
136 PVOID LookaheadBuffer,
137 UINT LookaheadBufferSize,
138 UINT PacketSize)
139 /*
140 * FUNCTION: Indicate received data to bound protocols
141 * ARGUMENTS:
142 * Adapter = Pointer to logical adapter
143 * MacReceiveContext = MAC receive context handle
144 * HeaderBuffer = Pointer to header buffer
145 * HeaderBufferSize = Size of header buffer
146 * LookaheadBuffer = Pointer to lookahead buffer
147 * LookaheadBufferSize = Size of lookahead buffer
148 * PacketSize = Total size of received packet
149 */
150 {
151 /* KIRQL OldIrql; */
152 PLIST_ENTRY CurrentEntry;
153 PADAPTER_BINDING AdapterBinding;
154
155 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called. Adapter (0x%X) HeaderBuffer (0x%X) "
156 "HeaderBufferSize (0x%X) LookaheadBuffer (0x%X) LookaheadBufferSize (0x%X).\n",
157 Adapter, HeaderBuffer, HeaderBufferSize, LookaheadBuffer, LookaheadBufferSize));
158
159 MiniDisplayPacket2(HeaderBuffer, HeaderBufferSize, LookaheadBuffer, LookaheadBufferSize);
160
161 /*
162 * XXX Think about this. This is probably broken. Spinlocks are
163 * taken out for now until i comprehend the Right Way to do this.
164 *
165 * This used to acquire the MiniportBlock spinlock and hold it until
166 * just before the call to ReceiveHandler. It would then release and
167 * subsequently re-acquire the lock.
168 *
169 * I don't see how this does any good, as it would seem he's just
170 * trying to protect the packet list. If someobdy else dequeues
171 * a packet, we are in fact in bad shape, but we don't want to
172 * necessarily call the receive handler at elevated irql either.
173 *
174 * therefore: We *are* going to call the receive handler at high irql
175 * (due to holding the lock) for now, and eventually we have to
176 * figure out another way to protect this packet list.
177 *
178 * UPDATE: this is busted; this results in a recursive lock acquisition.
179 */
180 //NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
181 //KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
182 {
183 CurrentEntry = Adapter->ProtocolListHead.Flink;
184 NDIS_DbgPrint(DEBUG_MINIPORT, ("CurrentEntry = %x\n", CurrentEntry));
185
186 if (CurrentEntry == &Adapter->ProtocolListHead)
187 {
188 NDIS_DbgPrint(DEBUG_MINIPORT, ("WARNING: No upper protocol layer.\n"));
189 }
190
191 while (CurrentEntry != &Adapter->ProtocolListHead)
192 {
193 AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
194 NDIS_DbgPrint(DEBUG_MINIPORT, ("AdapterBinding = %x\n", AdapterBinding));
195
196 /* see above */
197 /* KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); */
198
199 #ifdef DBG
200 if(!AdapterBinding)
201 {
202 NDIS_DbgPrint(MIN_TRACE, ("AdapterBinding was null\n"));
203 break;
204 }
205
206 if(!AdapterBinding->ProtocolBinding)
207 {
208 NDIS_DbgPrint(MIN_TRACE, ("AdapterBinding->ProtocolBinding was null\n"));
209 break;
210 }
211
212 if(!AdapterBinding->ProtocolBinding->Chars.u4.ReceiveHandler)
213 {
214 NDIS_DbgPrint(MIN_TRACE, ("AdapterBinding->ProtocolBinding->Chars.u4.ReceiveHandler was null\n"));
215 break;
216 }
217 #endif
218
219 NDIS_DbgPrint
220 (MID_TRACE,
221 ("XXX (%x) %x %x %x %x %x %x %x XXX\n",
222 *AdapterBinding->ProtocolBinding->Chars.u4.ReceiveHandler,
223 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
224 MacReceiveContext,
225 HeaderBuffer,
226 HeaderBufferSize,
227 LookaheadBuffer,
228 LookaheadBufferSize,
229 PacketSize));
230
231 /* call the receive handler */
232 (*AdapterBinding->ProtocolBinding->Chars.u4.ReceiveHandler)(
233 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
234 MacReceiveContext,
235 HeaderBuffer,
236 HeaderBufferSize,
237 LookaheadBuffer,
238 LookaheadBufferSize,
239 PacketSize);
240
241 /* see above */
242 /* KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql); */
243
244 CurrentEntry = CurrentEntry->Flink;
245 }
246 }
247 //KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
248
249 NDIS_DbgPrint(MAX_TRACE, ("Leaving.\n"));
250 }
251
252 \f
253 VOID STDCALL
254 MiniIndicateReceivePacket(
255 IN NDIS_HANDLE Miniport,
256 IN PPNDIS_PACKET PacketArray,
257 IN UINT NumberOfPackets)
258 /*
259 * FUNCTION: receives miniport packet array indications
260 * ARGUMENTS:
261 * Miniport: Miniport handle for the adapter
262 * PacketArray: pointer to a list of packet pointers to indicate
263 * NumberOfPackets: number of packets to indicate
264 * NOTES:
265 * - This currently is a big temporary hack. In the future this should
266 * call ProtocolReceivePacket() on each bound protocol if it exists.
267 * For now it just mimics NdisMEthIndicateReceive.
268 */
269 {
270 UINT i;
271
272 for(i = 0; i < NumberOfPackets; i++)
273 {
274 PCHAR PacketBuffer = 0;
275 UINT PacketLength = 0;
276 PNDIS_BUFFER NdisBuffer = 0;
277
278 #define PACKET_TAG (('k' << 24) + ('P' << 16) + ('D' << 8) + 'N')
279
280 NdisAllocateMemoryWithTag((PVOID)&PacketBuffer, 1518, PACKET_TAG);
281 if(!PacketBuffer)
282 {
283 NDIS_DbgPrint(MIN_TRACE, ("insufficient resources\n"));
284 return;
285 }
286
287 NdisQueryPacket(PacketArray[i], NULL, NULL, &NdisBuffer, NULL);
288
289 while(NdisBuffer)
290 {
291 PNDIS_BUFFER CurrentBuffer;
292 PVOID BufferVa;
293 UINT BufferLen;
294
295 NdisQueryBuffer(NdisBuffer, &BufferVa, &BufferLen);
296 memcpy(PacketBuffer + PacketLength, BufferVa, BufferLen);
297 PacketLength += BufferLen;
298
299 CurrentBuffer = NdisBuffer;
300 NdisGetNextBuffer(CurrentBuffer, &NdisBuffer);
301 }
302
303 NDIS_DbgPrint(MID_TRACE, ("indicating a %d-byte packet\n", PacketLength));
304
305 MiniIndicateData(Miniport, NULL, PacketBuffer, 14, PacketBuffer+14, PacketLength-14, PacketLength-14);
306
307 NdisFreeMemory(PacketBuffer, 0, 0);
308 }
309 }
310
311 \f
312 VOID STDCALL
313 MiniEthReceiveComplete(
314 IN PETH_FILTER Filter)
315 /*
316 * FUNCTION: Receive indication complete function for Ethernet devices
317 * ARGUMENTS:
318 * Filter = Pointer to Ethernet filter
319 */
320 {
321 KIRQL OldIrql;
322 PLIST_ENTRY CurrentEntry;
323 PLOGICAL_ADAPTER Adapter;
324 PADAPTER_BINDING AdapterBinding;
325
326 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
327
328 if( !Filter ) return;
329
330 Adapter = (PLOGICAL_ADAPTER)Filter->Miniport;
331
332 NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
333 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
334 {
335 CurrentEntry = Adapter->ProtocolListHead.Flink;
336
337 while (CurrentEntry != &Adapter->ProtocolListHead)
338 {
339 AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
340
341 /* see comment in MiniIndicateData */
342 /* KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); */
343
344 (*AdapterBinding->ProtocolBinding->Chars.ReceiveCompleteHandler)(
345 AdapterBinding->NdisOpenBlock.ProtocolBindingContext);
346
347 /* see above */
348 /* KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql); */
349
350 CurrentEntry = CurrentEntry->Flink;
351 }
352 }
353 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
354 }
355
356 \f
357 VOID STDCALL
358 MiniEthReceiveIndication(
359 IN PETH_FILTER Filter,
360 IN NDIS_HANDLE MacReceiveContext,
361 IN PCHAR Address,
362 IN PVOID HeaderBuffer,
363 IN UINT HeaderBufferSize,
364 IN PVOID LookaheadBuffer,
365 IN UINT LookaheadBufferSize,
366 IN UINT PacketSize)
367 /*
368 * FUNCTION: Receive indication function for Ethernet devices
369 * ARGUMENTS:
370 * MiniportAdapter = Miniport Adapter Handle (PLOGICAL_ADAPTER)
371 * MacReceiveContext = MAC receive context handle
372 * Address = Pointer to destination Ethernet address
373 * HeaderBuffer = Pointer to Ethernet header buffer
374 * HeaderBufferSize = Size of Ethernet header buffer
375 * LookaheadBuffer = Pointer to lookahead buffer
376 * LookaheadBufferSize = Size of lookahead buffer
377 * PacketSize = Total size of received packet
378 */
379 {
380 MiniIndicateData((PLOGICAL_ADAPTER)Filter->Miniport,
381 MacReceiveContext,
382 HeaderBuffer,
383 HeaderBufferSize,
384 LookaheadBuffer,
385 LookaheadBufferSize,
386 PacketSize);
387 }
388
389 \f
390 VOID STDCALL
391 MiniResetComplete(
392 IN NDIS_HANDLE MiniportAdapterHandle,
393 IN NDIS_STATUS Status,
394 IN BOOLEAN AddressingReset)
395 {
396 UNIMPLEMENTED
397 }
398
399
400 VOID STDCALL
401 MiniSendComplete(
402 IN NDIS_HANDLE MiniportAdapterHandle,
403 IN PNDIS_PACKET Packet,
404 IN NDIS_STATUS Status)
405 /*
406 * FUNCTION: Forwards a message to the initiating protocol saying
407 * that a packet was handled
408 * ARGUMENTS:
409 * NdisAdapterHandle = Handle input to MiniportInitialize
410 * Packet = Pointer to NDIS packet that was sent
411 * Status = Status of send operation
412 */
413 {
414 PADAPTER_BINDING AdapterBinding;
415
416 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
417
418 AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[0];
419
420 (*AdapterBinding->ProtocolBinding->Chars.u2.SendCompleteHandler)(
421 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
422 Packet,
423 Status);
424 }
425
426
427 VOID STDCALL
428 MiniSendResourcesAvailable(
429 IN NDIS_HANDLE MiniportAdapterHandle)
430 {
431 UNIMPLEMENTED
432 }
433
434
435 VOID STDCALL
436 MiniTransferDataComplete(
437 IN NDIS_HANDLE MiniportAdapterHandle,
438 IN PNDIS_PACKET Packet,
439 IN NDIS_STATUS Status,
440 IN UINT BytesTransferred)
441 {
442 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
443 PADAPTER_BINDING AdapterBinding = Adapter->MiniportAdapterBinding;
444
445 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
446
447 (*AdapterBinding->ProtocolBinding->Chars.u3.TransferDataCompleteHandler)(
448 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
449 Packet,
450 Status,
451 BytesTransferred);
452 }
453
454 \f
455 BOOLEAN
456 MiniAdapterHasAddress(
457 PLOGICAL_ADAPTER Adapter,
458 PNDIS_PACKET Packet)
459 /*
460 * FUNCTION: Determines wether a packet has the same destination address as an adapter
461 * ARGUMENTS:
462 * Adapter = Pointer to logical adapter object
463 * Packet = Pointer to NDIS packet
464 * RETURNS:
465 * TRUE if the destination address is that of the adapter, FALSE if not
466 */
467 {
468 UINT Length;
469 PUCHAR Start1;
470 PUCHAR Start2;
471 PNDIS_BUFFER NdisBuffer;
472 UINT BufferLength;
473
474 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
475
476 #ifdef DBG
477 if(!Adapter)
478 {
479 NDIS_DbgPrint(MID_TRACE, ("Adapter object was null\n"));
480 return FALSE;
481 }
482
483 if(!Packet)
484 {
485 NDIS_DbgPrint(MID_TRACE, ("Packet was null\n"));
486 return FALSE;
487 }
488 #endif
489
490 NdisQueryPacket(Packet, NULL, NULL, &NdisBuffer, NULL);
491
492 if (!NdisBuffer)
493 {
494 NDIS_DbgPrint(MID_TRACE, ("Packet contains no buffers.\n"));
495 return FALSE;
496 }
497
498 NdisQueryBuffer(NdisBuffer, (PVOID)&Start2, &BufferLength);
499
500 /* FIXME: Should handle fragmented packets */
501
502 switch (Adapter->NdisMiniportBlock.MediaType)
503 {
504 case NdisMedium802_3:
505 Length = ETH_LENGTH_OF_ADDRESS;
506 /* Destination address is the first field */
507 break;
508
509 default:
510 NDIS_DbgPrint(MIN_TRACE, ("Adapter has unsupported media type (0x%X).\n", Adapter->NdisMiniportBlock.MediaType));
511 return FALSE;
512 }
513
514 if (BufferLength < Length)
515 {
516 NDIS_DbgPrint(MID_TRACE, ("Buffer is too small.\n"));
517 return FALSE;
518 }
519
520 Start1 = (PUCHAR)&Adapter->Address;
521 NDIS_DbgPrint(MAX_TRACE, ("packet address: %x:%x:%x:%x:%x:%x adapter address: %x:%x:%x:%x:%x:%x\n",
522 *((char *)Start1), *(((char *)Start1)+1), *(((char *)Start1)+2), *(((char *)Start1)+3), *(((char *)Start1)+4), *(((char *)Start1)+5),
523 *((char *)Start2), *(((char *)Start2)+1), *(((char *)Start2)+2), *(((char *)Start2)+3), *(((char *)Start2)+4), *(((char *)Start2)+5))
524 );
525
526 return (RtlCompareMemory((PVOID)Start1, (PVOID)Start2, Length) == Length);
527 }
528
529 \f
530 PLOGICAL_ADAPTER
531 MiniLocateDevice(
532 PNDIS_STRING AdapterName)
533 /*
534 * FUNCTION: Finds an adapter object by name
535 * ARGUMENTS:
536 * AdapterName = Pointer to name of adapter
537 * RETURNS:
538 * Pointer to logical adapter object, or NULL if none was found.
539 * If found, the adapter is referenced for the caller. The caller
540 * is responsible for dereferencing after use
541 */
542 {
543 KIRQL OldIrql;
544 PLIST_ENTRY CurrentEntry;
545 PLOGICAL_ADAPTER Adapter = 0;
546
547 ASSERT(AdapterName);
548
549 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
550
551 if(IsListEmpty(&AdapterListHead))
552 {
553 NDIS_DbgPrint(DEBUG_MINIPORT, ("No registered miniports for protocol to bind to\n"));
554 return NULL;
555 }
556
557 KeAcquireSpinLock(&AdapterListLock, &OldIrql);
558 {
559 do
560 {
561 CurrentEntry = AdapterListHead.Flink;
562
563 while (CurrentEntry != &AdapterListHead)
564 {
565 Adapter = CONTAINING_RECORD(CurrentEntry, LOGICAL_ADAPTER, ListEntry);
566
567 ASSERT(Adapter);
568
569 NDIS_DbgPrint(DEBUG_MINIPORT, ("AdapterName = %wZ\n", &AdapterName));
570 NDIS_DbgPrint(DEBUG_MINIPORT, ("DeviceName = %wZ\n", &Adapter->DeviceName));
571
572 if (RtlCompareUnicodeString(AdapterName, &Adapter->DeviceName, TRUE) == 0)
573 {
574 ReferenceObject(Adapter);
575 break;
576 }
577
578 CurrentEntry = CurrentEntry->Flink;
579 }
580 } while (0);
581 }
582 KeReleaseSpinLock(&AdapterListLock, OldIrql);
583
584 if(Adapter)
585 {
586 NDIS_DbgPrint(DEBUG_MINIPORT, ("Leaving. Adapter found at 0x%x\n", Adapter));
587 }
588 else
589 {
590 NDIS_DbgPrint(DEBUG_MINIPORT, ("Leaving (adapter not found).\n"));
591 }
592
593 return Adapter;
594 }
595
596 \f
597 NDIS_STATUS
598 MiniQueryInformation(
599 PLOGICAL_ADAPTER Adapter,
600 NDIS_OID Oid,
601 ULONG Size,
602 PULONG BytesWritten)
603 /*
604 * FUNCTION: Queries a logical adapter for properties
605 * ARGUMENTS:
606 * Adapter = Pointer to the logical adapter object to query
607 * Oid = Specifies the Object ID to query for
608 * Size = If non-zero overrides the length in the adapter object
609 * BytesWritten = Address of buffer to place number of bytes written
610 * NOTES:
611 * If the specified buffer is too small, a new buffer is allocated,
612 * and the query is attempted again
613 * RETURNS:
614 * Status of operation
615 * TODO:
616 * Is there any way to use the buffer provided by the protocol?
617 */
618 {
619 NDIS_STATUS NdisStatus;
620 ULONG BytesNeeded;
621
622 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
623
624 if (Adapter->QueryBufferLength == 0)
625 {
626 /* XXX is 32 the right number? */
627 Adapter->QueryBuffer = ExAllocatePool(NonPagedPool, (Size == 0)? 32 : Size);
628
629 if (!Adapter->QueryBuffer)
630 {
631 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
632 return NDIS_STATUS_RESOURCES;
633 }
634
635 /* ditto */
636 Adapter->QueryBufferLength = (Size == 0)? 32 : Size;
637 }
638
639 /* this is the third time i've seen this conditional */
640 BytesNeeded = (Size == 0)? Adapter->QueryBufferLength : Size;
641
642 /* call the miniport's queryinfo handler */
643 NdisStatus = (*Adapter->Miniport->Chars.QueryInformationHandler)(
644 Adapter->NdisMiniportBlock.MiniportAdapterContext,
645 Oid,
646 Adapter->QueryBuffer,
647 BytesNeeded,
648 BytesWritten,
649 &BytesNeeded);
650
651 /* XXX is status_pending part of success macro? */
652 if ((NT_SUCCESS(NdisStatus)) || (NdisStatus == NDIS_STATUS_PENDING))
653 {
654 NDIS_DbgPrint(DEBUG_MINIPORT, ("Miniport returned status (0x%X).\n", NdisStatus));
655 return NdisStatus;
656 }
657
658 if (NdisStatus == NDIS_STATUS_INVALID_LENGTH)
659 {
660 ExFreePool(Adapter->QueryBuffer);
661
662 Adapter->QueryBufferLength += BytesNeeded;
663 Adapter->QueryBuffer = ExAllocatePool(NonPagedPool, Adapter->QueryBufferLength);
664
665 if (!Adapter->QueryBuffer)
666 {
667 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
668 return NDIS_STATUS_RESOURCES;
669 }
670
671 NdisStatus = (*Adapter->Miniport->Chars.QueryInformationHandler)(
672 Adapter->NdisMiniportBlock.MiniportAdapterContext,
673 Oid,
674 Adapter->QueryBuffer,
675 Size,
676 BytesWritten,
677 &BytesNeeded);
678 }
679
680 return NdisStatus;
681 }
682
683 \f
684 NDIS_STATUS
685 FASTCALL
686 MiniQueueWorkItem(
687 PLOGICAL_ADAPTER Adapter,
688 NDIS_WORK_ITEM_TYPE WorkItemType,
689 PVOID WorkItemContext,
690 NDIS_HANDLE Initiator)
691 /*
692 * FUNCTION: Queues a work item for execution at a later time
693 * ARGUMENTS:
694 * Adapter = Pointer to the logical adapter object to queue work item on
695 * WorkItemType = Type of work item to queue
696 * WorkItemContext = Pointer to context information for work item
697 * Initiator = Pointer to ADAPTER_BINDING structure of initiating protocol
698 * NOTES:
699 * Adapter lock must be held when called
700 * RETURNS:
701 * Status of operation
702 */
703 {
704 PNDIS_MINIPORT_WORK_ITEM Item;
705
706 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
707
708 ASSERT(Adapter);
709
710 if (Adapter->WorkQueueLevel < NDIS_MINIPORT_WORK_QUEUE_SIZE - 1)
711 {
712 Item = &Adapter->WorkQueue[Adapter->WorkQueueLevel];
713 Adapter->WorkQueueLevel++;
714 }
715 else
716 {
717 Item = ExAllocatePool(NonPagedPool, sizeof(NDIS_MINIPORT_WORK_ITEM));
718 if (Item)
719 {
720 /* Set flag so we know that the buffer should be freed when work item is dequeued */
721 Item->Allocated = TRUE;
722 }
723 else
724 {
725 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
726 return NDIS_STATUS_RESOURCES;
727 }
728 }
729
730 Item->WorkItemType = WorkItemType;
731 Item->WorkItemContext = WorkItemContext;
732 Item->Initiator = Initiator;
733
734 /* safe due to adapter lock held */
735 Item->Link.Next = NULL;
736 if (!Adapter->WorkQueueHead)
737 {
738 Adapter->WorkQueueHead = Item;
739 Adapter->WorkQueueTail = Item;
740 }
741 else
742 {
743 Adapter->WorkQueueTail->Link.Next = (PSINGLE_LIST_ENTRY)Item;
744 Adapter->WorkQueueTail = Item;
745 }
746
747 KeInsertQueueDpc(&Adapter->MiniportDpc, NULL, NULL);
748
749 return NDIS_STATUS_SUCCESS;
750 }
751
752 \f
753 NDIS_STATUS
754 FASTCALL
755 MiniDequeueWorkItem(
756 PLOGICAL_ADAPTER Adapter,
757 NDIS_WORK_ITEM_TYPE *WorkItemType,
758 PVOID *WorkItemContext,
759 NDIS_HANDLE *Initiator)
760 /*
761 * FUNCTION: Dequeues a work item from the work queue of a logical adapter
762 * ARGUMENTS:
763 * Adapter = Pointer to the logical adapter object to dequeue work item from
764 * WorkItemType = Address of buffer for work item type
765 * WorkItemContext = Address of buffer for pointer to context information
766 * Initiator = Address of buffer for initiator of the work (ADAPTER_BINDING)
767 * NOTES:
768 * Adapter lock must be held when called
769 * RETURNS:
770 * Status of operation
771 */
772 {
773 PNDIS_MINIPORT_WORK_ITEM Item;
774
775 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
776
777 Item = Adapter->WorkQueueHead;
778
779 if (Item)
780 {
781 /* safe due to adapter lock held */
782 Adapter->WorkQueueHead = (PNDIS_MINIPORT_WORK_ITEM)Item->Link.Next;
783
784 if (Item == Adapter->WorkQueueTail)
785 Adapter->WorkQueueTail = NULL;
786
787 *WorkItemType = Item->WorkItemType;
788 *WorkItemContext = Item->WorkItemContext;
789 *Initiator = Item->Initiator;
790
791 if (Item->Allocated)
792 {
793 ExFreePool(Item);
794 }
795 else
796 {
797 Adapter->WorkQueueLevel--;
798 #ifdef DBG
799 if (Adapter->WorkQueueLevel < 0)
800 {
801 NDIS_DbgPrint(MIN_TRACE, ("Adapter->WorkQueueLevel is < 0 (should be >= 0).\n"));
802 }
803 #endif
804 }
805
806 return NDIS_STATUS_SUCCESS;
807 }
808
809 return NDIS_STATUS_FAILURE;
810 }
811
812 \f
813 NDIS_STATUS
814 MiniDoRequest(
815 PLOGICAL_ADAPTER Adapter,
816 PNDIS_REQUEST NdisRequest)
817 /*
818 * FUNCTION: Sends a request to a miniport
819 * ARGUMENTS:
820 * Adapter = Pointer to logical adapter object
821 * NdisRequest = Pointer to NDIS request structure describing request
822 * RETURNS:
823 * Status of operation
824 */
825 {
826 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
827
828 Adapter->NdisMiniportBlock.MediaRequest = NdisRequest;
829
830 switch (NdisRequest->RequestType)
831 {
832 case NdisRequestQueryInformation:
833 return (*Adapter->Miniport->Chars.QueryInformationHandler)(
834 Adapter->NdisMiniportBlock.MiniportAdapterContext,
835 NdisRequest->DATA.QUERY_INFORMATION.Oid,
836 NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
837 NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength,
838 (PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesWritten,
839 (PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded);
840 break;
841
842 case NdisRequestSetInformation:
843 return (*Adapter->Miniport->Chars.SetInformationHandler)(
844 Adapter->NdisMiniportBlock.MiniportAdapterContext,
845 NdisRequest->DATA.SET_INFORMATION.Oid,
846 NdisRequest->DATA.SET_INFORMATION.InformationBuffer,
847 NdisRequest->DATA.SET_INFORMATION.InformationBufferLength,
848 (PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesRead,
849 (PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesNeeded);
850 break;
851
852 default:
853 return NDIS_STATUS_FAILURE;
854 }
855 }
856
857 \f
858 VOID STDCALL MiniportDpc(
859 IN PKDPC Dpc,
860 IN PVOID DeferredContext,
861 IN PVOID SystemArgument1,
862 IN PVOID SystemArgument2)
863 /*
864 * FUNCTION: Deferred routine to handle serialization
865 * ARGUMENTS:
866 * Dpc = Pointer to DPC object
867 * DeferredContext = Pointer to context information (LOGICAL_ADAPTER)
868 * SystemArgument1 = Unused
869 * SystemArgument2 = Unused
870 */
871 {
872 NDIS_STATUS NdisStatus;
873 PVOID WorkItemContext;
874 NDIS_WORK_ITEM_TYPE WorkItemType;
875 PADAPTER_BINDING AdapterBinding;
876 PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(DeferredContext);
877
878 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
879
880 /* XXX is adapter lock held here? should be... */
881 NdisStatus = MiniDequeueWorkItem(Adapter, &WorkItemType, &WorkItemContext, (PNDIS_HANDLE)&AdapterBinding);
882
883 if (NdisStatus == NDIS_STATUS_SUCCESS)
884 {
885 Adapter->MiniportAdapterBinding = AdapterBinding;
886
887 switch (WorkItemType)
888 {
889 case NdisWorkItemSend:
890 /*
891 * called by ProSend when protocols want to send packets to the miniport
892 */
893 #ifdef DBG
894 MiniDisplayPacket((PNDIS_PACKET)WorkItemContext);
895 #endif
896 if(Adapter->Miniport->Chars.SendPacketsHandler)
897 {
898 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
899
900 /*
901 * XXX assumes single-packet - prolly OK since we'll call something
902 * different on multi-packet sends
903 */
904 (*Adapter->Miniport->Chars.SendPacketsHandler)(
905 Adapter->NdisMiniportBlock.MiniportAdapterContext, (PPNDIS_PACKET)&WorkItemContext, 1);
906
907 NDIS_DbgPrint(MAX_TRACE, ("back from miniport's SendPackets handler\n"));
908 }
909 else
910 {
911 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
912
913 NdisStatus = (*Adapter->Miniport->Chars.u1.SendHandler)(
914 Adapter->NdisMiniportBlock.MiniportAdapterContext, (PNDIS_PACKET)WorkItemContext, 0);
915
916 NDIS_DbgPrint(MAX_TRACE, ("back from miniport's Send handler\n"));
917
918 if (NdisStatus != NDIS_STATUS_PENDING)
919 MiniSendComplete((NDIS_HANDLE)Adapter, (PNDIS_PACKET)WorkItemContext, NdisStatus);
920 }
921
922 break;
923
924 case NdisWorkItemSendLoopback:
925 /*
926 * called by ProSend when protocols want to send loopback packets
927 */
928 /* XXX atm ProIndicatePacket sends a packet up via the loopback adapter only */
929 NdisStatus = ProIndicatePacket(Adapter, (PNDIS_PACKET)WorkItemContext);
930 MiniSendComplete((NDIS_HANDLE)Adapter, (PNDIS_PACKET)WorkItemContext, NdisStatus);
931 break;
932
933 case NdisWorkItemReturnPackets:
934 break;
935
936 case NdisWorkItemResetRequested:
937 break;
938
939 case NdisWorkItemResetInProgress:
940 break;
941
942 case NdisWorkItemHalt:
943 break;
944
945 case NdisWorkItemMiniportCallback:
946 break;
947
948 case NdisWorkItemRequest:
949 NdisStatus = MiniDoRequest(Adapter, (PNDIS_REQUEST)WorkItemContext);
950
951 if (NdisStatus == NDIS_STATUS_PENDING)
952 break;
953
954 switch (((PNDIS_REQUEST)WorkItemContext)->RequestType)
955 {
956 case NdisRequestQueryInformation:
957 NdisMQueryInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
958 break;
959
960 case NdisRequestSetInformation:
961 NdisMSetInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
962 break;
963
964 default:
965 NDIS_DbgPrint(MIN_TRACE, ("Unknown NDIS request type.\n"));
966 break;
967 }
968 break;
969
970 default:
971 NDIS_DbgPrint(MIN_TRACE, ("Unknown NDIS work item type (%d).\n", WorkItemType));
972 break;
973 }
974 }
975 }
976
977 \f
978 /*
979 * @unimplemented
980 */
981 VOID
982 EXPORT
983 NdisMCloseLog(
984 IN NDIS_HANDLE LogHandle)
985 {
986 UNIMPLEMENTED
987 }
988
989 \f
990 /*
991 * @unimplemented
992 */
993 NDIS_STATUS
994 EXPORT
995 NdisMCreateLog(
996 IN NDIS_HANDLE MiniportAdapterHandle,
997 IN UINT Size,
998 OUT PNDIS_HANDLE LogHandle)
999 {
1000 UNIMPLEMENTED
1001
1002 return NDIS_STATUS_FAILURE;
1003 }
1004
1005 \f
1006 /*
1007 * @implemented
1008 */
1009 VOID
1010 EXPORT
1011 NdisMDeregisterAdapterShutdownHandler(
1012 IN NDIS_HANDLE MiniportHandle)
1013 /*
1014 * FUNCTION: de-registers a shutdown handler
1015 * ARGUMENTS: MiniportHandle: Handle passed into MiniportInitialize
1016 */
1017 {
1018 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
1019 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportHandle;
1020
1021 if(Adapter->BugcheckContext->ShutdownHandler)
1022 KeDeregisterBugCheckCallback(Adapter->BugcheckContext->CallbackRecord);
1023 }
1024
1025 \f
1026 /*
1027 * @unimplemented
1028 */
1029 VOID
1030 EXPORT
1031 NdisMFlushLog(
1032 IN NDIS_HANDLE LogHandle)
1033 {
1034 UNIMPLEMENTED
1035 }
1036
1037
1038 /*
1039 * @unimplemented
1040 */
1041 VOID
1042 EXPORT
1043 NdisMIndicateStatus(
1044 IN NDIS_HANDLE MiniportAdapterHandle,
1045 IN NDIS_STATUS GeneralStatus,
1046 IN PVOID StatusBuffer,
1047 IN UINT StatusBufferSize)
1048 {
1049 UNIMPLEMENTED
1050 }
1051
1052
1053 /*
1054 * @unimplemented
1055 */
1056 VOID
1057 EXPORT
1058 NdisMIndicateStatusComplete(
1059 IN NDIS_HANDLE MiniportAdapterHandle)
1060 {
1061 UNIMPLEMENTED
1062 }
1063
1064 \f
1065 /*
1066 * @implemented
1067 */
1068 VOID
1069 EXPORT
1070 NdisInitializeWrapper(
1071 OUT PNDIS_HANDLE NdisWrapperHandle,
1072 IN PVOID SystemSpecific1,
1073 IN PVOID SystemSpecific2,
1074 IN PVOID SystemSpecific3)
1075 /*
1076 * FUNCTION: Notifies the NDIS library that a new miniport is initializing
1077 * ARGUMENTS:
1078 * NdisWrapperHandle = Address of buffer to place NDIS wrapper handle
1079 * SystemSpecific1 = Pointer to the driver's driver object
1080 * SystemSpecific2 = Pointer to the driver's registry path
1081 * SystemSpecific3 = Always NULL
1082 * NOTES:
1083 * - SystemSpecific2 goes invalid so we copy it
1084 */
1085 {
1086 PMINIPORT_DRIVER Miniport;
1087 PUNICODE_STRING RegistryPath;
1088 WCHAR *RegistryBuffer;
1089
1090 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1091
1092 ASSERT(NdisWrapperHandle);
1093
1094 *NdisWrapperHandle = NULL;
1095
1096 #if BREAK_ON_MINIPORT_INIT
1097 __asm__ ("int $3\n");
1098 #endif
1099
1100 Miniport = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_DRIVER));
1101
1102 if (!Miniport)
1103 {
1104 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1105 return;
1106 }
1107
1108 RtlZeroMemory(Miniport, sizeof(MINIPORT_DRIVER));
1109
1110 KeInitializeSpinLock(&Miniport->Lock);
1111
1112 Miniport->RefCount = 1;
1113
1114 Miniport->DriverObject = (PDRIVER_OBJECT)SystemSpecific1;
1115
1116 /* set the miniport's driver registry path */
1117 RegistryPath = ExAllocatePool(PagedPool, sizeof(UNICODE_STRING));
1118 if(!RegistryPath)
1119 {
1120 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1121 return;
1122 }
1123
1124 RegistryPath->Length = ((PUNICODE_STRING)SystemSpecific2)->Length;
1125 RegistryPath->MaximumLength = RegistryPath->Length + sizeof(WCHAR); /* room for 0-term */
1126
1127 RegistryBuffer = ExAllocatePool(PagedPool, RegistryPath->MaximumLength);
1128 if(!RegistryBuffer)
1129 {
1130 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1131 return;
1132 }
1133
1134 RtlCopyMemory(RegistryBuffer, ((PUNICODE_STRING)SystemSpecific2)->Buffer, RegistryPath->Length);
1135 RegistryBuffer[RegistryPath->Length/sizeof(WCHAR)] = 0;
1136
1137 RegistryPath->Buffer = RegistryBuffer;
1138 Miniport->RegistryPath = RegistryPath;
1139
1140 InitializeListHead(&Miniport->AdapterListHead);
1141
1142 /* Put miniport in global miniport list */
1143 ExInterlockedInsertTailList(&MiniportListHead, &Miniport->ListEntry, &MiniportListLock);
1144
1145 *NdisWrapperHandle = Miniport;
1146 }
1147
1148 \f
1149 /*
1150 * @implemented
1151 */
1152 VOID
1153 EXPORT
1154 NdisMQueryInformationComplete(
1155 IN NDIS_HANDLE MiniportAdapterHandle,
1156 IN NDIS_STATUS Status)
1157 {
1158 PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
1159 PADAPTER_BINDING AdapterBinding = (PADAPTER_BINDING)Adapter->MiniportAdapterBinding;
1160
1161 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1162
1163 (*AdapterBinding->ProtocolBinding->Chars.RequestCompleteHandler)(
1164 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
1165 Adapter->NdisMiniportBlock.MediaRequest,
1166 Status);
1167 }
1168
1169 \f
1170 VOID STDCALL NdisIBugcheckCallback(
1171 IN PVOID Buffer,
1172 IN ULONG Length)
1173 /*
1174 * FUNCTION: Internal callback for handling bugchecks - calls adapter's shutdown handler
1175 * ARGUMENTS:
1176 * Buffer: Pointer to a bugcheck callback context
1177 * Length: Unused
1178 */
1179 {
1180 PMINIPORT_BUGCHECK_CONTEXT Context = (PMINIPORT_BUGCHECK_CONTEXT)Buffer;
1181 ADAPTER_SHUTDOWN_HANDLER sh = (ADAPTER_SHUTDOWN_HANDLER)Context->ShutdownHandler;
1182
1183 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
1184
1185 if(sh)
1186 sh(Context->DriverContext);
1187 }
1188
1189 \f
1190 /*
1191 * @implemented
1192 */
1193 VOID
1194 EXPORT
1195 NdisMRegisterAdapterShutdownHandler(
1196 IN NDIS_HANDLE MiniportHandle,
1197 IN PVOID ShutdownContext,
1198 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler)
1199 /*
1200 * FUNCTION: Register a shutdown handler for an adapter
1201 * ARGUMENTS:
1202 * MiniportHandle: Handle originally passed into MiniportInitialize
1203 * ShutdownContext: Pre-initialized bugcheck context
1204 * ShutdownHandler: Function to call to handle the bugcheck
1205 * NOTES:
1206 * - I'm not sure about ShutdownContext
1207 * - FIXME - memory leak below
1208 */
1209 {
1210 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportHandle;
1211 PMINIPORT_BUGCHECK_CONTEXT BugcheckContext = Adapter->BugcheckContext;
1212
1213 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
1214
1215 if(BugcheckContext)
1216 return;
1217
1218 BugcheckContext = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_BUGCHECK_CONTEXT));
1219 if(!BugcheckContext)
1220 {
1221 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1222 return;
1223 }
1224
1225 BugcheckContext->ShutdownHandler = ShutdownHandler;
1226 BugcheckContext->DriverContext = ShutdownContext;
1227
1228 /* not sure if this needs to be initialized or not... oh well, it's a leak. */
1229 BugcheckContext->CallbackRecord = ExAllocatePool(NonPagedPool, sizeof(KBUGCHECK_CALLBACK_RECORD));
1230
1231 KeRegisterBugCheckCallback(BugcheckContext->CallbackRecord, NdisIBugcheckCallback,
1232 BugcheckContext, sizeof(BugcheckContext), "Ndis Miniport");
1233 }
1234
1235 \f
1236 NDIS_STATUS
1237 DoQueries(
1238 PLOGICAL_ADAPTER Adapter,
1239 NDIS_OID AddressOID)
1240 /*
1241 * FUNCTION: Queries miniport for information
1242 * ARGUMENTS:
1243 * Adapter = Pointer to logical adapter
1244 * AddressOID = OID to use to query for current address
1245 * RETURNS:
1246 * Status of operation
1247 */
1248 {
1249 ULONG BytesWritten;
1250 NDIS_STATUS NdisStatus;
1251
1252 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1253
1254 /* Get MAC options for adapter */
1255 NdisStatus = MiniQueryInformation(Adapter, OID_GEN_MAC_OPTIONS, 0, &BytesWritten);
1256
1257 if (NdisStatus != NDIS_STATUS_SUCCESS)
1258 {
1259 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAC_OPTIONS failed. NdisStatus (0x%X).\n", NdisStatus));
1260 return NdisStatus;
1261 }
1262
1263 RtlCopyMemory(&Adapter->NdisMiniportBlock.MacOptions, Adapter->QueryBuffer, sizeof(UINT));
1264
1265 NDIS_DbgPrint(DEBUG_MINIPORT, ("MacOptions (0x%X).\n", Adapter->NdisMiniportBlock.MacOptions));
1266
1267 /* Get current hardware address of adapter */
1268 NdisStatus = MiniQueryInformation(Adapter, AddressOID, 0, &BytesWritten);
1269
1270 if (NdisStatus != NDIS_STATUS_SUCCESS)
1271 {
1272 NDIS_DbgPrint(MIN_TRACE, ("Address OID (0x%X) failed. NdisStatus (0x%X).\n", AddressOID, NdisStatus));
1273 return NdisStatus;
1274 }
1275
1276 RtlCopyMemory(&Adapter->Address, Adapter->QueryBuffer, Adapter->AddressLength);
1277 #ifdef DBG
1278 {
1279 /* 802.3 only */
1280
1281 PUCHAR A = (PUCHAR)&Adapter->Address.Type.Medium802_3;
1282
1283 NDIS_DbgPrint(MAX_TRACE, ("Adapter address is (%02X %02X %02X %02X %02X %02X).\n", A[0], A[1], A[2], A[3], A[4], A[5]));
1284 }
1285 #endif /* DBG */
1286
1287 /* Get maximum lookahead buffer size of adapter */
1288 NdisStatus = MiniQueryInformation(Adapter, OID_GEN_MAXIMUM_LOOKAHEAD, 0, &BytesWritten);
1289
1290 if (NdisStatus != NDIS_STATUS_SUCCESS)
1291 {
1292 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAXIMUM_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus));
1293 return NdisStatus;
1294 }
1295
1296 Adapter->MaxLookaheadLength = *((PULONG)Adapter->QueryBuffer);
1297
1298 NDIS_DbgPrint(DEBUG_MINIPORT, ("MaxLookaheadLength (0x%X).\n", Adapter->MaxLookaheadLength));
1299
1300 /* Get current lookahead buffer size of adapter */
1301 NdisStatus = MiniQueryInformation(Adapter, OID_GEN_CURRENT_LOOKAHEAD, 0, &BytesWritten);
1302
1303 if (NdisStatus != NDIS_STATUS_SUCCESS)
1304 {
1305 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_CURRENT_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus));
1306 return NdisStatus;
1307 }
1308
1309 Adapter->CurLookaheadLength = *((PULONG)Adapter->QueryBuffer);
1310
1311 NDIS_DbgPrint(DEBUG_MINIPORT, ("CurLookaheadLength (0x%X).\n", Adapter->CurLookaheadLength));
1312
1313 if (Adapter->MaxLookaheadLength != 0)
1314 {
1315 Adapter->LookaheadLength = Adapter->MaxLookaheadLength + Adapter->MediumHeaderSize;
1316 Adapter->LookaheadBuffer = ExAllocatePool(NonPagedPool, Adapter->LookaheadLength);
1317
1318 if (!Adapter->LookaheadBuffer)
1319 return NDIS_STATUS_RESOURCES;
1320 }
1321
1322 return STATUS_SUCCESS;
1323 }
1324
1325 \f
1326 VOID
1327 NdisIStartAdapter(
1328 UNICODE_STRING *DeviceName,
1329 PDEVICE_OBJECT PhysicalDeviceObject,
1330 PMINIPORT_DRIVER Miniport
1331 )
1332 /*
1333 * FUNCTION: Start an adapter
1334 * ARGUMENTS:
1335 * DeviceName: Name of device to start
1336 * PhysicalDeviceObject: PDO for our adapter
1337 * NOTES:
1338 * TODO:
1339 * - verify that all resources are properly freed on success & failure
1340 * - break up this 250-line function
1341 */
1342 {
1343 HANDLE RegKeyHandle;
1344 NDIS_STATUS NdisStatus;
1345 NDIS_STATUS OpenErrorStatus;
1346 NTSTATUS Status;
1347 UINT SelectedMediumIndex = 0;
1348 PLOGICAL_ADAPTER Adapter = 0;
1349 NDIS_OID AddressOID;
1350 BOOLEAN MemError = FALSE;
1351 KIRQL OldIrql;
1352 ULONG Size;
1353
1354 Adapter = ExAllocatePool(NonPagedPool, sizeof(LOGICAL_ADAPTER));
1355 if (!Adapter)
1356 {
1357 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1358 return;
1359 }
1360
1361 /* This is very important */
1362 RtlZeroMemory(Adapter, sizeof(LOGICAL_ADAPTER));
1363
1364 Adapter->DeviceName.Buffer = ExAllocatePool(NonPagedPool, DeviceName->Length);
1365 if(!Adapter->DeviceName.Buffer)
1366 {
1367 NDIS_DbgPrint(MIN_TRACE,("Insufficient memory\n"));
1368 ExFreePool(Adapter);
1369 return;
1370 }
1371 Adapter->DeviceName.MaximumLength = DeviceName->Length;
1372 RtlCopyUnicodeString(&Adapter->DeviceName, DeviceName);
1373
1374 NDIS_DbgPrint(MAX_TRACE, ("creating device %wZ\n", DeviceName));
1375
1376 Status = IoCreateDevice(Miniport->DriverObject, 0, &Adapter->DeviceName, FILE_DEVICE_PHYSICAL_NETCARD,
1377 0, FALSE, &Adapter->NdisMiniportBlock.DeviceObject);
1378 if (!NT_SUCCESS(Status))
1379 {
1380 NDIS_DbgPrint(MIN_TRACE, ("Could not create device object.\n"));
1381 ExFreePool(Adapter);
1382 return;
1383 }
1384
1385 Status = IoOpenDeviceRegistryKey(PhysicalDeviceObject, PLUGPLAY_REGKEY_DRIVER,
1386 KEY_ALL_ACCESS, &RegKeyHandle);
1387 if(Status != STATUS_SUCCESS)
1388 {
1389 NDIS_DbgPrint(MIN_TRACE,("failed to open adapter-specific reg key\n"));
1390 ExFreePool(Adapter);
1391 return;
1392 }
1393
1394 NDIS_DbgPrint(MAX_TRACE, ("opened device reg key\n"));
1395
1396 NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
1397 KeInitializeSpinLock(&Adapter->NdisMiniportBlock.Lock);
1398 InitializeListHead(&Adapter->ProtocolListHead);
1399 Adapter->RefCount = 1;
1400 Adapter->Miniport = Miniport;
1401
1402 /* FIXME: Check return values. */
1403 Size = sizeof(ULONG);
1404 IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyLegacyBusType,
1405 Size, &Adapter->BusType, &Size);
1406 IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyBusNumber,
1407 Size, &Adapter->BusNumber, &Size);
1408 IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyAddress,
1409 Size, &Adapter->SlotNumber, &Size);
1410
1411 /* Set handlers (some NDIS macros require these) */
1412
1413 Adapter->NdisMiniportBlock.EthRxCompleteHandler = MiniEthReceiveComplete;
1414 Adapter->NdisMiniportBlock.EthRxIndicateHandler = MiniEthReceiveIndication;
1415 Adapter->NdisMiniportBlock.SendCompleteHandler = MiniSendComplete;
1416 Adapter->NdisMiniportBlock.SendResourcesHandler = MiniSendResourcesAvailable;
1417 Adapter->NdisMiniportBlock.ResetCompleteHandler = MiniResetComplete;
1418 Adapter->NdisMiniportBlock.TDCompleteHandler = MiniTransferDataComplete;
1419 Adapter->NdisMiniportBlock.PacketIndicateHandler= MiniIndicateReceivePacket;
1420
1421 KeInitializeDpc(&Adapter->MiniportDpc, MiniportDpc, (PVOID)Adapter);
1422
1423 /* Put adapter in adapter list for this miniport */
1424 ExInterlockedInsertTailList(&Miniport->AdapterListHead, &Adapter->MiniportListEntry, &Miniport->Lock);
1425
1426 /* Put adapter in global adapter list */
1427 ExInterlockedInsertTailList(&AdapterListHead, &Adapter->ListEntry, &AdapterListLock);
1428
1429 /* Call MiniportInitialize */
1430 NDIS_DbgPrint(MID_TRACE, ("calling MiniportInitialize\n"));
1431 NdisStatus = (*Miniport->Chars.InitializeHandler)( &OpenErrorStatus, &SelectedMediumIndex, &MediaArray[0],
1432 MEDIA_ARRAY_SIZE, Adapter, RegKeyHandle);
1433
1434 ZwClose(RegKeyHandle);
1435
1436 if ((NdisStatus == NDIS_STATUS_SUCCESS) && (SelectedMediumIndex < MEDIA_ARRAY_SIZE))
1437 {
1438 NDIS_DbgPrint(MID_TRACE,("successful return from MiniportInitialize\n"));
1439
1440 Adapter->NdisMiniportBlock.MediaType = MediaArray[SelectedMediumIndex];
1441
1442 switch (Adapter->NdisMiniportBlock.MediaType)
1443 {
1444 case NdisMedium802_3:
1445 Adapter->MediumHeaderSize = 14; /* XXX figure out what to do about LLC */
1446 AddressOID = OID_802_3_CURRENT_ADDRESS;
1447 Adapter->AddressLength = ETH_LENGTH_OF_ADDRESS;
1448
1449 Adapter->NdisMiniportBlock.FilterDbs.u.EthDB = ExAllocatePool(NonPagedPool, sizeof(ETH_FILTER));
1450 if (Adapter->NdisMiniportBlock.FilterDbs.u.EthDB)
1451 {
1452 RtlZeroMemory(Adapter->NdisMiniportBlock.FilterDbs.u.EthDB, sizeof(ETH_FILTER));
1453 Adapter->NdisMiniportBlock.FilterDbs.u.EthDB->Miniport = (PNDIS_MINIPORT_BLOCK)Adapter;
1454 }
1455 else
1456 MemError = TRUE;
1457
1458 break;
1459
1460 default:
1461 /* FIXME: Support other types of media */
1462 NDIS_DbgPrint(MIN_TRACE, ("error: unsupported media\n"));
1463 ExFreePool(Adapter);
1464 ASSERT(FALSE);
1465 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
1466 return;
1467 }
1468
1469 NdisStatus = DoQueries(Adapter, AddressOID);
1470 }
1471
1472 if ((MemError) || (NdisStatus != NDIS_STATUS_SUCCESS) || (SelectedMediumIndex >= MEDIA_ARRAY_SIZE))
1473 {
1474 NDIS_DbgPrint(MAX_TRACE, ("return from MiniportInitialize: NdisStatus 0x%x, SelectedMediumIndex 0x%x\n",
1475 NdisStatus, SelectedMediumIndex));
1476
1477 /* Remove adapter from adapter list for this miniport */
1478 KeAcquireSpinLock(&Miniport->Lock, &OldIrql);
1479 RemoveEntryList(&Adapter->MiniportListEntry);
1480 KeReleaseSpinLock(&Miniport->Lock, OldIrql);
1481
1482 /* Remove adapter from global adapter list */
1483 KeAcquireSpinLock(&AdapterListLock, &OldIrql);
1484 RemoveEntryList(&Adapter->ListEntry);
1485 KeReleaseSpinLock(&AdapterListLock, OldIrql);
1486
1487 if (Adapter->LookaheadBuffer)
1488 ExFreePool(Adapter->LookaheadBuffer);
1489
1490 IoDeleteDevice(Adapter->NdisMiniportBlock.DeviceObject);
1491 ExFreePool(Adapter);
1492 NDIS_DbgPrint(MIN_TRACE, ("MiniportInitialize() failed for an adapter.\n"));
1493 }
1494 else
1495 {
1496 IoAttachDeviceToDeviceStack(Adapter->NdisMiniportBlock.DeviceObject,
1497 PhysicalDeviceObject);
1498 }
1499 }
1500
1501 \f
1502 NTSTATUS
1503 STDCALL
1504 NdisIAddDevice(
1505 IN PDRIVER_OBJECT DriverObject,
1506 IN PDEVICE_OBJECT PhysicalDeviceObject
1507 )
1508 /*
1509 * FUNCTION: Start an adapter found using PnP
1510 * ARGUMENTS:
1511 * DriverObject = Pointer to the miniport driver object
1512 * PhysicalDeviceObject = Pointer to the PDO for our adapter
1513 */
1514 {
1515 static const WCHAR ClassKeyName[] = {'C','l','a','s','s','\\'};
1516 static const WCHAR LinkageKeyName[] = {'\\','L','i','n','k','a','g','e',0};
1517 PMINIPORT_DRIVER Miniport;
1518 PMINIPORT_DRIVER *MiniportPtr;
1519 WCHAR *LinkageKeyBuffer;
1520 ULONG DriverKeyLength;
1521 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
1522 UNICODE_STRING ExportName;
1523 NTSTATUS Status;
1524
1525 /*
1526 * Gain the access to the miniport data structure first.
1527 */
1528
1529 MiniportPtr = IoGetDriverObjectExtension(DriverObject, (PVOID)TAG('D','I','M','N'));
1530 if (MiniportPtr == NULL)
1531 {
1532 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't get driver object extension.\n"));
1533 return STATUS_UNSUCCESSFUL;
1534 }
1535 Miniport = *MiniportPtr;
1536
1537 /*
1538 * Get name of the Linkage registry key for our adapter. It's located under
1539 * the driver key for our driver and so we have basicly two ways to do it.
1540 * Either we can use IoOpenDriverRegistryKey or compose it using information
1541 * gathered by IoGetDeviceProperty. I choosed the second because
1542 * IoOpenDriverRegistryKey wasn't implemented at the time of writing.
1543 */
1544
1545 Status = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyDriverKeyName,
1546 0, NULL, &DriverKeyLength);
1547 if (Status != STATUS_BUFFER_TOO_SMALL)
1548 {
1549 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't get miniport driver key length.\n"));
1550 return Status;
1551 }
1552
1553 LinkageKeyBuffer = ExAllocatePool(PagedPool, DriverKeyLength +
1554 sizeof(ClassKeyName) + sizeof(LinkageKeyName));
1555 if (LinkageKeyBuffer == NULL)
1556 {
1557 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't allocate memory for driver key name.\n"));
1558 return STATUS_INSUFFICIENT_RESOURCES;
1559 }
1560
1561 Status = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyDriverKeyName,
1562 DriverKeyLength, LinkageKeyBuffer +
1563 (sizeof(ClassKeyName) / sizeof(WCHAR)),
1564 &DriverKeyLength);
1565 if (!NT_SUCCESS(Status))
1566 {
1567 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't get miniport driver key.\n"));
1568 ExFreePool(LinkageKeyBuffer);
1569 return Status;
1570 }
1571
1572 /* Compose the linkage key name. */
1573 RtlCopyMemory(LinkageKeyBuffer, ClassKeyName, sizeof(ClassKeyName));
1574 RtlCopyMemory(LinkageKeyBuffer + ((sizeof(ClassKeyName) + DriverKeyLength) /
1575 sizeof(WCHAR)) - 1, LinkageKeyName, sizeof(LinkageKeyName));
1576
1577 NDIS_DbgPrint(DEBUG_MINIPORT, ("LinkageKey: %S.\n", LinkageKeyBuffer));
1578
1579 /*
1580 * Now open the linkage key and read the "Export" and "RootDevice" values
1581 * which contains device name and root service respectively.
1582 */
1583
1584 RtlZeroMemory(QueryTable, sizeof(QueryTable));
1585 RtlInitUnicodeString(&ExportName, NULL);
1586 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
1587 QueryTable[0].Name = L"Export";
1588 QueryTable[0].EntryContext = &ExportName;
1589
1590 Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, LinkageKeyBuffer,
1591 QueryTable, NULL, NULL);
1592 if (!NT_SUCCESS(Status))
1593 {
1594 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't get miniport device name. (%x)\n", Status));
1595 ExFreePool(LinkageKeyBuffer);
1596 return Status;
1597 }
1598 ExFreePool(LinkageKeyBuffer);
1599
1600 NdisIStartAdapter(&ExportName, PhysicalDeviceObject, Miniport);
1601 RtlFreeUnicodeString(&ExportName);
1602
1603 return STATUS_SUCCESS;
1604 }
1605
1606 \f
1607 /*
1608 * @implemented
1609 */
1610 NDIS_STATUS
1611 EXPORT
1612 NdisMRegisterMiniport(
1613 IN NDIS_HANDLE NdisWrapperHandle,
1614 IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics,
1615 IN UINT CharacteristicsLength)
1616 /*
1617 * FUNCTION: Registers a miniport's MiniportXxx entry points with the NDIS library
1618 * ARGUMENTS:
1619 * NdisWrapperHandle = Pointer to handle returned by NdisMInitializeWrapper
1620 * MiniportCharacteristics = Pointer to a buffer with miniport characteristics
1621 * CharacteristicsLength = Number of bytes in characteristics buffer
1622 * RETURNS:
1623 * Status of operation
1624 */
1625 {
1626 UINT MinSize;
1627 PMINIPORT_DRIVER Miniport = GET_MINIPORT_DRIVER(NdisWrapperHandle);
1628 PMINIPORT_DRIVER *MiniportPtr;
1629 NTSTATUS Status;
1630
1631 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1632
1633 switch (MiniportCharacteristics->MajorNdisVersion)
1634 {
1635 case 0x03:
1636 MinSize = sizeof(NDIS30_MINIPORT_CHARACTERISTICS_S);
1637 break;
1638
1639 case 0x04:
1640 MinSize = sizeof(NDIS40_MINIPORT_CHARACTERISTICS_S);
1641 break;
1642
1643 case 0x05:
1644 MinSize = sizeof(NDIS50_MINIPORT_CHARACTERISTICS_S);
1645 break;
1646
1647 default:
1648 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics version.\n"));
1649 return NDIS_STATUS_BAD_VERSION;
1650 }
1651
1652 if (CharacteristicsLength < MinSize)
1653 {
1654 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
1655 return NDIS_STATUS_BAD_CHARACTERISTICS;
1656 }
1657
1658 /* Check if mandatory MiniportXxx functions are specified */
1659 if ((!MiniportCharacteristics->HaltHandler) ||
1660 (!MiniportCharacteristics->InitializeHandler)||
1661 (!MiniportCharacteristics->QueryInformationHandler) ||
1662 (!MiniportCharacteristics->ResetHandler) ||
1663 (!MiniportCharacteristics->SetInformationHandler))
1664 {
1665 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
1666 return NDIS_STATUS_BAD_CHARACTERISTICS;
1667 }
1668
1669 if (MiniportCharacteristics->MajorNdisVersion == 0x03)
1670 {
1671 if (!MiniportCharacteristics->u1.SendHandler)
1672 {
1673 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
1674 return NDIS_STATUS_BAD_CHARACTERISTICS;
1675 }
1676 }
1677 else if (MiniportCharacteristics->MajorNdisVersion >= 0x04)
1678 {
1679 /* NDIS 4.0+ */
1680 if ((!MiniportCharacteristics->u1.SendHandler) &&
1681 (!MiniportCharacteristics->SendPacketsHandler))
1682 {
1683 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
1684 return NDIS_STATUS_BAD_CHARACTERISTICS;
1685 }
1686 }
1687
1688 /* TODO: verify NDIS5 and NDIS5.1 */
1689
1690 RtlCopyMemory(&Miniport->Chars, MiniportCharacteristics, MinSize);
1691
1692 /*
1693 * NOTE: This is VERY unoptimal! Should we store the MINIPORT_DRIVER
1694 * struture in the driver extension or what?
1695 */
1696
1697 Status = IoAllocateDriverObjectExtension(Miniport->DriverObject, (PVOID)TAG('D','I','M','N'),
1698 sizeof(PMINIPORT_DRIVER), (PVOID*)&MiniportPtr);
1699 if (!NT_SUCCESS(Status))
1700 {
1701 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't allocate driver object extension.\n"));
1702 return NDIS_STATUS_RESOURCES;
1703 }
1704
1705 *MiniportPtr = Miniport;
1706 Miniport->DriverObject->DriverExtension->AddDevice = NdisIAddDevice;
1707
1708 return NDIS_STATUS_SUCCESS;
1709 }
1710
1711 \f
1712 /*
1713 * @implemented
1714 */
1715 VOID
1716 EXPORT
1717 NdisMResetComplete(
1718 IN NDIS_HANDLE MiniportAdapterHandle,
1719 IN NDIS_STATUS Status,
1720 IN BOOLEAN AddressingReset)
1721 {
1722 MiniResetComplete(MiniportAdapterHandle, Status, AddressingReset);
1723 }
1724
1725 \f
1726 /*
1727 * @implemented
1728 */
1729 VOID
1730 EXPORT
1731 NdisMSendComplete(
1732 IN NDIS_HANDLE MiniportAdapterHandle,
1733 IN PNDIS_PACKET Packet,
1734 IN NDIS_STATUS Status)
1735 /*
1736 * FUNCTION: Forwards a message to the initiating protocol saying
1737 * that a packet was handled
1738 * ARGUMENTS:
1739 * NdisAdapterHandle = Handle input to MiniportInitialize
1740 * Packet = Pointer to NDIS packet that was sent
1741 * Status = Status of send operation
1742 */
1743 {
1744 MiniSendComplete(MiniportAdapterHandle, Packet, Status);
1745 }
1746
1747 \f
1748 /*
1749 * @implemented
1750 */
1751 VOID
1752 EXPORT
1753 NdisMSendResourcesAvailable(
1754 IN NDIS_HANDLE MiniportAdapterHandle)
1755 {
1756 MiniSendResourcesAvailable(MiniportAdapterHandle);
1757 }
1758
1759 \f
1760 /*
1761 * @implemented
1762 */
1763 VOID
1764 EXPORT
1765 NdisMTransferDataComplete(
1766 IN NDIS_HANDLE MiniportAdapterHandle,
1767 IN PNDIS_PACKET Packet,
1768 IN NDIS_STATUS Status,
1769 IN UINT BytesTransferred)
1770 {
1771 MiniTransferDataComplete(MiniportAdapterHandle, Packet, Status, BytesTransferred);
1772 }
1773
1774 \f
1775 /*
1776 * @implemented
1777 */
1778 VOID
1779 EXPORT
1780 NdisMSetInformationComplete(
1781 IN NDIS_HANDLE MiniportAdapterHandle,
1782 IN NDIS_STATUS Status)
1783 {
1784 PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
1785 PADAPTER_BINDING AdapterBinding = (PADAPTER_BINDING)Adapter->MiniportAdapterBinding;
1786
1787 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1788
1789 (*AdapterBinding->ProtocolBinding->Chars.RequestCompleteHandler)(
1790 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
1791 Adapter->NdisMiniportBlock.MediaRequest,
1792 Status);
1793 }
1794
1795 \f
1796 /*
1797 * @implemented
1798 */
1799 VOID
1800 EXPORT
1801 NdisMSetAttributes(
1802 IN NDIS_HANDLE MiniportAdapterHandle,
1803 IN NDIS_HANDLE MiniportAdapterContext,
1804 IN BOOLEAN BusMaster,
1805 IN NDIS_INTERFACE_TYPE AdapterType)
1806 /*
1807 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
1808 * ARGUMENTS:
1809 * MiniportAdapterHandle = Handle input to MiniportInitialize
1810 * MiniportAdapterContext = Pointer to context information
1811 * BusMaster = Specifies TRUE if the caller's NIC is a busmaster DMA device
1812 * AdapterType = Specifies the I/O bus interface of the caller's NIC
1813 */
1814 {
1815 PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
1816
1817 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1818
1819 Adapter->NdisMiniportBlock.MiniportAdapterContext = MiniportAdapterContext;
1820
1821 if(BusMaster)
1822 Adapter->NdisMiniportBlock.Flags |= NDIS_ATTRIBUTE_BUS_MASTER;
1823
1824 Adapter->NdisMiniportBlock.AdapterType = AdapterType;
1825 Adapter->AttributesSet = TRUE;
1826 }
1827
1828 \f
1829 /*
1830 * @implemented
1831 */
1832 VOID
1833 EXPORT
1834 NdisMSetAttributesEx(
1835 IN NDIS_HANDLE MiniportAdapterHandle,
1836 IN NDIS_HANDLE MiniportAdapterContext,
1837 IN UINT CheckForHangTimeInSeconds OPTIONAL,
1838 IN ULONG AttributeFlags,
1839 IN NDIS_INTERFACE_TYPE AdapterType)
1840 /*
1841 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
1842 * ARGUMENTS:
1843 * MiniportAdapterHandle = Handle input to MiniportInitialize
1844 * MiniportAdapterContext = Pointer to context information
1845 * CheckForHangTimeInSeconds = Specifies interval in seconds at which
1846 * MiniportCheckForHang should be called
1847 * AttributeFlags = Bitmask that indicates specific attributes
1848 * AdapterType = Specifies the I/O bus interface of the caller's NIC
1849 */
1850 {
1851 /* TODO: Take CheckForHandTimeInSeconds into account! */
1852
1853 PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
1854
1855 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1856
1857 Adapter->NdisMiniportBlock.MiniportAdapterContext = MiniportAdapterContext;
1858 Adapter->NdisMiniportBlock.Flags = AttributeFlags;
1859 Adapter->NdisMiniportBlock.AdapterType = AdapterType;
1860 Adapter->AttributesSet = TRUE;
1861 if (AttributeFlags & NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER)
1862 NDIS_DbgPrint(MAX_TRACE, ("Intermediate drivers not supported yet.\n"));
1863 }
1864
1865 \f
1866 /*
1867 * @implemented
1868 */
1869 VOID
1870 EXPORT
1871 NdisMSleep(
1872 IN ULONG MicrosecondsToSleep)
1873 /*
1874 * FUNCTION: delay the thread's execution for MicrosecondsToSleep
1875 * ARGUMENTS:
1876 * MicrosecondsToSleep: duh...
1877 * NOTES:
1878 * - Because this is a blocking call, current IRQL must be < DISPATCH_LEVEL
1879 */
1880 {
1881 KTIMER Timer;
1882 LARGE_INTEGER DueTime;
1883
1884 PAGED_CODE();
1885
1886 DueTime.QuadPart = (-1) * 10 * MicrosecondsToSleep;
1887
1888 KeInitializeTimer(&Timer);
1889 KeSetTimer(&Timer, DueTime, 0);
1890 KeWaitForSingleObject(&Timer, Executive, KernelMode, FALSE, 0);
1891 }
1892
1893 \f
1894 /*
1895 * @implemented
1896 */
1897 BOOLEAN
1898 EXPORT
1899 NdisMSynchronizeWithInterrupt(
1900 IN PNDIS_MINIPORT_INTERRUPT Interrupt,
1901 IN PVOID SynchronizeFunction,
1902 IN PVOID SynchronizeContext)
1903 {
1904 return(KeSynchronizeExecution((PKINTERRUPT)Interrupt,
1905 (PKSYNCHRONIZE_ROUTINE)SynchronizeFunction,
1906 SynchronizeContext));
1907 }
1908
1909 \f
1910 /*
1911 * @unimplemented
1912 */
1913 NDIS_STATUS
1914 EXPORT
1915 NdisMWriteLogData(
1916 IN NDIS_HANDLE LogHandle,
1917 IN PVOID LogBuffer,
1918 IN UINT LogBufferSize)
1919 {
1920 UNIMPLEMENTED
1921
1922 return NDIS_STATUS_FAILURE;
1923 }
1924
1925 \f
1926 /*
1927 * @implemented
1928 */
1929 VOID
1930 EXPORT
1931 NdisTerminateWrapper(
1932 IN NDIS_HANDLE NdisWrapperHandle,
1933 IN PVOID SystemSpecific)
1934 /*
1935 * FUNCTION: Releases resources allocated by a call to NdisInitializeWrapper
1936 * ARGUMENTS:
1937 * NdisWrapperHandle = Handle returned by NdisInitializeWrapper (MINIPORT_DRIVER)
1938 * SystemSpecific = Always NULL
1939 */
1940 {
1941 PMINIPORT_DRIVER Miniport = GET_MINIPORT_DRIVER(NdisWrapperHandle);
1942
1943 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1944
1945 ExFreePool(Miniport->RegistryPath->Buffer);
1946 ExFreePool(Miniport->RegistryPath);
1947 ExFreePool(Miniport);
1948 }
1949
1950 /* EOF */
1951