/*++ Copyright (c) 1990-1995 Microsoft Corporation Module Name: config.c Abstract: NDIS wrapper functions for full mac drivers configuration/initialization Author: Sean Selitrennikoff (SeanSe) 05-Oct-93 Jameel Hyder (JameelH) 01-Jun-95 Re-organization/optimization Environment: Kernel mode, FSD Revision History: --*/ #include #include // // Define the module number for debug code. // #define MODULE_NUMBER MODULE_CONFIG // // Requests Used by MAC Drivers // // VOID NdisInitializeWrapper( OUT PNDIS_HANDLE NdisWrapperHandle, IN PVOID SystemSpecific1, IN PVOID SystemSpecific2, IN PVOID SystemSpecific3 ) /*++ Routine Description: Called at the beginning of every MAC's initialization routine. Arguments: NdisWrapperHandle - A MAC specific handle for the wrapper. SystemSpecific1, a pointer to the driver object for the MAC. SystemSpecific2, a PUNICODE_STRING containing the location of the registry subtree for this driver. SystemSpecific3, unused on NT. Return Value: None. --*/ { NDIS_STATUS Status; PNDIS_WRAPPER_HANDLE WrapperHandle; ULONG cbSize; UNREFERENCED_PARAMETER (SystemSpecific3); #if TRACK_UNLOAD DbgPrint("NdisInitializeWrapper: DriverObject %p\n",SystemSpecific1); #endif DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO, ("==>NdisInitializeWrapper\n")); *NdisWrapperHandle = NULL; cbSize = sizeof(NDIS_WRAPPER_HANDLE) + ((PUNICODE_STRING)SystemSpecific2)->Length + sizeof(WCHAR); WrapperHandle = (PNDIS_WRAPPER_HANDLE)ALLOC_FROM_POOL(cbSize, NDIS_TAG_WRAPPER_HANDLE); if (WrapperHandle != NULL) { *NdisWrapperHandle = WrapperHandle; NdisZeroMemory(WrapperHandle, cbSize); WrapperHandle->DriverObject = (PDRIVER_OBJECT)SystemSpecific1; WrapperHandle->ServiceRegPath.Buffer = (PWSTR)((PUCHAR)WrapperHandle + sizeof(NDIS_WRAPPER_HANDLE)); WrapperHandle->ServiceRegPath.Length = ((PUNICODE_STRING)SystemSpecific2)->Length; WrapperHandle->ServiceRegPath.MaximumLength = WrapperHandle->ServiceRegPath.Length + sizeof(WCHAR); NdisMoveMemory(WrapperHandle->ServiceRegPath.Buffer, ((PUNICODE_STRING)SystemSpecific2)->Buffer, WrapperHandle->ServiceRegPath.Length); } DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO, ("<==NdisInitializeWrapper\n")); } VOID NdisTerminateWrapper( IN NDIS_HANDLE NdisWrapperHandle, IN PVOID SystemSpecific ) /*++ Routine Description: Called at the end of every MAC's termination routine. Arguments: NdisWrapperHandle - The handle returned from NdisInitializeWrapper. SystemSpecific - No defined value. Return Value: None. --*/ { PNDIS_WRAPPER_HANDLE WrapperHandle = (PNDIS_WRAPPER_HANDLE)NdisWrapperHandle; PNDIS_M_DRIVER_BLOCK MiniBlock; #if TRACK_UNLOAD DbgPrint("NdisTerminateWrapper: WrapperHandle %p\n",WrapperHandle); #endif DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO, ("==>NdisTerminateWrapper: NdisWrapperHandle %p\n", NdisWrapperHandle)); UNREFERENCED_PARAMETER(SystemSpecific); if ((WrapperHandle != NULL) && (WrapperHandle->DriverObject != NULL)) { #if TRACK_UNLOAD DbgPrint("NdisTerminateWrapper: DriverObject %p\n",WrapperHandle->DriverObject); #endif MiniBlock = (PNDIS_M_DRIVER_BLOCK)IoGetDriverObjectExtension(WrapperHandle->DriverObject, (PVOID)NDIS_PNP_MINIPORT_DRIVER_ID); if (MiniBlock != NULL) { #if TRACK_UNLOAD DbgPrint("NdisTerminateWrapper: MiniBlock %p\n",MiniBlock); #endif MiniBlock->Flags |= fMINIBLOCK_RECEIVED_TERMINATE_WRAPPER; // // Miniports should not be terminating the wrapper unless they are failing DriverEntry // if ((MiniBlock->MiniportQueue != NULL) || (MiniBlock->Flags & fMINIBLOCK_UNLOADING)) { DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO, ("<==NdisTerminateWrapper\n")); return; } DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO, ("NdisTerminateWrapper: MiniBlock %p\n", MiniBlock)); // // if the driver is going to fail DriverEntry, we expect it to have enough sense // to undo what it is done so far and not to wait for UnloadHandler // MiniBlock->UnloadHandler = NULL; MiniBlock->Flags |= fMINIBLOCK_TERMINATE_WRAPPER_UNLOAD; // // call unload entry point since PnP is not going to do it // ndisMUnload(WrapperHandle->DriverObject); } else { FREE_POOL(WrapperHandle); } } DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO, ("<==NdisTerminateWrapper\n")); } VOID NdisSetupDmaTransfer( OUT PNDIS_STATUS Status, IN NDIS_HANDLE NdisDmaHandle, IN PNDIS_BUFFER Buffer, IN ULONG Offset, IN ULONG Length, IN BOOLEAN WriteToDevice ) /*++ Routine Description: Sets up the host DMA controller for a DMA transfer. The DMA controller is set up to transfer the specified MDL. Since we register all DMA channels as non-scatter/gather, IoMapTransfer will ensure that the entire MDL is in a single logical piece for transfer. Arguments: Status - Returns the status of the request. NdisDmaHandle - Handle returned by NdisAllocateDmaChannel. Buffer - An NDIS_BUFFER which describes the host memory involved in the transfer. Offset - An offset within buffer where the transfer should start. Length - The length of the transfer. VirtualAddress plus Length must not extend beyond the end of the buffer. WriteToDevice - TRUE for a download operation (host to adapter); FALSE for an upload operation (adapter to host). Return Value: None. --*/ { PNDIS_DMA_BLOCK DmaBlock = (PNDIS_DMA_BLOCK)NdisDmaHandle; PMAP_TRANSFER mapTransfer = *((PDMA_ADAPTER)DmaBlock->SystemAdapterObject)->DmaOperations->MapTransfer; PFLUSH_ADAPTER_BUFFERS flushAdapterBuffers = *((PDMA_ADAPTER)DmaBlock->SystemAdapterObject)->DmaOperations->FlushAdapterBuffers; ULONG LengthMapped; // // Make sure another request is not in progress. // if (DmaBlock->InProgress) { *Status = NDIS_STATUS_RESOURCES; return; } DmaBlock->InProgress = TRUE; // // Use IoMapTransfer to set up the transfer. // LengthMapped = Length; mapTransfer(DmaBlock->SystemAdapterObject, (PMDL)Buffer, DmaBlock->MapRegisterBase, (PUCHAR)(MDL_VA(Buffer)) + Offset, &LengthMapped, WriteToDevice); if (LengthMapped != Length) { // // Somehow the request could not be mapped competely, // this should not happen for a non-scatter/gather adapter. // flushAdapterBuffers(DmaBlock->SystemAdapterObject, (PMDL)Buffer, DmaBlock->MapRegisterBase, (PUCHAR)(MDL_VA(Buffer)) + Offset, LengthMapped, WriteToDevice); DmaBlock->InProgress = FALSE; *Status = NDIS_STATUS_RESOURCES; } else *Status = NDIS_STATUS_SUCCESS; } VOID NdisCompleteDmaTransfer( OUT PNDIS_STATUS Status, IN NDIS_HANDLE NdisDmaHandle, IN PNDIS_BUFFER Buffer, IN ULONG Offset, IN ULONG Length, IN BOOLEAN WriteToDevice ) /*++ Routine Description: Completes a previously started DMA transfer. Arguments: Status - Returns the status of the transfer. NdisDmaHandle - Handle returned by NdisAllocateDmaChannel. Buffer - An NDIS_BUFFER which was passed to NdisSetupDmaTransfer. Offset - the offset passed to NdisSetupDmaTransfer. Length - The length passed to NdisSetupDmaTransfer. WriteToDevice - TRUE for a download operation (host to adapter); FALSE for an upload operation (adapter to host). Return Value: None. --*/ { PNDIS_DMA_BLOCK DmaBlock = (PNDIS_DMA_BLOCK)NdisDmaHandle; PFLUSH_ADAPTER_BUFFERS flushAdapterBuffers = *((PDMA_ADAPTER)DmaBlock->SystemAdapterObject)->DmaOperations->FlushAdapterBuffers; BOOLEAN Successful; Successful = flushAdapterBuffers(DmaBlock->SystemAdapterObject, (PMDL)Buffer, DmaBlock->MapRegisterBase, (PUCHAR)(MDL_VA(Buffer)) + Offset, Length, WriteToDevice); *Status = (Successful ? NDIS_STATUS_SUCCESS : NDIS_STATUS_RESOURCES); DmaBlock->InProgress = FALSE; } #pragma hdrstop