Пример #1
0
//Read configuration from PCI bus.
static DWORD PciReadConfig(__SYSTEM_BUS* bus, DWORD dwConfigReg,int size)
{
	DWORD dwTmp = 0;
	DWORD _cfg  = 0x80000000;
	
	dwTmp = bus->dwBusNum;
	dwTmp &= 0x000000FF;    //Only reserve the lowest 7 bits.
	_cfg  += (dwTmp << 16);  //Now,_cfg value countains the bus number.
	_cfg  += (dwConfigReg & 0x0000FFFF); //Now the device and function number are combined into _cfg.

	//Read PCI configuration.
	__outd(CONFIG_REGISTER, _cfg);
	switch (size)
	{
	case 4:
		return __ind(DATA_REGISTER);
	case 2:
		//return __inw(DATA_REGISTER);
		return (__ind(DATA_REGISTER) & 0xFFFF);
	case 1:
		//return __inb(DATA_REGISTER);
		return (__ind(DATA_REGISTER) & 0xFF);
	default:
		return 0;
	}
}
Пример #2
0
//Write configuration to PCI bus.
static BOOL PciWriteConfig(__SYSTEM_BUS* bus, DWORD dwConfigReg, DWORD dwVal,int size)
{
	DWORD dwTmp = 0;
	DWORD _cfg = 0x80000000;
	DWORD result;

	//Combine the bus number,dev number,function number and offset together.
	dwTmp = bus->dwBusNum;
	dwTmp &= 0x000000FF;
	_cfg += (dwTmp << 16);
	_cfg += (dwConfigReg & 0x0000FFFF);

	//Issue writting.
	__outd(CONFIG_REGISTER, _cfg);
	switch (size)
	{
	case 4:
		__outd(DATA_REGISTER, dwVal);
		result = __ind(DATA_REGISTER);
		break;
	case 2:
		__outw((WORD)dwVal, DATA_REGISTER);
		result = __inw(DATA_REGISTER);
		dwVal &= 0xFFFF;
		break;
	case 1:
		__outb((UCHAR)dwVal, DATA_REGISTER);
		result = __inb(DATA_REGISTER);
		dwVal &= 0xFF;
		break;
	default:
		return FALSE;
	}

	//Check if writting is successful.
	if (dwVal == result)
	{
		return TRUE;
	}
	//For debugging.
	_hx_printf("PCI_DRV: Write data to PCI space failed,val = %d,result = %d.\r\n",dwVal,result);
	return FALSE;
}
Пример #3
0
//
//The following routine scans all devices on one system bus,and inserts them into
//system bus's device list.
//
static VOID PciScanDevices(__SYSTEM_BUS* lpSysBus)
{
	DWORD                           dwConfigReg   = 0x80000000;
	DWORD                           dwLoop        = 0;
	DWORD                           dwTmp         = 0;

	if(NULL == lpSysBus) //Parameter check.
		return;

	dwTmp =  lpSysBus->dwBusNum;
	dwTmp &= 0x000000FF;    //Only reserve the lowest 7 bits.
	dwConfigReg += (dwTmp << 16);  //Now,dwConfigReg value countains the bus number.

	//
	//The following code scans all devices and functions in one PCI bus,if there is
	//a device or function,it calles PciAddDevice routine to initialize it and add it
	//to system bus's device list.
	//
	for(dwLoop = 0;dwLoop < 0x100;dwLoop ++)  //For every devices and functions.
	{
		dwConfigReg &= 0xFFFF0000;
		dwConfigReg += (dwLoop << 8);  //Now,dwConfigReg countains the bus number,device number,
		                               //and function number.

		__outd(CONFIG_REGISTER,dwConfigReg);
		dwTmp = __ind(DATA_REGISTER);

		if(0xFFFFFFFF == dwTmp)        //The device or function does not exist.
			continue;
		/*
		//
		//Now,find one PCI device,first,we check if it is a multi-function device,
		//if so,enumerate all sub-functions of this physical device,and add them to
		//system bus,otherwise,add the current physical device to system bus,and
		//increment 7 to dwLoop to skip all functions bound to this physical device.
		//
		dwConfigReg += PCI_CONFIG_OFFSET_CACHELINESZ;
		__outd(CONFIG_REGISTER,dwConfigReg);
		dwTmp = __ind(DATA_REGISTER);        //Read one double word countaining the header
		                                     //type segment.
		dwConfigReg -= PCI_CONFIG_OFFSET_CACHELINESZ;
		if(dwTmp & 0x00800000)               //This is a multiple function device.
		{
			PciAddDevice(dwConfigReg,lpSysBus);
		}
		else                                 //This is a single function device.
		{
			PciAddDevice(dwConfigReg,lpSysBus);
			dwLoop += 7;                     //Skip all other functions of current device.
		}*/
		PciAddDevice(dwConfigReg,lpSysBus);  //Add to system device.
	}
	return;
}
Пример #4
0
//Probe if there is(are) PCI bus(es).
static BOOL PciBusProbe()
{
	DWORD   dwInit     = 0x80000000;

	__outd(CONFIG_REGISTER,dwInit);

	dwInit = __ind(DATA_REGISTER);

	if(dwInit == 0xFFFFFFFF)    //The HOST-PCI bridge is not exist.
		return FALSE;
	return TRUE;
}
Пример #5
0
/*
 * This routine reads resource information from a type 1 header,and fills them into
 * physical device's resource array.Primary bus number,secondary bus number and sub-ordinate
 * bus number are the most three parameters for PCI-PCI bridge.
 */
