WKern
Loading...
Searching...
No Matches
virtio.c
Go to the documentation of this file.
1/*
2WKern - A Bare Metal OS / Kernel I am maKing (For Fun)
3Copyright (C) 2025 Wdboyes13
4
5This program is free software: you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation, either version 3 of the License, or
8any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOut ANY WARRANTY; withOut even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program. If not, see <https://www.gnu.org/licenses/>.
17*/
18
19#include <idt/idtirq.h>
20#include <io/kio.h>
21#include <mem/kmem.h>
22#include <net/virtnet.h>
23#include <pci/pci.h>
24#include <types/nums.h>
25static u16 qsize = 0;
26static virtq_desc *desc = NULL;
27static virtq_avail *avail = NULL;
28static virtq_used *used = NULL;
29static void *virtq_rx = NULL;
30static void *rx_bufs[MAX_RX_DESCS]; // define somewhere
31static u16 last_used_idx = 0;
32
42 Kprintf("Reset device status\n");
44 Kprintf("Set ACKNOWLEDGE\n");
46 Kprintf("Set DRIVER\n");
49 Kprintf("Reading host features\n");
50 u32 host_features = Inl(iob + VIRTIO_PCI_HOST_FEATURES);
51 Kprintf("Host features: 0x");
52 KprintHex(host_features);
53 Kputchar('\n');
54 Kprintf("Writing guest features\n");
56 Kprintf("Set DRIVER_OK\n");
60 Kprintf("Negotiation done\n");
61}
62
80 Kprintf("Allocating mem\n");
81 virtq_rx = Kmalloc(4096, 4096);
82 if (!virtq_rx) {
83 Kprintf("Malloc Failed at virtnet_init");
84 return;
85 }
86
87 u16 raw_qsize = Inw(iob + VIRTIO_PCI_QUEUE_NUM);
88 Kprintf("Raw qsize: 0x%x\n", raw_qsize);
89
90 // Clamp regardless of device size
91 qsize = raw_qsize;
92 if (qsize == 0 || qsize > VIRTIO_MAX_SAFE_QSIZE) {
93 Kprintf("Clamping qsize from %d to %d\n", qsize, VIRTIO_MAX_SAFE_QSIZE);
95 }
96
97 Kmemset(virtq_rx, 0, 4096);
98
99 Kprintf("Setting descriptors, avail, and used\n");
100 desc = (virtq_desc *)virtq_rx;
101 avail = (virtq_avail *)(desc + qsize);
102 used = (virtq_used *)((u8 *)virtq_rx + 4096 - (6 + 8 * qsize));
103 int failed = 0;
104 for (int i = 0; i < qsize; i++) {
105 rx_bufs[i] = Kmalloc(2048, 4096);
106 if (!rx_bufs[i]) {
107 Kprintf("Failed to alloc rx_buf %d\n", i);
108 failed++;
109 continue;
110 }
111 desc[i].addr = (uptr)rx_bufs[i];
112 desc[i].len = 2048;
113 desc[i].flags = VIRTQ_DESC_F_WRITE;
114 avail->ring[i] = i;
115 }
116
117 Kprintf("Finishing net setup\n");
118 Kprintf("Failed RX_BUF: %d, Final qsize = %d\n", failed, qsize);
119
120 avail->idx = qsize;
121 Kprintf("Sending signal 1\n");
122 Outl(iob + VIRTIO_PCI_QUEUE_PFN, ((uptr)virtq_rx) >> 12);
123 Kprintf("BAR0: %x\n", bar0);
124 Kprintf("Sending signal 2\n");
126 Kprintf("NetworK up\n");
127}
128
139 // u8 isr = inb(iob + 0x13);
140 // if (!(isr & 0x1))
141 // return; // no pacKets
142 static const char hexchars[] = "0123456789ABCDEF";
143 while (last_used_idx != used->idx) {
144 u16 idx = last_used_idx % qsize;
145 u32 desc_id = used->ring[idx].id;
146 u32 len = used->ring[idx].len;
147
148 char *pacKet = (char *)desc[desc_id].addr;
149 Kprintf("Received pacKet (%d bytes):\n", len);
150 for (u32 b = 0; b < len; b++) {
151 u8 byte = pacKet[b];
152 Kputchar(hexchars[(byte >> 4) & 0xF]);
153 Kputchar(hexchars[byte & 0xF]);
154 Kputchar(' ');
155 }
156 Kputchar('\n');
157
158 // Re-add descriptor to avail ring so device can reuse it
159 avail->ring[avail->idx % qsize] = desc_id;
160 avail->idx++;
161
162 last_used_idx++;
163 }
164
165 // Notify device new buffers are available
167}
168
void * Kmalloc(size_t size, size_t align)
Allocate memory.
Definition alloc.c:48
void Outb(u16 port, u8 val)
Write a byte to the specified I/O port.
Definition asm.c:30
void Outw(u16 port, u16 val)
Write a 16-bit word to the specified I/O port.
Definition asm.c:52
u32 Inl(u16 port)
Read a 32-bit value from the specified I/O port.
Definition asm.c:84
u16 Inw(u16 port)
Read a 16-bit word from the specified I/O port.
Definition asm.c:62
void Outl(u16 port, u32 val)
Write a 32-bit value to the specified I/O port.
Definition asm.c:74
#define NULL
Definition global.h:39
u32 iob
Definition main.c:36
void IdtSetGate(u8 num, u32 base, u16 sel, u8 flags)
Set an IDT gate (entry) at given index.
Definition idt.c:40
#define KERNEL_CODE_SEGMENT
Definition idtirq.h:24
void UnmaskIrq(u8 irq)
Unmask an IRQ.
Definition masker.c:34
void Kprintf(const char *fmt,...)
Formatted output to the screen.
Definition printer.c:152
void KprintHex(u32 num)
Prints a 32-bit unsigned integer in hexadecimal format prefixed with "0x".
Definition printer.c:92
void Kputchar(char c)
Outputs a single character to the screen at the current cursor position.
Definition printer.c:46
void Kmemset(void *ptr, unsigned char value, unsigned int num)
Set memory to a value.
Definition memutil.c:26
unsigned int u32
32-Bit Unsigned Int
Definition nums.h:30
unsigned short u16
16-Bit Unsigned Int
Definition nums.h:36
unsigned long uptr
Long Unsigned Int.
Definition nums.h:34
unsigned char u8
8-Bit Unsigned Int
Definition nums.h:32
u8 virtio_slot
Definition scconfig.c:27
u8 virtio_bus
Definition scconfig.c:26
u32 bar0
Definition scconfig.c:30
u8 virtio_irq
Definition scconfig.c:25
#define PCI_INTERRUPT_LINE
Definition pci.h:22
u32 FindVirtionetDev()
Search for VirtNet Device.
Definition scconfig.c:59
u8 virtio_func
Definition scconfig.c:28
u32 PciConfigRead(u8 bus, u8 slot, u8 func, u8 offset)
Reads a 32-bit value from PCI configuration space.
Definition scconfig.c:48
void VirtnetSetup()
Performs full setup of the VirtIO network device.
Definition virtio.c:176
void NetStq(u32 iob)
Processes received packets from the VirtIO queue.
Definition virtio.c:138
void VirtnetNegotiate(u32 iob)
Performs device negotiation with the VirtIO network device.
Definition virtio.c:41
void VirtnetInit(u32 iob)
Initializes the VirtIO network queue and allocates RX buffers.
Definition virtio.c:78
#define VIRTIO_STATUS_DRIVER_OK
Definition virtnet.h:37
#define MAX_RX_DESCS
Definition virtnet.h:30
struct VirtqUsed virtq_used
#define VIRTIO_PCI_QUEUE_NUM
Definition virtnet.h:24
#define VIRTQ_DESC_F_WRITE
Definition virtnet.h:28
#define VIRTIO_STATUS_DRIVER
Definition virtnet.h:36
#define VIRTIO_STATUS_ACKNOWLEDGE
Definition virtnet.h:35
#define VIRTIO_PCI_HOST_FEATURES
Definition virtnet.h:31
#define VIRTIO_PCI_QUEUE_SEL
Definition virtnet.h:23
#define VIRTIO_PCI_STATUS
Definition virtnet.h:33
#define VIRTIO_PCI_QUEUE_NOTIFY
Definition virtnet.h:26
#define VIRTIO_PCI_GUEST_FEATURES
Definition virtnet.h:32
struct VirtqAvail virtq_avail
struct VirtqDesc virtq_desc
#define VIRTIO_MAX_SAFE_QSIZE
Definition virtnet.h:29
#define VIRTIO_PCI_QUEUE_PFN
Definition virtnet.h:25
void VirtnetIrqHandler()
Definition virtnetirq.c:11