
/*M*                     
//                    INTEL CORPORATION PROPRIETARY INFORMATION
//      This software is supplied under the terms of a license agreement or
//      nondisclosure agreement with Intel Corporation and may not be copied
//      or disclosed except in accordance with the terms of that agreement.
//            Copyright (c) 1995-2000 Intel Corporation.  All Rights Reserved.
//
*M*/
/*
 * $Log:   \\cospublic004\shareddata\ISC\ISC2x\NTWORK\SRC\imb\memmap.c.v  $
 * 
 *    Rev 1.1   08 Dec 1998 10:55:48   jpaiasno
 * Added code to support async.
 * DPC events from the EMP console.
 * 
 *    Rev 1.2   24 Mar 1998 14:40:54   fkhanx
 * Added copyright header
*/

#ifndef UWSVR4

#include "imb_os.h"
#include "memIf.h"

/////////////////////////////////////////////////////////////////////////////////////////////////

/*F*
//  Name:       MapTheMemory
//  Purpose:    Given a physical address range, maps it into a user mode process's
//                          address space
.
//  Context:    Called by map memory IOCTL  processing Mismic  device control function.
//  Returns:    STATUS_SUCCESS or STATUS_UNSUCCESSFUL
//  Parameters:
//                              DeviceObject            Pointer to device object        
//              IoBuffer                Pointer to bus number storage location
//                              InputBufferLength       length of input buffer 
//              OutputBufferLength  output buffer length. size of the mapped address pointer.
//  Notes:      
*F*/

NTSTATUS
MapTheMemory (
    IN PDEVICE_OBJECT DeviceObject,
    IN OUT PVOID      IoBuffer,
    IN ULONG          InputBufferLength,
    IN ULONG          OutputBufferLength
    )
{

    PPHYSICAL_MEMORY_INFO ppmi = (PPHYSICAL_MEMORY_INFO) IoBuffer;

    INTERFACE_TYPE     interfaceType;
    ULONG              busNumber;
    PHYSICAL_ADDRESS   physicalAddress;
    ULONG              length;
    UNICODE_STRING     physicalMemoryUnicodeString;
    OBJECT_ATTRIBUTES  objectAttributes;
    HANDLE             physicalMemoryHandle  = NULL;
    PVOID              PhysicalMemorySection = NULL;
    ULONG              inIoSpace, inIoSpace2;
    NTSTATUS           ntStatus;
    PHYSICAL_ADDRESS   physicalAddressBase;
    PHYSICAL_ADDRESS   physicalAddressEnd;
    PHYSICAL_ADDRESS   viewBase;
    PHYSICAL_ADDRESS   mappedLength;
    BOOLEAN            translateBaseAddress;
    BOOLEAN            translateEndAddress;
    PVOID              virtualAddress;

  


    if ( ( InputBufferLength  < sizeof (PHYSICAL_MEMORY_INFO) ) ||
		 ( OutputBufferLength < sizeof (PVOID) ) )      {
      

       ntStatus = STATUS_INSUFFICIENT_RESOURCES;

       goto done;
    }

    interfaceType          = ppmi->InterfaceType;
    busNumber              = ppmi->BusNumber;
    physicalAddress        = ppmi->BusAddress;
    inIoSpace = inIoSpace2 = ppmi->AddressSpace;
    length                 = ppmi->Length;

    //
    // Get a pointer to physical memory...
    //
    // - Create the name
    // - Initialize the data to find the object
    // - Open a handle to the oject and check the status
    // - Get a pointer to the object
    // - Free the handle
    //
    RtlInitUnicodeString (&physicalMemoryUnicodeString,
			  L"\\Device\\PhysicalMemory");

    InitializeObjectAttributes (&objectAttributes,
				&physicalMemoryUnicodeString,
				OBJ_CASE_INSENSITIVE,
				(HANDLE) NULL,
				(PSECURITY_DESCRIPTOR) NULL);

    ntStatus = ZwOpenSection (&physicalMemoryHandle,
			      SECTION_ALL_ACCESS,
			      &objectAttributes);

    if ( !NT_SUCCESS(ntStatus) )  {
		goto done;
    }
    ntStatus = ObReferenceObjectByHandle (physicalMemoryHandle,
					  SECTION_ALL_ACCESS,
					  (POBJECT_TYPE) NULL,
					  KernelMode,
					  &PhysicalMemorySection,
					  (POBJECT_HANDLE_INFORMATION) NULL);

    if ( !NT_SUCCESS(ntStatus) )  {
		goto close_handle;
    }
    //
    // Initialize the physical addresses that will be translated
    //
    physicalAddressEnd = RtlLargeIntegerAdd (physicalAddress,
							 RtlConvertUlongToLargeInteger(
							 length));
    //
    // Translate the physical addresses.
    //
    translateBaseAddress = HalTranslateBusAddress (interfaceType,
								busNumber,
								physicalAddress,
								&inIoSpace,
								&physicalAddressBase );

    translateEndAddress = HalTranslateBusAddress (interfaceType,
								busNumber,
								physicalAddressEnd,
								&inIoSpace2,
								&physicalAddressEnd );

    if ( !(translateBaseAddress && translateEndAddress) ) {
		ntStatus = STATUS_UNSUCCESSFUL;

		goto close_handle;
    }
    //
    // Calculate the length of the memory to be mapped
    //
    mappedLength = RtlLargeIntegerSubtract ( physicalAddressEnd, physicalAddressBase );

    //
    // If the mappedlength is zero, somthing  weird happened in the HAL
    // since the Length was checked against zero.
    //
    if ( mappedLength.LowPart == 0 ) {
		ntStatus = STATUS_UNSUCCESSFUL;

		goto close_handle;
    }
    length = mappedLength.LowPart;

    //
    // If the address is in io space, just return the address, otherwise
    // go through the mapping mechanism
    //
    if ( inIoSpace ) {
		*((PVOID *) IoBuffer) = (PVOID) physicalAddressBase.LowPart;
    } else {
		//
		// initialize view base that will receive the physical mapped
		// address after the MapViewOfSection call.
		//
		viewBase = physicalAddressBase;

		//
		// Let ZwMapViewOfSection pick an address
		//
		virtualAddress = NULL;

		//
		// Map the section
		//
		ntStatus = ZwMapViewOfSection ( physicalMemoryHandle,
						   (HANDLE) -1,
						   &virtualAddress,
						   0L,
						   length,
						   &viewBase,
						   &length,
						   ViewShare,
						   0,
						   PAGE_READWRITE | PAGE_NOCACHE);

		if ( !NT_SUCCESS(ntStatus) ) {
			goto close_handle;
		}
		//
		// Mapping the section above rounded the physical address down to the
		// nearest 64 K boundary. Now return a virtual address that sits where
		// we want by adding in the offset from the beginning of the section.
		//
		(ULONG) virtualAddress	+= (ULONG)physicalAddressBase.LowPart - (ULONG)viewBase.LowPart;

		*((PVOID *) IoBuffer)	 = virtualAddress;
    }
    ntStatus = STATUS_SUCCESS;

close_handle:

    ZwClose (physicalMemoryHandle);

done:

    return ntStatus;
}
#endif // UWSVR4
