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 User I/O driver 00004 * FILE: protocol.c 00005 * PURPOSE: Protocol stuff 00006 * PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org) 00007 */ 00008 00009 #include "ndisuio.h" 00010 00011 #define NDEBUG 00012 #include <debug.h> 00013 00014 VOID 00015 NTAPI 00016 NduOpenAdapterComplete(NDIS_HANDLE ProtocolBindingContext, 00017 NDIS_STATUS Status, 00018 NDIS_STATUS OpenStatus) 00019 { 00020 PNDISUIO_ADAPTER_CONTEXT AdapterContext = ProtocolBindingContext; 00021 00022 DPRINT("Asynchronous adapter open completed\n"); 00023 00024 /* Store the final status and signal the event */ 00025 AdapterContext->AsyncStatus = Status; 00026 KeSetEvent(&AdapterContext->AsyncEvent, IO_NO_INCREMENT, FALSE); 00027 } 00028 00029 VOID 00030 NTAPI 00031 NduCloseAdapterComplete(NDIS_HANDLE ProtocolBindingContext, 00032 NDIS_STATUS Status) 00033 { 00034 PNDISUIO_ADAPTER_CONTEXT AdapterContext = ProtocolBindingContext; 00035 00036 DPRINT("Asynchronous adapter close completed\n"); 00037 00038 /* Store the final status and signal the event */ 00039 AdapterContext->AsyncStatus = Status; 00040 KeSetEvent(&AdapterContext->AsyncEvent, IO_NO_INCREMENT, FALSE); 00041 } 00042 00043 VOID 00044 NTAPI 00045 NduSendComplete(NDIS_HANDLE ProtocolBindingContext, 00046 PNDIS_PACKET Packet, 00047 NDIS_STATUS Status) 00048 { 00049 PNDISUIO_ADAPTER_CONTEXT AdapterContext = ProtocolBindingContext; 00050 00051 DPRINT("Asynchronous adapter send completed\n"); 00052 00053 /* Store the final status and signal the event */ 00054 AdapterContext->AsyncStatus = Status; 00055 KeSetEvent(&AdapterContext->AsyncEvent, IO_NO_INCREMENT, FALSE); 00056 } 00057 00058 VOID 00059 NTAPI 00060 NduTransferDataComplete(NDIS_HANDLE ProtocolBindingContext, 00061 PNDIS_PACKET Packet, 00062 NDIS_STATUS Status, 00063 UINT BytesTransferred) 00064 { 00065 PNDISUIO_ADAPTER_CONTEXT AdapterContext = ProtocolBindingContext; 00066 00067 DPRINT("Asynchronous adapter transfer completed\n"); 00068 00069 /* Store the final status and signal the event */ 00070 AdapterContext->AsyncStatus = Status; 00071 KeSetEvent(&AdapterContext->AsyncEvent, IO_NO_INCREMENT, FALSE); 00072 } 00073 00074 VOID 00075 NTAPI 00076 NduResetComplete(NDIS_HANDLE ProtocolBindingContext, 00077 NDIS_STATUS Status) 00078 { 00079 PNDISUIO_ADAPTER_CONTEXT AdapterContext = ProtocolBindingContext; 00080 00081 DPRINT("Asynchronous adapter reset completed\n"); 00082 00083 /* Store the final status and signal the event */ 00084 AdapterContext->AsyncStatus = Status; 00085 KeSetEvent(&AdapterContext->AsyncEvent, IO_NO_INCREMENT, FALSE); 00086 } 00087 00088 VOID 00089 NTAPI 00090 NduRequestComplete(NDIS_HANDLE ProtocolBindingContext, 00091 PNDIS_REQUEST NdisRequest, 00092 NDIS_STATUS Status) 00093 { 00094 PNDISUIO_ADAPTER_CONTEXT AdapterContext = ProtocolBindingContext; 00095 00096 DPRINT("Asynchronous adapter request completed\n"); 00097 00098 /* Store the final status and signal the event */ 00099 AdapterContext->AsyncStatus = Status; 00100 KeSetEvent(&AdapterContext->AsyncEvent, IO_NO_INCREMENT, FALSE); 00101 } 00102 00103 NDIS_STATUS 00104 NTAPI 00105 NduReceive(NDIS_HANDLE ProtocolBindingContext, 00106 NDIS_HANDLE MacReceiveContext, 00107 PVOID HeaderBuffer, 00108 UINT HeaderBufferSize, 00109 PVOID LookAheadBuffer, 00110 UINT LookaheadBufferSize, 00111 UINT PacketSize) 00112 { 00113 PNDISUIO_ADAPTER_CONTEXT AdapterContext = ProtocolBindingContext; 00114 PNDISUIO_PACKET_ENTRY PacketEntry; 00115 PVOID PacketBuffer; 00116 PNDIS_PACKET Packet; 00117 NDIS_STATUS Status; 00118 UINT BytesTransferred; 00119 00120 DPRINT("Received a %d byte packet\n", PacketSize); 00121 00122 /* Discard if nobody is waiting for it */ 00123 if (AdapterContext->OpenCount == 0) 00124 return NDIS_STATUS_NOT_ACCEPTED; 00125 00126 /* Allocate a buffer to hold the packet data and header */ 00127 PacketBuffer = ExAllocatePool(NonPagedPool, PacketSize + HeaderBufferSize); 00128 if (!PacketBuffer) 00129 return NDIS_STATUS_NOT_ACCEPTED; 00130 00131 /* Allocate the packet descriptor and buffer */ 00132 Packet = CreatePacketFromPoolBuffer(AdapterContext, 00133 (PUCHAR)PacketBuffer + HeaderBufferSize, 00134 PacketSize); 00135 if (!Packet) 00136 { 00137 ExFreePool(PacketBuffer); 00138 return NDIS_STATUS_NOT_ACCEPTED; 00139 } 00140 00141 /* Transfer the packet data into our data buffer */ 00142 if (LookaheadBufferSize == PacketSize) 00143 { 00144 NdisCopyLookaheadData((PVOID)((PUCHAR)PacketBuffer + HeaderBufferSize), 00145 LookAheadBuffer, 00146 PacketSize, 00147 AdapterContext->MacOptions); 00148 BytesTransferred = PacketSize; 00149 } 00150 else 00151 { 00152 NdisTransferData(&Status, 00153 AdapterContext->BindingHandle, 00154 MacReceiveContext, 00155 0, 00156 PacketSize, 00157 Packet, 00158 &BytesTransferred); 00159 if (Status == NDIS_STATUS_PENDING) 00160 { 00161 KeWaitForSingleObject(&AdapterContext->AsyncEvent, 00162 Executive, 00163 KernelMode, 00164 FALSE, 00165 NULL); 00166 Status = AdapterContext->AsyncStatus; 00167 } 00168 if (Status != NDIS_STATUS_SUCCESS) 00169 { 00170 DPRINT1("Failed to transfer data with status 0x%x\n", Status); 00171 CleanupAndFreePacket(Packet, TRUE); 00172 return NDIS_STATUS_NOT_ACCEPTED; 00173 } 00174 } 00175 00176 /* Copy the header data */ 00177 RtlCopyMemory(PacketBuffer, HeaderBuffer, HeaderBufferSize); 00178 00179 /* Free the packet descriptor and buffers 00180 but not the pool because we still need it */ 00181 CleanupAndFreePacket(Packet, FALSE); 00182 00183 /* Allocate a packet entry from pool */ 00184 PacketEntry = ExAllocatePool(NonPagedPool, sizeof(NDISUIO_PACKET_ENTRY) + BytesTransferred + HeaderBufferSize - 1); 00185 if (!PacketEntry) 00186 { 00187 ExFreePool(PacketBuffer); 00188 return NDIS_STATUS_RESOURCES; 00189 } 00190 00191 /* Initialize the packet entry and copy in packet data */ 00192 PacketEntry->PacketLength = BytesTransferred + HeaderBufferSize; 00193 RtlCopyMemory(PacketEntry->PacketData, PacketBuffer, PacketEntry->PacketLength); 00194 00195 /* Free the old buffer */ 00196 ExFreePool(PacketBuffer); 00197 00198 /* Insert the packet on the adapter's packet list */ 00199 ExInterlockedInsertTailList(&AdapterContext->PacketList, 00200 &PacketEntry->ListEntry, 00201 &AdapterContext->Spinlock); 00202 00203 /* Signal the read event */ 00204 KeSetEvent(&AdapterContext->PacketReadEvent, 00205 IO_NETWORK_INCREMENT, 00206 FALSE); 00207 00208 return NDIS_STATUS_SUCCESS; 00209 } 00210 00211 VOID 00212 NTAPI 00213 NduReceiveComplete(NDIS_HANDLE ProtocolBindingContext) 00214 { 00215 /* No op */ 00216 } 00217 00218 VOID 00219 NTAPI 00220 NduStatus(NDIS_HANDLE ProtocolBindingContext, 00221 NDIS_STATUS GeneralStatus, 00222 PVOID StatusBuffer, 00223 UINT StatusBufferSize) 00224 { 00225 /* FIXME: Implement status tracking */ 00226 } 00227 00228 VOID 00229 NTAPI 00230 NduStatusComplete(NDIS_HANDLE ProtocolBindingContext) 00231 { 00232 /* FIXME: Implement status tracking */ 00233 } 00234 00235 static 00236 NDIS_STATUS 00237 UnbindAdapterByContext(PNDISUIO_ADAPTER_CONTEXT AdapterContext) 00238 { 00239 KIRQL OldIrql; 00240 PLIST_ENTRY CurrentEntry; 00241 PNDISUIO_OPEN_ENTRY OpenEntry; 00242 PNDISUIO_PACKET_ENTRY PacketEntry; 00243 NDIS_STATUS Status; 00244 00245 DPRINT("Unbinding adapter %wZ\n", &AdapterContext->DeviceName); 00246 00247 /* FIXME: We don't do anything with outstanding reads */ 00248 00249 /* Remove the adapter context from the global list */ 00250 KeAcquireSpinLock(&GlobalAdapterListLock, &OldIrql); 00251 RemoveEntryList(&AdapterContext->ListEntry); 00252 KeReleaseSpinLock(&GlobalAdapterListLock, OldIrql); 00253 00254 /* Free the device name string */ 00255 RtlFreeUnicodeString(&AdapterContext->DeviceName); 00256 00257 /* Invalidate all handles to this adapter */ 00258 CurrentEntry = AdapterContext->OpenEntryList.Flink; 00259 while (CurrentEntry != &AdapterContext->OpenEntryList) 00260 { 00261 OpenEntry = CONTAINING_RECORD(CurrentEntry, NDISUIO_OPEN_ENTRY, ListEntry); 00262 00263 /* Make sure the entry is sane */ 00264 ASSERT(OpenEntry->FileObject); 00265 00266 /* Remove the adapter context pointer */ 00267 ASSERT(AdapterContext == OpenEntry->FileObject->FsContext); 00268 OpenEntry->FileObject->FsContext = NULL; 00269 AdapterContext->OpenCount--; 00270 00271 /* Remove the open entry pointer */ 00272 ASSERT(OpenEntry == OpenEntry->FileObject->FsContext2); 00273 OpenEntry->FileObject->FsContext2 = NULL; 00274 00275 /* Move to the next entry */ 00276 CurrentEntry = CurrentEntry->Flink; 00277 00278 /* Free the open entry */ 00279 ExFreePool(OpenEntry); 00280 } 00281 00282 /* If this fails, we have a refcount mismatch somewhere */ 00283 ASSERT(AdapterContext->OpenCount == 0); 00284 00285 /* Free all pending packet entries */ 00286 CurrentEntry = AdapterContext->PacketList.Flink; 00287 while (CurrentEntry != &AdapterContext->PacketList) 00288 { 00289 PacketEntry = CONTAINING_RECORD(CurrentEntry, NDISUIO_PACKET_ENTRY, ListEntry); 00290 00291 /* Move to the next entry */ 00292 CurrentEntry = CurrentEntry->Flink; 00293 00294 /* Free the packet entry */ 00295 ExFreePool(PacketEntry); 00296 } 00297 00298 /* Send the close request */ 00299 NdisCloseAdapter(&Status, 00300 AdapterContext->BindingHandle); 00301 00302 /* Wait for a pending close */ 00303 if (Status == NDIS_STATUS_PENDING) 00304 { 00305 KeWaitForSingleObject(&AdapterContext->AsyncEvent, 00306 Executive, 00307 KernelMode, 00308 FALSE, 00309 NULL); 00310 Status = AdapterContext->AsyncStatus; 00311 } 00312 00313 /* Free the context */ 00314 ExFreePool(AdapterContext); 00315 00316 return Status; 00317 } 00318 00319 static 00320 NDIS_STATUS 00321 BindAdapterByName(PNDIS_STRING DeviceName) 00322 { 00323 NDIS_STATUS OpenErrorStatus; 00324 PNDISUIO_ADAPTER_CONTEXT AdapterContext; 00325 NDIS_MEDIUM SupportedMedia[1] = {NdisMedium802_3}; 00326 UINT SelectedMedium; 00327 NDIS_STATUS Status; 00328 NDIS_REQUEST Request; 00329 00330 /* Allocate the adapter context */ 00331 AdapterContext = ExAllocatePool(NonPagedPool, sizeof(*AdapterContext)); 00332 if (!AdapterContext) 00333 { 00334 return NDIS_STATUS_RESOURCES; 00335 } 00336 00337 /* Set up the adapter context */ 00338 RtlZeroMemory(AdapterContext, sizeof(*AdapterContext)); 00339 KeInitializeEvent(&AdapterContext->AsyncEvent, SynchronizationEvent, FALSE); 00340 KeInitializeEvent(&AdapterContext->PacketReadEvent, SynchronizationEvent, FALSE); 00341 KeInitializeSpinLock(&AdapterContext->Spinlock); 00342 InitializeListHead(&AdapterContext->PacketList); 00343 InitializeListHead(&AdapterContext->OpenEntryList); 00344 AdapterContext->OpenCount = 0; 00345 00346 AdapterContext->DeviceName.Length = 00347 AdapterContext->DeviceName.MaximumLength = DeviceName->Length; 00348 AdapterContext->DeviceName.Buffer = ExAllocatePool(NonPagedPool, DeviceName->Length); 00349 if (!AdapterContext->DeviceName.Buffer) 00350 { 00351 ExFreePool(AdapterContext); 00352 return NDIS_STATUS_RESOURCES; 00353 } 00354 00355 /* Copy the device name into the adapter context */ 00356 RtlCopyMemory(AdapterContext->DeviceName.Buffer, DeviceName->Buffer, DeviceName->Length); 00357 00358 DPRINT("Binding adapter %wZ\n", &AdapterContext->DeviceName); 00359 00360 /* Create the buffer pool */ 00361 NdisAllocateBufferPool(&Status, 00362 &AdapterContext->BufferPoolHandle, 00363 50); 00364 if (Status != NDIS_STATUS_SUCCESS) 00365 { 00366 DPRINT1("Failed to allocate buffer pool with status 0x%x\n", Status); 00367 RtlFreeUnicodeString(&AdapterContext->DeviceName); 00368 ExFreePool(AdapterContext); 00369 return Status; 00370 } 00371 00372 /* Create the packet pool */ 00373 NdisAllocatePacketPool(&Status, 00374 &AdapterContext->PacketPoolHandle, 00375 25, 00376 PROTOCOL_RESERVED_SIZE_IN_PACKET); 00377 if (Status != NDIS_STATUS_SUCCESS) 00378 { 00379 DPRINT1("Failed to allocate packet pool with status 0x%x\n", Status); 00380 NdisFreeBufferPool(AdapterContext->BufferPoolHandle); 00381 RtlFreeUnicodeString(&AdapterContext->DeviceName); 00382 ExFreePool(AdapterContext); 00383 return Status; 00384 } 00385 00386 /* Send the open request */ 00387 NdisOpenAdapter(&Status, 00388 &OpenErrorStatus, 00389 &AdapterContext->BindingHandle, 00390 &SelectedMedium, 00391 SupportedMedia, 00392 1, 00393 GlobalProtocolHandle, 00394 AdapterContext, 00395 DeviceName, 00396 0, 00397 NULL); 00398 00399 /* Wait for a pending open */ 00400 if (Status == NDIS_STATUS_PENDING) 00401 { 00402 KeWaitForSingleObject(&AdapterContext->AsyncEvent, 00403 Executive, 00404 KernelMode, 00405 FALSE, 00406 NULL); 00407 Status = AdapterContext->AsyncStatus; 00408 } 00409 00410 /* Check the final status */ 00411 if (Status != NDIS_STATUS_SUCCESS) 00412 { 00413 DPRINT1("Failed to open adapter for bind with status 0x%x\n", Status); 00414 NdisFreePacketPool(AdapterContext->PacketPoolHandle); 00415 NdisFreeBufferPool(AdapterContext->BufferPoolHandle); 00416 RtlFreeUnicodeString(&AdapterContext->DeviceName); 00417 ExFreePool(AdapterContext); 00418 return Status; 00419 } 00420 00421 /* Get the MAC options */ 00422 Request.RequestType = NdisRequestQueryInformation; 00423 Request.DATA.QUERY_INFORMATION.Oid = OID_GEN_MAC_OPTIONS; 00424 Request.DATA.QUERY_INFORMATION.InformationBuffer = &AdapterContext->MacOptions; 00425 Request.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(ULONG); 00426 NdisRequest(&Status, 00427 AdapterContext->BindingHandle, 00428 &Request); 00429 00430 /* Wait for a pending request */ 00431 if (Status == NDIS_STATUS_PENDING) 00432 { 00433 KeWaitForSingleObject(&AdapterContext->AsyncEvent, 00434 Executive, 00435 KernelMode, 00436 FALSE, 00437 NULL); 00438 Status = AdapterContext->AsyncStatus; 00439 } 00440 00441 /* Check the final status */ 00442 if (Status != NDIS_STATUS_SUCCESS) 00443 { 00444 NDIS_STATUS CloseStatus; 00445 00446 DPRINT1("Failed to get MAC options with status 0x%x\n", Status); 00447 00448 NdisCloseAdapter(&CloseStatus, 00449 AdapterContext->BindingHandle); 00450 if (CloseStatus == NDIS_STATUS_PENDING) 00451 { 00452 KeWaitForSingleObject(&AdapterContext->AsyncEvent, 00453 Executive, 00454 KernelMode, 00455 FALSE, 00456 NULL); 00457 } 00458 00459 NdisFreePacketPool(AdapterContext->PacketPoolHandle); 00460 NdisFreeBufferPool(AdapterContext->BufferPoolHandle); 00461 RtlFreeUnicodeString(&AdapterContext->DeviceName); 00462 ExFreePool(AdapterContext); 00463 return Status; 00464 } 00465 00466 /* Add the adapter context to the global list */ 00467 ExInterlockedInsertTailList(&GlobalAdapterList, 00468 &AdapterContext->ListEntry, 00469 &GlobalAdapterListLock); 00470 00471 return STATUS_SUCCESS; 00472 } 00473 00474 VOID 00475 NTAPI 00476 NduBindAdapter(PNDIS_STATUS Status, 00477 NDIS_HANDLE BindContext, 00478 PNDIS_STRING DeviceName, 00479 PVOID SystemSpecific1, 00480 PVOID SystemSpecific2) 00481 { 00482 /* Use our helper function to create a context for this adapter */ 00483 *Status = BindAdapterByName(DeviceName); 00484 } 00485 00486 VOID 00487 NTAPI 00488 NduUnbindAdapter(PNDIS_STATUS Status, 00489 NDIS_HANDLE ProtocolBindingContext, 00490 NDIS_HANDLE UnbindContext) 00491 { 00492 /* This is forced unbind. UnbindAdapterByContext() will take care of 00493 * invalidating file handles pointer to this adapter for us */ 00494 *Status = UnbindAdapterByContext(ProtocolBindingContext); 00495 } 00496 Generated on Sun May 27 2012 04:24:17 for ReactOS by
1.7.6.1
|