// Сканирование шины PCI
// определяем значения смещений для пространства шины PCI
#define VENDOR_ID 0x00
#define DEVICE_ID 0x02
#define C_OD_E 0x04
#define STATUS 0x06
#define REVISION_ID 0x08
#define INTERFACE 0x09
#define SUBCLASS 0x0A
#define CLASSCODE 0x0B
#define CACHE_LINE_SIZE 0x0C
#define LATENCY_TIMER 0x0D
#define HEADER_TYPE 0x0E
#define BIST 0x0F
#define BASE_ADDRESS_0 0x10
#define BASE_ADDRESS_1 0x14
#define BASE_ADDRESS_2 0x18
#define BASE_ADDRESS_3 0x1C
#define BASE_ADDRESS_4 0x20
#define BASE_ADDRESS_5 0x24
#define CARDBUS_POINTER 0x28
#define SUBVEN_ID 0x2C
#define SUBSYSTEM_ID 0x2E
#define ROM_BASE_ADDRESS 0x30
#define INTERRUPT_LINE 0x3C
#define INTERRUPT_PIN 0x3D
#define MIN_GNT 0x3E
#define MAX_LAT 0x3F
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
int GetDeviceSlot(int iDevice, int iFunction)
{
return ((((iDevice) & 0x1f) << 3) | ((iFunction) & 0x07));
}
//---------------------------------------------------------------------------
DWORD GetDevice(int iBusPCI, int iSlot, int iAddress)
{
return (0x80000000L | ((iBusPCI & 0xff) << 16) | (iSlot << 8) | (iAddress & ~3));
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// единственный аргумент функции определяет номер шины ( от 0 до 255 )
void ScanPCI(int iBusPCI)
{
DWORD dwResult = 0;
BYTE buffer[256];
// создаем двойной цикл для перебора всех устройств
for(int iDevice = 0; iDevice < 32; iDevice++)
{
for(int iFunction = 0; iFunction < 8; iFunction++)
{
memset(&buffer, 0, 256);
// вычисляем номер очередного слота
int iSlot = GetDeviceSlot(iDevice, iFunction);
// проверяем поле Vendor ID для определения наличия устройства
DWORD dwVendorID = 0;
// получаем конфигурацию устройства
dwResult = GetDevice(iBusPCI, iSlot, VENDOR_ID);
// пишем в адресный порт параметры устройства
SetPortVal(0xCF8, dwResult, 4);
dwResult = 0;
// читаем из порта данных идентификатор производителя
GetPortVal(0xCFC, &dwResult, 4);
// если полученное значение равно 0 или 0xFFFFFFFF,
// выходим из вложенного цикла и продолжаем поиск
if(dwVendorID == 0x00000000 || dwVendorID == 0xFFFFFFFF)
break;
DATA = 1;
// если устройство присутствует, читаем его параметры
// из конфигурационного пространства шины PCI
for(int j = 1; j < 256; j++)
{
// получаем конфигурацию устройства
dwResult = GetDevice(iBusPCI, iSlot, j);
// пишем в адресный порт параметры устройства
SetPortVal(0xCF8, dwResult, 4);
// получаем из порта очередной байт
GetPortVal(0xCFC + ( j&0x03 ), &dwResult, 1);
// сохраняем полученный байт в буфер
buffer[j] = dwResult;
// здесь мы можем извлечь нужные данные из буфера и сохранить
// их для последующего использования
// например, получим номер прерывания для устройства
// переменная uINT определена где-то ранее
//uINT = buffer[INTERRUPT_LINE];
// поле Header Type
//uHeader = buffer[HEADER_TYPE];
// поле Revision ID
//uRevID = buffer[REVISION_ID];
// поле Device ID
dwDeviceID = ( (WORD) ( ( (BYTE) (buffer[DEVICE_ID])) | ( ( (WORD) ( (BYTE) (buffer[DEVICE_ID] + 1) ) ) << 8) ) );
// поле Cod_e
dwC_od_e = ( (WORD) ( ( (BYTE) (buffer[C_OD_E]) ) | ( ( (WORD) ( (BYTE) (buffer[C_OD_E] + 1) ) ) << 8) ) );
// поле Subsystem Vendor ID
dwSubVendorID = ( (WORD) ( ( (BYTE) (buffer[SUBVEN_ID]) ) | ( ( (WORD) ( (BYTE) (buffer[SUBVEN_ID] + 1) ) ) << 8) ) );
// базовый адрес 0
WORD low = 0, high = 0;
// получаем младшее слово адреса
low = ( (WORD) ( ( (BYTE) (buffer[BASE_ADDRESS_0]) ) | ( ( (WORD) ( (BYTE) (buffer[BASE_ADDRESS_0] + 1) ) ) << 8) ) );
// получаем старшее слово адреса
high = ( (WORD) ( ( (BYTE) (buffer[BASE_ADDRESS_0] + 2) ) | ( ( (WORD) ( (BYTE) (buffer[BASE_ADDRESS_0] + 3) ) ) << 8) ) );
// вычисляем полный адрес
dwBaseAddress_0 = ( (LONG) ( ( (WORD) (low) ) | ( ( (DWORD) ( (WORD) (high) ) ) << 16) ) );
}
}
}
}
Сканирование пространства шины PCI
Пожалуйста подскажите как правельно просканировать шину PCI и получить адреса установленных устройств, собрал маломальский код, но постоянно получаю нулевые результаты, подскажите что нужно зделать ???