⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 comem.c

📁 The Lite Evaluation/Demonstration Kit is intended to illustrate use of the AN3042. The AN3042 is c
💻 C
📖 第 1 页 / 共 3 页
字号:
//////////////////////////////////////////////////////////////////////
//
// 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 + -