comem.c

来自「The Lite Evaluation/Demonstration Kit is」· C语言 代码 · 共 1,140 行 · 第 1/3 页

C
1,140
字号
         for (comemID = 0; comemID < COMEM_MAX_DEVICES; comemID++ )
            if (!comemDev[comemID])
              {
               comemDev[comemID] = comemDevStructConstructor();
      			if (!comemDev[comemID])
      				return CR_FAILURE;
               rc = CONFIGMG_Register_Device_Driver(Node, ConfigHandler, (DWORD) comemDev[comemID], CM_REGISTER_DEVICE_DRIVER_DISABLEABLE | CM_REGISTER_DEVICE_DRIVER_REMOVABLE);
      			if (rc != CR_SUCCESS)
      			  {
                 comemDevStructDestructor(comemDev[comemID]);
      				return rc;
      			  }

               comemDev[comemID]->devNode = Node;

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

		default:
			return(CR_DEFAULT);
	}
}

CONFIGRET CM_HANDLER ConfigHandler(CONFIGFUNC cfFuncName, SUBCONFIGFUNC scfSubFuncName, DEVNODE dnToDevNode, DWORD dwRefData, ULONG ulFlags)
{
	CMCONFIG	Config;
	DWORD		rc;
	void *dev = (void *)dwRefData;

	switch (cfFuncName) 
	{
	case CONFIG_START:
		return ProcessConfigStart(dnToDevNode, dev );

	case CONFIG_TEST:
		return CR_SUCCESS;

	case CONFIG_STOP:
   case CONFIG_PREREMOVE:
   case CONFIG_PREREMOVE2:
	case CONFIG_REMOVE:
	case CONFIG_SHUTDOWN:
		return ProcessConfigStop(dnToDevNode, dev );

	default:
		return CR_DEFAULT;
	}
}

static comemCount = 0;
CONFIGRET ProcessConfigStart( DEVNODE devnode, void *p )
{
//   DEVICE_CONTEXT *dev = (DEVICE_CONTEXT *)p;
//   CONFIGRET rc;
//   CMCONFIG  Config;
//   MEMREGS *regs;
//   WORD     reg;
//   IRQHANDLE hndIrq;
//
//   rc = CM_Get_Alloc_Log_Conf(&Config, devnode, CM_GET_ALLOC_LOG_CONF_ALLOC);
//	if (rc != CR_SUCCESS)
//	{
//      DPRINTF1(dbuf, "CM_Get_Alloc_Log_Conf failed rc=%x\n", rc );
//		return CR_FAILURE;
//	}
//
//	Print_Assigned_Resources(&Config);
//	if (! ((Config.wNumIRQs == 1) && 
//		    (Config.wNumIOPorts == 1 || Config.wNumMemWindows == 1))
//	   )
//	{
//      DPRINTF0(dbuf, "Expected resources not assigned" );
//		return CR_FAILURE;
//	}
//
//	if (Config.wNumMemWindows)
//	{
//		dev->MemBase = Config.dMemBase[0];
//      dev->MemSize = Config.dMemLength[0];
//		dev->pMem = (MEMREGS *)MyMapPhysToLinear( dev->MemBase, Config.dMemLength[0] );
//		if (!dev->pMem)
//		{
//         DPRINTF0(dbuf, "MyMapPhysToLinear failed" );
//			return CR_FAILURE;
//		}	
//		dev->pMem->Ctrl = CTRL_START_DEVICE;
//	}
//	else
//	{
//		dev->IoBase = Config.wIOPortBase[0];
//      reg = dev->IoBase + REG_CTRL;
//		_outpdw( reg, CTRL_START_DEVICE )
//	}
//			
//	dev->IrqDescr.VID_IRQ_Number = Config.bIRQRegisters[0];
//	dev->IrqDescr.VID_Options = VPICD_OPT_REF_DATA;
//	dev->IrqDescr.VID_Hw_Int_Ref = dev;
//	dev->IrqDescr.VID_Hw_Int_Proc = HwIntProcThunk;
//	hndIrq = VPICD_Virtualize_IRQ( &dev->IrqDescr );
//	if (!hndIrq)
//	{
//      DPRINTF0(dbuf, "VPICD_Virt failed" );
//		return CR_FAILURE;
//	}

	return CR_SUCCESS;
}

