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

📄 comem.c

📁 The Lite Evaluation/Demonstration Kit is intended to illustrate use of the AN3042. The AN3042 is c
💻 C
📖 第 1 页 / 共 3 页
字号:
//////////////////////////////////////////////////////////////////////
CONFIGRET GetPCIConfigData(
	DEVNODE Devnode, 
	DWORD 	StartByteOffset, 
	DWORD* 	ConfigDataBuffer, 
	ULONG 	nBytes)
{
	return 
		CONFIGMG_Call_Enumerator_Function(
			Devnode, 
			PCI_ENUM_FUNC_GET_DEVICE_INFO,
			StartByteOffset,
			ConfigDataBuffer,
			nBytes,
			0);
}

//////////////////////////////////////////////////////////////////////
CONFIGRET SetPCIConfigData(
	DEVNODE Devnode, 
	DWORD 	StartByteOffset, 
	DWORD* 	ConfigDataBuffer, 
	ULONG 	nBytes)
{
	return 
		CONFIGMG_Call_Enumerator_Function(
			Devnode, 
			PCI_ENUM_FUNC_SET_DEVICE_INFO,
			StartByteOffset,
			ConfigDataBuffer,
			nBytes,
			0);
}


// Create an entry for the comemDev array.
// Returns:
//    Pointer to allocated memory, NULL if couldn't allocate.
comemDevStruct * comemDevStructConstructor()
{
	int i;
   comemDevStruct *retPtr = _HeapAllocate(sizeof(comemDevStruct), HEAPZEROINIT);

   if (!retPtr)
      return(retPtr);
      

	// Initialize our variables
    // retPtr->fragCount = 0;   done by HEAPZEROINIT
	// retPtr->allocatedBlocks = NULL;  done by HEAPZEROINIT
	// retPtr->linBAR[xx] = NULL; done by HEAPZEROINIT
   return(retPtr);
}



// Return the PCI config block for the specified device
void COMEM_Get_PCICfg( PIOCTLPARAMS p )
{
   WORD DeviceId;
   WORD VendorId;
   DWORD comemID;
   DEVNODE dn[COMEM_MAX_DEVICES];
   CONFIGRET status;
   PCI_CONFIG_HEADER_0 *pcicfg;
   int count;

	GetPciCfgIn *inptr  = p->dioc_InBuf;
	GetPciCfgOut *outptr  = p->dioc_OutBuf;

   comemID = inptr->ComemId;

   pcicfg = (PCI_CONFIG_HEADER_0*)p->dioc_OutBuf;

   *p->dioc_bytesret = 0;

   if (comemID > COMEM_MAX_DEVICES)
     {
		outptr->status =  ERROR_INVALID_COMEM_ID;
      return;
     }

   if (!comemDev[comemID])
     {
		outptr->status =  ERROR_INVALID_COMEM_ID;
      return;
     }


  	status = GetPCIConfigData(comemDev[comemID]->devNode, 0, (ULONG*)pcicfg, sizeof(PCI_CONFIG_HEADER_0));
   if (status != CR_SUCCESS)
     {
      comemDev[comemID]->pcicfg.VendorID = comemDev[comemID]->pcicfg.DeviceID = 0;
      outptr->status = ERROR_DEVICE_NOT_FOUND;
      return;
     }
   else
     {
     *p->dioc_bytesret = sizeof(GetPciCfgOut);
     memcpy(&comemDev[comemID]->pcicfg, pcicfg, sizeof(PCI_CONFIG_HEADER_0));
     }

	outptr->status =  NO_ERROR;
}



