//////////////////////////////////////////////////////////////////
// File - pci_diag.c
//
// This is a diagnostics application for accessing the PCI card.
// Code was generated by WinDriver Wizard.
// It accesses the hardware via WinDriver functions.
// 
//////////////////////////////////////////////////////////////////

#include "pci_lib.h"
#include "../shared/pci_diag_lib.h"
#include <stdio.h>

// input of command from user
static char line[256];

char *PCI_GetAddrSpaceName(PCI_ADDR addrSpace)
{
    return 
        addrSpace==PCI_AD_BAR0 ? "Addr Space BAR0" :
        addrSpace==PCI_AD_BAR1 ? "Addr Space BAR1" :
        addrSpace==PCI_AD_BAR2 ? "Addr Space BAR2" :
        addrSpace==PCI_AD_BAR3 ? "Addr Space BAR3" :
        addrSpace==PCI_AD_BAR4 ? "Addr Space BAR4" :
        addrSpace==PCI_AD_BAR5 ? "Addr Space BAR5" :
        addrSpace==PCI_AD_EPROM ? "EEPROM Addr Space" :
        "Invalid";
}

void PCI_AccessRanges(PCI_HANDLE hPCI)
{
    int cmd, cmd2, i;
    DWORD addr, data;
    PCI_ADDR ad_sp = 0;
    PCI_MODE ad_mode = PCI_MODE_DWORD;

    for (; ad_sp<PCI_ITEMS && !PCI_IsAddrSpaceActive(hPCI, ad_sp); ad_sp++)
    if (ad_sp==PCI_ITEMS)
    {
        printf ("No active memory or IO ranges on board!\n");
        return;
    }

    do
    {
        printf ("Access the board's memory and IO ranges\n");
        printf ("---------------------------------------\n");
        printf ("1. Change active memory space: %s\n",PCI_GetAddrSpaceName(ad_sp));
        printf ("2. Toggle active mode: %s\n", 
            ad_mode==PCI_MODE_BYTE ? "BYTE (8 bit)" :
            ad_mode==PCI_MODE_WORD ? "WORD (16 bit)" : "DWORD (32 bit)");
        printf ("3. Read from board\n");
        printf ("4. Write to board\n");
        printf ("99. Back to main menu\n");
        printf ("\n");
        printf ("Enter option: ");
        cmd = 0;
        gets(line);
        sscanf(line, "%d",&cmd);
        switch (cmd)
        {
        case 1:
            printf ("Choose memory or IO space:\n");
            printf ("--------------------------\n");
            for (i=0; i<PCI_ITEMS; i++)
            {
                printf ("%d. %s\n", i+1, PCI_GetAddrSpaceName(i));
                if (!PCI_IsAddrSpaceActive(hPCI, i))
                    printf (" - space not active\n");
            }
            printf ("Enter option: ");
            cmd2 = 99;
            gets(line);
            sscanf(line, "%d",&cmd2);
            if (cmd2>=1 && cmd2<PCI_ITEMS+1)
            {
                ad_sp = cmd2-1;
                if (!PCI_IsAddrSpaceActive(hPCI, ad_sp))
                    printf ("Chosen space not active!\n");
            }
            break;
        case 2:
            ad_mode = (ad_mode + 1) % 3;
            break;
        case 3:
            printf ("Enter offset to read from: ");
            gets(line);
            sscanf (line, "%x", &addr);
            switch (ad_mode)
            {
            case PCI_MODE_BYTE:
                data = PCI_ReadByte(hPCI, ad_sp, addr);
                break;
            case PCI_MODE_WORD:
                data = PCI_ReadWord(hPCI, ad_sp, addr);
                break;
            case PCI_MODE_DWORD:
                data = PCI_ReadDword(hPCI, ad_sp, addr);
                break;
            }
            printf ("Value read: %x\n", data);
            break;
        case 4:
            printf ("Enter offset to write to: ");
            gets(line);
            sscanf (line,"%x", &addr);
            printf ("Enter data to write %s: ",
                ad_mode==PCI_MODE_BYTE ? "BYTE (8 bit)" :
                ad_mode==PCI_MODE_WORD ? "WORD (16 bit)" : "DWORD (32 bit)");
            gets(line);
            sscanf (line, "%x",&data);
            switch (ad_mode)
            {
            case PCI_MODE_BYTE:
                PCI_WriteByte(hPCI, ad_sp, addr, (BYTE) data);
                break;
            case PCI_MODE_WORD:
                PCI_WriteWord(hPCI, ad_sp, addr, (WORD) data);
                break;
            case PCI_MODE_DWORD:
                PCI_WriteDword(hPCI, ad_sp, addr, data);
                break;
            }
            break;
        }
    } while (cmd!=99);
}

void WINAPI PCI_IntHandlerRoutine(PCI_HANDLE hPCI, PCI_INT_RESULT *intResult)
{
    printf ("Got Int number %d\n", intResult->dwCounter);
}

void PCI_EnableDisableInterrupts(PCI_HANDLE hPCI)
{
    int cmd;

    printf ("WARNING!!!\n");
    printf ("----------\n");
    printf ("Your hardware has level sensitive interrupts.\n");
    printf ("You must modify the source code of PCI_IntEnable(), in the file pci_lib.c,\n");
    printf ("to acknowledge the interrupt before enabling interrupts.\n");
    printf ("Without this modification, your PC will HANG upon interrupt!\n");
    printf ("\n");

    do
    {
        printf ("Enable / Disable interrupts\n");
        printf ("---------------------------\n");
        printf ("1. %s Int\n", PCI_IntIsEnabled(hPCI) ? "Disable" : "Enable");
        printf ("99. Back to main menu\n");
        printf ("\n");
        printf ("Enter option: ");
        cmd = 0;
        gets(line);
        sscanf(line, "%d",&cmd);
        switch (cmd)
        {
        case 1:
            if (PCI_IntIsEnabled(hPCI))
            {
                printf ("Disabling interrupt Int\n");
                PCI_IntDisable(hPCI);
            }
            else
            {
                printf ("Enabling interrupt Int\n");
                if (!PCI_IntEnable(hPCI, PCI_IntHandlerRoutine))
                    printf ("failed enabling interrupt Int\n");
            }
            break;
        }
    } while (cmd!=99);
}

PCI_HANDLE PCI_LocateAndOpenBoard(DWORD dwVendorID, DWORD dwDeviceID, BOOL fUseInt)
{
    DWORD cards, my_card;
    PCI_HANDLE hPCI = NULL;

    if (dwVendorID==0)
    {
        printf ("Enter VendorID: ");
        gets(line);
        sscanf (line, "%x",&dwVendorID);
        if (dwVendorID==0) return NULL;

        printf ("Enter DeviceID: ");
        gets(line);
        sscanf (line, "%x",&dwDeviceID);
    }
    cards = PCI_CountCards (dwVendorID, dwDeviceID);
    if (cards==0)
    {
        printf("%s", PCI_ErrorString);
        return NULL;
    }
    else if (cards==1) my_card = 1;
    else
    {
        DWORD i;

        printf("Found %d matching PCI cards\n", cards);
        printf("Select card (1-%d): ", cards);
        i = 0;
        gets(line);
        sscanf (line, "%d",&i);
        if (i>=1 && i <=cards) my_card = i;
        else 
        {
            printf ("Choice out of range\n");
            return NULL;
        }
    }
    if (PCI_Open (&hPCI, dwVendorID, dwDeviceID, my_card - 1, fUseInt ? PCI_OPEN_USE_INT : 0 ))
        printf ("PCI PCI card found!\n");
    else printf ("%s", PCI_ErrorString);
    return hPCI;
}

int main(int argc, char *argv[])
{
    int cmd;
    PCI_HANDLE hPCI = NULL;
    HANDLE hWD;
    BOOL fUseInt = FALSE; // by default - do not install interrupts

    printf ("PCI diagnostic utility.\n");
    printf ("Application accesses hardware using WinDriver.\n");

    // make sure WinDriver is loaded
    if (!PCI_Get_WD_handle(&hWD)) return 0;

    if (PCI_DEFAULT_VENDOR_ID)
        hPCI = PCI_LocateAndOpenBoard(PCI_DEFAULT_VENDOR_ID, PCI_DEFAULT_DEVICE_ID, fUseInt);

    do
    {
        printf ("\n");
        printf ("PCI main menu\n");
        printf ("-------------------\n");
        printf ("1. Scan PCI bus\n");
        printf ("2. Set opening board %s interrupts\n", fUseInt ? "without" : "with");
        printf ("3. Locate/Choose PCI board (%s interrupts)\n", fUseInt ? "with" : "without");
        if (hPCI)
        {
            printf ("4. PCI configuration registers\n");
            printf ("6. Access PCI memory and IO ranges\n");
            if (hPCI->fUseInt)
                printf ("7. Enable / Disable interrupts\n");
        }
        printf ("99. Exit\n");
        printf ("Enter option: ");
        cmd = 0;
        gets(line);
        sscanf(line, "%d",&cmd);
        switch (cmd)
        {
        case 1: // Scan PCI bus
            PCI_Print_all_cards_info();
            break;
        case 2: // Set opening board with / without interrupts
            fUseInt = !fUseInt;
            break;
        case 3: // Locate PCI board
            if (hPCI) PCI_Close(hPCI);
            hPCI = PCI_LocateAndOpenBoard(0, 0, fUseInt);
            if (!hPCI) printf ("PCI card open failed!\n");
            break;
        case 4: // PCI configuration registers
            if (hPCI) PCI_EditConfigReg(hPCI->pciSlot);
            break;
        case 6: // Access PCI memory and IO ranges
            if (hPCI) PCI_AccessRanges(hPCI);
            break;
        case 7: // Enable / Disable interrupts
            if (hPCI && hPCI->fUseInt)
                PCI_EnableDisableInterrupts(hPCI);
            break;
        }
    } while (cmd!=99);

    if (hPCI) PCI_Close(hPCI);

    WD_Close (hWD);

    return 0;
}