Delete all Trailing spaces in code.
[reactos.git] / reactos / drivers / network / ndis / ndis / protocol.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NDIS library
4 * FILE: ndis/protocol.c
5 * PURPOSE: Routines used by NDIS protocol drivers
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Vizzini (vizzini@plasmic.com)
8 * REVISIONS:
9 * CSH 01/08-2000 Created
10 * 09-13-2003 Vizzini Updates for SendPackets support
11 */
12
13 #include "ndissys.h"
14 #include <buffer.h>
15
16 #define SERVICES_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
17 #define LINKAGE_KEY L"\\Linkage"
18 #define PARAMETERS_KEY L"\\Parameters\\"
19
20 LIST_ENTRY ProtocolListHead;
21 KSPIN_LOCK ProtocolListLock;
22
23 \f
24 /*
25 * @implemented
26 */
27 VOID
28 EXPORT
29 NdisCompleteBindAdapter(
30 IN NDIS_HANDLE BindAdapterContext,
31 IN NDIS_STATUS Status,
32 IN NDIS_STATUS OpenStatus)
33 /*
34 * FUNCTION: Indicates a packet to bound protocols
35 * ARGUMENTS:
36 * Adapter = Pointer to logical adapter
37 * Packet = Pointer to packet to indicate
38 * RETURNS:
39 * Status of operation
40 * NOTES:
41 * - FIXME: partially-implemented
42 */
43 {
44 PROTOCOL_BINDING *Protocol = (PROTOCOL_BINDING *)BindAdapterContext;
45
46 /* Put protocol binding struct on global list */
47 ExInterlockedInsertTailList(&ProtocolListHead, &Protocol->ListEntry, &ProtocolListLock);
48 }
49
50 \f
51 NDIS_STATUS
52 ProIndicatePacket(
53 PLOGICAL_ADAPTER Adapter,
54 PNDIS_PACKET Packet)
55 /*
56 * FUNCTION: Indicates a packet to bound protocols
57 * ARGUMENTS:
58 * Adapter = Pointer to logical adapter
59 * Packet = Pointer to packet to indicate
60 * RETURNS:
61 * STATUS_SUCCESS in all cases
62 * NOTES:
63 * - XXX ATM, this only handles loopback packets - is that its designed function?
64 */
65 {
66 KIRQL OldIrql;
67 UINT BufferedLength;
68 UINT PacketLength;
69
70 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
71
72 #ifdef DBG
73 MiniDisplayPacket(Packet);
74 #endif
75
76 NdisQueryPacket(Packet, NULL, NULL, NULL, &PacketLength);
77
78 NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
79 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
80 {
81 Adapter->NdisMiniportBlock.IndicatedPacket[KeGetCurrentProcessorNumber()] = Packet;
82 BufferedLength = CopyPacketToBuffer(Adapter->LookaheadBuffer, Packet, 0, Adapter->NdisMiniportBlock.CurrentLookahead);
83 }
84 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
85
86 if (BufferedLength > Adapter->MediumHeaderSize)
87 {
88 /* XXX Change this to call SendPackets so we don't have to duplicate this wacky logic */
89 MiniIndicateData(Adapter, NULL, Adapter->LookaheadBuffer, Adapter->MediumHeaderSize,
90 &Adapter->LookaheadBuffer[Adapter->MediumHeaderSize], BufferedLength - Adapter->MediumHeaderSize,
91 PacketLength - Adapter->MediumHeaderSize);
92 }
93 else
94 {
95 MiniIndicateData(Adapter, NULL, Adapter->LookaheadBuffer, Adapter->MediumHeaderSize, NULL, 0, 0);
96 }
97
98 NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
99 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
100 {
101 Adapter->NdisMiniportBlock.IndicatedPacket[KeGetCurrentProcessorNumber()] = NULL;
102 }
103 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
104
105 return STATUS_SUCCESS;
106 }
107
108 \f
109 NDIS_STATUS NTAPI
110 ProRequest(
111 IN NDIS_HANDLE MacBindingHandle,
112 IN PNDIS_REQUEST NdisRequest)
113 /*
114 * FUNCTION: Forwards a request to an NDIS miniport
115 * ARGUMENTS:
116 * MacBindingHandle = Adapter binding handle
117 * NdisRequest = Pointer to request to perform
118 * RETURNS:
119 * Status of operation
120 */
121 {
122 KIRQL OldIrql;
123 BOOLEAN QueueWorkItem = FALSE;
124 NDIS_STATUS NdisStatus;
125 PADAPTER_BINDING AdapterBinding;
126 PLOGICAL_ADAPTER Adapter;
127 PNDIS_REQUEST_MAC_BLOCK MacBlock = (PNDIS_REQUEST_MAC_BLOCK)NdisRequest->MacReserved;
128
129 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
130
131 ASSERT(MacBindingHandle);
132 AdapterBinding = GET_ADAPTER_BINDING(MacBindingHandle);
133
134 ASSERT(AdapterBinding->Adapter);
135 Adapter = AdapterBinding->Adapter;
136
137 MacBlock->Binding = &AdapterBinding->NdisOpenBlock;
138
139 /*
140 * If the miniport is already busy, queue a workitem
141 */
142 NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
143 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
144 {
145 if(Adapter->MiniportBusy)
146 QueueWorkItem = TRUE;
147 else
148 {
149 NDIS_DbgPrint(MAX_TRACE, ("Setting adapter 0x%x to busy\n"));
150 Adapter->MiniportBusy = TRUE;
151 }
152 }
153
154 /* MiniQueueWorkItem must be called at IRQL >= DISPATCH_LEVEL */
155 if (QueueWorkItem)
156 {
157 MiniQueueWorkItem(Adapter, NdisWorkItemRequest, (PVOID)NdisRequest);
158 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
159 return NDIS_STATUS_PENDING;
160 }
161
162 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
163
164 /* MiniportQueryInformation (called by MiniDoRequest) runs at DISPATCH_LEVEL */
165 /* TODO (?): move the irql raise into MiniDoRequest */
166 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
167 {
168 NdisStatus = MiniDoRequest(&Adapter->NdisMiniportBlock, NdisRequest);
169
170 NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
171 KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
172 {
173 NDIS_DbgPrint(MAX_TRACE, ("Setting adapter 0x%x to free\n"));
174 Adapter->MiniportBusy = FALSE;
175
176 if (Adapter->WorkQueueHead)
177 KeInsertQueueDpc(&Adapter->NdisMiniportBlock.DeferredDpc, NULL, NULL);
178 }
179 KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
180 }
181 KeLowerIrql(OldIrql);
182
183 return NdisStatus;
184 }
185
186 \f
187 NDIS_STATUS NTAPI
188 ProReset(
189 IN NDIS_HANDLE MacBindingHandle)
190 {
191 UNIMPLEMENTED
192
193 return NDIS_STATUS_FAILURE;
194 }
195
196 \f
197 NDIS_STATUS NTAPI
198 ProSend(
199 IN NDIS_HANDLE MacBindingHandle,
200 IN PNDIS_PACKET Packet)
201 /*
202 * FUNCTION: Forwards a request to send a packet to an NDIS miniport
203 * ARGUMENTS:
204 * MacBindingHandle = Adapter binding handle
205 * Packet = Pointer to NDIS packet descriptor
206 * RETURNS:
207 * NDIS_STATUS_SUCCESS always
208 * NOTES:
209 * TODO:
210 * - Fix return values
211 * - Should queue packet if miniport returns NDIS_STATUS_RESOURCES
212 * - Queue packets directly on the adapters when possible (i.e.
213 * when miniports not busy)
214 * - Break this up
215 */
216 {
217 KIRQL RaiseOldIrql, SpinOldIrql;
218 BOOLEAN QueueWorkItem = FALSE;
219 NDIS_STATUS NdisStatus;
220 PADAPTER_BINDING AdapterBinding;
221 PLOGICAL_ADAPTER Adapter;
222
223 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
224
225 ASSERT(MacBindingHandle);
226 AdapterBinding = GET_ADAPTER_BINDING(MacBindingHandle);
227
228 ASSERT(AdapterBinding);
229 Adapter = AdapterBinding->Adapter;
230
231 ASSERT(Adapter);
232
233 /* if the following is not true, KeRaiseIrql() below will break */
234 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
235
236 /* XXX what is this crazy black magic? */
237 Packet->Reserved[0] = (ULONG_PTR)MacBindingHandle;
238
239 /*
240 * Acquire this lock in order to see if the miniport is busy.
241 * If it is not busy, we mark it as busy and release the lock.
242 * Else we don't do anything because we have to queue a workitem
243 * anyway.
244 */
245 NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
246 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &SpinOldIrql);
247 {
248 /*
249 * if the miniport is marked as busy, we queue the packet as a work item,
250 * else we send the packet directly to the miniport. Sending to the miniport
251 * makes it busy.
252 */
253 if (Adapter->MiniportBusy)
254 QueueWorkItem = TRUE;
255 else
256 {
257 NDIS_DbgPrint(MAX_TRACE, ("Setting adapter 0x%x to busy\n"));
258 Adapter->MiniportBusy = TRUE;
259 }
260 }
261 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, SpinOldIrql);
262
263 /*
264 * Test the packet to see if it is a MAC loopback.
265 *
266 * We may have to loop this packet if miniport cannot.
267 * If dest MAC address of packet == MAC address of adapter,
268 * this is a loopback frame.
269 */
270 if ((Adapter->NdisMiniportBlock.MacOptions & NDIS_MAC_OPTION_NO_LOOPBACK) &&
271 MiniAdapterHasAddress(Adapter, Packet))
272 {
273 NDIS_DbgPrint(MIN_TRACE, ("Looping packet.\n"));
274
275 if (QueueWorkItem)
276 {
277 MiniQueueWorkItem(Adapter, NdisWorkItemSendLoopback, (PVOID)Packet);
278 return NDIS_STATUS_PENDING;
279 }
280
281 KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
282 {
283 /*
284 * atm this *only* handles loopback packets - it calls MiniIndicateData to
285 * send back to the protocol. FIXME: this will need to be adjusted a bit.
286 * Also, I'm not sure you really have to be at dispatch level for this. It
287 * might use a ReceivePackets handler, which can run <= DISPATCH_LEVEL.
288 */
289 NdisStatus = ProIndicatePacket(Adapter, Packet);
290
291 NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
292 KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
293 {
294 NDIS_DbgPrint(MAX_TRACE, ("Setting adapter 0x%x to free\n"));
295 Adapter->MiniportBusy = FALSE;
296
297 if (Adapter->WorkQueueHead)
298 KeInsertQueueDpc(&Adapter->NdisMiniportBlock.DeferredDpc, NULL, NULL);
299 else
300 NDIS_DbgPrint(MID_TRACE,("Failed to insert packet into work queue\n"));
301 }
302 KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
303 }
304 KeLowerIrql(RaiseOldIrql);
305
306 return NdisStatus;
307 }
308 else
309 NDIS_DbgPrint(MID_TRACE,("Not a loopback packet\n"));
310
311 /* This is a normal send packet, not a loopback packet. */
312 if (QueueWorkItem)
313 {
314 MiniQueueWorkItem(Adapter, NdisWorkItemSend, (PVOID)Packet);
315 NDIS_DbgPrint(MAX_TRACE, ("Queued a work item and returning\n"));
316 return NDIS_STATUS_PENDING;
317 }
318
319 ASSERT(Adapter->NdisMiniportBlock.DriverHandle);
320
321 /*
322 * Call the appropriate send handler
323 *
324 * If a miniport provides a SendPackets handler, we always call it. If not, we call the
325 * Send handler.
326 */
327 if(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)
328 {
329 if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
330 {
331 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
332 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
333 Adapter->NdisMiniportBlock.MiniportAdapterContext, &Packet, 1);
334 }
335 else
336 {
337 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
338 KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
339 {
340 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
341 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
342 Adapter->NdisMiniportBlock.MiniportAdapterContext, &Packet, 1);
343 }
344 KeLowerIrql(RaiseOldIrql);
345 }
346
347 /* SendPackets handlers return void - they always "succeed" */
348 NdisStatus = NDIS_STATUS_SUCCESS;
349 }
350 else
351 {
352 /* XXX FIXME THIS IS WRONG */
353 /* uh oh... forgot why i thought that... */
354 if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
355 {
356 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
357 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
358 Adapter->NdisMiniportBlock.MiniportAdapterContext, Packet, 0);
359 NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n"));
360 }
361 else
362 {
363 /* Send handlers always run at DISPATCH_LEVEL so we raise here */
364 KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
365
366 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
367 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
368 Adapter->NdisMiniportBlock.MiniportAdapterContext, Packet, 0);
369 NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n"));
370 if( NdisStatus != NDIS_STATUS_PENDING ) {
371 Adapter->MiniportBusy = FALSE;
372 }
373 KeLowerIrql(RaiseOldIrql);
374 }
375 }
376
377 /* XXX why the hell do we do this? */
378 NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
379 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &SpinOldIrql);
380 {
381 if (Adapter->WorkQueueHead)
382 {
383 KeInsertQueueDpc(&Adapter->NdisMiniportBlock.DeferredDpc, NULL, NULL);
384 NDIS_DbgPrint(MAX_TRACE, ("MiniportDpc queued; returning NDIS_STATUS_SUCCESS\n"));
385 }
386 }
387 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, SpinOldIrql);
388
389 NDIS_DbgPrint(MAX_TRACE, ("returning 0x%x\n", NdisStatus));
390 return NdisStatus;
391 }
392
393 \f
394 VOID NTAPI
395 ProSendPackets(
396 IN NDIS_HANDLE NdisBindingHandle,
397 IN PPNDIS_PACKET PacketArray,
398 IN UINT NumberOfPackets)
399 {
400 UNIMPLEMENTED
401 }
402
403 \f
404 NDIS_STATUS NTAPI
405 ProTransferData(
406 IN NDIS_HANDLE MacBindingHandle,
407 IN NDIS_HANDLE MacReceiveContext,
408 IN UINT ByteOffset,
409 IN UINT BytesToTransfer,
410 IN OUT PNDIS_PACKET Packet,
411 OUT PUINT BytesTransferred)
412 /*
413 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
414 * ARGUMENTS:
415 * MacBindingHandle = Adapter binding handle
416 * MacReceiveContext = MAC receive context
417 * ByteOffset = Offset in packet to place data
418 * BytesToTransfer = Number of bytes to copy into packet
419 * Packet = Pointer to NDIS packet descriptor
420 * BytesTransferred = Address of buffer to place number of bytes copied
421 */
422 {
423 PADAPTER_BINDING AdapterBinding = GET_ADAPTER_BINDING(MacBindingHandle);
424 PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
425
426 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
427
428 /* FIXME: Interrupts must be disabled for adapter */
429 /* XXX sd - why is that true? */
430
431 if (Packet == Adapter->NdisMiniportBlock.IndicatedPacket[KeGetCurrentProcessorNumber()]) {
432 NDIS_DbgPrint(MAX_TRACE, ("LoopPacket\n"));
433 /* NDIS is responsible for looping this packet */
434 NdisCopyFromPacketToPacket(Packet,
435 ByteOffset,
436 BytesToTransfer,
437 Adapter->NdisMiniportBlock.IndicatedPacket[KeGetCurrentProcessorNumber()],
438 0,
439 BytesTransferred);
440 return NDIS_STATUS_SUCCESS;
441 }
442
443 return (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.TransferDataHandler)(
444 Packet,
445 BytesTransferred,
446 Adapter->NdisMiniportBlock.MiniportAdapterContext,
447 MacReceiveContext,
448 ByteOffset,
449 BytesToTransfer);
450 }
451
452
453
454 /*
455 * @implemented
456 */
457 VOID
458 EXPORT
459 NdisCloseAdapter(
460 OUT PNDIS_STATUS Status,
461 IN NDIS_HANDLE NdisBindingHandle)
462 /*
463 * FUNCTION: Closes an adapter opened with NdisOpenAdapter
464 * ARGUMENTS:
465 * Status = Address of buffer for status information
466 * NdisBindingHandle = Handle returned by NdisOpenAdapter
467 */
468 {
469 KIRQL OldIrql;
470 PADAPTER_BINDING AdapterBinding = GET_ADAPTER_BINDING(NdisBindingHandle);
471
472 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
473
474 /* Remove from protocol's bound adapters list */
475 KeAcquireSpinLock(&AdapterBinding->ProtocolBinding->Lock, &OldIrql);
476 RemoveEntryList(&AdapterBinding->ProtocolListEntry);
477 KeReleaseSpinLock(&AdapterBinding->ProtocolBinding->Lock, OldIrql);
478
479 /* Remove protocol from adapter's bound protocols list */
480 NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
481 KeAcquireSpinLock(&AdapterBinding->Adapter->NdisMiniportBlock.Lock, &OldIrql);
482 RemoveEntryList(&AdapterBinding->AdapterListEntry);
483 KeReleaseSpinLock(&AdapterBinding->Adapter->NdisMiniportBlock.Lock, OldIrql);
484
485 ExFreePool(AdapterBinding);
486
487 *Status = NDIS_STATUS_SUCCESS;
488 }
489
490
491 /*
492 * @implemented
493 */
494 VOID
495 EXPORT
496 NdisDeregisterProtocol(
497 OUT PNDIS_STATUS Status,
498 IN NDIS_HANDLE NdisProtocolHandle)
499 /*
500 * FUNCTION: Releases the resources allocated by NdisRegisterProtocol
501 * ARGUMENTS:
502 * Status = Address of buffer for status information
503 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol
504 */
505 {
506 KIRQL OldIrql;
507 PPROTOCOL_BINDING Protocol = GET_PROTOCOL_BINDING(NdisProtocolHandle);
508
509 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
510
511 /* FIXME: Make sure no adapter bindings exist */
512
513 /* Remove protocol from global list */
514 KeAcquireSpinLock(&ProtocolListLock, &OldIrql);
515 RemoveEntryList(&Protocol->ListEntry);
516 KeReleaseSpinLock(&ProtocolListLock, OldIrql);
517
518 ExFreePool(Protocol);
519
520 *Status = NDIS_STATUS_SUCCESS;
521 }
522
523
524 /*
525 * @implemented
526 */
527 VOID
528 EXPORT
529 NdisOpenAdapter(
530 OUT PNDIS_STATUS Status,
531 OUT PNDIS_STATUS OpenErrorStatus,
532 OUT PNDIS_HANDLE NdisBindingHandle,
533 OUT PUINT SelectedMediumIndex,
534 IN PNDIS_MEDIUM MediumArray,
535 IN UINT MediumArraySize,
536 IN NDIS_HANDLE NdisProtocolHandle,
537 IN NDIS_HANDLE ProtocolBindingContext,
538 IN PNDIS_STRING AdapterName,
539 IN UINT OpenOptions,
540 IN PSTRING AddressingInformation OPTIONAL)
541 /*
542 * FUNCTION: Opens an adapter for communication
543 * ARGUMENTS:
544 * Status = Address of buffer for status information
545 * OpenErrorStatus = Address of buffer for secondary error code
546 * NdisBindingHandle = Address of buffer for adapter binding handle
547 * SelectedMediumIndex = Address of buffer for selected medium
548 * MediumArray = Pointer to an array of NDIS_MEDIUMs called can support
549 * MediumArraySize = Number of elements in MediumArray
550 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol
551 * ProtocolBindingContext = Pointer to caller suplied context area
552 * AdapterName = Pointer to buffer with name of adapter
553 * OpenOptions = Bitmask with flags passed to next-lower driver
554 * AddressingInformation = Optional pointer to buffer with NIC specific information
555 */
556 {
557 UINT i;
558 BOOLEAN Found;
559 PLOGICAL_ADAPTER Adapter;
560 PADAPTER_BINDING AdapterBinding;
561 PPROTOCOL_BINDING Protocol = GET_PROTOCOL_BINDING(NdisProtocolHandle);
562
563 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
564
565 if(!NdisProtocolHandle)
566 {
567 NDIS_DbgPrint(MAX_TRACE, ("NdisProtocolHandle is NULL\n"));
568 *OpenErrorStatus = *Status = NDIS_STATUS_FAILURE;
569 return;
570 }
571
572 Adapter = MiniLocateDevice(AdapterName);
573 if (!Adapter)
574 {
575 NDIS_DbgPrint(MIN_TRACE, ("Adapter not found.\n"));
576 *Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
577 return;
578 }
579
580 /* Find the media type in the list provided by the protocol driver */
581 Found = FALSE;
582 for (i = 0; i < MediumArraySize; i++)
583 {
584 if (Adapter->NdisMiniportBlock.MediaType == MediumArray[i])
585 {
586 *SelectedMediumIndex = i;
587 Found = TRUE;
588 break;
589 }
590 }
591
592 if (!Found)
593 {
594 NDIS_DbgPrint(MIN_TRACE, ("Medium is not supported.\n"));
595 *Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
596 return;
597 }
598
599 /* Now that we have confirmed that the adapter can be opened, create a binding */
600
601 AdapterBinding = ExAllocatePool(NonPagedPool, sizeof(ADAPTER_BINDING));
602 if (!AdapterBinding)
603 {
604 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
605 *Status = NDIS_STATUS_RESOURCES;
606 return;
607 }
608
609 RtlZeroMemory(AdapterBinding, sizeof(ADAPTER_BINDING));
610
611 AdapterBinding->ProtocolBinding = Protocol;
612 AdapterBinding->Adapter = Adapter;
613 AdapterBinding->NdisOpenBlock.ProtocolBindingContext = ProtocolBindingContext;
614
615 /* Set fields required by some NDIS macros */
616 AdapterBinding->NdisOpenBlock.BindingHandle = (NDIS_HANDLE)AdapterBinding;
617
618 /* Set handlers (some NDIS macros require these) */
619
620 AdapterBinding->NdisOpenBlock.RequestHandler = ProRequest;
621 AdapterBinding->NdisOpenBlock.ResetHandler = ProReset;
622 AdapterBinding->NdisOpenBlock.SendHandler = ProSend;
623 AdapterBinding->NdisOpenBlock.SendPacketsHandler = ProSendPackets;
624 AdapterBinding->NdisOpenBlock.TransferDataHandler = ProTransferData;
625
626 AdapterBinding->NdisOpenBlock.RequestCompleteHandler =
627 Protocol->Chars.RequestCompleteHandler;
628
629 #if 0
630 /* XXX this looks fishy */
631 /* OK, this really *is* fishy - it bugchecks */
632 /* Put on protocol's bound adapters list */
633 ExInterlockedInsertTailList(&Protocol->AdapterListHead, &AdapterBinding->ProtocolListEntry, &Protocol->Lock);
634 #endif
635
636 /* XXX so does this */
637 /* Put protocol on adapter's bound protocols list */
638 NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
639 ExInterlockedInsertTailList(&Adapter->ProtocolListHead, &AdapterBinding->AdapterListEntry, &Adapter->NdisMiniportBlock.Lock);
640
641 *NdisBindingHandle = (NDIS_HANDLE)AdapterBinding;
642
643 *Status = NDIS_STATUS_SUCCESS;
644 }
645
646
647 /*
648 * @implemented
649 */
650 VOID
651 EXPORT
652 NdisRegisterProtocol(
653 OUT PNDIS_STATUS Status,
654 OUT PNDIS_HANDLE NdisProtocolHandle,
655 IN PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics,
656 IN UINT CharacteristicsLength)
657 /*
658 * FUNCTION: Registers an NDIS driver's ProtocolXxx entry points
659 * ARGUMENTS:
660 * Status = Address of buffer for status information
661 * NdisProtocolHandle = Address of buffer for handle used to identify the driver
662 * ProtocolCharacteristics = Pointer to NDIS_PROTOCOL_CHARACTERISTICS structure
663 * CharacteristicsLength = Size of structure which ProtocolCharacteristics targets
664 * NOTES:
665 * - you *must* set NdisProtocolHandle before doing anything that could wind up
666 * getting BindAdapterHandler, as it will probably call OpenAdapter with this handle
667 * - the above implies that the initialization of the protocol block must be complete
668 * by then
669 * TODO:
670 * - break this function up - probably do a 'ndisRefreshProtocolBindings' function
671 * - make this thing able to handle >1 protocol
672 */
673 {
674 PPROTOCOL_BINDING Protocol;
675 NTSTATUS NtStatus;
676 UINT MinSize;
677 HANDLE DriverKeyHandle = NULL;
678 PKEY_VALUE_PARTIAL_INFORMATION KeyInformation = NULL;
679 WCHAR *DataPtr;
680
681 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
682
683 /* first validate the PROTOCOL_CHARACTERISTICS */
684 switch (ProtocolCharacteristics->MajorNdisVersion)
685 {
686 case 0x03:
687 /* we don't really want to support ndis3 drivers - so we complain for now */
688 NDIS_DbgPrint(MID_TRACE, ("NDIS 3 protocol attempting to register\n"));
689 MinSize = sizeof(NDIS30_PROTOCOL_CHARACTERISTICS);
690 break;
691
692 case 0x04:
693 MinSize = sizeof(NDIS40_PROTOCOL_CHARACTERISTICS);
694 break;
695
696 case 0x05:
697 MinSize = sizeof(NDIS50_PROTOCOL_CHARACTERISTICS);
698 break;
699
700 default:
701 *Status = NDIS_STATUS_BAD_VERSION;
702 NDIS_DbgPrint(MIN_TRACE, ("Incorrect characteristics size\n"));
703 return;
704 }
705
706 if (CharacteristicsLength < MinSize)
707 {
708 NDIS_DbgPrint(DEBUG_PROTOCOL, ("Bad protocol characteristics.\n"));
709 *Status = NDIS_STATUS_BAD_CHARACTERISTICS;
710 return;
711 }
712
713 /* set up the protocol block */
714 Protocol = ExAllocatePool(NonPagedPool, sizeof(PROTOCOL_BINDING));
715 if (!Protocol)
716 {
717 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
718 *Status = NDIS_STATUS_RESOURCES;
719 return;
720 }
721
722 RtlZeroMemory(Protocol, sizeof(PROTOCOL_BINDING));
723 RtlCopyMemory(&Protocol->Chars, ProtocolCharacteristics, MinSize);
724
725 NtStatus = RtlUpcaseUnicodeString(&Protocol->Chars.Name, &ProtocolCharacteristics->Name, TRUE);
726 if (!NT_SUCCESS(NtStatus))
727 {
728 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
729 ExFreePool(Protocol);
730 *Status = NDIS_STATUS_RESOURCES;
731 return;
732 }
733
734 KeInitializeSpinLock(&Protocol->Lock);
735
736 InitializeListHead(&Protocol->AdapterListHead);
737
738 /*
739 * bind the protocol to all of its miniports
740 *
741 * open registry path
742 * get list of devices from Bind key
743 * call BindAdapterHandler for each
744 */
745 {
746 OBJECT_ATTRIBUTES ObjectAttributes;
747 UNICODE_STRING RegistryPath;
748 WCHAR *RegistryPathStr;
749
750 RegistryPathStr = ExAllocatePoolWithTag(PagedPool, sizeof(SERVICES_KEY) + ProtocolCharacteristics->Name.Length + sizeof(LINKAGE_KEY), NDIS_TAG + __LINE__);
751 if(!RegistryPathStr)
752 {
753 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
754 ExFreePool(Protocol);
755 *Status = NDIS_STATUS_RESOURCES;
756 return;
757 }
758
759 wcscpy(RegistryPathStr, SERVICES_KEY);
760 wcsncat(RegistryPathStr, ((WCHAR *)ProtocolCharacteristics->Name.Buffer), ProtocolCharacteristics->Name.Length / sizeof(WCHAR));
761 RegistryPathStr[wcslen(SERVICES_KEY)+ProtocolCharacteristics->Name.Length/sizeof(WCHAR)] = 0;
762 wcscat(RegistryPathStr, LINKAGE_KEY);
763
764 RtlInitUnicodeString(&RegistryPath, RegistryPathStr);
765 NDIS_DbgPrint(MAX_TRACE, ("Opening configuration key: %wZ\n", &RegistryPath));
766
767 InitializeObjectAttributes(&ObjectAttributes, &RegistryPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
768 NtStatus = ZwOpenKey(&DriverKeyHandle, KEY_READ, &ObjectAttributes);
769
770 ExFreePool(RegistryPathStr);
771
772 if(!NT_SUCCESS(NtStatus))
773 {
774 NDIS_DbgPrint(MID_TRACE, ("Unable to open protocol configuration\n"));
775 ExFreePool(Protocol);
776 *Status = NDIS_STATUS_FAILURE;
777 return;
778 }
779 }
780
781 NDIS_DbgPrint(MAX_TRACE, ("Successfully opened the registry configuration\n"));
782
783 {
784 UNICODE_STRING ValueName;
785 ULONG ResultLength;
786
787 RtlInitUnicodeString(&ValueName, L"Bind");
788
789 NtStatus = ZwQueryValueKey(DriverKeyHandle, &ValueName, KeyValuePartialInformation, NULL, 0, &ResultLength);
790 if(NtStatus != STATUS_BUFFER_OVERFLOW && NtStatus != STATUS_BUFFER_TOO_SMALL)
791 {
792 NDIS_DbgPrint(MID_TRACE, ("Unable to query the Bind value for size\n"));
793 ZwClose(DriverKeyHandle);
794 ExFreePool(Protocol);
795 *Status = NDIS_STATUS_FAILURE;
796 return;
797 }
798
799 KeyInformation = ExAllocatePoolWithTag(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + ResultLength, NDIS_TAG + __LINE__);
800 if(!KeyInformation)
801 {
802 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
803 ZwClose(DriverKeyHandle);
804 ExFreePool(Protocol);
805 *Status = NDIS_STATUS_FAILURE;
806 return;
807 }
808
809 NtStatus = ZwQueryValueKey(DriverKeyHandle, &ValueName, KeyValuePartialInformation, KeyInformation,
810 sizeof(KEY_VALUE_PARTIAL_INFORMATION) + ResultLength, &ResultLength);
811
812 if(!NT_SUCCESS(NtStatus))
813 {
814 NDIS_DbgPrint(MIN_TRACE, ("Unable to query the Bind value\n"));
815 ZwClose(DriverKeyHandle);
816 ExFreePool(KeyInformation);
817 ExFreePool(Protocol);
818 *Status = NDIS_STATUS_FAILURE;
819 return;
820 }
821 }
822
823 for (DataPtr = (WCHAR *)KeyInformation->Data;
824 *DataPtr != 0;
825 DataPtr += wcslen(DataPtr) + 1)
826 {
827 /* BindContext is for tracking pending binding operations */
828 VOID *BindContext = 0;
829 NDIS_STRING DeviceName;
830 NDIS_STRING RegistryPath;
831 WCHAR *RegistryPathStr = NULL;
832 ULONG PathLength = 0;
833
834 RtlInitUnicodeString(&DeviceName, DataPtr); /* we know this is 0-term */
835
836 /*
837 * RegistryPath should be:
838 * \Registry\Machine\System\CurrentControlSet\Services\Nic1\Parameters\Tcpip
839 *
840 * This is constructed as follows:
841 * SERVICES_KEY + extracted device name + Protocol name from characteristics
842 */
843
844 PathLength = sizeof(SERVICES_KEY) + /* \Registry\Machine\System\CurrentControlSet\Services\ */
845 wcslen( DataPtr + 8 ) * sizeof(WCHAR) + /* Adapter1 (extracted from \Device\Adapter1) */
846 sizeof(PARAMETERS_KEY) + /* \Parameters\ */
847 ProtocolCharacteristics->Name.Length + sizeof(WCHAR); /* Tcpip */
848
849 RegistryPathStr = ExAllocatePool(PagedPool, PathLength);
850 if(!RegistryPathStr)
851 {
852 NDIS_DbgPrint(MIN_TRACE, ("insufficient resources.\n"));
853 ExFreePool(KeyInformation);
854 ExFreePool(Protocol);
855 *Status = NDIS_STATUS_RESOURCES;
856 return;
857 }
858
859 wcscpy(RegistryPathStr, SERVICES_KEY);
860 wcscat(RegistryPathStr, DataPtr + 8 );
861 wcscat(RegistryPathStr, PARAMETERS_KEY);
862 wcsncat(RegistryPathStr, ProtocolCharacteristics->Name.Buffer, ProtocolCharacteristics->Name.Length / sizeof(WCHAR) );
863
864 RegistryPathStr[PathLength/sizeof(WCHAR) - 1] = 0;
865
866 RtlInitUnicodeString(&RegistryPath, RegistryPathStr);
867
868 NDIS_DbgPrint(MAX_TRACE, ("Calling protocol's BindAdapter handler with DeviceName %wZ and RegistryPath %wZ\n",
869 &DeviceName, &RegistryPath));
870
871 /* XXX SD must do something with bind context */
872 *NdisProtocolHandle = Protocol;
873
874 {
875 BIND_HANDLER BindHandler = ProtocolCharacteristics->BindAdapterHandler;
876 if(BindHandler)
877 BindHandler(Status, BindContext, &DeviceName, &RegistryPath, 0);
878 else
879 NDIS_DbgPrint(MID_TRACE, ("No protocol bind handler specified\n"));
880 }
881
882 /*
883 (*(Protocol->Chars.BindAdapterHandler))(Status, BindContext, &DeviceName, &RegistryPath, 0);
884 */
885
886 if(*Status == NDIS_STATUS_SUCCESS)
887 {
888 /* Put protocol binding struct on global list */
889 ExInterlockedInsertTailList(&ProtocolListHead, &Protocol->ListEntry, &ProtocolListLock);
890 }
891
892 /*
893 else if(*Status != NDIS_STATUS_PENDING)
894 {
895 // what to do here?
896 }
897 */
898 }
899
900 *Status = NDIS_STATUS_SUCCESS;
901 }
902
903 \f
904 /*
905 * @implemented
906 */
907 VOID
908 EXPORT
909 NdisRequest(
910 OUT PNDIS_STATUS Status,
911 IN NDIS_HANDLE NdisBindingHandle,
912 IN PNDIS_REQUEST NdisRequest)
913 /*
914 * FUNCTION: Forwards a request to an NDIS driver
915 * ARGUMENTS:
916 * Status = Address of buffer for status information
917 * NdisBindingHandle = Adapter binding handle
918 * NdisRequest = Pointer to request to perform
919 */
920 {
921 *Status = ProRequest(NdisBindingHandle, NdisRequest);
922 }
923
924 \f
925 /*
926 * @implemented
927 */
928 VOID
929 EXPORT
930 NdisReset(
931 OUT PNDIS_STATUS Status,
932 IN NDIS_HANDLE NdisBindingHandle)
933 {
934 *Status = ProReset(NdisBindingHandle);
935 }
936
937 \f
938 /*
939 * @implemented
940 */
941 #undef NdisSend
942 VOID
943 EXPORT
944 NdisSend(
945 OUT PNDIS_STATUS Status,
946 IN NDIS_HANDLE NdisBindingHandle,
947 IN PNDIS_PACKET Packet)
948 /*
949 * FUNCTION: Forwards a request to send a packet
950 * ARGUMENTS:
951 * Status = Address of buffer for status information
952 * NdisBindingHandle = Adapter binding handle
953 * Packet = Pointer to NDIS packet descriptor
954 */
955 {
956 *Status = ProSend(NdisBindingHandle, Packet);
957 }
958
959 \f
960 /*
961 * @implemented
962 */
963 #undef NdisSendPackets
964 VOID
965 EXPORT
966 NdisSendPackets(
967 IN NDIS_HANDLE NdisBindingHandle,
968 IN PPNDIS_PACKET PacketArray,
969 IN UINT NumberOfPackets)
970 {
971 ProSendPackets(NdisBindingHandle, PacketArray, NumberOfPackets);
972 }
973
974 \f
975 /*
976 * @implemented
977 */
978 #undef NdisTransferData
979 VOID
980 EXPORT
981 NdisTransferData(
982 OUT PNDIS_STATUS Status,
983 IN NDIS_HANDLE NdisBindingHandle,
984 IN NDIS_HANDLE MacReceiveContext,
985 IN UINT ByteOffset,
986 IN UINT BytesToTransfer,
987 IN OUT PNDIS_PACKET Packet,
988 OUT PUINT BytesTransferred)
989 /*
990 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
991 * ARGUMENTS:
992 * Status = Address of buffer for status information
993 * NdisBindingHandle = Adapter binding handle
994 * MacReceiveContext = MAC receive context
995 * ByteOffset = Offset in packet to place data
996 * BytesToTransfer = Number of bytes to copy into packet
997 * Packet = Pointer to NDIS packet descriptor
998 * BytesTransferred = Address of buffer to place number of bytes copied
999 */
1000 {
1001 *Status = ProTransferData(NdisBindingHandle,
1002 MacReceiveContext,
1003 ByteOffset,
1004 BytesToTransfer,
1005 Packet,
1006 BytesTransferred);
1007 }
1008
1009 /* EOF */