/*++ 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 #pragma hdrstop #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; PUNICODE_STRING RegPath; PNDIS_WRAPPER_HANDLE WrapperHandle; UNREFERENCED_PARAMETER (SystemSpecific3); DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO, ("==>NdisInitializeWrapper\n")); *NdisWrapperHandle = NULL; Status = NdisAllocateMemory((PVOID*)NdisWrapperHandle, sizeof(NDIS_WRAPPER_HANDLE) + sizeof(UNICODE_STRING) + ((PUNICODE_STRING)SystemSpecific2)->Length + sizeof(WCHAR), 0, HighestAcceptableMax); if (Status == NDIS_STATUS_SUCCESS) { WrapperHandle = (PNDIS_WRAPPER_HANDLE)(*NdisWrapperHandle); WrapperHandle->NdisWrapperDriver = (PDRIVER_OBJECT)SystemSpecific1; RegPath = (PUNICODE_STRING)((PUCHAR)WrapperHandle + sizeof(NDIS_WRAPPER_HANDLE)); RegPath->Buffer = (PWSTR)((PUCHAR)RegPath + sizeof(UNICODE_STRING)); RegPath->MaximumLength = RegPath->Length = ((PUNICODE_STRING)SystemSpecific2)->Length; NdisMoveMemory(RegPath->Buffer, ((PUNICODE_STRING)SystemSpecific2)->Buffer, RegPath->Length); WrapperHandle->NdisWrapperConfigurationHandle = RegPath; } DBGPRINT(DBG_COMP_ALL, 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 NdisMacInfo = (PNDIS_WRAPPER_HANDLE)NdisWrapperHandle; DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO, ("==>NdisTerminateWrapper\n")); UNREFERENCED_PARAMETER(SystemSpecific); if (NdisMacInfo != NULL) { NdisFreeMemory(NdisMacInfo, sizeof(NDIS_WRAPPER_HANDLE), 0); } DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO, ("<==NdisTerminateWrapper\n")); } // // Operating System Requests // // VOID NdisMapIoSpace( OUT PNDIS_STATUS Status, OUT PVOID * VirtualAddress, IN NDIS_HANDLE NdisAdapterHandle, IN NDIS_PHYSICAL_ADDRESS PhysicalAddress, IN UINT Length ) /*++ Routine Description: Map virtual memory address space onto a physical address. Arguments: Status - resulting status VirtualAddress - resulting address in virtual space. NdisAdapterHandle - value returned by NdisRegisterAdapter. PhysicalAddress - Physical address. Length - Size of requested memory mapping Return Value: none. --*/ { ULONG addressSpace = 0; ULONG NumberOfElements; ULONG BusNumber; NDIS_INTERFACE_TYPE BusType; PHYSICAL_ADDRESS PhysicalTemp; PCM_RESOURCE_LIST Resources, Resc; BOOLEAN Conflict; NTSTATUS NtStatus; PNDIS_ADAPTER_BLOCK AdptrP = (PNDIS_ADAPTER_BLOCK)(NdisAdapterHandle); PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)(NdisAdapterHandle); // // First check if any bus access is allowed // BusType = (AdptrP->DeviceObject != NULL) ? AdptrP->BusType : Miniport->BusType; BusNumber = (AdptrP->DeviceObject != NULL) ? AdptrP->BusNumber : Miniport->BusNumber; do { if ((BusType == (NDIS_INTERFACE_TYPE)-1) || (BusNumber == (ULONG)-1)) { *Status = NDIS_STATUS_FAILURE; break; } // // First check for resource conflict by expanding current resource list, // adding in the mapped space, and then re-submitting the resource list. // Resc = (AdptrP->DeviceObject != NULL) ? AdptrP->Resources : Miniport->Resources; if (Resc != NULL) { NumberOfElements = Resc->List[0].PartialResourceList.Count + 1; } else { NumberOfElements = 1; } // // First check for resource conflict by expanding current resource list, // adding in the mapped space, and then re-submitting the resource list. // Resources = (PCM_RESOURCE_LIST)ALLOC_FROM_POOL(sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * NumberOfElements, NDIS_TAG_RSRC_LIST); if (Resources == NULL) { *Status = NDIS_STATUS_RESOURCES; break; } if (Resc != NULL) { CopyMemory(Resources, Resc, sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * (NumberOfElements-1)); } else { // // Setup initial resource info -- NOTE: This is definitely a mini-port // ASSERT(AdptrP->DeviceObject == NULL); Resources->Count = 1; Resources->List[0].InterfaceType = Miniport->AdapterType; Resources->List[0].BusNumber = BusNumber; Resources->List[0].PartialResourceList.Version = 0; Resources->List[0].PartialResourceList.Revision = 0; Resources->List[0].PartialResourceList.Count = 0; } // // Setup memory // Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count].Type = CmResourceTypeMemory; Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count].ShareDisposition = CmResourceShareDeviceExclusive; Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count].Flags = CM_RESOURCE_MEMORY_READ_WRITE; Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count].u.Memory.Start = PhysicalAddress; Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count].u.Memory.Length = Length; Resources->List[0].PartialResourceList.Count++; // // Make the call // NtStatus = IoReportResourceUsage(NULL, ((AdptrP->DeviceObject != NULL) ? AdptrP->MacHandle->NdisMacInfo->NdisWrapperDriver : Miniport->DriverHandle->NdisDriverInfo->NdisWrapperDriver), NULL, 0, (AdptrP->DeviceObject != NULL) ? AdptrP->DeviceObject: Miniport->DeviceObject, Resources, sizeof(CM_RESOURCE_LIST) + (sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)*Resources->List[0].PartialResourceList.Count), TRUE, &Conflict); // // Check for conflict. // if (Resc != NULL) { FREE_POOL(Resc); } if (AdptrP->DeviceObject != NULL) { AdptrP->Resources = Resources; } else { Miniport->Resources = Resources; } if (Conflict || (NtStatus != STATUS_SUCCESS)) { if (Conflict) { // // Log an error // PIO_ERROR_LOG_PACKET errorLogEntry; volatile ULONG i; ULONG StringSize; PUCHAR Place; PWCH baseFileName; WCHAR Character; ULONG Value; baseFileName = ((AdptrP->DeviceObject != NULL) ? AdptrP->AdapterName.Buffer : Miniport->MiniportName.Buffer); // // Parse out the path name, leaving only the device name. // for (i = 0; i < ((AdptrP->DeviceObject != NULL) ? AdptrP->AdapterName.Length : Miniport->MiniportName.Length) / sizeof(WCHAR); i++) { // // If s points to a directory separator, set baseFileName to // the character after the separator. // if (((AdptrP->DeviceObject != NULL) ? AdptrP->AdapterName.Buffer[i] : Miniport->MiniportName.Buffer[i]) == OBJ_NAME_PATH_SEPARATOR) { baseFileName = ((AdptrP->DeviceObject != NULL) ? &(AdptrP->AdapterName.Buffer[++i]): &(Miniport->MiniportName.Buffer[++i])); } } StringSize = ((AdptrP->DeviceObject != NULL) ? AdptrP->AdapterName.MaximumLength : Miniport->MiniportName.MaximumLength) - (((ULONG)baseFileName) - ((AdptrP->DeviceObject != NULL) ? ((ULONG)AdptrP->AdapterName.Buffer) : ((ULONG)Miniport->MiniportName.Buffer))); errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(((AdptrP->DeviceObject != NULL) ? AdptrP->DeviceObject : Miniport->DeviceObject), (UCHAR)(sizeof(IO_ERROR_LOG_PACKET) + StringSize + 34)); // wstrlen("FFFFFFFFFFFFFFFF") * sizeof(WHCAR) + sizeof(UNICODE_NULL) if (errorLogEntry != NULL) { errorLogEntry->ErrorCode = EVENT_NDIS_MEMORY_CONFLICT; // // store the time // errorLogEntry->MajorFunctionCode = 0; errorLogEntry->RetryCount = 0; errorLogEntry->UniqueErrorValue = 0; errorLogEntry->FinalStatus = 0; errorLogEntry->SequenceNumber = 0; errorLogEntry->IoControlCode = 0; // // Set string information // if (StringSize != 0) { errorLogEntry->NumberOfStrings = 1; errorLogEntry->StringOffset = sizeof(IO_ERROR_LOG_PACKET); CopyMemory (((PUCHAR)errorLogEntry) + sizeof(IO_ERROR_LOG_PACKET), (PVOID)baseFileName, StringSize); Place = ((PUCHAR)errorLogEntry) + sizeof(IO_ERROR_LOG_PACKET) + StringSize; } else { Place = ((PUCHAR)errorLogEntry) + sizeof(IO_ERROR_LOG_PACKET); errorLogEntry->NumberOfStrings = 0; } errorLogEntry->NumberOfStrings++; // // Put in memory address // for (StringSize = 0; StringSize < 2; StringSize++) { if (StringSize == 0) { // // Do high part // Value = NdisGetPhysicalAddressHigh(PhysicalAddress); } else { // // Do Low part // Value = NdisGetPhysicalAddressLow(PhysicalAddress); } // // Convert value // for (i = 1; i <= (sizeof(ULONG) * 2); i++) { WCHAR c; c = (WCHAR)((Value >> (((sizeof(ULONG) * 2) - i) * 4)) & 0x0F); if (c <= 9) { Character = L'0' + c; } else { Character = L'A' + c - 10; } memcpy((PVOID)Place, (PVOID)&Character, sizeof(WCHAR)); Place += sizeof(WCHAR); } } Character = UNICODE_NULL; memcpy((PVOID)Place, (PVOID)&Character, sizeof(WCHAR)); // // write it out // IoWriteErrorLogEntry(errorLogEntry); } *Status = NDIS_STATUS_RESOURCE_CONFLICT; break; } *Status = NDIS_STATUS_FAILURE; break; } if (!HalTranslateBusAddress(BusType, BusNumber, PhysicalAddress, &addressSpace, &PhysicalTemp)) { // // It would be nice to return a better status here, but we only get // TRUE/FALSE back from HalTranslateBusAddress. // *Status = NDIS_STATUS_FAILURE; break; } if (addressSpace == 0) { // // memory space // *VirtualAddress = MmMapIoSpace(PhysicalTemp, (Length), FALSE); } else { // // I/O space // *VirtualAddress = (PVOID)(PhysicalTemp.LowPart); } *Status = NDIS_STATUS_SUCCESS; if (*VirtualAddress == NULL) { *Status = NDIS_STATUS_RESOURCES; } } while (FALSE); } VOID NdisAllocateDmaChannel( OUT PNDIS_STATUS Status, OUT PNDIS_HANDLE NdisDmaHandle, IN NDIS_HANDLE NdisAdapterHandle, IN PNDIS_DMA_DESCRIPTION DmaDescription, IN ULONG MaximumLength ) /*++ Routine Description: Sets up a DMA channel for future DMA operations. Arguments: Status - Returns the status of the request. NdisDmaHandle - Returns a handle used to specify this channel to future operations. NdisAdapterHandle - handle returned by NdisRegisterAdapter. DmaDescription - Details of the DMA channel. MaximumLength - The maximum length DMA transfer that will be done using this channel. Return Value: None. --*/ { // // For registering this set of resources // PCM_RESOURCE_LIST Resources; BOOLEAN Conflict; // // Needed to call HalGetAdapter. // DEVICE_DESCRIPTION DeviceDescription; // // Returned by HalGetAdapter. // PADAPTER_OBJECT AdapterObject; // // Map registers needed per channel. // ULONG MapRegistersNeeded; // // Map registers allowed per channel. // ULONG MapRegistersAllowed; // // Saves the structure we allocate for this channel. // PNDIS_DMA_BLOCK DmaBlock; // // Convert the handle to our internal structure. PNDIS_ADAPTER_BLOCK AdapterBlock = (PNDIS_ADAPTER_BLOCK) NdisAdapterHandle; PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK) NdisAdapterHandle; BOOLEAN IsAMiniport; // // Save our IRQL when we raise it to call IoAllocateAdapterChannel. // KIRQL OldIrql; ULONG NumberOfElements; NTSTATUS NtStatus; LARGE_INTEGER TimeoutValue; IsAMiniport = (AdapterBlock->DeviceObject == NULL); // // First check if any bus access is allowed // if (((IsAMiniport ? Miniport->BusType : AdapterBlock->BusType) == (NDIS_INTERFACE_TYPE)-1) || ((IsAMiniport ? Miniport->BusNumber : AdapterBlock->BusNumber) == (ULONG)-1)) { *Status = NDIS_STATUS_FAILURE; return; } // // First check for resource conflict by expanding current resource list, // adding in the mapped space, and then re-submitting the resource list. // if ((IsAMiniport ? Miniport->Resources : AdapterBlock->Resources) != NULL) { NumberOfElements = (IsAMiniport ? Miniport->Resources->List[0].PartialResourceList.Count : AdapterBlock->Resources->List[0].PartialResourceList.Count) + 1; } else { NumberOfElements = 1; } // // First check for resource conflict by expanding current resource list, // adding in the mapped space, and then re-submitting the resource list. // Resources = (PCM_RESOURCE_LIST)ALLOC_FROM_POOL(sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * NumberOfElements, NDIS_TAG_RSRC_LIST); if (Resources == NULL) { *Status = NDIS_STATUS_RESOURCES; return; } if ((IsAMiniport ? Miniport->Resources : AdapterBlock->Resources) != NULL) { CopyMemory(Resources, (IsAMiniport ? Miniport->Resources : AdapterBlock->Resources), sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * (NumberOfElements - 1)); } else { // // Setup initial resource info // ASSERT(IsAMiniport); Resources->Count = 1; Resources->List[0].InterfaceType = Miniport->AdapterType; Resources->List[0].BusNumber = Miniport->BusNumber; Resources->List[0].PartialResourceList.Version = 0; Resources->List[0].PartialResourceList.Revision = 0; Resources->List[0].PartialResourceList.Count = 0; } // // Setup DMA Channel // Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count].Type = CmResourceTypeDma; Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count].ShareDisposition = CmResourceShareDeviceExclusive; Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count].Flags = 0; Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count].u.Dma.Channel = (IsAMiniport ? Miniport->ChannelNumber : (DmaDescription->DmaChannelSpecified ? DmaDescription->DmaChannel : AdapterBlock->ChannelNumber)); Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count].u.Dma.Port = DmaDescription->DmaPort; Resources->List[0].PartialResourceList.Count++; // // Make the call // *Status = IoReportResourceUsage(NULL, (IsAMiniport ? Miniport->DriverHandle->NdisDriverInfo->NdisWrapperDriver : AdapterBlock->MacHandle->NdisMacInfo->NdisWrapperDriver), NULL, 0, (IsAMiniport ? Miniport->DeviceObject : AdapterBlock->DeviceObject), Resources, sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * Resources->List[0].PartialResourceList.Count, TRUE, &Conflict); if ((IsAMiniport ? Miniport->Resources : AdapterBlock->Resources) != NULL) { FREE_POOL((IsAMiniport ? Miniport->Resources : AdapterBlock->Resources)); } if (IsAMiniport) { Miniport->Resources = Resources; } else { AdapterBlock->Resources = Resources; } // // Check for conflict. // if (Conflict || (*Status != STATUS_SUCCESS)) { if (Conflict) { // // Log an error // PIO_ERROR_LOG_PACKET errorLogEntry; ULONG i; ULONG StringSize; PUCHAR Place; PWCH baseFileName; WCHAR Character; ULONG Value; baseFileName = (IsAMiniport ? Miniport->MiniportName.Buffer : AdapterBlock->AdapterName.Buffer); // // Parse out the path name, leaving only the device name. // for (i = 0; i < (IsAMiniport ? Miniport->MiniportName.Length : AdapterBlock->AdapterName.Length) / sizeof(WCHAR); i++) { // // If s points to a directory separator, set baseFileName to // the character after the separator. // if ((IsAMiniport ? Miniport->MiniportName.Buffer[i] : AdapterBlock->AdapterName.Buffer[i]) == OBJ_NAME_PATH_SEPARATOR) { baseFileName = (IsAMiniport ? &(Miniport->MiniportName.Buffer[++i]) : &(AdapterBlock->AdapterName.Buffer[++i])); } } StringSize = (IsAMiniport ? Miniport->MiniportName.MaximumLength : AdapterBlock->AdapterName.MaximumLength) - (((ULONG)baseFileName) - (IsAMiniport ? ((ULONG)Miniport->MiniportName.Buffer) : ((ULONG)AdapterBlock->AdapterName.Buffer))); errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry( (IsAMiniport ? Miniport->DeviceObject : AdapterBlock->DeviceObject), (UCHAR)(sizeof(IO_ERROR_LOG_PACKET) + StringSize + 6)); // wstrlen("99") * sizeof(WHCAR) + sizeof(UNICODE_NULL) if (errorLogEntry != NULL) { errorLogEntry->ErrorCode = EVENT_NDIS_DMA_CONFLICT; // // store the time // errorLogEntry->MajorFunctionCode = 0; errorLogEntry->RetryCount = 0; errorLogEntry->UniqueErrorValue = 0; errorLogEntry->FinalStatus = 0; errorLogEntry->SequenceNumber = 0; errorLogEntry->IoControlCode = 0; // // Set string information // if (StringSize != 0) { errorLogEntry->NumberOfStrings = 1; errorLogEntry->StringOffset = sizeof(IO_ERROR_LOG_PACKET); CopyMemory(((PUCHAR)errorLogEntry) + sizeof(IO_ERROR_LOG_PACKET), (PVOID)baseFileName, StringSize); Place = ((PUCHAR)errorLogEntry) + sizeof(IO_ERROR_LOG_PACKET) + StringSize; } else { Place = ((PUCHAR)errorLogEntry) + sizeof(IO_ERROR_LOG_PACKET); errorLogEntry->NumberOfStrings = 0; } errorLogEntry->NumberOfStrings++; // // Put in dma channel // Value = (IsAMiniport ? Miniport->ChannelNumber : AdapterBlock->ChannelNumber); // // Convert value // // I couldn't think of a better way to do this (with some // loop). If you find one, plz put it in. // if (Value > 9) { Character = L'0' + (WCHAR)(Value / 10); memcpy((PVOID)Place, (PVOID)&Character, sizeof(WCHAR)); Place += sizeof(WCHAR); Value -= 10; } Character = L'0' + (WCHAR)Value; memcpy((PVOID)Place, (PVOID)&Character, sizeof(WCHAR)); Place += sizeof(WCHAR); Character = UNICODE_NULL; memcpy((PVOID)Place, (PVOID)&Character, sizeof(WCHAR)); // // write it out // IoWriteErrorLogEntry(errorLogEntry); } *Status = NDIS_STATUS_RESOURCE_CONFLICT; return; } *Status = NDIS_STATUS_FAILURE; return; } // // Set up the device description; zero it out in case its // size changes. // ZeroMemory(&DeviceDescription, sizeof(DEVICE_DESCRIPTION)); DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION; DeviceDescription.Master = (BOOLEAN)(IsAMiniport ? MINIPORT_TEST_FLAG(Miniport, fMINIPORT_BUS_MASTER) : FALSE); DeviceDescription.ScatterGather = (BOOLEAN)(IsAMiniport ? MINIPORT_TEST_FLAG(Miniport, fMINIPORT_BUS_MASTER) : FALSE); DeviceDescription.DemandMode = DmaDescription->DemandMode; DeviceDescription.AutoInitialize = DmaDescription->AutoInitialize; DeviceDescription.Dma32BitAddresses = (BOOLEAN)(IsAMiniport ? MINIPORT_TEST_FLAG(Miniport, fMINIPORT_DMA_32_BIT_ADDRESSES) : FALSE); DeviceDescription.BusNumber = (IsAMiniport ? Miniport->BusNumber : AdapterBlock->BusNumber); DeviceDescription.DmaChannel = (IsAMiniport ? Miniport->ChannelNumber : (DmaDescription->DmaChannelSpecified ? DmaDescription->DmaChannel : AdapterBlock->ChannelNumber)); DeviceDescription.InterfaceType = (IsAMiniport ? Miniport->BusType : AdapterBlock->BusType); DeviceDescription.DmaWidth = DmaDescription->DmaWidth; DeviceDescription.DmaSpeed = DmaDescription->DmaSpeed; DeviceDescription.MaximumLength = MaximumLength; DeviceDescription.DmaPort = DmaDescription->DmaPort; MapRegistersNeeded = ((MaximumLength - 2) / PAGE_SIZE) + 2; // // Get the adapter object. // AdapterObject = HalGetAdapter (&DeviceDescription, &MapRegistersAllowed); if ((AdapterObject == NULL) || (MapRegistersAllowed < MapRegistersNeeded)) { *Status = NDIS_STATUS_RESOURCES; return; } // // Allocate storage for our DMA block. // DmaBlock = (PNDIS_DMA_BLOCK)ALLOC_FROM_POOL(sizeof(NDIS_DMA_BLOCK), NDIS_TAG_DMA); if (DmaBlock == (PNDIS_DMA_BLOCK)NULL) { *Status = NDIS_STATUS_RESOURCES; return; } // // Use this event to tell us when ndisAllocationExecutionRoutine // has been called. // INITIALIZE_EVENT(&DmaBlock->AllocationEvent); // // We save this to call IoFreeAdapterChannel later. // DmaBlock->SystemAdapterObject = AdapterObject; // // Now allocate the adapter channel. // RAISE_IRQL_TO_DISPATCH(&OldIrql); NtStatus = IoAllocateAdapterChannel( AdapterObject, (IsAMiniport ? Miniport->DeviceObject : AdapterBlock->DeviceObject), MapRegistersNeeded, ndisDmaExecutionRoutine, (PVOID)DmaBlock); LOWER_IRQL(OldIrql); if (!NT_SUCCESS(NtStatus)) { DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR, ("NDIS DMA AllocateAdapterChannel: %lx\n", NtStatus)); FREE_POOL(DmaBlock); *Status = NDIS_STATUS_RESOURCES; return; } TimeoutValue.QuadPart = Int32x32To64(100 * 1000, -10000); // // ndisDmaExecutionRoutine will set this event // when it has been called. // NtStatus = WAIT_FOR_OBJECT(&DmaBlock->AllocationEvent, &TimeoutValue); if (NtStatus != STATUS_SUCCESS) { DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR, ("NDIS DMA AllocateAdapterChannel: %lx\n", NtStatus)); FREE_POOL(DmaBlock); *Status = NDIS_STATUS_RESOURCES; return; } RESET_EVENT(&DmaBlock->AllocationEvent); // // We now have the DMA channel allocated, we are done. // DmaBlock->InProgress = FALSE; *NdisDmaHandle = (NDIS_HANDLE)DmaBlock; *Status = NDIS_STATUS_SUCCESS; } VOID NdisFreeDmaChannel( IN NDIS_HANDLE NdisDmaHandle ) /*++ Routine Description: Frees a DMA channel allocated with NdisAllocateDmaChannel. Arguments: NdisDmaHandle - Handle returned by NdisAllocateDmaChannel, indicating the DMA channel that is to be freed. Return Value: None. --*/ { KIRQL OldIrql; PNDIS_DMA_BLOCK DmaBlock = (PNDIS_DMA_BLOCK)NdisDmaHandle; RAISE_IRQL_TO_DISPATCH(&OldIrql); IoFreeAdapterChannel (DmaBlock->SystemAdapterObject); LOWER_IRQL(OldIrql); FREE_POOL(DmaBlock); } VOID NdisSetupDmaTransfer( OUT PNDIS_STATUS Status, IN PNDIS_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; PHYSICAL_ADDRESS LogicalAddress; 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; LogicalAddress = IoMapTransfer(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. // (VOID)IoFlushAdapterBuffers(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 PNDIS_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; BOOLEAN Successful; Successful = IoFlushAdapterBuffers(DmaBlock->SystemAdapterObject, (PMDL)Buffer, DmaBlock->MapRegisterBase, (PUCHAR)(MDL_VA(Buffer)) + Offset, Length, WriteToDevice); *Status = (Successful ? NDIS_STATUS_SUCCESS : NDIS_STATUS_RESOURCES); DmaBlock->InProgress = FALSE; } VOID NdisRegisterMac( OUT PNDIS_STATUS Status, OUT PNDIS_HANDLE NdisMacHandle, IN NDIS_HANDLE NdisWrapperHandle, IN NDIS_HANDLE MacMacContext, IN PNDIS_MAC_CHARACTERISTICS MacCharacteristics, IN UINT CharacteristicsLength ) /*++ Routine Description: Register an NDIS MAC. Arguments: Status - Returns the final status. NdisMacHandle - Returns a handle referring to this MAC. NdisWrapperHandle - Handle returned by NdisInitializeWrapper. MacMacContext - Context for calling MACUnloadMac and MACAddAdapter. MacCharacteritics - The NDIS_MAC_CHARACTERISTICS table. CharacteristicsLength - The length of MacCharacteristics. Return Value: None. --*/ { PNDIS_WRAPPER_HANDLE NdisMacInfo = (PNDIS_WRAPPER_HANDLE)(NdisWrapperHandle); PNDIS_MAC_BLOCK MacBlock; UNICODE_STRING Us; PWSTR pWch; USHORT i; UINT MemNeeded; KIRQL OldIrql; // // check that this is an NDIS 3.0 MAC. // DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO, ("==>NdisRegisterMac\n")); do { *NdisMacHandle = (NDIS_HANDLE)NULL; if (NdisMacInfo == NULL) { *Status = NDIS_STATUS_FAILURE; break; } IF_DBG(DBG_COMP_CONFIG, DBG_LEVEL_ERR) { BOOLEAN f = FALSE; if (DbgIsNull(MacCharacteristics->OpenAdapterHandler)) { DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR, ("RegisterMac: Null OpenAdapterHandler \n")); f = TRUE; } if (DbgIsNull(MacCharacteristics->CloseAdapterHandler)) { DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR, ("RegisterMac: Null CloseAdapterHandler \n")); f = TRUE; } if (DbgIsNull(MacCharacteristics->SendHandler)) { DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR, ("RegisterMac: Null SendHandler \n")); f = TRUE; } if (DbgIsNull(MacCharacteristics->TransferDataHandler)) { DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR, ("RegisterMac: Null TransferDataHandler \n")); f = TRUE; } if (DbgIsNull(MacCharacteristics->ResetHandler)) { DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR, ("RegisterMac: Null ResetHandler \n")); f = TRUE; } if (DbgIsNull(MacCharacteristics->RequestHandler)) { DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR, ("RegisterMac: Null RequestHandler \n")); f = TRUE; } if (DbgIsNull(MacCharacteristics->QueryGlobalStatisticsHandler)) { DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR, ("RegisterMac: Null QueryGlobalStatisticsHandler \n")); f = TRUE; } if (DbgIsNull(MacCharacteristics->UnloadMacHandler)) { DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR, ("RegisterMac: Null UnloadMacHandler \n")); f = TRUE; } if (DbgIsNull(MacCharacteristics->AddAdapterHandler)) { DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR, ("RegisterMac: Null AddAdapterHandler \n")); f = TRUE; } if (DbgIsNull(MacCharacteristics->RemoveAdapterHandler)) { DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR, ("RegisterMac: Null RemoveAdapterHandler \n")); f = TRUE; } if (f) DBGBREAK(DBG_COMP_CONFIG, DBG_LEVEL_ERR); } if ((MacCharacteristics->MajorNdisVersion != 3) || (MacCharacteristics->MinorNdisVersion != 0)) { *Status = NDIS_STATUS_BAD_VERSION; DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO, ("<==NdisRegisterMac\n")); break; } // // Check that CharacteristicsLength is enough. // if (CharacteristicsLength < sizeof(NDIS_MAC_CHARACTERISTICS)) { DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR, ("char len = %d < %d\n", CharacteristicsLength, sizeof(NDIS_MAC_CHARACTERISTICS))); *Status = NDIS_STATUS_BAD_CHARACTERISTICS; DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO, ("<==NdisRegisterMac\n")); break; } // // Allocate memory for the NDIS MAC block. // MemNeeded = sizeof(NDIS_MAC_BLOCK) + MacCharacteristics->Name.Length; // // Extract the base-name, determine its length and allocate that much more // Us = *(PUNICODE_STRING)(NdisMacInfo->NdisWrapperConfigurationHandle); for (i = Us.Length/sizeof(WCHAR), pWch = Us.Buffer + i - 1; i > 0; pWch --, i--) { if (*pWch == L'\\') { Us.Buffer = pWch + 1; Us.Length -= i*sizeof(WCHAR); Us.MaximumLength = Us.Length + sizeof(WCHAR); break; } } MemNeeded += Us.MaximumLength; MacBlock = (PNDIS_MAC_BLOCK)ALLOC_FROM_POOL(MemNeeded, NDIS_TAG_MAC_BLOCK); if (MacBlock == (PNDIS_MAC_BLOCK)NULL) { *Status = NDIS_STATUS_RESOURCES; DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO, ("<==NdisRegisterMac\n")); break; } ZeroMemory(MacBlock, MemNeeded); MacBlock->Length = MemNeeded; // // Copy over the characteristics table. // CopyMemory((PVOID)&MacBlock->MacCharacteristics, (PVOID)MacCharacteristics, sizeof(NDIS_MAC_CHARACTERISTICS)); // // Move buffer pointer to correct location (extra space at the end of // the characteristics table) // MacBlock->MacCharacteristics.Name.Buffer = (PWSTR)((PUCHAR)MacBlock + sizeof(NDIS_MAC_BLOCK)); // // Copy String over. // MacBlock->MacCharacteristics.Name.Length = MacBlock->MacCharacteristics.Name.MaximumLength = MacCharacteristics->Name.Length; CopyMemory(MacBlock->MacCharacteristics.Name.Buffer, MacCharacteristics->Name.Buffer, MacCharacteristics->Name.Length); // // Upcase the base-name and save it in the MiniBlock // MacBlock->BaseName.Buffer = (PWSTR)((PUCHAR)MacBlock->MacCharacteristics.Name.Buffer + MacCharacteristics->Name.Length); MacBlock->BaseName.Length = Us.Length; MacBlock->BaseName.MaximumLength = Us.MaximumLength; RtlUpcaseUnicodeString(&MacBlock->BaseName, &Us, FALSE); // // No adapters yet registered for this MAC. // MacBlock->AdapterQueue = (PNDIS_ADAPTER_BLOCK)NULL; MacBlock->MacMacContext = MacMacContext; // // Set up unload handler // NdisMacInfo->NdisWrapperDriver->DriverUnload = ndisUnload; // // Set up shutdown handler // NdisMacInfo->NdisWrapperDriver->MajorFunction[IRP_MJ_SHUTDOWN] = ndisShutdown; // // Set up the handlers for this driver (they all do nothing). // NdisMacInfo->NdisWrapperDriver->MajorFunction[IRP_MJ_CREATE] = ndisCreateIrpHandler; NdisMacInfo->NdisWrapperDriver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ndisDeviceControlIrpHandler; NdisMacInfo->NdisWrapperDriver->MajorFunction[IRP_MJ_CLEANUP] = ndisSuccessIrpHandler; NdisMacInfo->NdisWrapperDriver->MajorFunction[IRP_MJ_CLOSE] = ndisCloseIrpHandler; MacBlock->NdisMacInfo = NdisMacInfo; // // Use this event to tell us when all adapters are removed from the mac // during an unload // INITIALIZE_EVENT(&MacBlock->AdaptersRemovedEvent); MacBlock->Unloading = FALSE; NdisInitializeRef(&MacBlock->Ref); // Lock the init code down now - before we take the lock below InitReferencePackage(); // // Put MAC on global list. // ACQUIRE_SPIN_LOCK(&ndisDriverListLock, &OldIrql); MacBlock->NextMac = ndisMacDriverList; ndisMacDriverList = MacBlock; RELEASE_SPIN_LOCK(&ndisDriverListLock, OldIrql); *NdisMacHandle = (NDIS_HANDLE)MacBlock; if (NdisMacInfo->NdisWrapperConfigurationHandle) { *Status = ndisInitializeAllAdapterInstances(MacBlock, NULL); if (*Status != NDIS_STATUS_SUCCESS) { *Status = NDIS_STATUS_FAILURE; ndisDereferenceMac(MacBlock); } } else { *Status = NDIS_STATUS_FAILURE; } InitDereferencePackage(); DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO, ("<==NdisRegisterMac\n")); } while (FALSE); ASSERT(CURRENT_IRQL < DISPATCH_LEVEL); } VOID NdisDeregisterMac( OUT PNDIS_STATUS Status, IN NDIS_HANDLE NdisMacHandle ) /*++ Routine Description: Deregisters an NDIS MAC. Arguments: Status - Returns the status of the request. NdisMacHandle - The handle returned by NdisRegisterMac. Return Value: None. --*/ { PNDIS_MAC_BLOCK OldMacP = (PNDIS_MAC_BLOCK)NdisMacHandle; // // If the MAC is already closing, return. // *Status = NDIS_STATUS_SUCCESS; if (OldMacP == NULL) { return; } DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO, ("==>NdisDeregisterMac\n")); DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO, (" Mac %wZ being deregistered\n",&OldMacP->MacCharacteristics.Name)); IF_DBG(DBG_COMP_CONFIG, DBG_LEVEL_ERR) { if (DbgIsNull(NdisMacHandle)) { DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR, ("DeregisterMac: Null Handle\n")); DBGBREAK(DBG_COMP_CONFIG, DBG_LEVEL_ERR); } if (!DbgIsNonPaged(NdisMacHandle)) { DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR, ("DeregisterMac: Handle not in NonPaged Memory\n")); DBGBREAK(DBG_COMP_CONFIG, DBG_LEVEL_ERR); } } if (!NdisCloseRef(&OldMacP->Ref)) { DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO, ("<==NdisDeregisterMac\n")); return; } ASSERT(OldMacP->AdapterQueue == (PNDIS_ADAPTER_BLOCK)NULL); DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO, ("<==NdisDeregisterMac\n")); } NDIS_STATUS NdisRegisterAdapter( OUT PNDIS_HANDLE NdisAdapterHandle, IN NDIS_HANDLE NdisMacHandle, IN NDIS_HANDLE MacAdapterContext, IN NDIS_HANDLE WrapperConfigurationContext, IN PNDIS_STRING AdapterName, IN PVOID AdapterInformation ) /*++ Routine Description: Register an NDIS adapter. Arguments: NdisAdapterHandle - Returns a handle referring to this adapter. NdisMacHandle - A handle for a previously registered MAC. MacAdapterContext - A context for calls into this MAC. WrapperConfigurationContext - Context passed to MacAddAdapter. AdapterName - The name the adapter should be registered under. AdapterInformation - Contains adapter information. For future use. NULL for the meantime. Storage for it must be allocated by the caller. Return Value: The final status. --*/ { PNDIS_ADAPTER_BLOCK NewAdaptP = NULL; PDEVICE_OBJECT TmpDeviceP = NULL; PNDIS_WRAPPER_CONFIGURATION_HANDLE ConfigurationHandle; PNDIS_MAC_BLOCK TmpMacP; NTSTATUS NtStatus; NDIS_STRING NdisAdapterName = { 0 }; PHYSICAL_ADDRESS PortAddress; PHYSICAL_ADDRESS InitialPortAddress; ULONG addressSpace; PNDIS_ADAPTER_INFORMATION AdapterInfo = (PNDIS_ADAPTER_INFORMATION)AdapterInformation; BOOLEAN Conflict, ValidBus; PCM_RESOURCE_LIST Resources = NULL; LARGE_INTEGER TimeoutValue; BOOLEAN AllocateIndividualPorts = TRUE, DerefMacOnError = FALSE; ULONG i, Size; ULONG BusNumber; NDIS_INTERFACE_TYPE BusType; NDIS_STATUS Status; UNICODE_STRING DeviceName, UpcaseDeviceName; UNICODE_STRING SymbolicLink; WCHAR SymLnkBuf[40]; KIRQL OldIrql; ConfigurationHandle = (PNDIS_WRAPPER_CONFIGURATION_HANDLE)WrapperConfigurationContext; DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO, ("==>NdisRegisterAdapter\n")); IF_DBG(DBG_COMP_CONFIG, DBG_LEVEL_ERR) { BOOLEAN f = FALSE; if (DbgIsNull(NdisMacHandle)) { DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR, ("RegisterAdapter: Null Handle\n")); f = TRUE; } if (!DbgIsNonPaged(NdisMacHandle)) { DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR, ("RegisterAdapter: Handle not in NonPaged Memory\n")); f = TRUE; } if (DbgIsNull(MacAdapterContext)) { DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR, ("RegisterAdapter: Null Context\n")); f = TRUE; } if (!DbgIsNonPaged(MacAdapterContext)) { DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR, ("RegisterAdapter: Context not in NonPaged Memory\n")); f = TRUE; } if (f) DBGBREAK(DBG_COMP_CONFIG, DBG_LEVEL_ERR); } do { // // Increment the MAC's refernce count. // if (!ndisReferenceMac((PNDIS_MAC_BLOCK)NdisMacHandle)) { // // The MAC is closing. // Status = NDIS_STATUS_CLOSING; break; } DerefMacOnError = TRUE; // // Allocate the string structure and space for the string. This // must be allocated from nonpaged pool, because it is touched by // NdisWriteErrorLogEntry, which may be called from DPC level. // NdisAdapterName.Buffer = (PWSTR)ALLOC_FROM_POOL(AdapterName->MaximumLength, NDIS_TAG_NAME_BUF); if (NdisAdapterName.Buffer == NULL) { Status = NDIS_STATUS_RESOURCES; break; } NdisAdapterName.MaximumLength = AdapterName->MaximumLength; NdisAdapterName.Length = AdapterName->Length; CopyMemory(NdisAdapterName.Buffer, AdapterName->Buffer, AdapterName->MaximumLength); // // Create a device object for this adapter. // NtStatus = IoCreateDevice(((PNDIS_MAC_BLOCK)NdisMacHandle)->NdisMacInfo->NdisWrapperDriver, sizeof(NDIS_ADAPTER_BLOCK) + ConfigurationHandle->DriverBaseName->Length + sizeof(NDIS_WRAPPER_CONTEXT), AdapterName, FILE_DEVICE_PHYSICAL_NETCARD, 0, FALSE, // exclusive flag &TmpDeviceP); if (NtStatus != STATUS_SUCCESS) { Status = NDIS_STATUS_DEVICE_FAILED; break; } // // Create symbolic link for the device // SymbolicLink.Buffer = SymLnkBuf; SymbolicLink.Length = sizeof(L"\\DosDevices\\") - sizeof(WCHAR); SymbolicLink.MaximumLength = sizeof(SymLnkBuf); RtlCopyMemory(SymLnkBuf, L"\\DosDevices\\", sizeof(L"\\DosDevices\\")); RtlAppendUnicodeStringToString(&SymbolicLink, ConfigurationHandle->DriverBaseName); IoCreateSymbolicLink(&SymbolicLink, AdapterName); // // Initialize the NDIS adapter block in the device object extension // // *** NDIS_WRAPPER_CONTEXT has a higher alignment requirement than // NDIS_ADAPTER_BLOCK, so we put it first in the extension. // ASSERT((sizeof(NDIS_WRAPPER_CONTEXT) & 3) <= (sizeof(NDIS_ADAPTER_BLOCK) & 3)); NewAdaptP = (PNDIS_ADAPTER_BLOCK)((PNDIS_WRAPPER_CONTEXT)TmpDeviceP->DeviceExtension + 1); ZeroMemory(NewAdaptP, sizeof(NDIS_ADAPTER_BLOCK)); NewAdaptP->BaseName.Buffer = (PWSTR)((PUCHAR)NewAdaptP + sizeof(NDIS_ADAPTER_BLOCK)); NewAdaptP->BaseName.MaximumLength = NewAdaptP->BaseName.Length = ConfigurationHandle->DriverBaseName->Length; RtlUpcaseUnicodeString(&NewAdaptP->BaseName, ConfigurationHandle->DriverBaseName, FALSE); NewAdaptP->DeviceObject = TmpDeviceP; NewAdaptP->MacHandle = TmpMacP = (PNDIS_MAC_BLOCK)NdisMacHandle; NewAdaptP->MacAdapterContext = MacAdapterContext; NewAdaptP->AdapterName = NdisAdapterName; NewAdaptP->OpenQueue = (PNDIS_OPEN_BLOCK)NULL; NewAdaptP->WrapperContext = TmpDeviceP->DeviceExtension; // // Save the bus information in the adapter block // NewAdaptP->BusType = ConfigurationHandle->Db.BusType; NewAdaptP->BusId = ConfigurationHandle->Db.BusId; NewAdaptP->BusNumber = ConfigurationHandle->Db.BusNumber; NewAdaptP->SlotNumber = ConfigurationHandle->Db.SlotNumber; // // Get the BusNumber and BusType from the context // BusNumber = ConfigurationHandle->ParametersQueryTable[3].DefaultLength; if (ConfigurationHandle->ParametersQueryTable[3].DefaultType == (NDIS_INTERFACE_TYPE)-1) { BusType = (NDIS_INTERFACE_TYPE)-1; } else { BusType = AdapterInfo->AdapterType; } // // Check that if there is no bus number or no bus type that the driver is not // going to try to acquire any hardware resources // ValidBus = ((BusType != (NDIS_INTERFACE_TYPE)-1) && (BusNumber != (ULONG)-1)); if ((BusType == (NDIS_INTERFACE_TYPE)-1) || (BusNumber == (ULONG)-1)) { if ((AdapterInfo != NULL) && ((AdapterInfo->NumberOfPortDescriptors != 0) || (AdapterInfo->Master))) { // // Error out // Status = NDIS_STATUS_BAD_CHARACTERISTICS; break; } } // // Free up previously assigned Resource memory // if ((BusType == NdisInterfacePci) && (BusNumber != -1) && (AdapterInfo != NULL) && (TmpMacP->PciAssignedResources != NULL)) { TmpMacP->PciAssignedResources->Count = 0; NtStatus = IoReportResourceUsage(NULL, ((PNDIS_MAC_BLOCK)NdisMacHandle)->NdisMacInfo->NdisWrapperDriver, TmpMacP->PciAssignedResources, sizeof(CM_RESOURCE_LIST), NULL, NULL, 0, TRUE, &Conflict); FREE_POOL(TmpMacP->PciAssignedResources); TmpMacP->PciAssignedResources = NULL; } // // Calculate size of new buffer // Size = sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * (AdapterInfo->NumberOfPortDescriptors + (((AdapterInfo->Master == TRUE) && (AdapterInfo->AdapterType == NdisInterfaceIsa)) ? 1 : 0)); Resources = (PCM_RESOURCE_LIST)ALLOC_FROM_POOL(Size, NDIS_TAG_RSRC_LIST); if (Resources == NULL) { // // Error out // Status = NDIS_STATUS_RESOURCES; break; } // // Fix up counts // Resources->List[0].PartialResourceList.Count = 0; // // Setup resources for the ports // if (ValidBus) { if (AdapterInfo != NULL) { ULONG HighestPort; ULONG LowestPort; Resources->Count = 1; Resources->List[0].InterfaceType = AdapterInfo->AdapterType; Resources->List[0].BusNumber = BusNumber; Resources->List[0].PartialResourceList.Version = 0; Resources->List[0].PartialResourceList.Revision = 0; NewAdaptP->Resources = Resources; NewAdaptP->BusNumber = BusNumber; NewAdaptP->BusType = BusType; NewAdaptP->AdapterType = AdapterInfo->AdapterType; NewAdaptP->Master = AdapterInfo->Master; // // NewAdaptP->InitialPort and NumberOfPorts refer to the // union of all port mappings specified; the area must // cover all possible ports. We scan the list, keeping track // of the highest and lowest ports used. // if (AdapterInfo->NumberOfPortDescriptors > 0) { // // Setup port // LowestPort = AdapterInfo->PortDescriptors[0].InitialPort; HighestPort = LowestPort + AdapterInfo->PortDescriptors[0].NumberOfPorts; if (AdapterInfo->PortDescriptors[0].PortOffset == NULL) { AllocateIndividualPorts = FALSE; } for (i = 0; i < AdapterInfo->NumberOfPortDescriptors; i++) { Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count + i].Type = CmResourceTypePort; Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count + i].ShareDisposition = CmResourceShareDeviceExclusive; Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count + i].Flags = (AdapterInfo->AdapterType == NdisInterfaceInternal)? CM_RESOURCE_PORT_MEMORY : CM_RESOURCE_PORT_IO; Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count + i].u.Port.Start.QuadPart = (ULONG)AdapterInfo->PortDescriptors[i].InitialPort; Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count + i].u.Port.Length = AdapterInfo->PortDescriptors[i].NumberOfPorts; if (AdapterInfo->PortDescriptors[i].PortOffset == NULL) { AllocateIndividualPorts = FALSE; } if (AdapterInfo->PortDescriptors[i].InitialPort < LowestPort) { LowestPort = AdapterInfo->PortDescriptors[i].InitialPort; } if ((AdapterInfo->PortDescriptors[i].InitialPort + AdapterInfo->PortDescriptors[i].NumberOfPorts) > HighestPort) { HighestPort = AdapterInfo->PortDescriptors[i].InitialPort + AdapterInfo->PortDescriptors[i].NumberOfPorts; } } NewAdaptP->InitialPort = LowestPort; NewAdaptP->NumberOfPorts = HighestPort - LowestPort; } else { NewAdaptP->NumberOfPorts = 0; } Resources->List[0].PartialResourceList.Count += AdapterInfo->NumberOfPortDescriptors; } else { // // Error out // Status = NDIS_STATUS_FAILURE; break; } } NewAdaptP->BeingRemoved = FALSE; if (ValidBus) { // // Submit Resources // NtStatus = IoReportResourceUsage(NULL, ((PNDIS_MAC_BLOCK)NdisMacHandle)->NdisMacInfo->NdisWrapperDriver, NULL, 0, NewAdaptP->DeviceObject, Resources, sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * Resources->List[0].PartialResourceList.Count, TRUE, &Conflict); // // Check for conflict. // if (Conflict || (NtStatus != STATUS_SUCCESS)) { if (Conflict) { // // Log an error // PIO_ERROR_LOG_PACKET errorLogEntry; ULONG StringSize; PWCH baseFileName; baseFileName = NewAdaptP->AdapterName.Buffer; // // Parse out the path name, leaving only the device name. // for (i = 0; i < NewAdaptP->AdapterName.Length / sizeof(WCHAR); i++) { // // If s points to a directory separator, set baseFileName to // the character after the separator. // if (NewAdaptP->AdapterName.Buffer[i] == OBJ_NAME_PATH_SEPARATOR) { baseFileName = &(NewAdaptP->AdapterName.Buffer[++i]); } } StringSize = NewAdaptP->AdapterName.MaximumLength - (((ULONG)baseFileName) - ((ULONG)NewAdaptP->AdapterName.Buffer)) ; errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(TmpDeviceP, (UCHAR)(sizeof(IO_ERROR_LOG_PACKET) + StringSize)); if (errorLogEntry != NULL) { errorLogEntry->ErrorCode = EVENT_NDIS_IO_PORT_CONFLICT; // // store the time // errorLogEntry->MajorFunctionCode = 0; errorLogEntry->RetryCount = 0; errorLogEntry->UniqueErrorValue = 0; errorLogEntry->FinalStatus = 0; errorLogEntry->SequenceNumber = 0; errorLogEntry->IoControlCode = 0; // // Set string information // if (StringSize != 0) { errorLogEntry->NumberOfStrings = 1; errorLogEntry->StringOffset = sizeof(IO_ERROR_LOG_PACKET); CopyMemory (((PUCHAR)errorLogEntry) + sizeof(IO_ERROR_LOG_PACKET), (PVOID)baseFileName, StringSize); } else { errorLogEntry->NumberOfStrings = 0; } // // write it out // IoWriteErrorLogEntry(errorLogEntry); } Status = NDIS_STATUS_RESOURCE_CONFLICT; break; } Status = NDIS_STATUS_FAILURE; break; } // // If port mapping is needed, we do that. If the result // is in memory, we have to map it. We map only the // ports specified in AdapterInformation; the default // is to map the first 4K. // // Note that NumberOfPorts can only be 0 if AdapterInfo // is provided and explicitly sets it to 0, so in that // case it is OK to leave the adapter in a state where // a call to NdisXXXPort will probably crash (because // PortOffset will be undefined). // if (NewAdaptP->NumberOfPorts > 0) { if (AllocateIndividualPorts) { Status = NDIS_STATUS_SUCCESS; // // We get here if we are supposed to allocate ports on an // individual bases -- which implies that the driver will // be using the Raw functions. // // Get the system physical address for this card. The card uses // I/O space, except for "internal" Jazz devices which use // memory space. // for (i = 0; i < AdapterInfo->NumberOfPortDescriptors; i++) { addressSpace = (NewAdaptP->AdapterType == NdisInterfaceInternal) ? 0 : 1; InitialPortAddress.LowPart = AdapterInfo->PortDescriptors[i].InitialPort; InitialPortAddress.HighPart = 0; if (!HalTranslateBusAddress(NewAdaptP->BusType, // InterfaceType NewAdaptP->BusNumber, // BusNumber InitialPortAddress, // Bus Address &addressSpace, // AddressSpace &PortAddress)) // Translated address { Status = NDIS_STATUS_FAILURE; break; } if (addressSpace == 0) { // // memory space // *(AdapterInfo->PortDescriptors[i].PortOffset) = MmMapIoSpace(PortAddress, AdapterInfo->PortDescriptors[i].NumberOfPorts, FALSE); if (*(AdapterInfo->PortDescriptors[i].PortOffset) == NULL) { Status = NDIS_STATUS_RESOURCES; break; } } else { // // I/O space // *(AdapterInfo->PortDescriptors[i].PortOffset) = (PUCHAR)PortAddress.LowPart; } } if (!NT_SUCCESS(Status)) break; } else { // // The driver will not use the Raw functions, only the // old NdisRead and NdisWrite port functions. // // Get the system physical address for this card. The card uses // I/O space, except for "internal" Jazz devices which use // memory space. // addressSpace = (NewAdaptP->AdapterType == NdisInterfaceInternal) ? 0 : 1; InitialPortAddress.LowPart = NewAdaptP->InitialPort; InitialPortAddress.HighPart = 0; if (!HalTranslateBusAddress(NewAdaptP->BusType, // InterfaceType NewAdaptP->BusNumber, // BusNumber InitialPortAddress, // Bus Address &addressSpace, // AddressSpace &PortAddress)) // Translated address { Status = NDIS_STATUS_FAILURE; break; } if (addressSpace == 0) { // // memory space // NewAdaptP->InitialPortMapping = MmMapIoSpace(PortAddress, NewAdaptP->NumberOfPorts, FALSE); if (NewAdaptP->InitialPortMapping == NULL) { Status = NDIS_STATUS_RESOURCES; break; } NewAdaptP->InitialPortMapped = TRUE; } else { // // I/O space // NewAdaptP->InitialPortMapping = (PUCHAR)PortAddress.LowPart; NewAdaptP->InitialPortMapped = FALSE; } // // PortOffset holds the mapped address of port 0. // NewAdaptP->PortOffset = NewAdaptP->InitialPortMapping - NewAdaptP->InitialPort; } } else { // // Technically should not allow this, but do it until // all drivers register their info correctly. // NewAdaptP->PortOffset = 0; } } // // If the driver want to be called back now, use // supplied callback routine. // if ((AdapterInfo != NULL) && (AdapterInfo->ActivateCallback != NULL)) { Status = (*(AdapterInfo->ActivateCallback))((NDIS_HANDLE)NewAdaptP, MacAdapterContext, AdapterInfo->DmaChannel); if (Status != NDIS_STATUS_SUCCESS) { break; } } // // Set information from AdapterInformation. The call back // routine can set these values. // NewAdaptP->ChannelNumber = AdapterInfo->DmaChannel; NewAdaptP->PhysicalMapRegistersNeeded = AdapterInfo->PhysicalMapRegistersNeeded; NewAdaptP->MaximumPhysicalMapping = AdapterInfo->MaximumPhysicalMapping; // // Check for resource conflic on DmaChannel. // if (NewAdaptP->Master && ValidBus && (NewAdaptP->AdapterType == NdisInterfaceIsa)) { // // Put the DMA channel in the resource list. // Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count].Type = CmResourceTypeDma; Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count].ShareDisposition = CmResourceShareDeviceExclusive; Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count].Flags = 0; Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count].u.Dma.Channel = NewAdaptP->ChannelNumber; Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count].u.Dma.Port = 0; Resources->List[0].PartialResourceList.Count++; // // Submit Resources // NtStatus = IoReportResourceUsage(NULL, ((PNDIS_MAC_BLOCK)NdisMacHandle)->NdisMacInfo->NdisWrapperDriver, NULL, 0, NewAdaptP->DeviceObject, Resources, sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * Resources->List[0].PartialResourceList.Count, TRUE, &Conflict); // // Check for conflict. // if (Conflict || (NtStatus != STATUS_SUCCESS)) { if (Conflict) { // // Log an error // PIO_ERROR_LOG_PACKET errorLogEntry; ULONG StringSize; PWCH baseFileName; baseFileName = NewAdaptP->AdapterName.Buffer; // // Parse out the path name, leaving only the device name. // for (i = 0; i < NewAdaptP->AdapterName.Length / sizeof(WCHAR); i++) { // // If s points to a directory separator, set baseFileName to // the character after the separator. // if (NewAdaptP->AdapterName.Buffer[i] == OBJ_NAME_PATH_SEPARATOR) { baseFileName = &(NewAdaptP->AdapterName.Buffer[++i]); } } StringSize = NewAdaptP->AdapterName.MaximumLength - (((ULONG)baseFileName) - ((ULONG)NewAdaptP->AdapterName.Buffer)) ; errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(TmpDeviceP, (UCHAR)(sizeof(IO_ERROR_LOG_PACKET) + StringSize)); if (errorLogEntry != NULL) { if ((NewAdaptP->Master) && (NewAdaptP->AdapterType == Isa)) { errorLogEntry->ErrorCode = EVENT_NDIS_PORT_OR_DMA_CONFLICT; } else { errorLogEntry->ErrorCode = EVENT_NDIS_IO_PORT_CONFLICT; } // // store the time // errorLogEntry->MajorFunctionCode = 0; errorLogEntry->RetryCount = 0; errorLogEntry->UniqueErrorValue = 0; errorLogEntry->FinalStatus = 0; errorLogEntry->SequenceNumber = 0; errorLogEntry->IoControlCode = 0; // // Set string information // if (StringSize != 0) { errorLogEntry->NumberOfStrings = 1; errorLogEntry->StringOffset = sizeof(IO_ERROR_LOG_PACKET); CopyMemory (((PUCHAR)errorLogEntry) + sizeof(IO_ERROR_LOG_PACKET), (PVOID)baseFileName, StringSize); } else { errorLogEntry->NumberOfStrings = 0; } // // write it out // IoWriteErrorLogEntry(errorLogEntry); } Status = NDIS_STATUS_RESOURCE_CONFLICT; break; } Status = NDIS_STATUS_FAILURE; break; } } // // If the device is a busmaster, we get an adapter // object for it. // If map registers are needed, we loop, allocating an // adapter channel for each map register needed. // if ((NewAdaptP->Master) && ValidBus) { // // This is needed by HalGetAdapter. // DEVICE_DESCRIPTION DeviceDescription; // // Returned by HalGetAdapter. // ULONG MapRegistersAllowed; // // Returned by HalGetAdapter. // PADAPTER_OBJECT AdapterObject; // // Map registers needed per channel. // ULONG MapRegistersPerChannel; NTSTATUS Status; // // Allocate storage for holding the appropriate // information for each map register. // NewAdaptP->MapRegisters = (PMAP_REGISTER_ENTRY)ALLOC_FROM_POOL(sizeof(MAP_REGISTER_ENTRY) * NewAdaptP->PhysicalMapRegistersNeeded, NDIS_TAG_MAP_REG); if (NewAdaptP->MapRegisters == (PMAP_REGISTER_ENTRY)NULL) { Status = NDIS_STATUS_RESOURCES; break; } // // Use this event to tell us when ndisAllocationExecutionRoutine // has been called. // INITIALIZE_EVENT(&NewAdaptP->AllocationEvent); // // Set up the device description; zero it out in case its // size changes. // ZeroMemory(&DeviceDescription, sizeof(DEVICE_DESCRIPTION)); DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION; DeviceDescription.Master = TRUE; DeviceDescription.ScatterGather = TRUE; DeviceDescription.BusNumber = NewAdaptP->BusNumber; DeviceDescription.DmaChannel = NewAdaptP->ChannelNumber; DeviceDescription.InterfaceType = NewAdaptP->AdapterType; if (DeviceDescription.InterfaceType == NdisInterfaceIsa) { // // For ISA devices, the width is based on the DMA channel: // 0-3 == 8 bits, 5-7 == 16 bits. Timing is compatibility // mode. // if (NewAdaptP->ChannelNumber > 4) { DeviceDescription.DmaWidth = Width16Bits; } else { DeviceDescription.DmaWidth = Width8Bits; } DeviceDescription.DmaSpeed = Compatible; } else if ((DeviceDescription.InterfaceType == NdisInterfaceMca) || (DeviceDescription.InterfaceType == NdisInterfaceEisa) || (DeviceDescription.InterfaceType == NdisInterfacePci)) { DeviceDescription.Dma32BitAddresses = AdapterInfo->Dma32BitAddresses; DeviceDescription.DmaPort = 0; } DeviceDescription.MaximumLength = NewAdaptP->MaximumPhysicalMapping; // // Determine how many map registers we need per channel. // MapRegistersPerChannel = ((NewAdaptP->MaximumPhysicalMapping - 2) / PAGE_SIZE) + 2; // // Get the adapter object. // AdapterObject = HalGetAdapter (&DeviceDescription, &MapRegistersAllowed); if (AdapterObject == NULL) { Status = NDIS_STATUS_RESOURCES; break; } ASSERT (MapRegistersAllowed >= MapRegistersPerChannel); // // We save this to call IoFreeMapRegisters later. // NewAdaptP->SystemAdapterObject = AdapterObject; // // Now loop, allocating an adapter channel each time, then // freeing everything but the map registers. // for (i=0; iPhysicalMapRegistersNeeded; i++) { NewAdaptP->CurrentMapRegister = i; RAISE_IRQL_TO_DISPATCH(&OldIrql); Status = IoAllocateAdapterChannel(AdapterObject, NewAdaptP->DeviceObject, MapRegistersPerChannel, ndisAllocationExecutionRoutine, (PVOID)NewAdaptP); if (!NT_SUCCESS(Status)) { DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR, ("Failed to load driver because of\n")); DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR, ("insufficient map registers.\n")); DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR, ("AllocateAdapterChannel: %lx\n", Status)); FREE_POOL(Resources); for (; i != 0; i--) { IoFreeMapRegisters(NewAdaptP->SystemAdapterObject, NewAdaptP->MapRegisters[i-1].MapRegister, MapRegistersPerChannel); } LOWER_IRQL(OldIrql); Status = NDIS_STATUS_RESOURCES; break; } LOWER_IRQL(OldIrql); TimeoutValue.QuadPart = Int32x32To64(10 * 1000, -10000); // // ndisAllocationExecutionRoutine will set this event // when it has gotten FirstTranslationEntry. // NtStatus = WAIT_FOR_OBJECT(&NewAdaptP->AllocationEvent, &TimeoutValue); if (NtStatus != STATUS_SUCCESS) { DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR, ("NDIS DMA AllocateAdapterChannel: %lx\n", NtStatus)); FREE_POOL(Resources); RAISE_IRQL_TO_DISPATCH(&OldIrql); for (; i != 0; i--) { IoFreeMapRegisters(NewAdaptP->SystemAdapterObject, NewAdaptP->MapRegisters[i-1].MapRegister, MapRegistersPerChannel); } LOWER_IRQL(OldIrql); Status = NDIS_STATUS_RESOURCES; break; } RESET_EVENT(&NewAdaptP->AllocationEvent); } if (!NT_SUCCESS(Status)) break; } NdisInitializeRef(&NewAdaptP->Ref); if (!ndisQueueAdapterOnMac(NewAdaptP, TmpMacP)) { // // The MAC is closing, undo what we have done. // if (NewAdaptP->Master) { ULONG MapRegistersPerChannel = ((NewAdaptP->MaximumPhysicalMapping - 2) / PAGE_SIZE) + 2; for (i=0; iPhysicalMapRegistersNeeded; i++) { RAISE_IRQL_TO_DISPATCH(&OldIrql); IoFreeMapRegisters(NewAdaptP->SystemAdapterObject, NewAdaptP->MapRegisters[i].MapRegister, MapRegistersPerChannel); LOWER_IRQL(OldIrql); } } Status = NDIS_STATUS_CLOSING; break; } // // Add an extra reference because the wrapper is using the MAC // ndisReferenceAdapter(NewAdaptP); MacReferencePackage(); *NdisAdapterHandle = (NDIS_HANDLE)NewAdaptP; Status = NDIS_STATUS_SUCCESS; DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO, ("<==NdisRegisterAdapter\n")); } while (FALSE); if (Status != NDIS_STATUS_SUCCESS) { DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO, ("<==NdisRegisterAdapter\n")); if (NewAdaptP != NULL) { NdisWriteErrorLogEntry(NewAdaptP, Status, 0); } if (DerefMacOnError) { ndisDereferenceMac(TmpMacP); } if (NdisAdapterName.Buffer != NULL) { FREE_POOL(NdisAdapterName.Buffer); } if (TmpDeviceP != NULL) { IoDeleteDevice(TmpDeviceP); if (NewAdaptP->MapRegisters != NULL) { FREE_POOL(NewAdaptP->MapRegisters); } if (Resources != NULL) { FREE_POOL(Resources); } } } return Status; } NDIS_STATUS NdisDeregisterAdapter( IN NDIS_HANDLE NdisAdapterHandle ) /*++ Routine Description: Deregisters an NDIS adapter. Arguments: NdisAdapterHandle - The handle returned by NdisRegisterAdapter. Return Value: NDIS_STATUS_SUCCESS. --*/ { // // KillAdapter does all the work. // DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO, ("==>NdisDeregisterAdapter\n")); DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO, (" Deregistering Adapter %s\n", ((PNDIS_ADAPTER_BLOCK)NdisAdapterHandle)->AdapterName.Buffer)); IF_DBG(DBG_COMP_CONFIG, DBG_LEVEL_ERR) { if (DbgIsNull(NdisAdapterHandle)) { DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR, ("DeregisterAdapter: Null Handle\n")); DBGBREAK(DBG_COMP_CONFIG, DBG_LEVEL_ERR); } if (!DbgIsNonPaged(NdisAdapterHandle)) { DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR, ("DeregisterAdapter: Handle not in NonPaged Memory\n")); DBGBREAK(DBG_COMP_CONFIG, DBG_LEVEL_ERR); } } ndisKillAdapter((PNDIS_ADAPTER_BLOCK)NdisAdapterHandle); // // Remove reference from wrapper // ndisDereferenceAdapter((PNDIS_ADAPTER_BLOCK)NdisAdapterHandle); MacDereferencePackage(); DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO, ("<==NdisDeregisterAdapter\n")); return NDIS_STATUS_SUCCESS; } VOID NdisRegisterAdapterShutdownHandler( IN NDIS_HANDLE NdisAdapterHandle, IN PVOID ShutdownContext, IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler ) /*++ Routine Description: Registers an NDIS adapter. Arguments: NdisAdapterHandle - The handle returned by NdisRegisterAdapter. ShutdownContext - Context to pass the the handler, when called. ShutdownHandler - The Handler for the Adapter, to be called on shutdown. Return Value: NDIS_STATUS_SUCCESS. --*/ { PNDIS_ADAPTER_BLOCK Adapter = (PNDIS_ADAPTER_BLOCK) NdisAdapterHandle; PNDIS_WRAPPER_CONTEXT WrapperContext = Adapter->WrapperContext; if (WrapperContext->ShutdownHandler == NULL) { // // Store information // WrapperContext->ShutdownHandler = ShutdownHandler; WrapperContext->ShutdownContext = ShutdownContext; // // Register our shutdown handler for either a system shutdown // notification or a bugcheck. // IoRegisterShutdownNotification(Adapter->DeviceObject); KeInitializeCallbackRecord(&WrapperContext->BugcheckCallbackRecord); KeRegisterBugCheckCallback( &WrapperContext->BugcheckCallbackRecord,// callback record. (PVOID) ndisBugcheckHandler, // callback routine. (PVOID) WrapperContext, // free form buffer. sizeof(NDIS_WRAPPER_CONTEXT), // buffer size. "Ndis mac"); // component id. } } VOID NdisDeregisterAdapterShutdownHandler( IN NDIS_HANDLE NdisAdapterHandle ) /*++ Routine Description: Deregisters an NDIS adapter. Arguments: NdisAdapterHandle - The handle returned by NdisRegisterAdapter. Return Value: NDIS_STATUS_SUCCESS. --*/ { PNDIS_ADAPTER_BLOCK Adapter = (PNDIS_ADAPTER_BLOCK) NdisAdapterHandle; PNDIS_WRAPPER_CONTEXT WrapperContext = Adapter->WrapperContext; if (WrapperContext->ShutdownHandler != NULL) { // // Clear information // WrapperContext->ShutdownHandler = NULL; IoUnregisterShutdownNotification(Adapter->DeviceObject); KeDeregisterBugCheckCallback(&WrapperContext->BugcheckCallbackRecord); } } NDIS_STATUS NdisPciAssignResources( IN NDIS_HANDLE NdisMacHandle, IN NDIS_HANDLE NdisWrapperHandle, IN NDIS_HANDLE WrapperConfigurationContext, IN ULONG SlotNumber, OUT PNDIS_RESOURCE_LIST * AssignedResources ) /*++ Routine Description: This routine uses the Hal to assign a set of resources to a PCI device. Arguments: NdisMacHandle - Handle returned from NdisRegisterMac. NdisWrapperHandle - Handle returned from NdisInitializeWrapper. WrapperConfigurationContext - Handle passed to MacAddAdapter. SlotNumber - Slot number of the device. AssignedResources - The returned resources. Return Value: Status of the operation --*/ { NTSTATUS NdisStatus = NDIS_STATUS_FAILURE; NTSTATUS NtStatus; ULONG BusNumber; NDIS_INTERFACE_TYPE BusType; PRTL_QUERY_REGISTRY_TABLE KeyQueryTable; PCM_RESOURCE_LIST AllocatedResources = NULL; PNDIS_WRAPPER_HANDLE NdisMacInfo = (PNDIS_WRAPPER_HANDLE)NdisWrapperHandle; // // Get the BusNumber and the BusType from the Context here!! // KeyQueryTable = ((PNDIS_WRAPPER_CONFIGURATION_HANDLE)WrapperConfigurationContext)->ParametersQueryTable; BusType = (NDIS_INTERFACE_TYPE)KeyQueryTable[3].DefaultType; BusNumber = KeyQueryTable[3].DefaultLength; NtStatus = HalAssignSlotResources((PUNICODE_STRING)(NdisMacInfo->NdisWrapperConfigurationHandle), NULL, NdisMacInfo->NdisWrapperDriver, NULL, BusType, BusNumber, SlotNumber, &AllocatedResources); *AssignedResources = NULL; // Assume failure if (NtStatus == STATUS_SUCCESS) { // // Store resources into the driver wide block // ((PNDIS_MAC_BLOCK)NdisMacHandle)->PciAssignedResources = AllocatedResources; *AssignedResources = &(AllocatedResources->List[0].PartialResourceList); // // Update slot number since the driver can also scan and so the one // in the registry is probably invalid // KeyQueryTable[4].DefaultLength = SlotNumber; NdisStatus = NDIS_STATUS_SUCCESS; } return NdisStatus; }