mirror of
https://github.com/BoredDevNL/BoredOS.git
synced 2026-05-15 10:48:38 +00:00
rtl8111 NIC driver
This commit is contained in:
parent
b05b221c41
commit
df73f00efd
11 changed files with 315 additions and 8 deletions
BIN
boredos.iso
BIN
boredos.iso
Binary file not shown.
BIN
build/ps2.o
BIN
build/ps2.o
Binary file not shown.
|
|
@ -109,7 +109,16 @@ int network_init(void) {
|
|||
|
||||
int network_get_mac_address(mac_address_t* mac) {
|
||||
if (!lwip_initialized) return -1;
|
||||
for (int i = 0; i < 6; i++) mac->bytes[i] = nic_netif.hwaddr[i];
|
||||
return nic_get_mac_address(mac->bytes);
|
||||
}
|
||||
|
||||
int network_get_nic_name(char* name_out) {
|
||||
if (!lwip_initialized) return -1;
|
||||
extern const char* nic_get_active_name(void);
|
||||
const char* n = nic_get_active_name();
|
||||
if (!n) return -1;
|
||||
while (*n) *name_out++ = *n++;
|
||||
*name_out = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ typedef struct {
|
|||
|
||||
int network_init(void);
|
||||
int network_get_mac_address(mac_address_t* mac);
|
||||
int network_get_nic_name(char* name_out);
|
||||
int network_get_ipv4_address(ipv4_address_t* ip);
|
||||
int network_set_ipv4_address(const ipv4_address_t* ip);
|
||||
int network_send_frame(const void* data, size_t length);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
#include "pci.h"
|
||||
#include "kutils.h"
|
||||
|
||||
// Forward declarations for driver inits
|
||||
extern int e1000_init(pci_device_t* pci_dev);
|
||||
extern int rtl8139_init(pci_device_t* pci_dev);
|
||||
extern int virtio_net_init(pci_device_t* pci_dev);
|
||||
|
|
@ -22,6 +21,11 @@ extern int virtio_net_send_packet(const void* data, size_t length);
|
|||
extern int virtio_net_receive_packet(void* buffer, size_t buffer_size);
|
||||
extern int virtio_net_get_mac(uint8_t* mac_out);
|
||||
|
||||
extern int rtl8111_init(pci_device_t* pci_dev);
|
||||
extern int rtl8111_send_packet(const void* data, size_t length);
|
||||
extern int rtl8111_receive_packet(void* buffer, size_t buffer_size);
|
||||
extern int rtl8111_get_mac(uint8_t* mac_out);
|
||||
|
||||
static nic_driver_t active_nic_driver = {0};
|
||||
static int nic_initialized = 0;
|
||||
|
||||
|
|
@ -61,12 +65,30 @@ static int register_virtio_net(pci_device_t* dev) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int register_rtl8111(pci_device_t* dev) {
|
||||
if (rtl8111_init(dev) == 0) {
|
||||
active_nic_driver.name = "rtl8111";
|
||||
active_nic_driver.init = rtl8111_init;
|
||||
active_nic_driver.send_packet = rtl8111_send_packet;
|
||||
active_nic_driver.receive_packet = rtl8111_receive_packet;
|
||||
active_nic_driver.get_mac_address = rtl8111_get_mac;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int nic_init(void) {
|
||||
if (nic_initialized) return 0;
|
||||
|
||||
pci_device_t pci_dev;
|
||||
|
||||
// Try finding RTL8139 (Vendor: 0x10EC, Device: 0x8139)
|
||||
if (pci_find_device(0x10EC, 0x8168, &pci_dev)) {
|
||||
if (register_rtl8111(&pci_dev) == 0) {
|
||||
nic_initialized = 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (pci_find_device(0x10EC, 0x8139, &pci_dev)) {
|
||||
if (register_rtl8139(&pci_dev) == 0) {
|
||||
nic_initialized = 1;
|
||||
|
|
@ -74,8 +96,7 @@ int nic_init(void) {
|
|||
}
|
||||
}
|
||||
|
||||
// Try finding Virtio-Net (Vendor: 0x1AF4, Device: 0x1000 for legacy or 0x1041 for modern)
|
||||
// Here we mainly support legacy VirtIO Network (0x1000)
|
||||
|
||||
if (pci_find_device(0x1AF4, 0x1000, &pci_dev)) {
|
||||
if (register_virtio_net(&pci_dev) == 0) {
|
||||
nic_initialized = 1;
|
||||
|
|
@ -83,7 +104,6 @@ int nic_init(void) {
|
|||
}
|
||||
}
|
||||
|
||||
// Modern VirtIO NET is 0x1041
|
||||
if (pci_find_device(0x1AF4, 0x1041, &pci_dev)) {
|
||||
if (register_virtio_net(&pci_dev) == 0) {
|
||||
nic_initialized = 1;
|
||||
|
|
@ -91,7 +111,6 @@ int nic_init(void) {
|
|||
}
|
||||
}
|
||||
|
||||
// Try finding E1000 (Vendor: 0x8086, Device: 0x100E)
|
||||
if (pci_find_device(0x8086, 0x100E, &pci_dev)) {
|
||||
if (register_e1000(&pci_dev) == 0) {
|
||||
nic_initialized = 1;
|
||||
|
|
@ -99,7 +118,7 @@ int nic_init(void) {
|
|||
}
|
||||
}
|
||||
|
||||
return -1; // No supported NIC found
|
||||
return -1;
|
||||
}
|
||||
|
||||
nic_driver_t* nic_get_driver(void) {
|
||||
|
|
@ -121,3 +140,8 @@ int nic_get_mac_address(uint8_t* mac_out) {
|
|||
if (!nic_initialized || !active_nic_driver.get_mac_address) return -1;
|
||||
return active_nic_driver.get_mac_address(mac_out);
|
||||
}
|
||||
|
||||
const char* nic_get_active_name(void) {
|
||||
if (!nic_initialized || !active_nic_driver.name) return NULL;
|
||||
return active_nic_driver.name;
|
||||
}
|
||||
|
|
|
|||
229
src/kernel/rtl8111.c
Normal file
229
src/kernel/rtl8111.c
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
// Copyright (c) 2023-2026 Chris (boreddevnl)
|
||||
// This software is released under the GNU General Public License v3.0. See LICENSE file for details.
|
||||
// This header needs to maintain in any file it is present in, as per the GPL license terms.
|
||||
#include "rtl8111.h"
|
||||
#include "io.h"
|
||||
#include "kutils.h"
|
||||
#include "platform.h"
|
||||
|
||||
#define RTL8111_MAC0 0x00
|
||||
#define RTL8111_TDSAR 0x20
|
||||
#define RTL8111_CR 0x37
|
||||
#define RTL8111_TPPOLL 0x38
|
||||
#define RTL8111_IMR 0x3C
|
||||
#define RTL8111_ISR 0x3E
|
||||
#define RTL8111_TCR 0x40
|
||||
#define RTL8111_RCR 0x44
|
||||
#define RTL8111_MULINT 0x5C
|
||||
#define RTL8111_RMS 0xDA
|
||||
#define RTL8111_MTPS 0xEC
|
||||
#define RTL8111_RDSAR 0xE4
|
||||
|
||||
#define RTL8111_CR_TE (1 << 2)
|
||||
#define RTL8111_CR_RE (1 << 3)
|
||||
#define RTL8111_CR_RST (1 << 4)
|
||||
|
||||
#define RTL8111_DESC_OWN (1u << 31)
|
||||
#define RTL8111_DESC_EOR (1u << 30)
|
||||
#define RTL8111_DESC_FS (1u << 29)
|
||||
#define RTL8111_DESC_LS (1u << 28)
|
||||
|
||||
struct rtl8111_desc {
|
||||
uint32_t opts1;
|
||||
uint32_t opts2;
|
||||
uint64_t buf_addr;
|
||||
} __attribute__((packed, aligned(16)));
|
||||
|
||||
#define RTL8111_NUM_RX_DESC 128
|
||||
#define RTL8111_NUM_TX_DESC 128
|
||||
|
||||
static int rtl8111_initialized = 0;
|
||||
static uint64_t mmio_base_addr = 0;
|
||||
static uint8_t mac_addr[6];
|
||||
|
||||
static struct rtl8111_desc rx_desc[RTL8111_NUM_RX_DESC] __attribute__((aligned(256)));
|
||||
static struct rtl8111_desc tx_desc[RTL8111_NUM_TX_DESC] __attribute__((aligned(256)));
|
||||
|
||||
static uint8_t rx_buffers[RTL8111_NUM_RX_DESC][2048] __attribute__((aligned(8)));
|
||||
static uint8_t tx_buffers[RTL8111_NUM_TX_DESC][2048] __attribute__((aligned(8)));
|
||||
|
||||
static uint16_t rx_idx = 0;
|
||||
static uint16_t tx_idx = 0;
|
||||
|
||||
static inline uint8_t rtl8111_inb(uint16_t offset) { return *(volatile uint8_t*)(uintptr_t)(mmio_base_addr + offset); }
|
||||
static inline uint16_t rtl8111_inw(uint16_t offset) { return *(volatile uint16_t*)(uintptr_t)(mmio_base_addr + offset); }
|
||||
static inline uint32_t rtl8111_inl(uint16_t offset) { return *(volatile uint32_t*)(uintptr_t)(mmio_base_addr + offset); }
|
||||
|
||||
static inline void rtl8111_outb(uint16_t offset, uint8_t value) { *(volatile uint8_t*)(uintptr_t)(mmio_base_addr + offset) = value; }
|
||||
static inline void rtl8111_outw(uint16_t offset, uint16_t value) { *(volatile uint16_t*)(uintptr_t)(mmio_base_addr + offset) = value; }
|
||||
static inline void rtl8111_outl(uint16_t offset, uint32_t value) { *(volatile uint32_t*)(uintptr_t)(mmio_base_addr + offset) = value; }
|
||||
|
||||
int rtl8111_init(pci_device_t* pci_dev) {
|
||||
if (rtl8111_initialized) return 0;
|
||||
|
||||
uint32_t command = pci_read_config(pci_dev->bus, pci_dev->device, pci_dev->function, 0x04);
|
||||
pci_write_config(pci_dev->bus, pci_dev->device, pci_dev->function, 0x04, command | (1 << 2) | (1 << 1));
|
||||
|
||||
uint32_t bar2 = pci_read_config(pci_dev->bus, pci_dev->device, pci_dev->function, 0x18);
|
||||
|
||||
uint64_t mmio_phys = 0;
|
||||
for (int bar_off = 0x10; bar_off <= 0x24; bar_off += 4) {
|
||||
uint32_t bar = pci_read_config(pci_dev->bus, pci_dev->device, pci_dev->function, bar_off);
|
||||
if (bar != 0 && bar != 0xFFFFFFFF && !(bar & 1)) {
|
||||
mmio_phys = (bar & ~0xF);
|
||||
if ((bar & 0x6) == 0x4) {
|
||||
uint32_t bar_upper = pci_read_config(pci_dev->bus, pci_dev->device, pci_dev->function, bar_off + 4);
|
||||
mmio_phys |= ((uint64_t)bar_upper << 32);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mmio_phys == 0) return -1;
|
||||
|
||||
mmio_base_addr = p2v(mmio_phys);
|
||||
|
||||
extern void serial_write(const char *str);
|
||||
serial_write("[RTL8111] MMIO Base: 0x");
|
||||
char hex_buf[32]; k_itoa_hex(mmio_base_addr, hex_buf); serial_write(hex_buf); serial_write("\n");
|
||||
|
||||
rtl8111_outb(RTL8111_CR, RTL8111_CR_RST);
|
||||
for (int i = 0; i < 100000; i++) {
|
||||
if (!(rtl8111_inb(RTL8111_CR) & RTL8111_CR_RST)) break;
|
||||
}
|
||||
|
||||
uint32_t mac_low = rtl8111_inl(RTL8111_MAC0);
|
||||
uint32_t mac_high = rtl8111_inl(RTL8111_MAC0 + 4);
|
||||
mac_addr[0] = (mac_low >> 0) & 0xFF;
|
||||
mac_addr[1] = (mac_low >> 8) & 0xFF;
|
||||
mac_addr[2] = (mac_low >> 16) & 0xFF;
|
||||
mac_addr[3] = (mac_low >> 24) & 0xFF;
|
||||
mac_addr[4] = (mac_high >> 0) & 0xFF;
|
||||
mac_addr[5] = (mac_high >> 8) & 0xFF;
|
||||
|
||||
serial_write("[RTL8111] MAC: ");
|
||||
for(int i=0; i<6; i++) {
|
||||
char buf[4]; k_itoa_hex(mac_addr[i], buf); serial_write(buf);
|
||||
if(i<5) serial_write(":");
|
||||
}
|
||||
serial_write("\n");
|
||||
|
||||
rtl8111_outb(0x50, 0xC0);
|
||||
|
||||
k_memset(rx_desc, 0, sizeof(rx_desc));
|
||||
for (int i = 0; i < RTL8111_NUM_RX_DESC; i++) {
|
||||
uint64_t buf_phys = v2p((uint64_t)(uintptr_t)rx_buffers[i]);
|
||||
rx_desc[i].buf_addr = buf_phys;
|
||||
uint32_t cmd = 2048 | RTL8111_DESC_OWN;
|
||||
if (i == RTL8111_NUM_RX_DESC - 1) {
|
||||
cmd |= RTL8111_DESC_EOR;
|
||||
}
|
||||
rx_desc[i].opts1 = cmd;
|
||||
rx_desc[i].opts2 = 0;
|
||||
}
|
||||
uint64_t rx_ring_phys = v2p((uint64_t)(uintptr_t)rx_desc);
|
||||
rtl8111_outl(RTL8111_RDSAR, (uint32_t)rx_ring_phys);
|
||||
rtl8111_outl(RTL8111_RDSAR + 4, (uint32_t)(rx_ring_phys >> 32));
|
||||
|
||||
k_memset(tx_desc, 0, sizeof(tx_desc));
|
||||
uint64_t tx_ring_phys = v2p((uint64_t)(uintptr_t)tx_desc);
|
||||
rtl8111_outl(RTL8111_TDSAR, (uint32_t)tx_ring_phys);
|
||||
rtl8111_outl(RTL8111_TDSAR + 4, (uint32_t)(tx_ring_phys >> 32));
|
||||
|
||||
rtl8111_outl(RTL8111_RCR, 0x0F | (0x07 << 8) | (0x07 << 13));
|
||||
rtl8111_outl(RTL8111_TCR, (0x03 << 24));
|
||||
rtl8111_outw(RTL8111_RMS, 2048);
|
||||
rtl8111_outb(RTL8111_MTPS, 0x3F);
|
||||
|
||||
rtl8111_outb(0x50, 0x00);
|
||||
|
||||
rtl8111_outb(RTL8111_CR, RTL8111_CR_RE | RTL8111_CR_TE);
|
||||
|
||||
rtl8111_outw(RTL8111_MULINT, 0);
|
||||
rtl8111_outw(RTL8111_IMR, 0x0005);
|
||||
|
||||
rx_idx = 0;
|
||||
tx_idx = 0;
|
||||
rtl8111_initialized = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtl8111_send_packet(const void* data, size_t length) {
|
||||
if (!rtl8111_initialized) return -1;
|
||||
if (length > 2048) return -1;
|
||||
|
||||
struct rtl8111_desc* desc = &tx_desc[tx_idx];
|
||||
|
||||
if (desc->opts1 & RTL8111_DESC_OWN) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t* tx_buf = tx_buffers[tx_idx];
|
||||
uint8_t* src = (uint8_t*)data;
|
||||
for (size_t i = 0; i < length; i++) tx_buf[i] = src[i];
|
||||
|
||||
desc->buf_addr = v2p((uint64_t)(uintptr_t)tx_buf);
|
||||
|
||||
uint32_t cmd = length | RTL8111_DESC_OWN | RTL8111_DESC_FS | RTL8111_DESC_LS;
|
||||
if (tx_idx == RTL8111_NUM_TX_DESC - 1) {
|
||||
cmd |= RTL8111_DESC_EOR;
|
||||
}
|
||||
desc->opts2 = 0;
|
||||
__asm__ __volatile__ ("mfence");
|
||||
desc->opts1 = cmd;
|
||||
|
||||
rtl8111_outb(RTL8111_TPPOLL, 0x40);
|
||||
|
||||
tx_idx = (tx_idx + 1) % RTL8111_NUM_TX_DESC;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtl8111_receive_packet(void* buffer, size_t buffer_size) {
|
||||
if (!rtl8111_initialized) return 0;
|
||||
|
||||
uint16_t isr = rtl8111_inw(RTL8111_ISR);
|
||||
if (isr) {
|
||||
rtl8111_outw(RTL8111_ISR, isr);
|
||||
}
|
||||
|
||||
struct rtl8111_desc* desc = &rx_desc[rx_idx];
|
||||
|
||||
if (desc->opts1 & RTL8111_DESC_OWN) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t len = desc->opts1 & 0x3FFF;
|
||||
|
||||
if (desc->opts1 & (1 << 21)) {
|
||||
len = 0;
|
||||
} else if (len > 0) {
|
||||
if (len > 4) len -= 4;
|
||||
if (len > buffer_size) len = buffer_size;
|
||||
|
||||
uint8_t* dest = (uint8_t*)buffer;
|
||||
uint8_t* pkt = rx_buffers[rx_idx];
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
dest[i] = pkt[i];
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t cmd = 2048 | RTL8111_DESC_OWN;
|
||||
if (rx_idx == RTL8111_NUM_RX_DESC - 1) {
|
||||
cmd |= RTL8111_DESC_EOR;
|
||||
}
|
||||
desc->buf_addr = v2p((uint64_t)(uintptr_t)rx_buffers[rx_idx]);
|
||||
desc->opts2 = 0;
|
||||
__asm__ __volatile__ ("mfence");
|
||||
desc->opts1 = cmd;
|
||||
|
||||
rx_idx = (rx_idx + 1) % RTL8111_NUM_RX_DESC;
|
||||
return len;
|
||||
}
|
||||
|
||||
int rtl8111_get_mac(uint8_t* mac_out) {
|
||||
if (!rtl8111_initialized) return -1;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
mac_out[i] = mac_addr[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
16
src/kernel/rtl8111.h
Normal file
16
src/kernel/rtl8111.h
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright (c) 2023-2026 Chris (boreddevnl)
|
||||
// This software is released under the GNU General Public License v3.0. See LICENSE file for details.
|
||||
// This header needs to maintain in any file it is present in, as per the GPL license terms.
|
||||
#ifndef RTL8111_H
|
||||
#define RTL8111_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "pci.h"
|
||||
|
||||
int rtl8111_init(pci_device_t* pci_dev);
|
||||
int rtl8111_send_packet(const void* data, size_t length);
|
||||
int rtl8111_receive_packet(void* buffer, size_t buffer_size);
|
||||
int rtl8111_get_mac(uint8_t* mac_out);
|
||||
|
||||
#endif
|
||||
|
|
@ -1175,6 +1175,20 @@ static uint64_t syscall_handler_inner(registers_t *regs) {
|
|||
return 0;
|
||||
}
|
||||
return -1;
|
||||
} else if (cmd == 48) { // SYSTEM_CMD_NETWORK_GET_NIC_NAME
|
||||
char *user_buf = (char *)arg2;
|
||||
if (!user_buf) return -1;
|
||||
char name_buf[64];
|
||||
extern int network_get_nic_name(char *name_out);
|
||||
if (network_get_nic_name(name_buf) == 0) {
|
||||
extern void mem_memcpy(void *dest, const void *src, size_t len);
|
||||
size_t len = 0;
|
||||
while (name_buf[len] && len < 63) len++;
|
||||
name_buf[len] = 0;
|
||||
mem_memcpy(user_buf, name_buf, len + 1);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -150,6 +150,10 @@ int sys_network_get_mac(net_mac_address_t *mac) {
|
|||
return (int)syscall2(SYS_SYSTEM, SYSTEM_CMD_NETWORK_GET_MAC, (uint64_t)mac);
|
||||
}
|
||||
|
||||
int sys_network_get_nic_name(char *name_out) {
|
||||
return (int)syscall2(SYS_SYSTEM, SYSTEM_CMD_NETWORK_GET_NIC_NAME, (uint64_t)name_out);
|
||||
}
|
||||
|
||||
int sys_network_get_ip(net_ipv4_address_t *ip) {
|
||||
return (int)syscall2(SYS_SYSTEM, SYSTEM_CMD_NETWORK_GET_IP, (uint64_t)ip);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@
|
|||
#define SYSTEM_CMD_NETWORK_IS_INIT 27
|
||||
#define SYSTEM_CMD_NETWORK_HAS_IP 30
|
||||
#define SYSTEM_CMD_GET_SHELL_CONFIG 28
|
||||
#define SYSTEM_CMD_NETWORK_GET_NIC_NAME 48
|
||||
#define SYSTEM_CMD_SET_TEXT_COLOR 29
|
||||
#define SYSTEM_CMD_SET_WALLPAPER_PATH 31
|
||||
#define SYSTEM_CMD_TCP_CONNECT 33
|
||||
|
|
@ -130,6 +131,7 @@ typedef struct { uint8_t bytes[4]; } net_ipv4_address_t;
|
|||
int sys_network_init(void);
|
||||
int sys_network_dhcp_acquire(void);
|
||||
int sys_network_get_mac(net_mac_address_t *mac);
|
||||
int sys_network_get_nic_name(char *name_out);
|
||||
int sys_network_get_ip(net_ipv4_address_t *ip);
|
||||
int sys_network_set_ip(const net_ipv4_address_t *ip);
|
||||
int sys_network_get_stat(int stat_type);
|
||||
|
|
|
|||
|
|
@ -206,6 +206,14 @@ static void cmd_netinfo(void) {
|
|||
}
|
||||
net_mac_address_t mac;
|
||||
net_ipv4_address_t ip, gw, dns;
|
||||
char nic_name[64];
|
||||
|
||||
if (sys_network_get_nic_name(nic_name) == 0) {
|
||||
printf("NIC: %s\n", nic_name);
|
||||
} else {
|
||||
printf("NIC: Unknown\n");
|
||||
}
|
||||
|
||||
sys_network_get_mac(&mac);
|
||||
printf("MAC: %X:%X:%X:%X:%X:%X\n", mac.bytes[0], mac.bytes[1], mac.bytes[2], mac.bytes[3], mac.bytes[4], mac.bytes[5]);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue