📄 comem.c
字号:
//////////////////////////////////////////////////////////////////////
//
// File: comem.c
// $Archive: /ComemL/Host/Driver/Win98/comem.c $
//
// Purpose:
// main module for VxD COMEM, the Win 95 driver for the 3041 co-mem
//
// Environment:
// kernel mode
//
// $Author: Stevek $
//
// $History: comem.c $
//
// ***************** Version 16 *****************
// User: Stevek Date: 11/11/98 Time: 9:40a
// Updated in $/ComemL/Host/Driver/Win98
// Fixed problem with create lin ptr, which would only return a pointer to
// the first block correctly.
//
// ***************** Version 15 *****************
// User: Stevek Date: 10/23/98 Time: 5:06p
// Updated in $/ComemL/Host/Driver/Win98
// Still untested, compiling and linking.
//
// ***************** Version 14 *****************
// User: Stevek Date: 10/23/98 Time: 4:58p
// Updated in $/ComemL/Host/Driver/Win98
// Fixed more lite stuff, still not tested
//
// ***************** Version 13 *****************
// User: Stevek Date: 10/23/98 Time: 4:38p
// Updated in $/ComemL/Host/Driver/Win98
// Untested lite changes
//
// ***************** Version 12 *****************
// User: Stevek Date: 8/26/98 Time: 2:32p
// Updated in $/ComemL/Host/Driver/Win98
// Fixed problem where the ISR was clearing the interrupt mask as well as
// the interrupt.
//
// ***************** Version 11 *****************
// User: Stevek Date: 8/26/98 Time: 2:12p
// Updated in $/ComemL/Host/Driver/Win98
// Fixed lite interrupt handling.
//
// This breaks the page table. Do not use the page table for anything bug
// debug.
//
// ***************** Version 9 *****************
// User: Stevek Date: 5/29/98 Time: 9:53a
// Updated in $/Comem/Win 95 driver
// Expanded BAR0 range to allow for the 32K space needed by lite.
//
// ***************** Version 8 *****************
// User: Stevek Date: 12/03/97 Time: 10:12a
// Updated in $/Comem/Win 95 driver
// Added reference count
// Fixed bug in deallocation
//
// ***************** Version 7 *****************
// User: Stevek Date: 10/22/97 Time: 12:35p
// Updated in $/Comem/Win 95 driver
// Added file header to all files
//
// Copyright (c) 1997 Anchor Chips, Inc. May not be reproduced without
// permission. See the license agreement for more details.
//
//////////////////////////////////////////////////////////////////////
#define DEVICE_MAIN
#include <vtoolsc.h>
#include <vtoolsd.h>
#include "comemdrv.h"
#undef DEVICE_MAIN
#include "comemlif.h"
#include <vmm.h>
#ifdef DEBUG
#define DPRINTF0(buf, fmt ) _Sprintf(buf, fmt ); Out_Debug_String( buf )
#define DPRINTF1(buf, fmt, arg1) _Sprintf(buf, fmt, arg1 ); Out_Debug_String( buf )
#define DPRINTF2(buf, fmt, arg1, arg2) _Sprintf(buf, fmt, arg1, arg2 ); Out_Debug_String( buf )
#else
#define DPRINTF0(buf, fmt)
#define DPRINTF1(buf, fmt, arg1)
#define DPRINTF2(buf, fmt, arg1, arg2)
#endif
//////////////////////////////////////////////////////////////////////
//
// Local Structure definitions start
typedef struct
comemMemblockStruct {
DWORD linearAddr;
DWORD physAddr;
DWORD size;
struct comemMemblockStruct *next;
} comemMemblock;
typedef struct
{
comemMemblock *allocatedBlocks;
DWORD fragCount;
DWORD linBAR[COMEM_MAX_BARS];
DEVNODE devNode;
PCI_CONFIG_HEADER_0 pcicfg;
IRQHANDLE IRQHandle; // Handle for virtual IRQ
} comemDevStruct;
comemDevStruct *comemDev[COMEM_MAX_DEVICES] = { 0 };
DWORD referenceCount = 0;
//
// Local Structure definitions end
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//
// Local function definitions
//
BOOL __stdcall COMEMInt_Handler(VMHANDLE hVM, IRQHANDLE hIRQ, DWORD refData);
VOID __stdcall ComemEventService(VMHANDLE hVM, PVOID Refdata, PCLIENT_STRUCT pRegs);
DWORD Assign_Linear_To_BARs(PCI_CONFIG_HEADER_0* pcicfg, DWORD comemID);
comemDevStruct * comemDevStructConstructor();
void comemDevStructDestructor(comemDevStruct * ptr);
CONFIGRET SetPCIConfigData(
DEVNODE Devnode,
DWORD StartByteOffset,
DWORD* ConfigDataBuffer,
ULONG nBytes);
CONFIGRET GetPCIConfigData(
DEVNODE Devnode,
DWORD StartByteOffset,
DWORD* ConfigDataBuffer,
ULONG nBytes);
void COMEM_Get_Status(PIOCTLPARAMS);
DWORD COMEM_Get_Version();
void COMEM_Get_PCICfg( PIOCTLPARAMS p );
void COMEM_Set_PCICfg( PIOCTLPARAMS p );
void COMEM_DeallocMemory(PIOCTLPARAMS p );
void COMEM_CreateLinPtr(PIOCTLPARAMS p);
void COMEM_DestroyLinPtr(PIOCTLPARAMS p );
void COMEM_CreateBarPtr(PIOCTLPARAMS p);
void COMEM_DestroyBarPtr(PIOCTLPARAMS p);
void COMEM_AllocContigMemory( PIOCTLPARAMS p );
void COMEM_DeallocContigMemory( PIOCTLPARAMS p );
CONFIGRET CM_HANDLER ConfigHandler(CONFIGFUNC cfFuncName, SUBCONFIGFUNC scfSubFuncName, DEVNODE dnToDevNode, DWORD dwRefData, ULONG ulFlags);
CONFIGRET ProcessConfigStart( DEVNODE devnode, void *p );
CONFIGRET ProcessConfigStop( DEVNODE devnode, void *p );
//
// Local function definitions end
//////////////////////////////////////////////////////////////////////
Declare_Virtual_Device(COMEM)
VPICD_HWInt_THUNK ComemIntThunk; // Thunk for interrupt handler
Event_THUNK ComemEventThunk; // Thunk for hour event handler
/////////////////////////////////////////////////////////////////////////////
// Doesn't do anything. All initialization is done in OnPnpNewDevnode()
/////////////////////////////////////////////////////////////////////////////
BOOL OnSysDynamicDeviceInit()
{
return TRUE;
}
//////////////////////////////////////////////////////////////////////
//
// Called when the VxD is going away. We must free everything we
// have allocated or we are leaking memory.
//
//////////////////////////////////////////////////////////////////////
BOOL OnSysDynamicDeviceExit()
{
int comemID;
// TBD -- have to free the memory allocated to the BARs too
for (comemID = 0; comemID < COMEM_MAX_DEVICES; comemID++ )
if (comemDev[comemID])
{
comemDevStructDestructor(comemDev[comemID]);
comemDev[comemID] = 0;
}
return TRUE;
}
void comemDevStructDestructor(comemDevStruct * ptr)
{
int i;
if (ptr)
{
for (i = 0; i < COMEM_MAX_BARS; i++)
{
if (ptr->linBAR[i])
_PageFree(ptr->linBAR[i], 0);
// Don't have to set linBAR to 0 because we're going to free this puppy
}
_HeapFree(ptr, 0);
}
}
// Return the linear page table address and the
// physical page table address to the user.
void COMEM_Get_Status(PIOCTLPARAMS p)
{
GetStatusOut *outPtr = p->dioc_OutBuf;
GetStatusIn *inptr = p->dioc_InBuf;
DWORD comemID = inptr->comemID;
int i;
if (inptr->comemID > COMEM_MAX_DEVICES)
{
*p->dioc_bytesret = 4;
outPtr->status = ERROR_INVALID_COMEM_ID;
return;
}
if (!comemDev[inptr->comemID])
{
*p->dioc_bytesret = 4;
outPtr->status = ERROR_INVALID_COMEM_ID;
return;
}
// set # of returned bytes
*p->dioc_bytesret = sizeof(GetStatusOut);
outPtr->status = NO_ERROR;
outPtr->referenceCount = referenceCount;
}
DWORD _cdecl COMEM_Get_Version()
{
return (COMEM_Major << 8) | COMEM_Minor;
}
DefineControlHandler(SYS_DYNAMIC_DEVICE_INIT, OnSysDynamicDeviceInit);
DefineControlHandler(SYS_DYNAMIC_DEVICE_EXIT, OnSysDynamicDeviceExit);
DefineControlHandler(W32_DEVICEIOCONTROL, OnW32Deviceiocontrol);
DefineControlHandler(PNP_NEW_DEVNODE, OnPnpNewDevnode);
BOOL __cdecl ControlDispatcher(
DWORD dwControlMessage,
DWORD EBX,
DWORD EDX,
DWORD ESI,
DWORD EDI,
DWORD ECX)
{
START_CONTROL_DISPATCH
ON_SYS_DYNAMIC_DEVICE_INIT(OnSysDynamicDeviceInit);
ON_SYS_DYNAMIC_DEVICE_EXIT(OnSysDynamicDeviceExit);
ON_W32_DEVICEIOCONTROL(OnW32Deviceiocontrol);
ON_PNP_NEW_DEVNODE(OnPnpNewDevnode);
END_CONTROL_DISPATCH
return TRUE;
}
// Catches IOCTL messages sent to the VxD. Calls the four functions below:
DWORD OnW32Deviceiocontrol(PIOCTLPARAMS p)
{
switch (p->dioc_IOCtlCode)
{
case DIOC_OPEN:
referenceCount++;
return DEVIOCTL_NOERROR;
case DIOC_CLOSEHANDLE:
referenceCount--;
return DEVIOCTL_NOERROR;
case IOCTL_COMEM_GETSTATUS:
COMEM_Get_Status( p );
return DEVIOCTL_NOERROR;
case IOCTL_COMEM_GETVERSION:
COMEM_Get_Version( p );
return DEVIOCTL_NOERROR;
case IOCTL_COMEM_GETPCICFG:
COMEM_Get_PCICfg( p );
return DEVIOCTL_NOERROR;
case IOCTL_COMEM_SETPCICFG:
COMEM_Set_PCICfg( p );
return DEVIOCTL_NOERROR;
case IOCTL_COMEM_DEALLOCCONTIGMEM:
COMEM_DeallocContigMemory( p );
return DEVIOCTL_NOERROR;
case IOCTL_COMEM_ALLOCCONTIGMEM:
COMEM_AllocContigMemory( p );
return DEVIOCTL_NOERROR;
case IOCTL_COMEM_CREATEBARPTR:
COMEM_CreateBarPtr( p );
return DEVIOCTL_NOERROR;
case IOCTL_COMEM_DESTROYBARPTR:
COMEM_DestroyBarPtr( p );
return DEVIOCTL_NOERROR;
case IOCTL_COMEM_CREATELINPTR:
COMEM_CreateLinPtr( p );
return DEVIOCTL_NOERROR;
case IOCTL_COMEM_DESTROYLINPTR:
COMEM_DestroyLinPtr( p );
return DEVIOCTL_NOERROR;
}
return 0;
}
#define in(data, low, hi) (data >= low && data < hi)
#define overlap(addr, len, addr2, len2) (in(addr, addr2, addr2 + len2) || in(addr+len-1, addr2, addr2 + len2) || in(addr2, addr, addr+len) || in(addr2 + len2 - 1, addr, addr+len))
// Assign linear addresses to the BARs
// TBD -- need to detect if they are already assigned!
DWORD Assign_Linear_To_BARs(PCI_CONFIG_HEADER_0* pcicfg, DWORD comemID)
{
const int len[COMEM_MAX_BARS] =
{
8,1,8,0
};
int i;
for (i = 0; i < COMEM_MAX_BARS && len[i]; i++ )
{
// In win95 it is ok (actually, it's necessary to allow multiple calls to this.
// If two tasks want to talk to the same co-mem, they both need linear pointers.
// The flip side of this is that the destroy call cannot do anything in W95. The
// pointers live until the vxd is stopped.
if (comemDev[comemID]->linBAR[i])
return NO_ERROR;
comemDev[comemID]->linBAR[i] = (DWORD) _PageReserve(PR_SHARED, // page type
len[i], // npages,
0); // flags (PR_FIXED, PR_STATIC or PR_4MEG)
if (comemDev[comemID]->linBAR[i] == -1)
return ERROR_MEMORY_ALLOC;
if (!_PageCommitPhys(comemDev[comemID]->linBAR[i]/PAGE_SIZE, len[i], pcicfg->BaseAddresses[i]/PAGE_SIZE, PC_INCR | PC_USER | PC_WRITEABLE))
return ERROR_MEMORY_ALLOC;
if (!_LinPageLock(comemDev[comemID]->linBAR[i]/PAGE_SIZE, len[i], 0 /* Flags */))
return ERROR_MEMORY_ALLOC;
// Now OR in the bits that could exist in the physical address that are below a page boundary
comemDev[comemID]->linBAR[i] |= pcicfg->BaseAddresses[i] & 0xff0;
}
// The last one is in i/o space. No translation
comemDev[comemID]->linBAR[3] = pcicfg->BaseAddresses[i] & 0xfffc;
return(NO_ERROR);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -