#define WANTVXDWRAPS #include #include #include #include #include #include #include "irqcos.h" #pragma VxD_LOCKED_CODE_SEG #pragma VxD_LOCKED_DATA_SEG DWORD cbIn, cbOut; // Sizes of input and output buffers PSTR lpOut; // Pointers to input and output buffers LPOVERLAPPED lpo; // Pointer to overlapped structure unsigned char myIRQ = 0; // holds irq sent by dll unsigned long myBase = 0; // holds base address sent by dll unsigned char ReturnData[6] = {0,0,0,0,0,0}; // holds data when an int occurs BOOL IRQ_Hooked = FALSE; BOOL IRQ_Occurred = FALSE; BOOL IRQ_Requested = FALSE; HIRQ hIRQ; VID IRQCOS_IRQ_Desc = {0,0,0,0,0,0,0,0,0}; unsigned short _stdcall inport(unsigned short port) { unsigned short t=0; _asm { mov dx,port in ax,dx mov t,ax } return t; } unsigned char _stdcall inportb(unsigned short port) { unsigned short t=0; _asm { mov dx,port in al,dx xor ah,ah mov t,ax } return t; } void _stdcall outport(unsigned short port, unsigned short val) { _asm { mov dx, port mov ax, val out dx, ax } } void _stdcall outportb(unsigned short port, unsigned char val) { _asm { mov dx, port mov al, val out dx, al } } /**************************************************************************** IRQCOS_DeviceIOControl // Returning a positive value will cause the WIN32 DeviceIOControl // call to return FALSE, the error code can then be retrieved // via the WIN32 API GetLastError. ****************************************************************************/ DWORD _stdcall IRQCOS_DeviceIOControl(DWORD dwService, DWORD dwDDB, DWORD hDevice, LPDIOC lpDIOCParms) { DWORD dwRetVal = 0; switch (dwService) { case DIOC_OPEN: // same as GET_VERSION dwRetVal = 0; break; case DIOC_CLOSEHANDLE: dwRetVal = IRQCOS_CleanUp(); break; case InitCOSDriver: dwRetVal = IRQCOS_InitCOSDriver(dwDDB, hDevice, lpDIOCParms); break; case GetData: dwRetVal = IRQCOS_GetData(dwDDB, hDevice, lpDIOCParms); break; case Abort: dwRetVal = IRQCOS_Abort(dwDDB, hDevice, lpDIOCParms); break; default: dwRetVal = ERROR_NOT_SUPPORTED; break; } return(dwRetVal); } DWORD _stdcall IRQCOS_InitCOSDriver(DWORD dwDDB, DWORD hDevice, LPDIOC lpDIOCtl) { PIRQCOS_INIT_DATA pBuffer; pBuffer = (PIRQCOS_INIT_DATA)lpDIOCtl->lpvInBuffer; cbIn = lpDIOCtl->cbInBuffer; if (cbIn < sizeof(IRQCOS_INIT_DATA)) return ERROR_INVALID_PARAMETER; if (IRQ_Hooked) VPICD_Force_Default_Behavior(hIRQ); IRQ_Hooked = FALSE; /* if (IRQ_Requested) { lpo->O_InternalHigh = 0; VWIN32_DIOCCompletionRoutine(lpo->O_Internal); }*/ myIRQ = pBuffer->IRQ; myBase = pBuffer->BaseAddress; IRQCOS_IRQ_Desc.VID_IRQ_Number = myIRQ; IRQCOS_IRQ_Desc.VID_Hw_Int_Proc = (ULONG)&IRQCOS_Event_Callback; hIRQ = VPICD_Virtualize_IRQ(&IRQCOS_IRQ_Desc); IRQ_Hooked = TRUE; VPICD_Physically_Unmask(hIRQ); return(0); } DWORD _stdcall IRQCOS_GetData(DWORD dwDDB, DWORD hDevice, LPDIOC lpDIOCtl) { *(PDWORD)(lpDIOCtl->lpcbBytesReturned) = 0; if ( !lpDIOCtl->lpoOverlapped || !IRQ_Hooked || IRQ_Requested) return ERROR_NOT_SUPPORTED; lpOut = (PSTR)lpDIOCtl->lpvOutBuffer; cbOut = lpDIOCtl->cbOutBuffer; lpo = (LPOVERLAPPED)lpDIOCtl->lpoOverlapped; if (IRQ_Occurred) { lpOut[0] = ReturnData[0]; lpOut[1] = ReturnData[1]; lpOut[2] = ReturnData[2]; lpOut[3] = ReturnData[3]; lpOut[4] = ReturnData[4]; lpOut[5] = ReturnData[5]; *(PDWORD)(lpDIOCtl->lpcbBytesReturned) = sizeof(ReturnData); IRQ_Occurred = FALSE; return(0); // This will make DeviceIOControl return synchronously } IRQ_Requested = TRUE; lpOut = (PSTR)MyPageLock((DWORD)lpOut, cbOut); lpo = (LPOVERLAPPED)MyPageLock((DWORD)lpo, sizeof(OVERLAPPED)); return(-1); // This will make DeviceIOControl return ERROR_IO_PENDING } DWORD _stdcall IRQCOS_Abort(DWORD dwDDB, DWORD hDevice, LPDIOC lpDIOCtl) { if (!IRQ_Requested) return ERROR_NOT_SUPPORTED; lpo->O_InternalHigh = 0; VWIN32_DIOCCompletionRoutine(lpo->O_Internal); MyPageUnlock((DWORD)lpOut, cbOut); MyPageUnlock((DWORD)lpo, sizeof(OVERLAPPED)); IRQ_Requested = FALSE; *(PDWORD)(lpDIOCtl->lpcbBytesReturned) = 0; return(0); } void _cdecl IRQCOS_Event_Callback(void) { outportb(myBase + 0x0f, 0); ReturnData[0] = inportb(myBase); ReturnData[1] = inportb(myBase+1); ReturnData[2] = inportb(myBase+2); ReturnData[3] = inportb(myBase+4); ReturnData[4] = inportb(myBase+5); ReturnData[5] = inportb(myBase+6); IRQ_Occurred = TRUE; if (IRQ_Requested) { lpOut[0] = ReturnData[0]; lpOut[1] = ReturnData[1]; lpOut[2] = ReturnData[2]; lpOut[3] = ReturnData[3]; lpOut[4] = ReturnData[4]; lpOut[5] = ReturnData[5]; lpo->O_InternalHigh = sizeof(ReturnData); VWIN32_DIOCCompletionRoutine(lpo->O_Internal); MyPageUnlock((DWORD)lpOut, cbOut); MyPageUnlock((DWORD)lpo, sizeof(OVERLAPPED)); IRQ_Occurred = FALSE; IRQ_Requested = FALSE; } VPICD_Phys_EOI(hIRQ); } DWORD _stdcall IRQCOS_CleanUp(void) { if (IRQ_Hooked) VPICD_Force_Default_Behavior(hIRQ); if (IRQ_Requested) { MyPageUnlock((DWORD)lpOut, cbOut); MyPageUnlock((DWORD)lpo, sizeof(OVERLAPPED)); } IRQ_Hooked = IRQ_Requested = IRQ_Occurred = FALSE; return(VXD_SUCCESS); } DWORD _stdcall IRQCOS_Dynamic_Exit(void) { return(VXD_SUCCESS); } DWORD _stdcall MyPageLock(DWORD lpMem, DWORD cbSize) { DWORD LinPageNum, LinOffset, nPages; LinOffset = lpMem & 0xfff; // page offset of memory to map LinPageNum = lpMem >> 12; // generate page number // Calculate # of pages to map globally nPages = ((lpMem + cbSize) >> 12) - LinPageNum + 1; // // Return global mapping of passed in pointer, as this new pointer // is how the memory must be accessed out of context. // return (_LinPageLock(LinPageNum, nPages, PAGEMAPGLOBAL) + LinOffset); } void _stdcall MyPageUnlock(DWORD lpMem, DWORD cbSize) { DWORD LinPageNum, nPages; LinPageNum = lpMem >> 12; nPages = ((lpMem + cbSize) >> 12) - LinPageNum + 1; // Free globally mapped memory _LinPageUnlock(LinPageNum, nPages, PAGEMAPGLOBAL); } #pragma VxD_ICODE_SEG #pragma VxD_IDATA_SEG DWORD _stdcall IRQCOS_Dynamic_Init(void) { return(VXD_SUCCESS); }