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