// Return the PCI config block for the specified device
void COMEM_Set_PCICfg( PIOCTLPARAMS p )
{
	SetPciCfgIn *inptr  = p->dioc_InBuf;
	SetPciCfgOut *outptr  = p->dioc_OutBuf;

   DWORD comemID;
   DEVNODE dn[COMEM_MAX_DEVICES];
   CONFIGRET status;
   PCI_CONFIG_HEADER_0 *pcicfg;
   int count;

   comemID = ((SetPciCfgIn*)(p->dioc_InBuf))->ComemID;

   pcicfg = (PCI_CONFIG_HEADER_0*)p->dioc_InBuf;

   *p->dioc_bytesret = 4;

   if (comemID > COMEM_MAX_DEVICES)
     {
      *p->dioc_bytesret = 4;
		outptr->status =  ERROR_INVALID_COMEM_ID;
      return;
     }

   if (!comemDev[comemID])
     {
      *p->dioc_bytesret = 4;
		outptr->status =  ERROR_INVALID_COMEM_ID;
      return;
     }

 	status = SetPCIConfigData(comemDev[comemID]->devNode, 0, (ULONG*)pcicfg, sizeof(PCI_CONFIG_HEADER_0));
	if (status != CR_SUCCESS)
	  {
      comemDev[comemID]->pcicfg.VendorID = comemDev[comemID]->pcicfg.DeviceID = 0;
	  }

	outptr->status =  NO_ERROR;
}



void COMEM_CreateBarPtr(PIOCTLPARAMS p)
{
   int i;
   DWORD comemID;
   DWORD status;
   PCI_CONFIG_HEADER_0 pcicfg;

   CreateBarPtrIn  *inptr = p->dioc_InBuf;
   CreateBarPtrOut *outptr = p->dioc_OutBuf;
   comemID = inptr->comemID;

   if (comemID > COMEM_MAX_DEVICES)
		{
		*p->dioc_bytesret = 4;
		outptr->status =  ERROR_INVALID_COMEM_ID;
		return;
		}

   if (!comemDev[comemID])
		{
		*p->dioc_bytesret = 4;
		outptr->status =  ERROR_INVALID_COMEM_ID;
		return;
		}

  	status = GetPCIConfigData(comemDev[comemID]->devNode, 0, (ULONG*)&pcicfg, sizeof(PCI_CONFIG_HEADER_0));
   if (status != CR_SUCCESS)
     {
      comemDev[comemID]->pcicfg.VendorID = comemDev[comemID]->pcicfg.DeviceID = 0;
      outptr->status = ERROR_DEVICE_NOT_FOUND;
      return;
     }
   *p->dioc_bytesret = sizeof(CreateBarPtrOut);
   outptr->status = Assign_Linear_To_BARs(&pcicfg, comemID);
   for (i = 0; i < COMEM_MAX_BARS; i++ )
     {
     outptr->linBAR[i] = comemDev[comemID]->linBAR[i];
     }
	outptr->linPage  = 0;
	outptr->physPage = 0;
}


// In win95 it is ok (actually, it's necessary to allow multiple calls to createBarPtr.
// 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.
void COMEM_DestroyBarPtr( PIOCTLPARAMS p )
{
   int i;
	DestroyBarPtrIn  *inptr   = p->dioc_InBuf;
	DestroyBarPtrOut *outptr  = p->dioc_OutBuf;
	*p->dioc_bytesret = 4;
	outptr->status =  NO_ERROR;

   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;
		}
}

