SayoriOS  0.3.3
pci.c
См. документацию.
1 
11 #include <lib/stdio.h>
12 #include <io/ports.h>
13 #include <drv/pci.h>
14 #include "io/tty.h"
15 #include "../lib/libvector/include/vector.h"
16 #include "mem/vmm.h"
17 
18 vector_t* pci_device_list = 0;
19 
32 uint16_t pci_read_confspc_word(uint8_t bus, uint8_t slot, uint8_t function, uint8_t offset) {
33  uint32_t addr;
34  // uint32_t bus32 = bus;
35  uint32_t slot32 = slot;
36  uint32_t func32 = function;
37 
38  addr = (uint32_t)(((uint32_t)bus << 16) | (slot32 << 11) |
39  (func32 << 8) | (offset & 0xfc) | ((uint32_t)0x80000000)); //yes, this line is copied from osdev
40 
41  outl(PCI_ADDRESS_PORT, addr);
42 
43  return inl(PCI_DATA_PORT) >> ((offset & 2) * 8);
44 }
45 
54 uint32_t pci_read32(uint8_t bus, uint8_t slot, uint8_t function, uint8_t offset) {
55  uint32_t addr;
56  uint32_t bus32 = bus;
57  uint32_t slot32 = slot;
58  uint32_t func32 = function;
59  addr = (uint32_t)((bus32 << 16) | (slot32 << 11) |
60  (func32 << 8) | offset | 0x80000000); //yes, this line is copied from osdev
61  outl(PCI_ADDRESS_PORT, addr);
62  // return ((inl(PCI_DATA_PORT) >> ((offset & 2) * 8)) & 0xffffffff); //this too... I'm too lazy to write them
63  return inl(PCI_DATA_PORT); //this too... I'm too lazy to write them
64 }
65 
66 
71 static struct {
72  uint8_t klass, subclass;
73  const char *name;
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} // Конец
165 };
166 
171 static struct {
172  uint16_t vendor;
173  const char *name;
174 } pci_vendor_name_strings[] = {
175  {0x8086, "Intel Corporation"},
176  {0x10DE, "NVIDIA"},
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."},
186  {0x1014, "IBM"},
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."},
205  {0, nullptr}
206 };
207 
217 inline uint8_t pci_get_class(uint8_t bus, uint8_t slot, uint8_t function) {
218  /* Сдвигаем, чтобы оставить только нужные данные в переменной */
219  return (uint8_t) (pci_read_confspc_word(bus, slot, function, 10) >> 8);
220 }
221 
230 inline uint8_t pci_get_subclass(uint8_t bus, uint8_t slot, uint8_t function) {
231  /* Сдвигаем, чтобы оставить только нужные данные в переменной */
232  return (uint8_t) pci_read_confspc_word(bus, slot, function, 10);
233 }
234 
243 inline uint8_t pci_get_hdr_type(uint8_t bus, uint8_t slot, uint8_t function) {
244  /* Сдвигаем, чтобы оставить только нужные данные в переменной */
245  return (uint8_t) pci_read_confspc_word(bus, slot, function, 7);
246 }
247 
256 inline uint16_t pci_get_vendor(uint8_t bus, uint8_t slot, uint8_t function) {
257  /* Сдвигаем, чтобы оставить только нужные данные в переменной */
258  return pci_read_confspc_word(bus, slot, function, 0);
259 }
260 
269 inline uint16_t pci_get_device(uint8_t bus, uint8_t slot, uint8_t function) {
270  /* Сдвигаем, чтобы оставить только нужные данные в переменной */
271  return pci_read_confspc_word(bus, slot, function, 2);
272 }
273 
281 const char *pci_get_device_type(uint8_t klass, uint8_t subclass) {
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;
285 
286  return nullptr;
287 }
288 
295 const char *pci_get_vendor_name(uint16_t vendor) {
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;
299  }
300 
301  return "unknown";
302 }
303 
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;
321  uint16_t bar_low = pci_read_confspc_word(bus, slot, func, 0x10 + off);
322  uint16_t bar_high = pci_read_confspc_word(bus, slot, func, 0x10 + off + 1);
323  if ((bar_low & 1) == 0) {
324  if ((bar_low & ~0b110) == 0x00) // 32 бит. 64 бит нужно добавить!
325  {
326  uint32_t ret = (uint32_t) bar_low | (uint32_t) (bar_high << 16);
327  ret &= ~0b1111;
328  *bar_type = 0;
329  return ret;
330  }
331  }
332  if ((bar_low & 1) == 1) {
333  uint32_t ret = (uint32_t)bar_low | (uint32_t)(bar_high << 16);
334  ret &= ~0b11;
335  *bar_type = 1;
336  return ret;
337  }
338  }
339  return 0;
340 }
341 
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);
344  // uint32_t addr = 0x80000000 | (bus << 16) | (slot << 11) | (func << 8) | offset;
345  // qemu_log("PCI Write to: %x; Value: %d (%x)", addr, value, value);
346  // Tell where we want to write
347  outl(PCI_ADDRESS_PORT, addr);
348  // Value to write
349  outl(PCI_DATA_PORT, value);
350  // qemu_log("Ok.");
351 }
352 
362 void pci_find_device(uint16_t vendor, uint16_t device, uint8_t *bus_ret, uint8_t *slot_ret, uint8_t *func_ret) {
363 // qemu_log("Checking device: %x:%x\n", vendor, device);
364 
365 // for (uint32_t bus = 0; bus < 256; bus++) {
366 // for (uint32_t slot = 0; slot < 32; slot++) {
367 // for (uint32_t func = 0; func < 8; func++) {
368 // if (pci_get_device(bus, slot, func) == device
369 // && pci_get_vendor(bus, slot, func) == vendor) {
370 // *bus_ret = bus;
371 // *slot_ret = slot;
372 // *func_ret = func;
373 // return;
374 // }
375 // }
376 // }
377 // }
378 
379  assert(pci_device_list == 0, "DEVICE LIST IS NULL!");
380 
381  for(int i = 0; i < pci_device_list->size; i++) {
382  pci_device_t *dev = (pci_device_t*)pci_device_list->data[i];
383  if(dev->vendor_id == vendor && dev->device_id == device) {
384  *bus_ret = dev->bus;
385  *slot_ret = dev->slot;
386  *func_ret = dev->func;
387  return;
388  }
389  }
390 
391  *bus_ret = *slot_ret = *func_ret = 0xFF;
392 }
393 
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) {
396  uint8_t func;
397 
398  for (uint32_t bus = 0; bus < 256; bus++) {
399  for (uint32_t slot = 0; slot < 32; slot++) {
400  if (pci_get_class(bus, slot, 0) == class
401  && pci_get_subclass(bus, slot, 0) == subclass) {
402  *vendor_ret = pci_get_vendor(bus, slot, 0);
403  *deviceid_ret = pci_get_device(bus, slot, 0);
404  *bus_ret = bus;
405  *slot_ret = slot;
406  *func_ret = 0;
407 
408  qemu_ok("! FOUND %d.%d.%d", *bus_ret, *slot_ret, *func_ret);
409  return;
410  }
411 
412  if((pci_get_hdr_type(bus, slot, 0) & 0x80) == 0) {
413  for (func = 1; func < 8; func++) {
414  if (pci_get_class(bus, slot, func) == class
415  && pci_get_subclass(bus, slot, func) == subclass) {
416  *vendor_ret = pci_get_vendor(bus, slot, func);
417  *deviceid_ret = pci_get_device(bus, slot, func);
418  *bus_ret = bus;
419  *slot_ret = slot;
420  *func_ret = func;
421 
422 
423  qemu_ok("!! FOUND %d.%d.%d", *bus_ret, *slot_ret, *func_ret);
424  return;
425  }
426  }
427  }
428  }
429  }
430 
431  *vendor_ret = *deviceid_ret = 0;
432  *bus_ret = *slot_ret = *func_ret = 0xFF;
433 }
434 
435 void pci_enable_bus_mastering(uint8_t bus, uint8_t slot, uint8_t func) {
436  uint16_t command_register = pci_read_confspc_word(bus, slot, func, 4);
437 
438  command_register |= 0x05;
439 
440  pci_write(bus, slot, func, 4, command_register);
441 }
442 
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 ",
445  class,
446  subclass,
447  bus,
448  slot,
449  func,
450  pci_get_device_type(class, subclass),
451  pci_get_vendor_name(vendor),
452  vendor,
453  device);
454 
455  if((hdr & 0x80) == 0) {
456  _tty_printf("[Multifunc]");
457  }
458 
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));
465 
466  tty_printf("\nAddresses: [%-10x, %-10x, %-10x, %-10x, %-10x, %-10x]",
467  bar0,
468  bar1,
469  bar2,
470  bar3,
471  bar4,
472  bar5);
473 
474  _tty_printf("\n");
475 }
476 
477 void pci_scan_everything() {
478  if(pci_device_list == 0) {
479  pci_device_list = vector_new();
480  } else {
481  for(int i = 0; i < pci_device_list->size; i++) {
482  kfree((void *) vector_get(pci_device_list, i).element);
483  }
484 
485  vector_erase_all(pci_device_list);
486  }
487 
488  size_t start_time = timestamp();
489 
490  for (uint32_t bus = 0; bus < 256; bus++) {
491  for (uint8_t slot = 0; slot < 32; slot++) {
492  uint32_t func = 0;
493  uint16_t hdrtype = 0, clid = 0, sclid = 0, device = 0;
494 
495  uint16_t vendor = pci_get_vendor(bus, slot, func);
496 
497  if (vendor != 0xFFFF) {
498  clid = pci_get_class(bus, slot, func);
499  sclid = pci_get_subclass(bus, slot, func);
500  hdrtype = pci_get_hdr_type(bus, slot, func);
501  device = pci_get_device(bus, slot, func);
502 
503  pci_device_t* dev = kcalloc(1, sizeof(pci_device_t));
504  dev->klass = clid;
505  dev->subclass = sclid;
506  dev->bus = bus;
507  dev->slot = slot;
508  dev->func = func;
509  dev->hdrtype = hdrtype | 0x80;
510  dev->vendor_id = vendor;
511  dev->device_id = device;
512 
513  vector_push_back(pci_device_list, (size_t)dev);
514  }
515 
516  if ((hdrtype & 0x80) == 0) {
517  for (func = 1; func < 8; func++) {
518  vendor = pci_get_vendor(bus, slot, func);
519 
520  if (vendor != 0xFFFF) {
521  clid = pci_get_class(bus, slot, func);
522  sclid = pci_get_subclass(bus, slot, func);
523  device = pci_get_device(bus, slot, func);
524 
525  pci_device_t* dev = kcalloc(1, sizeof(pci_device_t));
526  dev->klass = clid;
527  dev->subclass = sclid;
528  dev->bus = bus;
529  dev->slot = slot;
530  dev->hdrtype = hdrtype;
531  dev->func = func;
532  dev->vendor_id = vendor;
533  dev->device_id = device;
534 
535  vector_push_back(pci_device_list, (size_t)dev);
536  }
537  }
538  }
539  }
540  }
541 
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);
545 }
546 
547 //void pci_print_list() {
548 // uint8_t clid;
549 // uint8_t sclid;
550 // uint8_t hdrtype;
551 // uint16_t vendor;
552 // uint16_t device;
553 //
554 // tty_printf("PCI список устройств:\n");
555 // for (uint32_t bus = 0; bus < 256; bus++) {
556 // for (uint8_t slot = 0; slot < 32; slot++) {
557 // uint32_t func = 0;
558 //
559 // vendor = pci_get_vendor(bus, slot, func);
560 //
561 // if (vendor != 0xFFFF) {
562 // clid = pci_get_class(bus, slot, func);
563 // sclid = pci_get_subclass(bus, slot, func);
564 // hdrtype = pci_get_hdr_type(bus, slot, func);
565 // device = pci_get_device(bus, slot, func);
566 //
567 // pci_print_nth(clid, sclid, bus, slot, hdrtype | 0x80, vendor, device, func);
568 // }
569 //
570 // if ((hdrtype & 0x80) == 0) {
571 // for (func = 1; func < 8; func++) {
572 // vendor = pci_get_vendor(bus, slot, func);
573 //
574 // if (vendor != 0xFFFF) {
575 // clid = pci_get_class(bus, slot, func);
576 // sclid = pci_get_subclass(bus, slot, func);
577 // device = pci_get_device(bus, slot, func);
578 //
579 // pci_print_nth(clid, sclid, bus, slot, hdrtype, vendor, device, func);
580 // }
581 // }
582 // }
583 // }
584 // }
585 //
586 // qemu_log("PCI scan end");
587 //}
588 
589 void pci_print_list() {
590  for(int i = 0; i < pci_device_list->size; i++) {
591  pci_device_t* device = (pci_device_t*)pci_device_list->data[i];
592 
593  pci_print_nth(
594  device->klass,
595  device->subclass,
596  device->bus,
597  device->slot,
598  device->hdrtype,
599  device->vendor_id,
600  device->device_id,
601  device->func
602  );
603  }
604 }
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] ???
Definition: pci.c:318
uint16_t pci_read_confspc_word(uint8_t bus, uint8_t slot, uint8_t function, uint8_t offset)
[PCI] Чтение 16-битных полей из пространства механизма конфигураций 1
Definition: pci.c:32
void pci_find_device(uint16_t vendor, uint16_t device, uint8_t *bus_ret, uint8_t *slot_ret, uint8_t *func_ret)
[PCI] Поиск устройства по ID-поставшика и устройства
Definition: pci.c:362
uint8_t pci_get_hdr_type(uint8_t bus, uint8_t slot, uint8_t function)
[PCI] Получение HDR-тип устройства
Definition: pci.c:243
uint16_t pci_get_vendor(uint8_t bus, uint8_t slot, uint8_t function)
[PCI] Получение ID-поставщика
Definition: pci.c:256
const char * pci_get_device_type(uint8_t klass, uint8_t subclass)
[PCI] Получение классификации устройства
Definition: pci.c:281
const char * pci_get_vendor_name(uint16_t vendor)
[PCI] Получение названия поставщика
Definition: pci.c:295
uint32_t pci_read32(uint8_t bus, uint8_t slot, uint8_t function, uint8_t offset)
Чтение данных из шины PCI.
Definition: pci.c:54
uint8_t pci_get_class(uint8_t bus, uint8_t slot, uint8_t function)
[PCI] Получение основной категории устройства
Definition: pci.c:217
uint16_t pci_get_device(uint8_t bus, uint8_t slot, uint8_t function)
[PCI] Получение ID-Устройства
Definition: pci.c:269
uint8_t pci_get_subclass(uint8_t bus, uint8_t slot, uint8_t function)
[PCI] Получение под-категории устройства
Definition: pci.c:230
Definition: vector.h:7