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 }
pci_read_confspc_word
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
pci_find_device
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
pci_get_device
uint16_t pci_get_device(uint8_t bus, uint8_t slot, uint8_t function)
[PCI] Получение ID-Устройства
Definition: pci.c:269