/* * Scans a PCI bus and all it's child buses(if exist).For each bus,use * one element of SystemBus array(in DeviceManager object) to record it. * This routine returns the largest bus number in this bus tree,if failed, * returns MAX_DWORD_VALUE, which is 0xFFFFFFFF currently. */ static DWORD PciScanBus(__DEVICE_MANAGER* lpDevMgr, __PHYSICAL_DEVICE* lpBridge, DWORD dwBusNum) { DWORD dwLoop = 0; __PHYSICAL_DEVICE* lpPhyDev = NULL; DWORD dwSubNum = dwBusNum; /* Basic checking. */ BUG_ON(NULL == lpDevMgr); /* * This routine can be called only in process of system * initialization,so no locks are obtained when initialize * the physial device list or other global data structures. */ BUG_ON(!IN_SYSINITIALIZATION()); if(255 <= dwBusNum) { /* Maximal bus number should not exceed 255. */ return MAX_DWORD_VALUE; } for(dwLoop = 0;dwLoop < MAX_BUS_NUM;dwLoop ++) { if (BUS_TYPE_NULL == lpDevMgr->SystemBus[dwLoop].dwBusType) { break; } } if(MAX_BUS_NUM == dwLoop) { /* Can not find a free bus,the number of system buses exceed MAX_BUS_NUM. */ return MAX_DWORD_VALUE; } /* Now we have found a free system bus element,initialize it. */ lpDevMgr->SystemBus[dwLoop].dwBusType = BUS_TYPE_PCI; lpDevMgr->SystemBus[dwLoop].dwBusNum = dwBusNum; lpDevMgr->SystemBus[dwLoop].lpHomeBridge = lpBridge; if(lpBridge) { /* If the current bus is not root bus. */ lpDevMgr->SystemBus[dwLoop].lpParentBus = lpBridge->lpHomeBus; lpBridge->lpChildBus = &lpDevMgr->SystemBus[dwLoop]; } //Set PCI bus operations. lpDevMgr->SystemBus[dwLoop].ReadConfig = PciReadConfig; lpDevMgr->SystemBus[dwLoop].WriteConfig = PciWriteConfig; /* Scan all devices on this bus. */ PciScanDevices(&lpDevMgr->SystemBus[dwLoop]); lpPhyDev = lpDevMgr->SystemBus[dwLoop].lpDevListHdr; /* Scan all child buses of the current bus. */ while(lpPhyDev) { if(PCI_DEVICE_TYPE_BRIDGE == ((__PCI_DEVICE_INFO*)lpPhyDev->lpPrivateInfo)->dwDeviceType) { /* PCI bridge. */ dwSubNum = PciScanBus(lpDevMgr, lpPhyDev, ((__PCI_DEVICE_INFO*)lpPhyDev->lpPrivateInfo)->ucSecondary); } lpPhyDev = lpPhyDev->lpNext; } return dwSubNum; }
// //The following routine scans a PCI bus and all it's child buses(if exist),for each bus,use //one element of SystemBus array(in DeviceManager object) to record it. //This routine returns the largest bus number in this bus tree,if failed,returns MAX_DWORD_VALUE, //which is 0xFFFFFFFF currently. // static DWORD PciScanBus(__DEVICE_MANAGER* lpDevMgr, __PHYSICAL_DEVICE* lpBridge, DWORD dwBusNum) { DWORD dwLoop = 0; DWORD dwFlags = 0; //__PCI_DEVICE_INFO* lpDevInfo = NULL; __PHYSICAL_DEVICE* lpPhyDev = NULL; DWORD dwSubNum = dwBusNum; if(NULL == lpDevMgr) //Parameter check. { return MAX_DWORD_VALUE; } if(255 <= dwBusNum) //Maximal bus number should not exceed 255. { return MAX_DWORD_VALUE; } __ENTER_CRITICAL_SECTION(NULL,dwFlags); for(dwLoop = 0;dwLoop < MAX_BUS_NUM;dwLoop ++) { if(BUS_TYPE_NULL == lpDevMgr->SystemBus[dwLoop].dwBusType) break; } if(MAX_BUS_NUM == dwLoop) //Can not find a free bus,the number of system buses exceed //MAX_BUS_NUM. { __LEAVE_CRITICAL_SECTION(NULL,dwFlags); return MAX_DWORD_VALUE; } // //Now,we have found a free system bus element,so initialize it. // lpDevMgr->SystemBus[dwLoop].dwBusType = BUS_TYPE_PCI; lpDevMgr->SystemBus[dwLoop].dwBusNum = dwBusNum; lpDevMgr->SystemBus[dwLoop].lpHomeBridge = lpBridge; if(lpBridge) //If the current bus is not root bus. { lpDevMgr->SystemBus[dwLoop].lpParentBus = lpBridge->lpHomeBus; lpBridge->lpChildBus = &lpDevMgr->SystemBus[dwLoop]; } //Set PCI bus operations. lpDevMgr->SystemBus[dwLoop].ReadConfig = PciReadConfig; lpDevMgr->SystemBus[dwLoop].WriteConfig = PciWriteConfig; PciScanDevices(&lpDevMgr->SystemBus[dwLoop]); //Scan all devices on this bus. lpPhyDev = lpDevMgr->SystemBus[dwLoop].lpDevListHdr; while(lpPhyDev) //Now,scan all child buses of the current bus. { if(PCI_DEVICE_TYPE_BRIDGE == ((__PCI_DEVICE_INFO*)lpPhyDev->lpPrivateInfo)->dwDeviceType) //This is a PCI-PCI //bridge. { dwSubNum = PciScanBus(lpDevMgr,lpPhyDev,//++dwBusNum); //Scan child bus. ((__PCI_DEVICE_INFO*)lpPhyDev->lpPrivateInfo)->ucSecondary); } lpPhyDev = lpPhyDev->lpNext; } __LEAVE_CRITICAL_SECTION(NULL,dwFlags); return dwSubNum; }