PUCHAR SoundMapPortAddress( INTERFACE_TYPE BusType, ULONG BusNumber, ULONG PortBase, ULONG Length, PULONG MemType ) /*++ Routine Description : Map a physical device port address to an address we can pass to READ/WRITE_PORT_UCHAR/USHORT etc Arguments : BusType - type of bus BusNumber - bus number PortBase - The port start address Length - how many bytes of port space to map (needed by MmMapIoSpace) Return Value : The virtual port address --*/ { PHYSICAL_ADDRESS PortAddress; PHYSICAL_ADDRESS MappedAddress; *MemType = 1; // IO space PortAddress.LowPart = PortBase; PortAddress.HighPart = 0; HalTranslateBusAddress( BusType, BusNumber, PortAddress, MemType, &MappedAddress); if (*MemType == 0) { // // Map memory type IO space into our address space // return (PUCHAR)MmMapIoSpace(MappedAddress, Length, FALSE); } else { return (PUCHAR)MappedAddress.LowPart; } }
BOOLEAN NTAPI HalpTranslateIsaBusAddress(PBUS_HANDLER BusHandler, ULONG BusNumber, PHYSICAL_ADDRESS BusAddress, PULONG AddressSpace, PPHYSICAL_ADDRESS TranslatedAddress) { BOOLEAN Result; Result = HalTranslateBusAddress(PCIBus, BusNumber, BusAddress, AddressSpace, TranslatedAddress); if (Result != FALSE) return Result; Result = HalTranslateBusAddress(Internal, BusNumber, BusAddress, AddressSpace, TranslatedAddress); return Result; }
/* * @implemented */ NDIS_STATUS EXPORT NdisMMapIoSpace( OUT PVOID *VirtualAddress, IN NDIS_HANDLE MiniportAdapterHandle, IN NDIS_PHYSICAL_ADDRESS PhysicalAddress, IN UINT Length) /* * FUNCTION: Maps a bus-relative address to a system-wide virtual address * ARGUMENTS: * VirtualAddress: receives virtual address of mapping * MiniportAdapterHandle: Handle originally input to MiniportInitialize * PhysicalAddress: bus-relative address to map * Length: Number of bytes to map * RETURNS: * NDIS_STATUS_SUCCESS: the operation completed successfully * NDIS_STATUS_RESOURCE_CONFLICT: the physical address range is already claimed * NDIS_STATUS_RESOURCES: insufficient resources to complete the mapping * NDIS_STATUS_FAILURE: a general failure has occured * NOTES: * - Must be called at IRQL = PASSIVE_LEVEL */ { PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle; ULONG AddressSpace = 0; /* Memory Space */ NDIS_PHYSICAL_ADDRESS TranslatedAddress; PAGED_CODE(); ASSERT(VirtualAddress && MiniportAdapterHandle); NDIS_DbgPrint(MAX_TRACE, ("Called\n")); if(!HalTranslateBusAddress(Adapter->NdisMiniportBlock.BusType, Adapter->NdisMiniportBlock.BusNumber, PhysicalAddress, &AddressSpace, &TranslatedAddress)) { NDIS_DbgPrint(MIN_TRACE, ("Unable to translate address\n")); return NDIS_STATUS_RESOURCES; } *VirtualAddress = MmMapIoSpace(TranslatedAddress, Length, MmNonCached); if(!*VirtualAddress) { NDIS_DbgPrint(MIN_TRACE, ("MmMapIoSpace failed\n")); return NDIS_STATUS_RESOURCES; } return NDIS_STATUS_SUCCESS; }
/* * @implemented */ VOID EXPORT NdisMDeregisterIoPortRange(IN NDIS_HANDLE MiniportAdapterHandle, IN UINT InitialPort, IN UINT NumberOfPorts, IN PVOID PortOffset) /* * FUNCTION: Releases a register mapping to I/O ports * ARGUMENTS: * MiniportAdapterHandle = Specifies handle input to MiniportInitialize * InitialPort = Bus-relative base port address of a range to be mapped * NumberOfPorts = Specifies number of ports to be mapped * PortOffset = Pointer to mapped base port address */ { PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle; PHYSICAL_ADDRESS PortAddress = RtlConvertUlongToLargeInteger(InitialPort); PHYSICAL_ADDRESS TranslatedAddress; ULONG AddressSpace = 1; NDIS_DbgPrint(MAX_TRACE, ("Called - InitialPort 0x%x, NumberOfPorts 0x%x, Port Offset 0x%x\n", InitialPort, NumberOfPorts, PortOffset)); /* Translate the initial port again to find the address space of the translated address */ if(!HalTranslateBusAddress(Adapter->NdisMiniportBlock.BusType, Adapter->NdisMiniportBlock.BusNumber, PortAddress, &AddressSpace, &TranslatedAddress)) { NDIS_DbgPrint(MIN_TRACE, ("Unable to translate address\n")); return; } /* Make sure we got the same translation as last time */ ASSERT(TranslatedAddress.QuadPart == (ULONG_PTR)PortOffset); /* Check if we're in memory space */ if (!AddressSpace) { NDIS_DbgPrint(MAX_TRACE, ("Calling MmUnmapIoSpace\n")); /* Unmap the memory */ MmUnmapIoSpace(PortOffset, NumberOfPorts); } }
NTSTATUS AnajoystMapDevice( DWORD PortBase, DWORD NumberOfPorts, PJOY_EXTENSION pJoyExtension ) { DWORD MemType; PHYSICAL_ADDRESS PortAddress; PHYSICAL_ADDRESS MappedAddress; MemType = 1; // IO space PortAddress.LowPart = PortBase; PortAddress.HighPart = 0; HalTranslateBusAddress( Isa, 0, PortAddress, &MemType, &MappedAddress); if (MemType == 0) { // // Map memory type IO space into our address space // pJoyExtension->DeviceAddress = (PUCHAR) MmMapIoSpace(MappedAddress, NumberOfPorts, FALSE); } else { pJoyExtension->DeviceAddress = (PUCHAR) MappedAddress.LowPart; } return STATUS_SUCCESS; }
NTSTATUS SoundReportResourceUsage( IN PDEVICE_OBJECT DeviceObject, IN INTERFACE_TYPE BusType, IN ULONG BusNumber, IN PULONG InterruptNumber OPTIONAL, IN KINTERRUPT_MODE InterruptMode, IN BOOLEAN InterruptShareDisposition, IN PULONG DmaChannel OPTIONAL, IN PULONG FirstIoPort OPTIONAL, IN ULONG IoPortLength ) /*++ Routine Description : Calls IoReportResourceUsage for the device and resources passed in. NOTE that this supercedes previous resources declared for this device. It is assumed that all resources owned by the device cannot be shared, except for level-sensitive interrupts which can be shared. Arguments : DeviceObject - The device which 'owns' the resources This can also be a pointer to a driver object BusType - The type of bus on which the device lives BusNumber - The bus number (of type BusType) where the device is InterruptNumber - The interrupt the devices uses (if any) DmaChannel - The DMA channel the device uses FirstIoPort - The start Io port for the device IoPortLength - The number of bytes of IO space the device uses (starting at FirstIoPort) Return Value : STATUS_SUCCESS if no problems The return from IoReportResourceUsage if this fails STATUS_DEVICE_CONFIGURATION_ERROR is IoReportResourceUsage reports a conflict --*/ { NTSTATUS Status; // // Our resource list to report back to the system // /* Compiler rejects this UCHAR ResBuffer[FIELD_OFFSET( CM_RESOURCE_LIST, List[0].PartialResourceList.PartialDescriptors[3].Type)]; */ UCHAR ResBuffer[3 * sizeof(CM_RESOURCE_LIST)]; BOOLEAN ResourceConflict; PCM_RESOURCE_LIST ResourceList; PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor; ResourceList = (PCM_RESOURCE_LIST)ResBuffer; Descriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors; ResourceConflict = FALSE; // // Zero out any unused data // RtlZeroMemory(ResBuffer, sizeof(ResBuffer)); // // We assume there's only 1 bus so we only need one list. // Fill in the bus description // ResourceList->Count = 1; ResourceList->List[0].InterfaceType = BusType; ResourceList->List[0].BusNumber = BusNumber; // // If the device is using IO Ports add this to the list // if (ARGUMENT_PRESENT(FirstIoPort)) { PHYSICAL_ADDRESS PortAddress; ULONG MemType; PHYSICAL_ADDRESS MappedAddress; PortAddress.LowPart = *FirstIoPort; PortAddress.HighPart = 0; MemType = 1; HalTranslateBusAddress( BusType, BusNumber, PortAddress, &MemType, &MappedAddress); ResourceList->List[0].PartialResourceList.Count++; Descriptor->Type = CmResourceTypePort; Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; Descriptor->u.Port.Start.LowPart = *FirstIoPort; Descriptor->u.Port.Length = IoPortLength; Descriptor->Flags = MemType == 0 ? CM_RESOURCE_PORT_MEMORY : CM_RESOURCE_PORT_IO; // // Move on to next resource descriptor entry // Descriptor++; } // // Add interrupt information (if any) to the list // if (ARGUMENT_PRESENT(InterruptNumber)) { KAFFINITY Affinity; KIRQL InterruptRequestLevel; ULONG InterruptVector; // // Get the processor affinity and vector // InterruptVector = HalGetInterruptVector(BusType, BusNumber, *InterruptNumber, *InterruptNumber, &InterruptRequestLevel, &Affinity); ResourceList->List[0].PartialResourceList.Count++; Descriptor->Type = CmResourceTypeInterrupt; Descriptor->ShareDisposition = (UCHAR)(InterruptShareDisposition ? CmResourceShareShared : CmResourceShareDeviceExclusive); Descriptor->Flags = InterruptMode == Latched ? CM_RESOURCE_INTERRUPT_LATCHED : CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; Descriptor->u.Interrupt.Level = *InterruptNumber; Descriptor->u.Interrupt.Vector = InterruptVector; Descriptor->u.Interrupt.Affinity = (ULONG)Affinity; // // Move on to next resource descriptor entry // Descriptor++; } // // Add DMA description if any // if (ARGUMENT_PRESENT(DmaChannel)) { ResourceList->List[0].PartialResourceList.Count++; Descriptor->Type = CmResourceTypeDma; Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; Descriptor->u.Dma.Channel = *DmaChannel; Descriptor->u.Dma.Port = 0; // ??? // // Move on to next resource descriptor entry // Descriptor++; } // // Report our resource usage and detect conflicts // switch (DeviceObject->Type) { case IO_TYPE_DEVICE: Status = IoReportResourceUsage(NULL, DeviceObject->DriverObject, NULL, 0, DeviceObject, ResourceList, (PUCHAR)Descriptor - (PUCHAR)ResourceList, FALSE, &ResourceConflict); break; case IO_TYPE_DRIVER: Status = IoReportResourceUsage(NULL, (PDRIVER_OBJECT)DeviceObject, ResourceList, (PUCHAR)Descriptor - (PUCHAR)ResourceList, NULL, NULL, 0, FALSE, &ResourceConflict); break; default: ASSERTMSG("SoundReportResourceUsage - invalid object", FALSE); } if (ResourceConflict) { dprintf1(("Resource conflict reported")); Status = STATUS_DEVICE_CONFIGURATION_ERROR; } return Status; }
PVOID PipGetMappedAddress( IN INTERFACE_TYPE BusType, IN ULONG BusNumber, IN PHYSICAL_ADDRESS IoAddress, IN ULONG NumberOfBytes, IN ULONG AddressSpace, OUT PBOOLEAN MappedAddress ) /*++ Routine Description: This routine maps an IO address to system address space. Arguments: BusType - Supplies the type of bus - eisa, mca, isa... IoBusNumber - Supplies the bus number. IoAddress - Supplies the base device address to be mapped. NumberOfBytes - Supplies the number of bytes for which the address is valid. AddressSpace - Supplies whether the address is in io space or memory. MappedAddress - Supplies whether the address was mapped. This only has meaning if the address returned is non-null. Return Value: The mapped address. --*/ { PHYSICAL_ADDRESS cardAddress; PVOID address; HalTranslateBusAddress(BusType, BusNumber, IoAddress, &AddressSpace, &cardAddress); // // Map the device base address into the virtual address space // if the address is in memory space. // if (!AddressSpace) { address = MmMapIoSpace(cardAddress, NumberOfBytes, FALSE); *MappedAddress = (address ? TRUE : FALSE); } else { address = (PVOID) cardAddress.LowPart; *MappedAddress = FALSE; } return address; }
BOOLEAN HalHandleNMI( IN PKINTERRUPT Interrupt, IN PVOID ServiceContext ) /*++ Routine Description: This function is called when an EISA NMI occurs. It prints the appropriate status information and bugchecks. Arguments: Interrupt - Supplies a pointer to the interrupt object ServiceContext - Bug number to call bugcheck with. Return Value: Returns TRUE. --*/ { UCHAR StatusByte; UCHAR EisaPort; ULONG port; ULONG AddressSpace = 1; // 1 = I/O address space BOOLEAN Status; PHYSICAL_ADDRESS BusAddress; PHYSICAL_ADDRESS TranslatedAddress; UCHAR Datum; NMIcount++; // // Set the Eisa NMI disable bit. We do this to mask further NMI // interrupts while we're servicing this one. // Datum = READ_PORT_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable); ((PNMI_ENABLE)(&Datum))->NmiDisable = 1; WRITE_PORT_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable, Datum); #ifdef HALDBG DbgPrint("HalpIntializeNMI: wrote 0x%x to NmiEnable\n\r", Datum); #endif StatusByte = READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus); if (StatusByte & 0x80) { #ifdef HALDBG DbgPrint("HalHandleNMI: Parity Check / Parity Error\n"); DbgPrint("HalHandleNMI: StatusByte = 0x%x\r\n", StatusByte); #else // // jwlfix - For the present, we're commenting out an NMI parity // error bugcheck, until investigation into its causes // yields a better solution. // // HalDisplayString ("NMI: Parity Check / Parity Error\n"); // KeBugCheck(NMI_HARDWARE_FAILURE); // return (TRUE); #endif } Datum = READ_REGISTER_UCHAR((PUCHAR)HalpServerControlQva ); if (((PMIKASA_SRV)(&Datum))->HaltIncoming == 0 || ((PMIKASA_SRV)(&Datum))->TempFail == 1 || ((PMIKASA_SRV)(&Datum))->Fan1Fault == 0 || ((PMIKASA_SRV)(&Datum))->Fan2Fault == 0) { #ifdef HALDBG DbgPrint("HalHandleNMI: Server management NMI\n"); DbgPrint("HalHandleNMI: StatusByte = 0x%x\r\n", StatusByte); DbgPrint("HalHandleNMI: Server Management Byte = 0x%x\r\n", Datum); #else // // jwlfix - All the above conditions are for handling server // management features. Implementing more than simple // dismissal waits upon definition of desired behavior // by platform designers or Microsoft Windows NT // requirements for server behavior. #endif } if (StatusByte & 0x40) { #ifdef HALDBG DbgPrint("HalHandleNMI: Channel Check / IOCHK\n"); DbgPrint("HalHandleNMI: StatusByte = 0x%x\r\n", StatusByte); #else HalDisplayString ("NMI: Channel Check / IOCHK\n"); KeBugCheck(NMI_HARDWARE_FAILURE); return (TRUE); #endif } #if 0 // jwlfix - This code can be added in later, as we have need // for it. It's good to have it here, for when it // might be of use. // // This is an Eisa machine, check for extnded nmi information... // StatusByte = READ_PORT_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl); if (StatusByte & 0x80) { HalDisplayString ("NMI: Fail-safe timer\n"); } if (StatusByte & 0x40) { HalDisplayString ("NMI: Bus Timeout\n"); } if (StatusByte & 0x20) { HalDisplayString ("NMI: Software NMI generated\n"); } // // Look for any Eisa expansion board. See if it asserted NMI. // // jwlfix - The following doesn't work, at this moment; it's // likey the 12-bit shift, which should be a 5-bit // shift on Mikasa. // BusAddress.HighPart = 0; for (EisaPort = 0; EisaPort <= 0xf; EisaPort++) { BusAddress.LowPart = (EisaPort << 12) + 0xC80; Status = HalTranslateBusAddress(Eisa, // InterfaceType 0, // BusNumber BusAddress, &AddressSpace, // 1=I/O address space &TranslatedAddress); // QVA if (Status == FALSE) { UCHAR pbuf[80]; sprintf(pbuf, "Unable to translate bus address %x for EISA slot %d\n", BusAddress.LowPart, EisaPort); HalDisplayString(pbuf); KeBugCheck(NMI_HARDWARE_FAILURE); } port = TranslatedAddress.LowPart; WRITE_PORT_UCHAR ((PUCHAR) port, 0xff); StatusByte = READ_PORT_UCHAR ((PUCHAR) port); if ((StatusByte & 0x80) == 0) { // // Found valid Eisa board, Check to see if its // IOCHKERR is asserted. // StatusByte = READ_PORT_UCHAR ((PUCHAR) port+4); if (StatusByte & 0x2) { EisaNMIMsg[25] = (EisaPort > 9 ? 'A'-10 : '0') + EisaPort; HalDisplayString (EisaNMIMsg); KeBugCheck(NMI_HARDWARE_FAILURE); } } } #ifdef HALDBG // Reset extended NMI interrupts (for debugging purposes only). WRITE_PORT_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl, 0x00); WRITE_PORT_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl, 0x02); #endif #endif #ifdef HALDBG DbgPrint("HalHandleNMI: Resetting PERR#; NMI count = %d\r\n", NMIcount); #endif // // Reset PERR# and disable it. // WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus, 0x04); // // now enable it again. // WRITE_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus, 0); // // Clear the Eisa NMI disable bit. This re-enables NMI interrupts, // now that we're done servicing this one. // Datum = READ_PORT_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable); ((PNMI_ENABLE)(&Datum))->NmiDisable = 0; WRITE_PORT_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable, Datum); #ifdef HALDBG DbgPrint("HalpIntializeNMI: wrote 0x%x to NmiEnable\n\r", Datum); #endif return(TRUE); }
VOID NdisMDeregisterIoPortRange( IN NDIS_HANDLE MiniportAdapterHandle, IN UINT InitialPort, IN UINT NumberOfPorts, IN PVOID PortOffset ) /*++ Routine Description: Sets up an IO port for operations. Arguments: MiniportAdapterHandle - Handle passed to Miniport Initialize. InitialPort - Physical address of the starting port number. NumberOfPorts - Number of ports to map. PortOffset - The mapped port address the Miniport uses for NdisRaw functions. Return Value: None. --*/ { PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)(MiniportAdapterHandle); PHYSICAL_ADDRESS PortAddress; PHYSICAL_ADDRESS InitialPortAddress; ULONG addressSpace; CM_PARTIAL_RESOURCE_DESCRIPTOR Resource; NDIS_STATUS Status; // // Get the system physical address for this card. The card uses // I/O space, except for "internal" Jazz devices which use // memory space. // addressSpace = (Miniport->AdapterType == NdisInterfaceInternal) ? 0 : 1; InitialPortAddress.LowPart = InitialPort; InitialPortAddress.HighPart = 0; HalTranslateBusAddress(Miniport->BusType, // InterfaceType Miniport->BusNumber, // BusNumber InitialPortAddress, // Bus Address &addressSpace, // AddressSpace &PortAddress); // Translated address if (addressSpace == 0) { // // memory space // MmUnmapIoSpace(PortOffset, NumberOfPorts); } // // Build the resource to remove. // Resource.Type = CmResourceTypePort; Resource.ShareDisposition = CmResourceShareDeviceExclusive; Resource.Flags = (Miniport->AdapterType == NdisInterfaceInternal) ? CM_RESOURCE_PORT_MEMORY : CM_RESOURCE_PORT_IO; Resource.u.Port.Start.QuadPart = InitialPort; Resource.u.Port.Length = NumberOfPorts; // // Remove the resource. // Status = ndisRemoveResource( &Miniport->Resources, &Resource, Miniport->DriverHandle->NdisDriverInfo->NdisWrapperDriver, Miniport->DeviceObject, &Miniport->MiniportName); if (Status != NDIS_STATUS_SUCCESS) { DBGPRINT(DBG_COMP_UNLOAD, DBG_LEVEL_INFO, ("NdisMDeregisterIoPortRange failed to remove the resource\n")); } }
NTSTATUS MapPhysicalMemoryToLinearSpace(PVOID pPhysAddress, ULONG PhysMemSizeInBytes, PVOID *ppPhysMemLin, HANDLE *pPhysicalMemoryHandle) { UNICODE_STRING PhysicalMemoryUnicodeString; PVOID PhysicalMemorySection = NULL; OBJECT_ATTRIBUTES ObjectAttributes; PHYSICAL_ADDRESS ViewBase; NTSTATUS ntStatus; PHYSICAL_ADDRESS pStartPhysAddress; PHYSICAL_ADDRESS pEndPhysAddress; PHYSICAL_ADDRESS MappingLength; BOOLEAN Result1, Result2; ULONG IsIOSpace; unsigned char *pbPhysMemLin = NULL; OutputDebugString ("Entering MapPhysicalMemoryToLinearSpace"); RtlInitUnicodeString (&PhysicalMemoryUnicodeString, L"\\Device\\PhysicalMemory"); InitializeObjectAttributes (&ObjectAttributes, &PhysicalMemoryUnicodeString, OBJ_CASE_INSENSITIVE, (HANDLE) NULL, (PSECURITY_DESCRIPTOR) NULL); *pPhysicalMemoryHandle = NULL; ntStatus = ZwOpenSection (pPhysicalMemoryHandle, SECTION_ALL_ACCESS, &ObjectAttributes); if (NT_SUCCESS(ntStatus)) { ntStatus = ObReferenceObjectByHandle (*pPhysicalMemoryHandle, SECTION_ALL_ACCESS, (POBJECT_TYPE) NULL, KernelMode, &PhysicalMemorySection, (POBJECT_HANDLE_INFORMATION) NULL); if (NT_SUCCESS(ntStatus)) { pStartPhysAddress.QuadPart = (ULONGLONG)pPhysAddress; pEndPhysAddress = RtlLargeIntegerAdd (pStartPhysAddress, RtlConvertUlongToLargeInteger(PhysMemSizeInBytes)); IsIOSpace = 0; Result1 = HalTranslateBusAddress (1, 0, pStartPhysAddress, &IsIOSpace, &pStartPhysAddress); IsIOSpace = 0; Result2 = HalTranslateBusAddress (1, 0, pEndPhysAddress, &IsIOSpace, &pEndPhysAddress); if (Result1 && Result2) { MappingLength = RtlLargeIntegerSubtract (pEndPhysAddress, pStartPhysAddress); if (MappingLength.LowPart) { // Let ZwMapViewOfSection pick a linear address PhysMemSizeInBytes = MappingLength.LowPart; ViewBase = pStartPhysAddress; ntStatus = ZwMapViewOfSection (*pPhysicalMemoryHandle, (HANDLE) -1, &pbPhysMemLin, 0L, PhysMemSizeInBytes, &ViewBase, &PhysMemSizeInBytes, ViewShare, 0, PAGE_READWRITE | PAGE_NOCACHE); if (!NT_SUCCESS(ntStatus)) OutputDebugString ("ERROR: ZwMapViewOfSection failed"); else { pbPhysMemLin += (ULONG)pStartPhysAddress.LowPart - (ULONG)ViewBase.LowPart; *ppPhysMemLin = pbPhysMemLin; } } else OutputDebugString ("ERROR: RtlLargeIntegerSubtract failed"); } else OutputDebugString ("ERROR: MappingLength = 0"); } else OutputDebugString ("ERROR: ObReferenceObjectByHandle failed"); } else OutputDebugString ("ERROR: ZwOpenSection failed"); if (!NT_SUCCESS(ntStatus)) ZwClose(*pPhysicalMemoryHandle); OutputDebugString ("Leaving MapPhysicalMemoryToLinearSpace"); return ntStatus; }
/* * @implemented */ NDIS_STATUS EXPORT NdisMRegisterIoPortRange( OUT PVOID *PortOffset, IN NDIS_HANDLE MiniportAdapterHandle, IN UINT InitialPort, IN UINT NumberOfPorts) /* * FUNCTION: Sets up driver access to device I/O ports * ARGUMENTS: * PortOffset = Address of buffer to place mapped base port address * MiniportAdapterHandle = Specifies handle input to MiniportInitialize * InitialPort = Bus-relative base port address of a range to be mapped * NumberOfPorts = Specifies number of ports to be mapped * RETURNS: * Status of operation */ { PHYSICAL_ADDRESS PortAddress, TranslatedAddress; PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle; ULONG AddressSpace = 1; /* FIXME The HAL handles this wrong atm */ *PortOffset = 0; NDIS_DbgPrint(MAX_TRACE, ("Called - InitialPort 0x%x, NumberOfPorts 0x%x\n", InitialPort, NumberOfPorts)); memset(&PortAddress, 0, sizeof(PortAddress)); /* * FIXME: NDIS 5+ completely ignores the InitialPort parameter, but * we don't have a way to get the I/O base address yet (see * NDIS_MINIPORT_BLOCK->AllocatedResources and * NDIS_MINIPORT_BLOCK->AllocatedResourcesTranslated). */ if(InitialPort) PortAddress = RtlConvertUlongToLargeInteger(InitialPort); else ASSERT(FALSE); NDIS_DbgPrint(MAX_TRACE, ("Translating address 0x%x 0x%x\n", PortAddress.u.HighPart, PortAddress.u.LowPart)); if(!HalTranslateBusAddress(Adapter->NdisMiniportBlock.BusType, Adapter->NdisMiniportBlock.BusNumber, PortAddress, &AddressSpace, &TranslatedAddress)) { NDIS_DbgPrint(MIN_TRACE, ("Unable to translate address\n")); return NDIS_STATUS_RESOURCES; } NDIS_DbgPrint(MAX_TRACE, ("Hal returned AddressSpace=0x%x TranslatedAddress=0x%x 0x%x\n", AddressSpace, TranslatedAddress.u.HighPart, TranslatedAddress.u.LowPart)); if(AddressSpace) { ASSERT(TranslatedAddress.u.HighPart == 0); *PortOffset = (PVOID)(ULONG_PTR)TranslatedAddress.QuadPart; NDIS_DbgPrint(MAX_TRACE, ("Returning 0x%x\n", *PortOffset)); return NDIS_STATUS_SUCCESS; } NDIS_DbgPrint(MAX_TRACE, ("calling MmMapIoSpace\n")); *PortOffset = MmMapIoSpace(TranslatedAddress, NumberOfPorts, MmNonCached); NDIS_DbgPrint(MAX_TRACE, ("Returning 0x%x for port range\n", *PortOffset)); if(!*PortOffset) { NDIS_DbgPrint(MIN_TRACE, ("MmMapIoSpace failed\n")); return NDIS_STATUS_RESOURCES; } return NDIS_STATUS_SUCCESS; }
VOID KdpWriteIoSpaceExtended ( IN PDBGKD_MANIPULATE_STATE64 m, IN PSTRING AdditionalData, IN PCONTEXT Context ) /*++ Routine Description: This function is called in response of a read io space extended state manipulation message. Its function is to read system io locations. Arguments: m - Supplies the state manipulation message. AdditionalData - Supplies any additional data for the message. Context - Supplies the current context. Return Value: None. --*/ { PDBGKD_READ_WRITE_IO_EXTENDED64 a = &m->u.ReadWriteIoExtended; ULONG Length; STRING MessageHeader; PUCHAR b; PUSHORT s; PULONG l; ULONG BusNumber; ULONG AddressSpace; ULONG SavedAddressSpace; PHYSICAL_ADDRESS IoAddress; ULONG DataSize; PHYSICAL_ADDRESS TranslatedAddress; INTERFACE_TYPE InterfaceType; ULONG Value; MessageHeader.Length = sizeof(*m); MessageHeader.Buffer = (PCHAR)m; ASSERT(AdditionalData->Length == 0); m->ReturnStatus = STATUS_SUCCESS; InterfaceType = a->InterfaceType; BusNumber = a->BusNumber; AddressSpace = SavedAddressSpace = a->AddressSpace; IoAddress.QuadPart = (ULONG_PTR)a->IoAddress; DataSize = a->DataSize; Value = a->DataValue; // // Translate the bus address to the physical system address // or QVA. // if( !HalTranslateBusAddress( InterfaceType, BusNumber, IoAddress, &AddressSpace, &TranslatedAddress ) ){ m->ReturnStatus = STATUS_INVALID_PARAMETER; goto SendWriteIoSpaceExtendedResponse; } // // N.B. - for the moment we will only support QVAs ie. when AddressSpace // is one. It may be in later systems that we will have to // check the address space, map it, perform the virtual read // unmap, and then return the data - only we will have to be // careful about what Irql we are to make sure the memory mgmt // stuff will all work // if( !AddressSpace ){ m->ReturnStatus = STATUS_INVALID_PARAMETER; goto SendWriteIoSpaceExtendedResponse; } // // Do the IO space read using the appropriate HAL routines based upon // the original address space and the data size requested. // if( !SavedAddressSpace ){ // // Memory (buffer) space on the bus // switch( DataSize ){ case 1: WRITE_REGISTER_UCHAR( (PUCHAR)TranslatedAddress.QuadPart, (UCHAR)Value ); break; case 2: WRITE_REGISTER_USHORT( (PUSHORT)TranslatedAddress.QuadPart, (USHORT)Value ); break; case 4: WRITE_REGISTER_ULONG( (PULONG)TranslatedAddress.QuadPart, Value ); break; default: m->ReturnStatus = STATUS_INVALID_PARAMETER; } } else { // // I/O space on the bus // switch( DataSize ){ case 1: WRITE_PORT_UCHAR( (PUCHAR)TranslatedAddress.QuadPart, (UCHAR)Value ); break; case 2: WRITE_PORT_USHORT( (PUSHORT)TranslatedAddress.QuadPart, (USHORT)Value); break; case 4: WRITE_PORT_ULONG( (PULONG)TranslatedAddress.QuadPart, Value ); break; default: m->ReturnStatus = STATUS_INVALID_PARAMETER; } } SendWriteIoSpaceExtendedResponse: KdpSendPacket( PACKET_TYPE_KD_STATE_MANIPULATE, &MessageHeader, NULL ); }
VOID KdpReadIoSpace ( IN PDBGKD_MANIPULATE_STATE64 m, IN PSTRING AdditionalData, IN PCONTEXT Context ) /*++ Routine Description: This function is called in response of a read io space state manipulation message. Its function is to read system io locations. Arguments: m - Supplies the state manipulation message. AdditionalData - Supplies any additional data for the message. Context - Supplies the current context. Return Value: None. --*/ { PDBGKD_READ_WRITE_IO64 a = &m->u.ReadWriteIo; STRING MessageHeader; INTERFACE_TYPE InterfaceType; ULONG BusNumber; PHYSICAL_ADDRESS IoAddress; PHYSICAL_ADDRESS TranslatedAddress; ULONG AddressSpace; ULONG DataSize; MessageHeader.Length = sizeof(*m); MessageHeader.Buffer = (PCHAR)m; ASSERT(AdditionalData->Length == 0); m->ReturnStatus = STATUS_SUCCESS; // // Capture the input parameters and use the default values for those // parameters not specified in the Api. // InterfaceType = Isa; BusNumber = 0; AddressSpace = 1; IoAddress.QuadPart = (ULONG_PTR)a->IoAddress; DataSize = a->DataSize; // // Zero the return data value. // a->DataValue = 0; // // Translate the bus address to the physical system address // or QVA. // if( !HalTranslateBusAddress( InterfaceType, BusNumber, IoAddress, &AddressSpace, &TranslatedAddress ) ){ m->ReturnStatus = STATUS_INVALID_PARAMETER; goto SendReadIoSpaceResponse; } // // N.B. - for the moment we will only support QVAs ie. when AddressSpace // is one. It may be in later systems that we will have to // check the address space, map it, perform the virtual read // unmap, and then return the data - only we will have to be // careful about what Irql we are to make sure the memory mgmt // stuff will all work // if( !AddressSpace ){ m->ReturnStatus = STATUS_INVALID_PARAMETER; goto SendReadIoSpaceResponse; } // // Do the IO space read using the appropriate HAL routines based upon // the default address space (io) and the data size requested. // switch( DataSize ){ case 1: a->DataValue = READ_PORT_UCHAR( (PUCHAR)(ULONG_PTR) TranslatedAddress.QuadPart ); break; case 2: a->DataValue = READ_PORT_USHORT( (PUSHORT)(ULONG_PTR) TranslatedAddress.QuadPart ); break; case 4: a->DataValue = READ_PORT_ULONG((PULONG)(ULONG_PTR) TranslatedAddress.QuadPart ); break; default: m->ReturnStatus = STATUS_INVALID_PARAMETER; } SendReadIoSpaceResponse: KdpSendPacket( PACKET_TYPE_KD_STATE_MANIPULATE, &MessageHeader, NULL ); }
BOOLEAN HalInitSystem ( IN ULONG Phase, IN PLOADER_PARAMETER_BLOCK LoaderBlock ) /*++ Routine Description: This function initializes the Hardware Architecture Layer (HAL) for a MIPS R3000 or R4000 system. Arguments: Phase - Supplies the initialization phase (zero or one). LoaderBlock - Supplies a pointer to a loader parameter block. Return Value: A value of TRUE is returned is the initialization was successfully complete. Otherwise a value of FALSE is returend. --*/ { ULONG FailedAddress; PKPRCB Prcb; PHYSICAL_ADDRESS PhysicalAddress; PHYSICAL_ADDRESS ZeroAddress; ULONG AddressSpace; // // Initialize the HAL components based on the phase of initialization // and the processor number. // Prcb = PCR->Prcb; PCR->DataBusError = HalpBusError; PCR->InstructionBusError = HalpBusError; if ((Phase == 0) || (Prcb->Number != 0)) { // // Phase 0 initialization. // // N.B. Phase 0 initialization is executed on all processors. // // Verify that the processor block major version number conform // to the system that is being loaded. // if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) { KeBugCheck(MISMATCHED_HAL); } // // Map the fixed TB entries. // HalpMapFixedTbEntries(); // // If processor 0 is being initialized, then initialize various // variables, spin locks, and the display adapter. // if (Prcb->Number == 0) { // // Set the number of process id's and TB entries. // **((PULONG *)(&KeNumberProcessIds)) = 256; **((PULONG *)(&KeNumberTbEntries)) = 48; // // Set the interval clock increment value. // HalpCurrentTimeIncrement = MAXIMUM_INCREMENT; HalpNextTimeIncrement = MAXIMUM_INCREMENT; HalpNextIntervalCount = 0; KeSetTimeIncrement(MAXIMUM_INCREMENT, MINIMUM_INCREMENT); // // Initialize all spin locks. // #if defined(_DUO_) KeInitializeSpinLock(&HalpBeepLock); KeInitializeSpinLock(&HalpDisplayAdapterLock); KeInitializeSpinLock(&HalpSystemInterruptLock); #endif // // Set address of cache error routine. // KeSetCacheErrorRoutine(HalpCacheErrorRoutine); // // Initialize the display adapter. // HalpInitializeDisplay0(LoaderBlock); // // Allocate map register memory. // HalpAllocateMapRegisters(LoaderBlock); // // Initialize and register a bug check callback record. // KeInitializeCallbackRecord(&HalpCallbackRecord); KeRegisterBugCheckCallback(&HalpCallbackRecord, HalpBugCheckCallback, &HalpBugCheckBuffer, sizeof(HALP_BUGCHECK_BUFFER), &HalpComponentId[0]); } // // Clear memory address error registers. // #if defined(_DUO_) FailedAddress = ((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress.Long; #endif FailedAddress = ((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->MemoryFailedAddress.Long; // // Initialize interrupts // HalpInitializeInterrupts(); return TRUE; } else { // // Phase 1 initialization. // // N.B. Phase 1 initialization is only executed on processor 0. // // Complete initialization of the display adapter. // if (HalpInitializeDisplay1(LoaderBlock) == FALSE) { return FALSE; } else { // // Map I/O space, calibrate the stall execution scale factor, // and create DMA data structures. // HalpMapIoSpace(); HalpCalibrateStall(); HalpCreateDmaStructures(); // // Map EISA memory space so the x86 bios emulator emulator can // initialze a video adapter in an EISA slot. // ZeroAddress.QuadPart = 0; AddressSpace = 0; HalTranslateBusAddress(Isa, 0, ZeroAddress, &AddressSpace, &PhysicalAddress); HalpEisaMemoryBase = MmMapIoSpace(PhysicalAddress, PAGE_SIZE * 256, FALSE); HalpInitializeX86DisplayAdapter(); return TRUE; } } }
VOID DumpT2( VOID ) /*++ Routine Description: Read the interesting T2 registers and print them to the debug port. Arguments: None. Return Value: None. --*/ { PVOID RegisterQva; PVOID TestQva; ULONGLONG Value; ULONG LongValue; T2_TDR Tdr; // DbgPrint( "Dumping the T2 registers, " ); #if 0 // // This code tests whether the windows and holes allow access to // the address in I/O memory space set in PhysicalAddress. // See also the companion code at the end of this routine. // { ULONG AddressSpace; PHYSICAL_ADDRESS PhysicalAddress; AddressSpace = 0; PhysicalAddress.LowPart = 0xD0000; // DE422 // PhysicalAddress.LowPart = 0x2200000; // 34Mbytes // PhysicalAddress.LowPart = 0x0400000; // 4Mbytes PhysicalAddress.HighPart = 0; HalTranslateBusAddress( Isa, 0, PhysicalAddress, &AddressSpace, &TestQva ); LongValue = READ_REGISTER_ULONG( TestQva ); DbgPrint( "TestQva = %lx, Value = %x, writing 0xa5a5a5a5..\n", TestQva, LongValue ); LongValue = 0xa5a5a5a5; WRITE_REGISTER_ULONG( TestQva, LongValue ); LongValue = READ_REGISTER_ULONG( TestQva ); DbgPrint( "TestQva = %lx, Value = %x\n", TestQva, LongValue ); } #endif // 0 #if 0 RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Iocsr; Value = READ_T2_REGISTER( RegisterQva ); DbgPrint( "Iocsr = %Lx, ", Value ); RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Ivrpr; Value = READ_T2_REGISTER( RegisterQva ); DbgPrint( "Ivrpr = %Lx\n", Value ); RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_1; Value = READ_T2_REGISTER( RegisterQva ); DbgPrint( "Hae0_1 = %Lx, ", Value ); RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Hae0_2; Value = READ_T2_REGISTER( RegisterQva ); DbgPrint( "Hae0_2 = %Lx, ", Value ); RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Hbase; Value = READ_T2_REGISTER( RegisterQva ); DbgPrint( "Hbase = %Lx\n", Value ); RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Wbase1; Value = READ_T2_REGISTER( RegisterQva ); DbgPrint( "Wbase1 = %Lx, ", Value ); RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Wmask1; Value = READ_T2_REGISTER( RegisterQva ); DbgPrint( "Wmask1 = %Lx, ", Value ); RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Tbase1; Value = READ_T2_REGISTER( RegisterQva ); DbgPrint( "Tbase1 = %Lx\n", Value ); RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Wbase2; Value = READ_T2_REGISTER( RegisterQva ); DbgPrint( "Wbase2 = %Lx, ", Value ); RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Wmask2; Value = READ_T2_REGISTER( RegisterQva ); DbgPrint( "Wmask2 = %Lx, ", Value ); RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Tbase2; Value = READ_T2_REGISTER( RegisterQva ); DbgPrint( "Tbase2 = %Lx\n", Value ); #endif // 0 RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Tdr0; Value = READ_T2_REGISTER( RegisterQva ); Tdr = *(PT2_TDR)&Value; DbgPrint( "Tdr0 PFN=%x, V=%x, Tag=%x, ", Tdr.Pfn, Tdr.Valid, Tdr.Tag ); RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Tdr1; Value = READ_T2_REGISTER( RegisterQva ); Tdr = *(PT2_TDR)&Value; DbgPrint( "Tdr1 PFN=%x, V=%x, Tag=%x\n", Tdr.Pfn, Tdr.Valid, Tdr.Tag ); RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Tdr2; Value = READ_T2_REGISTER( RegisterQva ); Tdr = *(PT2_TDR)&Value; DbgPrint( "Tdr2 PFN=%x, V=%x, Tag=%x, ", Tdr.Pfn, Tdr.Valid, Tdr.Tag ); RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Tdr3; Value = READ_T2_REGISTER( RegisterQva ); Tdr = *(PT2_TDR)&Value; DbgPrint( "Tdr3 PFN=%x, V=%x, Tag=%x\n", Tdr.Pfn, Tdr.Valid, Tdr.Tag ); RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Tdr4; Value = READ_T2_REGISTER( RegisterQva ); Tdr = *(PT2_TDR)&Value; DbgPrint( "Tdr4 PFN=%x, V=%x, Tag=%x, ", Tdr.Pfn, Tdr.Valid, Tdr.Tag ); RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Tdr5; Value = READ_T2_REGISTER( RegisterQva ); Tdr = *(PT2_TDR)&Value; DbgPrint( "Tdr5 PFN=%x, V=%x, Tag=%x\n", Tdr.Pfn, Tdr.Valid, Tdr.Tag ); RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Tdr6; Value = READ_T2_REGISTER( RegisterQva ); Tdr = *(PT2_TDR)&Value; DbgPrint( "Tdr6 PFN=%x, V=%x, Tag=%x, ", Tdr.Pfn, Tdr.Valid, Tdr.Tag ); RegisterQva = &((PT2_CSRS)(T2_CSRS_QVA))->Tdr7; Value = READ_T2_REGISTER( RegisterQva ); Tdr = *(PT2_TDR)&Value; DbgPrint( "Tdr7 PFN=%x, V=%x, Tag=%x\n", Tdr.Pfn, Tdr.Valid, Tdr.Tag ); #if 0 LongValue = READ_REGISTER_ULONG( TestQva ); DbgPrint( "TestQva = %lx, Value = %x, writing 0xc3c3c3c3..\n", TestQva, LongValue ); LongValue = 0xc3c3c3c3; WRITE_REGISTER_ULONG( TestQva, LongValue ); LongValue = READ_REGISTER_ULONG( TestQva ); DbgPrint( "TestQva = %lx, Value = %x\n", TestQva, LongValue ); #endif // 0 // DbgPrint( "--end T2 dump\n\n" ); return; }
NDIS_STATUS NdisMRegisterIoPortRange( OUT PVOID * PortOffset, IN NDIS_HANDLE MiniportAdapterHandle, IN UINT InitialPort, IN UINT NumberOfPorts ) /*++ Routine Description: Sets up an IO port for operations. Arguments: PortOffset - The mapped port address the Miniport uses for NdisRaw functions. MiniportAdapterHandle - Handle passed to Miniport Initialize. InitialPort - Physical address of the starting port number. NumberOfPorts - Number of ports to map. Return Value: None. --*/ { PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)(MiniportAdapterHandle); PHYSICAL_ADDRESS PortAddress; PHYSICAL_ADDRESS InitialPortAddress; ULONG addressSpace; NDIS_STATUS Status; CM_PARTIAL_RESOURCE_DESCRIPTOR Resource; // // First check if any bus access is allowed // if ((Miniport->BusType == (NDIS_INTERFACE_TYPE)-1) || (Miniport->BusNumber == (ULONG)-1)) { return(NDIS_STATUS_FAILURE); } // // Setup port // Resource.Type = CmResourceTypePort; Resource.ShareDisposition = CmResourceShareDeviceExclusive; Resource.Flags = (Miniport->AdapterType == NdisInterfaceInternal) ? CM_RESOURCE_PORT_MEMORY : CM_RESOURCE_PORT_IO; Resource.u.Port.Start.QuadPart = InitialPort; Resource.u.Port.Length = NumberOfPorts; // // Add the new resource. // Status = ndisAddResource( &Miniport->Resources, &Resource, Miniport->AdapterType, Miniport->BusNumber, Miniport->DriverHandle->NdisDriverInfo->NdisWrapperDriver, Miniport->DeviceObject, &Miniport->MiniportName); if (Status != NDIS_STATUS_SUCCESS) { return(Status); } // // Now Map the ports // // // Get the system physical address for this card. The card uses // I/O space, except for "internal" Jazz devices which use // memory space. // addressSpace = (Miniport->AdapterType == NdisInterfaceInternal) ? 0 : 1; InitialPortAddress.LowPart = InitialPort; InitialPortAddress.HighPart = 0; if (!HalTranslateBusAddress(Miniport->BusType, // InterfaceType Miniport->BusNumber, // BusNumber InitialPortAddress, // Bus Address &addressSpace, // AddressSpace &PortAddress)) // Translated address { // // It would be nice to return a better status here, but we only get // TRUE/FALSE back from HalTranslateBusAddress. // return NDIS_STATUS_FAILURE; } if (addressSpace == 0) { // // memory space // *(PortOffset) = (PULONG)MmMapIoSpace(PortAddress, NumberOfPorts, FALSE); if (*(PortOffset) == (PULONG)NULL) { return NDIS_STATUS_RESOURCES; } } else { // // I/O space // *(PortOffset) = (PULONG)PortAddress.LowPart; } return(NDIS_STATUS_SUCCESS); }
VOID HalpReportResourceUsage ( IN PUNICODE_STRING HalName, IN INTERFACE_TYPE DeviceInterfaceToUse ) /*++ Routine Description: Arguments: Return Value: --*/ { PCM_RESOURCE_LIST RawResourceList, TranslatedResourceList; PCM_FULL_RESOURCE_DESCRIPTOR pRFullDesc, pTFullDesc; PCM_PARTIAL_RESOURCE_LIST pRPartList, pTPartList; PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, pTCurLoc; PCM_PARTIAL_RESOURCE_DESCRIPTOR pRSortLoc, pTSortLoc; CM_PARTIAL_RESOURCE_DESCRIPTOR RPartialDesc, TPartialDesc; ULONG i, j, k, ListSize, Count; ULONG curscale, sortscale; UCHAR pass, reporton; INTERFACE_TYPE interfacetype; ULONG CurrentIDT, CurrentElement; ADDRESS_USAGE *CurrentAddress; LARGE_INTEGER curvalue, sortvalue; // // Allocate some space to build the resource structure // RawResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2); TranslatedResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2); // This functions assumes unset fields are zero RtlZeroMemory (RawResourceList, PAGE_SIZE*2); RtlZeroMemory (TranslatedResourceList, PAGE_SIZE*2); // // Initialize the lists // RawResourceList->List[0].InterfaceType = (INTERFACE_TYPE) -1; pRFullDesc = RawResourceList->List; pRCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) RawResourceList->List; pTCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) TranslatedResourceList->List; // // Make sure all vectors 00-2f are reserved // 00-1E reserved by Intel // 1F reserved by Intel for APIC (apc priority level) // 20-2e reserved by Microsoft // 2f reserved by Microsoft for APIC (dpc priority level) // #if defined(_R98_) // CHG001 for(i=0; i < DEVICE_VECTORS; i++) { // ADD001 HalpIDTUsage[i].Flags = InternalUsage | InterruptLatched; HalpIDTUsage[i].BusReleativeVector = (UCHAR) i; } #else for(i=0; i < PRIMARY_VECTOR_BASE; i++) { if (!(HalpIDTUsage[i].Flags & IDTOwned)) { HalpIDTUsage[i].Flags = InternalUsage; HalpIDTUsage[i].BusReleativeVector = (UCHAR) i; } } #endif for(pass=0; pass < 2; pass++) { if (pass == 0) { // // First pass - build resource lists for resources reported // reported against device usage. // reporton = DeviceUsage & ~IDTOwned; interfacetype = DeviceInterfaceToUse; } else { // // Second pass = build reousce lists for resources reported // as internal usage. // reporton = InternalUsage & ~IDTOwned; interfacetype = Internal; } CurrentIDT = 0; CurrentElement = 0; CurrentAddress = HalpAddressUsageList; for (; ;) { if (CurrentIDT <= MAXIMUM_VECTOR) { // CHG001 // // Check to see if CurrentIDT needs to be reported // if (!(HalpIDTUsage[CurrentIDT].Flags & reporton)) { // Don't report on this one CurrentIDT++; continue; } // // Report CurrentIDT resource // RPartialDesc.Type = CmResourceTypeInterrupt; RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive; RPartialDesc.Flags = HalpIDTUsage[CurrentIDT].Flags & InterruptLatched ? CM_RESOURCE_INTERRUPT_LATCHED : CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; RPartialDesc.u.Interrupt.Vector = HalpIDTUsage[CurrentIDT].BusReleativeVector; RPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].BusReleativeVector; RPartialDesc.u.Interrupt.Affinity = HalpActiveProcessors; RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc); TPartialDesc.u.Interrupt.Vector = CurrentIDT; TPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].Irql; CurrentIDT++; } else { // // Check to see if CurrentAddress needs to be reported // if (!CurrentAddress) { break; // No addresses left } if (!(CurrentAddress->Flags & reporton)) { // Don't report on this list CurrentElement = 0; CurrentAddress = CurrentAddress->Next; continue; } if (!CurrentAddress->Element[CurrentElement].Length) { // End of current list, go to next list CurrentElement = 0; CurrentAddress = CurrentAddress->Next; continue; } // // Report CurrentAddress // RPartialDesc.Type = (UCHAR) CurrentAddress->Type; RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive; if (RPartialDesc.Type == CmResourceTypePort) { i = 1; // address space port RPartialDesc.Flags = CM_RESOURCE_PORT_IO; } else { i = 0; // address space memory RPartialDesc.Flags = CM_RESOURCE_MEMORY_READ_WRITE; } // Notice: assuming u.Memory and u.Port have the same layout RPartialDesc.u.Memory.Start.HighPart = 0; RPartialDesc.u.Memory.Start.LowPart = CurrentAddress->Element[CurrentElement].Start; RPartialDesc.u.Memory.Length = CurrentAddress->Element[CurrentElement].Length; // translated address = Raw address RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc); HalTranslateBusAddress ( interfacetype, // device bus or internal 0, // bus number RPartialDesc.u.Memory.Start, // source address &i, // address space &TPartialDesc.u.Memory.Start ); // translated address if (RPartialDesc.Type == CmResourceTypePort && i == 0) { TPartialDesc.Flags = CM_RESOURCE_PORT_MEMORY; } CurrentElement++; } // // Include the current resource in the HALs list // if (pRFullDesc->InterfaceType != interfacetype) { // // Interface type changed, add another full section // RawResourceList->Count++; TranslatedResourceList->Count++; pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc; pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc; pRFullDesc->InterfaceType = interfacetype; pTFullDesc->InterfaceType = interfacetype; pRPartList = &pRFullDesc->PartialResourceList; pTPartList = &pTFullDesc->PartialResourceList; // // Bump current location pointers up // pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors; pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors; } pRPartList->Count++; pTPartList->Count++; RtlCopyMemory (pRCurLoc, &RPartialDesc, sizeof RPartialDesc); RtlCopyMemory (pTCurLoc, &TPartialDesc, sizeof TPartialDesc); pRCurLoc++; pTCurLoc++; } } ListSize = (ULONG) ( ((PUCHAR) pRCurLoc) - ((PUCHAR) RawResourceList) ); // // The HAL's resource usage structures have been built // Sort the partial lists based on the Raw resource values // pRFullDesc = RawResourceList->List; pTFullDesc = TranslatedResourceList->List; for (i=0; i < RawResourceList->Count; i++) { pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors; pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors; Count = pRFullDesc->PartialResourceList.Count; for (j=0; j < Count; j++) { HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue); pRSortLoc = pRCurLoc; pTSortLoc = pTCurLoc; for (k=j; k < Count; k++) { HalpGetResourceSortValue (pRSortLoc, &sortscale, &sortvalue); if (sortscale < curscale || (sortscale == curscale && RtlLargeIntegerLessThan (sortvalue, curvalue)) ) { // // Swap the elements.. // RtlCopyMemory (&RPartialDesc, pRCurLoc, sizeof RPartialDesc); RtlCopyMemory (pRCurLoc, pRSortLoc, sizeof RPartialDesc); RtlCopyMemory (pRSortLoc, &RPartialDesc, sizeof RPartialDesc); // swap translated descriptor as well RtlCopyMemory (&TPartialDesc, pTCurLoc, sizeof TPartialDesc); RtlCopyMemory (pTCurLoc, pTSortLoc, sizeof TPartialDesc); RtlCopyMemory (pTSortLoc, &TPartialDesc, sizeof TPartialDesc); // get new curscale & curvalue HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue); } pRSortLoc++; pTSortLoc++; } pRCurLoc++; pTCurLoc++; } pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc; pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc; } // // Inform the IO system of our resources.. // IoReportHalResourceUsage ( HalName, RawResourceList, TranslatedResourceList, ListSize ); ExFreePool (RawResourceList); ExFreePool (TranslatedResourceList); }
static NTSTATUS IopTranslateDeviceResources( IN PDEVICE_NODE DeviceNode) { PCM_PARTIAL_RESOURCE_LIST pPartialResourceList; PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw, DescriptorTranslated; ULONG i, j, ListSize; NTSTATUS Status; if (!DeviceNode->ResourceList) { DeviceNode->ResourceListTranslated = NULL; return STATUS_SUCCESS; } /* That's easy to translate a resource list. Just copy the * untranslated one and change few fields in the copy */ ListSize = PnpDetermineResourceListSize(DeviceNode->ResourceList); DeviceNode->ResourceListTranslated = ExAllocatePool(PagedPool, ListSize); if (!DeviceNode->ResourceListTranslated) { Status = STATUS_NO_MEMORY; goto cleanup; } RtlCopyMemory(DeviceNode->ResourceListTranslated, DeviceNode->ResourceList, ListSize); for (i = 0; i < DeviceNode->ResourceList->Count; i++) { pPartialResourceList = &DeviceNode->ResourceList->List[i].PartialResourceList; for (j = 0; j < pPartialResourceList->Count; j++) { DescriptorRaw = &pPartialResourceList->PartialDescriptors[j]; DescriptorTranslated = &DeviceNode->ResourceListTranslated->List[i].PartialResourceList.PartialDescriptors[j]; switch (DescriptorRaw->Type) { case CmResourceTypePort: { ULONG AddressSpace = 1; /* IO space */ if (!HalTranslateBusAddress( DeviceNode->ResourceList->List[i].InterfaceType, DeviceNode->ResourceList->List[i].BusNumber, DescriptorRaw->u.Port.Start, &AddressSpace, &DescriptorTranslated->u.Port.Start)) { Status = STATUS_UNSUCCESSFUL; DPRINT1("Failed to translate port resource (Start: 0x%I64x)\n", DescriptorRaw->u.Port.Start.QuadPart); goto cleanup; } if (AddressSpace == 0) { DPRINT1("Guessed incorrect address space: 1 -> 0\n"); /* FIXME: I think all other CM_RESOURCE_PORT_XXX flags are * invalid for this state but I'm not 100% sure */ DescriptorRaw->Flags = DescriptorTranslated->Flags = CM_RESOURCE_PORT_MEMORY; } break; } case CmResourceTypeInterrupt: { DescriptorTranslated->u.Interrupt.Vector = HalGetInterruptVector( DeviceNode->ResourceList->List[i].InterfaceType, DeviceNode->ResourceList->List[i].BusNumber, DescriptorRaw->u.Interrupt.Level, DescriptorRaw->u.Interrupt.Vector, (PKIRQL)&DescriptorTranslated->u.Interrupt.Level, &DescriptorTranslated->u.Interrupt.Affinity); if (!DescriptorTranslated->u.Interrupt.Vector) { Status = STATUS_UNSUCCESSFUL; DPRINT1("Failed to translate interrupt resource (Vector: 0x%x | Level: 0x%x)\n", DescriptorRaw->u.Interrupt.Vector, DescriptorRaw->u.Interrupt.Level); goto cleanup; } break; } case CmResourceTypeMemory: { ULONG AddressSpace = 0; /* Memory space */ if (!HalTranslateBusAddress( DeviceNode->ResourceList->List[i].InterfaceType, DeviceNode->ResourceList->List[i].BusNumber, DescriptorRaw->u.Memory.Start, &AddressSpace, &DescriptorTranslated->u.Memory.Start)) { Status = STATUS_UNSUCCESSFUL; DPRINT1("Failed to translate memory resource (Start: 0x%I64x)\n", DescriptorRaw->u.Memory.Start.QuadPart); goto cleanup; } if (AddressSpace != 0) { DPRINT1("Guessed incorrect address space: 0 -> 1\n"); /* This should never happen for memory space */ ASSERT(FALSE); } } case CmResourceTypeDma: case CmResourceTypeBusNumber: case CmResourceTypeDeviceSpecific: /* Nothing to do */ break; default: DPRINT1("Unknown resource descriptor type 0x%x\n", DescriptorRaw->Type); Status = STATUS_NOT_IMPLEMENTED; goto cleanup; } } } return STATUS_SUCCESS; cleanup: /* Yes! Also delete ResourceList because ResourceList and * ResourceListTranslated should be a pair! */ ExFreePool(DeviceNode->ResourceList); DeviceNode->ResourceList = NULL; if (DeviceNode->ResourceListTranslated) { ExFreePool(DeviceNode->ResourceListTranslated); DeviceNode->ResourceList = NULL; } return Status; }
static NTSTATUS NTAPI ConfigCallback(PVOID Context, PUNICODE_STRING PathName, INTERFACE_TYPE BusType, ULONG BusNumber, PKEY_VALUE_FULL_INFORMATION *BusInformation, CONFIGURATION_TYPE ControllerType, ULONG ControllerNumber, PKEY_VALUE_FULL_INFORMATION *ControllerInformation, CONFIGURATION_TYPE PeripheralType, ULONG PeripheralNumber, PKEY_VALUE_FULL_INFORMATION *PeripheralInformation) /* * FUNCTION: Callback to IoQueryDeviceDescription, which tells us about our controllers * ARGUMENTS: * Context: Unused * PathName: Unused * BusType: Type of the bus that our controller is on * BusNumber: Number of the bus that our controller is on * BusInformation: Unused * ControllerType: Unused * ControllerNumber: Number of the controller that we're adding * ControllerInformation: Full configuration information for our controller * PeripheralType: Unused * PeripheralNumber: Unused * PeripheralInformation: Full configuration information for each drive on our controller * RETURNS: * STATUS_SUCCESS in all cases * NOTES: * - The only documentation I've found about the contents of these structures is * from the various Microsoft floppy samples and from the DDK headers. They're * very vague, though, so I'm only mostly sure that this stuff is correct, as * the MS samples do things completely differently than I have done them. Seems * to work in my VMWare, though. * - Basically, the function gets all of the information (port, dma, irq) about the * controller, and then loops through all of the drives presented in PeripheralInformation. * - Each controller has a CONTROLLER_INFO created for it, and each drive has a DRIVE_INFO. * - Device objects are created for each drive (not controller), as that's the targeted * device in the eyes of the rest of the OS. Each DRIVE_INFO points to a single CONTROLLER_INFO. * - We only support up to four controllers in the whole system, each of which supports up to four * drives. */ { PKEY_VALUE_FULL_INFORMATION ControllerFullDescriptor = ControllerInformation[IoQueryDeviceConfigurationData]; PCM_FULL_RESOURCE_DESCRIPTOR ControllerResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PCHAR)ControllerFullDescriptor + ControllerFullDescriptor->DataOffset); PKEY_VALUE_FULL_INFORMATION PeripheralFullDescriptor = PeripheralInformation[IoQueryDeviceConfigurationData]; PCM_FULL_RESOURCE_DESCRIPTOR PeripheralResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PCHAR)PeripheralFullDescriptor + PeripheralFullDescriptor->DataOffset); PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; PCM_FLOPPY_DEVICE_DATA FloppyDeviceData; UCHAR i; PAGED_CODE(); UNREFERENCED_PARAMETER(PeripheralType); UNREFERENCED_PARAMETER(PeripheralNumber); UNREFERENCED_PARAMETER(BusInformation); UNREFERENCED_PARAMETER(Context); UNREFERENCED_PARAMETER(ControllerType); UNREFERENCED_PARAMETER(PathName); TRACE_(FLOPPY, "ConfigCallback called with ControllerNumber %d\n", ControllerNumber); gControllerInfo[gNumberOfControllers].ControllerNumber = ControllerNumber; gControllerInfo[gNumberOfControllers].InterfaceType = BusType; gControllerInfo[gNumberOfControllers].BusNumber = BusNumber; /* Get controller interrupt level/vector, dma channel, and port base */ for(i = 0; i < ControllerResourceDescriptor->PartialResourceList.Count; i++) { KeInitializeEvent(&gControllerInfo[gNumberOfControllers].SynchEvent, NotificationEvent, FALSE); PartialDescriptor = &ControllerResourceDescriptor->PartialResourceList.PartialDescriptors[i]; if(PartialDescriptor->Type == CmResourceTypeInterrupt) { gControllerInfo[gNumberOfControllers].Level = PartialDescriptor->u.Interrupt.Level; gControllerInfo[gNumberOfControllers].Vector = PartialDescriptor->u.Interrupt.Vector; if(PartialDescriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED) gControllerInfo[gNumberOfControllers].InterruptMode = Latched; else gControllerInfo[gNumberOfControllers].InterruptMode = LevelSensitive; } else if(PartialDescriptor->Type == CmResourceTypePort) { PHYSICAL_ADDRESS TranslatedAddress; ULONG AddressSpace = 0x1; /* I/O Port Range */ if(!HalTranslateBusAddress(BusType, BusNumber, PartialDescriptor->u.Port.Start, &AddressSpace, &TranslatedAddress)) { WARN_(FLOPPY, "HalTranslateBusAddress failed; returning\n"); return STATUS_IO_DEVICE_ERROR; } if(AddressSpace == 0) gControllerInfo[gNumberOfControllers].BaseAddress = MmMapIoSpace(TranslatedAddress, FDC_PORT_BYTES, MmNonCached); else gControllerInfo[gNumberOfControllers].BaseAddress = (PUCHAR)(ULONG_PTR)TranslatedAddress.QuadPart; } else if(PartialDescriptor->Type == CmResourceTypeDma) gControllerInfo[gNumberOfControllers].Dma = PartialDescriptor->u.Dma.Channel; } /* Start with 0 drives, then go looking */ gControllerInfo[gNumberOfControllers].NumberOfDrives = 0; /* learn about drives attached to controller */ for(i = 0; i < PeripheralResourceDescriptor->PartialResourceList.Count; i++) { PDRIVE_INFO DriveInfo = &gControllerInfo[gNumberOfControllers].DriveInfo[i]; PartialDescriptor = &PeripheralResourceDescriptor->PartialResourceList.PartialDescriptors[i]; if(PartialDescriptor->Type != CmResourceTypeDeviceSpecific) continue; FloppyDeviceData = (PCM_FLOPPY_DEVICE_DATA)(PartialDescriptor + 1); DriveInfo->ControllerInfo = &gControllerInfo[gNumberOfControllers]; DriveInfo->UnitNumber = i; DriveInfo->FloppyDeviceData.MaxDensity = FloppyDeviceData->MaxDensity; DriveInfo->FloppyDeviceData.MountDensity = FloppyDeviceData->MountDensity; DriveInfo->FloppyDeviceData.StepRateHeadUnloadTime = FloppyDeviceData->StepRateHeadUnloadTime; DriveInfo->FloppyDeviceData.HeadLoadTime = FloppyDeviceData->HeadLoadTime; DriveInfo->FloppyDeviceData.MotorOffTime = FloppyDeviceData->MotorOffTime; DriveInfo->FloppyDeviceData.SectorLengthCode = FloppyDeviceData->SectorLengthCode; DriveInfo->FloppyDeviceData.SectorPerTrack = FloppyDeviceData->SectorPerTrack; DriveInfo->FloppyDeviceData.ReadWriteGapLength = FloppyDeviceData->ReadWriteGapLength; DriveInfo->FloppyDeviceData.FormatGapLength = FloppyDeviceData->FormatGapLength; DriveInfo->FloppyDeviceData.FormatFillCharacter = FloppyDeviceData->FormatFillCharacter; DriveInfo->FloppyDeviceData.HeadSettleTime = FloppyDeviceData->HeadSettleTime; DriveInfo->FloppyDeviceData.MotorSettleTime = FloppyDeviceData->MotorSettleTime; DriveInfo->FloppyDeviceData.MaximumTrackValue = FloppyDeviceData->MaximumTrackValue; DriveInfo->FloppyDeviceData.DataTransferLength = FloppyDeviceData->DataTransferLength; /* Once it's all set up, acknowledge its existance in the controller info object */ gControllerInfo[gNumberOfControllers].NumberOfDrives++; } gControllerInfo[gNumberOfControllers].Populated = TRUE; gNumberOfControllers++; return STATUS_SUCCESS; }
BOOLEAN NTAPI HaliFindBusAddressTranslation(IN PHYSICAL_ADDRESS BusAddress, IN OUT PULONG AddressSpace, OUT PPHYSICAL_ADDRESS TranslatedAddress, IN OUT PULONG_PTR Context, IN BOOLEAN NextBus) { PHAL_BUS_HANDLER BusHandler; PBUS_HANDLER Handler; PLIST_ENTRY NextEntry; ULONG ContextValue; /* Make sure we have a context */ if (!Context) return FALSE; ASSERT((*Context) || (NextBus == TRUE)); /* Read the context */ ContextValue = *Context; /* Find the bus handler */ Handler = HalpContextToBusHandler(ContextValue); if (!Handler) return FALSE; /* Check if this is an ongoing lookup */ if (NextBus) { /* Get the HAL bus handler */ BusHandler = CONTAINING_RECORD(Handler, HAL_BUS_HANDLER, Handler); NextEntry = &BusHandler->AllHandlers; /* Get the next one if we were already with one */ if (ContextValue) NextEntry = NextEntry->Flink; /* Start scanning */ while (TRUE) { /* Check if this is the last one */ if (NextEntry == &HalpAllBusHandlers) { /* Quit */ *Context = 1; return FALSE; } /* Call this translator */ BusHandler = CONTAINING_RECORD(NextEntry, HAL_BUS_HANDLER, AllHandlers); if (HalTranslateBusAddress(BusHandler->Handler.InterfaceType, BusHandler->Handler.BusNumber, BusAddress, AddressSpace, TranslatedAddress)) break; /* Try the next one */ NextEntry = NextEntry->Flink; } /* If we made it, we're done */ *Context = (ULONG_PTR)Handler; return TRUE; } /* Try the first one through */ if (!HalTranslateBusAddress(Handler->InterfaceType, Handler->BusNumber, BusAddress, AddressSpace, TranslatedAddress)) return FALSE; /* Remember for next time */ *Context = (ULONG_PTR)Handler; return TRUE; }