//Declare some globals 
PCI_INFO PciInfo;
HANDLE hPort;
HANDLE hMem;
HANDLE hDma;
HANDLE hIntr;
UCHAR InterruptLine;
DWORD MemBasePA;
DWORD DmaBasePA;
long DmaSize = 0x20000;        
DWORD Error;
char szEventName[EVENT_NAME_SIZE]; 

//System data declaration for use in ring0
#pragma data_seg(".sdata")
    USHORT IoBasePA = 0;
    UCHAR Istat = 0;
    UCHAR Dstat = 0;
    UCHAR Sist0 = 0;
    UCHAR Sist1 = 0;
#pragma data_seg()

//System code declaration for use in ring0
//This routine really runs at RING0 in Kernel mode
//and has IOPL privileges.
#pragma code_seg(".scode")
void static IsrRoutine(void)
{
    //Reset interrupts by reading registers
    SHA_SYSTEM_READPORT(IoBasePA + 0x14, &Istat);
    SHA_SYSTEM_READPORT(IoBasePA + 0x0C, &Dstat);
    SHA_SYSTEM_READPORT(IoBasePA + 0x42, &Sist0);
    SHA_SYSTEM_READPORT(IoBasePA + 0x43, &Sist1);
}
#pragma code_seg()

//Get PCI BIOS configuration
Error = ShaScanPciBus(
                  0x1000,      //Vendor ID
                  0x0001,      //Device ID 
                  &PciInfo);   //OUT : Pointer to PCI info    

IoBasePA = (USHORT)(PciInfo.BaseAddr[0] & (~1));
MemBasePA = (ULONG)(PciInfo.BaseAddr[1]); 
InterruptLine = (UCHAR)PciInfo.IntrLine;

//Register IO address space
Error = ShaRegisterPort(
                  IFT_PCIBUS,       //Interface type
                  IoBasePA,         //Physical IO base address
                  0x100,            //Memory range
                  &hPort);          //Port handle

//Map physical memory and get pointer to it
Error = ShaMapMem(
             IFT_PCIBUS,            //Interface type
             MemBasePA,             //Physical memory mapped base address
             0x100,                 //Memory range
             (void**)&pPort,        //Pointer to port memory
             &hMem);                //Port handle

//Allocate DMA memory
Error = ShaAllocMem(
             IFT_PCIBUS,            //Interface type
             TRUE,                  //Set busmaster DMA
             0,                     //Required channel for system DMA
             &DmaBasePA,            //Physical address
             &DmaSize,              //Memory range
             (void**)&pDma,         //Pointer to user DMA memory
             &hDma);                //Handle to DMA device

//Set interrupt for busmaster DMA
Error = ShaConnectInterrupt(
                     IFT_PCIBUS,      //Interface type
                     IsrRoutine,      //Optional fast ISR function
                     NULL,            //Optional handle to DMA device (only required for slave DMA)
                     InterruptLine,   //Interrupt number
                     szEventName,     //Interrupt event name
                     &hIntr);         //Interrupt handle

//Reset interrupts by reading registers (IO space access)
Error = ShaReadPort(IoBasePA + ISTAT, &Istat);
Error = ShaReadPort(IoBasePA + DSTAT, &Dstat);
Error = ShaReadPort(IoBasePA + SIST0, &Sist0); 
Error = ShaReadPort(IoBasePA + SIST1, &Sist1); 
  
//Start the programm (mapped memory access)
pPort[0x2C] = (UCHAR)(DmaBasePA);
pPort[0x2D] = (UCHAR)(DmaBasePA >> 8);
pPort[0x2E] = (UCHAR)(DmaBasePA >> 16);
pPort[0x2F] = (UCHAR)(DmaBasePA >> 24); 
  
//Open interrupt event with the received
//event name by ShaConnectInterrupt
HANDLE hEvent = OpenEvent(SYNCHRONIZE, FALSE, szEventName) ;
if (hEvent)
{
    //Wait for interrupt event
    WaitForSingleObject(hEvent, INFINITE);
}

//////////////////////////////////////////////////////
//Note: After usage, clean up all requested resources
//////////////////////////////////////////////////////
CloseHandle(hEvent);
ShaDisconnectInterrupt(hIntr);
ShaFreeMem(hDma);
ShaUnmapMem(hMem);
ShaUnregisterPort(hPort); 


