////////////////////////////////////////////////////////////////////// // File - sli6_lib.cpp // // Library for accessing the SLI6 card, version 1.10. // Code was composed by Kirill Bezmaternykh // INP, lab 6-1 (ppi6@gorodok.net) // It accesses the hardware via WinDriver functions. // ////////////////////////////////////////////////////////////////////// #include "sli6_lib.h" #include "sli6_ext.h" #include "windrvr_int_thread.h" #include #ifndef __KERNEL__ #include #endif #ifdef __cplusplus extern "C" { #endif // internal data structures typedef struct { WD_INTERRUPT Int; HANDLE hThread; WD_TRANSFER Trans[1]; SLI6_INT_HANDLER funcIntHandler; } SLI6_INT_INTERRUPT; typedef struct { DWORD index; DWORD dwMask; BOOL fIsMemory; BOOL fActive; } SLI6_ADDR_DESC; typedef struct SLI6_STRUCT { HANDLE hWD; BOOL fUseInt; SLI6_INT_INTERRUPT Int; WD_PCI_SLOT pciSlot; SLI6_ADDR_DESC addrDesc[SLI6_ITEMS]; WD_CARD_REGISTER cardReg; } SLI6_STRUCT; ///////////////////////////////////////////////////// SLI6_HANDLE Cards[MAX_CARDS-MIN_CARDS+1]; // "ручка" для карточки char SLI6_ErrorString[1024]; // this string is set to an error message, if one occurs unsigned short Crates[MAX_CARDS-MIN_CARDS+1][MAX_CRATES-MIN_CRATES+1]; // количесвто открваний канала INTLAMFUNC intf[MAX_CARDS-MIN_CARDS+1][MAX_CRATES-MIN_CRATES+1]; PVOID param[MAX_CARDS-MIN_CARDS+1][MAX_CRATES-MIN_CRATES+1]; HANDLE int_rut[MAX_CARDS-MIN_CARDS+1]; void Sli6IntHandler( SLI6_HANDLE hSLI6, SLI6_INT_RESULT *intResult); /////////////////////////////////////////////////////// int __stdcall OpenCard(unsigned int CardN, BOOL use_int) { DWORD cards; //////////////////// проверка параметров //////////////////////////////////////// if(!( (MIN_CARDS <= CardN)&&(CardN <= MAX_CARDS) )) { sprintf(SLI6_ErrorString,"Wrong parametrs!"); return SLI6_ERROR; } ///////////////////////////////////////////////////////////////////////////////// CardN -= MIN_CARDS; cards = SLI6_CountCards (SLI6_DEFAULT_VENDOR_ID, SLI6_DEFAULT_DEVICE_ID); if ((cards == 0) || (cards <= CardN)) { return SLI6_ERROR; // ошибка - нет карточек вообще // либо указана несуществуюющая карточка } if(use_int) { if (SLI6_Open (Cards+CardN, SLI6_DEFAULT_VENDOR_ID, SLI6_DEFAULT_DEVICE_ID, CardN, SLI6_OPEN_USE_INT)) { if( (int_rut[CardN] = CreateMutex(NULL, // no security attributes FALSE, // initially not owned NULL) ) == NULL) // without a name { sprintf(SLI6_ErrorString,"Can't create mutex!"); return SLI6_ERROR; // Check for error. } SLI6_WriteWord (Cards[CardN], SLI6_AD_BAR0, INT_GENABLE, 0x1); SLI6_WriteWord (Cards[CardN], SLI6_AD_BAR0, INT_ENABLE, 0x0); return SLI6_OK; }else{ Cards[CardN] = NULL; return SLI6_ERROR; //ошибка нет больше карт } }else { if (SLI6_Open (Cards+CardN, SLI6_DEFAULT_VENDOR_ID, SLI6_DEFAULT_DEVICE_ID, CardN, 0x0)) { SLI6_WriteWord (Cards[CardN], SLI6_AD_BAR0, INT_GENABLE, 0x0); SLI6_WriteWord (Cards[CardN], SLI6_AD_BAR0, INT_ENABLE, 0x0); return SLI6_OK; }else{ Cards[CardN] = NULL; return SLI6_ERROR; //ошибка нет больше карт } } } int __stdcall CloseCard(unsigned int CardN) { if( (MIN_CARDS <= CardN) && (CardN <= MAX_CARDS) && (Cards[CardN-MIN_CARDS] != NULL)) { CardN -= MIN_CARDS; SLI6_Close(Cards[CardN]); Cards[CardN] = NULL; if( int_rut[CardN] != NULL ) { CloseHandle(int_rut[CardN]); int_rut[CardN] = NULL; } return SLI6_OK; } sprintf(SLI6_ErrorString,"Wrong parametrs!"); return SLI6_ERROR; } int __stdcall OpenCrate(unsigned int CardN,unsigned int CrateN) { WORD ifexist; //////////////// допустимость параметров ////////////////////////// if(!( ((MIN_CARDS <= CardN)&&(CardN <= MAX_CARDS))&& ((MIN_CRATES <= CrateN)&&(CrateN <= MAX_CRATES)) ) ) { sprintf(SLI6_ErrorString,"Wrong parameters!"); return SLI6_ERROR; } CardN -= MIN_CARDS; CrateN -= MIN_CRATES; //////////////// проверяем открыта ли такая карточка ////////////// if(Cards[CardN] == NULL) { // карточка закрыта - открываем if(OpenCard(CardN + MIN_CARDS,0) == SLI6_ERROR) return SLI6_ERROR;// отрываем без прерываний, если что переоткроется! } //////////////// проверяем физическое наличие канала ///////////// ifexist = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, EXIST); if( (ifexist >> CrateN)&1L == 0) { CloseCard(CardN + MIN_CARDS); sprintf(SLI6_ErrorString,"Channel doesn't physically exist!"); return SLI6_ERROR; } //////////////// увеличиывем счетчик канала ////////////// if( ++Crates[CardN][CrateN] == 0) { sprintf(SLI6_ErrorString,"Channel opened too many times!"); Crates[CardN][CrateN] = 255; return SLI6_ERROR; } ////////////////////////////////////////////////////////////////// CardN += MIN_CARDS; CrateN += MIN_CRATES; return (int)( (CardN << 16) | CrateN ); // CN = ID канала } int __stdcall CloseCrate(int CN) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16); if(!( ((MIN_CARDS <= CardN)&&(CardN <= MAX_CARDS))&& ((MIN_CRATES <= CrateN)&&(CrateN <= MAX_CRATES)) ) ) { sprintf(SLI6_ErrorString,"Wrong parameters!"); return SLI6_ERROR; } CardN -= MIN_CARDS; CrateN -= MIN_CRATES; if( --Crates[CardN][CrateN] == 255) { sprintf(SLI6_ErrorString,"Crate hasn't been opened!"); Crates[CardN][CrateN] = 0; return SLI6_ERROR; } unsigned int sum = 0; for(unsigned short c = 0; c < MAX_CRATES; c++) sum += Crates[CardN][c]; if(sum == 0) // если нету больше открытых каналов CloseCard(CardN + MIN_CARDS);// закрываем карточку return 0; } WORD __stdcall cam16(int CN, int posN, int A, int F, WORD *data) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16); DWORD dwOffset; WORD busy,status; CardN -= MIN_CARDS; CrateN -= MIN_CRATES; /////////////// подготовка /////////////////////////////////////////// dwOffset = BASE | (1L << (CrateN + 13)) | (0x1000) | (posN << 6) | (A << 2); ////////////// запись функции в контроллер /////////////////////////// SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, CAM_STATUS | (1L << (CrateN+13)) ); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); status = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, DATA_WOUT_INIT | (1L << (CrateN+13))); status = status & (~(0x1F)) | F ; SLI6_WriteWord (Cards[CardN], SLI6_AD_BAR0, CAM_STATUS | (1L << (CrateN+13)), status); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); //////////////// сама операция :)/////////////////////////////////////////// if(F < 16) // чтение { SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, dwOffset); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); (*data) = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, DATA_WOUT_INIT | (1L << (CrateN+13)) ); status = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BASE | (1L << (CrateN+13))); } else{ // запись // запуск цикла SLI6_WriteWord(Cards[CardN], SLI6_AD_BAR0, dwOffset, *data); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); status = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BASE | (1L << (CrateN+13))); } //////////////////////////////////////////////////////////////////// return status; // возвращаем LXQToEr - STATUS } WORD __stdcall cam16write(int CN, int posN, int A, WORD *data) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16); DWORD dwOffset; WORD busy,status; CardN -= MIN_CARDS; CrateN -= MIN_CRATES; /////////////// подготовка /////////////////////////////////////////// dwOffset = BASE | (1L << (CrateN + 13)) | (0x1000) | (posN << 6) | (A << 2); //////////////// сама операция :)/////////////////////////////////////////// // запуск цикла SLI6_WriteWord(Cards[CardN], SLI6_AD_BAR0, dwOffset, *data); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); status = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BASE | (1L << (CrateN+13))); //////////////////////////////////////////////////////////////////// return status; // возвращаем LXQToEr - STATUS } WORD __stdcall cam16read(int CN, int posN, int A, WORD *data) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16); DWORD dwOffset; WORD busy,status; CardN -= MIN_CARDS; CrateN -= MIN_CRATES; /////////////// подготовка /////////////////////////////////////////// dwOffset = BASE | (1L << (CrateN + 13)) | (0x1000) | (posN << 6) | (A << 2); //////////////// сама операция :)/////////////////////////////////////////// // запуск цикла SLI6_ReadDword (Cards[CardN], SLI6_AD_BAR0, dwOffset); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); (*data) = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, DATA_WOUT_INIT | (1L << (CrateN+13)) ); status = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BASE | (1L << (CrateN+13))); //////////////////////////////////////////////////////////////////// return status; // возвращаем LXQToEr - STATUS } WORD __stdcall cam24write(int CN, int posN, int A, DWORD *data) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16); DWORD dwOffset; WORD busy,status; CardN -= MIN_CARDS; CrateN -= MIN_CRATES; /////////////// подготовка /////////////////////////////////////////// dwOffset = BASE | (1L << (CrateN + 13)) | (0x1000) | (posN << 6) | (A << 2); //////////////// камак цикл /////////////////////////////////////////// // старшие 8 бит //////////////////////////////////////////////// SLI6_WriteDword(Cards[CardN], SLI6_AD_BAR0, CAM_HBYTE | (1L << (CrateN+13)), ((*data) >> 16)); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); // младшие 16 бит ///////////////////////////////////////////////// SLI6_WriteDword(Cards[CardN], SLI6_AD_BAR0, dwOffset, *data); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); status = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, STATUS | (1L << (CrateN+13))); ////////////////////////////////////////////////////////////////// return status; // возвращаем LXQToEr - STATUS } WORD __stdcall cam24read(int CN, int posN, int A, DWORD *data) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16); DWORD dwOffset; WORD busy,status; CardN -= MIN_CARDS; CrateN -= MIN_CRATES; /////////////// подготовка /////////////////////////////////////////// dwOffset = BASE | (1L << (CrateN + 13)) | (0x1000) | (posN << 6) | (A << 2); //////////////// камак цикл /////////////////////////////////////////// // младшие 16 бит //////////////////////////////////////////////// // запуск цикла SLI6_ReadDword (Cards[CardN], SLI6_AD_BAR0, dwOffset); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); (*data) = SLI6_ReadDword (Cards[CardN], SLI6_AD_BAR0, DATA_WOUT_INIT | (1L << (CrateN+13)) ); status = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BASE | (1L << (CrateN+13)) ); // старшие 8 бит ///////////////////////////////////////////////// // запуск цикла SLI6_ReadDword (Cards[CardN], SLI6_AD_BAR0, CAM_HBYTE | (1L << (CrateN+13)) ); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); (*data) |= ( (SLI6_ReadDword (Cards[CardN], SLI6_AD_BAR0, DATA_WOUT_INIT | (1L << (CrateN+13)) ) << 8) &0xFF0000 ); ////////////////////////////////////////////////////////////////// return status; // возвращаем LXQToEr - STATUS } WORD __stdcall cam24(int CN, int posN, int A, int F, DWORD *data) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16); DWORD dwOffset; WORD busy,status; CardN -= MIN_CARDS; CrateN -= MIN_CRATES; /////////////// подготовка /////////////////////////////////////////// dwOffset = BASE | (1L << (CrateN + 13)) | (0x1000) | (posN << 6) | (A << 2); ////////////// запись функции в контроллер /////////////////////////// SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, CAM_STATUS | (1L << (CrateN+13)) ); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); status = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, DATA_WOUT_INIT | (1L << (CrateN+13))); status = status & (~(0x1F)) | F ; SLI6_WriteWord (Cards[CardN], SLI6_AD_BAR0, CAM_STATUS | (1L << (CrateN+13)), status); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); //////////////// камак цикл /////////////////////////////////////////// if(F < 16) // чтение { // младшие 16 бит //////////////////////////////////////////////// // запуск цикла SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, dwOffset); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); (*data) = SLI6_ReadDword (Cards[CardN], SLI6_AD_BAR0, DATA_WOUT_INIT | (1L << (CrateN+13)) ); status = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BASE | (1L << (CrateN+13)) ); // старшие 8 бит ///////////////////////////////////////////////// // запуск цикла SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, CAM_HBYTE | (1L << (CrateN+13)) ); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); (*data) |= ( (SLI6_ReadDword (Cards[CardN], SLI6_AD_BAR0, DATA_WOUT_INIT | (1L << (CrateN+13)) ) << 16) &0xFF0000 ); ////////////////////////////////////////////////////////////////// } else{ // запись // старшие 8 бит //////////////////////////////////////////////// // запуск цикла SLI6_WriteDword(Cards[CardN], SLI6_AD_BAR0, CAM_HBYTE | (1L << (CrateN+13)), ((*data) >> 16)); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); // младшие 16 бит ///////////////////////////////////////////////// SLI6_WriteDword(Cards[CardN], SLI6_AD_BAR0, dwOffset, *data); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); status = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, STATUS | (1L << (CrateN+13))); ////////////////////////////////////////////////////////////////// } return status; // возвращаем LXQToEr - STATUS } WORD __stdcall cam24Block(int CN, int posN, int A, int F, unsigned int Nblock, DWORD *data) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16); DWORD dwOffset; WORD busy,status; CardN -= MIN_CARDS; CrateN -= MIN_CRATES; /////////////// подготовка /////////////////////////////////////////// dwOffset = BASE | (1L << (CrateN + 13)) | (0x1000) | (posN << 6) | (A << 2); ////////////// запись функции в контроллер /////////////////////////// SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, CAM_STATUS | (1L << (CrateN+13)) ); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); status = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, DATA_WOUT_INIT | (1L << (CrateN+13)) )& (~(0x1F)); status |= F; SLI6_WriteWord (Cards[CardN], SLI6_AD_BAR0, CAM_STATUS | (1L << (CrateN+13)), status); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); //////////////// камак цикл /////////////////////////////////////////// if(F < 16) // чтение { for(unsigned long i=0; i < Nblock-1; i++) { // младшие 16 бит //////////////////////////////////////////////// // запуск цикла SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, dwOffset); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); (*data) = SLI6_ReadDword (Cards[CardN], SLI6_AD_BAR0, DATA_WOUT_INIT | (1L << (CrateN+13)) ); // старшие 8 бит ///////////////////////////////////////////////// // запуск цикла SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, CAM_HBYTE | (1L << (CrateN+13)) ); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); (*data++) |= ( (SLI6_ReadDword (Cards[CardN], SLI6_AD_BAR0, DATA_WOUT_INIT | (1L << (CrateN+13)) ) << 16) &0xFF0000 ); } ///////// поcледний цикл чтения /////////////////////////////////////// SLI6_ReadDword (Cards[CardN], SLI6_AD_BAR0, dwOffset); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); (*data) = SLI6_ReadDword (Cards[CardN], SLI6_AD_BAR0, DATA_WOUT_INIT | (1L << (CrateN+13)) ); status = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BASE | (1L << (CrateN+13))); // старшие 8 бит ///////////////////////////////////////////////// // запуск цикла SLI6_ReadDword (Cards[CardN], SLI6_AD_BAR0, CAM_HBYTE | (1L << (CrateN+13)) ); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); (*data) |= ( (SLI6_ReadDword (Cards[CardN], SLI6_AD_BAR0, DATA_WOUT_INIT | (1L << (CrateN+13)) ) << 16) &0xFF0000 ); ////////////////////////////////////////////////////////////////// } else{ // запись for(unsigned long i=0; i < Nblock; i++) { // старшие 8 бит //////////////////////////////////////////////// // запуск цикла SLI6_WriteWord(Cards[CardN], SLI6_AD_BAR0, CAM_HBYTE | (1L << (CrateN+13)), (WORD)((*data) >> 16)); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); // младшие 16 бит ///////////////////////////////////////////////// SLI6_WriteWord(Cards[CardN], SLI6_AD_BAR0, dwOffset, (WORD)(*(data++))); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); } status = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, STATUS | (1L << (CrateN+13))); ////////////////////////////////////////////////////////////////// } return status; // возвращаем XQErToAcXAcQAcErAcTo - STATUS // накопленный статус корявый! } WORD __stdcall cam16Block(int CN, int posN, int A, int F,unsigned long Nblock, WORD *data) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16); DWORD dwOffset; WORD busy,status; CardN -= MIN_CARDS; CrateN -= MIN_CRATES; /////////////// подготовка /////////////////////////////////////////// dwOffset = BASE | (1L << (CrateN + 13)) | (0x1000) | (posN << 6) | (A << 2); ////////////// запись функции в контроллер /////////////////////////// SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, CAM_STATUS | (1L << (CrateN+13)) ); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); status = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, DATA_WOUT_INIT | (1L << (CrateN+13)) )& (~(0x1F)); status |= F; SLI6_WriteWord (Cards[CardN], SLI6_AD_BAR0, CAM_STATUS | (1L << (CrateN+13)), status); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); //////////////// сама операция :)/////////////////////////////////////////// if(F < 16) // чтение { for(unsigned long i=0; i < Nblock; i++) { SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, dwOffset); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); (*data++) = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, DATA_WOUT_INIT | (1L << (CrateN+13)) ); } status = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BASE | (1L << (CrateN+13))); } else{ // запись // запуск цикла for(unsigned long i = 0; i < Nblock; i++) { SLI6_WriteWord(Cards[CardN], SLI6_AD_BAR0, dwOffset, *(data++)); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); } status = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BASE | (1L << (CrateN+13))); } /////////////////////////////////////////////////////////////////// return status; // возвращаем XQErToAcXAcQAcErAcTo - STATUS } WORD __stdcall camZ(int CN) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16); WORD busy,status; CardN -= MIN_CARDS; CrateN -= MIN_CRATES; //////////////// камак цикл /////////////////////////////////////////// // чтение статуса SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, CAM_STATUS | (1L << (CrateN+13)) ); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); status = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, DATA_WOUT_INIT | (1L << (CrateN+13)) ); // запуск цикла SLI6_WriteDword (Cards[CardN], SLI6_AD_BAR0, CAM_STATUS | (1L << (CrateN+13)),status|CAM_Z_BIT); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); // чтение статуса соответствующего канала status = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BASE | (1L << (CrateN+13)) ); ////////////////////////////////////////////////////////////////// return status; // возвращаем LXQToEr - STATUS } WORD __stdcall camC(int CN) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16); WORD busy,status; CardN -= MIN_CARDS; CrateN -= MIN_CRATES; //////////////// камак цикл /////////////////////////////////////////// // чтение статуса SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, CAM_STATUS | (1L << (CrateN+13)) ); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); status = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, DATA_WOUT_INIT | (1L << (CrateN+13)) ); // запуск цикла SLI6_WriteDword (Cards[CardN], SLI6_AD_BAR0, CAM_STATUS | (1L << (CrateN+13)),status|CAM_C_BIT); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); // чтение статуса соответствующего канала status = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BASE | (1L << (CrateN+13)) ); ////////////////////////////////////////////////////////////////// return status; // возвращаем LXQToEr - STATUS } WORD __stdcall cam16RW(int CN, int posN, int A, WORD *dataw,WORD *datar) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16); DWORD dwOffset; WORD busy,status; CardN -= MIN_CARDS; CrateN -= MIN_CRATES; /////////////// подготовка /////////////////////////////////////////// dwOffset = BASE | (1L << (CrateN + 13)) | (0x1000) | (posN << 6) | (A << 2); //////////////// сама операция :)/////////////////////////////////////////// // запись SLI6_WriteWord(Cards[CardN], SLI6_AD_BAR0, dwOffset, *dataw); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); status = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BASE | (1L << (CrateN+13))); // чтение SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, dwOffset); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); (*datar) = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, DATA_WOUT_INIT | (1L << (CrateN+13)) ); status |= ( SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BASE | (1L << (CrateN+13))) << 8 ); //////////////////////////////////////////////////////////////////// return status; // возвращаем LXQToEr - STATUS (страший байт - статус чтения, // младший - статус записи) } WORD __stdcall cam24RW(int CN, int posN, int A,DWORD *dataw, DWORD *datar) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16); DWORD dwOffset; WORD busy,status; CardN -= MIN_CARDS; CrateN -= MIN_CRATES; /////////////// подготовка /////////////////////////////////////////// dwOffset = BASE | (1L << (CrateN + 13)) | (0x1000) | (posN << 6) | (A << 2); //////////////// камак цикл /////////////////////////////////////////// // запись // старшие 8 бит //////////////////////////////////////////////// // запуск цикла SLI6_WriteDword(Cards[CardN], SLI6_AD_BAR0, CAM_HBYTE | (1L << (CrateN+13)), ((*dataw) >> 16)); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); // младшие 16 бит ///////////////////////////////////////////////// SLI6_WriteDword(Cards[CardN], SLI6_AD_BAR0, dwOffset, *dataw); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); status = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, STATUS | (1L << (CrateN+13))); ////////////////////////////////////////////////////////////////// // чтение // младшие 16 бит //////////////////////////////////////////////// // запуск цикла SLI6_ReadDword (Cards[CardN], SLI6_AD_BAR0, dwOffset); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); (*datar) = SLI6_ReadDword (Cards[CardN], SLI6_AD_BAR0, DATA_WOUT_INIT | (1L << (CrateN+13)) ); status |= ( SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BASE | (1L << (CrateN+13)) ) << 8 ); // старшие 8 бит ///////////////////////////////////////////////// // запуск цикла SLI6_ReadDword (Cards[CardN], SLI6_AD_BAR0, CAM_HBYTE | (1L << (CrateN+13)) ); do{ // ожидание конца цикла busy = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, BUSY); }while( ( (busy >> CrateN)&1L ) == 0L); (*datar) |= ( (SLI6_ReadDword (Cards[CardN], SLI6_AD_BAR0, DATA_WOUT_INIT | (1L << (CrateN+13)) ) << 8) &0xFF0000 ); ////////////////////////////////////////////////////////////////// return status; // возвращаем LXQToEr - STATUS (страший байт - статус чтения, // младший - статус записи) } int __stdcall ClearStatus(int CN) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16); CardN -= MIN_CARDS; CrateN -= MIN_CRATES; SLI6_WriteWord(Cards[CardN],SLI6_AD_BAR0,BASE | (1L << (CrateN+13)), 0x0); return SLI6_OK; } int __stdcall GetChannels(unsigned int CardN) { WORD exist; int n=0; //////////////// допустимость параметров ////////////////////////// if(!( (MIN_CARDS <= CardN) && (CardN <= MAX_CARDS) ) ) { sprintf(SLI6_ErrorString,"Wrong parametrs!"); return SLI6_ERROR; } CardN -= MIN_CARDS; //////////////// проверяем открыта ли такая карточка ////////////// if(Cards[CardN] == NULL) { if(OpenCard(CardN + MIN_CARDS,0) != SLI6_OK) return SLI6_ERROR; exist = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, EXIST); while((exist >> n++)&1L){;} CloseCard(CardN + MIN_CARDS); return n-1; } else{ exist = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, EXIST); while((exist >> n++)&1L){;} return n-1; } } /////////////// прерывания ///////////////////////////////////////////// void Sli6IntHandler( SLI6_HANDLE hSLI6, SLI6_INT_RESULT *intResult) { int i = 0; WORD int_r,mask; // прочитать регистр прерываний // установить маскирование для данного бита или канала // поиск карточки в массиве while( i <= (MAX_CARDS - MIN_CARDS) ) { if( Cards[i] == hSLI6) { int_r = SLI6_ReadWord (Cards[i], SLI6_AD_BAR0, INT); //////////////// ждем не работают ли сейчас с прерываниями //////// DWORD dwWaitResult = WaitForSingleObject( int_rut[i], // handle to mutex INFINITE); // ждет бесконечно /////////////////////////////////////////////////////////////////// // прописываем маску mask = SLI6_ReadWord (Cards[i], SLI6_AD_BAR0, INT_ENABLE); mask &= ~(int_r); SLI6_WriteWord (Cards[i], SLI6_AD_BAR0, INT_ENABLE, mask); // включаем прерывания снова SLI6_WriteWord (Cards[i], SLI6_AD_BAR0, INT_GENABLE, 0x1); /////////////////////////////////////////////////////////////////// if (! ReleaseMutex(int_rut[i])) { sprintf(SLI6_ErrorString,"Can't reales mutex!"); return; } //////////////////////////////////////////////////////////////////// // поиск функции обработчика for(int k=0;k <= (MAX_CRATES-MIN_CRATES);k++) if( (int_r >> k)&1L == 1L) { if(intf[i][k] != NULL) { intf[i][k](( ((i+MIN_CARDS) << 16) | (k+MIN_CRATES) ),param[i][k]); // вызвать функцию-обработчик юзера //return; // иначе прерывания не установлены юзером } //sprintf(SLI6_ErrorString, "Error in interrupt hendler\n"); //return; // такого быть не может } return; } i++; } // в принципе не досягаемо!!!! sprintf(SLI6_ErrorString, "Error in interrupt hendler\n"); return; // такого быть не может } int __stdcall SetIntOnLAMfunc(int CN, INTLAMFUNC _intf) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16); //////////////// допустимость параметров ////////////////////////// if(!( ((MIN_CARDS <= CardN)&&(CardN <= MAX_CARDS))&& ((MIN_CRATES <= CrateN)&&(CrateN <= MAX_CRATES))&& (_intf != NULL)) ) { sprintf(SLI6_ErrorString,"Wrong parameters!"); return SLI6_ERROR; } CardN -= MIN_CARDS; CrateN -= MIN_CRATES; if(int_rut[CardN] == NULL) { // если карточка была открыта без прерываний CloseCard(CardN + MIN_CARDS); // открываем ее заново, но с прерываниями! if(OpenCard(CardN + MIN_CARDS,1) != SLI6_OK) return SLI6_ERROR; } intf[CardN][CrateN] = _intf; // пропиcываем функцию-обработчик юзера return SLI6_OK; } int __stdcall LAMIntEnable(int CN,PVOID _param) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16); WORD mask; //////////////// допустимость параметров ////////////////////////// if(!( ((MIN_CARDS <= CardN)&&(CardN <= MAX_CARDS))&& ((MIN_CRATES <= CrateN)&&(CrateN <= MAX_CRATES)) ) ) { sprintf(SLI6_ErrorString,"Wrong parameters!"); return SLI6_ERROR; } CardN -= MIN_CARDS; CrateN -= MIN_CRATES; if(int_rut[CardN] == NULL) { sprintf(SLI6_ErrorString,"Card hasn't been opened with interrupts!"); return SLI6_ERROR; // Карта не была открыта с прерываниями } //////////////// ждем не работают ли сейчас с прерываниями //////// DWORD dwWaitResult = WaitForSingleObject( int_rut[CardN], // handle to mutex INFINITE); // ждет бесконечно //////////////// критическая секция /////////////////////////////// // прописываем маску - разрешаем прерывание в ИПС-6 mask = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, INT_ENABLE); mask |= (1L << CrateN); SLI6_WriteWord (Cards[CardN], SLI6_AD_BAR0, INT_ENABLE, mask); param[CardN][CrateN] = _param; /////////////////////////////////////////////////////////////////// if (! ReleaseMutex(int_rut[CardN])) { sprintf(SLI6_ErrorString,"Can't reales mutex!"); return SLI6_ERROR; } if( !SLI6_IntIsEnabled(Cards[CardN])) if(!SLI6_IntEnable (Cards[CardN], Sli6IntHandler)) { sprintf(SLI6_ErrorString,"Can't Enable interruptions :("); return SLI6_ERROR; } return SLI6_OK; } int __stdcall LAMIntDisable(int CN) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16); WORD mask; if(!( ((MIN_CARDS <= CardN)&&(CardN <= MAX_CARDS))&& ((MIN_CRATES <= CrateN)&&(CrateN <= MAX_CRATES)) ) ) { sprintf(SLI6_ErrorString,"Wrong parameters!"); return SLI6_ERROR; } CardN -= MIN_CARDS; CrateN -= MIN_CRATES; if(int_rut[CardN] == NULL) { sprintf(SLI6_ErrorString,"Card hasn't been opened with interrupts!"); return SLI6_ERROR; // Карта не была открыта с прерываниями } //////////////// ждем не работают ли сейчас с прерываниями //////// DWORD dwWaitResult = WaitForSingleObject( int_rut[CardN], // handle to mutex INFINITE); // ждет бесконечно //////////////// критическая секция /////////////////////////////// // прописываем маску - запрещаем прерывание в ИПС-6 mask = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, INT_ENABLE); mask &= ~(1L << CrateN); SLI6_WriteWord (Cards[CardN], SLI6_AD_BAR0, INT_ENABLE, mask); ////////////////////////////////////////////////////////////////// if (! ReleaseMutex(int_rut[CardN])) { sprintf(SLI6_ErrorString,"Can't reales mutex!"); return SLI6_ERROR; } if(mask == 0) SLI6_IntDisable(Cards[CardN]); // если маска пуста - выключаем обработку вообще return SLI6_OK; } int __stdcall LAMIntIsEnabled(int CN) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16); WORD mask; if(!( ((MIN_CARDS <= CardN)&&(CardN <= MAX_CARDS))&& ((MIN_CRATES <= CrateN)&&(CrateN <= MAX_CRATES)) ) ) { sprintf(SLI6_ErrorString,"Wrong parameters!"); return SLI6_ERROR; } CardN -= MIN_CARDS; CrateN -= MIN_CRATES; // читаем маску mask = SLI6_ReadWord (Cards[CardN], SLI6_AD_BAR0, INT_ENABLE); return (mask >> CrateN)&1L ; } /////////// обработка ошибок ///////////////////////////////// void __stdcall GetErrStr(char * str) { strncpy(str,SLI6_ErrorString,sizeof(SLI6_ErrorString)); } //////////////////////////////////////////////////////////////////////// // internal function used by SLI6_Open() BOOL SLI6_DetectCardElements(SLI6_HANDLE hSLI6); DWORD SLI6_CountCards (DWORD dwVendorID, DWORD dwDeviceID) { WD_VERSION ver; WD_PCI_SCAN_CARDS pciScan; HANDLE hWD = INVALID_HANDLE_VALUE; SLI6_RegisterWinDriver(); SLI6_ErrorString[0] = '\0'; hWD = WD_Open(); // check if handle valid & version OK if (hWD==INVALID_HANDLE_VALUE) { sprintf (SLI6_ErrorString, "Failed opening WinDriver device\n"); return 0; } BZERO(ver); WD_Version(hWD,&ver); if (ver.dwVerhWD = WD_Open(); // check if handle valid & version OK if (hSLI6->hWD==INVALID_HANDLE_VALUE) { sprintf (SLI6_ErrorString, "Failed opening WinDriver device\n"); goto Exit; } BZERO(ver); WD_Version(hSLI6->hWD,&ver); if (ver.dwVerhWD, &pciScan); if (pciScan.dwCards==0) // Found at least one card { sprintf (SLI6_ErrorString, "Could not find PCI card\n"); goto Exit; } if (pciScan.dwCards<=nCardNum) { sprintf (SLI6_ErrorString, "Card out of range of available cards\n"); goto Exit; } BZERO(pciCardInfo); pciCardInfo.pciSlot = pciScan.cardSlot[nCardNum]; WD_PciGetCardInfo (hSLI6->hWD, &pciCardInfo); hSLI6->pciSlot = pciCardInfo.pciSlot; hSLI6->cardReg.Card = pciCardInfo.Card; hSLI6->fUseInt = (dwOptions & SLI6_OPEN_USE_INT) ? TRUE : FALSE; if (!hSLI6->fUseInt) { DWORD i; // Remove interrupt item if not needed for (i=0; icardReg.Card.dwItems; i++) { WD_ITEMS *pItem = &hSLI6->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 = &hSLI6->cardReg.Card.Item[i]; if (pItem->item==ITEM_INTERRUPT) pItem->fNotSharable = FALSE; } } hSLI6->cardReg.fCheckLockOnly = FALSE; WD_CardRegister (hSLI6->hWD, &hSLI6->cardReg); if (hSLI6->cardReg.hCard==0) { sprintf (SLI6_ErrorString, "Failed locking device.\n"); goto Exit; } if (!SLI6_DetectCardElements(hSLI6)) { sprintf (SLI6_ErrorString, "Card does not have all items expected for SLI6\n"); goto Exit; } // Open finished OK *phSLI6 = hSLI6; return TRUE; Exit: // Error during Open if (hSLI6->cardReg.hCard) WD_CardUnregister(hSLI6->hWD, &hSLI6->cardReg); if (hSLI6->hWD!=INVALID_HANDLE_VALUE) WD_Close(hSLI6->hWD); free (hSLI6); return FALSE; } void SLI6_Close(SLI6_HANDLE hSLI6) { // disable interrupts if (SLI6_IntIsEnabled(hSLI6)) SLI6_IntDisable(hSLI6); // unregister card if (hSLI6->cardReg.hCard) WD_CardUnregister(hSLI6->hWD, &hSLI6->cardReg); // close WinDriver WD_Close(hSLI6->hWD); free (hSLI6); } void SLI6_RegisterWinDriver() { HANDLE hWD; WD_LICENSE lic; hWD = WD_Open(); if (hWD!=INVALID_HANDLE_VALUE) { strcpy(lic.cLicense, "68C9BECCEDE89D5060EF8FC5BD1BA552.Warlock//SSG"); WD_License(hWD, &lic); WD_Close(hWD); } } void SLI6_WritePCIReg(SLI6_HANDLE hSLI6, DWORD dwReg, DWORD dwData) { WD_PCI_CONFIG_DUMP pciCnf; BZERO(pciCnf); pciCnf.pciSlot = hSLI6->pciSlot; pciCnf.pBuffer = &dwData; pciCnf.dwOffset = dwReg; pciCnf.dwBytes = 4; pciCnf.fIsRead = FALSE; WD_PciConfigDump(hSLI6->hWD,&pciCnf); } DWORD SLI6_ReadPCIReg(SLI6_HANDLE hSLI6, DWORD dwReg) { WD_PCI_CONFIG_DUMP pciCnf; DWORD dwVal; BZERO(pciCnf); pciCnf.pciSlot = hSLI6->pciSlot; pciCnf.pBuffer = &dwVal; pciCnf.dwOffset = dwReg; pciCnf.dwBytes = 4; pciCnf.fIsRead = TRUE; WD_PciConfigDump(hSLI6->hWD,&pciCnf); return dwVal; } BOOL SLI6_DetectCardElements(SLI6_HANDLE hSLI6) { DWORD i; DWORD ad_sp; BZERO(hSLI6->Int); BZERO(hSLI6->addrDesc); for (i=0; icardReg.Card.dwItems; i++) { WD_ITEMS *pItem = &hSLI6->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 & 0xffff; fIsMemory = FALSE; } for (ad_sp=0; ad_spaddrDesc[ad_sp].fActive = TRUE; hSLI6->addrDesc[ad_sp].index = i; hSLI6->addrDesc[ad_sp].fIsMemory = fIsMemory; hSLI6->addrDesc[ad_sp].dwMask = 0; for (j=1; jaddrDesc[ad_sp].dwMask = (hSLI6->addrDesc[ad_sp].dwMask << 1) | 1; } } } break; case ITEM_INTERRUPT: if (hSLI6->Int.Int.hInterrupt) return FALSE; hSLI6->Int.Int.hInterrupt = pItem->I.Int.hInterrupt; break; } } // check that all the items needed were found // check if interrupt found if (hSLI6->fUseInt && !hSLI6->Int.Int.hInterrupt) { return FALSE; } // check that at least one memory space was found for (i = 0; iaddrDesc[addrSpace].fActive; } void SLI6_GetPciSlot(SLI6_HANDLE hSLI6, WD_PCI_SLOT *pPciSlot) { memcpy((PVOID)pPciSlot, &(hSLI6->pciSlot), sizeof(WD_PCI_SLOT)); } // General read/write function void SLI6_ReadWriteBlock(SLI6_HANDLE hSLI6, SLI6_ADDR addrSpace, DWORD dwOffset, BOOL fRead, PVOID buf, DWORD dwBytes, SLI6_MODE mode) { WD_TRANSFER trans; BOOL fMem = hSLI6->addrDesc[addrSpace].fIsMemory; // safty check: is the address range active if (!SLI6_IsAddrSpaceActive(hSLI6, addrSpace)) return; BZERO(trans); if (fRead) { if (mode==SLI6_MODE_BYTE) trans.cmdTrans = fMem ? RM_SBYTE : RP_SBYTE; else if (mode==SLI6_MODE_WORD) trans.cmdTrans = fMem ? RM_SWORD : RP_SWORD; else if (mode==SLI6_MODE_DWORD) trans.cmdTrans = fMem ? RM_SDWORD : RP_SDWORD; } else { if (mode==SLI6_MODE_BYTE) trans.cmdTrans = fMem ? WM_SBYTE : WP_SBYTE; else if (mode==SLI6_MODE_WORD) trans.cmdTrans = fMem ? WM_SWORD : WP_SWORD; else if (mode==SLI6_MODE_DWORD) trans.cmdTrans = fMem ? WM_SDWORD : WP_SDWORD; } if (fMem) trans.dwPort = hSLI6->cardReg.Card.Item[hSLI6->addrDesc[addrSpace].index].I.Mem.dwTransAddr; else trans.dwPort = hSLI6->cardReg.Card.Item[hSLI6->addrDesc[addrSpace].index].I.IO.dwAddr; trans.dwPort += dwOffset; trans.fAutoinc = TRUE; trans.dwBytes = dwBytes; trans.dwOptions = 0; trans.Data.pBuffer = buf; WD_Transfer (hSLI6->hWD, &trans); } BYTE SLI6_ReadByte (SLI6_HANDLE hSLI6, SLI6_ADDR addrSpace, DWORD dwOffset) { BYTE data; if (hSLI6->addrDesc[addrSpace].fIsMemory) { PBYTE pData = (PBYTE) (hSLI6->cardReg.Card.Item[hSLI6->addrDesc[addrSpace].index].I.Mem.dwUserDirectAddr + dwOffset); data = *pData; // read from the memory mapped range directly } else SLI6_ReadWriteBlock(hSLI6, addrSpace, dwOffset, TRUE, &data, sizeof(BYTE), SLI6_MODE_BYTE); return data; } WORD SLI6_ReadWord (SLI6_HANDLE hSLI6, SLI6_ADDR addrSpace, DWORD dwOffset) { WORD data; if (hSLI6->addrDesc[addrSpace].fIsMemory) { PWORD pData = (PWORD) (hSLI6->cardReg.Card.Item[hSLI6->addrDesc[addrSpace].index].I.Mem.dwUserDirectAddr + dwOffset); data = *pData; // read from the memory mapped range directly } else SLI6_ReadWriteBlock(hSLI6, addrSpace, dwOffset, TRUE, &data, sizeof(WORD), SLI6_MODE_WORD); return data; } DWORD SLI6_ReadDword (SLI6_HANDLE hSLI6, SLI6_ADDR addrSpace, DWORD dwOffset) { DWORD data; if (hSLI6->addrDesc[addrSpace].fIsMemory) { PDWORD pData = (PDWORD) (hSLI6->cardReg.Card.Item[hSLI6->addrDesc[addrSpace].index].I.Mem.dwUserDirectAddr + dwOffset); data = *pData; // read from the memory mapped range directly } else SLI6_ReadWriteBlock(hSLI6, addrSpace, dwOffset, TRUE, &data, sizeof(DWORD), SLI6_MODE_DWORD); return data; } void SLI6_WriteByte (SLI6_HANDLE hSLI6, SLI6_ADDR addrSpace, DWORD dwOffset, BYTE data) { if (hSLI6->addrDesc[addrSpace].fIsMemory) { PBYTE pData = (PBYTE) (hSLI6->cardReg.Card.Item[hSLI6->addrDesc[addrSpace].index].I.Mem.dwUserDirectAddr + dwOffset); *pData = data; // write to the memory mapped range directly } else SLI6_ReadWriteBlock(hSLI6, addrSpace, dwOffset, FALSE, &data, sizeof(BYTE), SLI6_MODE_BYTE); } void SLI6_WriteWord (SLI6_HANDLE hSLI6, SLI6_ADDR addrSpace, DWORD dwOffset, WORD data) { if (hSLI6->addrDesc[addrSpace].fIsMemory) { PWORD pData = (PWORD) (hSLI6->cardReg.Card.Item[hSLI6->addrDesc[addrSpace].index].I.Mem.dwUserDirectAddr + dwOffset); *pData = data; // write to the memory mapped range directly } else SLI6_ReadWriteBlock(hSLI6, addrSpace, dwOffset, FALSE, &data, sizeof(WORD), SLI6_MODE_WORD); } void SLI6_WriteDword (SLI6_HANDLE hSLI6, SLI6_ADDR addrSpace, DWORD dwOffset, DWORD data) { if (hSLI6->addrDesc[addrSpace].fIsMemory) { PDWORD pData = (PDWORD) (hSLI6->cardReg.Card.Item[hSLI6->addrDesc[addrSpace].index].I.Mem.dwUserDirectAddr + dwOffset); *pData = data; // write to the memory mapped range directly } else SLI6_ReadWriteBlock(hSLI6, addrSpace, dwOffset, FALSE, &data, sizeof(DWORD), SLI6_MODE_DWORD); } BOOL SLI6_IntIsEnabled (SLI6_HANDLE hSLI6) { if (!hSLI6->fUseInt) return FALSE; if (!hSLI6->Int.hThread) return FALSE; return TRUE; } void SLI6_IntHandler (PVOID pData) { SLI6_HANDLE hSLI6 = (SLI6_HANDLE) pData; SLI6_INT_RESULT intResult; intResult.dwCounter = hSLI6->Int.Int.dwCounter; intResult.dwLost = hSLI6->Int.Int.dwLost; intResult.fStopped = hSLI6->Int.Int.fStopped; hSLI6->Int.funcIntHandler(hSLI6, &intResult); } BOOL SLI6_IntEnable (SLI6_HANDLE hSLI6, SLI6_INT_HANDLER funcIntHandler) { SLI6_ADDR addrSpace; if (!hSLI6->fUseInt) return FALSE; // check if interrupt is already enabled if (hSLI6->Int.hThread) return FALSE; BZERO(hSLI6->Int.Trans); // This is a sample of handling interrupts: // One transfer command is issued to CANCEL the source of the interrupt, // otherwise, the PC will hang when an interrupt occurs! // You will need to modify this code to fit your specific hardware. addrSpace = SLI6_AD_BAR0; // put the address space of the register here if (hSLI6->addrDesc[addrSpace].fIsMemory) { hSLI6->Int.Trans[0].dwPort = hSLI6->cardReg.Card.Item[hSLI6->addrDesc[addrSpace].index].I.Mem.dwTransAddr; hSLI6->Int.Trans[0].cmdTrans = WM_DWORD; } else { hSLI6->Int.Trans[0].dwPort = hSLI6->cardReg.Card.Item[hSLI6->addrDesc[addrSpace].index].I.IO.dwAddr; hSLI6->Int.Trans[0].cmdTrans = WP_DWORD; } hSLI6->Int.Trans[0].dwPort += INT_GENABLE ; // put the offset of the register from the beginning of the address space here hSLI6->Int.Trans[0].Data.Dword = 0x0; hSLI6->Int.Int.dwCmds = 1; hSLI6->Int.Int.Cmd = hSLI6->Int.Trans; hSLI6->Int.Int.dwOptions |= INTERRUPT_CMD_COPY; // this calls WD_IntEnable() and creates an interrupt handler thread hSLI6->Int.funcIntHandler = funcIntHandler; if (!InterruptThreadEnable(&hSLI6->Int.hThread, hSLI6->hWD, &hSLI6->Int.Int, SLI6_IntHandler, (PVOID) hSLI6)) return FALSE; return TRUE; } void SLI6_IntDisable (SLI6_HANDLE hSLI6) { if (!hSLI6->fUseInt) return; if (!hSLI6->Int.hThread) return; // this calls WD_IntDisable() InterruptThreadDisable(hSLI6->Int.hThread); hSLI6->Int.hThread = NULL; } #ifdef __cplusplus } #endif