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 }
struct registers __attribute__((packed))
Структура данных пакета от мыши
Definition: psf.h:19
void * memset(void *ptr, char value, size_t num)
Заполнение массива указанными символами
Definition: string.c:203
void * memcpy(void *restrict destination, const void *restrict source, size_t n)
Копирование непересекающихся массивов используя SSE.
Definition: string.c:173
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
Definition: cards.h:5