//
// MEMTEST.c
//
// Test proggie for the MAPMEM device driver. Asks the MAPMEM driver
//   to map the specified physical memory into this process's
//   address space so we can party on it.
//
// To test this (on x86 ISA platforms) try: "memtest 1 0 655360 10000"
//   and watch it draw on video memory.
//

#include "windows.h"
#include "stdio.h"
#include "stdlib.h"



//
// A couple of typedefs mapmem.h depends on from  MINIPORT.H & NTDDK.H.
//

typedef enum _INTERFACE_TYPE {
    Internal,
    Isa,
    Eisa,
    MicroChannel,
    TurboChannel,
    MaximumInterfaceType
}INTERFACE_TYPE, *PINTERFACE_TYPE;

typedef LARGE_INTEGER PHYSICAL_ADDRESS;

#include "..\mapmem.h"



int main(int argc, char *argv[])
{
    HANDLE               hDriver;
    PHYSICAL_MEMORY_INFO pmi;
    PVOID                pPartyMem;
    DWORD                cbReturned;
    ULONG                length;
    char                 *aInterfaceType[] =  {"Internal",
                                               "Isa",
                                               "Eisa",
                                               "MicroChannel",
                                               "TurboChannel" };

    if (argc < 4)
    {
        printf ("\nUsage: memtest <interfaceType> <bus#> <physicalAddr> <length>\n\n");
        printf ("\t<interfaceType>: 1 = Isa, 2 = Eisa, 3 = Microchannel, 4 = TurboChannel\n");
        printf ("\t<bus#>         : bus number, i.e. 0 for standard x86 ISA systems\n");
        printf ("\t<physicalAddr> : physical address to map (decimal)\n");
        printf ("\t<length>       : length of section to map (decimal)\n\n");

        printf ("\tTry 'memtest 1 0 655360 8192' to retrieve a pointer to\n");
        printf ("\tphysical address 0xA0000 (x86 ISA VGA video memory), and\n");
        printf ("\tthen write out to the memory.\n");
        return 0;
    }

    if ((hDriver = CreateFile("\\\\.\\MAPMEM",
                              GENERIC_READ | GENERIC_WRITE,
                              0,
                              NULL,
                              OPEN_EXISTING,
                              FILE_ATTRIBUTE_NORMAL,
                              NULL
                              )) != ((HANDLE)-1))

        printf("\nRetrieved valid handle for MAPMEM driver\n");


    else
    {
        printf("Can't get a handle to MAPMEM driver\n");
        return 0;
    }

    pmi.interfaceType            = (INTERFACE_TYPE) atoi (argv[1]);
    pmi.busNumber                = (ULONG)          atoi (argv[2]);
    pmi.physicalAddress.LowPart  = (ULONG)          atoi (argv[3]);
    pmi.physicalAddress.HighPart = (LONG)           0x00000000;
    length = pmi.length          = (ULONG)          atoi (argv[4]);

    printf ("\tinterfaceType = %s\n", aInterfaceType[pmi.interfaceType]);
    printf ("\tbus number    = %d\n", pmi.busNumber);
    printf ("\tphysicalAddr  = %d (0x%x)\n",
            pmi.physicalAddress.LowPart, pmi.physicalAddress.LowPart);
    printf ("\tlength        = %d (0x%x)\n", pmi.length, pmi.length);

    if (DeviceIoControl (hDriver,
                         IOCTL_MAPMEM_MAP_USER_PHYSICAL_MEMORY,
                         &pmi,
                         sizeof(PHYSICAL_MEMORY_INFO),
                         &pPartyMem,
                         sizeof(PVOID),
                         &cbReturned,
                         0
                         ) )
    {
        ULONG j;

        //
        // party on memory...
        //

        if (pPartyMem)
        {
            UCHAR uc;

            for (j = 0; j < length; j++)
            {
                uc = *(((PUCHAR) pPartyMem) + j);

                *(((PUCHAR) pPartyMem) + j) = 0x47;
            }
        }

        else

            printf ("pPartyMem = NULL\n");
    }

    else

        printf ("DeviceIoControl failed\n");


    CloseHandle(hDriver);

    return 1;
}
