SayoriOS  0.3.3
virtio_network.c
1 
9 #include "../../../include/drv/network/virtio_network.h"
10 #include <drv/rtl8139.h>
11 #include <net/cards.h>
12 #include <drv/pci.h>
13 #include <io/ports.h>
14 #include <net/endianess.h>
15 #include <net/ethernet.h>
16 #include <debug/hexview.h>
17 #include <sys/isr.h>
18 #include "lib/string.h"
19 #include "mem/vmm.h"
20 #include "mem/pmm.h"
21 
22 /*
23  *
24 1. Найдите устройство PCI с поставщиком/устройством 1af4/1000.
25 2. Получите BAR0 для этого устройства.
26 3. Запишите 0x01 в BAR0+0x12, чтобы подтвердить, что вы обнаружили устройство.
27 4. Запишите 0x03 в BAR0+0x12, чтобы уведомить хост о загрузке драйвера.
28 5. Запишите 0x00000000 в BAR0+0x0E, чтобы выбрать Очередь 0.
29 6. Запишите 0x00000100 в BAR0+0x08, чтобы установить адрес очереди 0x00100000.
30 [SKIP??] Запишите 0x00000001 в BAR0+0x0E, чтобы выбрать Очередь 1.
31 [SKIP??] Запишите 0x00000120 в BAR0+0x08, чтобы установить адрес очереди 0x00120000.
32 [SKIP??] Настройте цепочки буферов в памяти для обеих очередей.
33 7. Запишите 0x00010020 в BAR0+0x04, чтобы установить флаги гостевой функции.
34 8. Запишите 0x07 в BAR0+0x12, чтобы уведомить хост о готовности драйвера.
35 9. Запишите 0x00 в BAR0+0x10, чтобы уведомить хост о том, что очередь 0 была изменена драйвером.
36 
37  */
38 void vio_ntw_init(){
39  qemu_log("[VirtIO] [Network] Init");
40  uint8_t busnum, slot, func;
41  uint32_t io_base, mem_base, bar_type;
42  uint8_t mac[6];
43  size_t phys_buffer = 0;
44  char* virt_buffer = (char*)0;
45 
46 
47  size_t phys_buffer2 = 0;
48  char* virt_buffer2 = (char*)0;
49 
50  void* transfer_buffer;
51  size_t transfer_buffer_phys;
52 
53 
54  pci_find_device(VIO_NET_VENDOR, VIO_NET_DEVICE,
55  &busnum, &slot, &func);
56  uint16_t devnum = pci_get_device(busnum, slot, func);
57 
58  qemu_log("[VirtIO] [Network] ID: %d (%x)", devnum, devnum);
59 
60  if(devnum == PCI_VENDOR_NO_DEVICE) {
61  qemu_err("[VirtIO] [Network] Error is not connected!");
62  return;
63  } else {
64  qemu_ok("Detected VirtIO Network");
65  }
66 
67  uint32_t ret = pci_read_confspc_word(busnum, slot, func, 0x10); // BAR0
68 
69  // If bar type is 0 use memory-based access, use port-based otherwise.
70  bar_type = ret & 0x1;
71  io_base = ret & (~0x3);
72  mem_base = ret & (~0xf);
73 
74  qemu_log("[VirtIO] [Network] BAR TYPE: %d; IO BASE: %x; MEMORY BASE: %x", bar_type, io_base, mem_base);
75 
76 
77  uint32_t mac_part1 = inl(io_base + VIO_NAT_NDR_MAC1P);
78  uint16_t mac_part2 = inw(io_base + VIO_NAT_NDR_MAC2P);
79 
80  mac[0] = (mac_part1 >> 0) & 0xFF;
81  mac[1] = mac_part1 >> 8;
82  mac[2] = mac_part1 >> 16;
83  mac[3] = mac_part1 >> 24;
84 
85  mac[4] = mac_part2 >> 0;
86  mac[5] = mac_part2 >> 8;
87 
88  qemu_log("Mac is: %v:%v:%v:%v:%v:%v", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
89 
90  // Создаем буферы
91 
92  virt_buffer = kmalloc_common(4, PAGE_SIZE);
93  phys_buffer = virt2phys(get_kernel_page_directory(), (virtual_addr_t) virt_buffer);
94 
95  virt_buffer2 = kmalloc_common(4, PAGE_SIZE);
96  phys_buffer2 = virt2phys(get_kernel_page_directory(), (virtual_addr_t) virt_buffer2);
97 
98 
99  transfer_buffer = kmalloc_common(65550, PAGE_SIZE);
100  transfer_buffer_phys = virt2phys(get_kernel_page_directory(), (virtual_addr_t)transfer_buffer);
101 
102  // 3. Запишите 0x01 в BAR0+0x12, чтобы подтвердить, что вы обнаружили устройство.
103  outl(io_base + VIO_NAT_IDR_DS, 0x01);
104  // 4. Запишите 0x03 в BAR0+0x12, чтобы уведомить хост о загрузке драйвера.
105  outl(io_base + VIO_NAT_IDR_DS, 0x03);
106  // 5. Запишите 0x00000000 в BAR0+0x0E, чтобы выбрать Очередь 0.
107  outl(io_base + VIO_NAT_IDR_QS, 0x01);
108  // 6. Запишите 0x00000100 в BAR0+0x08, чтобы установить адрес очереди 0x00100000.
109  outl(io_base + VIO_NAT_IDR_QA, phys_buffer);
110  // 7. Запишите 0x00010020 в BAR0+0x04, чтобы установить флаги гостевой функции.
111  outl(io_base + VIO_NAT_IDR_GF, 0x00010020);
112  // 8. Запишите 0x07 в BAR0+0x12, чтобы уведомить хост о готовности драйвера.
113  outl(io_base + VIO_NAT_IDR_DS, 0x01);
114  // 9. Запишите 0x00 в BAR0+0x10, чтобы уведомить хост о том, что очередь 0 была изменена драйвером.
115  outl(io_base + VIO_NAT_IDR_QN, 0x00);
116 
117 }
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
uint16_t pci_get_device(uint8_t bus, uint8_t slot, uint8_t function)
[PCI] Получение ID-Устройства
Definition: pci.c:269