////////////////////////////////////////////////////////////////////// // File: edgar2_lib.c // // Library for accessing the EDgAR-2 card. // The code was generated by WinDriver Wizard. // It accesses the hardware via WinDriver functions. // ////////////////////////////////////////////////////////////////////// #include "edgar2_lib.h" #include "windrvr_int_thread.h" #include // This string is set to an error message, if one occurs CHAR EDGAR2A_ErrorString[1024]; // Internal function used by EDGAR2A_Open() BOOL EDGAR2A_DetectCardElements(EDGAR2A_HANDLE hEDGAR2A); DWORD EDGAR2A_CountCards (DWORD dwVendorID, DWORD dwDeviceID) { WD_VERSION ver; WD_PCI_SCAN_CARDS pciScan; HANDLE hWD; EDGAR2A_ErrorString[0] = '\0'; hWD = WD_Open(); // Check if handle valid & version OK if (hWD==INVALID_HANDLE_VALUE) { sprintf( EDGAR2A_ErrorString, "Cannot open WinDriver device\n"); return 0; } BZERO(ver); WD_Version(hWD,&ver); if (ver.dwVercardReg.hCard = 0; hEDGAR2A->hWD = WD_Open(); // Check if handle valid & version OK if (hEDGAR2A->hWD==INVALID_HANDLE_VALUE) { sprintf( EDGAR2A_ErrorString, "Cannot open WinDriver device\n"); goto Exit; } BZERO(ver); WD_Version(hEDGAR2A->hWD,&ver); if (ver.dwVerhWD, &pciScan); if (pciScan.dwCards==0) // Found at least one card { sprintf( EDGAR2A_ErrorString, "error - Cannot find PCI card\n"); goto Exit; } if (pciScan.dwCards<=nCardNum) { sprintf( EDGAR2A_ErrorString, "Card out of range of available cards\n"); goto Exit; } BZERO(pciCardInfo); pciCardInfo.pciSlot = pciScan.cardSlot[nCardNum]; WD_PciGetCardInfo (hEDGAR2A->hWD, &pciCardInfo); hEDGAR2A->pciSlot = pciCardInfo.pciSlot; hEDGAR2A->cardReg.Card = pciCardInfo.Card; hEDGAR2A->fUseInt = (options & EDGAR2A_OPEN_USE_INT) ? TRUE : FALSE; if (!hEDGAR2A->fUseInt) { DWORD i; // Remove interrupt item if not needed for (i=0; icardReg.Card.dwItems; i++) { WD_ITEMS *pItem = &hEDGAR2A->cardReg.Card.Item[i]; if (pItem->item==ITEM_INTERRUPT) pItem->item = ITEM_NONE; } } else { DWORD i; // Make interrupt resource sharable for (i=0; icardReg.Card.dwItems; i++) { WD_ITEMS *pItem = &hEDGAR2A->cardReg.Card.Item[i]; if (pItem->item==ITEM_INTERRUPT) pItem->fNotSharable = FALSE; } } hEDGAR2A->cardReg.fCheckLockOnly = FALSE; WD_CardRegister (hEDGAR2A->hWD, &hEDGAR2A->cardReg); if (hEDGAR2A->cardReg.hCard==0) { sprintf ( EDGAR2A_ErrorString, "error: could not lock device, already in use\n"); goto Exit; } if (!EDGAR2A_DetectCardElements(hEDGAR2A)) { sprintf ( EDGAR2A_ErrorString, "error: card does not have all items expected for EDgAR-2\n"); goto Exit; } // Open finished OK *phEDGAR2A = hEDGAR2A; return TRUE; Exit: // Error during Open if (hEDGAR2A->cardReg.hCard) WD_CardUnregister(hEDGAR2A->hWD, &hEDGAR2A->cardReg); if (hEDGAR2A->hWD!=INVALID_HANDLE_VALUE) WD_Close(hEDGAR2A->hWD); free (hEDGAR2A); return FALSE; } void EDGAR2A_Close(EDGAR2A_HANDLE hEDGAR2A) { // Disable interrupts if (EDGAR2A_IntIsEnabled(hEDGAR2A)) EDGAR2A_IntDisable(hEDGAR2A); // Unregister card if (hEDGAR2A->cardReg.hCard) WD_CardUnregister(hEDGAR2A->hWD, &hEDGAR2A->cardReg); // Close WinDriver WD_Close(hEDGAR2A->hWD); free (hEDGAR2A); } void EDGAR2A_WritePCIReg(EDGAR2A_HANDLE hEDGAR2A,DWORD dwReg,DWORD dwData) { WD_PCI_CONFIG_DUMP pciCnf; BZERO(pciCnf); pciCnf.pciSlot = hEDGAR2A->pciSlot; pciCnf.pBuffer = &dwData; pciCnf.dwOffset = dwReg; pciCnf.dwBytes = 4; pciCnf.fIsRead = FALSE; WD_PciConfigDump(hEDGAR2A->hWD,&pciCnf); } DWORD EDGAR2A_ReadPCIReg(EDGAR2A_HANDLE hEDGAR2A, DWORD dwReg) { WD_PCI_CONFIG_DUMP pciCnf; DWORD dwVal; BZERO(pciCnf); pciCnf.pciSlot = hEDGAR2A->pciSlot; pciCnf.pBuffer = &dwVal; pciCnf.dwOffset = dwReg; pciCnf.dwBytes = 4; pciCnf.fIsRead = TRUE; WD_PciConfigDump(hEDGAR2A->hWD,&pciCnf); return dwVal; } BOOL EDGAR2A_DetectCardElements(EDGAR2A_HANDLE hEDGAR2A) { DWORD i; DWORD ad_sp; BZERO(hEDGAR2A->Int); BZERO(hEDGAR2A->addrDesc); for (i=0; icardReg.Card.dwItems; i++) { WD_ITEMS *pItem = &hEDGAR2A->cardReg.Card.Item[i]; switch (pItem->item) { case ITEM_MEMORY: case ITEM_IO: { DWORD dwBytes; DWORD dwPhysAddr; BOOL fIsMemory; if (pItem->item==ITEM_MEMORY) { dwBytes = pItem->I.Mem.dwBytes; dwPhysAddr = pItem->I.Mem.dwPhysicalAddr; fIsMemory = TRUE; } else { dwBytes = pItem->I.IO.dwBytes; dwPhysAddr = pItem->I.IO.dwAddr; fIsMemory = FALSE; } for (ad_sp=0; ad_spaddrDesc[ad_sp].fActive = TRUE; hEDGAR2A->addrDesc[ad_sp].index = i; hEDGAR2A->addrDesc[ad_sp].fIsMemory = fIsMemory; hEDGAR2A->addrDesc[ad_sp].dwMask = 0; for (j=1; jaddrDesc[ad_sp].dwMask = (hEDGAR2A->addrDesc[ad_sp].dwMask << 1) | 1; } } } break; case ITEM_INTERRUPT: if (hEDGAR2A->Int.Int.hInterrupt) return FALSE; hEDGAR2A->Int.Int.hInterrupt = pItem->I.Int.hInterrupt; break; } } // Check that all the items needed were found // Check if interrupt found if (hEDGAR2A->fUseInt && !hEDGAR2A->Int.Int.hInterrupt) { return FALSE; } // Check that at least one memory space was found for (i = 0; iaddrDesc[addrSpace].fActive; } // General read/write function void EDGAR2A_ReadWriteBlock(EDGAR2A_HANDLE hEDGAR2A, EDGAR2A_ADDR addrSpace, DWORD dwOffset, BOOL fRead, PVOID buf, DWORD dwBytes, EDGAR2A_MODE mode) { WD_TRANSFER trans; BOOL fMem = hEDGAR2A->addrDesc[addrSpace].fIsMemory; // Safety check: is the address range active if (!EDGAR2A_IsAddrSpaceActive(hEDGAR2A, addrSpace)) return; BZERO(trans); if (fRead) { if (mode==EDGAR2A_MODE_BYTE) trans.cmdTrans = fMem ? RM_SBYTE : RP_SBYTE; else if (mode==EDGAR2A_MODE_WORD) trans.cmdTrans = fMem ? RM_SWORD : RP_SWORD; else if (mode==EDGAR2A_MODE_DWORD) trans.cmdTrans = fMem ? RM_SDWORD : RP_SDWORD; } else { if (mode==EDGAR2A_MODE_BYTE) trans.cmdTrans = fMem ? WM_SBYTE : WP_SBYTE; else if (mode==EDGAR2A_MODE_WORD) trans.cmdTrans = fMem ? WM_SWORD : WP_SWORD; else if (mode==EDGAR2A_MODE_DWORD) trans.cmdTrans = fMem ? WM_SDWORD : WP_SDWORD; } if (fMem) trans.dwPort = hEDGAR2A->cardReg.Card.Item[hEDGAR2A->addrDesc[addrSpace].index].I.Mem.dwTransAddr; else trans.dwPort = hEDGAR2A->cardReg.Card.Item[hEDGAR2A->addrDesc[addrSpace].index].I.IO.dwAddr; trans.dwPort += dwOffset; trans.fAutoinc = TRUE; trans.dwBytes = dwBytes; trans.dwOptions = 0; trans.Data.pBuffer = buf; WD_Transfer (hEDGAR2A->hWD, &trans); } BYTE EDGAR2A_ReadByte (EDGAR2A_HANDLE hEDGAR2A, EDGAR2A_ADDR addrSpace, DWORD dwOffset) { BYTE data; if (hEDGAR2A->addrDesc[addrSpace].fIsMemory) { PBYTE pData = (PBYTE) (hEDGAR2A->cardReg.Card.Item[hEDGAR2A->addrDesc[addrSpace].index].I.Mem.dwUserDirectAddr + dwOffset); data = *pData; // Read from the memory mapped range directly } else EDGAR2A_ReadWriteBlock( hEDGAR2A, addrSpace, dwOffset, TRUE, &data, sizeof (BYTE), EDGAR2A_MODE_BYTE); return data; } WORD EDGAR2A_ReadWord (EDGAR2A_HANDLE hEDGAR2A, EDGAR2A_ADDR addrSpace, DWORD dwOffset) { WORD data; if (hEDGAR2A->addrDesc[addrSpace].fIsMemory) { PWORD pData = (PWORD) (hEDGAR2A->cardReg.Card.Item[hEDGAR2A->addrDesc[addrSpace].index].I.Mem.dwUserDirectAddr + dwOffset); data = *pData; // Read from the memory mapped range directly } else EDGAR2A_ReadWriteBlock( hEDGAR2A, addrSpace, dwOffset, TRUE, &data, sizeof (WORD), EDGAR2A_MODE_WORD); return data; } DWORD EDGAR2A_ReadDword (EDGAR2A_HANDLE hEDGAR2A, EDGAR2A_ADDR addrSpace, DWORD dwOffset) { DWORD data; if (hEDGAR2A->addrDesc[addrSpace].fIsMemory) { PDWORD pData = (PDWORD) (hEDGAR2A->cardReg.Card.Item[hEDGAR2A->addrDesc[addrSpace].index].I.Mem.dwUserDirectAddr + dwOffset); data = *pData; // Read from the memory mapped range directly } else EDGAR2A_ReadWriteBlock( hEDGAR2A, addrSpace, dwOffset, TRUE, &data, sizeof (DWORD), EDGAR2A_MODE_DWORD); return data; } void EDGAR2A_WriteByte (EDGAR2A_HANDLE hEDGAR2A, EDGAR2A_ADDR addrSpace, DWORD dwOffset, BYTE data) { if (hEDGAR2A->addrDesc[addrSpace].fIsMemory) { PBYTE pData = (PBYTE) (hEDGAR2A->cardReg.Card.Item[hEDGAR2A->addrDesc[addrSpace].index].I.Mem.dwUserDirectAddr + dwOffset); *pData = data; // Write to the memory mapped range directly } else EDGAR2A_ReadWriteBlock( hEDGAR2A, addrSpace, dwOffset, FALSE, &data, sizeof (BYTE), EDGAR2A_MODE_BYTE); } void EDGAR2A_WriteWord (EDGAR2A_HANDLE hEDGAR2A, EDGAR2A_ADDR addrSpace, DWORD dwOffset, WORD data) { if (hEDGAR2A->addrDesc[addrSpace].fIsMemory) { PWORD pData = (PWORD) (hEDGAR2A->cardReg.Card.Item[hEDGAR2A->addrDesc[addrSpace].index].I.Mem.dwUserDirectAddr + dwOffset); *pData = data; // Write to the memory mapped range directly } else EDGAR2A_ReadWriteBlock( hEDGAR2A, addrSpace, dwOffset, FALSE, &data, sizeof (WORD), EDGAR2A_MODE_WORD); } void EDGAR2A_WriteDword (EDGAR2A_HANDLE hEDGAR2A, EDGAR2A_ADDR addrSpace, DWORD dwOffset, DWORD data) { if (hEDGAR2A->addrDesc[addrSpace].fIsMemory) { PDWORD pData = (PDWORD) (hEDGAR2A->cardReg.Card.Item[hEDGAR2A->addrDesc[addrSpace].index].I.Mem.dwUserDirectAddr + dwOffset); *pData = data; // Write to the memory mapped range directly } else EDGAR2A_ReadWriteBlock( hEDGAR2A, addrSpace, dwOffset, FALSE, &data, sizeof (DWORD), EDGAR2A_MODE_DWORD); } DWORD EDGAR2A_ReadDONE (EDGAR2A_HANDLE hEDGAR2A) { return EDGAR2A_ReadDword(hEDGAR2A, EDGAR2A_DONE_SPACE, EDGAR2A_DONE_OFFSET); } void EDGAR2A_WritenotProgramFpga (EDGAR2A_HANDLE hEDGAR2A, DWORD data) { EDGAR2A_WriteDword(hEDGAR2A, EDGAR2A_notProgramFpga_SPACE, EDGAR2A_notProgramFpga_OFFSET, data); } DWORD EDGAR2A_ReadnotINIT (EDGAR2A_HANDLE hEDGAR2A) { return EDGAR2A_ReadDword(hEDGAR2A, EDGAR2A_notINIT_SPACE, EDGAR2A_notINIT_OFFSET); } DWORD EDGAR2A_ReadfpgaRdyNotBusy (EDGAR2A_HANDLE hEDGAR2A) { return EDGAR2A_ReadDword(hEDGAR2A, EDGAR2A_fpgaRdyNotBusy_SPACE, EDGAR2A_fpgaRdyNotBusy_OFFSET); } void EDGAR2A_WriteinterruptRequest (EDGAR2A_HANDLE hEDGAR2A, DWORD data) { EDGAR2A_WriteDword(hEDGAR2A, EDGAR2A_interruptRequest_SPACE, EDGAR2A_interruptRequest_OFFSET, data); } void EDGAR2A_Writecfg_1 (EDGAR2A_HANDLE hEDGAR2A, DWORD data) { EDGAR2A_WriteDword(hEDGAR2A, EDGAR2A_cfg_1_SPACE, EDGAR2A_cfg_1_OFFSET, data); } void EDGAR2A_Writecfg_0 (EDGAR2A_HANDLE hEDGAR2A, DWORD data) { EDGAR2A_WriteDword(hEDGAR2A, EDGAR2A_cfg_0_SPACE, EDGAR2A_cfg_0_OFFSET, data); } void EDGAR2A_Writecfg_2 (EDGAR2A_HANDLE hEDGAR2A, DWORD data) { EDGAR2A_WriteDword(hEDGAR2A, EDGAR2A_cfg_2_SPACE, EDGAR2A_cfg_2_OFFSET, data); } void EDGAR2A_Writecfg_3 (EDGAR2A_HANDLE hEDGAR2A, DWORD data) { EDGAR2A_WriteDword(hEDGAR2A, EDGAR2A_cfg_3_SPACE, EDGAR2A_cfg_3_OFFSET, data); } void EDGAR2A_Writecfg_1_0 (EDGAR2A_HANDLE hEDGAR2A, DWORD data) { EDGAR2A_WriteDword(hEDGAR2A, EDGAR2A_cfg_1_0_SPACE, EDGAR2A_cfg_1_0_OFFSET, data); } void EDGAR2A_Writecfg_2_0 (EDGAR2A_HANDLE hEDGAR2A, DWORD data) { EDGAR2A_WriteDword(hEDGAR2A, EDGAR2A_cfg_2_0_SPACE, EDGAR2A_cfg_2_0_OFFSET, data); } void EDGAR2A_Writecfg_3_0 (EDGAR2A_HANDLE hEDGAR2A, DWORD data) { EDGAR2A_WriteDword(hEDGAR2A, EDGAR2A_cfg_3_0_SPACE, EDGAR2A_cfg_3_0_OFFSET, data); } void EDGAR2A_Writecfg_3_1 (EDGAR2A_HANDLE hEDGAR2A, DWORD data) { EDGAR2A_WriteDword(hEDGAR2A, EDGAR2A_cfg_3_1_SPACE, EDGAR2A_cfg_3_1_OFFSET, data); } void EDGAR2A_Writecfg_3_2 (EDGAR2A_HANDLE hEDGAR2A, DWORD data) { EDGAR2A_WriteDword(hEDGAR2A, EDGAR2A_cfg_3_2_SPACE, EDGAR2A_cfg_3_2_OFFSET, data); } void EDGAR2A_Writecfg_2_1_0 (EDGAR2A_HANDLE hEDGAR2A, DWORD data) { EDGAR2A_WriteDword(hEDGAR2A, EDGAR2A_cfg_2_1_0_SPACE, EDGAR2A_cfg_2_1_0_OFFSET, data); } void EDGAR2A_Writecfg_3_2_0 (EDGAR2A_HANDLE hEDGAR2A, DWORD data) { EDGAR2A_WriteDword(hEDGAR2A, EDGAR2A_cfg_3_2_0_SPACE, EDGAR2A_cfg_3_2_0_OFFSET, data); } void EDGAR2A_Writecfg_3_2_1 (EDGAR2A_HANDLE hEDGAR2A, DWORD data) { EDGAR2A_WriteDword(hEDGAR2A, EDGAR2A_cfg_3_2_1_SPACE, EDGAR2A_cfg_3_2_1_OFFSET, data); } void EDGAR2A_Writecfg_3_2_1_0 (EDGAR2A_HANDLE hEDGAR2A, DWORD data) { EDGAR2A_WriteDword(hEDGAR2A, EDGAR2A_cfg_3_2_1_0_SPACE, EDGAR2A_cfg_3_2_1_0_OFFSET, data); } void EDGAR2A_Writecfg_3_1_0 (EDGAR2A_HANDLE hEDGAR2A, DWORD data) { EDGAR2A_WriteDword(hEDGAR2A, EDGAR2A_cfg_3_1_0_SPACE, EDGAR2A_cfg_3_1_0_OFFSET, data); } void EDGAR2A_Writecfg_2_1 (EDGAR2A_HANDLE hEDGAR2A, DWORD data) { EDGAR2A_WriteDword(hEDGAR2A, EDGAR2A_cfg_2_1_SPACE, EDGAR2A_cfg_2_1_OFFSET, data); } void EDGAR2A_WriteenablePciCtlSignals (EDGAR2A_HANDLE hEDGAR2A,DWORD data) { EDGAR2A_WriteDword(hEDGAR2A, EDGAR2A_enablePciCtlSignals_SPACE, EDGAR2A_enablePciCtlSignals_OFFSET, data); } void EDGAR2A_WriteprogramJtagChain (EDGAR2A_HANDLE hEDGAR2A, DWORD data) { EDGAR2A_WriteDword(hEDGAR2A, EDGAR2A_programJtagChain_SPACE, EDGAR2A_programJtagChain_OFFSET, data); } void EDGAR2A_WriteSCLOCK (EDGAR2A_HANDLE hEDGAR2A, DWORD data) { EDGAR2A_WriteDword(hEDGAR2A, EDGAR2A_SCLOCK_SPACE, EDGAR2A_SCLOCK_OFFSET, data); } BOOL EDGAR2A_IntIsEnabled (EDGAR2A_HANDLE hEDGAR2A) { if (!hEDGAR2A->fUseInt) return FALSE; if (!hEDGAR2A->Int.hThread) return FALSE; return TRUE; } VOID EDGAR2A_IntHandler (PVOID pData) { EDGAR2A_HANDLE hEDGAR2A = (EDGAR2A_HANDLE) pData; EDGAR2A_INT_RESULT intResult; intResult.dwCounter = hEDGAR2A->Int.Int.dwCounter; intResult.dwLost = hEDGAR2A->Int.Int.dwLost; intResult.fStopped = hEDGAR2A->Int.Int.fStopped; hEDGAR2A->Int.funcIntHandler(hEDGAR2A, &intResult); } BOOL EDGAR2A_IntEnable (EDGAR2A_HANDLE hEDGAR2A, EDGAR2A_INT_HANDLER funcIntHandler) { EDGAR2A_ADDR addrSpace; if (!hEDGAR2A->fUseInt) return FALSE; // Check if interrupt is already enabled if (hEDGAR2A->Int.hThread) return FALSE; BZERO(hEDGAR2A->Int.Trans); // One transfer commands is issued to CANCEL the source of the interrupt, // otherwise, the PC will hang when an interrupt occurs! addrSpace = EDGAR2A_interruptRequest_SPACE; if (hEDGAR2A->addrDesc[addrSpace].fIsMemory) { hEDGAR2A->Int.Trans[0].dwPort = hEDGAR2A->cardReg.Card.Item[hEDGAR2A->addrDesc[addrSpace].index].I.Mem.dwTransAddr; hEDGAR2A->Int.Trans[0].cmdTrans = WM_DWORD; } else { hEDGAR2A->Int.Trans[0].dwPort = hEDGAR2A->cardReg.Card.Item[hEDGAR2A->addrDesc[addrSpace].index].I.IO.dwAddr; hEDGAR2A->Int.Trans[0].cmdTrans = WP_DWORD; } hEDGAR2A->Int.Trans[0].dwPort += EDGAR2A_interruptRequest_OFFSET; hEDGAR2A->Int.Trans[0].Data.Dword = 0x80; hEDGAR2A->Int.Int.dwCmds = 1; hEDGAR2A->Int.Int.Cmd = hEDGAR2A->Int.Trans; hEDGAR2A->Int.Int.dwOptions |= INTERRUPT_CMD_COPY; // This calls WD_IntEnable() and creates an interrupt handler thread hEDGAR2A->Int.funcIntHandler = funcIntHandler; if (!InterruptThreadEnable(&hEDGAR2A->Int.hThread, hEDGAR2A->hWD, &hEDGAR2A->Int.Int, EDGAR2A_IntHandler, (PVOID) hEDGAR2A)) return FALSE; return TRUE; } void EDGAR2A_IntDisable (EDGAR2A_HANDLE hEDGAR2A) { if (!hEDGAR2A->fUseInt) return; if (!hEDGAR2A->Int.hThread) return; // This calls WD_IntDisable() InterruptThreadDisable(hEDGAR2A->Int.hThread); hEDGAR2A->Int.hThread = NULL; }