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