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