static VOID PciFillBridgeResources(DWORD dwConfigReg,__PHYSICAL_DEVICE* lpPhyDev)
{
	__PCI_DEVICE_INFO* pDevInfo = NULL;
	DWORD dwTmp = 0;

	if(NULL == lpPhyDev)
	{
		return;
	}
	pDevInfo = (__PCI_DEVICE_INFO*)lpPhyDev->lpPrivateInfo;
	//Read the bridge's primary,secondary and subordinate bus number respectly.
	dwConfigReg &= 0xFFFFFF00;
	dwConfigReg += PCI_CONFIG_OFFSET_PRIMARY;
	__outd(CONFIG_REGISTER,dwConfigReg);
	dwTmp = __ind(DATA_REGISTER);
	pDevInfo->ucPrimary      = (UCHAR)dwTmp;
	pDevInfo->ucSecondary    = (UCHAR)(dwTmp >> 8);
	pDevInfo->ucSubordinate  = (UCHAR)(dwTmp >> 16);
	return;
}
Пример #6
0
/*
 * Scans all devices on one system bus,and inserts them into
 * system bus's device list.
 */
static VOID PciScanDevices(__SYSTEM_BUS* lpSysBus)
{
	DWORD dwConfigReg = 0x80000000;
	DWORD dwLoop = 0, dwTmp = 0;

	if (NULL == lpSysBus)
	{
		return;
	}

	dwTmp =  lpSysBus->dwBusNum;
	dwTmp &= 0x000000FF;    //Only reserve the lowest 7 bits.
	dwConfigReg += (dwTmp << 16);  //Now,dwConfigReg value countains the bus number.

	/*
	 * The following code scans all devices and functions in one PCI bus,if there is
	 * a device or function,it calles PciAddDevice routine to initialize it and add it
	 * to system bus's device list.
	 */
	for(dwLoop = 0;dwLoop < 0x100;dwLoop ++)
	{
		dwConfigReg &= 0xFFFF0000;
		/* Now,dwConfigReg countains the bus number,device number, and function number. */
		dwConfigReg += (dwLoop << 8);

		__outd(CONFIG_REGISTER,dwConfigReg);
		dwTmp = __ind(DATA_REGISTER);

		/* The device or function does not exist. */
		if (0xFFFFFFFF == dwTmp)
		{
			continue;
		}
		/* Add the probed device into system. */
		PciAddDevice(dwConfigReg,lpSysBus);
	}
	return;
}
Пример #7
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;
}
Пример #8
0
/* The following routine filles resource array of a physical device object. */
static VOID PciFillDevResources(DWORD dwConfigReg,__PHYSICAL_DEVICE* lpPhyDev)
{
	DWORD dwTmp = 0, dwOrg = 0;
	DWORD dwSize = 0;
	DWORD dwIndex = 0;
	DWORD dwLoop = 0;

	if ((0 == dwConfigReg) || (NULL == lpPhyDev))
	{
		return;
	}

	dwConfigReg &= 0xFFFFFF00;    //Clear the offset part.
	dwConfigReg += PCI_CONFIG_OFFSET_BASE1;  //Pointing to the first base address register.
	for(dwLoop = 0;dwLoop < 6;dwLoop ++)  //Read resources.
	{
		__outd(CONFIG_REGISTER,dwConfigReg);
		/* Read and save the original value. */
		dwOrg = __ind(DATA_REGISTER);
		__outd(DATA_REGISTER,0xFFFFFFFF);
		dwTmp = __ind(DATA_REGISTER);
		/* This base address register is not used. */
		if((0 == dwTmp) || (0xFFFFFFFF == dwTmp))
		{
			dwConfigReg += 4;
			/* Restore original value. */
			__outd(DATA_REGISTER,dwOrg);
			continue;
		}

		/* Restore original value. */
		__outd(DATA_REGISTER,dwOrg);
		if(dwOrg & 0x00000001)
		{
			/* IO Port range. */
			dwSize = GetRangeSize(dwTmp);
			dwOrg &= 0xFFFFFFFE;   //Clear the lowest bit.
			lpPhyDev->Resource[dwIndex].dwResType = RESOURCE_TYPE_IO;
			lpPhyDev->Resource[dwIndex].Dev_Res.IOPort.wStartPort = (WORD)dwOrg;
			lpPhyDev->Resource[dwIndex].Dev_Res.IOPort.wEndPort   = 
				(WORD)(dwOrg + dwSize - 1);
		}
		else
		{
			/* Memory map range. */
			dwOrg &= 0xFFFFFFF0;    //Clear the lowest 4 bits.
			dwSize = GetRangeSize(dwTmp);
			lpPhyDev->Resource[dwIndex].dwResType = RESOURCE_TYPE_MEMORY;
			lpPhyDev->Resource[dwIndex].Dev_Res.MemoryRegion.lpStartAddr = (LPVOID)dwOrg;
			lpPhyDev->Resource[dwIndex].Dev_Res.MemoryRegion.lpEndAddr   = 
				(LPVOID)(dwOrg + dwSize - 1);
		}
		dwIndex ++;
		dwConfigReg += 4;
	}

	/* Obtain interrupt vector information from configure space. */
	dwConfigReg &= 0xFFFFFF00;
	dwConfigReg += PCI_CONFIG_OFFSET_INTLINE;
	__outd(CONFIG_REGISTER,dwConfigReg);
	dwTmp = __ind(DATA_REGISTER);
	/* No interrupt vector is present. */
	if (0xFF == (UCHAR)dwTmp)
	{
		return;
	}
	lpPhyDev->Resource[dwIndex].dwResType = RESOURCE_TYPE_INTERRUPT;
	lpPhyDev->Resource[dwIndex].Dev_Res.ucVector  = (UCHAR)dwTmp;
	return;
}
Пример #9
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;
}