CONFIGRET ProcessConfigStop( DEVNODE devnode, void *p )
{
   int comemID;

   // TBD -- have to free the memory allocated to the BARs too
   for (comemID = 0; comemID < COMEM_MAX_DEVICES; comemID++ )
     if (comemDev[comemID])
        if (comemDev[comemID]->devNode == devnode)
           {
           // Remove the interrupt stuff
           if (comemDev[comemID]->IRQHandle)
              VPICD_Force_Default_Behavior( comemDev[comemID]->IRQHandle );

		   // Kill the data structure
		   comemDevStructDestructor(comemDev[comemID]);

           // Mark it so we don't do this again.
           comemDev[comemID] = 0;
           return(CR_SUCCESS);
           
           }


//   DEVICE_CONTEXT *dev = (DEVICE_CONTEXT *)p; 
//   WORD  reg;
//
// 	if (dev->pMem)
// 	{
// 		dev->pMem->Ctrl = CTRL_STOP_DEVICE;
// 		UnMapPhysToLinear( (DWORD)dev->pMem, dev->MemSize );
// 	}
// 	else if (dev->IoBase)
// 	{
//      reg = dev->IoBase + REG_CTRL;
//		_outpdw( reg, CTRL_STOP_DEVICE )
// 	}
// 	VPICD_Force_Default_Behavior( dev->hndIrq );
// 	_HeapFree( dev, 0 );
 	return CR_SUCCESS;
}


//////////////////////////////////////////////////////////////////////
// 
// DWORD comemCreateLinPtr(AllocMemoryAll *out)
// Function:  Create linear pointers (pointers used by C programs) to 
//            the memory space allocated to the co-mem.  It returns a 
//            structure that fully describes the co-memory抯 memory
//            space because the memory may have been allocated by 
//            another program.  This must be called after any calls 
//            to alloc and realloc.
//
//            Under NT, this function returns DIFFERENT linear pointers
//            to each device.  Under W95, this is not needed because we
//            still have shared memory.
//
// Returns:	ERROR_NO_DRIVER -- Driver not detected
// 		GENERIC_ERROR -- Other error reported by driver
// 		NO_MAPPER_ERROR -- No errors
// 		Fills the structure with fragment starts, sizes and linear pointers.
// 
//////////////////////////////////////////////////////////////////////
void COMEM_CreateLinPtr(PIOCTLPARAMS p)
{
   int i;
   DWORD comemID;

   CreateLinPtrIn  *inptr = p->dioc_InBuf;
   CreateLinPtrOut *outptr = p->dioc_OutBuf;
   comemMemblock *recPtr;
   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;
		}

   recPtr = comemDev[comemID]->allocatedBlocks;
   for (i = 0; i < MAX_FRAGMENTS && recPtr; i++, recPtr = recPtr->next)
      {
      outptr->data[i].linearAddr = recPtr->linearAddr;
      outptr->data[i].physAddr   = recPtr->physAddr;
      outptr->data[i].size       = recPtr->size;
      }

   // Zero out the remaining blocks
   for (; i < MAX_FRAGMENTS; i++ )
      {
      outptr->data[i].size = 0;
      outptr->data[i].linearAddr = 0;
      outptr->data[i].physAddr = 0;
      }
	outptr->status =  NO_ERROR;
}

// In win95 it is ok (actually, it's necessary to allow multiple calls to createLinPtr.
// 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_DestroyLinPtr( PIOCTLPARAMS p )
{
	DestroyLinPtrIn  *inptr   = p->dioc_InBuf;
	DestroyLinPtrOut *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;
		}
}


