31f34a711af11d11bb7eea2b27c48cdb13e1bb9c
[reactos.git] / reactos / drivers / net / 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 #include <roscfg.h>
14 #include "ndissys.h"
15
16 #ifdef DBG
17 #include <buffer.h>
18 #endif /* DBG */
19
20 /* Root of the scm database */
21 #define SERVICES_ROOT L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
22
23 /*
24 * Define to 1 to get a debugger breakpoint at the end of NdisInitializeWrapper
25 * for each new miniport starting up
26 */
27 #define BREAK_ON_MINIPORT_INIT 0
28
29 /*
30 * This has to be big enough to hold the results of querying the Route value
31 * from the Linkage key. Please re-code me to determine this dynamically.
32 */
33 #define ROUTE_DATA_SIZE 256
34
35 /* Number of media we know */
36 #define MEDIA_ARRAY_SIZE 15
37
38 static NDIS_MEDIUM MediaArray[MEDIA_ARRAY_SIZE] =
39 {
40 NdisMedium802_3,
41 NdisMedium802_5,
42 NdisMediumFddi,
43 NdisMediumWan,
44 NdisMediumLocalTalk,
45 NdisMediumDix,
46 NdisMediumArcnetRaw,
47 NdisMediumArcnet878_2,
48 NdisMediumAtm,
49 NdisMediumWirelessWan,
50 NdisMediumIrda,
51 NdisMediumBpc,
52 NdisMediumCoWan,
53 NdisMedium1394,
54 NdisMediumMax
55 };
56
57 /* global list and lock of Miniports NDIS has registered */
58 LIST_ENTRY MiniportListHead;
59 KSPIN_LOCK MiniportListLock;
60
61 /* global list and lock of adapters NDIS has registered */
62 LIST_ENTRY AdapterListHead;
63 KSPIN_LOCK AdapterListLock;
64
65 VOID
66 MiniDisplayPacket(
67 PNDIS_PACKET Packet)
68 {
69 //#ifdef DBG
70 #if 0
71 ULONG i, Length;
72 UCHAR Buffer[64];
73 if ((DebugTraceLevel | DEBUG_PACKET) > 0) {
74 Length = CopyPacketToBuffer(
75 (PUCHAR)&Buffer,
76 Packet,
77 0,
78 64);
79
80 DbgPrint("*** PACKET START ***");
81
82 for (i = 0; i < Length; i++) {
83 if (i % 12 == 0)
84 DbgPrint("\n%04X ", i);
85 DbgPrint("%02X ", Buffer[i]);
86 }
87
88 DbgPrint("*** PACKET STOP ***\n");
89 }
90 #endif /* DBG */
91 }
92
93 VOID
94 MiniDisplayPacket2(
95 PVOID HeaderBuffer,
96 UINT HeaderBufferSize,
97 PVOID LookaheadBuffer,
98 UINT LookaheadBufferSize)
99 {
100 #ifdef DBG
101 if ((DebugTraceLevel | DEBUG_PACKET) > 0) {
102 ULONG i, Length;
103 PUCHAR p;
104
105 DbgPrint("*** RECEIVE PACKET START ***\n");
106 DbgPrint("HEADER:");
107 p = HeaderBuffer;
108 for (i = 0; i < HeaderBufferSize; i++) {
109 if (i % 16 == 0)
110 DbgPrint("\n%04X ", i);
111 DbgPrint("%02X ", *p);
112 *(ULONG_PTR*)p += 1;
113 }
114
115 DbgPrint("\nFRAME:");
116
117 p = LookaheadBuffer;
118 Length = (LookaheadBufferSize < 64)? LookaheadBufferSize : 64;
119 for (i = 0; i < Length; i++) {
120 if (i % 16 == 0)
121 DbgPrint("\n%04X ", i);
122 DbgPrint("%02X ", *p);
123 *(ULONG_PTR*)p += 1;
124 }
125
126 DbgPrint("\n*** RECEIVE PACKET STOP ***\n");
127 }
128 #endif /* DBG */
129 }
130
131 \f
132 VOID
133 MiniIndicateData(
134 PLOGICAL_ADAPTER Adapter,
135 NDIS_HANDLE MacReceiveContext,
136 PVOID HeaderBuffer,
137 UINT HeaderBufferSize,
138 PVOID LookaheadBuffer,
139 UINT LookaheadBufferSize,
140 UINT PacketSize)
141 /*
142 * FUNCTION: Indicate received data to bound protocols
143 * ARGUMENTS:
144 * Adapter = Pointer to logical adapter
145 * MacReceiveContext = MAC receive context handle
146 * HeaderBuffer = Pointer to header buffer
147 * HeaderBufferSize = Size of header buffer
148 * LookaheadBuffer = Pointer to lookahead buffer
149 * LookaheadBufferSize = Size of lookahead buffer
150 * PacketSize = Total size of received packet
151 */
152 {
153 /* KIRQL OldIrql; */
154 PLIST_ENTRY CurrentEntry;
155 PADAPTER_BINDING AdapterBinding;
156
157 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called. Adapter (0x%X) HeaderBuffer (0x%X) "
158 "HeaderBufferSize (0x%X) LookaheadBuffer (0x%X) LookaheadBufferSize (0x%X).\n",
159 Adapter, HeaderBuffer, HeaderBufferSize, LookaheadBuffer, LookaheadBufferSize));
160
161 MiniDisplayPacket2(HeaderBuffer, HeaderBufferSize, LookaheadBuffer, LookaheadBufferSize);
162
163 /*
164 * XXX Think about this. This is probably broken. Spinlocks are
165 * taken out for now until i comprehend the Right Way to do this.
166 *
167 * This used to acquire the MiniportBlock spinlock and hold it until
168 * just before the call to ReceiveHandler. It would then release and
169 * subsequently re-acquire the lock.
170 *
171 * I don't see how this does any good, as it would seem he's just
172 * trying to protect the packet list. If someobdy else dequeues
173 * a packet, we are in fact in bad shape, but we don't want to
174 * necessarily call the receive handler at elevated irql either.
175 *
176 * therefore: We *are* going to call the receive handler at high irql
177 * (due to holding the lock) for now, and eventually we have to
178 * figure out another way to protect this packet list.
179 *
180 * UPDATE: this is busted; this results in a recursive lock acquisition.
181 */
182 //NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
183 //KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
184 {
185 CurrentEntry = Adapter->ProtocolListHead.Flink;
186 NDIS_DbgPrint(DEBUG_MINIPORT, ("CurrentEntry = %x\n", CurrentEntry));
187
188 if (CurrentEntry == &Adapter->ProtocolListHead)
189 {
190 NDIS_DbgPrint(DEBUG_MINIPORT, ("WARNING: No upper protocol layer.\n"));
191 }
192
193 while (CurrentEntry != &Adapter->ProtocolListHead)
194 {
195 AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
196 NDIS_DbgPrint(DEBUG_MINIPORT, ("AdapterBinding = %x\n", AdapterBinding));
197
198 /* see above */
199 /* KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); */
200
201 #ifdef DBG
202 if(!AdapterBinding)
203 {
204 NDIS_DbgPrint(MIN_TRACE, ("AdapterBinding was null\n"));
205 break;
206 }
207
208 if(!AdapterBinding->ProtocolBinding)
209 {
210 NDIS_DbgPrint(MIN_TRACE, ("AdapterBinding->ProtocolBinding was null\n"));
211 break;
212 }
213
214 if(!AdapterBinding->ProtocolBinding->Chars.u4.ReceiveHandler)
215 {
216 NDIS_DbgPrint(MIN_TRACE, ("AdapterBinding->ProtocolBinding->Chars.u4.ReceiveHandler was null\n"));
217 break;
218 }
219 #endif
220
221 NDIS_DbgPrint
222 (MID_TRACE,
223 ("XXX (%x) %x %x %x %x %x %x %x XXX\n",
224 *AdapterBinding->ProtocolBinding->Chars.u4.ReceiveHandler,
225 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
226 MacReceiveContext,
227 HeaderBuffer,
228 HeaderBufferSize,
229 LookaheadBuffer,
230 LookaheadBufferSize,
231 PacketSize));
232
233 /* call the receive handler */
234 (*AdapterBinding->ProtocolBinding->Chars.u4.ReceiveHandler)(
235 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
236 MacReceiveContext,
237 HeaderBuffer,
238 HeaderBufferSize,
239 LookaheadBuffer,
240 LookaheadBufferSize,
241 PacketSize);
242
243 /* see above */
244 /* KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql); */
245
246 CurrentEntry = CurrentEntry->Flink;
247 }
248 }
249 //KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
250
251 NDIS_DbgPrint(MAX_TRACE, ("Leaving.\n"));
252 }
253
254 \f
255 VOID STDCALL
256 MiniIndicateReceivePacket(
257 IN NDIS_HANDLE Miniport,
258 IN PPNDIS_PACKET PacketArray,
259 IN UINT NumberOfPackets)
260 /*
261 * FUNCTION: receives miniport packet array indications
262 * ARGUMENTS:
263 * Miniport: Miniport handle for the adapter
264 * PacketArray: pointer to a list of packet pointers to indicate
265 * NumberOfPackets: number of packets to indicate
266 * NOTES:
267 * - This currently is a big temporary hack. In the future this should
268 * call ProtocolReceivePacket() on each bound protocol if it exists.
269 * For now it just mimics NdisMEthIndicateReceive.
270 */
271 {
272 UINT i;
273
274 for(i = 0; i < NumberOfPackets; i++)
275 {
276 PCHAR PacketBuffer = 0;
277 UINT PacketLength = 0;
278 PNDIS_BUFFER NdisBuffer = 0;
279
280 #define PACKET_TAG (('k' << 24) + ('P' << 16) + ('D' << 8) + 'N')
281
282 NdisAllocateMemoryWithTag((PVOID)&PacketBuffer, 1518, PACKET_TAG);
283 if(!PacketBuffer)
284 {
285 NDIS_DbgPrint(MIN_TRACE, ("insufficient resources\n"));
286 return;
287 }
288
289 NdisQueryPacket(PacketArray[i], NULL, NULL, &NdisBuffer, NULL);
290
291 while(NdisBuffer)
292 {
293 PNDIS_BUFFER CurrentBuffer;
294 PVOID BufferVa;
295 UINT BufferLen;
296
297 NdisQueryBuffer(NdisBuffer, &BufferVa, &BufferLen);
298 memcpy(PacketBuffer + PacketLength, BufferVa, BufferLen);
299 PacketLength += BufferLen;
300
301 CurrentBuffer = NdisBuffer;
302 NdisGetNextBuffer(CurrentBuffer, &NdisBuffer);
303 }
304
305 NDIS_DbgPrint(MID_TRACE, ("indicating a %d-byte packet\n", PacketLength));
306
307 MiniIndicateData(Miniport, NULL, PacketBuffer, 14, PacketBuffer+14, PacketLength-14, PacketLength-14);
308
309 NdisFreeMemory(PacketBuffer, 0, 0);
310 }
311 }
312
313 \f
314 VOID STDCALL
315 MiniEthReceiveComplete(
316 IN PETH_FILTER Filter)
317 /*
318 * FUNCTION: Receive indication complete function for Ethernet devices
319 * ARGUMENTS:
320 * Filter = Pointer to Ethernet filter
321 */
322 {
323 KIRQL OldIrql;
324 PLIST_ENTRY CurrentEntry;
325 PLOGICAL_ADAPTER Adapter;
326 PADAPTER_BINDING AdapterBinding;
327
328 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
329
330 if( !Filter ) return;
331
332 Adapter = (PLOGICAL_ADAPTER)Filter->Miniport;
333
334 NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
335 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
336 {
337 CurrentEntry = Adapter->ProtocolListHead.Flink;
338
339 while (CurrentEntry != &Adapter->ProtocolListHead)
340 {
341 AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
342
343 /* see comment in MiniIndicateData */
344 /* KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); */
345
346 (*AdapterBinding->ProtocolBinding->Chars.ReceiveCompleteHandler)(
347 AdapterBinding->NdisOpenBlock.ProtocolBindingContext);
348
349 /* see above */
350 /* KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql); */
351
352 CurrentEntry = CurrentEntry->Flink;
353 }
354 }
355 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
356 }
357
358 \f
359 VOID STDCALL
360 MiniEthReceiveIndication(
361 IN PETH_FILTER Filter,
362 IN NDIS_HANDLE MacReceiveContext,
363 IN PCHAR Address,
364 IN PVOID HeaderBuffer,
365 IN UINT HeaderBufferSize,
366 IN PVOID LookaheadBuffer,
367 IN UINT LookaheadBufferSize,
368 IN UINT PacketSize)
369 /*
370 * FUNCTION: Receive indication function for Ethernet devices
371 * ARGUMENTS:
372 * MiniportAdapter = Miniport Adapter Handle (PLOGICAL_ADAPTER)
373 * MacReceiveContext = MAC receive context handle
374 * Address = Pointer to destination Ethernet address
375 * HeaderBuffer = Pointer to Ethernet header buffer
376 * HeaderBufferSize = Size of Ethernet header buffer
377 * LookaheadBuffer = Pointer to lookahead buffer
378 * LookaheadBufferSize = Size of lookahead buffer
379 * PacketSize = Total size of received packet
380 */
381 {
382 MiniIndicateData((PLOGICAL_ADAPTER)Filter->Miniport,
383 MacReceiveContext,
384 HeaderBuffer,
385 HeaderBufferSize,
386 LookaheadBuffer,
387 LookaheadBufferSize,
388 PacketSize);
389 }
390
391 \f
392 VOID STDCALL
393 MiniResetComplete(
394 IN NDIS_HANDLE MiniportAdapterHandle,
395 IN NDIS_STATUS Status,
396 IN BOOLEAN AddressingReset)
397 {
398 UNIMPLEMENTED
399 }
400
401
402 VOID STDCALL
403 MiniSendComplete(
404 IN NDIS_HANDLE MiniportAdapterHandle,
405 IN PNDIS_PACKET Packet,
406 IN NDIS_STATUS Status)
407 /*
408 * FUNCTION: Forwards a message to the initiating protocol saying
409 * that a packet was handled
410 * ARGUMENTS:
411 * NdisAdapterHandle = Handle input to MiniportInitialize
412 * Packet = Pointer to NDIS packet that was sent
413 * Status = Status of send operation
414 */
415 {
416 PADAPTER_BINDING AdapterBinding;
417
418 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
419
420 AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[0];
421
422 (*AdapterBinding->ProtocolBinding->Chars.u2.SendCompleteHandler)(
423 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
424 Packet,
425 Status);
426 }
427
428
429 VOID STDCALL
430 MiniSendResourcesAvailable(
431 IN NDIS_HANDLE MiniportAdapterHandle)
432 {
433 UNIMPLEMENTED
434 }
435
436
437 VOID STDCALL
438 MiniTransferDataComplete(
439 IN NDIS_HANDLE MiniportAdapterHandle,
440 IN PNDIS_PACKET Packet,
441 IN NDIS_STATUS Status,
442 IN UINT BytesTransferred)
443 {
444 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
445 PADAPTER_BINDING AdapterBinding = Adapter->MiniportAdapterBinding;
446
447 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
448
449 (*AdapterBinding->ProtocolBinding->Chars.u3.TransferDataCompleteHandler)(
450 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
451 Packet,
452 Status,
453 BytesTransferred);
454 }
455
456 \f
457 BOOLEAN
458 MiniAdapterHasAddress(
459 PLOGICAL_ADAPTER Adapter,
460 PNDIS_PACKET Packet)
461 /*
462 * FUNCTION: Determines wether a packet has the same destination address as an adapter
463 * ARGUMENTS:
464 * Adapter = Pointer to logical adapter object
465 * Packet = Pointer to NDIS packet
466 * RETURNS:
467 * TRUE if the destination address is that of the adapter, FALSE if not
468 */
469 {
470 UINT Length;
471 PUCHAR Start1;
472 PUCHAR Start2;
473 PNDIS_BUFFER NdisBuffer;
474 UINT BufferLength;
475
476 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
477
478 #ifdef DBG
479 if(!Adapter)
480 {
481 NDIS_DbgPrint(MID_TRACE, ("Adapter object was null\n"));
482 return FALSE;
483 }
484
485 if(!Packet)
486 {
487 NDIS_DbgPrint(MID_TRACE, ("Packet was null\n"));
488 return FALSE;
489 }
490 #endif
491
492 NdisQueryPacket(Packet, NULL, NULL, &NdisBuffer, NULL);
493
494 if (!NdisBuffer)
495 {
496 NDIS_DbgPrint(MID_TRACE, ("Packet contains no buffers.\n"));
497 return FALSE;
498 }
499
500 NdisQueryBuffer(NdisBuffer, (PVOID)&Start2, &BufferLength);
501
502 /* FIXME: Should handle fragmented packets */
503
504 switch (Adapter->NdisMiniportBlock.MediaType)
505 {
506 case NdisMedium802_3:
507 Length = ETH_LENGTH_OF_ADDRESS;
508 /* Destination address is the first field */
509 break;
510
511 default:
512 NDIS_DbgPrint(MIN_TRACE, ("Adapter has unsupported media type (0x%X).\n", Adapter->NdisMiniportBlock.MediaType));
513 return FALSE;
514 }
515
516 if (BufferLength < Length)
517 {
518 NDIS_DbgPrint(MID_TRACE, ("Buffer is too small.\n"));
519 return FALSE;
520 }
521
522 Start1 = (PUCHAR)&Adapter->Address;
523 NDIS_DbgPrint(MAX_TRACE, ("packet address: %x:%x:%x:%x:%x:%x adapter address: %x:%x:%x:%x:%x:%x\n",
524 *((char *)Start1), *(((char *)Start1)+1), *(((char *)Start1)+2), *(((char *)Start1)+3), *(((char *)Start1)+4), *(((char *)Start1)+5),
525 *((char *)Start2), *(((char *)Start2)+1), *(((char *)Start2)+2), *(((char *)Start2)+3), *(((char *)Start2)+4), *(((char *)Start2)+5))
526 );
527
528 return (RtlCompareMemory((PVOID)Start1, (PVOID)Start2, Length) == Length);
529 }
530
531 \f
532 PLOGICAL_ADAPTER
533 MiniLocateDevice(
534 PNDIS_STRING AdapterName)
535 /*
536 * FUNCTION: Finds an adapter object by name
537 * ARGUMENTS:
538 * AdapterName = Pointer to name of adapter
539 * RETURNS:
540 * Pointer to logical adapter object, or NULL if none was found.
541 * If found, the adapter is referenced for the caller. The caller
542 * is responsible for dereferencing after use
543 */
544 {
545 KIRQL OldIrql;
546 PLIST_ENTRY CurrentEntry;
547 PLOGICAL_ADAPTER Adapter = 0;
548
549 ASSERT(AdapterName);
550
551 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
552
553 if(IsListEmpty(&AdapterListHead))
554 {
555 NDIS_DbgPrint(DEBUG_MINIPORT, ("No registered miniports for protocol to bind to\n"));
556 return NULL;
557 }
558
559 KeAcquireSpinLock(&AdapterListLock, &OldIrql);
560 {
561 do
562 {
563 CurrentEntry = AdapterListHead.Flink;
564
565 while (CurrentEntry != &AdapterListHead)
566 {
567 Adapter = CONTAINING_RECORD(CurrentEntry, LOGICAL_ADAPTER, ListEntry);
568
569 ASSERT(Adapter);
570
571 NDIS_DbgPrint(DEBUG_MINIPORT, ("AdapterName = %wZ\n", &AdapterName));
572 NDIS_DbgPrint(DEBUG_MINIPORT, ("DeviceName = %wZ\n", &Adapter->DeviceName));
573
574 if (RtlCompareUnicodeString(AdapterName, &Adapter->DeviceName, TRUE) == 0)
575 {
576 ReferenceObject(Adapter);
577 break;
578 }
579
580 CurrentEntry = CurrentEntry->Flink;
581 }
582 } while (0);
583 }
584 KeReleaseSpinLock(&AdapterListLock, OldIrql);
585
586 if(Adapter)
587 {
588 NDIS_DbgPrint(DEBUG_MINIPORT, ("Leaving. Adapter found at 0x%x\n", Adapter));
589 }
590 else
591 {
592 NDIS_DbgPrint(DEBUG_MINIPORT, ("Leaving (adapter not found).\n"));
593 }
594
595 return Adapter;
596 }
597
598 \f
599 NDIS_STATUS
600 MiniQueryInformation(
601 PLOGICAL_ADAPTER Adapter,
602 NDIS_OID Oid,
603 ULONG Size,
604 PULONG BytesWritten)
605 /*
606 * FUNCTION: Queries a logical adapter for properties
607 * ARGUMENTS:
608 * Adapter = Pointer to the logical adapter object to query
609 * Oid = Specifies the Object ID to query for
610 * Size = If non-zero overrides the length in the adapter object
611 * BytesWritten = Address of buffer to place number of bytes written
612 * NOTES:
613 * If the specified buffer is too small, a new buffer is allocated,
614 * and the query is attempted again
615 * RETURNS:
616 * Status of operation
617 * TODO:
618 * Is there any way to use the buffer provided by the protocol?
619 */
620 {
621 NDIS_STATUS NdisStatus;
622 ULONG BytesNeeded;
623
624 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
625
626 if (Adapter->QueryBufferLength == 0)
627 {
628 /* XXX is 32 the right number? */
629 Adapter->QueryBuffer = ExAllocatePool(NonPagedPool, (Size == 0)? 32 : Size);
630
631 if (!Adapter->QueryBuffer)
632 {
633 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
634 return NDIS_STATUS_RESOURCES;
635 }
636
637 /* ditto */
638 Adapter->QueryBufferLength = (Size == 0)? 32 : Size;
639 }
640
641 /* this is the third time i've seen this conditional */
642 BytesNeeded = (Size == 0)? Adapter->QueryBufferLength : Size;
643
644 /* call the miniport's queryinfo handler */
645 NdisStatus = (*Adapter->Miniport->Chars.QueryInformationHandler)(
646 Adapter->NdisMiniportBlock.MiniportAdapterContext,
647 Oid,
648 Adapter->QueryBuffer,
649 BytesNeeded,
650 BytesWritten,
651 &BytesNeeded);
652
653 /* XXX is status_pending part of success macro? */
654 if ((NT_SUCCESS(NdisStatus)) || (NdisStatus == NDIS_STATUS_PENDING))
655 {
656 NDIS_DbgPrint(DEBUG_MINIPORT, ("Miniport returned status (0x%X).\n", NdisStatus));
657 return NdisStatus;
658 }
659
660 if (NdisStatus == NDIS_STATUS_INVALID_LENGTH)
661 {
662 ExFreePool(Adapter->QueryBuffer);
663
664 Adapter->QueryBufferLength += BytesNeeded;
665 Adapter->QueryBuffer = ExAllocatePool(NonPagedPool, Adapter->QueryBufferLength);
666
667 if (!Adapter->QueryBuffer)
668 {
669 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
670 return NDIS_STATUS_RESOURCES;
671 }
672
673 NdisStatus = (*Adapter->Miniport->Chars.QueryInformationHandler)(
674 Adapter->NdisMiniportBlock.MiniportAdapterContext,
675 Oid,
676 Adapter->QueryBuffer,
677 Size,
678 BytesWritten,
679 &BytesNeeded);
680 }
681
682 return NdisStatus;
683 }
684
685 \f
686 NDIS_STATUS
687 FASTCALL
688 MiniQueueWorkItem(
689 PLOGICAL_ADAPTER Adapter,
690 NDIS_WORK_ITEM_TYPE WorkItemType,
691 PVOID WorkItemContext,
692 NDIS_HANDLE Initiator)
693 /*
694 * FUNCTION: Queues a work item for execution at a later time
695 * ARGUMENTS:
696 * Adapter = Pointer to the logical adapter object to queue work item on
697 * WorkItemType = Type of work item to queue
698 * WorkItemContext = Pointer to context information for work item
699 * Initiator = Pointer to ADAPTER_BINDING structure of initiating protocol
700 * NOTES:
701 * Adapter lock must be held when called
702 * RETURNS:
703 * Status of operation
704 */
705 {
706 PNDIS_MINIPORT_WORK_ITEM Item;
707
708 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
709
710 ASSERT(Adapter);
711
712 if (Adapter->WorkQueueLevel < NDIS_MINIPORT_WORK_QUEUE_SIZE - 1)
713 {
714 Item = &Adapter->WorkQueue[Adapter->WorkQueueLevel];
715 Adapter->WorkQueueLevel++;
716 }
717 else
718 {
719 Item = ExAllocatePool(NonPagedPool, sizeof(NDIS_MINIPORT_WORK_ITEM));
720 if (Item)
721 {
722 /* Set flag so we know that the buffer should be freed when work item is dequeued */
723 Item->Allocated = TRUE;
724 }
725 else
726 {
727 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
728 return NDIS_STATUS_RESOURCES;
729 }
730 }
731
732 Item->WorkItemType = WorkItemType;
733 Item->WorkItemContext = WorkItemContext;
734 Item->Initiator = Initiator;
735
736 /* safe due to adapter lock held */
737 Item->Link.Next = NULL;
738 if (!Adapter->WorkQueueHead)
739 {
740 Adapter->WorkQueueHead = Item;
741 Adapter->WorkQueueTail = Item;
742 }
743 else
744 {
745 Adapter->WorkQueueTail->Link.Next = (PSINGLE_LIST_ENTRY)Item;
746 Adapter->WorkQueueTail = Item;
747 }
748
749 KeInsertQueueDpc(&Adapter->MiniportDpc, NULL, NULL);
750
751 return NDIS_STATUS_SUCCESS;
752 }
753
754 \f
755 NDIS_STATUS
756 FASTCALL
757 MiniDequeueWorkItem(
758 PLOGICAL_ADAPTER Adapter,
759 NDIS_WORK_ITEM_TYPE *WorkItemType,
760 PVOID *WorkItemContext,
761 NDIS_HANDLE *Initiator)
762 /*
763 * FUNCTION: Dequeues a work item from the work queue of a logical adapter
764 * ARGUMENTS:
765 * Adapter = Pointer to the logical adapter object to dequeue work item from
766 * WorkItemType = Address of buffer for work item type
767 * WorkItemContext = Address of buffer for pointer to context information
768 * Initiator = Address of buffer for initiator of the work (ADAPTER_BINDING)
769 * NOTES:
770 * Adapter lock must be held when called
771 * RETURNS:
772 * Status of operation
773 */
774 {
775 PNDIS_MINIPORT_WORK_ITEM Item;
776
777 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
778
779 Item = Adapter->WorkQueueHead;
780
781 if (Item)
782 {
783 /* safe due to adapter lock held */
784 Adapter->WorkQueueHead = (PNDIS_MINIPORT_WORK_ITEM)Item->Link.Next;
785
786 if (Item == Adapter->WorkQueueTail)
787 Adapter->WorkQueueTail = NULL;
788
789 *WorkItemType = Item->WorkItemType;
790 *WorkItemContext = Item->WorkItemContext;
791 *Initiator = Item->Initiator;
792
793 if (Item->Allocated)
794 {
795 ExFreePool(Item);
796 }
797 else
798 {
799 Adapter->WorkQueueLevel--;
800 #ifdef DBG
801 if (Adapter->WorkQueueLevel < 0)
802 {
803 NDIS_DbgPrint(MIN_TRACE, ("Adapter->WorkQueueLevel is < 0 (should be >= 0).\n"));
804 }
805 #endif
806 }
807
808 return NDIS_STATUS_SUCCESS;
809 }
810
811 return NDIS_STATUS_FAILURE;
812 }
813
814 \f
815 NDIS_STATUS
816 MiniDoRequest(
817 PLOGICAL_ADAPTER Adapter,
818 PNDIS_REQUEST NdisRequest)
819 /*
820 * FUNCTION: Sends a request to a miniport
821 * ARGUMENTS:
822 * Adapter = Pointer to logical adapter object
823 * NdisRequest = Pointer to NDIS request structure describing request
824 * RETURNS:
825 * Status of operation
826 */
827 {
828 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
829
830 Adapter->NdisMiniportBlock.MediaRequest = NdisRequest;
831
832 switch (NdisRequest->RequestType)
833 {
834 case NdisRequestQueryInformation:
835 return (*Adapter->Miniport->Chars.QueryInformationHandler)(
836 Adapter->NdisMiniportBlock.MiniportAdapterContext,
837 NdisRequest->DATA.QUERY_INFORMATION.Oid,
838 NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
839 NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength,
840 (PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesWritten,
841 (PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded);
842 break;
843
844 case NdisRequestSetInformation:
845 return (*Adapter->Miniport->Chars.SetInformationHandler)(
846 Adapter->NdisMiniportBlock.MiniportAdapterContext,
847 NdisRequest->DATA.SET_INFORMATION.Oid,
848 NdisRequest->DATA.SET_INFORMATION.InformationBuffer,
849 NdisRequest->DATA.SET_INFORMATION.InformationBufferLength,
850 (PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesRead,
851 (PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesNeeded);
852 break;
853
854 default:
855 return NDIS_STATUS_FAILURE;
856 }
857 }
858
859 \f
860 VOID STDCALL MiniportDpc(
861 IN PKDPC Dpc,
862 IN PVOID DeferredContext,
863 IN PVOID SystemArgument1,
864 IN PVOID SystemArgument2)
865 /*
866 * FUNCTION: Deferred routine to handle serialization
867 * ARGUMENTS:
868 * Dpc = Pointer to DPC object
869 * DeferredContext = Pointer to context information (LOGICAL_ADAPTER)
870 * SystemArgument1 = Unused
871 * SystemArgument2 = Unused
872 */
873 {
874 NDIS_STATUS NdisStatus;
875 PVOID WorkItemContext;
876 NDIS_WORK_ITEM_TYPE WorkItemType;
877 PADAPTER_BINDING AdapterBinding;
878 PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(DeferredContext);
879
880 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
881
882 /* XXX is adapter lock held here? should be... */
883 NdisStatus = MiniDequeueWorkItem(Adapter, &WorkItemType, &WorkItemContext, (PNDIS_HANDLE)&AdapterBinding);
884
885 if (NdisStatus == NDIS_STATUS_SUCCESS)
886 {
887 Adapter->MiniportAdapterBinding = AdapterBinding;
888
889 switch (WorkItemType)
890 {
891 case NdisWorkItemSend:
892 /*
893 * called by ProSend when protocols want to send packets to the miniport
894 */
895 #ifdef DBG
896 MiniDisplayPacket((PNDIS_PACKET)WorkItemContext);
897 #endif
898 if(Adapter->Miniport->Chars.SendPacketsHandler)
899 {
900 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
901
902 /*
903 * XXX assumes single-packet - prolly OK since we'll call something
904 * different on multi-packet sends
905 */
906 (*Adapter->Miniport->Chars.SendPacketsHandler)(
907 Adapter->NdisMiniportBlock.MiniportAdapterContext, (PPNDIS_PACKET)&WorkItemContext, 1);
908
909 NDIS_DbgPrint(MAX_TRACE, ("back from miniport's SendPackets handler\n"));
910 }
911 else
912 {
913 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
914
915 NdisStatus = (*Adapter->Miniport->Chars.u1.SendHandler)(
916 Adapter->NdisMiniportBlock.MiniportAdapterContext, (PNDIS_PACKET)WorkItemContext, 0);
917
918 NDIS_DbgPrint(MAX_TRACE, ("back from miniport's Send handler\n"));
919
920 if (NdisStatus != NDIS_STATUS_PENDING)
921 MiniSendComplete((NDIS_HANDLE)Adapter, (PNDIS_PACKET)WorkItemContext, NdisStatus);
922 }
923
924 break;
925
926 case NdisWorkItemSendLoopback:
927 /*
928 * called by ProSend when protocols want to send loopback packets
929 */
930 /* XXX atm ProIndicatePacket sends a packet up via the loopback adapter only */
931 NdisStatus = ProIndicatePacket(Adapter, (PNDIS_PACKET)WorkItemContext);
932 MiniSendComplete((NDIS_HANDLE)Adapter, (PNDIS_PACKET)WorkItemContext, NdisStatus);
933 break;
934
935 case NdisWorkItemReturnPackets:
936 break;
937
938 case NdisWorkItemResetRequested:
939 break;
940
941 case NdisWorkItemResetInProgress:
942 break;
943
944 case NdisWorkItemHalt:
945 break;
946
947 case NdisWorkItemMiniportCallback:
948 break;
949
950 case NdisWorkItemRequest:
951 NdisStatus = MiniDoRequest(Adapter, (PNDIS_REQUEST)WorkItemContext);
952
953 if (NdisStatus == NDIS_STATUS_PENDING)
954 break;
955
956 switch (((PNDIS_REQUEST)WorkItemContext)->RequestType)
957 {
958 case NdisRequestQueryInformation:
959 NdisMQueryInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
960 break;
961
962 case NdisRequestSetInformation:
963 NdisMSetInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
964 break;
965
966 default:
967 NDIS_DbgPrint(MIN_TRACE, ("Unknown NDIS request type.\n"));
968 break;
969 }
970 break;
971
972 default:
973 NDIS_DbgPrint(MIN_TRACE, ("Unknown NDIS work item type (%d).\n", WorkItemType));
974 break;
975 }
976 }
977 }
978
979 \f
980 /*
981 * @unimplemented
982 */
983 VOID
984 EXPORT
985 NdisMCloseLog(
986 IN NDIS_HANDLE LogHandle)
987 {
988 UNIMPLEMENTED
989 }
990
991 \f
992 /*
993 * @unimplemented
994 */
995 NDIS_STATUS
996 EXPORT
997 NdisMCreateLog(
998 IN NDIS_HANDLE MiniportAdapterHandle,
999 IN UINT Size,
1000 OUT PNDIS_HANDLE LogHandle)
1001 {
1002 UNIMPLEMENTED
1003
1004 return NDIS_STATUS_FAILURE;
1005 }
1006
1007 \f
1008 /*
1009 * @implemented
1010 */
1011 VOID
1012 EXPORT
1013 NdisMDeregisterAdapterShutdownHandler(
1014 IN NDIS_HANDLE MiniportHandle)
1015 /*
1016 * FUNCTION: de-registers a shutdown handler
1017 * ARGUMENTS: MiniportHandle: Handle passed into MiniportInitialize
1018 */
1019 {
1020 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
1021 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportHandle;
1022
1023 if(Adapter->BugcheckContext->ShutdownHandler)
1024 KeDeregisterBugCheckCallback(Adapter->BugcheckContext->CallbackRecord);
1025 }
1026
1027 \f
1028 /*
1029 * @unimplemented
1030 */
1031 VOID
1032 EXPORT
1033 NdisMFlushLog(
1034 IN NDIS_HANDLE LogHandle)
1035 {
1036 UNIMPLEMENTED
1037 }
1038
1039
1040 /*
1041 * @unimplemented
1042 */
1043 VOID
1044 EXPORT
1045 NdisMIndicateStatus(
1046 IN NDIS_HANDLE MiniportAdapterHandle,
1047 IN NDIS_STATUS GeneralStatus,
1048 IN PVOID StatusBuffer,
1049 IN UINT StatusBufferSize)
1050 {
1051 UNIMPLEMENTED
1052 }
1053
1054
1055 /*
1056 * @unimplemented
1057 */
1058 VOID
1059 EXPORT
1060 NdisMIndicateStatusComplete(
1061 IN NDIS_HANDLE MiniportAdapterHandle)
1062 {
1063 UNIMPLEMENTED
1064 }
1065
1066 \f
1067 /*
1068 * @implemented
1069 */
1070 VOID
1071 EXPORT
1072 NdisInitializeWrapper(
1073 OUT PNDIS_HANDLE NdisWrapperHandle,
1074 IN PVOID SystemSpecific1,
1075 IN PVOID SystemSpecific2,
1076 IN PVOID SystemSpecific3)
1077 /*
1078 * FUNCTION: Notifies the NDIS library that a new miniport is initializing
1079 * ARGUMENTS:
1080 * NdisWrapperHandle = Address of buffer to place NDIS wrapper handle
1081 * SystemSpecific1 = Pointer to the driver's driver object
1082 * SystemSpecific2 = Pointer to the driver's registry path
1083 * SystemSpecific3 = Always NULL
1084 * NOTES:
1085 * - SystemSpecific2 goes invalid so we copy it
1086 */
1087 {
1088 PMINIPORT_DRIVER Miniport;
1089 PUNICODE_STRING RegistryPath;
1090 WCHAR *RegistryBuffer;
1091
1092 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1093
1094 ASSERT(NdisWrapperHandle);
1095
1096 *NdisWrapperHandle = NULL;
1097
1098 #if BREAK_ON_MINIPORT_INIT
1099 __asm__ ("int $3\n");
1100 #endif
1101
1102 Miniport = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_DRIVER));
1103
1104 if (!Miniport)
1105 {
1106 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1107 return;
1108 }
1109
1110 RtlZeroMemory(Miniport, sizeof(MINIPORT_DRIVER));
1111
1112 KeInitializeSpinLock(&Miniport->Lock);
1113
1114 Miniport->RefCount = 1;
1115
1116 Miniport->DriverObject = (PDRIVER_OBJECT)SystemSpecific1;
1117
1118 /* set the miniport's driver registry path */
1119 RegistryPath = ExAllocatePool(PagedPool, sizeof(UNICODE_STRING));
1120 if(!RegistryPath)
1121 {
1122 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1123 return;
1124 }
1125
1126 RegistryPath->Length = ((PUNICODE_STRING)SystemSpecific2)->Length;
1127 RegistryPath->MaximumLength = RegistryPath->Length + sizeof(WCHAR); /* room for 0-term */
1128
1129 RegistryBuffer = ExAllocatePool(PagedPool, RegistryPath->MaximumLength);
1130 if(!RegistryBuffer)
1131 {
1132 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1133 return;
1134 }
1135
1136 RtlCopyMemory(RegistryBuffer, ((PUNICODE_STRING)SystemSpecific2)->Buffer, RegistryPath->Length);
1137 RegistryBuffer[RegistryPath->Length/sizeof(WCHAR)] = 0;
1138
1139 RegistryPath->Buffer = RegistryBuffer;
1140 Miniport->RegistryPath = RegistryPath;
1141
1142 InitializeListHead(&Miniport->AdapterListHead);
1143
1144 /* Put miniport in global miniport list */
1145 ExInterlockedInsertTailList(&MiniportListHead, &Miniport->ListEntry, &MiniportListLock);
1146
1147 *NdisWrapperHandle = Miniport;
1148 }
1149
1150 \f
1151 /*
1152 * @implemented
1153 */
1154 VOID
1155 EXPORT
1156 NdisMQueryInformationComplete(
1157 IN NDIS_HANDLE MiniportAdapterHandle,
1158 IN NDIS_STATUS Status)
1159 {
1160 PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
1161 PADAPTER_BINDING AdapterBinding = (PADAPTER_BINDING)Adapter->MiniportAdapterBinding;
1162
1163 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1164
1165 (*AdapterBinding->ProtocolBinding->Chars.RequestCompleteHandler)(
1166 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
1167 Adapter->NdisMiniportBlock.MediaRequest,
1168 Status);
1169 }
1170
1171 \f
1172 VOID STDCALL NdisIBugcheckCallback(
1173 IN PVOID Buffer,
1174 IN ULONG Length)
1175 /*
1176 * FUNCTION: Internal callback for handling bugchecks - calls adapter's shutdown handler
1177 * ARGUMENTS:
1178 * Buffer: Pointer to a bugcheck callback context
1179 * Length: Unused
1180 */
1181 {
1182 PMINIPORT_BUGCHECK_CONTEXT Context = (PMINIPORT_BUGCHECK_CONTEXT)Buffer;
1183 ADAPTER_SHUTDOWN_HANDLER sh = (ADAPTER_SHUTDOWN_HANDLER)Context->ShutdownHandler;
1184
1185 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
1186
1187 if(sh)
1188 sh(Context->DriverContext);
1189 }
1190
1191 \f
1192 /*
1193 * @implemented
1194 */
1195 VOID
1196 EXPORT
1197 NdisMRegisterAdapterShutdownHandler(
1198 IN NDIS_HANDLE MiniportHandle,
1199 IN PVOID ShutdownContext,
1200 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler)
1201 /*
1202 * FUNCTION: Register a shutdown handler for an adapter
1203 * ARGUMENTS:
1204 * MiniportHandle: Handle originally passed into MiniportInitialize
1205 * ShutdownContext: Pre-initialized bugcheck context
1206 * ShutdownHandler: Function to call to handle the bugcheck
1207 * NOTES:
1208 * - I'm not sure about ShutdownContext
1209 * - FIXME - memory leak below
1210 */
1211 {
1212 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportHandle;
1213 PMINIPORT_BUGCHECK_CONTEXT BugcheckContext = Adapter->BugcheckContext;
1214
1215 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
1216
1217 if(BugcheckContext)
1218 return;
1219
1220 BugcheckContext = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_BUGCHECK_CONTEXT));
1221 if(!BugcheckContext)
1222 {
1223 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1224 return;
1225 }
1226
1227 BugcheckContext->ShutdownHandler = ShutdownHandler;
1228 BugcheckContext->DriverContext = ShutdownContext;
1229
1230 /* not sure if this needs to be initialized or not... oh well, it's a leak. */
1231 BugcheckContext->CallbackRecord = ExAllocatePool(NonPagedPool, sizeof(KBUGCHECK_CALLBACK_RECORD));
1232
1233 KeRegisterBugCheckCallback(BugcheckContext->CallbackRecord, NdisIBugcheckCallback,
1234 BugcheckContext, sizeof(BugcheckContext), "Ndis Miniport");
1235 }
1236
1237 \f
1238 NDIS_STATUS
1239 DoQueries(
1240 PLOGICAL_ADAPTER Adapter,
1241 NDIS_OID AddressOID)
1242 /*
1243 * FUNCTION: Queries miniport for information
1244 * ARGUMENTS:
1245 * Adapter = Pointer to logical adapter
1246 * AddressOID = OID to use to query for current address
1247 * RETURNS:
1248 * Status of operation
1249 */
1250 {
1251 ULONG BytesWritten;
1252 NDIS_STATUS NdisStatus;
1253
1254 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1255
1256 /* Get MAC options for adapter */
1257 NdisStatus = MiniQueryInformation(Adapter, OID_GEN_MAC_OPTIONS, 0, &BytesWritten);
1258
1259 if (NdisStatus != NDIS_STATUS_SUCCESS)
1260 {
1261 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAC_OPTIONS failed. NdisStatus (0x%X).\n", NdisStatus));
1262 return NdisStatus;
1263 }
1264
1265 RtlCopyMemory(&Adapter->NdisMiniportBlock.MacOptions, Adapter->QueryBuffer, sizeof(UINT));
1266
1267 NDIS_DbgPrint(DEBUG_MINIPORT, ("MacOptions (0x%X).\n", Adapter->NdisMiniportBlock.MacOptions));
1268
1269 /* Get current hardware address of adapter */
1270 NdisStatus = MiniQueryInformation(Adapter, AddressOID, 0, &BytesWritten);
1271
1272 if (NdisStatus != NDIS_STATUS_SUCCESS)
1273 {
1274 NDIS_DbgPrint(MIN_TRACE, ("Address OID (0x%X) failed. NdisStatus (0x%X).\n", AddressOID, NdisStatus));
1275 return NdisStatus;
1276 }
1277
1278 RtlCopyMemory(&Adapter->Address, Adapter->QueryBuffer, Adapter->AddressLength);
1279 #ifdef DBG
1280 {
1281 /* 802.3 only */
1282
1283 PUCHAR A = (PUCHAR)&Adapter->Address.Type.Medium802_3;
1284
1285 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]));
1286 }
1287 #endif /* DBG */
1288
1289 /* Get maximum lookahead buffer size of adapter */
1290 NdisStatus = MiniQueryInformation(Adapter, OID_GEN_MAXIMUM_LOOKAHEAD, 0, &BytesWritten);
1291
1292 if (NdisStatus != NDIS_STATUS_SUCCESS)
1293 {
1294 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAXIMUM_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus));
1295 return NdisStatus;
1296 }
1297
1298 Adapter->MaxLookaheadLength = *((PULONG)Adapter->QueryBuffer);
1299
1300 NDIS_DbgPrint(DEBUG_MINIPORT, ("MaxLookaheadLength (0x%X).\n", Adapter->MaxLookaheadLength));
1301
1302 /* Get current lookahead buffer size of adapter */
1303 NdisStatus = MiniQueryInformation(Adapter, OID_GEN_CURRENT_LOOKAHEAD, 0, &BytesWritten);
1304
1305 if (NdisStatus != NDIS_STATUS_SUCCESS)
1306 {
1307 NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_CURRENT_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus));
1308 return NdisStatus;
1309 }
1310
1311 Adapter->CurLookaheadLength = *((PULONG)Adapter->QueryBuffer);
1312
1313 NDIS_DbgPrint(DEBUG_MINIPORT, ("CurLookaheadLength (0x%X).\n", Adapter->CurLookaheadLength));
1314
1315 if (Adapter->MaxLookaheadLength != 0)
1316 {
1317 Adapter->LookaheadLength = Adapter->MaxLookaheadLength + Adapter->MediumHeaderSize;
1318 Adapter->LookaheadBuffer = ExAllocatePool(NonPagedPool, Adapter->LookaheadLength);
1319
1320 if (!Adapter->LookaheadBuffer)
1321 return NDIS_STATUS_RESOURCES;
1322 }
1323
1324 return STATUS_SUCCESS;
1325 }
1326
1327 \f
1328 VOID
1329 NdisIStartAdapter(
1330 UNICODE_STRING *DeviceName,
1331 PDEVICE_OBJECT PhysicalDeviceObject,
1332 PMINIPORT_DRIVER Miniport
1333 )
1334 /*
1335 * FUNCTION: Start an adapter
1336 * ARGUMENTS:
1337 * DeviceName: Name of device to start
1338 * PhysicalDeviceObject: PDO for our adapter
1339 * NOTES:
1340 * TODO:
1341 * - verify that all resources are properly freed on success & failure
1342 * - break up this 250-line function
1343 */
1344 {
1345 HANDLE RegKeyHandle;
1346 NDIS_STATUS NdisStatus;
1347 NDIS_STATUS OpenErrorStatus;
1348 NTSTATUS Status;
1349 UINT SelectedMediumIndex = 0;
1350 PLOGICAL_ADAPTER Adapter = 0;
1351 NDIS_OID AddressOID;
1352 BOOLEAN MemError = FALSE;
1353 KIRQL OldIrql;
1354 ULONG Size;
1355
1356 Adapter = ExAllocatePool(NonPagedPool, sizeof(LOGICAL_ADAPTER));
1357 if (!Adapter)
1358 {
1359 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1360 return;
1361 }
1362
1363 /* This is very important */
1364 RtlZeroMemory(Adapter, sizeof(LOGICAL_ADAPTER));
1365
1366 Adapter->DeviceName.Buffer = ExAllocatePool(NonPagedPool, DeviceName->Length);
1367 if(!Adapter->DeviceName.Buffer)
1368 {
1369 NDIS_DbgPrint(MIN_TRACE,("Insufficient memory\n"));
1370 ExFreePool(Adapter);
1371 return;
1372 }
1373 Adapter->DeviceName.MaximumLength = DeviceName->Length;
1374 RtlCopyUnicodeString(&Adapter->DeviceName, DeviceName);
1375
1376 NDIS_DbgPrint(MAX_TRACE, ("creating device %wZ\n", DeviceName));
1377
1378 Status = IoCreateDevice(Miniport->DriverObject, 0, &Adapter->DeviceName, FILE_DEVICE_PHYSICAL_NETCARD,
1379 0, FALSE, &Adapter->NdisMiniportBlock.DeviceObject);
1380 if (!NT_SUCCESS(Status))
1381 {
1382 NDIS_DbgPrint(MIN_TRACE, ("Could not create device object.\n"));
1383 ExFreePool(Adapter);
1384 return;
1385 }
1386
1387 Status = IoOpenDeviceRegistryKey(PhysicalDeviceObject, PLUGPLAY_REGKEY_DRIVER,
1388 KEY_ALL_ACCESS, &RegKeyHandle);
1389 if(Status != STATUS_SUCCESS)
1390 {
1391 NDIS_DbgPrint(MIN_TRACE,("failed to open adapter-specific reg key\n"));
1392 ExFreePool(Adapter);
1393 return;
1394 }
1395
1396 NDIS_DbgPrint(MAX_TRACE, ("opened device reg key\n"));
1397
1398 NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
1399 KeInitializeSpinLock(&Adapter->NdisMiniportBlock.Lock);
1400 InitializeListHead(&Adapter->ProtocolListHead);
1401 Adapter->RefCount = 1;
1402 Adapter->Miniport = Miniport;
1403
1404 /* FIXME: Check return values. */
1405 Size = sizeof(ULONG);
1406 IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyLegacyBusType,
1407 Size, &Adapter->BusType, &Size);
1408 IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyBusNumber,
1409 Size, &Adapter->BusNumber, &Size);
1410 IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyAddress,
1411 Size, &Adapter->SlotNumber, &Size);
1412
1413 /* Set handlers (some NDIS macros require these) */
1414
1415 Adapter->NdisMiniportBlock.EthRxCompleteHandler = MiniEthReceiveComplete;
1416 Adapter->NdisMiniportBlock.EthRxIndicateHandler = MiniEthReceiveIndication;
1417 Adapter->NdisMiniportBlock.SendCompleteHandler = MiniSendComplete;
1418 Adapter->NdisMiniportBlock.SendResourcesHandler = MiniSendResourcesAvailable;
1419 Adapter->NdisMiniportBlock.ResetCompleteHandler = MiniResetComplete;
1420 Adapter->NdisMiniportBlock.TDCompleteHandler = MiniTransferDataComplete;
1421 Adapter->NdisMiniportBlock.PacketIndicateHandler= MiniIndicateReceivePacket;
1422
1423 KeInitializeDpc(&Adapter->MiniportDpc, MiniportDpc, (PVOID)Adapter);
1424
1425 /* Put adapter in adapter list for this miniport */
1426 ExInterlockedInsertTailList(&Miniport->AdapterListHead, &Adapter->MiniportListEntry, &Miniport->Lock);
1427
1428 /* Put adapter in global adapter list */
1429 ExInterlockedInsertTailList(&AdapterListHead, &Adapter->ListEntry, &AdapterListLock);
1430
1431 /* Call MiniportInitialize */
1432 NDIS_DbgPrint(MID_TRACE, ("calling MiniportInitialize\n"));
1433 NdisStatus = (*Miniport->Chars.InitializeHandler)( &OpenErrorStatus, &SelectedMediumIndex, &MediaArray[0],
1434 MEDIA_ARRAY_SIZE, Adapter, RegKeyHandle);
1435
1436 ZwClose(RegKeyHandle);
1437
1438 if ((NdisStatus == NDIS_STATUS_SUCCESS) && (SelectedMediumIndex < MEDIA_ARRAY_SIZE))
1439 {
1440 NDIS_DbgPrint(MID_TRACE,("successful return from MiniportInitialize\n"));
1441
1442 Adapter->NdisMiniportBlock.MediaType = MediaArray[SelectedMediumIndex];
1443
1444 switch (Adapter->NdisMiniportBlock.MediaType)
1445 {
1446 case NdisMedium802_3:
1447 Adapter->MediumHeaderSize = 14; /* XXX figure out what to do about LLC */
1448 AddressOID = OID_802_3_CURRENT_ADDRESS;
1449 Adapter->AddressLength = ETH_LENGTH_OF_ADDRESS;
1450
1451 Adapter->NdisMiniportBlock.FilterDbs.u.EthDB = ExAllocatePool(NonPagedPool, sizeof(ETH_FILTER));
1452 if (Adapter->NdisMiniportBlock.FilterDbs.u.EthDB)
1453 {
1454 RtlZeroMemory(Adapter->NdisMiniportBlock.FilterDbs.u.EthDB, sizeof(ETH_FILTER));
1455 Adapter->NdisMiniportBlock.FilterDbs.u.EthDB->Miniport = (PNDIS_MINIPORT_BLOCK)Adapter;
1456 }
1457 else
1458 MemError = TRUE;
1459
1460 break;
1461
1462 default:
1463 /* FIXME: Support other types of media */
1464 NDIS_DbgPrint(MIN_TRACE, ("error: unsupported media\n"));
1465 ExFreePool(Adapter);
1466 ASSERT(FALSE);
1467 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
1468 return;
1469 }
1470
1471 NdisStatus = DoQueries(Adapter, AddressOID);
1472 }
1473
1474 if ((MemError) || (NdisStatus != NDIS_STATUS_SUCCESS) || (SelectedMediumIndex >= MEDIA_ARRAY_SIZE))
1475 {
1476 NDIS_DbgPrint(MAX_TRACE, ("return from MiniportInitialize: NdisStatus 0x%x, SelectedMediumIndex 0x%x\n",
1477 NdisStatus, SelectedMediumIndex));
1478
1479 /* Remove adapter from adapter list for this miniport */
1480 KeAcquireSpinLock(&Miniport->Lock, &OldIrql);
1481 RemoveEntryList(&Adapter->MiniportListEntry);
1482 KeReleaseSpinLock(&Miniport->Lock, OldIrql);
1483
1484 /* Remove adapter from global adapter list */
1485 KeAcquireSpinLock(&AdapterListLock, &OldIrql);
1486 RemoveEntryList(&Adapter->ListEntry);
1487 KeReleaseSpinLock(&AdapterListLock, OldIrql);
1488
1489 if (Adapter->LookaheadBuffer)
1490 ExFreePool(Adapter->LookaheadBuffer);
1491
1492 IoDeleteDevice(Adapter->NdisMiniportBlock.DeviceObject);
1493 ExFreePool(Adapter);
1494 NDIS_DbgPrint(MIN_TRACE, ("MiniportInitialize() failed for an adapter.\n"));
1495 }
1496 else
1497 {
1498 IoAttachDeviceToDeviceStack(Adapter->NdisMiniportBlock.DeviceObject,
1499 PhysicalDeviceObject);
1500 }
1501 }
1502
1503 \f
1504 NTSTATUS
1505 STDCALL
1506 NdisIAddDevice(
1507 IN PDRIVER_OBJECT DriverObject,
1508 IN PDEVICE_OBJECT PhysicalDeviceObject
1509 )
1510 /*
1511 * FUNCTION: Start an adapter found using PnP
1512 * ARGUMENTS:
1513 * DriverObject = Pointer to the miniport driver object
1514 * PhysicalDeviceObject = Pointer to the PDO for our adapter
1515 */
1516 {
1517 static const WCHAR ClassKeyName[] = {'C','l','a','s','s','\\'};
1518 static const WCHAR LinkageKeyName[] = {'\\','L','i','n','k','a','g','e',0};
1519 PMINIPORT_DRIVER Miniport;
1520 PMINIPORT_DRIVER *MiniportPtr;
1521 WCHAR *LinkageKeyBuffer;
1522 ULONG DriverKeyLength;
1523 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
1524 UNICODE_STRING ExportName;
1525 NTSTATUS Status;
1526
1527 /*
1528 * Gain the access to the miniport data structure first.
1529 */
1530
1531 MiniportPtr = IoGetDriverObjectExtension(DriverObject, (PVOID)TAG('D','I','M','N'));
1532 if (MiniportPtr == NULL)
1533 {
1534 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't get driver object extension.\n"));
1535 return STATUS_UNSUCCESSFUL;
1536 }
1537 Miniport = *MiniportPtr;
1538
1539 /*
1540 * Get name of the Linkage registry key for our adapter. It's located under
1541 * the driver key for our driver and so we have basicly two ways to do it.
1542 * Either we can use IoOpenDriverRegistryKey or compose it using information
1543 * gathered by IoGetDeviceProperty. I choosed the second because
1544 * IoOpenDriverRegistryKey wasn't implemented at the time of writing.
1545 */
1546
1547 Status = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyDriverKeyName,
1548 0, NULL, &DriverKeyLength);
1549 if (Status != STATUS_BUFFER_TOO_SMALL)
1550 {
1551 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't get miniport driver key length.\n"));
1552 return Status;
1553 }
1554
1555 LinkageKeyBuffer = ExAllocatePool(PagedPool, DriverKeyLength +
1556 sizeof(ClassKeyName) + sizeof(LinkageKeyName));
1557 if (LinkageKeyBuffer == NULL)
1558 {
1559 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't allocate memory for driver key name.\n"));
1560 return STATUS_INSUFFICIENT_RESOURCES;
1561 }
1562
1563 Status = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyDriverKeyName,
1564 DriverKeyLength, LinkageKeyBuffer +
1565 (sizeof(ClassKeyName) / sizeof(WCHAR)),
1566 &DriverKeyLength);
1567 if (!NT_SUCCESS(Status))
1568 {
1569 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't get miniport driver key.\n"));
1570 ExFreePool(LinkageKeyBuffer);
1571 return Status;
1572 }
1573
1574 /* Compose the linkage key name. */
1575 RtlCopyMemory(LinkageKeyBuffer, ClassKeyName, sizeof(ClassKeyName));
1576 RtlCopyMemory(LinkageKeyBuffer + ((sizeof(ClassKeyName) + DriverKeyLength) /
1577 sizeof(WCHAR)) - 1, LinkageKeyName, sizeof(LinkageKeyName));
1578
1579 NDIS_DbgPrint(DEBUG_MINIPORT, ("LinkageKey: %S.\n", LinkageKeyBuffer));
1580
1581 /*
1582 * Now open the linkage key and read the "Export" and "RootDevice" values
1583 * which contains device name and root service respectively.
1584 */
1585
1586 RtlZeroMemory(QueryTable, sizeof(QueryTable));
1587 RtlInitUnicodeString(&ExportName, NULL);
1588 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
1589 QueryTable[0].Name = L"Export";
1590 QueryTable[0].EntryContext = &ExportName;
1591
1592 Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, LinkageKeyBuffer,
1593 QueryTable, NULL, NULL);
1594 if (!NT_SUCCESS(Status))
1595 {
1596 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't get miniport device name. (%x)\n", Status));
1597 ExFreePool(LinkageKeyBuffer);
1598 return Status;
1599 }
1600 ExFreePool(LinkageKeyBuffer);
1601
1602 NdisIStartAdapter(&ExportName, PhysicalDeviceObject, Miniport);
1603 RtlFreeUnicodeString(&ExportName);
1604
1605 return STATUS_SUCCESS;
1606 }
1607
1608 \f
1609 /*
1610 * @implemented
1611 */
1612 NDIS_STATUS
1613 EXPORT
1614 NdisMRegisterMiniport(
1615 IN NDIS_HANDLE NdisWrapperHandle,
1616 IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics,
1617 IN UINT CharacteristicsLength)
1618 /*
1619 * FUNCTION: Registers a miniport's MiniportXxx entry points with the NDIS library
1620 * ARGUMENTS:
1621 * NdisWrapperHandle = Pointer to handle returned by NdisMInitializeWrapper
1622 * MiniportCharacteristics = Pointer to a buffer with miniport characteristics
1623 * CharacteristicsLength = Number of bytes in characteristics buffer
1624 * RETURNS:
1625 * Status of operation
1626 */
1627 {
1628 UINT MinSize;
1629 PMINIPORT_DRIVER Miniport = GET_MINIPORT_DRIVER(NdisWrapperHandle);
1630 PMINIPORT_DRIVER *MiniportPtr;
1631 NTSTATUS Status;
1632
1633 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1634
1635 switch (MiniportCharacteristics->MajorNdisVersion)
1636 {
1637 case 0x03:
1638 MinSize = sizeof(NDIS30_MINIPORT_CHARACTERISTICS_S);
1639 break;
1640
1641 case 0x04:
1642 MinSize = sizeof(NDIS40_MINIPORT_CHARACTERISTICS_S);
1643 break;
1644
1645 case 0x05:
1646 MinSize = sizeof(NDIS50_MINIPORT_CHARACTERISTICS_S);
1647 break;
1648
1649 default:
1650 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics version.\n"));
1651 return NDIS_STATUS_BAD_VERSION;
1652 }
1653
1654 if (CharacteristicsLength < MinSize)
1655 {
1656 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
1657 return NDIS_STATUS_BAD_CHARACTERISTICS;
1658 }
1659
1660 /* Check if mandatory MiniportXxx functions are specified */
1661 if ((!MiniportCharacteristics->HaltHandler) ||
1662 (!MiniportCharacteristics->InitializeHandler)||
1663 (!MiniportCharacteristics->QueryInformationHandler) ||
1664 (!MiniportCharacteristics->ResetHandler) ||
1665 (!MiniportCharacteristics->SetInformationHandler))
1666 {
1667 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
1668 return NDIS_STATUS_BAD_CHARACTERISTICS;
1669 }
1670
1671 if (MiniportCharacteristics->MajorNdisVersion == 0x03)
1672 {
1673 if (!MiniportCharacteristics->u1.SendHandler)
1674 {
1675 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
1676 return NDIS_STATUS_BAD_CHARACTERISTICS;
1677 }
1678 }
1679 else if (MiniportCharacteristics->MajorNdisVersion >= 0x04)
1680 {
1681 /* NDIS 4.0+ */
1682 if ((!MiniportCharacteristics->u1.SendHandler) &&
1683 (!MiniportCharacteristics->SendPacketsHandler))
1684 {
1685 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
1686 return NDIS_STATUS_BAD_CHARACTERISTICS;
1687 }
1688 }
1689
1690 /* TODO: verify NDIS5 and NDIS5.1 */
1691
1692 RtlCopyMemory(&Miniport->Chars, MiniportCharacteristics, MinSize);
1693
1694 /*
1695 * NOTE: This is VERY unoptimal! Should we store the MINIPORT_DRIVER
1696 * struture in the driver extension or what?
1697 */
1698
1699 Status = IoAllocateDriverObjectExtension(Miniport->DriverObject, (PVOID)TAG('D','I','M','N'),
1700 sizeof(PMINIPORT_DRIVER), (PVOID*)&MiniportPtr);
1701 if (!NT_SUCCESS(Status))
1702 {
1703 NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't allocate driver object extension.\n"));
1704 return NDIS_STATUS_RESOURCES;
1705 }
1706
1707 *MiniportPtr = Miniport;
1708 Miniport->DriverObject->DriverExtension->AddDevice = NdisIAddDevice;
1709
1710 return NDIS_STATUS_SUCCESS;
1711 }
1712
1713 \f
1714 /*
1715 * @implemented
1716 */
1717 VOID
1718 EXPORT
1719 NdisMResetComplete(
1720 IN NDIS_HANDLE MiniportAdapterHandle,
1721 IN NDIS_STATUS Status,
1722 IN BOOLEAN AddressingReset)
1723 {
1724 MiniResetComplete(MiniportAdapterHandle, Status, AddressingReset);
1725 }
1726
1727 \f
1728 /*
1729 * @implemented
1730 */
1731 VOID
1732 EXPORT
1733 NdisMSendComplete(
1734 IN NDIS_HANDLE MiniportAdapterHandle,
1735 IN PNDIS_PACKET Packet,
1736 IN NDIS_STATUS Status)
1737 /*
1738 * FUNCTION: Forwards a message to the initiating protocol saying
1739 * that a packet was handled
1740 * ARGUMENTS:
1741 * NdisAdapterHandle = Handle input to MiniportInitialize
1742 * Packet = Pointer to NDIS packet that was sent
1743 * Status = Status of send operation
1744 */
1745 {
1746 MiniSendComplete(MiniportAdapterHandle, Packet, Status);
1747 }
1748
1749 \f
1750 /*
1751 * @implemented
1752 */
1753 VOID
1754 EXPORT
1755 NdisMSendResourcesAvailable(
1756 IN NDIS_HANDLE MiniportAdapterHandle)
1757 {
1758 MiniSendResourcesAvailable(MiniportAdapterHandle);
1759 }
1760
1761 \f
1762 /*
1763 * @implemented
1764 */
1765 VOID
1766 EXPORT
1767 NdisMTransferDataComplete(
1768 IN NDIS_HANDLE MiniportAdapterHandle,
1769 IN PNDIS_PACKET Packet,
1770 IN NDIS_STATUS Status,
1771 IN UINT BytesTransferred)
1772 {
1773 MiniTransferDataComplete(MiniportAdapterHandle, Packet, Status, BytesTransferred);
1774 }
1775
1776 \f
1777 /*
1778 * @implemented
1779 */
1780 VOID
1781 EXPORT
1782 NdisMSetInformationComplete(
1783 IN NDIS_HANDLE MiniportAdapterHandle,
1784 IN NDIS_STATUS Status)
1785 {
1786 PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
1787 PADAPTER_BINDING AdapterBinding = (PADAPTER_BINDING)Adapter->MiniportAdapterBinding;
1788
1789 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1790
1791 (*AdapterBinding->ProtocolBinding->Chars.RequestCompleteHandler)(
1792 AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
1793 Adapter->NdisMiniportBlock.MediaRequest,
1794 Status);
1795 }
1796
1797 \f
1798 /*
1799 * @implemented
1800 */
1801 VOID
1802 EXPORT
1803 NdisMSetAttributes(
1804 IN NDIS_HANDLE MiniportAdapterHandle,
1805 IN NDIS_HANDLE MiniportAdapterContext,
1806 IN BOOLEAN BusMaster,
1807 IN NDIS_INTERFACE_TYPE AdapterType)
1808 /*
1809 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
1810 * ARGUMENTS:
1811 * MiniportAdapterHandle = Handle input to MiniportInitialize
1812 * MiniportAdapterContext = Pointer to context information
1813 * BusMaster = Specifies TRUE if the caller's NIC is a busmaster DMA device
1814 * AdapterType = Specifies the I/O bus interface of the caller's NIC
1815 */
1816 {
1817 PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
1818
1819 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1820
1821 Adapter->NdisMiniportBlock.MiniportAdapterContext = MiniportAdapterContext;
1822
1823 if(BusMaster)
1824 Adapter->NdisMiniportBlock.Flags |= NDIS_ATTRIBUTE_BUS_MASTER;
1825
1826 Adapter->NdisMiniportBlock.AdapterType = AdapterType;
1827 Adapter->AttributesSet = TRUE;
1828 }
1829
1830 \f
1831 /*
1832 * @implemented
1833 */
1834 VOID
1835 EXPORT
1836 NdisMSetAttributesEx(
1837 IN NDIS_HANDLE MiniportAdapterHandle,
1838 IN NDIS_HANDLE MiniportAdapterContext,
1839 IN UINT CheckForHangTimeInSeconds OPTIONAL,
1840 IN ULONG AttributeFlags,
1841 IN NDIS_INTERFACE_TYPE AdapterType)
1842 /*
1843 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
1844 * ARGUMENTS:
1845 * MiniportAdapterHandle = Handle input to MiniportInitialize
1846 * MiniportAdapterContext = Pointer to context information
1847 * CheckForHangTimeInSeconds = Specifies interval in seconds at which
1848 * MiniportCheckForHang should be called
1849 * AttributeFlags = Bitmask that indicates specific attributes
1850 * AdapterType = Specifies the I/O bus interface of the caller's NIC
1851 */
1852 {
1853 /* TODO: Take CheckForHandTimeInSeconds into account! */
1854
1855 PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
1856
1857 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1858
1859 Adapter->NdisMiniportBlock.MiniportAdapterContext = MiniportAdapterContext;
1860 Adapter->NdisMiniportBlock.Flags = AttributeFlags;
1861 Adapter->NdisMiniportBlock.AdapterType = AdapterType;
1862 Adapter->AttributesSet = TRUE;
1863 if (AttributeFlags & NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER)
1864 NDIS_DbgPrint(MAX_TRACE, ("Intermediate drivers not supported yet.\n"));
1865 }
1866
1867 \f
1868 /*
1869 * @implemented
1870 */
1871 VOID
1872 EXPORT
1873 NdisMSleep(
1874 IN ULONG MicrosecondsToSleep)
1875 /*
1876 * FUNCTION: delay the thread's execution for MicrosecondsToSleep
1877 * ARGUMENTS:
1878 * MicrosecondsToSleep: duh...
1879 * NOTES:
1880 * - Because this is a blocking call, current IRQL must be < DISPATCH_LEVEL
1881 */
1882 {
1883 KTIMER Timer;
1884 LARGE_INTEGER DueTime;
1885
1886 PAGED_CODE();
1887
1888 DueTime.QuadPart = (-1) * 10 * MicrosecondsToSleep;
1889
1890 KeInitializeTimer(&Timer);
1891 KeSetTimer(&Timer, DueTime, 0);
1892 KeWaitForSingleObject(&Timer, Executive, KernelMode, FALSE, 0);
1893 }
1894
1895 \f
1896 /*
1897 * @implemented
1898 */
1899 BOOLEAN
1900 EXPORT
1901 NdisMSynchronizeWithInterrupt(
1902 IN PNDIS_MINIPORT_INTERRUPT Interrupt,
1903 IN PVOID SynchronizeFunction,
1904 IN PVOID SynchronizeContext)
1905 {
1906 return(KeSynchronizeExecution((PKINTERRUPT)Interrupt,
1907 (PKSYNCHRONIZE_ROUTINE)SynchronizeFunction,
1908 SynchronizeContext));
1909 }
1910
1911 \f
1912 /*
1913 * @unimplemented
1914 */
1915 NDIS_STATUS
1916 EXPORT
1917 NdisMWriteLogData(
1918 IN NDIS_HANDLE LogHandle,
1919 IN PVOID LogBuffer,
1920 IN UINT LogBufferSize)
1921 {
1922 UNIMPLEMENTED
1923
1924 return NDIS_STATUS_FAILURE;
1925 }
1926
1927 \f
1928 /*
1929 * @implemented
1930 */
1931 VOID
1932 EXPORT
1933 NdisTerminateWrapper(
1934 IN NDIS_HANDLE NdisWrapperHandle,
1935 IN PVOID SystemSpecific)
1936 /*
1937 * FUNCTION: Releases resources allocated by a call to NdisInitializeWrapper
1938 * ARGUMENTS:
1939 * NdisWrapperHandle = Handle returned by NdisInitializeWrapper (MINIPORT_DRIVER)
1940 * SystemSpecific = Always NULL
1941 */
1942 {
1943 PMINIPORT_DRIVER Miniport = GET_MINIPORT_DRIVER(NdisWrapperHandle);
1944
1945 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1946
1947 ExFreePool(Miniport->RegistryPath->Buffer);
1948 ExFreePool(Miniport->RegistryPath);
1949 ExFreePool(Miniport);
1950 }
1951
1952 /* EOF */
1953