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 + -
显示快捷键?