// Reserve 16K block of contig memory.
// To change allocation size, need to add size parm, add checking on size parm
// and change PAGE_TABLE_NUM_PAGES and PAGE_TABLE_ALIGN to the input variables
// Also, the structure needs to save the size for the dealloc call.
void COMEM_AllocContigMemory( PIOCTLPARAMS p )
{
	AllocContigMemIn *inptr  = p->dioc_InBuf;
	AllocContigMemOut *outptr  = p->dioc_OutBuf;
    int comemID;
	*p->dioc_bytesret = sizeof(AllocContigMemOut);

    comemID = inptr->comemID;

	outptr->status =  NO_ERROR;

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

	if (comemDev[comemID]->fragCount + 1 == MAX_FRAGMENTS)
	{
	  outptr->linearAddr = 0;
	  outptr->status = ERROR_INVALID_REGION;
      return;
	}

	outptr->linearAddr = (DWORD) _PageReserve(PR_SHARED,  // page type
									PAGE_TABLE_NUM_PAGES,	// npages,
									PR_FIXED);	// flags (PR_FIXED, PR_STATIC or PR_4MEG)

	if (outptr->linearAddr == 0)
	  {
	  outptr->status = ERROR_MEMORY_ALLOC;
      return;
	  }

	outptr->physAddr = (DWORD) _PageCommitContig(outptr->linearAddr/4096,	// ULONG page,
									  	PAGE_TABLE_NUM_PAGES,			// ULONG npages,
									  	PCC_ZEROINIT | PC_USER | PC_WRITEABLE,	//	ULONG flags -- The pages are accessible at ring 3.
									  	PAGE_TABLE_ALIGN,			// ULONG alignmask,
									  	0,					// ULONG minphys,
									  	-1);				// ULONG maxphys);


	if (outptr->physAddr == -1)
	  {
	  outptr->linearAddr = 0;
	  outptr->status = ERROR_MEMORY_ALLOC;
      _PageFree(outptr->linearAddr, 0);
      return;
	  }

	{
    comemMemblock *recPtr;

	recPtr = _HeapAllocate(sizeof(comemMemblock), HEAPZEROINIT);
	if (!recPtr)
		{
		outptr->status = ERROR_MEMORY_ALLOC;
		return;
		}
	recPtr->linearAddr = outptr->linearAddr;
	recPtr->physAddr = outptr->physAddr;
	recPtr->size = inptr->size;
	recPtr->next = comemDev[comemID]->allocatedBlocks;
	comemDev[comemID]->allocatedBlocks = recPtr;
	}

  return;
}


void COMEM_DeallocContigMemory( PIOCTLPARAMS p )
{
	DeallocContigMemIn *inptr  = p->dioc_InBuf;
	DeallocContigMemOut *outptr  = p->dioc_OutBuf;
    int comemID = inptr->comemID;
	*p->dioc_bytesret = sizeof(DeallocContigMemOut);

	outptr->status =  NO_ERROR;

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

	if (!inptr->linearAddr)
	{
	  outptr->status = ERROR_INVALID_REGION;
	  *p->dioc_bytesret = 4;
	  return;
	}

	// Make sure they own the block
	{
		comemMemblock *memptr = comemDev[comemID]->allocatedBlocks;
		comemMemblock **prevptrptr = &comemDev[comemID]->allocatedBlocks;	// This is where we put the next ptr on the delete
    	comemDevStruct *recPtr;

		while (memptr != NULL && memptr->linearAddr != inptr->linearAddr)
		{
			prevptrptr = &(memptr->next);	
			memptr = memptr->next;
		}

		if (memptr == NULL)
		{
		  outptr->status = ERROR_INVALID_REGION;
		  return;
		}

		// Remove the record from the list (this screws up the order of the list, but that's okay.  This isn't NT)
		*prevptrptr = memptr->next;

		// And free the linked list record
        _HeapFree(memptr, 0);

		// Finally, decommit the addresses and free the memory associated with it
       _PageDecommit(inptr->linearAddr/ PAGE_SIZE, PAGE_TABLE_NUM_PAGES, 0);
       _PageFree(inptr->linearAddr, 0);

	}
}

⌨️ 快捷键说明

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