Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenprotocol.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS NDIS library 00004 * FILE: ndis/protocol.c 00005 * PURPOSE: Routines used by NDIS protocol drivers 00006 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) 00007 * Vizzini (vizzini@plasmic.com) 00008 * REVISIONS: 00009 * CSH 01/08-2000 Created 00010 * 09-13-2003 Vizzini Updates for SendPackets support 00011 */ 00012 00013 #include "ndissys.h" 00014 00015 #define SERVICES_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\" 00016 #define LINKAGE_KEY L"\\Linkage" 00017 #define PARAMETERS_KEY L"\\Parameters\\" 00018 00019 LIST_ENTRY ProtocolListHead; 00020 KSPIN_LOCK ProtocolListLock; 00021 00022 #define WORKER_TEST 0 00023 00024 typedef struct _DMA_CONTEXT { 00025 PLOGICAL_ADAPTER Adapter; 00026 PNDIS_PACKET Packet; 00027 } DMA_CONTEXT, *PDMA_CONTEXT; 00028 00029 PNET_PNP_EVENT 00030 ProSetupPnPEvent( 00031 NET_PNP_EVENT_CODE EventCode, 00032 PVOID EventBuffer, 00033 ULONG EventBufferLength) 00034 { 00035 PNET_PNP_EVENT PnPEvent; 00036 00037 PnPEvent = ExAllocatePool(PagedPool, sizeof(NET_PNP_EVENT)); 00038 if (!PnPEvent) { 00039 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n")); 00040 return NULL; 00041 } 00042 00043 RtlZeroMemory(PnPEvent, sizeof(NET_PNP_EVENT)); 00044 00045 PnPEvent->NetEvent = EventCode; 00046 00047 if (EventBuffer != NULL) 00048 { 00049 PnPEvent->Buffer = ExAllocatePool(PagedPool, EventBufferLength); 00050 if (!PnPEvent->Buffer) 00051 { 00052 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n")); 00053 ExFreePool(PnPEvent); 00054 return NULL; 00055 } 00056 00057 PnPEvent->BufferLength = EventBufferLength; 00058 00059 RtlCopyMemory(PnPEvent->Buffer, EventBuffer, PnPEvent->BufferLength); 00060 } 00061 00062 return PnPEvent; 00063 } 00064 00065 NDIS_STATUS 00066 ProSendAndFreePnPEvent( 00067 PLOGICAL_ADAPTER Adapter, 00068 PNET_PNP_EVENT PnPEvent, 00069 PIRP Irp) 00070 { 00071 PLIST_ENTRY CurrentEntry; 00072 NDIS_STATUS Status; 00073 PADAPTER_BINDING AdapterBinding; 00074 00075 CurrentEntry = Adapter->ProtocolListHead.Flink; 00076 00077 while (CurrentEntry != &Adapter->ProtocolListHead) 00078 { 00079 AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry); 00080 00081 Status = (*AdapterBinding->ProtocolBinding->Chars.PnPEventHandler)( 00082 AdapterBinding->NdisOpenBlock.ProtocolBindingContext, 00083 PnPEvent); 00084 00085 if (Status == NDIS_STATUS_PENDING) 00086 { 00087 IoMarkIrpPending(Irp); 00088 /* Yes, I know this is stupid */ 00089 PnPEvent->NdisReserved[0] = (ULONG_PTR)Irp; 00090 PnPEvent->NdisReserved[1] = (ULONG_PTR)CurrentEntry->Flink; 00091 return NDIS_STATUS_PENDING; 00092 } 00093 else if (Status != NDIS_STATUS_SUCCESS) 00094 { 00095 if (PnPEvent->Buffer) ExFreePool(PnPEvent->Buffer); 00096 ExFreePool(PnPEvent); 00097 return Status; 00098 } 00099 00100 CurrentEntry = CurrentEntry->Flink; 00101 } 00102 00103 if (PnPEvent->Buffer) ExFreePool(PnPEvent->Buffer); 00104 ExFreePool(PnPEvent); 00105 00106 return NDIS_STATUS_SUCCESS; 00107 } 00108 00109 NTSTATUS 00110 NTAPI 00111 NdisIPwrSetPower( 00112 IN PDEVICE_OBJECT DeviceObject, 00113 PIRP Irp) 00114 { 00115 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension; 00116 PNET_PNP_EVENT PnPEvent; 00117 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); 00118 00119 ASSERT(Stack->Parameters.Power.Type == DevicePowerState); 00120 00121 PnPEvent = ProSetupPnPEvent(NetEventSetPower, &Stack->Parameters.Power.State, sizeof(NDIS_DEVICE_POWER_STATE)); 00122 if (!PnPEvent) { 00123 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n")); 00124 return NDIS_STATUS_RESOURCES; 00125 } 00126 00127 return ProSendAndFreePnPEvent(Adapter, PnPEvent, Irp); 00128 } 00129 00130 NTSTATUS 00131 NTAPI 00132 NdisIPwrQueryPower( 00133 IN PDEVICE_OBJECT DeviceObject, 00134 PIRP Irp) 00135 { 00136 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension; 00137 PNET_PNP_EVENT PnPEvent; 00138 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); 00139 00140 ASSERT(Stack->Parameters.Power.Type == DevicePowerState); 00141 00142 PnPEvent = ProSetupPnPEvent(NetEventQueryPower, &Stack->Parameters.Power.State, sizeof(NDIS_DEVICE_POWER_STATE)); 00143 if (!PnPEvent) { 00144 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n")); 00145 return NDIS_STATUS_RESOURCES; 00146 } 00147 00148 return ProSendAndFreePnPEvent(Adapter, PnPEvent, Irp); 00149 } 00150 00151 00152 NTSTATUS 00153 NTAPI 00154 NdisIPnPQueryStopDevice( 00155 IN PDEVICE_OBJECT DeviceObject, 00156 PIRP Irp) 00157 { 00158 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension; 00159 PNET_PNP_EVENT PnPEvent; 00160 00161 PnPEvent = ProSetupPnPEvent(NetEventQueryRemoveDevice, NULL, 0); 00162 if (!PnPEvent) { 00163 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n")); 00164 return NDIS_STATUS_RESOURCES; 00165 } 00166 00167 return ProSendAndFreePnPEvent(Adapter, PnPEvent, Irp); 00168 } 00169 00170 NTSTATUS 00171 NTAPI 00172 NdisIPnPCancelStopDevice( 00173 IN PDEVICE_OBJECT DeviceObject, 00174 PIRP Irp) 00175 { 00176 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension; 00177 PNET_PNP_EVENT PnPEvent; 00178 00179 PnPEvent = ProSetupPnPEvent(NetEventCancelRemoveDevice, NULL, 0); 00180 if (!PnPEvent) { 00181 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n")); 00182 return NDIS_STATUS_RESOURCES; 00183 } 00184 00185 return ProSendAndFreePnPEvent(Adapter, PnPEvent, Irp); 00186 } 00187 00188 00189 /* 00190 * @implemented 00191 */ 00192 VOID 00193 EXPORT 00194 NdisCompleteBindAdapter( 00195 IN NDIS_HANDLE BindAdapterContext, 00196 IN NDIS_STATUS Status, 00197 IN NDIS_STATUS OpenStatus) 00198 /* 00199 * FUNCTION: Indicates a packet to bound protocols 00200 * ARGUMENTS: 00201 * Adapter = Pointer to logical adapter 00202 * Packet = Pointer to packet to indicate 00203 * RETURNS: 00204 * Status of operation 00205 * NOTES: 00206 * - FIXME: partially-implemented 00207 */ 00208 { 00209 PROTOCOL_BINDING *Protocol = (PROTOCOL_BINDING *)BindAdapterContext; 00210 00211 if (!NT_SUCCESS(Status)) { 00212 NDIS_DbgPrint(MIN_TRACE, ("Binding failed (%x)\n", Status)); 00213 return; 00214 } 00215 00216 /* Put protocol binding struct on global list */ 00217 ExInterlockedInsertTailList(&ProtocolListHead, &Protocol->ListEntry, &ProtocolListLock); 00218 } 00219 00220 /* 00221 * @implemented 00222 */ 00223 VOID 00224 EXPORT 00225 NdisCompleteUnbindAdapter( 00226 IN NDIS_HANDLE UnbindAdapterContext, 00227 IN NDIS_STATUS Status) 00228 { 00229 /* We probably need to do more here but for now we just do 00230 * the opposite of what NdisCompleteBindAdapter does 00231 */ 00232 00233 PROTOCOL_BINDING *Protocol = (PROTOCOL_BINDING *)UnbindAdapterContext; 00234 00235 if (!NT_SUCCESS(Status)) { 00236 NDIS_DbgPrint(MIN_TRACE, ("Unbinding failed (%x)\n", Status)); 00237 return; 00238 } 00239 00240 ExInterlockedRemoveEntryList(&Protocol->ListEntry, &ProtocolListLock); 00241 } 00242 00243 00244 NDIS_STATUS 00245 ProIndicatePacket( 00246 PLOGICAL_ADAPTER Adapter, 00247 PNDIS_PACKET Packet) 00248 /* 00249 * FUNCTION: Indicates a packet to bound protocols 00250 * ARGUMENTS: 00251 * Adapter = Pointer to logical adapter 00252 * Packet = Pointer to packet to indicate 00253 * RETURNS: 00254 * STATUS_SUCCESS in all cases 00255 * NOTES: 00256 * - XXX ATM, this only handles loopback packets - is that its designed function? 00257 */ 00258 { 00259 UINT BufferedLength; 00260 UINT PacketLength; 00261 KIRQL OldIrql; 00262 PUCHAR LookaheadBuffer; 00263 00264 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 00265 00266 #if DBG 00267 MiniDisplayPacket(Packet); 00268 #endif 00269 00270 NdisQueryPacket(Packet, NULL, NULL, NULL, &PacketLength); 00271 00272 LookaheadBuffer = ExAllocatePool(NonPagedPool, PacketLength); 00273 if (!LookaheadBuffer) { 00274 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n")); 00275 return NDIS_STATUS_RESOURCES; 00276 } 00277 00278 NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n")); 00279 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql); 00280 { 00281 BufferedLength = CopyPacketToBuffer(LookaheadBuffer, Packet, 0, PacketLength); 00282 Adapter->NdisMiniportBlock.IndicatedPacket[KeGetCurrentProcessorNumber()] = Packet; 00283 } 00284 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); 00285 00286 if (BufferedLength > Adapter->MediumHeaderSize) 00287 { 00288 /* XXX Change this to call SendPackets so we don't have to duplicate this wacky logic */ 00289 MiniIndicateData(Adapter, NULL, LookaheadBuffer, Adapter->MediumHeaderSize, 00290 &LookaheadBuffer[Adapter->MediumHeaderSize], BufferedLength - Adapter->MediumHeaderSize, 00291 PacketLength - Adapter->MediumHeaderSize); 00292 } 00293 else 00294 { 00295 MiniIndicateData(Adapter, NULL, LookaheadBuffer, Adapter->MediumHeaderSize, NULL, 0, 0); 00296 } 00297 00298 ExFreePool(LookaheadBuffer); 00299 00300 KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql); 00301 { 00302 Adapter->NdisMiniportBlock.IndicatedPacket[KeGetCurrentProcessorNumber()] = NULL; 00303 } 00304 KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); 00305 00306 return NDIS_STATUS_SUCCESS; 00307 } 00308 00309 00310 NDIS_STATUS NTAPI 00311 ProRequest( 00312 IN NDIS_HANDLE MacBindingHandle, 00313 IN PNDIS_REQUEST NdisRequest) 00314 /* 00315 * FUNCTION: Forwards a request to an NDIS miniport 00316 * ARGUMENTS: 00317 * MacBindingHandle = Adapter binding handle 00318 * NdisRequest = Pointer to request to perform 00319 * RETURNS: 00320 * Status of operation 00321 */ 00322 { 00323 PADAPTER_BINDING AdapterBinding; 00324 PLOGICAL_ADAPTER Adapter; 00325 PNDIS_REQUEST_MAC_BLOCK MacBlock = (PNDIS_REQUEST_MAC_BLOCK)NdisRequest->MacReserved; 00326 00327 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 00328 00329 ASSERT(MacBindingHandle); 00330 AdapterBinding = GET_ADAPTER_BINDING(MacBindingHandle); 00331 00332 ASSERT(AdapterBinding->Adapter); 00333 Adapter = AdapterBinding->Adapter; 00334 00335 MacBlock->Binding = &AdapterBinding->NdisOpenBlock; 00336 00337 #if WORKER_TEST 00338 MiniQueueWorkItem(Adapter, NdisWorkItemRequest, NdisRequest, FALSE); 00339 return NDIS_STATUS_PENDING; 00340 #else 00341 if (MiniIsBusy(Adapter, NdisWorkItemRequest)) { 00342 MiniQueueWorkItem(Adapter, NdisWorkItemRequest, NdisRequest, FALSE); 00343 return NDIS_STATUS_PENDING; 00344 } 00345 00346 return MiniDoRequest(Adapter, NdisRequest); 00347 #endif 00348 } 00349 00350 00351 NDIS_STATUS NTAPI 00352 ProReset( 00353 IN NDIS_HANDLE MacBindingHandle) 00354 { 00355 PADAPTER_BINDING AdapterBinding = MacBindingHandle; 00356 00357 /* FIXME: Wait for all packets to be sent */ 00358 00359 return MiniReset(AdapterBinding->Adapter); 00360 } 00361 00362 VOID NTAPI 00363 ScatterGatherSendPacket( 00364 IN PDEVICE_OBJECT DeviceObject, 00365 IN PIRP Irp, 00366 IN PSCATTER_GATHER_LIST ScatterGather, 00367 IN PVOID Context) 00368 { 00369 PDMA_CONTEXT DmaContext = Context; 00370 PLOGICAL_ADAPTER Adapter = DmaContext->Adapter; 00371 PNDIS_PACKET Packet = DmaContext->Packet; 00372 NDIS_STATUS Status; 00373 00374 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 00375 00376 NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, 00377 ScatterGatherListPacketInfo) = ScatterGather; 00378 00379 Status = proSendPacketToMiniport(Adapter, Packet); 00380 00381 if (Status != NDIS_STATUS_PENDING) { 00382 NDIS_DbgPrint(MAX_TRACE, ("Completing packet.\n")); 00383 MiniSendComplete(Adapter, 00384 Packet, 00385 Status); 00386 } 00387 00388 ExFreePool(DmaContext); 00389 } 00390 00391 NDIS_STATUS 00392 proSendPacketToMiniport(PLOGICAL_ADAPTER Adapter, PNDIS_PACKET Packet) 00393 { 00394 #if WORKER_TEST 00395 MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet, FALSE); 00396 return NDIS_STATUS_PENDING; 00397 #else 00398 KIRQL RaiseOldIrql; 00399 NDIS_STATUS NdisStatus; 00400 00401 if(MiniIsBusy(Adapter, NdisWorkItemSend)) { 00402 MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet, FALSE); 00403 return NDIS_STATUS_PENDING; 00404 } 00405 00406 if(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler) 00407 { 00408 if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE) 00409 { 00410 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n")); 00411 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)( 00412 Adapter->NdisMiniportBlock.MiniportAdapterContext, &Packet, 1); 00413 NdisStatus = NDIS_STATUS_PENDING; 00414 } else { 00415 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */ 00416 KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql); 00417 { 00418 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n")); 00419 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)( 00420 Adapter->NdisMiniportBlock.MiniportAdapterContext, &Packet, 1); 00421 } 00422 KeLowerIrql(RaiseOldIrql); 00423 00424 NdisStatus = NDIS_GET_PACKET_STATUS(Packet); 00425 if (NdisStatus == NDIS_STATUS_RESOURCES) { 00426 MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet, TRUE); 00427 NdisStatus = NDIS_STATUS_PENDING; 00428 } 00429 } 00430 00431 return NdisStatus; 00432 } else { 00433 if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE) 00434 { 00435 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n")); 00436 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)( 00437 Adapter->NdisMiniportBlock.MiniportAdapterContext, Packet, Packet->Private.Flags); 00438 NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n")); 00439 } else { 00440 /* Send is called at DISPATCH_LEVEL for all serialized miniports */ 00441 KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql); 00442 NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n")); 00443 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)( 00444 Adapter->NdisMiniportBlock.MiniportAdapterContext, Packet, Packet->Private.Flags); 00445 NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n")); 00446 KeLowerIrql(RaiseOldIrql); 00447 00448 if (NdisStatus == NDIS_STATUS_RESOURCES) { 00449 MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet, TRUE); 00450 NdisStatus = NDIS_STATUS_PENDING; 00451 } 00452 } 00453 00454 return NdisStatus; 00455 } 00456 #endif 00457 } 00458 00459 00460 NDIS_STATUS NTAPI 00461 ProSend( 00462 IN NDIS_HANDLE MacBindingHandle, 00463 IN PNDIS_PACKET Packet) 00464 /* 00465 * FUNCTION: Forwards a request to send a packet to an NDIS miniport 00466 * ARGUMENTS: 00467 * MacBindingHandle = Adapter binding handle 00468 * Packet = Pointer to NDIS packet descriptor 00469 * RETURNS: 00470 * NDIS_STATUS_SUCCESS if the packet was successfully sent 00471 * NDIS_STATUS_PENDING if the miniport was busy or a serialized miniport returned NDIS_STATUS_RESOURCES 00472 */ 00473 { 00474 PADAPTER_BINDING AdapterBinding; 00475 PLOGICAL_ADAPTER Adapter; 00476 PNDIS_BUFFER NdisBuffer; 00477 PDMA_CONTEXT Context; 00478 NDIS_STATUS NdisStatus; 00479 UINT PacketLength; 00480 KIRQL OldIrql; 00481 00482 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 00483 00484 ASSERT(MacBindingHandle); 00485 AdapterBinding = GET_ADAPTER_BINDING(MacBindingHandle); 00486 00487 ASSERT(AdapterBinding); 00488 Adapter = AdapterBinding->Adapter; 00489 00490 ASSERT(Adapter); 00491 00492 /* if the following is not true, KeRaiseIrql() below will break */ 00493 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); 00494 00495 /* XXX what is this crazy black magic? */ 00496 Packet->Reserved[1] = (ULONG_PTR)MacBindingHandle; 00497 00498 /* 00499 * Test the packet to see if it is a MAC loopback. 00500 * 00501 * We may have to loop this packet if miniport cannot. 00502 * If dest MAC address of packet == MAC address of adapter, 00503 * this is a loopback frame. 00504 */ 00505 00506 if ((Adapter->NdisMiniportBlock.MacOptions & NDIS_MAC_OPTION_NO_LOOPBACK) && 00507 MiniAdapterHasAddress(Adapter, Packet)) 00508 { 00509 #if WORKER_TEST 00510 MiniQueueWorkItem(Adapter, NdisWorkItemSendLoopback, Packet, FALSE); 00511 return NDIS_STATUS_PENDING; 00512 #else 00513 return ProIndicatePacket(Adapter, Packet); 00514 #endif 00515 } else { 00516 if (Adapter->NdisMiniportBlock.ScatterGatherListSize != 0) 00517 { 00518 NDIS_DbgPrint(MID_TRACE, ("Using Scatter/Gather DMA\n")); 00519 00520 NdisQueryPacket(Packet, 00521 NULL, 00522 NULL, 00523 &NdisBuffer, 00524 &PacketLength); 00525 00526 Context = ExAllocatePool(NonPagedPool, sizeof(DMA_CONTEXT)); 00527 if (!Context) { 00528 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n")); 00529 return NDIS_STATUS_RESOURCES; 00530 } 00531 00532 Context->Adapter = Adapter; 00533 Context->Packet = Packet; 00534 00535 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); 00536 00537 KeFlushIoBuffers(NdisBuffer, FALSE, TRUE); 00538 00539 NdisStatus = Adapter->NdisMiniportBlock.SystemAdapterObject->DmaOperations->GetScatterGatherList( 00540 Adapter->NdisMiniportBlock.SystemAdapterObject, 00541 Adapter->NdisMiniportBlock.PhysicalDeviceObject, 00542 NdisBuffer, 00543 MmGetMdlVirtualAddress(NdisBuffer), 00544 PacketLength, 00545 ScatterGatherSendPacket, 00546 Context, 00547 TRUE); 00548 00549 KeLowerIrql(OldIrql); 00550 00551 if (!NT_SUCCESS(NdisStatus)) { 00552 NDIS_DbgPrint(MIN_TRACE, ("GetScatterGatherList failed! (%x)\n", NdisStatus)); 00553 return NdisStatus; 00554 } 00555 00556 return NDIS_STATUS_PENDING; 00557 } 00558 00559 00560 return proSendPacketToMiniport(Adapter, Packet); 00561 } 00562 } 00563 00564 00565 VOID NTAPI 00566 ProSendPackets( 00567 IN NDIS_HANDLE NdisBindingHandle, 00568 IN PPNDIS_PACKET PacketArray, 00569 IN UINT NumberOfPackets) 00570 { 00571 PADAPTER_BINDING AdapterBinding = NdisBindingHandle; 00572 PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter; 00573 KIRQL RaiseOldIrql; 00574 NDIS_STATUS NdisStatus; 00575 UINT i; 00576 00577 if(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler) 00578 { 00579 if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE) 00580 { 00581 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)( 00582 Adapter->NdisMiniportBlock.MiniportAdapterContext, PacketArray, NumberOfPackets); 00583 } 00584 else 00585 { 00586 /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */ 00587 KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql); 00588 (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)( 00589 Adapter->NdisMiniportBlock.MiniportAdapterContext, PacketArray, NumberOfPackets); 00590 KeLowerIrql(RaiseOldIrql); 00591 for (i = 0; i < NumberOfPackets; i++) 00592 { 00593 NdisStatus = NDIS_GET_PACKET_STATUS(PacketArray[i]); 00594 if (NdisStatus != NDIS_STATUS_PENDING) 00595 MiniSendComplete(Adapter, PacketArray[i], NdisStatus); 00596 } 00597 } 00598 } 00599 else 00600 { 00601 if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE) 00602 { 00603 for (i = 0; i < NumberOfPackets; i++) 00604 { 00605 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)( 00606 Adapter->NdisMiniportBlock.MiniportAdapterContext, PacketArray[i], PacketArray[i]->Private.Flags); 00607 if (NdisStatus != NDIS_STATUS_PENDING) 00608 MiniSendComplete(Adapter, PacketArray[i], NdisStatus); 00609 } 00610 } 00611 else 00612 { 00613 /* Send is called at DISPATCH_LEVEL for all serialized miniports */ 00614 KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql); 00615 for (i = 0; i < NumberOfPackets; i++) 00616 { 00617 NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)( 00618 Adapter->NdisMiniportBlock.MiniportAdapterContext, PacketArray[i], PacketArray[i]->Private.Flags); 00619 if (NdisStatus != NDIS_STATUS_PENDING) 00620 MiniSendComplete(Adapter, PacketArray[i], NdisStatus); 00621 } 00622 KeLowerIrql(RaiseOldIrql); 00623 } 00624 } 00625 } 00626 00627 00628 NDIS_STATUS NTAPI 00629 ProTransferData( 00630 IN NDIS_HANDLE MacBindingHandle, 00631 IN NDIS_HANDLE MacReceiveContext, 00632 IN UINT ByteOffset, 00633 IN UINT BytesToTransfer, 00634 IN OUT PNDIS_PACKET Packet, 00635 OUT PUINT BytesTransferred) 00636 /* 00637 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet 00638 * ARGUMENTS: 00639 * MacBindingHandle = Adapter binding handle 00640 * MacReceiveContext = MAC receive context 00641 * ByteOffset = Offset in packet to place data 00642 * BytesToTransfer = Number of bytes to copy into packet 00643 * Packet = Pointer to NDIS packet descriptor 00644 * BytesTransferred = Address of buffer to place number of bytes copied 00645 */ 00646 { 00647 PADAPTER_BINDING AdapterBinding = GET_ADAPTER_BINDING(MacBindingHandle); 00648 PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter; 00649 NDIS_STATUS Status; 00650 KIRQL OldIrql; 00651 00652 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 00653 00654 /* FIXME: Interrupts must be disabled for adapter */ 00655 /* XXX sd - why is that true? */ 00656 00657 if (Adapter->NdisMiniportBlock.IndicatedPacket[KeGetCurrentProcessorNumber()]) { 00658 NDIS_DbgPrint(MAX_TRACE, ("LoopPacket\n")); 00659 /* NDIS is responsible for looping this packet */ 00660 NdisCopyFromPacketToPacket(Packet, 00661 ByteOffset + Adapter->MediumHeaderSize, 00662 BytesToTransfer + Adapter->MediumHeaderSize, 00663 Adapter->NdisMiniportBlock.IndicatedPacket[KeGetCurrentProcessorNumber()], 00664 0, 00665 BytesTransferred); 00666 return NDIS_STATUS_SUCCESS; 00667 } 00668 00669 ASSERT(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.TransferDataHandler); 00670 00671 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); 00672 00673 Status = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.TransferDataHandler)( 00674 Packet, 00675 BytesTransferred, 00676 Adapter->NdisMiniportBlock.MiniportAdapterContext, 00677 MacReceiveContext, 00678 ByteOffset, 00679 BytesToTransfer); 00680 00681 KeLowerIrql(OldIrql); 00682 00683 return Status; 00684 } 00685 00686 00687 00688 /* 00689 * @implemented 00690 */ 00691 VOID 00692 EXPORT 00693 NdisCloseAdapter( 00694 OUT PNDIS_STATUS Status, 00695 IN NDIS_HANDLE NdisBindingHandle) 00696 /* 00697 * FUNCTION: Closes an adapter opened with NdisOpenAdapter 00698 * ARGUMENTS: 00699 * Status = Address of buffer for status information 00700 * NdisBindingHandle = Handle returned by NdisOpenAdapter 00701 */ 00702 { 00703 PADAPTER_BINDING AdapterBinding = GET_ADAPTER_BINDING(NdisBindingHandle); 00704 00705 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 00706 00707 /* Remove from protocol's bound adapters list */ 00708 ExInterlockedRemoveEntryList(&AdapterBinding->ProtocolListEntry, &AdapterBinding->ProtocolBinding->Lock); 00709 00710 /* Remove protocol from adapter's bound protocols list */ 00711 ExInterlockedRemoveEntryList(&AdapterBinding->AdapterListEntry, &AdapterBinding->Adapter->NdisMiniportBlock.Lock); 00712 00713 ExFreePool(AdapterBinding); 00714 00715 *Status = NDIS_STATUS_SUCCESS; 00716 } 00717 00718 00719 /* 00720 * @implemented 00721 */ 00722 VOID 00723 EXPORT 00724 NdisDeregisterProtocol( 00725 OUT PNDIS_STATUS Status, 00726 IN NDIS_HANDLE NdisProtocolHandle) 00727 /* 00728 * FUNCTION: Releases the resources allocated by NdisRegisterProtocol 00729 * ARGUMENTS: 00730 * Status = Address of buffer for status information 00731 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol 00732 */ 00733 { 00734 PPROTOCOL_BINDING Protocol = GET_PROTOCOL_BINDING(NdisProtocolHandle); 00735 00736 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 00737 00738 /* FIXME: Make sure no adapter bindings exist */ 00739 00740 /* Remove protocol from global list */ 00741 ExInterlockedRemoveEntryList(&Protocol->ListEntry, &ProtocolListLock); 00742 00743 ExFreePool(Protocol); 00744 00745 *Status = NDIS_STATUS_SUCCESS; 00746 } 00747 00748 00749 /* 00750 * @implemented 00751 */ 00752 VOID 00753 EXPORT 00754 NdisOpenAdapter( 00755 OUT PNDIS_STATUS Status, 00756 OUT PNDIS_STATUS OpenErrorStatus, 00757 OUT PNDIS_HANDLE NdisBindingHandle, 00758 OUT PUINT SelectedMediumIndex, 00759 IN PNDIS_MEDIUM MediumArray, 00760 IN UINT MediumArraySize, 00761 IN NDIS_HANDLE NdisProtocolHandle, 00762 IN NDIS_HANDLE ProtocolBindingContext, 00763 IN PNDIS_STRING AdapterName, 00764 IN UINT OpenOptions, 00765 IN PSTRING AddressingInformation OPTIONAL) 00766 /* 00767 * FUNCTION: Opens an adapter for communication 00768 * ARGUMENTS: 00769 * Status = Address of buffer for status information 00770 * OpenErrorStatus = Address of buffer for secondary error code 00771 * NdisBindingHandle = Address of buffer for adapter binding handle 00772 * SelectedMediumIndex = Address of buffer for selected medium 00773 * MediumArray = Pointer to an array of NDIS_MEDIUMs called can support 00774 * MediumArraySize = Number of elements in MediumArray 00775 * NdisProtocolHandle = Handle returned by NdisRegisterProtocol 00776 * ProtocolBindingContext = Pointer to caller suplied context area 00777 * AdapterName = Pointer to buffer with name of adapter 00778 * OpenOptions = Bitmask with flags passed to next-lower driver 00779 * AddressingInformation = Optional pointer to buffer with NIC specific information 00780 */ 00781 { 00782 UINT i; 00783 BOOLEAN Found; 00784 PLOGICAL_ADAPTER Adapter; 00785 PADAPTER_BINDING AdapterBinding; 00786 PPROTOCOL_BINDING Protocol = GET_PROTOCOL_BINDING(NdisProtocolHandle); 00787 00788 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 00789 00790 if(!NdisProtocolHandle) 00791 { 00792 NDIS_DbgPrint(MIN_TRACE, ("NdisProtocolHandle is NULL\n")); 00793 *OpenErrorStatus = *Status = NDIS_STATUS_FAILURE; 00794 return; 00795 } 00796 00797 Adapter = MiniLocateDevice(AdapterName); 00798 if (!Adapter) 00799 { 00800 NDIS_DbgPrint(MIN_TRACE, ("Adapter not found.\n")); 00801 *Status = NDIS_STATUS_ADAPTER_NOT_FOUND; 00802 return; 00803 } 00804 00805 /* Find the media type in the list provided by the protocol driver */ 00806 Found = FALSE; 00807 for (i = 0; i < MediumArraySize; i++) 00808 { 00809 if (Adapter->NdisMiniportBlock.MediaType == MediumArray[i]) 00810 { 00811 *SelectedMediumIndex = i; 00812 Found = TRUE; 00813 break; 00814 } 00815 } 00816 00817 if (!Found) 00818 { 00819 NDIS_DbgPrint(MIN_TRACE, ("Medium is not supported.\n")); 00820 *Status = NDIS_STATUS_UNSUPPORTED_MEDIA; 00821 return; 00822 } 00823 00824 /* Now that we have confirmed that the adapter can be opened, create a binding */ 00825 00826 AdapterBinding = ExAllocatePool(NonPagedPool, sizeof(ADAPTER_BINDING)); 00827 if (!AdapterBinding) 00828 { 00829 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); 00830 *Status = NDIS_STATUS_RESOURCES; 00831 return; 00832 } 00833 00834 RtlZeroMemory(AdapterBinding, sizeof(ADAPTER_BINDING)); 00835 00836 AdapterBinding->ProtocolBinding = Protocol; 00837 AdapterBinding->Adapter = Adapter; 00838 AdapterBinding->NdisOpenBlock.ProtocolBindingContext = ProtocolBindingContext; 00839 00840 /* Set fields required by some NDIS macros */ 00841 AdapterBinding->NdisOpenBlock.BindingHandle = (NDIS_HANDLE)AdapterBinding; 00842 00843 /* Set handlers (some NDIS macros require these) */ 00844 00845 AdapterBinding->NdisOpenBlock.RequestHandler = ProRequest; 00846 AdapterBinding->NdisOpenBlock.ResetHandler = ProReset; 00847 AdapterBinding->NdisOpenBlock.SendHandler = ProSend; 00848 AdapterBinding->NdisOpenBlock.SendPacketsHandler = ProSendPackets; 00849 AdapterBinding->NdisOpenBlock.TransferDataHandler = ProTransferData; 00850 00851 AdapterBinding->NdisOpenBlock.RequestCompleteHandler = 00852 Protocol->Chars.RequestCompleteHandler; 00853 00854 /* Put on protocol's bound adapters list */ 00855 ExInterlockedInsertTailList(&Protocol->AdapterListHead, &AdapterBinding->ProtocolListEntry, &Protocol->Lock); 00856 00857 /* Put protocol on adapter's bound protocols list */ 00858 NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n")); 00859 ExInterlockedInsertTailList(&Adapter->ProtocolListHead, &AdapterBinding->AdapterListEntry, &Adapter->NdisMiniportBlock.Lock); 00860 00861 *NdisBindingHandle = (NDIS_HANDLE)AdapterBinding; 00862 00863 *Status = NDIS_STATUS_SUCCESS; 00864 } 00865 00866 PADAPTER_BINDING 00867 NTAPI 00868 LocateAdapterBindingByName(IN PPROTOCOL_BINDING ProtocolBinding, IN PNDIS_STRING AdapterName) 00869 { 00870 PLIST_ENTRY CurrentEntry; 00871 PADAPTER_BINDING AdapterBinding; 00872 KIRQL OldIrql; 00873 00874 KeAcquireSpinLock(&ProtocolBinding->Lock, &OldIrql); 00875 00876 CurrentEntry = ProtocolBinding->AdapterListHead.Flink; 00877 00878 while (CurrentEntry != &ProtocolBinding->AdapterListHead) 00879 { 00880 AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, ProtocolListEntry); 00881 00882 if (RtlCompareUnicodeString(AdapterName, &AdapterBinding->Adapter->NdisMiniportBlock.MiniportName, TRUE) == 0) 00883 { 00884 KeReleaseSpinLock(&ProtocolBinding->Lock, OldIrql); 00885 return AdapterBinding; 00886 } 00887 00888 CurrentEntry = CurrentEntry->Flink; 00889 } 00890 00891 KeReleaseSpinLock(&ProtocolBinding->Lock, OldIrql); 00892 00893 return NULL; 00894 } 00895 00896 VOID 00897 NTAPI 00898 ndisBindMiniportsToProtocol(OUT PNDIS_STATUS Status, IN PPROTOCOL_BINDING Protocol) 00899 { 00900 /* 00901 * bind the protocol to all of its miniports 00902 * 00903 * open registry path 00904 * get list of devices from Bind key 00905 * call BindAdapterHandler for each 00906 */ 00907 OBJECT_ATTRIBUTES ObjectAttributes; 00908 UNICODE_STRING RegistryPath; 00909 WCHAR *RegistryPathStr, *DataPtr = NULL; 00910 NTSTATUS NtStatus; 00911 HANDLE DriverKeyHandle = NULL; 00912 PKEY_VALUE_PARTIAL_INFORMATION KeyInformation = NULL; 00913 PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics = &Protocol->Chars; 00914 UNICODE_STRING ValueName; 00915 ULONG ResultLength; 00916 PLIST_ENTRY CurrentEntry = NULL; 00917 00918 RegistryPathStr = ExAllocatePoolWithTag(PagedPool, sizeof(SERVICES_KEY) + ProtocolCharacteristics->Name.Length + sizeof(LINKAGE_KEY), NDIS_TAG + __LINE__); 00919 if(!RegistryPathStr) 00920 { 00921 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); 00922 *Status = NDIS_STATUS_RESOURCES; 00923 return; 00924 } 00925 00926 wcscpy(RegistryPathStr, SERVICES_KEY); 00927 wcsncat(RegistryPathStr, ((WCHAR *)ProtocolCharacteristics->Name.Buffer), ProtocolCharacteristics->Name.Length / sizeof(WCHAR)); 00928 RegistryPathStr[wcslen(SERVICES_KEY)+ProtocolCharacteristics->Name.Length/sizeof(WCHAR)] = 0; 00929 wcscat(RegistryPathStr, LINKAGE_KEY); 00930 00931 RtlInitUnicodeString(&RegistryPath, RegistryPathStr); 00932 NDIS_DbgPrint(MAX_TRACE, ("Opening configuration key: %wZ\n", &RegistryPath)); 00933 00934 InitializeObjectAttributes(&ObjectAttributes, &RegistryPath, OBJ_CASE_INSENSITIVE, NULL, NULL); 00935 NtStatus = ZwOpenKey(&DriverKeyHandle, KEY_READ, &ObjectAttributes); 00936 00937 ExFreePool(RegistryPathStr); 00938 00939 if(NT_SUCCESS(NtStatus)) 00940 { 00941 NDIS_DbgPrint(MAX_TRACE, ("Successfully opened the registry configuration\n")); 00942 00943 RtlInitUnicodeString(&ValueName, L"Bind"); 00944 00945 NtStatus = ZwQueryValueKey(DriverKeyHandle, &ValueName, KeyValuePartialInformation, NULL, 0, &ResultLength); 00946 if(NtStatus != STATUS_BUFFER_OVERFLOW && NtStatus != STATUS_BUFFER_TOO_SMALL && NtStatus != STATUS_SUCCESS) 00947 { 00948 NDIS_DbgPrint(MIN_TRACE, ("Unable to query the Bind value for size\n")); 00949 ZwClose(DriverKeyHandle); 00950 } 00951 else 00952 { 00953 KeyInformation = ExAllocatePoolWithTag(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + ResultLength, NDIS_TAG + __LINE__); 00954 if(!KeyInformation) 00955 { 00956 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); 00957 ZwClose(DriverKeyHandle); 00958 NtStatus = STATUS_NO_MEMORY; 00959 } 00960 else 00961 { 00962 NtStatus = ZwQueryValueKey(DriverKeyHandle, &ValueName, KeyValuePartialInformation, KeyInformation, 00963 sizeof(KEY_VALUE_PARTIAL_INFORMATION) + ResultLength, &ResultLength); 00964 00965 ZwClose(DriverKeyHandle); 00966 00967 if(!NT_SUCCESS(NtStatus)) 00968 { 00969 NDIS_DbgPrint(MIN_TRACE, ("Unable to query the Bind value\n")); 00970 ExFreePool(KeyInformation); 00971 KeyInformation = NULL; 00972 } 00973 } 00974 } 00975 } 00976 00977 if (!NT_SUCCESS(NtStatus)) 00978 { 00979 NDIS_DbgPrint(MIN_TRACE, ("Performing global bind for protocol '%wZ'\n", &ProtocolCharacteristics->Name)); 00980 KeyInformation = NULL; 00981 00982 CurrentEntry = AdapterListHead.Flink; 00983 } 00984 else 00985 { 00986 NDIS_DbgPrint(MIN_TRACE, ("Performing standard bind for protocol '%wZ'\n", &ProtocolCharacteristics->Name)); 00987 00988 DataPtr = (WCHAR*)KeyInformation->Data; 00989 } 00990 00991 /* Assume success for now */ 00992 *Status = NDIS_STATUS_SUCCESS; 00993 00994 while (TRUE) 00995 { 00996 /* BindContext is for tracking pending binding operations */ 00997 VOID *BindContext = 0; 00998 NDIS_STRING DeviceName; 00999 NDIS_STRING RegistryPath; 01000 WCHAR *RegistryPathStr = NULL; 01001 ULONG PathLength = 0; 01002 PLOGICAL_ADAPTER Adapter; 01003 01004 if (KeyInformation) 01005 { 01006 /* Parse the REG_MULTI_SZ entry for device names */ 01007 if (!(*DataPtr)) 01008 break; 01009 01010 RtlInitUnicodeString(&DeviceName, DataPtr); 01011 } 01012 else 01013 { 01014 /* Use the device name from the global adapter list */ 01015 if (CurrentEntry == &AdapterListHead) 01016 break; 01017 01018 Adapter = CONTAINING_RECORD(CurrentEntry, LOGICAL_ADAPTER, ListEntry); 01019 01020 DeviceName = Adapter->NdisMiniportBlock.MiniportName; 01021 } 01022 01023 /* Make sure the adapter has started */ 01024 if (!MiniLocateDevice(&DeviceName)) 01025 { 01026 /* It wasn't in the global miniport list, so skip the bind entry */ 01027 goto next; 01028 } 01029 01030 /* Make sure this device isn't already bound to this protocol */ 01031 if (LocateAdapterBindingByName(Protocol, &DeviceName)) 01032 { 01033 /* It was already in this protocol's bound adapter list, so skip the bind entry */ 01034 goto next; 01035 } 01036 01037 /* 01038 * RegistryPath should be: 01039 * \Registry\Machine\System\CurrentControlSet\Services\Nic1\Parameters\Tcpip 01040 * 01041 * This is constructed as follows: 01042 * SERVICES_KEY + extracted device name + Protocol name from characteristics 01043 */ 01044 01045 PathLength = sizeof(SERVICES_KEY) + /* \Registry\Machine\System\CurrentControlSet\Services\ */ 01046 wcslen( DeviceName.Buffer + 8 ) * sizeof(WCHAR) + /* Adapter1 (extracted from \Device\Adapter1) */ 01047 sizeof(PARAMETERS_KEY) + /* \Parameters\ */ 01048 ProtocolCharacteristics->Name.Length + sizeof(WCHAR); /* Tcpip */ 01049 01050 RegistryPathStr = ExAllocatePool(PagedPool, PathLength); 01051 if(!RegistryPathStr) 01052 { 01053 NDIS_DbgPrint(MIN_TRACE, ("insufficient resources.\n")); 01054 *Status = NDIS_STATUS_RESOURCES; 01055 break; 01056 } 01057 01058 wcscpy(RegistryPathStr, SERVICES_KEY); 01059 wcscat(RegistryPathStr, DeviceName.Buffer + 8 ); 01060 wcscat(RegistryPathStr, PARAMETERS_KEY); 01061 wcsncat(RegistryPathStr, ProtocolCharacteristics->Name.Buffer, ProtocolCharacteristics->Name.Length / sizeof(WCHAR) ); 01062 01063 RegistryPathStr[PathLength/sizeof(WCHAR) - 1] = 0; 01064 01065 RtlInitUnicodeString(&RegistryPath, RegistryPathStr); 01066 01067 NDIS_DbgPrint(MAX_TRACE, ("Calling protocol's BindAdapter handler with DeviceName %wZ and RegistryPath %wZ\n", 01068 &DeviceName, &RegistryPath)); 01069 01070 { 01071 BIND_HANDLER BindHandler = ProtocolCharacteristics->BindAdapterHandler; 01072 if(BindHandler) 01073 { 01074 BindHandler(Status, BindContext, &DeviceName, &RegistryPath, 0); 01075 NDIS_DbgPrint(MIN_TRACE, ("%wZ's BindAdapter handler returned 0x%x for %wZ\n", &ProtocolCharacteristics->Name, *Status, &DeviceName)); 01076 } 01077 else 01078 NDIS_DbgPrint(MIN_TRACE, ("No protocol bind handler specified\n")); 01079 } 01080 01081 next: 01082 if (KeyInformation) 01083 { 01084 /* Advance to the next adapter in the REG_MULTI_SZ */ 01085 DataPtr += (DeviceName.Length / sizeof(WCHAR)) + 1; 01086 } 01087 else 01088 { 01089 /* Advance to the next adapter in the global list */ 01090 CurrentEntry = CurrentEntry->Flink; 01091 } 01092 } 01093 01094 if (KeyInformation) 01095 { 01096 ExFreePool(KeyInformation); 01097 } 01098 } 01099 01100 /* 01101 * @implemented 01102 */ 01103 VOID 01104 EXPORT 01105 NdisRegisterProtocol( 01106 OUT PNDIS_STATUS Status, 01107 OUT PNDIS_HANDLE NdisProtocolHandle, 01108 IN PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics, 01109 IN UINT CharacteristicsLength) 01110 /* 01111 * FUNCTION: Registers an NDIS driver's ProtocolXxx entry points 01112 * ARGUMENTS: 01113 * Status = Address of buffer for status information 01114 * NdisProtocolHandle = Address of buffer for handle used to identify the driver 01115 * ProtocolCharacteristics = Pointer to NDIS_PROTOCOL_CHARACTERISTICS structure 01116 * CharacteristicsLength = Size of structure which ProtocolCharacteristics targets 01117 * NOTES: 01118 * - you *must* set NdisProtocolHandle before doing anything that could wind up 01119 * getting BindAdapterHandler, as it will probably call OpenAdapter with this handle 01120 * - the above implies that the initialization of the protocol block must be complete 01121 * by then 01122 * TODO: 01123 * - break this function up - probably do a 'ndisRefreshProtocolBindings' function 01124 * - make this thing able to handle >1 protocol 01125 */ 01126 { 01127 PPROTOCOL_BINDING Protocol; 01128 NTSTATUS NtStatus; 01129 UINT MinSize; 01130 PNET_PNP_EVENT PnPEvent; 01131 01132 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 01133 01134 *NdisProtocolHandle = NULL; 01135 01136 /* first validate the PROTOCOL_CHARACTERISTICS */ 01137 switch (ProtocolCharacteristics->MajorNdisVersion) 01138 { 01139 case 0x03: 01140 /* we don't really want to support ndis3 drivers - so we complain for now */ 01141 NDIS_DbgPrint(MID_TRACE, ("NDIS 3 protocol attempting to register\n")); 01142 MinSize = sizeof(NDIS30_PROTOCOL_CHARACTERISTICS); 01143 break; 01144 01145 case 0x04: 01146 MinSize = sizeof(NDIS40_PROTOCOL_CHARACTERISTICS); 01147 break; 01148 01149 case 0x05: 01150 MinSize = sizeof(NDIS50_PROTOCOL_CHARACTERISTICS); 01151 break; 01152 01153 default: 01154 *Status = NDIS_STATUS_BAD_VERSION; 01155 NDIS_DbgPrint(MIN_TRACE, ("Incorrect characteristics size\n")); 01156 return; 01157 } 01158 01159 if (CharacteristicsLength < MinSize) 01160 { 01161 NDIS_DbgPrint(MIN_TRACE, ("Bad protocol characteristics.\n")); 01162 *Status = NDIS_STATUS_BAD_CHARACTERISTICS; 01163 return; 01164 } 01165 01166 /* set up the protocol block */ 01167 Protocol = ExAllocatePool(NonPagedPool, sizeof(PROTOCOL_BINDING)); 01168 if (!Protocol) 01169 { 01170 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); 01171 *Status = NDIS_STATUS_RESOURCES; 01172 return; 01173 } 01174 01175 RtlZeroMemory(Protocol, sizeof(PROTOCOL_BINDING)); 01176 RtlCopyMemory(&Protocol->Chars, ProtocolCharacteristics, MinSize); 01177 01178 NtStatus = RtlUpcaseUnicodeString(&Protocol->Chars.Name, &ProtocolCharacteristics->Name, TRUE); 01179 if (!NT_SUCCESS(NtStatus)) 01180 { 01181 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); 01182 ExFreePool(Protocol); 01183 *Status = NDIS_STATUS_RESOURCES; 01184 return; 01185 } 01186 01187 KeInitializeSpinLock(&Protocol->Lock); 01188 01189 InitializeListHead(&Protocol->AdapterListHead); 01190 01191 /* We must set this before the call to ndisBindMiniportsToProtocol because the protocol's 01192 * BindAdapter handler might need it */ 01193 01194 *NdisProtocolHandle = Protocol; 01195 01196 ndisBindMiniportsToProtocol(Status, Protocol); 01197 01198 /* Should we only send this if ndisBindMiniportsToProtocol succeeds? */ 01199 PnPEvent = ProSetupPnPEvent(NetEventBindsComplete, NULL, 0); 01200 if (PnPEvent) 01201 { 01202 if (Protocol->Chars.PnPEventHandler) 01203 { 01204 /* We call this with a NULL binding context because it affects all bindings */ 01205 NtStatus = (*Protocol->Chars.PnPEventHandler)(NULL, 01206 PnPEvent); 01207 01208 /* FIXME: We don't support this yet */ 01209 ASSERT(NtStatus != NDIS_STATUS_PENDING); 01210 } 01211 01212 ExFreePool(PnPEvent); 01213 } 01214 01215 if (*Status == NDIS_STATUS_SUCCESS) { 01216 ExInterlockedInsertTailList(&ProtocolListHead, &Protocol->ListEntry, &ProtocolListLock); 01217 } else { 01218 NDIS_DbgPrint(MIN_TRACE, ("Binding failed (%x)\n", *Status)); 01219 ExFreePool(Protocol); 01220 *NdisProtocolHandle = NULL; 01221 } 01222 } 01223 01224 01225 /* 01226 * @implemented 01227 */ 01228 VOID 01229 EXPORT 01230 NdisRequest( 01231 OUT PNDIS_STATUS Status, 01232 IN NDIS_HANDLE NdisBindingHandle, 01233 IN PNDIS_REQUEST NdisRequest) 01234 /* 01235 * FUNCTION: Forwards a request to an NDIS driver 01236 * ARGUMENTS: 01237 * Status = Address of buffer for status information 01238 * NdisBindingHandle = Adapter binding handle 01239 * NdisRequest = Pointer to request to perform 01240 */ 01241 { 01242 *Status = ProRequest(NdisBindingHandle, NdisRequest); 01243 } 01244 01245 01246 /* 01247 * @implemented 01248 */ 01249 VOID 01250 EXPORT 01251 NdisReset( 01252 OUT PNDIS_STATUS Status, 01253 IN NDIS_HANDLE NdisBindingHandle) 01254 { 01255 *Status = ProReset(NdisBindingHandle); 01256 } 01257 01258 01259 /* 01260 * @implemented 01261 */ 01262 #undef NdisSend 01263 VOID 01264 EXPORT 01265 NdisSend( 01266 OUT PNDIS_STATUS Status, 01267 IN NDIS_HANDLE NdisBindingHandle, 01268 IN PNDIS_PACKET Packet) 01269 /* 01270 * FUNCTION: Forwards a request to send a packet 01271 * ARGUMENTS: 01272 * Status = Address of buffer for status information 01273 * NdisBindingHandle = Adapter binding handle 01274 * Packet = Pointer to NDIS packet descriptor 01275 */ 01276 { 01277 *Status = ProSend(NdisBindingHandle, Packet); 01278 } 01279 01280 01281 /* 01282 * @implemented 01283 */ 01284 #undef NdisSendPackets 01285 VOID 01286 EXPORT 01287 NdisSendPackets( 01288 IN NDIS_HANDLE NdisBindingHandle, 01289 IN PPNDIS_PACKET PacketArray, 01290 IN UINT NumberOfPackets) 01291 { 01292 ProSendPackets(NdisBindingHandle, PacketArray, NumberOfPackets); 01293 } 01294 01295 01296 /* 01297 * @implemented 01298 */ 01299 #undef NdisTransferData 01300 VOID 01301 EXPORT 01302 NdisTransferData( 01303 OUT PNDIS_STATUS Status, 01304 IN NDIS_HANDLE NdisBindingHandle, 01305 IN NDIS_HANDLE MacReceiveContext, 01306 IN UINT ByteOffset, 01307 IN UINT BytesToTransfer, 01308 IN OUT PNDIS_PACKET Packet, 01309 OUT PUINT BytesTransferred) 01310 /* 01311 * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet 01312 * ARGUMENTS: 01313 * Status = Address of buffer for status information 01314 * NdisBindingHandle = Adapter binding handle 01315 * MacReceiveContext = MAC receive context 01316 * ByteOffset = Offset in packet to place data 01317 * BytesToTransfer = Number of bytes to copy into packet 01318 * Packet = Pointer to NDIS packet descriptor 01319 * BytesTransferred = Address of buffer to place number of bytes copied 01320 */ 01321 { 01322 *Status = ProTransferData(NdisBindingHandle, 01323 MacReceiveContext, 01324 ByteOffset, 01325 BytesToTransfer, 01326 Packet, 01327 BytesTransferred); 01328 } 01329 01330 /* 01331 * @implemented 01332 */ 01333 VOID 01334 NTAPI 01335 NdisReEnumerateProtocolBindings(IN NDIS_HANDLE NdisProtocolHandle) 01336 { 01337 NDIS_STATUS NdisStatus; 01338 01339 ndisBindMiniportsToProtocol(&NdisStatus, NdisProtocolHandle); 01340 } 01341 01342 01343 /* 01344 * @implemented 01345 */ 01346 VOID 01347 EXPORT 01348 NdisGetDriverHandle( 01349 IN PNDIS_HANDLE NdisBindingHandle, 01350 OUT PNDIS_HANDLE NdisDriverHandle) 01351 /* 01352 * FUNCTION: 01353 * ARGUMENTS: 01354 * NOTES: 01355 * NDIS 5.0 01356 */ 01357 { 01358 PADAPTER_BINDING Binding = (PADAPTER_BINDING)NdisBindingHandle; 01359 01360 if (!Binding) 01361 { 01362 NDIS_DbgPrint(MIN_TRACE, ("Bad binding handle\n")); 01363 *NdisDriverHandle = NULL; 01364 return; 01365 } 01366 01367 *NdisDriverHandle = Binding->Adapter->NdisMiniportBlock.DriverHandle; 01368 } 01369 01370 /* EOF */ Generated on Fri May 25 2012 04:22:11 for ReactOS by
1.7.6.1
|