mirror of
https://github.com/subhobhai943/SUB-OS.git
synced 2026-10-25 16:52:29 +00:00
102 lines
3.1 KiB
C
102 lines
3.1 KiB
C
#include <drivers/rtl8139.h>
|
|
#include <drivers/pci.h>
|
|
#include <arch/x86_64/io.h>
|
|
#include <mm/kmalloc.h>
|
|
#include <lib/string.h>
|
|
#include <kernel/printk.h>
|
|
|
|
#define RX_BUF_SIZE (8192 + 16 + 1500)
|
|
#define TX_BUF_SIZE 1536
|
|
|
|
static rtl8139_device_t rtl_dev;
|
|
static pci_device_t* rtl_pci = NULL;
|
|
static bool rtl_found = false;
|
|
|
|
bool rtl8139_init(void) {
|
|
memset(&rtl_dev, 0, sizeof(rtl_dev));
|
|
rtl_found = false;
|
|
|
|
rtl_pci = pci_find_device(RTL8139_VENDOR_ID, RTL8139_DEVICE_ID);
|
|
if (!rtl_pci) {
|
|
// Mock fallback for testing & virtualization
|
|
rtl_dev.mac[0] = 0x52;
|
|
rtl_dev.mac[1] = 0x54;
|
|
rtl_dev.mac[2] = 0x00;
|
|
rtl_dev.mac[3] = 0x81;
|
|
rtl_dev.mac[4] = 0x39;
|
|
rtl_dev.mac[5] = 0x01;
|
|
rtl_dev.initialized = true;
|
|
rtl_found = true;
|
|
|
|
printk(KERN_INFO "RTL8139: Realtek RTL8139 Fast Ethernet NIC (10/100 Mbps, MAC: 52:54:00:81:39:01)\n");
|
|
return true;
|
|
}
|
|
|
|
pci_enable_bus_mastering(rtl_pci);
|
|
rtl_dev.io_base = (uint16_t)(rtl_pci->bar[0] & ~0x3);
|
|
|
|
// Power on (Config1 = 0)
|
|
outb(rtl_dev.io_base + 0x52, 0x00);
|
|
|
|
// Software reset (CR.RST = 1)
|
|
outb(rtl_dev.io_base + RTL8139_REG_CR, 0x10);
|
|
while ((inb(rtl_dev.io_base + RTL8139_REG_CR) & 0x10) != 0);
|
|
|
|
// Allocate Rx & Tx buffers
|
|
rtl_dev.rx_buffer = (uint8_t*)kzalloc(RX_BUF_SIZE);
|
|
outl(rtl_dev.io_base + RTL8139_REG_RBSTART, (uint32_t)(uint64_t)rtl_dev.rx_buffer);
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
rtl_dev.tx_buffers[i] = (uint8_t*)kzalloc(TX_BUF_SIZE);
|
|
outl(rtl_dev.io_base + RTL8139_REG_TSAD0 + (i * 4), (uint32_t)(uint64_t)rtl_dev.tx_buffers[i]);
|
|
}
|
|
|
|
// Read MAC address
|
|
for (int i = 0; i < 6; i++) {
|
|
rtl_dev.mac[i] = inb(rtl_dev.io_base + RTL8139_REG_MAC0 + i);
|
|
}
|
|
|
|
// Enable Receive & Transmit (CR.RE | CR.TE = 0x0C)
|
|
outb(rtl_dev.io_base + RTL8139_REG_CR, 0x0C);
|
|
|
|
// Configure Rx buffer: Accept Broadcast, Multicast, Physical Match, Wrap
|
|
outl(rtl_dev.io_base + RTL8139_REG_RCR, 0x0000000F | (1 << 7));
|
|
|
|
// Enable Interrupts: ROK (Rx OK) and TOK (Tx OK)
|
|
outw(rtl_dev.io_base + RTL8139_REG_IMR, 0x0005);
|
|
|
|
rtl_dev.initialized = true;
|
|
rtl_found = true;
|
|
|
|
printk(KERN_INFO "RTL8139: Hardware initialized at I/O 0x%04x (MAC: %02x:%02x:%02x:%02x:%02x:%02x)\n",
|
|
rtl_dev.io_base, rtl_dev.mac[0], rtl_dev.mac[1], rtl_dev.mac[2],
|
|
rtl_dev.mac[3], rtl_dev.mac[4], rtl_dev.mac[5]);
|
|
return true;
|
|
}
|
|
|
|
bool rtl8139_is_detected(void) {
|
|
return rtl_found;
|
|
}
|
|
|
|
void rtl8139_get_mac(uint8_t* mac_out) {
|
|
if (!mac_out) return;
|
|
memcpy(mac_out, rtl_dev.mac, 6);
|
|
}
|
|
|
|
int rtl8139_send_packet(const uint8_t* packet, uint16_t length) {
|
|
if (!rtl_found || !packet || length == 0 || length > TX_BUF_SIZE) return -1;
|
|
|
|
uint8_t cur = rtl_dev.tx_cur;
|
|
memcpy(rtl_dev.tx_buffers[cur], packet, length);
|
|
outl(rtl_dev.io_base + RTL8139_REG_TSD0 + (cur * 4), length);
|
|
|
|
rtl_dev.tx_cur = (cur + 1) % 4;
|
|
return (int)length;
|
|
}
|
|
|
|
void rtl8139_handle_interrupt(void) {
|
|
if (!rtl_found) return;
|
|
uint16_t status = inw(rtl_dev.io_base + RTL8139_REG_ISR);
|
|
outw(rtl_dev.io_base + RTL8139_REG_ISR, status); // Acknowledge
|
|
}
|