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