////////////////////////////////////////////////////////////////////// // File - sli6_lib.c // // Library for accessing the SLI6 card version 2.10 // Code was generated by DriverWizard v6.03 - http://www.jungo.com. // The library accesses the hardware via WinDriver functions. // // Copyright (c) 2003 Jungo Ltd. http://www.jungo.com // ////////////////////////////////////////////////////////////////////// #include "sli6_lib.h" #include "sli6_ext.h" #include "windrvr_int_thread.h" #include "windrvr_events.h" #include "status_strings.h" #ifndef __KERNEL__ #include #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; BOOL fIsMemory; BOOL fActive; } SLI6_ADDR_DESC; typedef struct SLI6_STRUCT { HANDLE hWD; HANDLE hEvent; 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) { 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 (SLI6_Open (Cards+CardN, SLI6_DEFAULT_VENDOR_ID, SLI6_DEFAULT_DEVICE_ID, CardN)) { 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!"); SLI6_Close(Cards[CardN]); Cards[CardN] = NULL; 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; //ошибка нет больше карт } } 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; 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) == 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(crate 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(crate CN, int posN, int A, int F, WORD *data) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16)&0x0000FFFF; DWORD dwOffset; WORD busy,status; CardN -= MIN_CARDS; CrateN -= MIN_CRATES; /////////////// подготовка /////////////////////////////////////////// dwOffset = BASE | (1L << (CrateN + 13)) | (0x1000) | ((posN&0x1F) << 6) | ((A&0xF) << 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 & 0xFFE0) | (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(crate CN, int posN, int A, WORD *data) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16)&0x0000FFFF; DWORD dwOffset; WORD busy,status; CardN -= MIN_CARDS; CrateN -= MIN_CRATES; /////////////// подготовка /////////////////////////////////////////// dwOffset = BASE | (1L << (CrateN + 13)) | (0x1000) | ((posN&0x1F) << 6) | ((A&0xF) << 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(crate CN, int posN, int A, WORD *data) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16)&0x0000FFFF; DWORD dwOffset; WORD busy,status; CardN -= MIN_CARDS; CrateN -= MIN_CRATES; /////////////// подготовка /////////////////////////////////////////// dwOffset = BASE | (1L << (CrateN + 13)) | (0x1000) | ((posN&0x1F) << 6) | ((A&0xF) << 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(crate CN, int posN, int A, DWORD *data) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16)&0x0000FFFF; DWORD dwOffset; WORD busy,status; CardN -= MIN_CARDS; CrateN -= MIN_CRATES; /////////////// подготовка /////////////////////////////////////////// dwOffset = BASE | (1L << (CrateN + 13)) | (0x1000) | ((posN&0x1F) << 6) | ((A&0xF) << 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(crate CN, int posN, int A, DWORD *data) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16)&0x0000FFFF; DWORD dwOffset; WORD busy,status; CardN -= MIN_CARDS; CrateN -= MIN_CRATES; /////////////// подготовка /////////////////////////////////////////// dwOffset = BASE | (1L << (CrateN + 13)) | (0x1000) | ((posN&0x1F) << 6) | ((A&0xF) << 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(crate CN, int posN, int A, int F, DWORD *data) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16)&0x0000FFFF; DWORD dwOffset; WORD busy,status; CardN -= MIN_CARDS; CrateN -= MIN_CRATES; /////////////// подготовка /////////////////////////////////////////// dwOffset = BASE | (1L << (CrateN + 13)) | (0x1000) | ((posN&0x1F) << 6) | ((A&0xF) << 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 & 0xFFE0) | (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(crate CN, int posN, int A, int F, unsigned int Nblock, DWORD *data) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16)&0x0000FFFF; DWORD dwOffset; WORD busy,status; CardN -= MIN_CARDS; CrateN -= MIN_CRATES; /////////////// подготовка /////////////////////////////////////////// dwOffset = BASE | (1L << (CrateN + 13)) | (0x1000) | ((posN&0x1F) << 6) | ((A&0xF) << 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 & 0xFFE0) | (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) // чтение { 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(crate CN, int posN, int A, int F,unsigned long Nblock, WORD *data) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16)&0x0000FFFF; DWORD dwOffset; WORD busy,status; CardN -= MIN_CARDS; CrateN -= MIN_CRATES; /////////////// подготовка /////////////////////////////////////////// dwOffset = BASE | (1L << (CrateN + 13)) | (0x1000) | ((posN&0x1F) << 6) | ((A&0xF) << 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 & 0xFFE0) | (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) // чтение { 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(crate CN) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16)&0x0000FFFF; 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(crate CN) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16)&0x0000FFFF; 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(crate CN, int posN, int A, WORD *dataw,WORD *datar) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16)&0x0000FFFF; DWORD dwOffset; WORD busy,status; CardN -= MIN_CARDS; CrateN -= MIN_CRATES; /////////////// подготовка /////////////////////////////////////////// dwOffset = BASE | (1L << (CrateN + 13)) | (0x1000) | ((posN&0x1F) << 6) | ((A&0xF) << 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(crate CN, int posN, int A,DWORD *dataw, DWORD *datar) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16)&0x0000FFFF; DWORD dwOffset; WORD busy,status; CardN -= MIN_CARDS; CrateN -= MIN_CRATES; /////////////// подготовка /////////////////////////////////////////// dwOffset = BASE | (1L << (CrateN + 13)) | (0x1000) | ((posN&0x1F) << 6) | ((A&0xF) << 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(crate CN) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16)&0x0000FFFF; 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) != 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); /////////////////////////////////////////////////////////////////// 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]); // вызвать функцию-обработчик юзера } // включаем прерывания снова SLI6_WriteWord (Cards[i], SLI6_AD_BAR0, INT_GENABLE, 0x1); return; } i++; } // в принципе не досягаемо!!!! sprintf(SLI6_ErrorString, "Error in interrupt handler\n"); return; // такого быть не может } int __stdcall SetIntOnLAMfunc(crate CN, INTLAMFUNC _intf) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16)&0x0000FFFF; //////////////// допустимость параметров ////////////////////////// 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) return SLI6_ERROR; intf[CardN][CrateN] = _intf; // пропиcываем функцию-обработчик юзера return SLI6_OK; } int __stdcall LAMIntEnable(crate CN,PVOID _param) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16)&0x0000FFFF; 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(crate CN) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16)&0x0000FFFF; 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!"); 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(crate CN) { unsigned int CrateN = CN & 0x0000FFFF; unsigned int CardN = (CN >> 16)&0x0000FFFF; 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); // Function: SLI6_CountCards() // Count the number of PCI cards that meets the given criteria. // Parameters: // hSLI6 [in] handle to the card as received from SLI6_Open(). // dwVendorID [in] indicates the vendor ID of the PCI card to search. // 0 indicates all vendor IDs. // dwDeviceID [in] indicates the Device ID of the PCI card to search. // 0 indicates all device IDs. // Return Value: // the number of PCI cards found. DWORD SLI6_CountCards (DWORD dwVendorID, DWORD dwDeviceID) { WD_VERSION ver; WD_PCI_SCAN_CARDS pciScan; HANDLE hWD = INVALID_HANDLE_VALUE; DWORD dwStatus; SLI6_RegisterWinDriver(); SLI6_ErrorString[0] = '\0'; hWD = WD_Open(); // Verify that the handle is valid and that the version number is correct 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(); // Verify that the handle is valid and that the version number is correct 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 (dwStatus) { sprintf(SLI6_ErrorString, "WD_PciScanCards() failed with status 0x%x - %s\n", dwStatus, Stat2Str(dwStatus)); goto Exit; } if (pciScan.dwCards==0) { sprintf(SLI6_ErrorString, "Could not find PCI card\n"); goto Exit; } if (pciScan.dwCards<=nCardNum) { sprintf(SLI6_ErrorString, "Card is out of range of available cards\n"); goto Exit; } // Found at least one card BZERO(pciCardInfo); pciCardInfo.pciSlot = pciScan.cardSlot[nCardNum]; dwStatus = WD_PciGetCardInfo(hSLI6->hWD, &pciCardInfo); if (dwStatus) { sprintf(SLI6_ErrorString, "WD_PciGetCardInfo() failed with status 0x%x - %s\n", dwStatus, Stat2Str(dwStatus)); goto Exit; } hSLI6->pciSlot = pciCardInfo.pciSlot; hSLI6->cardReg.Card = pciCardInfo.Card; hSLI6->cardReg.fCheckLockOnly = FALSE; dwStatus = WD_CardRegister(hSLI6->hWD, &hSLI6->cardReg); if (dwStatus) { sprintf(SLI6_ErrorString, "Failed locking device. Status 0x%x - %s\n", dwStatus, Stat2Str(dwStatus)); goto Exit; } if (!SLI6_DetectCardElements(hSLI6)) { sprintf (SLI6_ErrorString, "Card does not have all items expected for SLI6\n"); goto Exit; } // SLI6_Open() was successful *phSLI6 = hSLI6; return TRUE; Exit: // An error occured during the execution of SLI6_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; } // Function: SLI6_Close() // Unregister an opened card. // Parameters: // hSLI6 [in] handle to the card as received from SLI6_Open(). // Return Value: // None. 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); } // Function: SLI6_RegisterWinDriver() // Enter a license string into WinDriver module. // Parameters: // None. // Return Value: // None. void SLI6_RegisterWinDriver() { HANDLE hWD; WD_LICENSE lic; hWD = WD_Open(); if (hWD!=INVALID_HANDLE_VALUE) { strcpy(lic.cLicense, "6C3CC2BFF76637EC556BF9D50D98F518FD249B67.bkd"); WD_License(hWD, &lic); WD_Close(hWD); } } // Function: SLI6_WritePCIReg() // Write a DWORD to the PCI configuration space. // Parameters: // hSLI6 [in] handle to the card as received from SLI6_Open(). // dwReg [in] offset of the register in the PCI configuration space. // dwData [in] the value to write into the register. // Return Value: // None. 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); } // Function: SLI6_ReadPCIReg() // Read a DWORD from the PCI configuration space. // Parameters: // hSLI6 [in] handle to the card as received from SLI6_Open(). // dwReg [in] offset of the register in the PCI configuration space. // Return Value: // the value of the register. 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: ad_sp = pItem->I.Mem.dwBar; hSLI6->addrDesc[ad_sp].fIsMemory = TRUE; hSLI6->addrDesc[ad_sp].fActive = TRUE; hSLI6->addrDesc[ad_sp].index = i; break; case ITEM_IO: ad_sp = pItem->I.IO.dwBar; hSLI6->addrDesc[ad_sp].fIsMemory = FALSE; hSLI6->addrDesc[ad_sp].fActive = TRUE; hSLI6->addrDesc[ad_sp].index = i; break; case ITEM_INTERRUPT: if (hSLI6->Int.Int.hInterrupt) return FALSE; hSLI6->Int.Int.hInterrupt = pItem->I.Int.hInterrupt; break; } } // Verify that all the necessary items were found // Verify that an interrupt was found if (!hSLI6->Int.Int.hInterrupt) return FALSE; // Verify that at least one memory/IO space was found for (i = 0; iaddrDesc[addrSpace].fActive; } // Function: SLI6_GetPciSlot() // Return the logical location (bus, slot and function) of the PCI card. // Parameters: // hSLI6 [in] handle to the card as received from SLI6_Open(). // pPciSlot [out] - pointer to a caller allocated space that will hold the // logical location of the card // Return Value: // None. void SLI6_GetPciSlot(SLI6_HANDLE hSLI6, WD_PCI_SLOT *pPciSlot) { memcpy((PVOID)pPciSlot, &(hSLI6->pciSlot), sizeof(WD_PCI_SLOT)); } // General read/write functions // Function: SLI6_ReadWriteBlock() // Read/Write data from/to the card's memory/IO into/from a given buffer. // Parameters: // hSLI6 [in] handle to the card as received from SLI6_Open(). // addrSpace [in] the address space of the card to access. // dwOffset [in] offset relative to the beginning of the address space to access. // fRead [in] direction of operation: // TRUE indicates read from the card's memory/IO into the given buffer. // FALSE indicates write from the given buffer to the card's memory/IO. // buf [in/out] a caller allocated buffer to read/write to/from. // dwBytes [in] the number of bytes to read/write. The allocated buffer should be at least dwBytes long. // mode [in] perform the data transfer byte by byte / word by word / dword by dword. // Return Value: // None. 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; // safety 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); } // Function: SLI6_ReadByte() // Read a Byte from the card's memory/IO. // Parameters: // hSLI6 [in] handle to the card as received from SLI6_Open(). // addrSpace [in] the address space of the card to access. // dwOffset [in] offset relative to the beginning of the address space to access. // Return Value: // The value read from the card's memory/IO. 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 directly from the memory mapped range } else SLI6_ReadWriteBlock(hSLI6, addrSpace, dwOffset, TRUE, &data, sizeof(BYTE), SLI6_MODE_BYTE); return data; } // Function: SLI6_ReadWord() // Read a Word from the card's memory/IO. // Parameters: // hSLI6 [in] handle to the card as received from SLI6_Open(). // addrSpace [in] the address space of the card to access. // dwOffset [in] offset relative to the beginning of the address space to access. // Return Value: // The value read from the card's memory/IO. 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 directly from the memory mapped range } else SLI6_ReadWriteBlock(hSLI6, addrSpace, dwOffset, TRUE, &data, sizeof(WORD), SLI6_MODE_WORD); return data; } // Function: SLI6_ReadDword() // Read a Dword from the card's memory/IO. // Parameters: // hSLI6 [in] handle to the card as received from SLI6_Open(). // addrSpace [in] the address space of the card to access. // dwOffset [in] offset relative to the beginning of the address space to access. // Return Value: // The value read from the card's memory/IO. 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 directly from the memory mapped range } else SLI6_ReadWriteBlock(hSLI6, addrSpace, dwOffset, TRUE, &data, sizeof(DWORD), SLI6_MODE_DWORD); return data; } // Function: SLI6_WriteByte() // Write a Byte to the card's memory/IO. // Parameters: // hSLI6 [in] handle to the card as received from SLI6_Open(). // addrSpace [in] the address space of the card to access. // dwOffset [in] offset relative to the beginning of the address space to access. // data [in] the data to write to the card's memory/IO. // Return Value: // None. 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 directly to the memory mapped range } else SLI6_ReadWriteBlock(hSLI6, addrSpace, dwOffset, FALSE, &data, sizeof(BYTE), SLI6_MODE_BYTE); } // Function: SLI6_WriteWord() // Write a Word to the card's memory/IO. // Parameters: // hSLI6 [in] handle to the card as received from SLI6_Open(). // addrSpace [in] the address space of the card to access. // dwOffset [in] offset relative to the beginning of the address space to access. // data [in] the data to write to the card's memory/IO. // Return Value: // None. 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 directly to the memory mapped range } else SLI6_ReadWriteBlock(hSLI6, addrSpace, dwOffset, FALSE, &data, sizeof(WORD), SLI6_MODE_WORD); } // Function: SLI6_WriteDword() // Write a Dword to the card's memory/IO. // Parameters: // hSLI6 [in] handle to the card as received from SLI6_Open(). // addrSpace [in] the address space of the card to access. // dwOffset [in] offset relative to the beginning of the address space to access. // data [in] the data to write to the card's memory/IO. // Return Value: // None. 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 directly to the memory mapped range } else SLI6_ReadWriteBlock(hSLI6, addrSpace, dwOffset, FALSE, &data, sizeof(DWORD), SLI6_MODE_DWORD); } // Function: SLI6_IntIsEnabled() // Check if the interrupt is enabled. // Parameters: // hSLI6 [in] handle to the card as received from SLI6_Open(). // Return Value: // TRUE if the interrupt is enabled. FALSE otherwise. BOOL SLI6_IntIsEnabled (SLI6_HANDLE hSLI6) { 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); } // Function: SLI6_IntEnable() // Enable the interrupt. // Parameters: // hSLI6 [in] handle to the card as received from SLI6_Open. // funcIntHandler [in] The call back function to be called upon interrupt. // Return Value: // TRUE if the interrupt was successfully enabled. FALSE otherwise. BOOL SLI6_IntEnable (SLI6_HANDLE hSLI6, SLI6_INT_HANDLER funcIntHandler) { SLI6_ADDR addrSpace; DWORD dwStatus; // Check if interrupt is already enabled if (hSLI6->Int.hThread) return FALSE; BZERO(hSLI6->Int.Trans[0]); // One transfer command is issued to CANCEL the source of the interrupt, // otherwise, the PC will hang when an interrupt occurs! addrSpace = SLI6_RegisterG_INT_EN_SPACE; 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 += SLI6_RegisterG_INT_EN_OFFSET; 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; // Calls WD_IntEnable() and creates an interrupt handler thread hSLI6->Int.funcIntHandler = funcIntHandler; dwStatus = InterruptEnable(&hSLI6->Int.hThread, hSLI6->hWD, &hSLI6->Int.Int, SLI6_IntHandler, (PVOID) hSLI6); if (dwStatus) { sprintf(SLI6_ErrorString, "InterruptEnable() failed with status 0x%x - %s\n", dwStatus, Stat2Str(dwStatus)); return FALSE; } return TRUE; } // Function: SLI6_IntDisable() // Disable the interrupt. // Parameters: // hSLI6 [in] handle to the card as received from SLI6_Open(). // Return Value: // None. void SLI6_IntDisable (SLI6_HANDLE hSLI6) { if (!hSLI6->Int.hThread) return; // this calls WD_IntDisable() InterruptDisable(hSLI6->Int.hThread); hSLI6->Int.hThread = NULL; } // Function: SLI6_RegisterEvent() // Register to receive Plug-and-Play and power notification events according to the given criteria. // Parameters: // hSLI6 [in] handle to the PCI card as received from SLI6_Open(). // dwAction [in] bit-field data that indicated on what type of actions to be notified. // dwVendorID [in] indicates the vendor ID of the PCI card to register events upon. // 0 indicates all vendor IDs. // dwDeviceID [in] indicates the device ID of the PCI card to register events upon. // 0 indicates all device IDs. // pciSlot [in] indicates the logical location (bus, lot and function) of the PCI card // to register events upon. 0 indicates all // funcHandler [in] the call back function to be called when event is received. // Return Value: // TRUE is the registration was successful. FALSE otherwise. BOOL SLI6_RegisterEvent(SLI6_HANDLE hSLI6, DWORD dwAction, DWORD dwVendorID, DWORD dwDeviceID, WD_PCI_SLOT pciSlot, EVENT_HANDLER funcHandler) { HANDLE hEvent; WD_EVENT Events; DWORD dwStatus; BZERO(Events); Events.dwCardType = WD_BUS_PCI; Events.u.Pci.pciSlot = pciSlot; Events.u.Pci.cardId.dwVendorId = dwVendorID; Events.u.Pci.cardId.dwDeviceId = dwDeviceID; Events.dwAction = dwAction; dwStatus = EventRegister(&hEvent, hSLI6->hWD, &Events, funcHandler, NULL); if (dwStatus) { sprintf(SLI6_ErrorString, "EventRegister() failed with status 0x%x - %s\n", dwStatus, Stat2Str(dwStatus)); return FALSE; } hSLI6->hEvent = hEvent; return TRUE; } // Function: SLI6_UnregisterEvent() // Unregister events notification. // Parameters: // hSLI6 [in] handle to the PCI card as received from SLI6_Open(). // Return Value: // None. void SLI6_UnregisterEvent(SLI6_HANDLE hSLI6) { if (hSLI6->hEvent) EventUnregister(hSLI6->hEvent); }