Advertisement
anticlown

Lab_4(another header, now with classcodes' names)

Nov 13th, 2023 (edited)
720
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.47 KB | None | 0 0
  1. #include "stdio.h"
  2. #include "pci_c.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.  
  20. #define PCI_PORT_VMWARE_DEV "PCI Express Root Port"
  21. #define PCI_X_VMWARE_DEV "PCI-X Fusion-MPT Dual Ultra320 SCSI"
  22. #define USB_VMWARE_DEV "USB1.1 UHCI Controller"
  23. #define SATA_VMWARE_DEV "SATA AHCI controller"
  24. #define UNKNOWN_MSG "Unknown"
  25.  
  26. #define NUM_OF_VENDORS (sizeof(PciVenTable) / sizeof(PCI_VENTABLE))
  27. #define NUM_OF_DEVICES (sizeof(PciDevTable) / sizeof(PCI_DEVTABLE))
  28. #define NUM_OF_CLASSES (sizeof(PciClassCodeTable) / sizeof(PCI_CLASSCODETABLE))
  29.  
  30. #define BUS_NUM 256
  31. #define DEVICE_NUM 32
  32. #define FUNCTION_NUM 8
  33. /*  define end    */
  34.  
  35. /*    PCI methods start    */
  36. int calculateAddress(const int bus, const int device, const int function)
  37. {
  38.     return ENABLE_BIT + (bus << BUS_OFFSET) + (device << DEVICE_OFFSET) + (function << FUNCTION_OFFSET);
  39. }
  40.  
  41. int getPCIData(const int address)
  42. {
  43.     outl(address, CONFIG_ADDRESS_PORT); // прочитать по адресу
  44.     return inl(CONFIG_DATA_PORT);       // записать по адресу
  45. }
  46.  
  47. int readPCIDataField(const int data, const int offset)
  48. {
  49.     return (int)((data >> ((offset & 2) * 8)) & 0xFFFF);
  50. }
  51. /*    PCI methods end    */
  52.  
  53. /*    device methods start    */
  54. bool DoesDeviceExist(const int data)
  55. {
  56.     return data != -1;
  57. }
  58.  
  59. char *getVendorName(const int vendorID)
  60. {
  61.     for (int i = 0; i < NUM_OF_VENDORS; i++)
  62.         if (PciVenTable[i].VenId == vendorID)
  63.             return PciVenTable[i].VenFull;
  64.  
  65.     return UNKNOWN_MSG; // в случае, если не находится имя, выводится Unknown
  66. }
  67.  
  68. char *getDeviceName(const int vendorID, const int deviceID)
  69. {
  70.     for (int i = 0; i < NUM_OF_DEVICES; i++)
  71.     {
  72.         if (PciDevTable[i].VenId == vendorID && PciDevTable[i].DevId == deviceID)
  73.             return PciDevTable[i].Chip;
  74.         if (vendorID == 0x15AD && deviceID == 0x07a0)
  75.             return PCI_PORT_VMWARE_DEV;
  76.         if (vendorID == 0x15AD && deviceID == 0x0790)
  77.             return PCI_X_VMWARE_DEV;
  78.         if (vendorID == 0x15AD && deviceID == 0x0774)
  79.             return USB_VMWARE_DEV;
  80.         if (vendorID == 0x15AD && deviceID == 0x07e0)
  81.             return SATA_VMWARE_DEV;
  82.     }
  83.  
  84.     return UNKNOWN_MSG; // в случае, если не находится имя, выводится Unknown
  85. }
  86.  
  87. bool isBridge(const unsigned address)
  88. {
  89.     outl(address + 0x0C, CONFIG_ADDRESS_PORT);
  90.     //return (inl(CONFIG_DATA_PORT) >> 16) != 0;
  91.     return (inl(CONFIG_DATA_PORT) >> 16) & 1;
  92. }
  93.  
  94. int decodeROMBaseRegisters(const int address)
  95. {
  96.     if (!isBridge(address))
  97.     {
  98.         outl(address + 0x1C, CONFIG_ADDRESS_PORT);
  99.         int inter = inl(CONFIG_DATA_PORT);
  100.         return inter >> 11;
  101.     }
  102.     else
  103.         return 0;
  104. }
  105.  
  106. int decodeInputRegs(const int address)
  107. {
  108.     if (!isBridge(address))
  109.     {
  110.         for (int i = 0; i < 6; i++)
  111.         {
  112.             outl(address + 0x10 + i * 4, CONFIG_ADDRESS_PORT);
  113.             unsigned barValue = inl(CONFIG_DATA_PORT);
  114.             if ((barValue & 1) == 1) //является ли регистром ввода-вывода
  115.                 return barValue >> 2;
  116.         }
  117.         return 0;
  118.     }
  119.     else
  120.         return 0;
  121. }
  122.  
  123. int decodeClassCode(const int address)
  124. {
  125.     if (isBridge(address))
  126.     {
  127.         outl(address + 0x08, CONFIG_ADDRESS_PORT);
  128.         int inter = inl(CONFIG_DATA_PORT);
  129.         return inter >> 8; //Prog. I/F(8..15) + SubClass Code(16..23) + ClassCode(24..31)
  130.     }
  131.     else
  132.         return 0;
  133. }
  134.  
  135. char *getClassName(const int classCode)
  136. {
  137.     int baseClass = classCode / 0x10000;
  138.     int subClass = (classCode / 0x100) % 0x100;
  139.     int prog = classCode % 0x100;
  140.     for (int i = 0; i < NUM_OF_CLASSES; i++)
  141.     {
  142.         if (classCode == 0x0)
  143.             return UNKNOWN_MSG;
  144.         if (PciClassCodeTable[i].BaseClass == baseClass && PciClassCodeTable[i].SubClass == subClass && PciClassCodeTable[i].ProgIf == prog)
  145.             return PciClassCodeTable[i].SubDesc;
  146.     }
  147.  
  148.     return UNKNOWN_MSG; // в случае, если не находится имя, выводится Unknown
  149. }
  150.  
  151. // device structure
  152. typedef struct
  153. {
  154.     int bus;
  155.     int device;
  156.     int function;
  157.     int vendorID;
  158.     int deviceID;
  159.     char *vendorName;
  160.     char *deviceName;
  161.     int ROMBR;  // ROM Base Registers
  162.     int IOBReg; // I/O Base Registers
  163.     int clCode; // ClassCode
  164.     char* clCodeName;
  165. } deviceStruct;
  166.  
  167. deviceStruct constructor(const int bus, const int device, const int function, const int data, const int address)
  168. {
  169.     int vendorID = readPCIDataField(data, VENDOR_ID_OFFSET);
  170.     int deviceID = readPCIDataField(data, DEVICE_ID_OFFSET);
  171.     char *vendorName = getVendorName(vendorID);
  172.     char *deviceName = getDeviceName(vendorID, deviceID);
  173.     int ROMBaseReg = decodeROMBaseRegisters(address);
  174.     int inputBaseRegs = decodeInputRegs(address);
  175.     int classCode = decodeClassCode(address);
  176.     char *classCodeName = getClassName(classCode);
  177.     deviceStruct temp = {bus, device, function, vendorID, deviceID, vendorName, deviceName, ROMBaseReg, inputBaseRegs, classCode, classCodeName};
  178.  
  179.     return temp;
  180. }
  181. /*    device methods end    */
  182.  
  183. /*      print procedures start      */
  184. void printTaskInfo()
  185. {
  186.     printf("\n\tДанная программа формирует цикл опроса и идентификации устройств PCI, затем выводит информацию о них в сводной таблице.\n \t\t\t\t\t\tДоп. задания:\n");
  187.     printf("3.  \tЕсли устройство не мост(0-бит поля Header Type = 0) вывести  и расшифровать значение полей базовых регистров ввода/вывода.\n");
  188.     printf("4.  \tЕсли устройство не мост(0-бит поля Header Type = 0) вывести  и расшифровать значение полей базовых регистров постоянной (ROM) памяти.\n");
  189.     printf("11. Если устройство  мост(0-бит поля Header Type = 1) вывести  и расшифровать значение поля Сlass Code.\n\n");
  190. }
  191.  
  192. void printTableSplitter()
  193. {
  194.     printf("---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n");
  195. }
  196.  
  197. void printTableStart()
  198. {
  199.     printTableSplitter();
  200.     printf(" Bus | Device | Function | Vendor ID | Device ID |\tVendor Name\t| \t\tDevice Name\t\t | ROM B.Reg. |  I/O B.Reg. | ClassCode | ClassCode Name |\n");
  201.     printTableSplitter();
  202. }
  203.  
  204. void printDevice(const deviceStruct device, const int address)
  205. {
  206.     printf("  %02x |   %02x   |    %01x\t |%8x   |%8x   |%20s  |  %36s  | %9x  |     %4x    | %9x | %14s |\n", device.bus, device.device, device.function, device.vendorID, device.deviceID, device.vendorName, device.deviceName, device.ROMBR, device.IOBReg, device.clCode, device.clCodeName);
  207. }
  208. /*      print procedures end      */
  209.  
  210. int main(void)
  211. {
  212.     errno = 0;
  213.     if (iopl(REQUIRED_PRIVILEGE_LEVEL)) // проверка уровня привилегий
  214.     {
  215.         printf("Ошибка изменения уровня привилегий ввода-вывода: %s\nПопробуйте запустить программу, используя пользователя ROOT\n", (char *)strerror(errno));
  216.         return 1;
  217.     }
  218.  
  219.     printTaskInfo();
  220.     printTableStart();
  221.  
  222.     for (int busIndex = 0; busIndex < BUS_NUM; busIndex++)
  223.     {
  224.         for (int deviceIndex = 0; deviceIndex < DEVICE_NUM; deviceIndex++)
  225.         {
  226.             for (int functionIndex = 0; functionIndex < FUNCTION_NUM; functionIndex++)
  227.             {
  228.                 int address = calculateAddress(busIndex, deviceIndex, functionIndex);
  229.                 int data = getPCIData(address);
  230.                 if (DoesDeviceExist(data))
  231.                 {
  232.                     deviceStruct device = constructor(busIndex, deviceIndex, functionIndex, data, address);
  233.                     printDevice(device, address);
  234.                 }
  235.             }
  236.         }
  237.     }
  238.     printTableSplitter();
  239.  
  240.     return 0;
  241. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement