SayoriOS 0.3.3

rtl8139.c
1
9 #include <drv/rtl8139.h>
10 #include <net/cards.h>
11 #include <drv/pci.h>
12 #include <io/ports.h>
13 #include <net/endianess.h>
14 #include <net/ethernet.h>
15 #include <debug/hexview.h>
16 #include <sys/isr.h>
17 #include "lib/string.h"
18 #include "mem/vmm.h"
19 #include "mem/pmm.h"
20 #include "net/stack.h"
21
22 uint8_t rtl8139_busnum, rtl8139_slot, rtl8139_func;
23 uint32_t rtl8139_io_base, rtl8139_mem_base, rtl8139_bar_type;
24
25 size_t rtl8139_phys_buffer = 0;
26 char* rtl8139_virt_buffer = (char*)0;
27 uint8_t rtl8139_irq;
28
29 uint8_t rtl8139_mac[6];
30
31 uint8_t TSAD_array[4] = {0x20, 0x24, 0x28, 0x2C};
32 uint8_t TSD_array[4] = {0x10, 0x14, 0x18, 0x1C};
33
34 size_t rtl8139_current_tx_index = 0;
35
36 void* rtl8139_transfer_buffer;
37 size_t rtl8139_transfer_buffer_phys;
38
39 void rtl8139_send_packet(void* data, size_t length);
40 void rtl8139_receive_packet();
41
42 bool rtl8139_in_irq = false;
43
44 #define NETCARD_NAME ("RTL8139")
45
46 void rtl8139_netcard_get_mac(uint8_t mac[6]) {
47 rtl8139_read_mac();
48
49 memcpy(mac, rtl8139_mac, 6);
50 }
51
52 netcard_entry_t rtl8139_netcard = {
53 NETCARD_NAME,
54 {0, 0, 0, 0},
55 rtl8139_netcard_get_mac,
56 rtl8139_send_packet,
57 };
58
59 void rtl8139_init() {
60 qemu_log("Initializing RTL8139...");
61
62 pci_find_device(RTL8139_VENDOR, RTL8139_DEVICE,
63 &rtl8139_busnum, &rtl8139_slot, &rtl8139_func);
64
65 uint16_t devnum = pci_get_device(rtl8139_busnum, rtl8139_slot, rtl8139_func);
66
67 qemu_log("RTL8139 ID: %d (%x)", devnum, devnum);
68
69 if(devnum == PCI_VENDOR_NO_DEVICE) {
70 qemu_log("RTL8139 is not connected!");
71 return;
72 } else {
73 qemu_log("Detected RTL8139");
74 }
75
76 // Enable Bus Mastering
77
78 pci_enable_bus_mastering(rtl8139_busnum, rtl8139_slot, rtl8139_func);
79
80 qemu_log("Enabled Bus Mastering for RTL8139!");
81
82 uint32_t ret = pci_read_confspc_word(rtl8139_busnum, rtl8139_slot, rtl8139_func, 0x10); // BAR0
83
84 // If bar type is 0 use memory-based access, use port-based otherwise.
85 rtl8139_bar_type = ret & 0x1;
86 rtl8139_io_base = ret & (~0x3);
87 rtl8139_mem_base = ret & (~0xf);
88
89 qemu_log("RTL8139 BAR TYPE: %d; IO BASE: %x; MEMORY BASE: %x", rtl8139_bar_type, rtl8139_io_base, rtl8139_mem_base);
90
91 rtl8139_wake_up();
92 rtl8139_sw_reset();
93
94 rtl8139_virt_buffer = kmalloc_common(RTL8139_BUFFER_PAGE_COUNT, PAGE_SIZE);
95 rtl8139_phys_buffer = virt2phys(get_kernel_page_directory(), (virtual_addr_t) rtl8139_virt_buffer);
96
97 rtl8139_transfer_buffer = kmalloc_common(65535, PAGE_SIZE);
98 rtl8139_transfer_buffer_phys = virt2phys(get_kernel_page_directory(), (virtual_addr_t)rtl8139_transfer_buffer);
99
100 rtl8139_init_buffer();
101
102 qemu_log("RTL8139 Physical buffer at: %x", rtl8139_phys_buffer);
103
104 rtl8139_setup_rcr();
105 rtl8139_enable_rx_tx();
106
107 rtl8139_init_interrupts();
108
109 rtl8139_read_mac();
110
111 // If okay, add network card to list.
112 netcard_add(&rtl8139_netcard);
113 }
114
115 void rtl8139_read_mac() {
116 uint32_t mac_part1 = inl(rtl8139_io_base + MAC0_5);
117 uint16_t mac_part2 = inw(rtl8139_io_base + MAC0_5 + 4);
118
119 rtl8139_mac[0] = (mac_part1 >> 0) & 0xFF;
120 rtl8139_mac[1] = mac_part1 >> 8;
121 rtl8139_mac[2] = mac_part1 >> 16;
122 rtl8139_mac[3] = mac_part1 >> 24;
123
124 rtl8139_mac[4] = mac_part2 >> 0;
125 rtl8139_mac[5] = mac_part2 >> 8;
126
127 qemu_log("Mac is: %x:%x:%x:%x:%x:%x", rtl8139_mac[0], rtl8139_mac[1], rtl8139_mac[2], rtl8139_mac[3], rtl8139_mac[4], rtl8139_mac[5]);
128 }
129
130 void rtl8139_enable_rx_tx() {
131 outb(rtl8139_io_base + CMD, 0x0C); // Sets the RE and TE bits high
132 }
133
134 void rtl8139_setup_rcr() {
135 // AB - Accept Broadcast: Accept broadcast packets sent to mac ff:ff:ff:ff:ff:ff
136 // AM - Accept Multicast: Accept multicast packets.
137 // APM - Accept Physical Match: Accept packets send to NIC's MAC address.
138 // AAP - Accept All Packets. Accept all packets (run in promiscuous mode).
139 // (1 << 7) is the WRAP bit, 0xf is AB+AM+APM+AAP
140
141 outl(rtl8139_io_base + 0x44, 0xf | (1 << 7));
142 }
143
144 void rtl8139_wake_up() {
145 outb(rtl8139_io_base + CONFIG_1, 0x0);
146 }
147
148 void rtl8139_sw_reset() {
149 outb(rtl8139_io_base + CMD, 0x10); // Reset
150
151 while((inb(rtl8139_io_base + CMD) & 0x10) != 0)
152 ;
153 }
154
155 void rtl8139_init_buffer() {
156 outl(rtl8139_io_base + RBSTART, rtl8139_phys_buffer);
157 }
158
159 void rtl8139_handler(__attribute__((unused)) registers_t regs) {
160 qemu_log("Received RTL8139 interrupt!");
161
162 rtl8139_in_irq = true;
163
164 uint16_t status = inw(rtl8139_io_base + 0x3e);
165
166 if(status & TOK) {
167 qemu_log("Packet sent");
168 }
169
170 if (status & ROK) {
171 qemu_log("Packet received!\n");
172
173 // TODO: Push packet to stack then, when needed, work with packets on the stack
174 rtl8139_receive_packet();
175 }
176
177 outw(rtl8139_io_base + 0x3E, 0x05);
178
179 rtl8139_in_irq = false;
180 }
181
182 void rtl8139_send_packet(void *data, size_t length) {
183 // First, copy the data to a physically contiguous chunk of memory
184
185 //qemu_log("Waiting lock...");
186 //while(rtl8139_in_irq)
187 // ;
188
189 qemu_log("Sending packet");
190
191 memset(rtl8139_transfer_buffer, 0, 65535);
192
193 memcpy(rtl8139_transfer_buffer, data, length);
194
195 //qemu_log("Send packet: Virtual memory at %x", (size_t)rtl8139_transfer_buffer);
196 //qemu_log("Send packet: Physical memory at %x", rtl8139_transfer_buffer_phys);
197
198 // Second, fill in physical address of data, and length
199
200 //qemu_log("Before: %d", rtl8139_current_tx_index);
201
202 outl(rtl8139_io_base + TSAD_array[rtl8139_current_tx_index], (uint32_t)rtl8139_transfer_buffer_phys);
203 outl(rtl8139_io_base + TSD_array[rtl8139_current_tx_index++], length);
204
205 //qemu_log("After: %d", rtl8139_current_tx_index);
206
207 if(rtl8139_current_tx_index > 3)
208 rtl8139_current_tx_index = 0;
209
210 qemu_log("Send packet end");
211 }
212
213 size_t rtl8139_current_packet_ptr = 0;
214
215 // This function is a part of IRQ
216 void rtl8139_receive_packet() {
217 uint16_t* packet = (uint16_t*)(rtl8139_virt_buffer + rtl8139_current_packet_ptr);
218
219 EthernetPacked* e_pack = (EthernetPacked*)packet;
220
221 qemu_log("[Net] [RTL8139] Получен пакет!");
222 qemu_log(" |-- Заголовок данных: %x",e_pack->Header);
223 qemu_log(" |-- Длина данных: %d",e_pack->Size);
224 qemu_log(" |-- Источник: %x:%x:%x:%x:%x:%x",e_pack->MAC_SOURCE[0] ,e_pack->MAC_SOURCE[1],e_pack->MAC_SOURCE[2], e_pack->MAC_SOURCE[3] ,e_pack->MAC_SOURCE[4] ,e_pack->MAC_SOURCE[5]);
225 qemu_log(" |-- Кому: %x:%x:%x:%x:%x:%x", e_pack->MAC_DEVICE[0], e_pack->MAC_DEVICE[1], e_pack->MAC_DEVICE[2], e_pack->MAC_DEVICE[3], e_pack->MAC_DEVICE[4], e_pack->MAC_DEVICE[5]);
226 qemu_log(" |-- Тип данных: %x", bit_flip_short(e_pack->Type));
227
228 // Skip packet header, get packet length
229 //^ Может быть и верно, но теряется сама логика пакета, из-за этого я не мог понять некоторые моменты
230 // NDRAEY: Это сырая реализция!!!1
231
232 uint16_t packet_header = e_pack->Header;
233 uint16_t packet_length = e_pack->Size;
234
235 uint16_t* packet_data = packet + 2;
236
237 qemu_log("[Net] [RTL8139] Данные с пакета:\n");
238
239 // hexview_advanced((char *) packet_data, packet_length, 10, true, new_qemu_printf);
240
241 if(packet_header == HARDWARE_TYPE_ETHERNET) {
242 //netstack_push(&rtl8139_netcard, packet_data, packet_length);
243
244 qemu_note("Processing packet...");
245 ethernet_handle_packet(&rtl8139_netcard, (ethernet_frame_t *) packet_data, packet_length);
246 qemu_ok("Packet processing is finished!");
247 }
248
249 rtl8139_current_packet_ptr = (rtl8139_current_packet_ptr + packet_length + 7) & RX_READ_POINTER_MASK;
250
251 if(rtl8139_current_packet_ptr > 8192)
252 rtl8139_current_packet_ptr -= 8192;
253
254 outw(rtl8139_io_base + CAPR, rtl8139_current_packet_ptr - 0x10);
255 }
256
257 void rtl8139_init_interrupts() {
258 outw(rtl8139_io_base + IMR, 0x0005);
259
260 // https://wiki.osdev.org/PCI
261 //
262 // Offset 0x3C
263 //
264 // Bits 31-24 Bits 23-16 Bits 15-8 Bits 7-0
265 // Max latency Min Grant Interrupt PIN Interrupt Line
266 // ~~~~~~~~~~~~~~
267
268 uint32_t word = pci_read_confspc_word(rtl8139_busnum, rtl8139_slot, rtl8139_func, 0x3C); // All 0xF PCI register
269 rtl8139_irq = word & 0xff;
270
271 qemu_log("RTL8139 IRQ: %x", rtl8139_irq);
272
273 register_interrupt_handler(32 + rtl8139_irq, rtl8139_handler);
274
275 qemu_log("Initialized RTl8139 interrupts!");
276 }
__attribute__
struct registers __attribute__((packed))
Структура данных пакета от мыши
Definition: psf.h:19
memset
void * memset(void *ptr, char value, size_t num)
Заполнение массива указанными символами
Definition: string.c:203
memcpy
void * memcpy(void *restrict destination, const void *restrict source, size_t n)
Копирование непересекающихся массивов используя SSE.
Definition: string.c:173
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
netcard_entry_t
Definition: cards.h:5
registers
Definition: common.h:59