11 #include <lib/stdio.h>
15 #include "../lib/libvector/include/vector.h"
35 uint32_t slot32 = slot;
36 uint32_t func32 =
function;
38 addr = (uint32_t)(((uint32_t)bus << 16) | (slot32 << 11) |
39 (func32 << 8) | (offset & 0xfc) | ((uint32_t)0x80000000));
41 outl(PCI_ADDRESS_PORT, addr);
43 return inl(PCI_DATA_PORT) >> ((offset & 2) * 8);
54 uint32_t
pci_read32(uint8_t bus, uint8_t slot, uint8_t
function, uint8_t offset) {
57 uint32_t slot32 = slot;
58 uint32_t func32 =
function;
59 addr = (uint32_t)((bus32 << 16) | (slot32 << 11) |
60 (func32 << 8) | offset | 0x80000000);
61 outl(PCI_ADDRESS_PORT, addr);
63 return inl(PCI_DATA_PORT);
72 uint8_t klass, subclass;
74 } pci_device_type_strings[] = {
75 {0x00, 0x00,
"Неизвестное устройство"},
76 {0x00, 0x01,
"VGA-совместимое устройство"},
77 {0x01, 0x00,
"Контроллер шины SCSI"},
78 {0x01, 0x01,
"IDE-контроллер"},
79 {0x01, 0x02,
"Контроллер гибких дисков"},
80 {0x01, 0x03,
"Контроллер шины IPI"},
81 {0x01, 0x04,
"RAID-контроллер"},
82 {0x01, 0x05,
"Контроллер АТА"},
83 {0x01, 0x06,
"SATA-контроллер"},
84 {0x01, 0x07,
"Последовательный подключенный контроллер SCSI"},
85 {0x01, 0x80,
"Другой контроллер запоминающих устройств"},
86 {0x02, 0x00,
"Ethernet-контроллер"},
87 {0x02, 0x01,
"Контроллер Token Ring"},
88 {0x02, 0x02,
"FDDI-контроллер"},
89 {0x02, 0x03,
"Контроллер банкомата"},
90 {0x02, 0x04,
"ISDN-контроллер"},
91 {0x02, 0x05,
"Контроллер WorldFip"},
92 {0x02, 0x06,
"PICMG 2.14 Мультивычисления"},
93 {0x02, 0x80,
"Другой сетевой контроллер"},
94 {0x03, 0x00,
"VGA-совместимый контроллер"},
95 {0x03, 0x01,
"XGA-контроллер"},
96 {0x03, 0x02,
"3D контроллер"},
97 {0x03, 0x80,
"Другой контроллер дисплея"},
98 {0x04, 0x00,
"Видео-устройство"},
99 {0x04, 0x01,
"Аудио-устройство"},
100 {0x04, 0x02,
"Компьютерное телефонное устройство"},
101 {0x04, 0x03,
"Аудио-устройство (4.3)"},
102 {0x04, 0x80,
"Другое мультимедийное устройство"},
103 {0x05, 0x00,
"Контроллер оперативной памяти"},
104 {0x05, 0x01,
"Флэш-контроллер"},
105 {0x05, 0x80,
"Другой контроллер памяти"},
106 {0x06, 0x00,
"Хост-мост"},
107 {0x06, 0x01,
"ISA мост"},
108 {0x06, 0x02,
"EISA мост"},
109 {0x06, 0x03,
"MCA мост"},
110 {0x06, 0x04,
"PCI-to-PCI мост"},
111 {0x06, 0x05,
"PCMCIA мост"},
112 {0x06, 0x06,
"NuBus мост"},
113 {0x06, 0x07,
"CardBus мост"},
114 {0x06, 0x08,
"RACEWay мост"},
115 {0x06, 0x09,
"PCI-to-PCI мост (Полупрозрачный)"},
116 {0x06, 0x0A,
"Хост-мост InfiniBand-PCI"},
117 {0x06, 0x80,
"Другое устройство моста"},
118 {0x07, 0x00,
"Последовательный контроллер"},
119 {0x07, 0x01,
"Параллельный порт"},
120 {0x07, 0x02,
"Многопортовый последовательный контроллер"},
121 {0x07, 0x03,
"Универсальный модем"},
122 {0x07, 0x04,
"IEEE 488.1/2 (GPIB) контроллер"},
123 {0x07, 0x05,
"Интеллектуальная карточка"},
124 {0x07, 0x80,
"Другое устройство связи"},
125 {0x08, 0x00,
"Программируемый контроллер прерываний"},
126 {0x08, 0x01,
"Контроллер прямого доступа к памяти"},
127 {0x08, 0x02,
"Системный таймер"},
128 {0x08, 0x03,
"Часы реального времени"},
129 {0x08, 0x04,
"Универсальный контроллер PCI с возможностью горячей замены"},
130 {0x08, 0x80,
"Другая системная периферия"},
131 {0x09, 0x00,
"Контроллер клавиатуры"},
132 {0x09, 0x01,
"Цифровой преобразователь"},
133 {0x09, 0x02,
"Контроллер мыши"},
134 {0x09, 0x03,
"Контроллер сканера"},
135 {0x09, 0x04,
"Контроллер игрового порта"},
136 {0x09, 0x80,
"Другой контроллер ввода"},
137 {0x0A, 0x00,
"Универсальная док-станция"},
138 {0x0A, 0x80,
"Другая док-станция"},
139 {0x0B, 0x00,
"Процессор i386"},
140 {0x0B, 0x01,
"Процессор i486"},
141 {0x0B, 0x02,
"Процессор Pentium"},
142 {0x0B, 0x10,
"Процессор Alpha"},
143 {0x0B, 0x20,
"Процессор PowerPC"},
144 {0x0B, 0x30,
"Процессор MIPS"},
145 {0x0B, 0x40,
"Со-процессор"},
146 {0x0C, 0x00,
"Контроллер FireWire"},
147 {0x0C, 0x01,
"Контроллер ACCESS.bus"},
148 {0x0C, 0x02,
"SSA Контроллер"},
149 {0x0C, 0x03,
"USB Контроллер"},
150 {0x0C, 0x04,
"Волоконный канал"},
151 {0x0C, 0x05,
"SMBus"},
152 {0x0C, 0x06,
"InfiniBand"},
153 {0x0C, 0x07,
"Интерфейс IPMI SMIC"},
154 {0x0C, 0x08,
"Интерфейс SERCOS"},
155 {0x0C, 0x09,
"Интерфейс CANbus"},
156 {0x0D, 0x00,
"iRDA-совместимый контроллер"},
157 {0x0D, 0x01,
"Потребительский ИК-контроллер"},
158 {0x0D, 0x10,
"RF Контроллер"},
159 {0x0D, 0x11,
"Bluetooth Контроллер"},
160 {0x0D, 0x12,
"Broadband Контроллер"},
161 {0x0D, 0x20,
"802.11a (Wi-Fi) Ethernet-контроллер"},
162 {0x0D, 0x21,
"802.11b (Wi-Fi) Ethernet-контроллер"},
163 {0x0D, 0x80,
"Другой беспроводной контроллер"},
164 {0x00, 0x00,
nullptr}
174 } pci_vendor_name_strings[] = {
175 {0x8086,
"Intel Corporation"},
177 {0x0014,
"Loongson Technology Corporation Limited"},
178 {0x001C,
"PEAK-System Technik GmbH"},
179 {0x00B0,
"Blue Origin, LLC"},
180 {0x00BB,
"Bloombase"},
181 {0x0123,
"General Dynamics Mission Systems, Inc."},
182 {0x6688,
"GUANGZHOU MAXSUN INFORMATION TECHNOLOGY CO., LTD."},
183 {0x751A,
"Tesla Inc."},
184 {0x8080,
"StoreSwift Technology Co., Ltd."},
185 {0x1013,
"Cirrus Logic, Inc."},
187 {0x101E,
"American Megatrends Incorporated"},
188 {0x1028,
"Dell Computer Corporation"},
189 {0x102B,
"Matrox Graphics Inc."},
190 {0xA23B,
"Silicon Integrated Systems"},
191 {0x103C,
"Hewlett Packard"},
192 {0x1043,
"Asustek Computer Inc."},
193 {0x104C,
"Texas Instruments"},
194 {0x104D,
"Sony Group Corporation"},
195 {0x1054,
"Hitachi, Ltd."},
196 {0x1002,
"[AMD] Advanced Micro Devices Inc."},
197 {0x1022,
"[AMD] Advanced Micro Devices Inc."},
198 {0x10EC,
"Realtek Semiconductor Corp."},
199 {0x1039,
"[SiS] Silicon Integrated Systems"},
200 {0x0B05,
"[ASUS] ASUSTek Computer, Inc."},
201 {0x80EE,
"[VirtualBox] InnoTek Systemberatung GmbH"},
202 {0x1234,
"[QEMU] Technical Corp"},
203 {0x106B,
"Apple Inc."},
204 {0x1AF4,
"Red Hat, Inc."},
282 for (
int i=0; pci_device_type_strings[i].name !=
nullptr; i++)
283 if (pci_device_type_strings[i].klass == klass && pci_device_type_strings[i].subclass == subclass)
284 return pci_device_type_strings[i].name;
296 for (
int i = 0; pci_vendor_name_strings[i].name !=
nullptr; i++) {
297 if(pci_vendor_name_strings[i].vendor == vendor)
298 return pci_vendor_name_strings[i].name;
318 uint32_t
pci_get_bar(uint8_t hdrtype, uint8_t bus, uint8_t slot, uint8_t func, uint8_t bar_number, uint8_t *bar_type) {
319 if ((hdrtype & ~0x80) == 0) {
320 uint8_t off = bar_number * 2;
323 if ((bar_low & 1) == 0) {
324 if ((bar_low & ~0b110) == 0x00)
326 uint32_t ret = (uint32_t) bar_low | (uint32_t) (bar_high << 16);
332 if ((bar_low & 1) == 1) {
333 uint32_t ret = (uint32_t)bar_low | (uint32_t)(bar_high << 16);
342 void pci_write(uint8_t bus, uint8_t slot, uint8_t func, uint32_t offset, uint32_t value) {
343 uint32_t addr = (bus << 16) | (slot << 11) | (func << 8) | (offset & 0xfc) | ((uint32_t)0x80000000);
347 outl(PCI_ADDRESS_PORT, addr);
349 outl(PCI_DATA_PORT, value);
362 void pci_find_device(uint16_t vendor, uint16_t device, uint8_t *bus_ret, uint8_t *slot_ret, uint8_t *func_ret) {
379 assert(pci_device_list == 0,
"DEVICE LIST IS NULL!");
381 for(
int i = 0; i < pci_device_list->size; i++) {
383 if(dev->vendor_id == vendor && dev->device_id == device) {
385 *slot_ret = dev->slot;
386 *func_ret = dev->func;
391 *bus_ret = *slot_ret = *func_ret = 0xFF;
394 void pci_find_device_by_class_and_subclass(uint16_t
class, uint16_t subclass, uint16_t *vendor_ret, uint16_t *deviceid_ret,
395 uint8_t *bus_ret, uint8_t *slot_ret, uint8_t *func_ret) {
398 for (uint32_t bus = 0; bus < 256; bus++) {
399 for (uint32_t slot = 0; slot < 32; slot++) {
408 qemu_ok(
"! FOUND %d.%d.%d", *bus_ret, *slot_ret, *func_ret);
413 for (func = 1; func < 8; func++) {
423 qemu_ok(
"!! FOUND %d.%d.%d", *bus_ret, *slot_ret, *func_ret);
431 *vendor_ret = *deviceid_ret = 0;
432 *bus_ret = *slot_ret = *func_ret = 0xFF;
435 void pci_enable_bus_mastering(uint8_t bus, uint8_t slot, uint8_t func) {
438 command_register |= 0x05;
440 pci_write(bus, slot, func, 4, command_register);
443 void pci_print_nth(uint8_t
class, uint8_t subclass, uint8_t bus, uint8_t slot, uint8_t hdr, uint16_t vendor, uint16_t device, uint8_t func) {
444 _tty_printf(
"%d:%d:%d:%d.%d %s: %s (%x), девайс: %x ",
455 if((hdr & 0x80) == 0) {
456 _tty_printf(
"[Multifunc]");
459 uint32_t bar0 =
pci_read32(bus, slot, func, 0x10 + (0 * 4));
460 uint32_t bar1 =
pci_read32(bus, slot, func, 0x10 + (1 * 4));
461 uint32_t bar2 =
pci_read32(bus, slot, func, 0x10 + (2 * 4));
462 uint32_t bar3 =
pci_read32(bus, slot, func, 0x10 + (3 * 4));
463 uint32_t bar4 =
pci_read32(bus, slot, func, 0x10 + (4 * 4));
464 uint32_t bar5 =
pci_read32(bus, slot, func, 0x10 + (5 * 4));
466 tty_printf(
"\nAddresses: [%-10x, %-10x, %-10x, %-10x, %-10x, %-10x]",
477 void pci_scan_everything() {
478 if(pci_device_list == 0) {
479 pci_device_list = vector_new();
481 for(
int i = 0; i < pci_device_list->size; i++) {
482 kfree((
void *) vector_get(pci_device_list, i).element);
485 vector_erase_all(pci_device_list);
488 size_t start_time = timestamp();
490 for (uint32_t bus = 0; bus < 256; bus++) {
491 for (uint8_t slot = 0; slot < 32; slot++) {
493 uint16_t hdrtype = 0, clid = 0, sclid = 0, device = 0;
497 if (vendor != 0xFFFF) {
505 dev->subclass = sclid;
509 dev->hdrtype = hdrtype | 0x80;
510 dev->vendor_id = vendor;
511 dev->device_id = device;
513 vector_push_back(pci_device_list, (
size_t)dev);
516 if ((hdrtype & 0x80) == 0) {
517 for (func = 1; func < 8; func++) {
520 if (vendor != 0xFFFF) {
527 dev->subclass = sclid;
530 dev->hdrtype = hdrtype;
532 dev->vendor_id = vendor;
533 dev->device_id = device;
535 vector_push_back(pci_device_list, (
size_t)dev);
542 size_t elapsed = timestamp() - start_time;
543 qemu_log(
"PCI scan end in %d ms", elapsed);
544 qemu_log(
"Found %d devices", pci_device_list->size);
589 void pci_print_list() {
590 for(
int i = 0; i < pci_device_list->size; i++) {
uint32_t pci_get_bar(uint8_t hdrtype, uint8_t bus, uint8_t slot, uint8_t func, uint8_t bar_number, uint8_t *bar_type)
[PCI] ???
uint16_t pci_read_confspc_word(uint8_t bus, uint8_t slot, uint8_t function, uint8_t offset)
[PCI] Чтение 16-битных полей из пространства механизма конфигураций 1
void pci_find_device(uint16_t vendor, uint16_t device, uint8_t *bus_ret, uint8_t *slot_ret, uint8_t *func_ret)
[PCI] Поиск устройства по ID-поставшика и устройства
uint8_t pci_get_hdr_type(uint8_t bus, uint8_t slot, uint8_t function)
[PCI] Получение HDR-тип устройства
uint16_t pci_get_vendor(uint8_t bus, uint8_t slot, uint8_t function)
[PCI] Получение ID-поставщика
const char * pci_get_device_type(uint8_t klass, uint8_t subclass)
[PCI] Получение классификации устройства
const char * pci_get_vendor_name(uint16_t vendor)
[PCI] Получение названия поставщика
uint32_t pci_read32(uint8_t bus, uint8_t slot, uint8_t function, uint8_t offset)
Чтение данных из шины PCI.
uint8_t pci_get_class(uint8_t bus, uint8_t slot, uint8_t function)
[PCI] Получение основной категории устройства
uint16_t pci_get_device(uint8_t bus, uint8_t slot, uint8_t function)
[PCI] Получение ID-Устройства
uint8_t pci_get_subclass(uint8_t bus, uint8_t slot, uint8_t function)
[PCI] Получение под-категории устройства