#define WANTVXDWRAPS #include #include #include #include #include #include #include "irqgenm.h" #pragma VxD_LOCKED_CODE_SEG #pragma VxD_LOCKED_DATA_SEG BOOL IRQ_Hooked[16]; BOOL IRQ_Occurred[16]; BOOL IRQ_Requested[16]; ULONG BaseAddress[16]; // holds base address sent by dll USHORT LatchOffset[16]; // holds clear offset sent by dll UCHAR ClearOperation[16]; // holds operation sent by dll LPOVERLAPPED lpo[16]; // Pointer to overlapped structure HIRQ hIRQ[16]; VID IRQGENM_IRQ_Desc = {0,0,0,0,0,0,0,0,0}; /**************************************************************************** IRQGENM_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 IRQGENM_DeviceIOControl(DWORD dwService, DWORD dwDDB, DWORD hDevice, LPDIOC lpDIOCParms) { DWORD dwRetVal = 0; int i; switch(dwService) { case DIOC_OPEN: // same as DIOC_GETVERSION for (i=0; i<16; i++) IRQ_Hooked[i] = FALSE; dwRetVal = 0; break; case DIOC_CLOSEHANDLE: dwRetVal = IRQGENM_CleanUp(); break; case InitGenDriver: dwRetVal = IRQGENM_InitGenDriver(dwDDB, hDevice, lpDIOCParms); break; case DetectIRQ: dwRetVal = IRQGENM_DetectIRQ(dwDDB, hDevice, lpDIOCParms); break; case SendEOI: dwRetVal = IRQGENM_SendEOI(dwDDB, hDevice, lpDIOCParms); break; case Disconnect: dwRetVal = IRQGENM_DisconnectIRQ(dwDDB, hDevice, lpDIOCParms); break; case Abort: dwRetVal = IRQGENM_Abort(dwDDB, hDevice, lpDIOCParms); break; default: dwRetVal = ERROR_NOT_SUPPORTED; break; } return(dwRetVal); } DWORD _stdcall IRQGENM_SendEOI(DWORD dwDDB, DWORD hDevice, LPDIOC lpDIOCtl) { PULONG pBuffer; unsigned long IRQ; pBuffer = (PULONG)lpDIOCtl->lpvInBuffer; IRQ = *pBuffer; if (IRQ > 15) return ERROR_INVALID_PARAMETER; if (!IRQ_Hooked[IRQ]) return ERROR_NOT_SUPPORTED; VPICD_Phys_EOI(hIRQ[IRQ]); return(0); } DWORD _stdcall IRQGENM_Abort(DWORD dwDDB, DWORD hDevice, LPDIOC lpDIOCtl) { PULONG pBuffer; unsigned long IRQ; pBuffer = (PULONG)lpDIOCtl->lpvInBuffer; IRQ = *pBuffer; if (IRQ > 15) return ERROR_INVALID_PARAMETER; if (!IRQ_Requested[IRQ]) return ERROR_NOT_SUPPORTED; lpo[IRQ]->O_InternalHigh = 1; VWIN32_DIOCCompletionRoutine(lpo[IRQ]->O_Internal); MyPageUnlock((DWORD)lpo[IRQ], sizeof(OVERLAPPED)); IRQ_Requested[IRQ] = FALSE; return(0); } DWORD _stdcall IRQGENM_DisconnectIRQ(DWORD dwDDB, DWORD hDevice, LPDIOC lpDIOCtl) { PULONG pBuffer; unsigned long IRQ; pBuffer = (PULONG)lpDIOCtl->lpvInBuffer; IRQ = *pBuffer; if (IRQ > 15) return ERROR_INVALID_PARAMETER; if (IRQ_Hooked[IRQ]) VPICD_Force_Default_Behavior(hIRQ[IRQ]); if (IRQ_Requested[IRQ]) { lpo[IRQ]->O_InternalHigh = 1; VWIN32_DIOCCompletionRoutine(lpo[IRQ]->O_Internal); MyPageUnlock((DWORD)lpo[IRQ], sizeof(OVERLAPPED)); } IRQ_Hooked[IRQ] = IRQ_Requested[IRQ] = FALSE; return(0); } DWORD _stdcall IRQGENM_InitGenDriver(DWORD dwDDB, DWORD hDevice, LPDIOC lpDIOCtl) { PIRQGENM_INIT_DATA pBuffer; unsigned char IRQ; DWORD cbIn; ULONG WhichISR; pBuffer = (PIRQGENM_INIT_DATA)lpDIOCtl->lpvInBuffer; cbIn = lpDIOCtl->cbInBuffer; if (cbIn < sizeof(IRQGENM_INIT_DATA)) return ERROR_INVALID_PARAMETER; if ((IRQ = pBuffer->IRQ) > 15) return ERROR_INVALID_PARAMETER; if (IRQ_Hooked[IRQ]) VPICD_Force_Default_Behavior(hIRQ[IRQ]); BaseAddress[IRQ] = pBuffer->BaseAddress; LatchOffset[IRQ] = pBuffer->ClearOffset; ClearOperation[IRQ] = pBuffer->Operation; switch (IRQ) { case 1: WhichISR = (ULONG)&IRQGENM_ISR1; break; case 2: WhichISR = (ULONG)&IRQGENM_ISR2; break; case 3: WhichISR = (ULONG)&IRQGENM_ISR3; break; case 4: WhichISR = (ULONG)&IRQGENM_ISR4; break; case 5: WhichISR = (ULONG)&IRQGENM_ISR5; break; case 6: WhichISR = (ULONG)&IRQGENM_ISR6; break; case 7: WhichISR = (ULONG)&IRQGENM_ISR7; break; case 8: WhichISR = (ULONG)&IRQGENM_ISR8; break; case 9: WhichISR = (ULONG)&IRQGENM_ISR9; break; case 10: WhichISR = (ULONG)&IRQGENM_ISR10; break; case 11: WhichISR = (ULONG)&IRQGENM_ISR11; break; case 12: WhichISR = (ULONG)&IRQGENM_ISR12; break; case 13: WhichISR = (ULONG)&IRQGENM_ISR13; break; case 14: WhichISR = (ULONG)&IRQGENM_ISR14; break; case 15: WhichISR = (ULONG)&IRQGENM_ISR15; break; } IRQGENM_IRQ_Desc.VID_IRQ_Number = IRQ; IRQGENM_IRQ_Desc.VID_Hw_Int_Proc = WhichISR; IRQ_Occurred[IRQ] = IRQ_Requested[IRQ] = FALSE; hIRQ[IRQ] = VPICD_Virtualize_IRQ(&IRQGENM_IRQ_Desc); IRQ_Hooked[IRQ] = TRUE; VPICD_Physically_Unmask(hIRQ[IRQ]); return(0); } DWORD _stdcall IRQGENM_DetectIRQ(DWORD dwDDB, DWORD hDevice, LPDIOC lpDIOCtl) { PULONG pBuffer; unsigned char IRQ; pBuffer = (PULONG)lpDIOCtl->lpvInBuffer; IRQ = *pBuffer; if (IRQ > 15) return ERROR_INVALID_PARAMETER; *(PDWORD)(lpDIOCtl->lpcbBytesReturned) = 1; if (!lpDIOCtl->lpoOverlapped || !IRQ_Hooked[IRQ] || IRQ_Requested[IRQ]) return ERROR_NOT_SUPPORTED; lpo[IRQ] = (LPOVERLAPPED)lpDIOCtl->lpoOverlapped; if (IRQ_Occurred[IRQ]) { IRQ_Occurred[IRQ] = FALSE; *(PDWORD)(lpDIOCtl->lpcbBytesReturned) = 0; return(0); // This will make DeviceIOControl return synchronously } IRQ_Requested[IRQ] = TRUE; lpo[IRQ] = (LPOVERLAPPED)MyPageLock((DWORD)lpo[IRQ], sizeof(OVERLAPPED)); return(-1); // This will make DeviceIOControl return ERROR_IO_PENDING } DWORD _stdcall IRQGENM_CleanUp(void) { int i; for (i=0; i<16; i++) if (IRQ_Hooked[i]) { VPICD_Force_Default_Behavior(hIRQ[i]); if (IRQ_Requested[i]) MyPageUnlock((DWORD)lpo[i], sizeof(OVERLAPPED)); } return(VXD_SUCCESS); } DWORD _stdcall IRQGENM_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); } void _cdecl IRQGENM_ISR1(void) { unsigned short port; unsigned char val = 0; const unsigned char TheIRQ = 1; port = BaseAddress[TheIRQ] + LatchOffset[TheIRQ]; IRQ_Occurred[TheIRQ] = TRUE; switch (ClearOperation[TheIRQ]) { case WRITE_TO_CLEAR: _asm { mov dx, port mov al, val out dx, al } break; case READ_TO_CLEAR: _asm { mov dx,port in al,dx } break; } if (IRQ_Requested[TheIRQ]) { lpo[TheIRQ]->O_InternalHigh = 0; VWIN32_DIOCCompletionRoutine(lpo[TheIRQ]->O_Internal); MyPageUnlock((DWORD)lpo[TheIRQ], sizeof(OVERLAPPED)); IRQ_Occurred[TheIRQ] = FALSE; IRQ_Requested[TheIRQ] = FALSE; } } void _cdecl IRQGENM_ISR2(void) { unsigned short port; unsigned char val = 0; const unsigned char TheIRQ = 2; port = BaseAddress[TheIRQ] + LatchOffset[TheIRQ]; IRQ_Occurred[TheIRQ] = TRUE; switch (ClearOperation[TheIRQ]) { case WRITE_TO_CLEAR: _asm { mov dx, port mov al, val out dx, al } break; case READ_TO_CLEAR: _asm { mov dx,port in al,dx } break; } if (IRQ_Requested[TheIRQ]) { lpo[TheIRQ]->O_InternalHigh = 0; VWIN32_DIOCCompletionRoutine(lpo[TheIRQ]->O_Internal); MyPageUnlock((DWORD)lpo[TheIRQ], sizeof(OVERLAPPED)); IRQ_Occurred[TheIRQ] = FALSE; IRQ_Requested[TheIRQ] = FALSE; } } void _cdecl IRQGENM_ISR3(void) { unsigned short port; unsigned char val = 0; const unsigned char TheIRQ = 3; port = BaseAddress[TheIRQ] + LatchOffset[TheIRQ]; IRQ_Occurred[TheIRQ] = TRUE; switch (ClearOperation[TheIRQ]) { case WRITE_TO_CLEAR: _asm { mov dx, port mov al, val out dx, al } break; case READ_TO_CLEAR: _asm { mov dx,port in al,dx } break; } if (IRQ_Requested[TheIRQ]) { lpo[TheIRQ]->O_InternalHigh = 0; VWIN32_DIOCCompletionRoutine(lpo[TheIRQ]->O_Internal); MyPageUnlock((DWORD)lpo[TheIRQ], sizeof(OVERLAPPED)); IRQ_Occurred[TheIRQ] = FALSE; IRQ_Requested[TheIRQ] = FALSE; } } void _cdecl IRQGENM_ISR4(void) { unsigned short port; unsigned char val = 0; const unsigned char TheIRQ = 4; port = BaseAddress[TheIRQ] + LatchOffset[TheIRQ]; IRQ_Occurred[TheIRQ] = TRUE; switch (ClearOperation[TheIRQ]) { case WRITE_TO_CLEAR: _asm { mov dx, port mov al, val out dx, al } break; case READ_TO_CLEAR: _asm { mov dx,port in al,dx } break; } if (IRQ_Requested[TheIRQ]) { lpo[TheIRQ]->O_InternalHigh = 0; VWIN32_DIOCCompletionRoutine(lpo[TheIRQ]->O_Internal); MyPageUnlock((DWORD)lpo[TheIRQ], sizeof(OVERLAPPED)); IRQ_Occurred[TheIRQ] = FALSE; IRQ_Requested[TheIRQ] = FALSE; } } void _cdecl IRQGENM_ISR5(void) { unsigned short port; unsigned char val = 0; const unsigned char TheIRQ = 5; port = BaseAddress[TheIRQ] + LatchOffset[TheIRQ]; IRQ_Occurred[TheIRQ] = TRUE; switch (ClearOperation[TheIRQ]) { case WRITE_TO_CLEAR: _asm { mov dx, port mov al, val out dx, al } break; case READ_TO_CLEAR: _asm { mov dx,port in al,dx } break; } if (IRQ_Requested[TheIRQ]) { lpo[TheIRQ]->O_InternalHigh = 0; VWIN32_DIOCCompletionRoutine(lpo[TheIRQ]->O_Internal); MyPageUnlock((DWORD)lpo[TheIRQ], sizeof(OVERLAPPED)); IRQ_Occurred[TheIRQ] = FALSE; IRQ_Requested[TheIRQ] = FALSE; } } void _cdecl IRQGENM_ISR6(void) { unsigned short port; unsigned char val = 0; const unsigned char TheIRQ = 6; port = BaseAddress[TheIRQ] + LatchOffset[TheIRQ]; IRQ_Occurred[TheIRQ] = TRUE; switch (ClearOperation[TheIRQ]) { case WRITE_TO_CLEAR: _asm { mov dx, port mov al, val out dx, al } break; case READ_TO_CLEAR: _asm { mov dx,port in al,dx } break; } if (IRQ_Requested[TheIRQ]) { lpo[TheIRQ]->O_InternalHigh = 0; VWIN32_DIOCCompletionRoutine(lpo[TheIRQ]->O_Internal); MyPageUnlock((DWORD)lpo[TheIRQ], sizeof(OVERLAPPED)); IRQ_Occurred[TheIRQ] = FALSE; IRQ_Requested[TheIRQ] = FALSE; } } void _cdecl IRQGENM_ISR7(void) { unsigned short port; unsigned char val = 0; const unsigned char TheIRQ = 7; port = BaseAddress[TheIRQ] + LatchOffset[TheIRQ]; IRQ_Occurred[TheIRQ] = TRUE; switch (ClearOperation[TheIRQ]) { case WRITE_TO_CLEAR: _asm { mov dx, port mov al, val out dx, al } break; case READ_TO_CLEAR: _asm { mov dx,port in al,dx } break; } if (IRQ_Requested[TheIRQ]) { lpo[TheIRQ]->O_InternalHigh = 0; VWIN32_DIOCCompletionRoutine(lpo[TheIRQ]->O_Internal); MyPageUnlock((DWORD)lpo[TheIRQ], sizeof(OVERLAPPED)); IRQ_Occurred[TheIRQ] = FALSE; IRQ_Requested[TheIRQ] = FALSE; } } void _cdecl IRQGENM_ISR8(void) { unsigned short port; unsigned char val = 0; const unsigned char TheIRQ = 8; port = BaseAddress[TheIRQ] + LatchOffset[TheIRQ]; IRQ_Occurred[TheIRQ] = TRUE; switch (ClearOperation[TheIRQ]) { case WRITE_TO_CLEAR: _asm { mov dx, port mov al, val out dx, al } break; case READ_TO_CLEAR: _asm { mov dx,port in al,dx } break; } if (IRQ_Requested[TheIRQ]) { lpo[TheIRQ]->O_InternalHigh = 0; VWIN32_DIOCCompletionRoutine(lpo[TheIRQ]->O_Internal); MyPageUnlock((DWORD)lpo[TheIRQ], sizeof(OVERLAPPED)); IRQ_Occurred[TheIRQ] = FALSE; IRQ_Requested[TheIRQ] = FALSE; } } void _cdecl IRQGENM_ISR9(void) { unsigned short port; unsigned char val = 0; const unsigned char TheIRQ = 9; port = BaseAddress[TheIRQ] + LatchOffset[TheIRQ]; IRQ_Occurred[TheIRQ] = TRUE; switch (ClearOperation[TheIRQ]) { case WRITE_TO_CLEAR: _asm { mov dx, port mov al, val out dx, al } break; case READ_TO_CLEAR: _asm { mov dx,port in al,dx } break; } if (IRQ_Requested[TheIRQ]) { lpo[TheIRQ]->O_InternalHigh = 0; VWIN32_DIOCCompletionRoutine(lpo[TheIRQ]->O_Internal); MyPageUnlock((DWORD)lpo[TheIRQ], sizeof(OVERLAPPED)); IRQ_Occurred[TheIRQ] = FALSE; IRQ_Requested[TheIRQ] = FALSE; } } void _cdecl IRQGENM_ISR10(void) { unsigned short port; unsigned char val = 0; const unsigned char TheIRQ = 10; port = BaseAddress[TheIRQ] + LatchOffset[TheIRQ]; IRQ_Occurred[TheIRQ] = TRUE; switch (ClearOperation[TheIRQ]) { case WRITE_TO_CLEAR: _asm { mov dx, port mov al, val out dx, al } break; case READ_TO_CLEAR: _asm { mov dx,port in al,dx } break; } if (IRQ_Requested[TheIRQ]) { lpo[TheIRQ]->O_InternalHigh = 0; VWIN32_DIOCCompletionRoutine(lpo[TheIRQ]->O_Internal); MyPageUnlock((DWORD)lpo[TheIRQ], sizeof(OVERLAPPED)); IRQ_Occurred[TheIRQ] = FALSE; IRQ_Requested[TheIRQ] = FALSE; } } void _cdecl IRQGENM_ISR11(void) { unsigned short port; unsigned char val = 0; const unsigned char TheIRQ = 11; port = BaseAddress[TheIRQ] + LatchOffset[TheIRQ]; IRQ_Occurred[TheIRQ] = TRUE; switch (ClearOperation[TheIRQ]) { case WRITE_TO_CLEAR: _asm { mov dx, port mov al, val out dx, al } break; case READ_TO_CLEAR: _asm { mov dx,port in al,dx } break; } if (IRQ_Requested[TheIRQ]) { lpo[TheIRQ]->O_InternalHigh = 0; VWIN32_DIOCCompletionRoutine(lpo[TheIRQ]->O_Internal); MyPageUnlock((DWORD)lpo[TheIRQ], sizeof(OVERLAPPED)); IRQ_Occurred[TheIRQ] = FALSE; IRQ_Requested[TheIRQ] = FALSE; } } void _cdecl IRQGENM_ISR12(void) { unsigned short port; unsigned char val = 0; const unsigned char TheIRQ = 12; port = BaseAddress[TheIRQ] + LatchOffset[TheIRQ]; IRQ_Occurred[TheIRQ] = TRUE; switch (ClearOperation[TheIRQ]) { case WRITE_TO_CLEAR: _asm { mov dx, port mov al, val out dx, al } break; case READ_TO_CLEAR: _asm { mov dx,port in al,dx } break; } if (IRQ_Requested[TheIRQ]) { lpo[TheIRQ]->O_InternalHigh = 0; VWIN32_DIOCCompletionRoutine(lpo[TheIRQ]->O_Internal); MyPageUnlock((DWORD)lpo[TheIRQ], sizeof(OVERLAPPED)); IRQ_Occurred[TheIRQ] = FALSE; IRQ_Requested[TheIRQ] = FALSE; } } void _cdecl IRQGENM_ISR13(void) { unsigned short port; unsigned char val = 0; const unsigned char TheIRQ = 13; port = BaseAddress[TheIRQ] + LatchOffset[TheIRQ]; IRQ_Occurred[TheIRQ] = TRUE; switch (ClearOperation[TheIRQ]) { case WRITE_TO_CLEAR: _asm { mov dx, port mov al, val out dx, al } break; case READ_TO_CLEAR: _asm { mov dx,port in al,dx } break; } if (IRQ_Requested[TheIRQ]) { lpo[TheIRQ]->O_InternalHigh = 0; VWIN32_DIOCCompletionRoutine(lpo[TheIRQ]->O_Internal); MyPageUnlock((DWORD)lpo[TheIRQ], sizeof(OVERLAPPED)); IRQ_Occurred[TheIRQ] = FALSE; IRQ_Requested[TheIRQ] = FALSE; } } void _cdecl IRQGENM_ISR14(void) { unsigned short port; unsigned char val = 0; const unsigned char TheIRQ = 14; port = BaseAddress[TheIRQ] + LatchOffset[TheIRQ]; IRQ_Occurred[TheIRQ] = TRUE; switch (ClearOperation[TheIRQ]) { case WRITE_TO_CLEAR: _asm { mov dx, port mov al, val out dx, al } break; case READ_TO_CLEAR: _asm { mov dx,port in al,dx } break; } if (IRQ_Requested[TheIRQ]) { lpo[TheIRQ]->O_InternalHigh = 0; VWIN32_DIOCCompletionRoutine(lpo[TheIRQ]->O_Internal); MyPageUnlock((DWORD)lpo[TheIRQ], sizeof(OVERLAPPED)); IRQ_Occurred[TheIRQ] = FALSE; IRQ_Requested[TheIRQ] = FALSE; } } void _cdecl IRQGENM_ISR15(void) { unsigned short port; unsigned char val = 0; const unsigned char TheIRQ = 15; port = BaseAddress[TheIRQ] + LatchOffset[TheIRQ]; IRQ_Occurred[TheIRQ] = TRUE; switch (ClearOperation[TheIRQ]) { case WRITE_TO_CLEAR: _asm { mov dx, port mov al, val out dx, al } break; case READ_TO_CLEAR: _asm { mov dx,port in al,dx } break; } if (IRQ_Requested[TheIRQ]) { lpo[TheIRQ]->O_InternalHigh = 0; VWIN32_DIOCCompletionRoutine(lpo[TheIRQ]->O_Internal); MyPageUnlock((DWORD)lpo[TheIRQ], sizeof(OVERLAPPED)); IRQ_Occurred[TheIRQ] = FALSE; IRQ_Requested[TheIRQ] = FALSE; } } #pragma VxD_ICODE_SEG #pragma VxD_IDATA_SEG DWORD _stdcall IRQGENM_Dynamic_Init(void) { return(VXD_SUCCESS); }