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

📄 devmgr.cpp

📁 小型的操作系统开发的原代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//***********************************************************************/
//    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)
		{

⌨️ 快捷键说明

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