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