/* * 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; }
// //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; }