- Properly implement MiniIndicateReceivePacket
[reactos.git] / drivers / network / 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
14 #include "ndissys.h"
15 #include "efilter.h"
16
17 #ifdef DBG
18 #include <buffer.h>
19 #endif /* DBG */
20
21 #undef NdisMSendComplete
22 VOID
23 EXPORT
24 NdisMSendComplete(
25 IN NDIS_HANDLE MiniportAdapterHandle,
26 IN PNDIS_PACKET Packet,
27 IN NDIS_STATUS Status);
28
29 /* Root of the scm database */
30 #define SERVICES_ROOT L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
31
32 /*
33 * Define to 1 to get a debugger breakpoint at the end of NdisInitializeWrapper
34 * for each new miniport starting up
35 */
36 #define BREAK_ON_MINIPORT_INIT 0
37
38 /*
39 * This has to be big enough to hold the results of querying the Route value
40 * from the Linkage key. Please re-code me to determine this dynamically.
41 */
42 #define ROUTE_DATA_SIZE 256
43
44 /* Number of media we know */
45 #define MEDIA_ARRAY_SIZE 15
46
47 static NDIS_MEDIUM MediaArray[MEDIA_ARRAY_SIZE] =
48 {
49 NdisMedium802_3,
50 NdisMedium802_5,
51 NdisMediumFddi,
52 NdisMediumWan,
53 NdisMediumLocalTalk,
54 NdisMediumDix,
55 NdisMediumArcnetRaw,
56 NdisMediumArcnet878_2,
57 NdisMediumAtm,
58 NdisMediumWirelessWan,
59 NdisMediumIrda,
60 NdisMediumBpc,
61 NdisMediumCoWan,
62 NdisMedium1394,
63 NdisMediumMax
64 };
65
66 /* global list and lock of Miniports NDIS has registered */
67 LIST_ENTRY MiniportListHead;
68 KSPIN_LOCK MiniportListLock;
69
70 /* global list and lock of adapters NDIS has registered */
71 LIST_ENTRY AdapterListHead;
72 KSPIN_LOCK AdapterListLock;
73
74 VOID
75 MiniDisplayPacket(
76 PNDIS_PACKET Packet)
77 {
78 #ifdef DBG
79 ULONG i, Length;
80 UCHAR Buffer[64];
81 if ((DebugTraceLevel & DEBUG_PACKET) > 0) {
82 Length = CopyPacketToBuffer(
83 Buffer,
84 Packet,
85 0,
86 64);
87
88 DbgPrint("*** PACKET START ***");
89
90 for (i = 0; i < Length; i++) {
91 if (i % 12 == 0)
92 DbgPrint("\n%04X ", i);
93 DbgPrint("%02X ", Buffer[i]);
94 }
95
96 DbgPrint("*** PACKET STOP ***\n");
97 }
98 #endif /* DBG */
99 }
100
101 VOID
102 MiniDisplayPacket2(
103 PVOID HeaderBuffer,
104 UINT HeaderBufferSize,
105 PVOID LookaheadBuffer,
106 UINT LookaheadBufferSize)
107 {
108 #ifdef DBG
109 if ((DebugTraceLevel & DEBUG_PACKET) > 0) {
110 ULONG i, Length;
111 PUCHAR p;
112
113 DbgPrint("*** RECEIVE PACKET START ***\n");
114 DbgPrint("HEADER:");
115 p = HeaderBuffer;
116 for (i = 0; i < HeaderBufferSize; i++) {
117 if (i % 16 == 0)
118 DbgPrint("\n%04X ", i);
119 DbgPrint("%02X ", *p++);
120 }
121
122 DbgPrint("\nFRAME:");
123
124 p = LookaheadBuffer;
125 Length = (LookaheadBufferSize < 64)? LookaheadBufferSize : 64;
126 for (i = 0; i < Length; i++) {
127 if (i % 16 == 0)
128 DbgPrint("\n%04X ", i);
129 DbgPrint("%02X ", *p++);
130 }
131
132 DbgPrint("\n*** RECEIVE PACKET STOP ***\n");
133 }
134 #endif /* DBG */
135 }
136
137 \f
138 VOID
139 MiniIndicateData(
140 PLOGICAL_ADAPTER Adapter,
141 NDIS_HANDLE MacReceiveContext,
142 PVOID HeaderBuffer,
143 UINT HeaderBufferSize,
144 PVOID LookaheadBuffer,
145 UINT LookaheadBufferSize,
146 UINT PacketSize)
147 /*
148 * FUNCTION: Indicate received data to bound protocols
149 * ARGUMENTS:
150 * Adapter = Pointer to logical adapter
151 * MacReceiveContext = MAC receive context handle
152 * HeaderBuffer = Pointer to header buffer
153 * HeaderBufferSize = Size of header buffer
154 * LookaheadBuffer = Pointer to lookahead buffer
155 * LookaheadBufferSize = Size of lookahead buffer
156 * PacketSize = Total size of received packet
157 */
158 {
159 KIRQL OldIrql;
160 PLIST_ENTRY CurrentEntry;
161 PADAPTER_BINDING AdapterBinding;
162
163 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called. Adapter (0x%X) HeaderBuffer (0x%X) "
164 "HeaderBufferSize (0x%X) LookaheadBuffer (0x%X) LookaheadBufferSize (0x%X).\n",
165 Adapter, HeaderBuffer, HeaderBufferSize, LookaheadBuffer, LookaheadBufferSize));
166
167 MiniDisplayPacket2(HeaderBuffer, HeaderBufferSize, LookaheadBuffer, LookaheadBufferSize);
168
169 NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
170 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
171 {
172 CurrentEntry = Adapter->ProtocolListHead.Flink;
173 NDIS_DbgPrint(DEBUG_MINIPORT, ("CurrentEntry = %x\n", CurrentEntry));
174
175 if (CurrentEntry == &Adapter->ProtocolListHead)
176 {
177 NDIS_DbgPrint(DEBUG_MINIPORT, ("WARNING: No upper protocol layer.\n"));
178 }
179
180 while (CurrentEntry != &Adapter->ProtocolListHead)
181 {
182 AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
183 NDIS_DbgPrint(DEBUG_MINIPORT, ("AdapterBinding = %x\n", AdapterBinding));
184
185 #ifdef DBG
186 if(!AdapterBinding)
187 {
188 NDIS_DbgPrint(MIN_TRACE, ("AdapterBinding was null\n"));
189 break;
190 }
191
192 if(!AdapterBinding->ProtocolBinding)
193 {
194 NDIS_DbgPrint(MIN_TRACE, ("AdapterBinding->ProtocolBinding was null\n"));
195 break;
196 }
197
198 if(!AdapterBinding->ProtocolBinding->Chars.ReceiveHandler)
199 {
200 NDIS_DbgPrint(MIN_TRACE, ("AdapterBinding->ProtocolBinding->Chars.ReceiveHandler was null\n"));
201 break;
202 }
203 #endif
204
205 NDIS_DbgPrint
206 (MID_TRACE,
207 ("XXX (%x) %x %x %x %x %x %x %x XXX\n",
208 *AdapterBinding->ProtocolBinding->Chars.ReceiveHandler,
209 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
210 MacReceiveContext,
211 HeaderBuffer,
212 HeaderBufferSize,
213 LookaheadBuffer,
214 LookaheadBufferSize,
215 PacketSize));
216
217 /* call the receive handler */
218 (*AdapterBinding->ProtocolBinding->Chars.ReceiveHandler)(
219 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
220 MacReceiveContext,
221 HeaderBuffer,
222 HeaderBufferSize,
223 LookaheadBuffer,
224 LookaheadBufferSize,
225 PacketSize);
226
227 CurrentEntry = CurrentEntry->Flink;
228 }
229 }
230 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
231
232 NDIS_DbgPrint(MAX_TRACE, ("Leaving.\n"));
233 }
234
235 \f
236 VOID NTAPI
237 MiniIndicateReceivePacket(
238 IN NDIS_HANDLE MiniportAdapterHandle,
239 IN PPNDIS_PACKET PacketArray,
240 IN UINT NumberOfPackets)
241 /*
242 * FUNCTION: receives miniport packet array indications
243 * ARGUMENTS:
244 * MiniportAdapterHandle: Miniport handle for the adapter
245 * PacketArray: pointer to a list of packet pointers to indicate
246 * NumberOfPackets: number of packets to indicate
247 *
248 */
249 {
250 PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
251 PLIST_ENTRY CurrentEntry;
252 PADAPTER_BINDING AdapterBinding;
253 KIRQL OldIrql;
254 UINT i;
255
256 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
257
258 CurrentEntry = Adapter->ProtocolListHead.Flink;
259
260 while (CurrentEntry != &Adapter->ProtocolListHead)
261 {
262 AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
263
264 for (i = 0; i < NumberOfPackets; i++)
265 {
266 (*AdapterBinding->ProtocolBinding->Chars.ReceivePacketHandler)(
267 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
268 PacketArray[i]);
269 }
270
271 CurrentEntry = CurrentEntry->Flink;
272 }
273
274 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
275 }
276
277 \f
278 VOID NTAPI
279 MiniResetComplete(
280 IN NDIS_HANDLE MiniportAdapterHandle,
281 IN NDIS_STATUS Status,
282 IN BOOLEAN AddressingReset)
283 {
284 PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
285 KIRQL OldIrql;
286 NDIS_DbgPrint(MIN_TRACE, ("FIXME: MiniResetComplete is partially implemented\n"));
287 NdisMIndicateStatus(Adapter, NDIS_STATUS_RESET_END, NULL, 0);
288 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
289 Adapter->MiniportBusy = FALSE;
290 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
291 }
292
293
294 \f
295 VOID NTAPI
296 MiniRequestComplete(
297 IN PNDIS_HANDLE MiniportAdapterHandle,
298 IN PNDIS_REQUEST Request,
299 IN NDIS_STATUS Status)
300 {
301 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
302 PNDIS_REQUEST_MAC_BLOCK MacBlock = (PNDIS_REQUEST_MAC_BLOCK)Request->MacReserved;
303 KIRQL OldIrql;
304
305 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
306
307 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
308 if( MacBlock->Binding->RequestCompleteHandler ) {
309 (*MacBlock->Binding->RequestCompleteHandler)(
310 MacBlock->Binding->ProtocolBindingContext,
311 Request,
312 Status);
313 }
314 KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
315 Adapter->MiniportBusy = FALSE;
316 KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
317 KeLowerIrql(OldIrql);
318 }
319
320 VOID NTAPI
321 MiniSendComplete(
322 IN NDIS_HANDLE MiniportAdapterHandle,
323 IN PNDIS_PACKET Packet,
324 IN NDIS_STATUS Status)
325 /*
326 * FUNCTION: Forwards a message to the initiating protocol saying
327 * that a packet was handled
328 * ARGUMENTS:
329 * NdisAdapterHandle = Handle input to MiniportInitialize
330 * Packet = Pointer to NDIS packet that was sent
331 * Status = Status of send operation
332 */
333 {
334 PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
335 PADAPTER_BINDING AdapterBinding;
336 KIRQL OldIrql;
337
338 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
339
340 AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[0];
341
342 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
343 (*AdapterBinding->ProtocolBinding->Chars.SendCompleteHandler)(
344 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
345 Packet,
346 Status);
347 KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
348 Adapter->MiniportBusy = FALSE;
349 KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
350 KeLowerIrql(OldIrql);
351 }
352
353
354 VOID NTAPI
355 MiniSendResourcesAvailable(
356 IN NDIS_HANDLE MiniportAdapterHandle)
357 {
358 /*
359 UNIMPLEMENTED
360 */
361 }
362
363
364 VOID NTAPI
365 MiniTransferDataComplete(
366 IN NDIS_HANDLE MiniportAdapterHandle,
367 IN PNDIS_PACKET Packet,
368 IN NDIS_STATUS Status,
369 IN UINT BytesTransferred)
370 {
371 PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
372 PADAPTER_BINDING AdapterBinding;
373 KIRQL OldIrql;
374
375 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
376
377 AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[0];
378
379 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
380 (*AdapterBinding->ProtocolBinding->Chars.SendCompleteHandler)(
381 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
382 Packet,
383 Status);
384 KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
385 Adapter->MiniportBusy = FALSE;
386 KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
387 KeLowerIrql(OldIrql);
388 }
389
390 \f
391 BOOLEAN
392 MiniAdapterHasAddress(
393 PLOGICAL_ADAPTER Adapter,
394 PNDIS_PACKET Packet)
395 /*
396 * FUNCTION: Determines whether a packet has the same destination address as an adapter
397 * ARGUMENTS:
398 * Adapter = Pointer to logical adapter object
399 * Packet = Pointer to NDIS packet
400 * RETURNS:
401 * TRUE if the destination address is that of the adapter, FALSE if not
402 */
403 {
404 UINT Length;
405 PUCHAR Start1;
406 PUCHAR Start2;
407 PNDIS_BUFFER NdisBuffer;
408 UINT BufferLength;
409
410 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
411
412 #ifdef DBG
413 if(!Adapter)
414 {
415 NDIS_DbgPrint(MID_TRACE, ("Adapter object was null\n"));
416 return FALSE;
417 }
418
419 if(!Packet)
420 {
421 NDIS_DbgPrint(MID_TRACE, ("Packet was null\n"));
422 return FALSE;
423 }
424 #endif
425
426 NdisQueryPacket(Packet, NULL, NULL, &NdisBuffer, NULL);
427
428 if (!NdisBuffer)
429 {
430 NDIS_DbgPrint(MID_TRACE, ("Packet contains no buffers.\n"));
431 return FALSE;
432 }
433
434 NdisQueryBuffer(NdisBuffer, (PVOID)&Start2, &BufferLength);
435
436 /* FIXME: Should handle fragmented packets */
437
438 switch (Adapter->NdisMiniportBlock.MediaType)
439 {
440 case NdisMedium802_3:
441 Length = ETH_LENGTH_OF_ADDRESS;
442 /* Destination address is the first field */
443 break;
444
445 default:
446 NDIS_DbgPrint(MIN_TRACE, ("Adapter has unsupported media type (0x%X).\n", Adapter->NdisMiniportBlock.MediaType));
447 return FALSE;
448 }
449
450 if (BufferLength < Length)
451 {
452 NDIS_DbgPrint(MID_TRACE, ("Buffer is too small.\n"));
453 return FALSE;
454 }
455
456 Start1 = (PUCHAR)&Adapter->Address;
457 NDIS_DbgPrint(MAX_TRACE, ("packet address: %x:%x:%x:%x:%x:%x adapter address: %x:%x:%x:%x:%x:%x\n",
458 *((char *)Start1), *(((char *)Start1)+1), *(((char *)Start1)+2), *(((char *)Start1)+3), *(((char *)Start1)+4), *(((char *)Start1)+5),
459 *((char *)Start2), *(((char *)Start2)+1), *(((char *)Start2)+2), *(((char *)Start2)+3), *(((char *)Start2)+4), *(((char *)Start2)+5))
460 );
461
462 return (RtlCompareMemory((PVOID)Start1, (PVOID)Start2, Length) == Length);
463 }
464
465 \f
466 PLOGICAL_ADAPTER
467 MiniLocateDevice(
468 PNDIS_STRING AdapterName)
469 /*
470 * FUNCTION: Finds an adapter object by name
471 * ARGUMENTS:
472 * AdapterName = Pointer to name of adapter
473 * RETURNS:
474 * Pointer to logical adapter object, or NULL if none was found.
475 * If found, the adapter is referenced for the caller. The caller
476 * is responsible for dereferencing after use
477 */
478 {
479 KIRQL OldIrql;
480 PLIST_ENTRY CurrentEntry;
481 PLOGICAL_ADAPTER Adapter = 0;
482
483 ASSERT(AdapterName);
484
485 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
486
487 if(IsListEmpty(&AdapterListHead))
488 {
489 NDIS_DbgPrint(DEBUG_MINIPORT, ("No registered miniports for protocol to bind to\n"));
490 return NULL;
491 }
492
493 KeAcquireSpinLock(&AdapterListLock, &OldIrql);
494 {
495 CurrentEntry = AdapterListHead.Flink;
496
497 while (CurrentEntry != &AdapterListHead)
498 {
499 Adapter = CONTAINING_RECORD(CurrentEntry, LOGICAL_ADAPTER, ListEntry);
500
501 ASSERT(Adapter);
502
503 NDIS_DbgPrint(DEBUG_MINIPORT, ("Examining adapter 0x%lx\n", Adapter));
504 NDIS_DbgPrint(DEBUG_MINIPORT, ("AdapterName = %wZ\n", AdapterName));
505 NDIS_DbgPrint(DEBUG_MINIPORT, ("DeviceName = %wZ\n", &Adapter->NdisMiniportBlock.MiniportName));
506
507 if (RtlCompareUnicodeString(AdapterName, &Adapter->NdisMiniportBlock.MiniportName, TRUE) == 0)
508 {
509 break;
510 }
511
512 Adapter = NULL;
513 CurrentEntry = CurrentEntry->Flink;
514 }
515 }
516 KeReleaseSpinLock(&AdapterListLock, OldIrql);
517
518 if(Adapter)
519 {
520 NDIS_DbgPrint(DEBUG_MINIPORT, ("Leaving. Adapter found at 0x%x\n", Adapter));
521 }
522 else
523 {
524 NDIS_DbgPrint(DEBUG_MINIPORT, ("Leaving (adapter not found).\n"));
525 }
526
527 return Adapter;
528 }
529
530 \f
531 NDIS_STATUS
532 MiniQueryInformation(
533 PLOGICAL_ADAPTER Adapter,
534 NDIS_OID Oid,
535 ULONG Size,
536 PVOID Buffer,
537 PULONG BytesWritten)
538 /*
539 * FUNCTION: Queries a logical adapter for properties
540 * ARGUMENTS:
541 * Adapter = Pointer to the logical adapter object to query
542 * Oid = Specifies the Object ID to query for
543 * Size = Size of the passed buffer
544 * Buffer = Buffer for the output
545 * BytesWritten = Address of buffer to place number of bytes written
546 * NOTES:
547 * If the specified buffer is too small, a new buffer is allocated,
548 * and the query is attempted again
549 * RETURNS:
550 * Status of operation
551 * TODO:
552 * Is there any way to use the buffer provided by the protocol?
553 */
554 {
555 NDIS_STATUS NdisStatus;
556 ULONG BytesNeeded;
557 KIRQL OldIrql;
558
559 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
560
561 /* call the miniport's queryinfo handler */
562 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
563 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.QueryInformationHandler)(
564 Adapter->NdisMiniportBlock.MiniportAdapterContext,
565 Oid,
566 Buffer,
567 Size,
568 BytesWritten,
569 &BytesNeeded);
570 KeLowerIrql(OldIrql);
571
572 /* FIXME: Wait in pending case! */
573
574 return NdisStatus;
575 }
576
577 BOOLEAN
578 MiniCheckForHang( PLOGICAL_ADAPTER Adapter )
579 /*
580 * FUNCTION: Checks to see if the miniport is hung
581 * ARGUMENTS:
582 * Adapter = Pointer to the logical adapter object
583 * RETURNS:
584 * TRUE if the miniport is hung
585 * FALSE if the miniport is not hung
586 */
587 {
588 BOOLEAN Ret = FALSE;
589 KIRQL OldIrql;
590
591 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
592 if (Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CheckForHangHandler)
593 Ret = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CheckForHangHandler)(
594 Adapter->NdisMiniportBlock.MiniportAdapterContext);
595 KeLowerIrql(OldIrql);
596
597 return Ret;
598 }
599
600 NDIS_STATUS
601 MiniReset(
602 PLOGICAL_ADAPTER Adapter,
603 PBOOLEAN AddressingReset)
604 /*
605 * FUNCTION: Resets the miniport
606 * ARGUMENTS:
607 * Adapter = Pointer to the logical adapter object
608 * AddressingReset = Set to TRUE if we need to call MiniportSetInformation later
609 * RETURNS:
610 * Status of the operation
611 */
612 {
613 NDIS_STATUS Status;
614 KIRQL OldIrql;
615
616 if (Adapter->MiniportBusy) {
617 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
618 MiniQueueWorkItem(Adapter, NdisWorkItemResetRequested, NULL);
619 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
620 return NDIS_STATUS_PENDING;
621 }
622
623 NdisMIndicateStatus(Adapter, NDIS_STATUS_RESET_START, NULL, 0);
624 NdisMIndicateStatusComplete(Adapter);
625
626 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
627 Status = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.ResetHandler)(
628 Adapter->NdisMiniportBlock.MiniportAdapterContext,
629 AddressingReset);
630 KeLowerIrql(OldIrql);
631
632 if (Status != NDIS_STATUS_PENDING) {
633 NdisMIndicateStatus(Adapter, NDIS_STATUS_RESET_END, NULL, 0);
634 NdisMIndicateStatusComplete(Adapter);
635 } else {
636 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
637 Adapter->MiniportBusy = TRUE;
638 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
639 }
640
641 return Status;
642 }
643
644 VOID STDCALL
645 MiniportHangDpc(
646 PKDPC Dpc,
647 PVOID DeferredContext,
648 PVOID SystemArgument1,
649 PVOID SystemArgument2)
650 {
651 PLOGICAL_ADAPTER Adapter = DeferredContext;
652 BOOLEAN AddressingReset = FALSE;
653
654
655 if (MiniCheckForHang(Adapter)) {
656 NDIS_DbgPrint(MIN_TRACE, ("Miniport detected adapter hang\n"));
657 MiniReset(Adapter, &AddressingReset);
658 }
659
660 /* FIXME: We should call MiniportSetInformation if AddressingReset is TRUE */
661 }
662
663 \f
664 NDIS_STATUS
665 FASTCALL
666 MiniQueueWorkItem(
667 PLOGICAL_ADAPTER Adapter,
668 NDIS_WORK_ITEM_TYPE WorkItemType,
669 PVOID WorkItemContext)
670 /*
671 * FUNCTION: Queues a work item for execution at a later time
672 * ARGUMENTS:
673 * Adapter = Pointer to the logical adapter object to queue work item on
674 * WorkItemType = Type of work item to queue
675 * WorkItemContext = Pointer to context information for work item
676 * NOTES:
677 * Adapter lock must be held when called
678 * RETURNS:
679 * Status of operation
680 */
681 {
682 PNDIS_MINIPORT_WORK_ITEM Item;
683
684 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
685
686 ASSERT(Adapter);
687 ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
688
689 Item = ExAllocatePool(NonPagedPool, sizeof(NDIS_MINIPORT_WORK_ITEM));
690 if (Item == NULL)
691 {
692 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
693 return NDIS_STATUS_RESOURCES;
694 }
695
696 Item->WorkItemType = WorkItemType;
697 Item->WorkItemContext = WorkItemContext;
698
699 /* safe due to adapter lock held */
700 Item->Link.Next = NULL;
701 if (!Adapter->WorkQueueHead)
702 {
703 Adapter->WorkQueueHead = Item;
704 Adapter->WorkQueueTail = Item;
705 }
706 else
707 {
708 Adapter->WorkQueueTail->Link.Next = (PSINGLE_LIST_ENTRY)Item;
709 Adapter->WorkQueueTail = Item;
710 }
711
712 KeInsertQueueDpc(&Adapter->NdisMiniportBlock.DeferredDpc, NULL, NULL);
713
714 return NDIS_STATUS_SUCCESS;
715 }
716
717 \f
718 NDIS_STATUS
719 FASTCALL
720 MiniDequeueWorkItem(
721 PLOGICAL_ADAPTER Adapter,
722 NDIS_WORK_ITEM_TYPE *WorkItemType,
723 PVOID *WorkItemContext)
724 /*
725 * FUNCTION: Dequeues a work item from the work queue of a logical adapter
726 * ARGUMENTS:
727 * Adapter = Pointer to the logical adapter object to dequeue work item from
728 * AdapterBinding = Address of buffer for adapter binding for this request
729 * WorkItemType = Address of buffer for work item type
730 * WorkItemContext = Address of buffer for pointer to context information
731 * NOTES:
732 * Adapter lock must be held when called
733 * RETURNS:
734 * Status of operation
735 */
736 {
737 PNDIS_MINIPORT_WORK_ITEM Item;
738
739 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
740
741 if (Adapter->MiniportBusy) {
742 NDIS_DbgPrint(MID_TRACE, ("Waiting for miniport to become free.\n"));
743 KeInsertQueueDpc(&Adapter->NdisMiniportBlock.DeferredDpc, NULL, NULL);
744 return NDIS_STATUS_FAILURE;
745 }
746
747 Item = Adapter->WorkQueueHead;
748
749 if (Item)
750 {
751 /* safe due to adapter lock held */
752 Adapter->WorkQueueHead = (PNDIS_MINIPORT_WORK_ITEM)Item->Link.Next;
753
754 if (Item == Adapter->WorkQueueTail)
755 Adapter->WorkQueueTail = NULL;
756
757 *WorkItemType = Item->WorkItemType;
758 *WorkItemContext = Item->WorkItemContext;
759
760 ExFreePool(Item);
761
762 Adapter->MiniportBusy = TRUE;
763
764 return NDIS_STATUS_SUCCESS;
765 }
766
767 return NDIS_STATUS_FAILURE;
768 }
769
770 \f
771 NDIS_STATUS
772 MiniDoRequest(
773 PLOGICAL_ADAPTER Adapter,
774 PNDIS_REQUEST NdisRequest)
775 /*
776 * FUNCTION: Sends a request to a miniport
777 * ARGUMENTS:
778 * AdapterBinding = Pointer to binding used in the request
779 * NdisRequest = Pointer to NDIS request structure describing request
780 * RETURNS:
781 * Status of operation
782 */
783 {
784 NDIS_STATUS Status;
785 KIRQL OldIrql;
786 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
787
788 Adapter->NdisMiniportBlock.MediaRequest = NdisRequest;
789
790 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
791 switch (NdisRequest->RequestType)
792 {
793 case NdisRequestQueryInformation:
794 Status = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.QueryInformationHandler)(
795 Adapter->NdisMiniportBlock.MiniportAdapterContext,
796 NdisRequest->DATA.QUERY_INFORMATION.Oid,
797 NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
798 NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength,
799 (PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesWritten,
800 (PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded);
801 break;
802
803 case NdisRequestSetInformation:
804 Status = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SetInformationHandler)(
805 Adapter->NdisMiniportBlock.MiniportAdapterContext,
806 NdisRequest->DATA.SET_INFORMATION.Oid,
807 NdisRequest->DATA.SET_INFORMATION.InformationBuffer,
808 NdisRequest->DATA.SET_INFORMATION.InformationBufferLength,
809 (PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesRead,
810 (PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesNeeded);
811 break;
812
813 default:
814 Status = NDIS_STATUS_FAILURE;
815 }
816
817 if (Status == NDIS_STATUS_PENDING) {
818 KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
819 Adapter->MiniportBusy = TRUE;
820 KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
821 }
822
823 KeLowerIrql(OldIrql);
824 return Status;
825 }
826
827 \f
828 /*
829 * @implemented
830 */
831 #undef NdisMQueryInformationComplete
832 VOID
833 EXPORT
834 NdisMQueryInformationComplete(
835 IN NDIS_HANDLE MiniportAdapterHandle,
836 IN NDIS_STATUS Status)
837 {
838 PLOGICAL_ADAPTER Adapter =
839 (PLOGICAL_ADAPTER)MiniportAdapterHandle;
840 KIRQL OldIrql;
841 ASSERT(Adapter);
842 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
843 if( Adapter->NdisMiniportBlock.QueryCompleteHandler )
844 (Adapter->NdisMiniportBlock.QueryCompleteHandler)(MiniportAdapterHandle, Status);
845 KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
846 Adapter->MiniportBusy = FALSE;
847 KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
848 KeLowerIrql(OldIrql);
849 }
850
851 VOID NTAPI MiniportWorker(IN PVOID WorkItem)
852 {
853 PNDIS_WORK_ITEM NdisWorkItem = WorkItem;
854 PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(NdisWorkItem->Context);
855 KIRQL OldIrql, RaiseOldIrql;
856 NDIS_STATUS NdisStatus;
857 PVOID WorkItemContext;
858 NDIS_WORK_ITEM_TYPE WorkItemType;
859 BOOLEAN AddressingReset;
860
861 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
862
863 NdisStatus =
864 MiniDequeueWorkItem
865 (Adapter, &WorkItemType, &WorkItemContext);
866
867 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
868
869 if (NdisStatus == NDIS_STATUS_SUCCESS)
870 {
871 switch (WorkItemType)
872 {
873 case NdisWorkItemSend:
874 /*
875 * called by ProSend when protocols want to send packets to the miniport
876 */
877 #ifdef DBG
878 MiniDisplayPacket((PNDIS_PACKET)WorkItemContext);
879 #endif
880 if(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)
881 {
882 if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
883 {
884 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
885 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
886 Adapter->NdisMiniportBlock.MiniportAdapterContext, (PPNDIS_PACKET)&WorkItemContext, 1);
887 NdisStatus = NDIS_GET_PACKET_STATUS((PNDIS_PACKET)WorkItemContext);
888 }
889 else
890 {
891 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
892 KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
893 {
894 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
895 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
896 Adapter->NdisMiniportBlock.MiniportAdapterContext, (PPNDIS_PACKET)&WorkItemContext, 1);
897 }
898 KeLowerIrql(RaiseOldIrql);
899
900 NdisStatus = NDIS_GET_PACKET_STATUS((PNDIS_PACKET)WorkItemContext);
901 if( NdisStatus == NDIS_STATUS_RESOURCES ) {
902 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
903 MiniQueueWorkItem(Adapter, WorkItemType, WorkItemContext);
904 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
905 break;
906 }
907 }
908 }
909 else
910 {
911 if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
912 {
913 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
914 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
915 Adapter->NdisMiniportBlock.MiniportAdapterContext, (PNDIS_PACKET)WorkItemContext, 0);
916 NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n"));
917 }
918 else
919 {
920 /* Send is called at DISPATCH_LEVEL for all serialized miniports */
921 KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
922 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
923 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
924 Adapter->NdisMiniportBlock.MiniportAdapterContext, (PNDIS_PACKET)WorkItemContext, 0);
925 NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n"));
926 KeLowerIrql(RaiseOldIrql);
927 if( NdisStatus == NDIS_STATUS_RESOURCES ) {
928 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
929 MiniQueueWorkItem(Adapter, WorkItemType, WorkItemContext);
930 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
931 break;
932 }
933 }
934 }
935
936 if( NdisStatus != NDIS_STATUS_PENDING ) {
937 NdisMSendComplete
938 ( Adapter, (PNDIS_PACKET)WorkItemContext, NdisStatus );
939 }
940 break;
941
942 case NdisWorkItemSendLoopback:
943 /*
944 * called by ProSend when protocols want to send loopback packets
945 */
946 /* XXX atm ProIndicatePacket sends a packet up via the loopback adapter only */
947 NdisStatus = ProIndicatePacket(Adapter, (PNDIS_PACKET)WorkItemContext);
948
949 if( NdisStatus != NDIS_STATUS_PENDING )
950 MiniSendComplete((NDIS_HANDLE)Adapter, (PNDIS_PACKET)WorkItemContext, NdisStatus);
951 break;
952
953 case NdisWorkItemReturnPackets:
954 break;
955
956 case NdisWorkItemResetRequested:
957 NdisMIndicateStatus(Adapter, NDIS_STATUS_RESET_START, NULL, 0);
958 NdisMIndicateStatusComplete(Adapter);
959
960 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
961 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.ResetHandler)(
962 Adapter->NdisMiniportBlock.MiniportAdapterContext,
963 &AddressingReset);
964 KeLowerIrql(OldIrql);
965
966 if (NdisStatus == NDIS_STATUS_PENDING)
967 break;
968
969 MiniResetComplete(Adapter, NdisStatus, AddressingReset);
970 break;
971
972 case NdisWorkItemResetInProgress:
973 break;
974
975 case NdisWorkItemMiniportCallback:
976 break;
977
978 case NdisWorkItemRequest:
979 NdisStatus = MiniDoRequest(Adapter, (PNDIS_REQUEST)WorkItemContext);
980
981 if (NdisStatus == NDIS_STATUS_PENDING)
982 break;
983
984 switch (((PNDIS_REQUEST)WorkItemContext)->RequestType)
985 {
986 case NdisRequestQueryInformation:
987 NdisMQueryInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
988 MiniRequestComplete( (NDIS_HANDLE)Adapter, (PNDIS_REQUEST)WorkItemContext, NdisStatus );
989 break;
990
991 case NdisRequestSetInformation:
992 NdisMSetInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
993 MiniRequestComplete( (NDIS_HANDLE)Adapter, (PNDIS_REQUEST)WorkItemContext, NdisStatus );
994 break;
995
996 default:
997 NDIS_DbgPrint(MIN_TRACE, ("Unknown NDIS request type.\n"));
998 break;
999 }
1000 break;
1001
1002 default:
1003 NDIS_DbgPrint(MIN_TRACE, ("Unknown NDIS work item type (%d).\n", WorkItemType));
1004 break;
1005 }
1006 }
1007
1008 if( NdisStatus != NDIS_STATUS_PENDING ) {
1009 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
1010 Adapter->MiniportBusy = FALSE;
1011 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
1012 }
1013
1014 ExFreePool(WorkItem);
1015 }
1016
1017
1018 \f
1019 VOID NTAPI MiniportDpc(
1020 IN PKDPC Dpc,
1021 IN PVOID DeferredContext,
1022 IN PVOID SystemArgument1,
1023 IN PVOID SystemArgument2)
1024 /*
1025 * FUNCTION: Deferred routine to handle serialization
1026 * ARGUMENTS:
1027 * Dpc = Pointer to DPC object
1028 * DeferredContext = Pointer to context information (LOGICAL_ADAPTER)
1029 * SystemArgument1 = Unused
1030 * SystemArgument2 = Unused
1031 */
1032 {
1033 PNDIS_WORK_ITEM NdisWorkItem;
1034 PWORK_QUEUE_ITEM WorkItem;
1035
1036 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
1037
1038 NdisWorkItem = ExAllocatePool(NonPagedPool, sizeof(NDIS_WORK_ITEM));
1039 if (!NdisWorkItem) return;
1040
1041 WorkItem = (PWORK_QUEUE_ITEM)NdisWorkItem->WrapperReserved;
1042
1043 NdisWorkItem->Context = DeferredContext;
1044
1045 ExInitializeWorkItem(WorkItem, MiniportWorker, NdisWorkItem);
1046
1047 ExQueueWorkItem(WorkItem, CriticalWorkQueue);
1048 }
1049
1050 \f
1051 VOID
1052 NTAPI
1053 MiniStatus(
1054 IN NDIS_HANDLE MiniportHandle,
1055 IN NDIS_STATUS GeneralStatus,
1056 IN PVOID StatusBuffer,
1057 IN UINT StatusBufferSize)
1058 {
1059 PLOGICAL_ADAPTER Adapter = MiniportHandle;
1060 PLIST_ENTRY CurrentEntry;
1061 PADAPTER_BINDING AdapterBinding;
1062 KIRQL OldIrql;
1063
1064 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
1065
1066 CurrentEntry = Adapter->ProtocolListHead.Flink;
1067
1068 while (CurrentEntry != &Adapter->ProtocolListHead)
1069 {
1070 AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
1071
1072 (*AdapterBinding->ProtocolBinding->Chars.StatusHandler)(
1073 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
1074 GeneralStatus,
1075 StatusBuffer,
1076 StatusBufferSize);
1077
1078 CurrentEntry = CurrentEntry->Flink;
1079 }
1080
1081 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
1082 }
1083
1084 \f
1085 VOID
1086 NTAPI
1087 MiniStatusComplete(
1088 IN NDIS_HANDLE MiniportAdapterHandle)
1089 {
1090 PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
1091 PLIST_ENTRY CurrentEntry;
1092 PADAPTER_BINDING AdapterBinding;
1093 KIRQL OldIrql;
1094
1095 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
1096
1097 CurrentEntry = Adapter->ProtocolListHead.Flink;
1098
1099 while (CurrentEntry != &Adapter->ProtocolListHead)
1100 {
1101 AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
1102
1103 (*AdapterBinding->ProtocolBinding->Chars.StatusCompleteHandler)(
1104 AdapterBinding->NdisOpenBlock.ProtocolBindingContext);
1105
1106 CurrentEntry = CurrentEntry->Flink;
1107 }
1108
1109 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
1110 }
1111
1112 \f
1113 /*
1114 * @unimplemented
1115 */
1116 VOID
1117 EXPORT
1118 NdisMCloseLog(
1119 IN NDIS_HANDLE LogHandle)
1120 {
1121 UNIMPLEMENTED
1122 }
1123
1124 \f
1125 /*
1126 * @unimplemented
1127 */
1128 NDIS_STATUS
1129 EXPORT
1130 NdisMCreateLog(
1131 IN NDIS_HANDLE MiniportAdapterHandle,
1132 IN UINT Size,
1133 OUT PNDIS_HANDLE LogHandle)
1134 {
1135 UNIMPLEMENTED
1136
1137 return NDIS_STATUS_FAILURE;
1138 }
1139
1140 \f
1141 /*
1142 * @implemented
1143 */
1144 VOID
1145 EXPORT
1146 NdisMDeregisterAdapterShutdownHandler(
1147 IN NDIS_HANDLE MiniportHandle)
1148 /*
1149 * FUNCTION: de-registers a shutdown handler
1150 * ARGUMENTS: MiniportHandle: Handle passed into MiniportInitialize
1151 */
1152 {
1153 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportHandle;
1154
1155 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
1156
1157 if(Adapter->BugcheckContext->ShutdownHandler)
1158 KeDeregisterBugCheckCallback(Adapter->BugcheckContext->CallbackRecord);
1159 }
1160
1161 \f
1162 /*
1163 * @unimplemented
1164 */
1165 VOID
1166 EXPORT
1167 NdisMFlushLog(
1168 IN NDIS_HANDLE LogHandle)
1169 {
1170 UNIMPLEMENTED
1171 }
1172
1173 /*
1174 * @implemented
1175 */
1176 #undef NdisMIndicateStatus
1177 VOID
1178 EXPORT
1179 NdisMIndicateStatus(
1180 IN NDIS_HANDLE MiniportAdapterHandle,
1181 IN NDIS_STATUS GeneralStatus,
1182 IN PVOID StatusBuffer,
1183 IN UINT StatusBufferSize)
1184 {
1185 MiniStatus(MiniportAdapterHandle, GeneralStatus, StatusBuffer, StatusBufferSize);
1186 }
1187
1188 /*
1189 * @implemented
1190 */
1191 #undef NdisMIndicateStatusComplete
1192 VOID
1193 EXPORT
1194 NdisMIndicateStatusComplete(
1195 IN NDIS_HANDLE MiniportAdapterHandle)
1196 {
1197 MiniStatusComplete(MiniportAdapterHandle);
1198 }
1199
1200 \f
1201 /*
1202 * @implemented
1203 */
1204 VOID
1205 EXPORT
1206 NdisInitializeWrapper(
1207 OUT PNDIS_HANDLE NdisWrapperHandle,
1208 IN PVOID SystemSpecific1,
1209 IN PVOID SystemSpecific2,
1210 IN PVOID SystemSpecific3)
1211 /*
1212 * FUNCTION: Notifies the NDIS library that a new miniport is initializing
1213 * ARGUMENTS:
1214 * NdisWrapperHandle = Address of buffer to place NDIS wrapper handle
1215 * SystemSpecific1 = Pointer to the driver's driver object
1216 * SystemSpecific2 = Pointer to the driver's registry path
1217 * SystemSpecific3 = Always NULL
1218 * NOTES:
1219 * - SystemSpecific2 goes invalid so we copy it
1220 */
1221 {
1222 PNDIS_M_DRIVER_BLOCK Miniport;
1223 PUNICODE_STRING RegistryPath;
1224 WCHAR *RegistryBuffer;
1225
1226 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1227
1228 ASSERT(NdisWrapperHandle);
1229
1230 *NdisWrapperHandle = NULL;
1231
1232 #if BREAK_ON_MINIPORT_INIT
1233 __asm__ ("int $3\n");
1234 #endif
1235
1236 Miniport = ExAllocatePool(NonPagedPool, sizeof(NDIS_M_DRIVER_BLOCK));
1237
1238 if (!Miniport)
1239 {
1240 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1241 return;
1242 }
1243
1244 RtlZeroMemory(Miniport, sizeof(NDIS_M_DRIVER_BLOCK));
1245
1246 KeInitializeSpinLock(&Miniport->Lock);
1247
1248 Miniport->DriverObject = (PDRIVER_OBJECT)SystemSpecific1;
1249
1250 /* set the miniport's driver registry path */
1251 RegistryPath = ExAllocatePool(PagedPool, sizeof(UNICODE_STRING));
1252 if(!RegistryPath)
1253 {
1254 ExFreePool(Miniport);
1255 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1256 return;
1257 }
1258
1259 RegistryPath->Length = ((PUNICODE_STRING)SystemSpecific2)->Length;
1260 RegistryPath->MaximumLength = RegistryPath->Length + sizeof(WCHAR); /* room for 0-term */
1261
1262 RegistryBuffer = ExAllocatePool(PagedPool, RegistryPath->MaximumLength);
1263 if(!RegistryBuffer)
1264 {
1265 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1266 ExFreePool(Miniport);
1267 ExFreePool(RegistryPath);
1268 return;
1269 }
1270
1271 RtlCopyMemory(RegistryBuffer, ((PUNICODE_STRING)SystemSpecific2)->Buffer, RegistryPath->Length);
1272 RegistryBuffer[RegistryPath->Length/sizeof(WCHAR)] = 0;
1273
1274 RegistryPath->Buffer = RegistryBuffer;
1275 Miniport->RegistryPath = RegistryPath;
1276
1277 InitializeListHead(&Miniport->DeviceList);
1278
1279 /* Put miniport in global miniport list */
1280 ExInterlockedInsertTailList(&MiniportListHead, &Miniport->ListEntry, &MiniportListLock);
1281
1282 *NdisWrapperHandle = Miniport;
1283 }
1284
1285 \f
1286 VOID NTAPI NdisIBugcheckCallback(
1287 IN PVOID Buffer,
1288 IN ULONG Length)
1289 /*
1290 * FUNCTION: Internal callback for handling bugchecks - calls adapter's shutdown handler
1291 * ARGUMENTS:
1292 * Buffer: Pointer to a bugcheck callback context
1293 * Length: Unused
1294 */
1295 {
1296 PMINIPORT_BUGCHECK_CONTEXT Context = (PMINIPORT_BUGCHECK_CONTEXT)Buffer;
1297 ADAPTER_SHUTDOWN_HANDLER sh = (ADAPTER_SHUTDOWN_HANDLER)Context->ShutdownHandler;
1298
1299 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
1300
1301 if(sh)
1302 sh(Context->DriverContext);
1303 }
1304
1305 \f
1306 /*
1307 * @implemented
1308 */
1309 VOID
1310 EXPORT
1311 NdisMRegisterAdapterShutdownHandler(
1312 IN NDIS_HANDLE MiniportHandle,
1313 IN PVOID ShutdownContext,
1314 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler)
1315 /*
1316 * FUNCTION: Register a shutdown handler for an adapter
1317 * ARGUMENTS:
1318 * MiniportHandle: Handle originally passed into MiniportInitialize
1319 * ShutdownContext: Pre-initialized bugcheck context
1320 * ShutdownHandler: Function to call to handle the bugcheck
1321 * NOTES:
1322 * - I'm not sure about ShutdownContext
1323 */
1324 {
1325 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportHandle;
1326 PMINIPORT_BUGCHECK_CONTEXT BugcheckContext = Adapter->BugcheckContext;
1327
1328 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
1329
1330 if(BugcheckContext)
1331 return;
1332
1333 BugcheckContext = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_BUGCHECK_CONTEXT));
1334 if(!BugcheckContext)
1335 {
1336 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1337 return;
1338 }
1339
1340 BugcheckContext->ShutdownHandler = ShutdownHandler;
1341 BugcheckContext->DriverContext = ShutdownContext;
1342
1343 BugcheckContext->CallbackRecord = ExAllocatePool(NonPagedPool, sizeof(KBUGCHECK_CALLBACK_RECORD));
1344
1345 KeInitializeCallbackRecord(BugcheckContext->CallbackRecord);
1346
1347 KeRegisterBugCheckCallback(BugcheckContext->CallbackRecord, NdisIBugcheckCallback,
1348 BugcheckContext, sizeof(BugcheckContext), (PUCHAR)"Ndis Miniport");
1349 }
1350
1351 \f
1352 NDIS_STATUS
1353 DoQueries(
1354 PLOGICAL_ADAPTER Adapter,
1355 NDIS_OID AddressOID)
1356 /*
1357 * FUNCTION: Queries miniport for information
1358 * ARGUMENTS:
1359 * Adapter = Pointer to logical adapter
1360 * AddressOID = OID to use to query for current address
1361 * RETURNS:
1362 * Status of operation
1363 */
1364 {
1365 ULONG BytesWritten;
1366 NDIS_STATUS NdisStatus;
1367
1368 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1369
1370 /* Get MAC options for adapter */
1371 NdisStatus = MiniQueryInformation(Adapter, OID_GEN_MAC_OPTIONS, sizeof(UINT),
1372 &Adapter->NdisMiniportBlock.MacOptions,
1373 &BytesWritten);
1374
1375 if (NdisStatus != NDIS_STATUS_SUCCESS)
1376 {
1377 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAC_OPTIONS failed. NdisStatus (0x%X).\n", NdisStatus));
1378 return NdisStatus;
1379 }
1380
1381 NDIS_DbgPrint(DEBUG_MINIPORT, ("MacOptions (0x%X).\n", Adapter->NdisMiniportBlock.MacOptions));
1382
1383 /* Get current hardware address of adapter */
1384 NdisStatus = MiniQueryInformation(Adapter, AddressOID, Adapter->AddressLength,
1385 &Adapter->Address, &BytesWritten);
1386
1387 if (NdisStatus != NDIS_STATUS_SUCCESS)
1388 {
1389 NDIS_DbgPrint(MIN_TRACE, ("Address OID (0x%X) failed. NdisStatus (0x%X).\n", AddressOID, NdisStatus));
1390 return NdisStatus;
1391 }
1392
1393 #ifdef DBG
1394 {
1395 /* 802.3 only */
1396
1397 PUCHAR A = (PUCHAR)&Adapter->Address.Type.Medium802_3;
1398
1399 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]));
1400 }
1401 #endif /* DBG */
1402
1403 /* Get maximum lookahead buffer size of adapter */
1404 NdisStatus = MiniQueryInformation(Adapter, OID_GEN_MAXIMUM_LOOKAHEAD, sizeof(ULONG),
1405 &Adapter->NdisMiniportBlock.MaximumLookahead, &BytesWritten);
1406
1407 if (NdisStatus != NDIS_STATUS_SUCCESS)
1408 {
1409 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAXIMUM_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus));
1410 return NdisStatus;
1411 }
1412
1413 NDIS_DbgPrint(DEBUG_MINIPORT, ("MaxLookaheadLength (0x%X).\n", Adapter->NdisMiniportBlock.MaximumLookahead));
1414
1415 /* Get current lookahead buffer size of adapter */
1416 NdisStatus = MiniQueryInformation(Adapter, OID_GEN_CURRENT_LOOKAHEAD, sizeof(ULONG),
1417 &Adapter->NdisMiniportBlock.CurrentLookahead, &BytesWritten);
1418
1419 if (NdisStatus != NDIS_STATUS_SUCCESS)
1420 {
1421 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_CURRENT_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus));
1422 return NdisStatus;
1423 }
1424
1425 NdisStatus = MiniQueryInformation(Adapter, OID_GEN_MAXIMUM_SEND_PACKETS, sizeof(ULONG),
1426 &Adapter->NdisMiniportBlock.MaxSendPackets, &BytesWritten);
1427
1428 if (NdisStatus != NDIS_STATUS_SUCCESS)
1429 {
1430 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAXIMUM_SEND_PACKETS failed. NdisStatus (0x%X).\n", NdisStatus));
1431
1432 /* Set it to 1 if it fails because some drivers don't support this (?)*/
1433 Adapter->NdisMiniportBlock.MaxSendPackets = 1;
1434 }
1435
1436 NDIS_DbgPrint(DEBUG_MINIPORT, ("CurLookaheadLength (0x%X).\n", Adapter->NdisMiniportBlock.CurrentLookahead));
1437
1438 if (Adapter->NdisMiniportBlock.MaximumLookahead != 0)
1439 {
1440 Adapter->LookaheadLength = Adapter->NdisMiniportBlock.MaximumLookahead + Adapter->MediumHeaderSize;
1441 Adapter->LookaheadBuffer = ExAllocatePool(NonPagedPool, Adapter->LookaheadLength);
1442
1443 if (!Adapter->LookaheadBuffer)
1444 return NDIS_STATUS_RESOURCES;
1445 }
1446
1447 return STATUS_SUCCESS;
1448 }
1449
1450 \f
1451 NTSTATUS
1452 NTAPI
1453 NdisIForwardIrpAndWaitCompletionRoutine(
1454 PDEVICE_OBJECT Fdo,
1455 PIRP Irp,
1456 PVOID Context)
1457 {
1458 PKEVENT Event = Context;
1459
1460 if (Irp->PendingReturned)
1461 KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
1462
1463 return STATUS_MORE_PROCESSING_REQUIRED;
1464 }
1465
1466 \f
1467 NTSTATUS
1468 NTAPI
1469 NdisIForwardIrpAndWait(PLOGICAL_ADAPTER Adapter, PIRP Irp)
1470 {
1471 KEVENT Event;
1472 NTSTATUS Status;
1473
1474 KeInitializeEvent(&Event, NotificationEvent, FALSE);
1475 IoCopyCurrentIrpStackLocationToNext(Irp);
1476 IoSetCompletionRoutine(Irp, NdisIForwardIrpAndWaitCompletionRoutine, &Event,
1477 TRUE, TRUE, TRUE);
1478 Status = IoCallDriver(Adapter->NdisMiniportBlock.NextDeviceObject, Irp);
1479 if (Status == STATUS_PENDING)
1480 {
1481 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
1482 Status = Irp->IoStatus.Status;
1483 }
1484 return Status;
1485 }
1486
1487 \f
1488 NTSTATUS
1489 NTAPI
1490 NdisIPnPStartDevice(
1491 IN PDEVICE_OBJECT DeviceObject,
1492 PIRP Irp)
1493 /*
1494 * FUNCTION: Handle the PnP start device event
1495 * ARGUMENTS:
1496 * DeviceObejct = Functional Device Object
1497 * Irp = IRP_MN_START_DEVICE I/O request packet
1498 * RETURNS:
1499 * Status of operation
1500 */
1501 {
1502 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
1503 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
1504 NDIS_WRAPPER_CONTEXT WrapperContext;
1505 NDIS_STATUS NdisStatus;
1506 NDIS_STATUS OpenErrorStatus;
1507 NTSTATUS Status;
1508 UINT SelectedMediumIndex = 0;
1509 NDIS_OID AddressOID;
1510 BOOLEAN Success = FALSE;
1511 ULONG ResourceCount;
1512 ULONG ResourceListSize;
1513 UNICODE_STRING ParamName;
1514 PNDIS_CONFIGURATION_PARAMETER ConfigParam;
1515 NDIS_HANDLE ConfigHandle;
1516 ULONG Size;
1517 LARGE_INTEGER Timeout;
1518 /* FIXME - KIRQL OldIrql; */
1519
1520 /*
1521 * Prepare wrapper context used by HW and configuration routines.
1522 */
1523
1524 NDIS_DbgPrint(DEBUG_MINIPORT, ("Start Device %wZ\n", &Adapter->NdisMiniportBlock.MiniportName));
1525
1526 NDIS_DbgPrint(MAX_TRACE, ("Inserting adapter 0x%x into adapter list\n", Adapter));
1527
1528 /* Put adapter in global adapter list */
1529 ExInterlockedInsertTailList(&AdapterListHead, &Adapter->ListEntry, &AdapterListLock);
1530
1531 Status = IoOpenDeviceRegistryKey(
1532 Adapter->NdisMiniportBlock.PhysicalDeviceObject, PLUGPLAY_REGKEY_DRIVER,
1533 KEY_ALL_ACCESS, &WrapperContext.RegistryHandle);
1534 if (!NT_SUCCESS(Status))
1535 {
1536 NDIS_DbgPrint(MIN_TRACE,("failed to open adapter-specific reg key\n"));
1537 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
1538 return Status;
1539 }
1540
1541 NDIS_DbgPrint(MAX_TRACE, ("opened device reg key\n"));
1542
1543 WrapperContext.DeviceObject = Adapter->NdisMiniportBlock.DeviceObject;
1544
1545 /*
1546 * Store the adapter resources used by HW routines such as
1547 * NdisMQueryAdapterResources.
1548 */
1549
1550 if (Stack->Parameters.StartDevice.AllocatedResources != NULL)
1551 {
1552 ResourceCount = Stack->Parameters.StartDevice.AllocatedResources->List[0].
1553 PartialResourceList.Count;
1554 ResourceListSize =
1555 FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.
1556 PartialDescriptors[ResourceCount]);
1557
1558 Adapter->NdisMiniportBlock.AllocatedResources =
1559 ExAllocatePool(PagedPool, ResourceListSize);
1560 if (Adapter->NdisMiniportBlock.AllocatedResources == NULL)
1561 {
1562 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
1563 return STATUS_INSUFFICIENT_RESOURCES;
1564 }
1565
1566 RtlCopyMemory(Adapter->NdisMiniportBlock.AllocatedResources,
1567 Stack->Parameters.StartDevice.AllocatedResources,
1568 ResourceListSize);
1569 }
1570
1571 if (Stack->Parameters.StartDevice.AllocatedResourcesTranslated != NULL)
1572 {
1573 ResourceCount = Stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].
1574 PartialResourceList.Count;
1575 ResourceListSize =
1576 FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.
1577 PartialDescriptors[ResourceCount]);
1578
1579 Adapter->NdisMiniportBlock.AllocatedResourcesTranslated =
1580 ExAllocatePool(PagedPool, ResourceListSize);
1581 if (Adapter->NdisMiniportBlock.AllocatedResourcesTranslated == NULL)
1582 {
1583 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
1584 return STATUS_INSUFFICIENT_RESOURCES;
1585 }
1586
1587 RtlCopyMemory(Adapter->NdisMiniportBlock.AllocatedResourcesTranslated,
1588 Stack->Parameters.StartDevice.AllocatedResourcesTranslated,
1589 ResourceListSize);
1590 }
1591
1592 /*
1593 * Store the Bus Type, Bus Number and Slot information. It's used by
1594 * the hardware routines then.
1595 */
1596
1597 NdisOpenConfiguration(&NdisStatus, &ConfigHandle, (NDIS_HANDLE)&WrapperContext);
1598
1599 Size = sizeof(ULONG);
1600 Status = IoGetDeviceProperty(Adapter->NdisMiniportBlock.PhysicalDeviceObject,
1601 DevicePropertyLegacyBusType, Size,
1602 &Adapter->NdisMiniportBlock.BusType, &Size);
1603 if (!NT_SUCCESS(Status) || (INTERFACE_TYPE)Adapter->NdisMiniportBlock.BusType == InterfaceTypeUndefined)
1604 {
1605 NdisInitUnicodeString(&ParamName, L"BusType");
1606 NdisReadConfiguration(&NdisStatus, &ConfigParam, ConfigHandle,
1607 &ParamName, NdisParameterInteger);
1608 if (NdisStatus == NDIS_STATUS_SUCCESS)
1609 Adapter->NdisMiniportBlock.BusType = ConfigParam->ParameterData.IntegerData;
1610 else
1611 Adapter->NdisMiniportBlock.BusType = Isa;
1612 }
1613
1614 Status = IoGetDeviceProperty(Adapter->NdisMiniportBlock.PhysicalDeviceObject,
1615 DevicePropertyBusNumber, Size,
1616 &Adapter->NdisMiniportBlock.BusNumber, &Size);
1617 if (!NT_SUCCESS(Status) || Adapter->NdisMiniportBlock.BusNumber == 0xFFFFFFF0)
1618 {
1619 NdisInitUnicodeString(&ParamName, L"BusNumber");
1620 NdisReadConfiguration(&NdisStatus, &ConfigParam, ConfigHandle,
1621 &ParamName, NdisParameterInteger);
1622 if (NdisStatus == NDIS_STATUS_SUCCESS)
1623 Adapter->NdisMiniportBlock.BusNumber = ConfigParam->ParameterData.IntegerData;
1624 else
1625 Adapter->NdisMiniportBlock.BusNumber = 0;
1626 }
1627 WrapperContext.BusNumber = Adapter->NdisMiniportBlock.BusNumber;
1628
1629 Status = IoGetDeviceProperty(Adapter->NdisMiniportBlock.PhysicalDeviceObject,
1630 DevicePropertyAddress, Size,
1631 &Adapter->NdisMiniportBlock.SlotNumber, &Size);
1632 if (!NT_SUCCESS(Status) || Adapter->NdisMiniportBlock.SlotNumber == (NDIS_INTERFACE_TYPE)-1)
1633 {
1634 NdisInitUnicodeString(&ParamName, L"SlotNumber");
1635 NdisReadConfiguration(&NdisStatus, &ConfigParam, ConfigHandle,
1636 &ParamName, NdisParameterInteger);
1637 if (NdisStatus == NDIS_STATUS_SUCCESS)
1638 Adapter->NdisMiniportBlock.SlotNumber = ConfigParam->ParameterData.IntegerData;
1639 else
1640 Adapter->NdisMiniportBlock.SlotNumber = 0;
1641 }
1642 else
1643 {
1644 /* Convert slotnumber to PCI_SLOT_NUMBER */
1645 ULONG PciSlotNumber = Adapter->NdisMiniportBlock.SlotNumber;
1646 PCI_SLOT_NUMBER SlotNumber;
1647
1648 SlotNumber.u.AsULONG = 0;
1649 SlotNumber.u.bits.DeviceNumber = (PciSlotNumber >> 16) & 0xFFFF;
1650 SlotNumber.u.bits.FunctionNumber = PciSlotNumber & 0xFFFF;
1651
1652 Adapter->NdisMiniportBlock.SlotNumber = SlotNumber.u.AsULONG;
1653 }
1654 NdisCloseConfiguration(ConfigHandle);
1655
1656 /* Set handlers (some NDIS macros require these) */
1657 Adapter->NdisMiniportBlock.EthRxCompleteHandler = EthFilterDprIndicateReceiveComplete;
1658 Adapter->NdisMiniportBlock.EthRxIndicateHandler = EthFilterDprIndicateReceive;
1659 Adapter->NdisMiniportBlock.SendCompleteHandler = MiniSendComplete;
1660 Adapter->NdisMiniportBlock.SendResourcesHandler = MiniSendResourcesAvailable;
1661 Adapter->NdisMiniportBlock.ResetCompleteHandler = MiniResetComplete;
1662 Adapter->NdisMiniportBlock.TDCompleteHandler = MiniTransferDataComplete;
1663 Adapter->NdisMiniportBlock.PacketIndicateHandler= MiniIndicateReceivePacket;
1664 Adapter->NdisMiniportBlock.StatusHandler = MiniStatus;
1665 Adapter->NdisMiniportBlock.StatusCompleteHandler= MiniStatusComplete;
1666
1667 /*
1668 * Call MiniportInitialize.
1669 */
1670
1671 NDIS_DbgPrint(MID_TRACE, ("calling MiniportInitialize\n"));
1672 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.InitializeHandler)(
1673 &OpenErrorStatus, &SelectedMediumIndex, &MediaArray[0],
1674 MEDIA_ARRAY_SIZE, Adapter, (NDIS_HANDLE)&WrapperContext);
1675
1676 ZwClose(WrapperContext.RegistryHandle);
1677
1678 if (NdisStatus != NDIS_STATUS_SUCCESS ||
1679 SelectedMediumIndex >= MEDIA_ARRAY_SIZE)
1680 {
1681 NDIS_DbgPrint(MIN_TRACE, ("MiniportInitialize() failed for an adapter.\n"));
1682 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
1683 if (NdisStatus == NDIS_STATUS_SUCCESS) NdisStatus = NDIS_STATUS_FAILURE;
1684 return NdisStatus;
1685 }
1686
1687 Adapter->NdisMiniportBlock.MediaType = MediaArray[SelectedMediumIndex];
1688
1689 switch (Adapter->NdisMiniportBlock.MediaType)
1690 {
1691 case NdisMedium802_3:
1692 Adapter->MediumHeaderSize = 14; /* XXX figure out what to do about LLC */
1693 AddressOID = OID_802_3_CURRENT_ADDRESS;
1694 Adapter->AddressLength = ETH_LENGTH_OF_ADDRESS;
1695 NdisStatus = DoQueries(Adapter, AddressOID);
1696 if (NdisStatus == NDIS_STATUS_SUCCESS)
1697 {
1698 Success = EthCreateFilter(32, /* FIXME: Query this from miniport. */
1699 Adapter->Address.Type.Medium802_3,
1700 &Adapter->NdisMiniportBlock.EthDB);
1701 if (Success)
1702 ((PETHI_FILTER)Adapter->NdisMiniportBlock.EthDB)->Miniport = (PNDIS_MINIPORT_BLOCK)Adapter;
1703 else
1704 NdisStatus = NDIS_STATUS_RESOURCES;
1705 }
1706 break;
1707
1708 default:
1709 /* FIXME: Support other types of media */
1710 NDIS_DbgPrint(MIN_TRACE, ("error: unsupported media\n"));
1711 ASSERT(FALSE);
1712 /* FIXME - KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); */
1713 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
1714 return STATUS_UNSUCCESSFUL;
1715 }
1716
1717 if (NdisStatus != NDIS_STATUS_SUCCESS)
1718 {
1719 NDIS_DbgPrint(MAX_TRACE, ("couldn't create filter (%x)\n", NdisStatus));
1720 if (Adapter->LookaheadBuffer)
1721 {
1722 ExFreePool(Adapter->LookaheadBuffer);
1723 Adapter->LookaheadBuffer = NULL;
1724 }
1725 ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
1726 return NdisStatus;
1727 }
1728
1729 /* Check for a hang every two seconds if it wasn't set in MiniportInitialize */
1730 if (Adapter->NdisMiniportBlock.CheckForHangSeconds == 0)
1731 Adapter->NdisMiniportBlock.CheckForHangSeconds = 2;
1732
1733 Adapter->NdisMiniportBlock.OldPnPDeviceState = Adapter->NdisMiniportBlock.PnPDeviceState;
1734 Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceStarted;
1735
1736 Timeout.QuadPart = (LONGLONG)Adapter->NdisMiniportBlock.CheckForHangSeconds * -1000000;
1737 KeSetTimerEx(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Timer, Timeout,
1738 Adapter->NdisMiniportBlock.CheckForHangSeconds * 1000,
1739 &Adapter->NdisMiniportBlock.WakeUpDpcTimer.Dpc);
1740
1741 /* Put adapter in adapter list for this miniport */
1742 ExInterlockedInsertTailList(&Adapter->NdisMiniportBlock.DriverHandle->DeviceList, &Adapter->MiniportListEntry, &Adapter->NdisMiniportBlock.DriverHandle->Lock);
1743
1744 return STATUS_SUCCESS;
1745 }
1746
1747 \f
1748 NTSTATUS
1749 NTAPI
1750 NdisIPnPStopDevice(
1751 IN PDEVICE_OBJECT DeviceObject,
1752 PIRP Irp)
1753 /*
1754 * FUNCTION: Handle the PnP stop device event
1755 * ARGUMENTS:
1756 * DeviceObejct = Functional Device Object
1757 * Irp = IRP_MN_STOP_DEVICE I/O request packet
1758 * RETURNS:
1759 * Status of operation
1760 */
1761 {
1762 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
1763 KIRQL OldIrql;
1764
1765 /* Remove adapter from adapter list for this miniport */
1766 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.DriverHandle->Lock, &OldIrql);
1767 RemoveEntryList(&Adapter->MiniportListEntry);
1768 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.DriverHandle->Lock, OldIrql);
1769
1770 /* Remove adapter from global adapter list */
1771 KeAcquireSpinLock(&AdapterListLock, &OldIrql);
1772 RemoveEntryList(&Adapter->ListEntry);
1773 KeReleaseSpinLock(&AdapterListLock, OldIrql);
1774
1775 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.HaltHandler)(Adapter);
1776
1777 if (Adapter->LookaheadBuffer)
1778 {
1779 ExFreePool(Adapter->LookaheadBuffer);
1780 Adapter->LookaheadBuffer = NULL;
1781 }
1782 if (Adapter->NdisMiniportBlock.AllocatedResources)
1783 {
1784 ExFreePool(Adapter->NdisMiniportBlock.AllocatedResources);
1785 Adapter->NdisMiniportBlock.AllocatedResources = NULL;
1786 }
1787 if (Adapter->NdisMiniportBlock.AllocatedResourcesTranslated)
1788 {
1789 ExFreePool(Adapter->NdisMiniportBlock.AllocatedResourcesTranslated);
1790 Adapter->NdisMiniportBlock.AllocatedResourcesTranslated = NULL;
1791 }
1792
1793 Adapter->NdisMiniportBlock.OldPnPDeviceState = Adapter->NdisMiniportBlock.PnPDeviceState;
1794 Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceStopped;
1795
1796 KeCancelTimer(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Timer);
1797
1798 return STATUS_SUCCESS;
1799 }
1800
1801 \f
1802 NTSTATUS
1803 NTAPI
1804 NdisIDispatchPnp(
1805 IN PDEVICE_OBJECT DeviceObject,
1806 PIRP Irp)
1807 {
1808 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
1809 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
1810 NTSTATUS Status;
1811
1812 switch (Stack->MinorFunction)
1813 {
1814 case IRP_MN_START_DEVICE:
1815 Status = NdisIForwardIrpAndWait(Adapter, Irp);
1816 if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
1817 {
1818 Status = NdisIPnPStartDevice(DeviceObject, Irp);
1819 }
1820 Irp->IoStatus.Status = Status;
1821 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1822 break;
1823
1824 case IRP_MN_STOP_DEVICE:
1825 Status = NdisIForwardIrpAndWait(Adapter, Irp);
1826 if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
1827 {
1828 Status = NdisIPnPStopDevice(DeviceObject, Irp);
1829 }
1830 Irp->IoStatus.Status = Status;
1831 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1832 break;
1833
1834 case IRP_MN_QUERY_DEVICE_RELATIONS:
1835 Status = STATUS_NOT_SUPPORTED;
1836 Irp->IoStatus.Status = Status;
1837 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1838 break;
1839
1840 default:
1841 IoSkipCurrentIrpStackLocation(Irp);
1842 Status = IoCallDriver(Adapter->NdisMiniportBlock.NextDeviceObject, Irp);
1843 break;
1844 }
1845
1846 return Status;
1847 }
1848
1849 \f
1850 NTSTATUS
1851 NTAPI
1852 NdisIAddDevice(
1853 IN PDRIVER_OBJECT DriverObject,
1854 IN PDEVICE_OBJECT PhysicalDeviceObject)
1855 /*
1856 * FUNCTION: Create a device for an adapter found using PnP
1857 * ARGUMENTS:
1858 * DriverObject = Pointer to the miniport driver object
1859 * PhysicalDeviceObject = Pointer to the PDO for our adapter
1860 */
1861 {
1862 static const WCHAR ClassKeyName[] = {'C','l','a','s','s','\\'};
1863 static const WCHAR LinkageKeyName[] = {'\\','L','i','n','k','a','g','e',0};
1864 PNDIS_M_DRIVER_BLOCK Miniport;
1865 PNDIS_M_DRIVER_BLOCK *MiniportPtr;
1866 WCHAR *LinkageKeyBuffer;
1867 ULONG DriverKeyLength;
1868 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
1869 UNICODE_STRING ExportName;
1870 PDEVICE_OBJECT DeviceObject;
1871 PLOGICAL_ADAPTER Adapter;
1872 NTSTATUS Status;
1873
1874 /*
1875 * Gain the access to the miniport data structure first.
1876 */
1877
1878 MiniportPtr = IoGetDriverObjectExtension(DriverObject, (PVOID)TAG('D','I','M','N'));
1879 if (MiniportPtr == NULL)
1880 {
1881 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't get driver object extension.\n"));
1882 return STATUS_UNSUCCESSFUL;
1883 }
1884 Miniport = *MiniportPtr;
1885
1886 /*
1887 * Get name of the Linkage registry key for our adapter. It's located under
1888 * the driver key for our driver and so we have basicly two ways to do it.
1889 * Either we can use IoOpenDriverRegistryKey or compose it using information
1890 * gathered by IoGetDeviceProperty. I choosed the second because
1891 * IoOpenDriverRegistryKey wasn't implemented at the time of writing.
1892 */
1893
1894 Status = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyDriverKeyName,
1895 0, NULL, &DriverKeyLength);
1896 if (Status != STATUS_BUFFER_TOO_SMALL && Status != STATUS_BUFFER_OVERFLOW && Status != STATUS_SUCCESS)
1897 {
1898 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't get miniport driver key length.\n"));
1899 return Status;
1900 }
1901
1902 LinkageKeyBuffer = ExAllocatePool(PagedPool, DriverKeyLength +
1903 sizeof(ClassKeyName) + sizeof(LinkageKeyName));
1904 if (LinkageKeyBuffer == NULL)
1905 {
1906 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't allocate memory for driver key name.\n"));
1907 return STATUS_INSUFFICIENT_RESOURCES;
1908 }
1909
1910 Status = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyDriverKeyName,
1911 DriverKeyLength, LinkageKeyBuffer +
1912 (sizeof(ClassKeyName) / sizeof(WCHAR)),
1913 &DriverKeyLength);
1914 if (!NT_SUCCESS(Status))
1915 {
1916 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't get miniport driver key.\n"));
1917 ExFreePool(LinkageKeyBuffer);
1918 return Status;
1919 }
1920
1921 /* Compose the linkage key name. */
1922 RtlCopyMemory(LinkageKeyBuffer, ClassKeyName, sizeof(ClassKeyName));
1923 RtlCopyMemory(LinkageKeyBuffer + ((sizeof(ClassKeyName) + DriverKeyLength) /
1924 sizeof(WCHAR)) - 1, LinkageKeyName, sizeof(LinkageKeyName));
1925
1926 NDIS_DbgPrint(DEBUG_MINIPORT, ("LinkageKey: %S.\n", LinkageKeyBuffer));
1927
1928 /*
1929 * Now open the linkage key and read the "Export" and "RootDevice" values
1930 * which contains device name and root service respectively.
1931 */
1932
1933 RtlZeroMemory(QueryTable, sizeof(QueryTable));
1934 RtlInitUnicodeString(&ExportName, NULL);
1935 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
1936 QueryTable[0].Name = L"Export";
1937 QueryTable[0].EntryContext = &ExportName;
1938
1939 Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, LinkageKeyBuffer,
1940 QueryTable, NULL, NULL);
1941 ExFreePool(LinkageKeyBuffer);
1942 if (!NT_SUCCESS(Status))
1943 {
1944 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't get miniport device name. (%x)\n", Status));
1945 return Status;
1946 }
1947
1948 /*
1949 * Create the device object.
1950 */
1951
1952 NDIS_DbgPrint(MAX_TRACE, ("creating device %wZ\n", &ExportName));
1953
1954 Status = IoCreateDevice(Miniport->DriverObject, sizeof(LOGICAL_ADAPTER),
1955 &ExportName, FILE_DEVICE_PHYSICAL_NETCARD,
1956 0, FALSE, &DeviceObject);
1957 if (!NT_SUCCESS(Status))
1958 {
1959 NDIS_DbgPrint(MIN_TRACE, ("Could not create device object.\n"));
1960 RtlFreeUnicodeString(&ExportName);
1961 return Status;
1962 }
1963
1964 /*
1965 * Initialize the adapter structure.
1966 */
1967
1968 Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
1969 KeInitializeSpinLock(&Adapter->NdisMiniportBlock.Lock);
1970 InitializeListHead(&Adapter->ProtocolListHead);
1971 Adapter->NdisMiniportBlock.DriverHandle = Miniport;
1972
1973 Adapter->NdisMiniportBlock.MiniportName = ExportName;
1974
1975 Adapter->NdisMiniportBlock.DeviceObject = DeviceObject;
1976 Adapter->NdisMiniportBlock.PhysicalDeviceObject = PhysicalDeviceObject;
1977 Adapter->NdisMiniportBlock.NextDeviceObject =
1978 IoAttachDeviceToDeviceStack(Adapter->NdisMiniportBlock.DeviceObject,
1979 PhysicalDeviceObject);
1980
1981 Adapter->NdisMiniportBlock.OldPnPDeviceState = 0;
1982 Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceAdded;
1983
1984 KeInitializeTimer(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Timer);
1985 KeInitializeDpc(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Dpc, MiniportHangDpc, Adapter);
1986 KeInitializeDpc(&Adapter->NdisMiniportBlock.DeferredDpc, MiniportDpc, Adapter);
1987
1988 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
1989
1990 return STATUS_SUCCESS;
1991 }
1992
1993 \f
1994 /*
1995 * @implemented
1996 */
1997 NDIS_STATUS
1998 EXPORT
1999 NdisMRegisterMiniport(
2000 IN NDIS_HANDLE NdisWrapperHandle,
2001 IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics,
2002 IN UINT CharacteristicsLength)
2003 /*
2004 * FUNCTION: Registers a miniport's MiniportXxx entry points with the NDIS library
2005 * ARGUMENTS:
2006 * NdisWrapperHandle = Pointer to handle returned by NdisMInitializeWrapper
2007 * MiniportCharacteristics = Pointer to a buffer with miniport characteristics
2008 * CharacteristicsLength = Number of bytes in characteristics buffer
2009 * RETURNS:
2010 * Status of operation
2011 */
2012 {
2013 UINT MinSize;
2014 PNDIS_M_DRIVER_BLOCK Miniport = GET_MINIPORT_DRIVER(NdisWrapperHandle);
2015 PNDIS_M_DRIVER_BLOCK *MiniportPtr;
2016 NTSTATUS Status;
2017
2018 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
2019
2020 switch (MiniportCharacteristics->MajorNdisVersion)
2021 {
2022 case 0x03:
2023 MinSize = sizeof(NDIS30_MINIPORT_CHARACTERISTICS);
2024 break;
2025
2026 case 0x04:
2027 MinSize = sizeof(NDIS40_MINIPORT_CHARACTERISTICS);
2028 break;
2029
2030 case 0x05:
2031 MinSize = sizeof(NDIS50_MINIPORT_CHARACTERISTICS);
2032 break;
2033
2034 default:
2035 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics version.\n"));
2036 return NDIS_STATUS_BAD_VERSION;
2037 }
2038
2039 if (CharacteristicsLength < MinSize)
2040 {
2041 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
2042 return NDIS_STATUS_BAD_CHARACTERISTICS;
2043 }
2044
2045 /* Check if mandatory MiniportXxx functions are specified */
2046 if ((!MiniportCharacteristics->HaltHandler) ||
2047 (!MiniportCharacteristics->InitializeHandler)||
2048 (!MiniportCharacteristics->QueryInformationHandler) ||
2049 (!MiniportCharacteristics->ResetHandler) ||
2050 (!MiniportCharacteristics->SetInformationHandler))
2051 {
2052 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
2053 return NDIS_STATUS_BAD_CHARACTERISTICS;
2054 }
2055
2056 if (MiniportCharacteristics->MajorNdisVersion == 0x03)
2057 {
2058 if (!MiniportCharacteristics->SendHandler)
2059 {
2060 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
2061 return NDIS_STATUS_BAD_CHARACTERISTICS;
2062 }
2063 }
2064 else if (MiniportCharacteristics->MajorNdisVersion >= 0x04)
2065 {
2066 /* NDIS 4.0+ */
2067 if ((!MiniportCharacteristics->SendHandler) &&
2068 (!MiniportCharacteristics->SendPacketsHandler))
2069 {
2070 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
2071 return NDIS_STATUS_BAD_CHARACTERISTICS;
2072 }
2073 }
2074
2075 /* TODO: verify NDIS5 and NDIS5.1 */
2076
2077 RtlCopyMemory(&Miniport->MiniportCharacteristics, MiniportCharacteristics, MinSize);
2078
2079 /*
2080 * NOTE: This is VERY unoptimal! Should we store the NDIS_M_DRIVER_BLOCK
2081 * structure in the driver extension or what?
2082 */
2083
2084 Status = IoAllocateDriverObjectExtension(Miniport->DriverObject, (PVOID)TAG('D','I','M','N'),
2085 sizeof(PNDIS_M_DRIVER_BLOCK), (PVOID*)&MiniportPtr);
2086 if (!NT_SUCCESS(Status))
2087 {
2088 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't allocate driver object extension.\n"));
2089 return NDIS_STATUS_RESOURCES;
2090 }
2091
2092 *MiniportPtr = Miniport;
2093
2094 Miniport->DriverObject->MajorFunction[IRP_MJ_PNP] = NdisIDispatchPnp;
2095 Miniport->DriverObject->DriverExtension->AddDevice = NdisIAddDevice;
2096
2097 return NDIS_STATUS_SUCCESS;
2098 }
2099
2100 \f
2101 /*
2102 * @implemented
2103 */
2104 #undef NdisMResetComplete
2105 VOID
2106 EXPORT
2107 NdisMResetComplete(
2108 IN NDIS_HANDLE MiniportAdapterHandle,
2109 IN NDIS_STATUS Status,
2110 IN BOOLEAN AddressingReset)
2111 {
2112 MiniResetComplete(MiniportAdapterHandle, Status, AddressingReset);
2113 }
2114
2115 \f
2116 /*
2117 * @implemented
2118 */
2119 #undef NdisMSendComplete
2120 VOID
2121 EXPORT
2122 NdisMSendComplete(
2123 IN NDIS_HANDLE MiniportAdapterHandle,
2124 IN PNDIS_PACKET Packet,
2125 IN NDIS_STATUS Status)
2126 /*
2127 * FUNCTION: Forwards a message to the initiating protocol saying
2128 * that a packet was handled
2129 * ARGUMENTS:
2130 * NdisAdapterHandle = Handle input to MiniportInitialize
2131 * Packet = Pointer to NDIS packet that was sent
2132 * Status = Status of send operation
2133 */
2134 {
2135 MiniSendComplete(MiniportAdapterHandle, Packet, Status);
2136 }
2137
2138 \f
2139 /*
2140 * @implemented
2141 */
2142 #undef NdisMSendResourcesAvailable
2143 VOID
2144 EXPORT
2145 NdisMSendResourcesAvailable(
2146 IN NDIS_HANDLE MiniportAdapterHandle)
2147 {
2148 MiniSendResourcesAvailable(MiniportAdapterHandle);
2149 }
2150
2151 \f
2152 /*
2153 * @implemented
2154 */
2155 #undef NdisMTransferDataComplete
2156 VOID
2157 EXPORT
2158 NdisMTransferDataComplete(
2159 IN NDIS_HANDLE MiniportAdapterHandle,
2160 IN PNDIS_PACKET Packet,
2161 IN NDIS_STATUS Status,
2162 IN UINT BytesTransferred)
2163 {
2164 MiniTransferDataComplete(MiniportAdapterHandle, Packet, Status, BytesTransferred);
2165 }
2166
2167 \f
2168 /*
2169 * @implemented
2170 */
2171 #undef NdisMSetInformationComplete
2172 VOID
2173 EXPORT
2174 NdisMSetInformationComplete(
2175 IN NDIS_HANDLE MiniportAdapterHandle,
2176 IN NDIS_STATUS Status)
2177 {
2178 PLOGICAL_ADAPTER Adapter =
2179 (PLOGICAL_ADAPTER)MiniportAdapterHandle;
2180 KIRQL OldIrql;
2181 ASSERT(Adapter);
2182 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
2183 (Adapter->NdisMiniportBlock.SetCompleteHandler)(MiniportAdapterHandle, Status);
2184 KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
2185 Adapter->MiniportBusy = FALSE;
2186 KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
2187 KeLowerIrql(OldIrql);
2188 }
2189
2190 \f
2191 /*
2192 * @implemented
2193 */
2194 #undef NdisMSetAttributes
2195 VOID
2196 EXPORT
2197 NdisMSetAttributes(
2198 IN NDIS_HANDLE MiniportAdapterHandle,
2199 IN NDIS_HANDLE MiniportAdapterContext,
2200 IN BOOLEAN BusMaster,
2201 IN NDIS_INTERFACE_TYPE AdapterType)
2202 /*
2203 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
2204 * ARGUMENTS:
2205 * MiniportAdapterHandle = Handle input to MiniportInitialize
2206 * MiniportAdapterContext = Pointer to context information
2207 * BusMaster = Specifies TRUE if the caller's NIC is a busmaster DMA device
2208 * AdapterType = Specifies the I/O bus interface of the caller's NIC
2209 */
2210 {
2211 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
2212 NdisMSetAttributesEx(MiniportAdapterHandle, MiniportAdapterContext, 0,
2213 BusMaster ? NDIS_ATTRIBUTE_BUS_MASTER : 0,
2214 AdapterType);
2215 }
2216
2217 \f
2218 /*
2219 * @implemented
2220 */
2221 VOID
2222 EXPORT
2223 NdisMSetAttributesEx(
2224 IN NDIS_HANDLE MiniportAdapterHandle,
2225 IN NDIS_HANDLE MiniportAdapterContext,
2226 IN UINT CheckForHangTimeInSeconds OPTIONAL,
2227 IN ULONG AttributeFlags,
2228 IN NDIS_INTERFACE_TYPE AdapterType)
2229 /*
2230 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
2231 * ARGUMENTS:
2232 * MiniportAdapterHandle = Handle input to MiniportInitialize
2233 * MiniportAdapterContext = Pointer to context information
2234 * CheckForHangTimeInSeconds = Specifies interval in seconds at which
2235 * MiniportCheckForHang should be called
2236 * AttributeFlags = Bitmask that indicates specific attributes
2237 * AdapterType = Specifies the I/O bus interface of the caller's NIC
2238 */
2239 {
2240 PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
2241
2242 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
2243
2244 Adapter->NdisMiniportBlock.MiniportAdapterContext = MiniportAdapterContext;
2245 Adapter->NdisMiniportBlock.Flags = AttributeFlags;
2246 Adapter->NdisMiniportBlock.AdapterType = AdapterType;
2247 if (CheckForHangTimeInSeconds > 0)
2248 Adapter->NdisMiniportBlock.CheckForHangSeconds = CheckForHangTimeInSeconds;
2249 if (AttributeFlags & NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER)
2250 NDIS_DbgPrint(MAX_TRACE, ("Intermediate drivers not supported yet.\n"));
2251 }
2252
2253 \f
2254 /*
2255 * @implemented
2256 */
2257 VOID
2258 EXPORT
2259 NdisMSleep(
2260 IN ULONG MicrosecondsToSleep)
2261 /*
2262 * FUNCTION: delay the thread's execution for MicrosecondsToSleep
2263 * ARGUMENTS:
2264 * MicrosecondsToSleep: duh...
2265 * NOTES:
2266 * - Because this is a blocking call, current IRQL must be < DISPATCH_LEVEL
2267 */
2268 {
2269 KTIMER Timer;
2270 LARGE_INTEGER DueTime;
2271
2272 PAGED_CODE();
2273
2274 DueTime.QuadPart = (-1) * 10 * MicrosecondsToSleep;
2275
2276 KeInitializeTimer(&Timer);
2277 KeSetTimer(&Timer, DueTime, 0);
2278 KeWaitForSingleObject(&Timer, Executive, KernelMode, FALSE, 0);
2279 }
2280
2281 \f
2282 /*
2283 * @implemented
2284 */
2285 BOOLEAN
2286 EXPORT
2287 NdisMSynchronizeWithInterrupt(
2288 IN PNDIS_MINIPORT_INTERRUPT Interrupt,
2289 IN PVOID SynchronizeFunction,
2290 IN PVOID SynchronizeContext)
2291 {
2292 return(KeSynchronizeExecution(Interrupt->InterruptObject,
2293 (PKSYNCHRONIZE_ROUTINE)SynchronizeFunction,
2294 SynchronizeContext));
2295 }
2296
2297 \f
2298 /*
2299 * @unimplemented
2300 */
2301 NDIS_STATUS
2302 EXPORT
2303 NdisMWriteLogData(
2304 IN NDIS_HANDLE LogHandle,
2305 IN PVOID LogBuffer,
2306 IN UINT LogBufferSize)
2307 {
2308 PUCHAR Buffer = LogBuffer;
2309 UINT i, j, idx;
2310
2311 UNIMPLEMENTED;
2312 for (i = 0; i < LogBufferSize; i += 16)
2313 {
2314 DbgPrint("%08x |", i);
2315 for (j = 0; j < 16; j++)
2316 {
2317 idx = i + j;
2318 if (idx < LogBufferSize)
2319 DbgPrint(" %02x", Buffer[idx]);
2320 else
2321 DbgPrint(" ");
2322 }
2323 DbgPrint(" | ");
2324 for (j = 0; j < 16; j++)
2325 {
2326 idx = i + j;
2327 if (idx == LogBufferSize)
2328 break;
2329 if (Buffer[idx] >= ' ') /* FIXME: not portable! replace by if (isprint(Buffer[idx])) ? */
2330 DbgPrint("%c", Buffer[idx]);
2331 else
2332 DbgPrint(".");
2333 }
2334 DbgPrint("\n");
2335 }
2336
2337 return NDIS_STATUS_FAILURE;
2338 }
2339
2340 \f
2341 /*
2342 * @implemented
2343 */
2344 VOID
2345 EXPORT
2346 NdisTerminateWrapper(
2347 IN NDIS_HANDLE NdisWrapperHandle,
2348 IN PVOID SystemSpecific)
2349 /*
2350 * FUNCTION: Releases resources allocated by a call to NdisInitializeWrapper
2351 * ARGUMENTS:
2352 * NdisWrapperHandle = Handle returned by NdisInitializeWrapper (NDIS_M_DRIVER_BLOCK)
2353 * SystemSpecific = Always NULL
2354 */
2355 {
2356 PNDIS_M_DRIVER_BLOCK Miniport = GET_MINIPORT_DRIVER(NdisWrapperHandle);
2357
2358 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
2359
2360 ExFreePool(Miniport->RegistryPath->Buffer);
2361 ExFreePool(Miniport->RegistryPath);
2362 ExFreePool(Miniport);
2363 }
2364
2365 /* EOF */
2366