?? devmgr.cpp
字號(hào):
//***********************************************************************/
// Author : Garry
// Original Date : Oct,15 2005
// Module Name : DEVMGR.CPP
// Module Funciton :
// This module countains device manager object's implemen-
// tation code.
// Last modified Author :
// Last modified Date :
// Last modified Content :
// 1.
// 2.
// Lines number :
//***********************************************************************/
#ifndef __STDAFX_H__
#include "..\INCLUDE\StdAfx.h"
#endif
#ifndef __PCI_DRV_H__
#include "..\INCLUDE\PCI_DRV.H"
#endif
//
//Pre-declaration of local routines.
//
static BOOL DevMgrInitialize(__DEVICE_MANAGER*);
static BOOL CheckPortRegion(__DEVICE_MANAGER*,__RESOURCE*);
static BOOL ReservePortRegion(__DEVICE_MANAGER*,__RESOURCE*);
static VOID ReleasePortRegion(__DEVICE_MANAGER*,__RESOURCE*);
static VOID DeleteDevice(__DEVICE_MANAGER*,__PHYSICAL_DEVICE*);
static BOOL AppendDevice(__DEVICE_MANAGER*,__PHYSICAL_DEVICE*);
static __PHYSICAL_DEVICE* GetDevice(__DEVICE_MANAGER*,
DWORD,
__IDENTIFIER*,
__PHYSICAL_DEVICE*);
//
//The implementation of DeviceManager's initialize routine.
//
static BOOL DevMgrInitialize(__DEVICE_MANAGER* lpDevMgr)
{
BOOL bResult = FALSE;
__RESOURCE* lpRes = NULL;
if(NULL == lpDevMgr) //Invalid parameter.
return FALSE;
//lpRes = (__RESOURCE*)malloc(sizeof(__RESOURCE));
lpRes = (__RESOURCE*)KMemAlloc(sizeof(__RESOURCE),KMEM_SIZE_TYPE_ANY);
if(NULL == lpRes) //Can not allocate memory.
return FALSE;
lpRes->dwResType = RESOURCE_TYPE_IO;
lpRes->IOPort.wStartPort = MIN_IO_PORT;
lpRes->IOPort.wEndPort = MAX_IO_PORT;
lpDevMgr->FreePortResource.dwResType = RESOURCE_TYPE_EMPTY;
lpDevMgr->FreePortResource.lpNext = lpRes;
lpDevMgr->FreePortResource.lpPrev = lpRes;
lpRes->lpNext = &lpDevMgr->FreePortResource;
lpRes->lpPrev = &lpDevMgr->FreePortResource;
lpDevMgr->UsedPortResource.dwResType = RESOURCE_TYPE_EMPTY;
lpDevMgr->UsedPortResource.lpNext = &lpDevMgr->UsedPortResource;
lpDevMgr->UsedPortResource.lpPrev = &lpDevMgr->UsedPortResource;
for(DWORD dwLoop = 0;dwLoop < MAX_BUS_NUM;dwLoop ++) //Initialize bus array.
{
lpDevMgr->SystemBus[dwLoop].dwBusType = BUS_TYPE_NULL;
lpDevMgr->SystemBus[dwLoop].lpDevListHdr = NULL;
lpDevMgr->SystemBus[dwLoop].lpHomeBridge = NULL;
lpDevMgr->SystemBus[dwLoop].lpParentBus = NULL;
}
//lpDevMgr->AppendDevice = AppendDevice;
//lpDevMgr->CheckPortRegion = CheckPortRegion;
//lpDevMgr->DeleteDevice = DeleteDevice;
//lpDevMgr->GetDevice = GetDevice;
//lpDevMgr->ReleasePortRegion = ReleasePortRegion;
//lpDevMgr->ReservePortRegion = ReservePortRegion;
//
//Load system bus drivers here.
//
PciBusDriver(lpDevMgr);
return TRUE;
}
//
//A helper routine,used to insert a IO port region into list,and keeps all port region
//in order.
//
static VOID InsertIntoList(__RESOURCE* lpListHdr,__RESOURCE* lpRes)
{
__RESOURCE* lpBefore = NULL;
if((NULL == lpListHdr) || (NULL == lpRes)) //Invalid parameters.
return;
lpBefore = lpListHdr->lpNext;
while(lpBefore != lpListHdr) //Travel the whole list to find a statisfying position.
{
if(lpBefore->IOPort.wStartPort >= lpRes->IOPort.wEndPort) //Find it.
{
break;
}
lpBefore = lpBefore->lpNext;
}
//
//Insert lpRes into the list.
//
lpRes->lpNext = lpBefore;
lpRes->lpPrev = lpBefore->lpPrev;
lpBefore->lpPrev->lpNext = lpRes;
lpBefore->lpPrev = lpRes;
return;
}
//
//Some macros used to operate bi-direction link list.
//
#define INSERT_INTO_LIST(listhdr,node) \
InsertIntoList(listhdr,node)
#define DELETE_FROM_LIST(node) \
(node)->lpNext->lpPrev = (node)->lpPrev; \
(node)->lpPrev->lpNext = (node)->lpNext;
//
//The following routine is used to merge continues IO port region into one region.
//This is a helper routine,used by ReleasePortRegion to merge continues port region
//into one region.
//This routine searches the whole list,once find two continues region(wEndPort of the
//first region equals to wStartPort - 1 of the second region),then modify the first
//region's wEndPort to the second region's wEndPort,and delete the second region from
//list.
//
static VOID MergeRegion(__RESOURCE* lpListHdr)
{
__RESOURCE* lpFirst = NULL;
__RESOURCE* lpSecond = NULL;
__RESOURCE* lpTmp = NULL;
if(NULL == lpListHdr)
return;
lpFirst = lpListHdr->lpNext;
while(lpFirst != lpListHdr)
{
lpSecond = lpFirst->lpNext;
if(lpSecond == lpListHdr) //Finished to search.
{
break;
}
if(lpFirst->IOPort.wEndPort + 1 == lpSecond->IOPort.wStartPort) //Statisfy the continues
//condition.
{
DELETE_FROM_LIST(lpSecond); //Delete the second port region.
lpFirst->IOPort.wEndPort = lpSecond->IOPort.wEndPort; //Modify the first port region.
KMemFree((LPVOID)lpSecond,KMEM_SIZE_TYPE_ANY,0L);
//free((LPVOID)lpSecond);
continue;
}
lpFirst = lpFirst->lpNext;
}
}
//
//The implementation of ReservePortRegion routine.
//The second parameter,lpRes,indicates desired start address of port region,
//and port region's length can be calculated by minus start value from end value
//of the desired port region.
//
static BOOL ReservePortRegion(__DEVICE_MANAGER* lpDevMgr,__RESOURCE* lpRes)
{
BOOL bResult = FALSE;
WORD wSize = 0L;
__RESOURCE* lpStatisfy = NULL;
__RESOURCE* lpPotential = NULL;
BOOL bFind = FALSE;
DWORD dwFlags = 0L;
__RESOURCE* lpFirstRegion = NULL;
__RESOURCE* lpSecondRegion = NULL;
__RESOURCE* lpRes1 = NULL;
if((NULL == lpDevMgr) || (NULL == lpRes)) //Invalid parameters.
return bResult;
if(lpRes->dwResType != RESOURCE_TYPE_IO) //Invalid parameter.
return bResult;
if(lpRes->IOPort.wEndPort - lpRes->IOPort.wStartPort >= MAX_IO_PORT)
return bResult;
//lpRes1 = (__RESOURCE*)malloc(sizeof(__RESOURCE));
lpRes1 = (__RESOURCE*)KMemAlloc(sizeof(__RESOURCE),KMEM_SIZE_TYPE_ANY);
if(NULL == lpRes1) //Can not allocate resource.
return bResult;
//
//First,we look for free port list of DeviceManager object,to find
//a block of port region statisify the original desired(lpRes).
//
wSize = lpRes->IOPort.wEndPort - lpRes->IOPort.wStartPort + 1;
__ENTER_CRITICAL_SECTION(NULL,dwFlags);
lpStatisfy = lpDevMgr->FreePortResource.lpNext;
while(lpStatisfy != &lpDevMgr->FreePortResource) //Trave all the free port list.
{
if((lpStatisfy->IOPort.wStartPort <= lpRes->IOPort.wStartPort) &&
(lpStatisfy->IOPort.wEndPort >= lpRes->IOPort.wEndPort)) //Find one.
{
bFind = TRUE;
break;
}
if((lpStatisfy->IOPort.wEndPort - lpStatisfy->IOPort.wStartPort) >= wSize)
{
lpPotential = lpStatisfy; //The current block can statisfy the size of original
//request,so it is a potential statisfying region.
}
lpStatisfy = lpStatisfy->lpNext;
}
if(bFind) //Found a IO port region statisfy the original request.
{
DELETE_FROM_LIST(lpStatisfy); //Delete the region from free list.
if(lpStatisfy->IOPort.wStartPort < lpRes->IOPort.wStartPort) //Exceed the request.
{
//lpFirstRegion = (__RESOURCE*)malloc(sizeof(__RESOURCE));
lpFirstRegion = (__RESOURCE*)KMemAlloc(sizeof(__RESOURCE),KMEM_SIZE_TYPE_ANY);
if(NULL != lpFirstRegion) //Allocate successfully.
{
lpFirstRegion->dwResType = RESOURCE_TYPE_IO;
lpFirstRegion->IOPort.wStartPort = lpStatisfy->IOPort.wStartPort;
lpFirstRegion->IOPort.wEndPort = lpRes->IOPort.wStartPort - 1;
INSERT_INTO_LIST(&lpDevMgr->FreePortResource,lpFirstRegion); //Insert into
//free list.
}
}
if(lpStatisfy->IOPort.wEndPort > lpRes->IOPort.wEndPort) //Exceed the request.
{
//lpSecondRegion = (__RESOURCE*)malloc(sizeof(__RESOURCE));
lpSecondRegion = (__RESOURCE*)KMemAlloc(sizeof(__RESOURCE),KMEM_SIZE_TYPE_ANY);
if(NULL != lpSecondRegion) //Allocate successfully.
{
lpSecondRegion->dwResType = RESOURCE_TYPE_IO;
lpSecondRegion->IOPort.wStartPort = lpRes->IOPort.wEndPort + 1;
lpSecondRegion->IOPort.wEndPort = lpStatisfy->IOPort.wEndPort;
INSERT_INTO_LIST(&lpDevMgr->FreePortResource,lpSecondRegion);
}
}
lpRes1->dwResType = RESOURCE_TYPE_IO;
lpRes1->IOPort.wStartPort = lpRes->IOPort.wStartPort;
lpRes1->IOPort.wEndPort = lpRes->IOPort.wEndPort;
INSERT_INTO_LIST(&lpDevMgr->UsedPortResource,lpRes1); //Insert it into used port list.
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
bResult = TRUE;
KMemFree((LPVOID)lpStatisfy,KMEM_SIZE_TYPE_ANY,0L);
//free((LPVOID)lpStatisfy);
goto __TERMINAL;
}
if(lpPotential) //Though can not find a IO port region statisfy the original request,
//but there is at least one region statisfy requesting size,so reserve
//this region.
{
DELETE_FROM_LIST(lpPotential); //Delete from free list.
if((WORD)(lpPotential->IOPort.wEndPort - lpPotential->IOPort.wStartPort) > wSize)
{
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -