Advertisement
anticlown

Lab_4(analog of linux -lspci with extra info)

Nov 7th, 2023 (edited)
1,048
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.05 KB | None | 0 0
  1. #include "stdio.h"
  2. #include "pci.h"
  3. #include "stdbool.h"
  4. #include "sys/io.h"
  5. #include "string.h"
  6. #include "errno.h"
  7.  
  8. /*  define start    */
  9. #define REQUIRED_PRIVILEGE_LEVEL 3
  10.  
  11. #define CONFIG_ADDRESS_PORT 0xCF8
  12. #define CONFIG_DATA_PORT 0xCFC
  13. #define ENABLE_BIT 0x80000000
  14. #define BUS_OFFSET 16
  15. #define DEVICE_OFFSET 11
  16. #define FUNCTION_OFFSET 8
  17. #define DEVICE_ID_OFFSET 2
  18. #define VENDOR_ID_OFFSET 0
  19. #define UNKNOWN_MSG "Unknown"
  20.  
  21. #define NUM_OF_VENDORS (sizeof(PciVenTable) / sizeof(PCI_VENTABLE))
  22. #define NUM_OF_DEVICES (sizeof(PciDevTable) / sizeof(PCI_DEVTABLE))
  23.  
  24. #define BUS_NUM 256
  25. #define DEVICE_NUM 32
  26. #define FUNCTION_NUM 8
  27. /*  define end    */
  28.  
  29. /*    PCI methods start    */
  30. int calculateAddress(const int bus, const int device, const int function)
  31. {
  32.     return ENABLE_BIT + (bus << BUS_OFFSET) + (device << DEVICE_OFFSET) + (function << FUNCTION_OFFSET);
  33. }
  34.  
  35. int getPCIData(const int address)
  36. {
  37.     outl(address, CONFIG_ADDRESS_PORT); // прочитать по адресу
  38.     return inl(CONFIG_DATA_PORT);       // записать по адресу
  39. }
  40.  
  41. int readPCIDataField(const int data, const int offset)
  42. {
  43.     return (int)((data >> ((offset & 2) * 8)) & 0xFFFF);
  44. }
  45. /*    PCI methods end    */
  46.  
  47. /*    device methods start    */
  48. bool DoesDeviceExist(const int data)
  49. {
  50.     return data != -1;
  51. }
  52.  
  53. char *getVendorName(const int vendorID)
  54. {
  55.     for (int i = 0; i < NUM_OF_VENDORS; i++)
  56.         if (PciVenTable[i].VendorId == vendorID)
  57.             return PciVenTable[i].VendorName;
  58.  
  59.     return UNKNOWN_MSG; // в случае, если не находится имя, выводится Unknown
  60. }
  61.  
  62. char *getDeviceName(const int vendorID, const int deviceID)
  63. {
  64.     for (int i = 0; i < NUM_OF_DEVICES; i++)
  65.         if (PciDevTable[i].VendorId == vendorID && PciDevTable[i].DeviceId == deviceID)
  66.             return PciDevTable[i].DeviceName;
  67.  
  68.     return UNKNOWN_MSG; // в случае, если не находится имя, выводится Unknown
  69. }
  70.  
  71. bool isBridge(const unsigned address)
  72. {
  73.     outl(address + 0x0C, CONFIG_ADDRESS_PORT);
  74.     return (inl(CONFIG_DATA_PORT) >> 16) != 0;
  75. }
  76.  
  77. int decodeROMBaseRegisters(const int address)
  78. {
  79.     if (!isBridge(address))
  80.     {
  81.         outl(address + 0x1C, CONFIG_ADDRESS_PORT);
  82.         int inter = inl(CONFIG_DATA_PORT);
  83.         return inter >> 11;
  84.     }
  85.     else
  86.         return 0;
  87. }
  88.  
  89. int decodeInputRegs(const int address)
  90. {
  91.     if (!isBridge(address))
  92.     {
  93.         for (int i = 0; i < 6; i++)
  94.         {
  95.             outl(address + 0x10 + i * 4, CONFIG_ADDRESS_PORT);
  96.             unsigned barValue = inl(CONFIG_DATA_PORT);
  97.             if ((barValue & 1) == 1) //является ли регистром ввода-вывода
  98.                 return barValue >> 2;
  99.         }
  100.         return 0;
  101.     }
  102.     else
  103.         return 0;
  104. }
  105. int decodeClassCode(const int address)
  106. {
  107.     if (isBridge(address))
  108.     {
  109.         outl(address + 0x08, CONFIG_ADDRESS_PORT);
  110.         int inter = inl(CONFIG_DATA_PORT);
  111.         return inter >> 8; //Prog. I/F(8..15) + SubClass Code(16..23) + ClassCode(24..31)
  112.     }
  113.     else
  114.         return 0;
  115. }
  116.  
  117. // device structure
  118. typedef struct
  119. {
  120.     int bus;
  121.     int device;
  122.     int function;
  123.     int vendorID;
  124.     int deviceID;
  125.     char *vendorName;
  126.     char *deviceName;
  127.     int ROMBR;  // ROM Base Registers
  128.     int IOBReg; // I/O Base Registers
  129.     int clCode; // ClassCode
  130. } deviceStruct;
  131.  
  132. deviceStruct constructor(const int bus, const int device, const int function, const int data, const int address)
  133. {
  134.     int vendorID = readPCIDataField(data, VENDOR_ID_OFFSET);
  135.     int deviceID = readPCIDataField(data, DEVICE_ID_OFFSET);
  136.     char *vendorName = getVendorName(vendorID);
  137.     char *deviceName = getDeviceName(vendorID, deviceID);
  138.     int ROMBaseReg = decodeROMBaseRegisters(address);
  139.     int inputBaseRegs = decodeInputRegs(address);
  140.     int classCode = decodeClassCode(address);
  141.     deviceStruct temp = {bus, device, function, vendorID, deviceID, vendorName, deviceName, ROMBaseReg, inputBaseRegs, classCode};
  142.  
  143.     return temp;
  144. }
  145. /*    device methods end    */
  146.  
  147. /*      print procedures start      */
  148. void printTaskInfo()
  149. {
  150.     printf("\n\tДанная программа формирует цикл опроса и идентификации устройств PCI, затем выводит информацию о них в сводной таблице.\n \t\t\t\t\t\tДоп. задания:\n");
  151.     printf("3.  \tЕсли устройство не мост(0-бит поля Header Type = 0) вывести  и расшифровать значение полей базовых регистров ввода/вывода.\n");
  152.     printf("4.  \tЕсли устройство не мост(0-бит поля Header Type = 0) вывести  и расшифровать значение полей базовых регистров постоянной (ROM) памяти.\n");
  153.     printf("11. Если устройство  мост(0-бит поля Header Type = 1) вывести  и расшифровать значение поля Сlass Code.\n\n");
  154. }
  155.  
  156. void printTableSplitter()
  157. {
  158.     printf("---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n");
  159. }
  160.  
  161. void printTableStart()
  162. {
  163.     printTableSplitter();
  164.     printf(" Bus | Device | Function | Vendor ID | Device ID |\tVendor Name\t| \t\t\tDevice Name\t\t | ROM B.Reg. |  I/O B.Reg. | ClassCode |\n");
  165.     printTableSplitter();
  166. }
  167.  
  168. void printDevice(const deviceStruct device, const int address)
  169. {
  170.     printf("  %02x |   %02x   |    %01x\t |%8x   |%8x   |%20s  |  %45s | %9x  |     %4x    | %9x |\n", device.bus, device.device, device.function, device.vendorID, device.deviceID, device.vendorName, device.deviceName, device.ROMBR, device.IOBReg, device.clCode);
  171. }
  172. /*      print procedures end      */
  173.  
  174. int main(void)
  175. {
  176.     errno = 0;
  177.     if (iopl(REQUIRED_PRIVILEGE_LEVEL)) // проверка уровня привилегий
  178.     {
  179.         printf("Ошибка изменения уровня привилегий ввода-вывода: %s\nПопробуйте запустить программу, используя пользователя ROOT\n", (char *)strerror(errno));
  180.         return 1;
  181.     }
  182.  
  183.     printTaskInfo();
  184.     printTableStart();
  185.  
  186.     for (int busIndex = 0; busIndex < BUS_NUM; busIndex++)
  187.     {
  188.         for (int deviceIndex = 0; deviceIndex < DEVICE_NUM; deviceIndex++)
  189.         {
  190.             for (int functionIndex = 0; functionIndex < FUNCTION_NUM; functionIndex++)
  191.             {
  192.                 int address = calculateAddress(busIndex, deviceIndex, functionIndex);
  193.                 int data = getPCIData(address);
  194.                 if (DoesDeviceExist(data))
  195.                 {
  196.                     deviceStruct device = constructor(busIndex, deviceIndex, functionIndex, data, address);
  197.                     printDevice(device, address);
  198.                 }
  199.             }
  200.         }
  201.     }
  202.     printTableSplitter();
  203.  
  204.     return 0;
  205. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement