示例#1
0
/*
 * Add one PCI device(physical device) into a PCI
 * bus.
 * It first create a physical device and a PCI information structure,then initializes
 * them by reading data from configure space.
 */
static VOID PciAddDevice(DWORD dwConfigReg,__SYSTEM_BUS* lpSysBus)
{
	__PCI_DEVICE_INFO* lpDevInfo = NULL;
	__PHYSICAL_DEVICE* lpPhyDev = NULL;
	BOOL bResult = FALSE;
	DWORD dwTmp = 0;

	/* Basic checking. */
	if ((0 == dwConfigReg) || (NULL == lpSysBus))
	{
		return;
	}
	/* Only available in process of system initialization. */
	BUG_ON(!IN_SYSINITIALIZATION());

	/* Create physical device. */
	lpPhyDev = (__PHYSICAL_DEVICE*)KMemAlloc(sizeof(__PHYSICAL_DEVICE), KMEM_SIZE_TYPE_ANY);
	if (NULL == lpPhyDev)
	{
		goto __TERMINAL;
	}
	memset(lpPhyDev, 0, sizeof(__PHYSICAL_DEVICE));

	/* Create PCI device information structure. */
	lpDevInfo = (__PCI_DEVICE_INFO*)KMemAlloc(sizeof(__PCI_DEVICE_INFO), KMEM_SIZE_TYPE_ANY);
	if (NULL == lpDevInfo)
	{
		goto __TERMINAL;
	}
	memset(lpDevInfo, 0, sizeof(__PCI_DEVICE_INFO));
	
	lpDevInfo->DeviceNum   = (dwConfigReg >> 11) & 0x0000001F;  //Get device number.
	lpDevInfo->FunctionNum = (dwConfigReg >> 8) & 0x00000007;   //Get function number.
	lpPhyDev->lpPrivateInfo = (LPVOID)lpDevInfo;  //Link device information to physical device.

	//Save device number to physical device object.
	lpPhyDev->dwNumber = dwConfigReg & 0x0000FF00;
	lpPhyDev->dwNumber >>= 8;

	/* Initializes identifier member of physical device. */
	dwConfigReg &= 0xFFFFFF00;    //Clear offset part.
	dwConfigReg += PCI_CONFIG_OFFSET_VENDOR;
	__outd(CONFIG_REGISTER,dwConfigReg);
	dwTmp = __ind(DATA_REGISTER);  //Read vendor ID and device ID.

	lpPhyDev->DevId.dwBusType = BUS_TYPE_PCI;
	lpPhyDev->DevId.Bus_ID.PCI_Identifier.ucMask = PCI_IDENTIFIER_MASK_ALL;
	lpPhyDev->DevId.Bus_ID.PCI_Identifier.wVendor = (WORD)dwTmp;
	lpPhyDev->DevId.Bus_ID.PCI_Identifier.wDevice = (WORD)(dwTmp >> 16);

	dwConfigReg &= 0xFFFFFF00;
	dwConfigReg += PCI_CONFIG_OFFSET_REVISION;  //Get revision ID and class code.
	__outd(CONFIG_REGISTER,dwConfigReg);
	dwTmp = __ind(DATA_REGISTER);

	lpPhyDev->DevId.Bus_ID.PCI_Identifier.dwClass = dwTmp;
	/* Save to information struct also. */
	lpDevInfo->dwClassCode = dwTmp;

	dwConfigReg &= 0xFFFFFF00;
	/* Get header type. */
	dwConfigReg += PCI_CONFIG_OFFSET_CACHELINESZ;
	__outd(CONFIG_REGISTER,dwConfigReg);
	dwTmp = __ind(DATA_REGISTER);
	
	/* Get header type. */
	lpPhyDev->DevId.Bus_ID.PCI_Identifier.ucHdrType = (UCHAR)(dwTmp >> 16);

	/* Initializes the resource information required by device. */
	switch((dwTmp >> 16) & 0x7F)
	{
	case 0:         
		/* Normal PCI device. */
		lpDevInfo->dwDeviceType = PCI_DEVICE_TYPE_NORMAL;
		dwConfigReg &= 0xFFFFFF00;
		PciFillDevResources(dwConfigReg,lpPhyDev);
		bResult = TRUE;
		break;
	case 1:
		/* PCI-PCI bridge. */
		lpDevInfo->dwDeviceType = PCI_DEVICE_TYPE_BRIDGE;
		dwConfigReg &= 0xFFFFFF00;
		PciFillBridgeResources(dwConfigReg,lpPhyDev);
		bResult = TRUE;
		break;
	case 2:
		/* CardBus-PCI bridge. */
		lpDevInfo->dwDeviceType = PCI_DEVICE_TYPE_CARDBUS;
		bResult = TRUE;
		break;
	default:
		/* Not supported yet. */
		lpDevInfo->dwDeviceType = PCI_DEVICE_TYPE_UNSUPPORTED;
		bResult = TRUE;
		break;
	}

	//Set up physical device's configuration reading/writting routine.
	lpPhyDev->ReadDeviceConfig  = PciReadDeviceConfig;
	lpPhyDev->WriteDeviceConfig = PciWriteDeviceConfig;

	/*
	 * Now,we have finished to initialize resource information,just insert the physical device
	 * object into system bus.
	 */
	lpPhyDev->lpHomeBus = lpSysBus;
	bResult = DeviceManager.AppendDevice(&DeviceManager, lpPhyDev);

__TERMINAL:
	if(!bResult)
	{
		if (lpPhyDev)
		{
			KMemFree((LPVOID)lpPhyDev, KMEM_SIZE_TYPE_ANY, 0);
		}
		if (lpDevInfo)
		{
			KMemFree((LPVOID)lpDevInfo, KMEM_SIZE_TYPE_ANY, 0);
		}
	}
	return;
}
示例#2
0
//
//The following routine is used to add one PCI device(physical device) into a PCI
//bus.
//It first create a physical device and a PCI information structure,then initializes
//them by reading data from configure space.
//
static VOID PciAddDevice(DWORD dwConfigReg,__SYSTEM_BUS* lpSysBus)
{
	__PCI_DEVICE_INFO*                    lpDevInfo      = NULL;
	__PHYSICAL_DEVICE*                    lpPhyDev       = NULL;
	DWORD                                 dwFlags        = 0;
	BOOL                                  bResult        = FALSE;
	//DWORD                                 dwLoop         = 0;
	DWORD                                 dwTmp          = 0;

	if((0 == dwConfigReg) || (NULL == lpSysBus)) //Invalid parameters.
		return;

	lpPhyDev = (__PHYSICAL_DEVICE*)KMemAlloc(sizeof(__PHYSICAL_DEVICE), KMEM_SIZE_TYPE_ANY);  //Create physical device.
	if(NULL == lpPhyDev)
		goto __TERMINAL;

	lpDevInfo = (__PCI_DEVICE_INFO*)KMemAlloc(sizeof(__PCI_DEVICE_INFO), KMEM_SIZE_TYPE_ANY);
	if(NULL == lpDevInfo)  //Can not allocate information structure.
		goto __TERMINAL;
	
	lpDevInfo->DeviceNum   = (dwConfigReg >> 11) & 0x0000001F;  //Get device number.
	lpDevInfo->FunctionNum = (dwConfigReg >> 8) & 0x00000007;   //Get function number.
	lpPhyDev->lpPrivateInfo = (LPVOID)lpDevInfo;  //Link device information to physical device.

	//Save device number to physical device object.
	lpPhyDev->dwNumber = dwConfigReg & 0x0000FF00;
	lpPhyDev->dwNumber >>= 8;

	//
	//The following code initializes identifier member of physical device.
	//
	dwConfigReg &= 0xFFFFFF00;    //Clear offset part.
	dwConfigReg += PCI_CONFIG_OFFSET_VENDOR;
	__outd(CONFIG_REGISTER,dwConfigReg);
	dwTmp = __ind(DATA_REGISTER);  //Read vendor ID and device ID.

	lpPhyDev->DevId.dwBusType               = BUS_TYPE_PCI;
	lpPhyDev->DevId.Bus_ID.PCI_Identifier.ucMask   = PCI_IDENTIFIER_MASK_ALL;
	lpPhyDev->DevId.Bus_ID.PCI_Identifier.wVendor  = (WORD)dwTmp;
	lpPhyDev->DevId.Bus_ID.PCI_Identifier.wDevice  = (WORD)(dwTmp >> 16);

	dwConfigReg &= 0xFFFFFF00;
	dwConfigReg += PCI_CONFIG_OFFSET_REVISION;  //Get revision ID and class code.
	__outd(CONFIG_REGISTER,dwConfigReg);
	dwTmp = __ind(DATA_REGISTER);

	lpPhyDev->DevId.Bus_ID.PCI_Identifier.dwClass = dwTmp;
	lpDevInfo->dwClassCode                 = dwTmp;  //Save to information struct also.

	dwConfigReg &= 0xFFFFFF00;
	dwConfigReg += PCI_CONFIG_OFFSET_CACHELINESZ;    //Get header type.
	__outd(CONFIG_REGISTER,dwConfigReg);
	dwTmp = __ind(DATA_REGISTER);
	
	lpPhyDev->DevId.Bus_ID.PCI_Identifier.ucHdrType = (UCHAR)(dwTmp >> 16); //Get header type.

	//
	//The following code initializes the resource information required by device.
	//
	switch((dwTmp >> 16) & 0x7F)
	{
	case 0:         //Normal PCI device.
		lpDevInfo->dwDeviceType = PCI_DEVICE_TYPE_NORMAL;
		dwConfigReg &= 0xFFFFFF00;
		PciFillDevResources(dwConfigReg,lpPhyDev);
		bResult = TRUE;
		break;
	case 1:         //PCI-PCI bridge.
		lpDevInfo->dwDeviceType = PCI_DEVICE_TYPE_BRIDGE;
		dwConfigReg &= 0xFFFFFF00;
		PciFillBridgeResources(dwConfigReg,lpPhyDev);
		bResult = TRUE;
		break;
	case 2:        //CardBus-PCI bridge.
		lpDevInfo->dwDeviceType = PCI_DEVICE_TYPE_CARDBUS;
		bResult = TRUE;
		break;
	default:       //Not supported yet.
		lpDevInfo->dwDeviceType = PCI_DEVICE_TYPE_UNSUPPORTED;
		bResult = TRUE;
		break;
	}

	//Set up physical device's configuration reading/writting routine.
	lpPhyDev->ReadDeviceConfig  = PciReadDeviceConfig;
	lpPhyDev->WriteDeviceConfig = PciWriteDeviceConfig;

	//
	//Now,we have finished to initialize resource information,so we insert the physical device
	//object into system bus.
	//
	lpPhyDev->lpHomeBus = lpSysBus;
	__ENTER_CRITICAL_SECTION(NULL,dwFlags);
	lpPhyDev->lpNext = lpSysBus->lpDevListHdr;
	lpSysBus->lpDevListHdr = lpPhyDev;
	__LEAVE_CRITICAL_SECTION(NULL,dwFlags);

__TERMINAL:
	if(!bResult)
	{
		if(lpPhyDev)  //Release memory.
			KMemFree((LPVOID)lpPhyDev,KMEM_SIZE_TYPE_ANY,0);
		if(lpDevInfo)
			KMemFree((LPVOID)lpDevInfo,KMEM_SIZE_TYPE_ANY,0);
	}
	return;
}