Listing 3
/// VANYDEVDc.c
// --------------------------------------------
// Dynamically loadable VxD for ANYDEV board
// --------------------------------------------
#define WIN32_LEAN_AND_MEAN // Excludes un-needed parts of windows.h
#include "windows.h"
#include <e:\ddk95\inc32\vmm.h>
#include <e:\ddk95\inc32\vwin32.h>
#include <e:\ddk95\inc32\debug.h>
#include "VANYDEVD.H"
// -------------------------------------
// Externs defined in assembly module
// -------------------------------------
// These defined in assembly for the VMM.INC or VPICD.INC file inclusion
extern DWORD GET_BD_MEM(void);
extern DWORD Virt_IRQ(void);
extern DWORD Get_IRQ_Status(void);
extern void UNVirt_IRQ(DWORD IRQhandle);
extern void End_ISR(DWORD IRQhandle);
extern void Physically_Mask_IRQ(DWORD IRQhandle);
extern void Physically_UNMask_IRQ(DWORD IRQhandle);
// ------------------------
// PRAGMA for this DATA
// ------------------------
// Establish segment
#pragma data_seg ( "_LDATA","_LCODE")
// ------------------------------------
// Data structures MUST be INITIALIZED
// ------------------------------------
ADEV ANYDEVX = {0}; // Main structure for ANYDEV -- shared by app
// ------------------------
// PRAGMAS for this CODE
// ------------------------
// Establish segment
#pragma code_seg ( "_LTEXT", "_LCODE" )
//No stack checking for routines in this module
#pragma check_stack(off)
// ----------------
// Disable hardware
// ----------------
void Disable_AnyDev(void)
{
//This would likely be a port WRITE to DISABLE the board's interrupt
}
// ----------------
// Enable hardware
// ----------------
void Enable_AnyDev(void)
{
//This would likely be a port WRITE to ENABLE the board's interrupt
}
// --------------------------
// ISR Processing for ANYDEV
// --------------------------
void Process_ISR(void)
{
//This is where the user might SET FLAGS and indicators in the ANYDEVX structure
//in order to notify the application that data is available below 1MB
}
// -----------------
// ISR for ANYDEV
// -----------------
void _declspec(naked)ISR_ANYDEV(void)
{
// Save registers
_asm sti
_asm pushad
_asm pushfd
//Process the ISR
Process_ISR();
//End ISR
_asm clc
End_ISR(ANYDEVX.IRQhandle);
//Set GOOD return code
_asm clc
//Restore saved registers
_asm popfd
_asm popad
_asm ret;
}
// -------------------
// Virtualize the IRQ
// -------------------
DWORD CVirt_IRQ(void)
{
// If in use by an instance of this program, RETURN with BAD code
if (ANYDEVX.IRQcount)
return (BOGUSADDRESS);
// If in use by another program, RETURN with BAD code
ANYDEVX.IRQstatus = Get_IRQ_Status();
if (ANYDEVX.IRQstatus)
return (BOGUSADDRESS);
// If IRQ NOT in use this point is reached
// Set BAD return code
ANYDEVX.IRQhandle = BOGUSADDRESS;
// Disable ANYDEV hardware
Disable_AnyDev();
// Get global memory address below 1mb
ANYDEVX.Global_addr_1MB = GET_BD_MEM();
if (ANYDEVX.Global_addr_1MB != BOGUSADDRESS)
{
// Virtualize the IRQ
ANYDEVX.IRQhandle = Virt_IRQ();
if (ANYDEVX.IRQhandle != BOGUSADDRESS)
{
// unmask the IRQ, set OK flag & increment IRQ count
Physically_UNMask_IRQ(ANYDEVX.IRQhandle);
ANYDEVX.IRQflags |= IRQ_VIRT_OK;
++(ANYDEVX.IRQcount);
}
}
return(ANYDEVX.IRQhandle);
}
// ----------------------
// UN Virtualize the IRQ
// ----------------------
void CUNVirt_IRQ(DWORD IRQhandle)
{
// if IRQ has been successfully virtualized
if ((ANYDEVX.IRQhandle != 0)
&& (ANYDEVX.IRQhandle != BOGUSADDRESS))
{
// Physically mask the IRQ and UN virtualized it
Physically_Mask_IRQ(ANYDEVX.IRQhandle);
UNVirt_IRQ(ANYDEVX.IRQhandle);
}
// Set UNvirtualized flags and indicators
ANYDEVX.IRQhandle = BOGUSADDRESS;
ANYDEVX.IRQflags &= ~IRQ_VIRT_OK;
return;
}
// ---------------------------------------
// Set Good Return code for DIOC requests
// ---------------------------------------
void _declspec(naked)GoodReturnDIOC(void)
{
// Clear eax and carry flag for GOOD return
_asm xor eax,eax
_asm clc
_asm ret;
}
// ---------------------------------------
// Set Bad Return code for DIOC requests
// ---------------------------------------
void _declspec(naked) BadReturnDIOC(void)
{
// NOTE: 50 is a FCN NOT SUPPORTED code -- ok to use
// SET carry flag for BAD return
_asm mov eax,50
_asm stc
_asm ret;
}
// ------------------------------
// Routine for ANYDEV Device UNINIT
// ------------------------------
void CVANYDEVD_Device_UNInit()
{
// Disable ANYDEV, Unvirtualize IRQ, set GOOD return code
Disable_AnyDev();
CUNVirt_IRQ(ANYDEVX.IRQhandle);
GoodReturnDIOC();
return;
}
// ------------------------------
// Routine for ANYDEV Device INIT
// ------------------------------
void CVANYDEVD_Device_Init()
{
DWORD retcode;
// Try to virtualize the IRQ
retcode = CVirt_IRQ();
// Set GOOD or BAD return code based on success
if (retcode == BOGUSADDRESS)
BadReturnDIOC();
else
GoodReturnDIOC();
return;
}
// --------------------------------
// Routine for ANYDEV Device IO ctrl
// --------------------------------
void CVANYDEVD_Device_IOctrl(PDIOCPARAMETERS ptr)
{
DWORD *obuf1;
// Field the DEV IO requests from VMM
switch(ptr->dwIoControlCode)
{
case(VANYDEVD_INIT_ADEV_HARDWARE):
ANYDEVX.flags = 0;
//User likely to require other initialization here
break;
case(VANYDEVD_GRAB_ADDRESSES):
// Point to Output buffer
obuf1 = (DWORD *) ptr->lpvOutBuffer;
// Return GLOBAL 1MB addr, addr of data structure
// and return indicators of IRQ virtuaization request
*obuf1 = ANYDEVX.Global_addr_1MB;
*(obuf1+1) = (DWORD) &ANYDEVX;
*(obuf1+2) = (DWORD) ANYDEVX.IRQhandle;
*(obuf1+3) = (DWORD) ANYDEVX.IRQflags;
//User might want to return other/different values here
break;
case(VANYDEVD_ENABLE_ANYDEV_HDWR):
//Call routine to enable interrupt
Enable_AnyDev();
break;
case(VANYDEVD_DISABLE_ANYDEV_HWR):
//Call routine to disable interrupt
Disable_AnyDev();
break;
//The below DIOC_GETVERSION is a part of the dynamic load protocol
//It MUST return a GOOD code (all codes here use GoodReturnDIOC()
case(DIOC_GETVERSION):
case(DIOC_CLOSEHANDLE):
default:
break;
}
GoodReturnDIOC();
return;
}