// Function
// 	OnDeviceInit - Handler for DEVICE_INIT control message
//
// Input
//	hSysVM		Handle of system virtual machine
//	CommandTail	Pointer to Windows command line
//
// Remarks
//	This routine is responsible for hooking the PCI
//	interrupt and configuring it.
//
// Returns
//	Returns TRUE if successfully initialized
//
BOOL installIRQHandler(DWORD comemID)
{
	BYTE statreg;
	DWORD status;

// Hooking a hardware interrupt requires calling the Virtual Programmable
// Interrupt Controlloer Device (VPICD), to inform that this VxD will
// be responsible for the IRQ. VPICD provides five different notifications
// of events related to the IRQ, but this VxD uses only one of them, namely,
// that of the actual hardware interrupt event. The VPICD_Virtualize_IRQ
// call takes one parameter which points to a structure containing the
// address of this VxD's hardware interrupt handler, along with additional
// information related to the IRQ.

	struct VPICD_IRQ_Descriptor IRQdesc;	// struct to pass to
				    		// VPICD_Virtualize_IRQ

// Set up the structure to pass to VPICD_Virtualize_IRQ

	IRQdesc.VID_IRQ_Number = comemDev[comemID]->pcicfg.InterruptLine;	// IRQ to virtualize
	IRQdesc.VID_Options = VPICD_OPT_CAN_SHARE;		// Allow IRQ sharing

// To set the address of the our handler in the structure that will be
// passed to VPICD_Virtualize_IRQ, we pass the address of the handler's
// thunk to VPICD_Thunk_HWInt, which initializes the thunk and returns
// its address.

	IRQdesc.VID_Hw_Int_Proc =		// set address of handler
		(DWORD)VPICD_Thunk_HWInt_Ex(COMEMInt_Handler, &ComemIntThunk);

// The other callbacks are not used.

	IRQdesc.VID_EOI_Proc = 0;
	IRQdesc.VID_Virt_Int_Proc = 0;
	IRQdesc.VID_Mask_Change_Proc = 0;
	IRQdesc.VID_IRET_Proc = 0;

	IRQdesc.VID_IRET_Time_Out = 500;
	IRQdesc.VID_Hw_Int_Ref = comemDev[comemID];
	IRQdesc.VID_Options |= VPICD_OPT_REF_DATA;

// Now pass the structure to VPICD. VPICD returns the IRQ handle.

	comemDev[comemID]->IRQHandle = VPICD_Virtualize_IRQ(&IRQdesc);
	if (comemDev[comemID]->IRQHandle == 0)
		return FALSE;			// failed to virtualize

// Make sure the IRQ is unmasked on the PIC. Otherwise, the interrupt
// will never occur.

	VPICD_Physically_Unmask(comemDev[comemID]->IRQHandle);

	return TRUE;				// initialized successfully
}


// Function
// 	COMEMInt_Handler - handler for VID_Hw_Int callback
//
// Input
//	hVM		handle of current virtual machine
//	hIRQ		handle of this virtualized IRQ
//
// Remarks
//	VPICD invokes this routine (via the thunk) when the COMEM
//	interrupt (IRQ 8) occurrs.
//
BOOL __stdcall COMEMInt_Handler(VMHANDLE hVM, IRQHANDLE hIRQ, DWORD devPtr)
{
   int i;
   BOOL retval = FALSE;
   static DWORD counter[0x10] = 
     {
     0
     };

   DWORD comemID;
   DWORD scrap32;

  if ((comemDevStruct *)devPtr)
    {
     if (((comemDevStruct *)devPtr)->linBAR[0])
       {
	   DWORD * hintPtr = ((DWORD *)(((comemDevStruct *)devPtr)->linBAR[0])) + ADDR_HINT/sizeof(DWORD);

       // Read the interrupts that we have received via BAR0
       scrap32 = *hintPtr;

       if (scrap32 & 0x3ff)
         retval = TRUE;

       // Clear the active interrupts
       *hintPtr |= scrap32 & 0x3ff;
       
       // Count the interrupts received
       for (i = 0; i < 0x10; i++)
         {
         if (scrap32 & 1)
            counter[i]++;
         scrap32 >>= 1;
         }
       }

    Call_Global_Event(ComemEventService,
	      (PVOID)devPtr, &ComemEventThunk);
    }

   if (retval)
   	VPICD_Phys_EOI(hIRQ);		// tell VPICD to clear the interrupt

	return retval;	    		// Tell VPICD that it wasn't our interrupt -- we're sitting on someone else's
}

// Function
// 	ComemEventService - handler for hour event
//
// Input
//	hVM		handle of current VM
//	Refdata		not used
//	pRegs		pointer to client register structure
//
// Remarks
//	This routine is the handler for the event scheduled by the interrupt
//	handler. It is called on a co-mem interrupt.  If you wish to add
// interrupt processing in the VxD, do it here, not in the ISR.  The ISR
// cannot use most of the windows library functions, since they are not
// re-entrant.
//
VOID __stdcall ComemEventService(VMHANDLE hVM, PVOID Refdata, PCLIENT_STRUCT pRegs)
{
   // Dummy routine -- we could service it here, or post an event to Ring 3
   // using TBD method.
}


CONFIGRET OnPnpNewDevnode(DEVNODE Node, DWORD LoadType)
{
	CONFIGRET	rc;
   CONFIGRET status;

	switch (LoadType) 
	{

		case DLVXD_LOAD_DRIVER:
		  {
         int comemID = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -