But i don't know why my driver can only send packet but cannot receive packet.
Here's my code:
Code: Select all
using Mosa.External.x86;
using Mosa.Kernel;
using Mosa.Kernel.x86;
using Mosa.Runtime;
using System.Runtime.InteropServices;
using static Mosa.External.x86.MMIO;
namespace MOSA9
{
public static unsafe class Intel82540EM
{
public static uint BAR0;
public static uint RXDescs;
public static uint TXDescs;
public static void Init()
{
PCIDevice device = PCI.GetDevice(VendorID.Intel, (DeviceID)0x100E);
Console.WriteLine("Intel 82540EM Exist");
device.EnableDevice();
BAR0 = (uint)(device.BAR0 & (~3));
Map(BAR0, 0x10000);
Console.WriteLine($"BAR0:{BAR0.ToString("x2")}");
WriteRegister(0x14, 0x1);
bool HasEEPROM = false;
for (int i = 0; i < 1024; i++)
{
if ((ReadRegister(0x14) & 0x10) != 0)
{
HasEEPROM = true;
break;
}
}
if (!HasEEPROM)
{
Panic.Error("No EEPROM Found On This Network Card");
}
else
{
Console.WriteLine("EEPROM Exist");
}
Ethernet.MACAddress = new byte[6];
Ethernet.MACAddress[0] = (byte)(ReadROM(0) & 0xFF);
Ethernet.MACAddress[1] = (byte)(ReadROM(0) >> 8);
Ethernet.MACAddress[2] = (byte)(ReadROM(1) & 0xFF);
Ethernet.MACAddress[3] = (byte)(ReadROM(1) >> 8);
Ethernet.MACAddress[4] = (byte)(ReadROM(2) & 0xFF);
Ethernet.MACAddress[5] = (byte)(ReadROM(2) >> 8);
Console.Write("MAC Address: ");
for (int i = 0; i < 6; i++) Console.Write($"{Ethernet.MACAddress[i].ToString("x2").PadLeft(2, '0')}{((i == 5) ? "" : ":")}");
Console.WriteLine();
Linkup();
for (int i = 0; i < 0x80; i++)
WriteRegister((ushort)(0x5200 + i * 4), 0);
Console.WriteLine($"IRQ:{device.InterruptLine}");
RXInit();
TXInit();
WriteRegister(0x00D0, 0x1F6DC);
WriteRegister(0x00D0, 0xFF & ~4);
ReadRegister(0xC0);
Console.WriteLine("Intel 82540EM Configuration Done");
}
private static void TXInit()
{
TXDescs = (uint)GC.AllocateObject(8 * 16);
for (int i = 0; i < 8; i++)
{
TXDesc* desc = (TXDesc*)(TXDescs + (i * 16));
desc->addr = 0;
desc->cmd = 0;
}
WriteRegister(0x3800, TXDescs);
WriteRegister(0x3804, 0);
WriteRegister(0x3808, 8 * 16);
WriteRegister(0x3810, 0);
WriteRegister(0x3818, 0);
WriteRegister(0x0400, (1 << 1) | (1 << 3));
}
public static uint RXCurr = 0;
public static uint TXCurr = 0;
private static void RXInit()
{
RXDescs = (uint)GC.AllocateObject(32 * 16);
for (uint i = 0; i < 32; i++)
{
RXDesc* desc = (RXDesc*)(RXDescs + (i * 16));
desc->addr = (ulong)(void*)GC.AllocateObject(2048 + 16);
desc->status = 0;
}
WriteRegister(0x2800, RXDescs);
WriteRegister(0x2804, 0);
WriteRegister(0x2808, 32 * 16);
WriteRegister(0x2810, 0);
WriteRegister(0x2818, 32 - 1);
WriteRegister(0x0100,
(1 << 1) |
(1 << 2) |
(1 << 3) |
(1 << 4) |
(0 << 6) |
(0 << 8) |
(1 << 15) |
(1 << 26) |
(0 << 16)
);
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct RXDesc
{
public ulong addr;
public ushort length;
public ushort checksum;
public byte status;
public byte errors;
public ushort special;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct TXDesc
{
public ulong addr;
public ushort length;
public byte cso;
public byte cmd;
public byte status;
public byte css;
public ushort special;
}
public static void WriteRegister(ushort Reg, uint Val)
{
Out32(BAR0 + Reg, Val);
}
public static uint ReadRegister(ushort Reg)
{
return In32(BAR0 + Reg);
}
public static ushort ReadROM(uint Addr)
{
uint Temp;
WriteRegister(0x14, 1 | (Addr << 8));
while (((Temp = ReadRegister(0x14)) & 0x10) == 0) ;
return ((ushort)((Temp >> 16) & 0xFFFF));
}
internal static void OnInterrupt()
{
uint Status = ReadRegister(0xC0);
if ((Status & 0x04) != 0)
{
//Console.WriteLine("Linking Up");
Linkup();
}
if ((Status & 0x10) != 0)
{
//Console.WriteLine("Good Threshold");
}
if ((Status & 0x80) != 0)
{
//Console.WriteLine("Packet Received");
uint _RXCurr = RXCurr;
RXDesc* desc = (RXDesc*)(RXDescs + (RXCurr * 16));
while ((desc->status & 0x1) != 0)
{
Ethernet.HandlePacket((byte*)desc->addr,desc->length);
//desc->addr;
desc->status = 0;
RXCurr = (RXCurr + 1) % 32;
WriteRegister(0x2818, _RXCurr);
}
}
}
private static void Linkup()
{
WriteRegister(0, ReadRegister(0) | 0x40);
}
public static void Send(byte* Buffer, ushort Length)
{
TXDesc* desc = (TXDesc*)(TXDescs + (TXCurr * 16));
desc->addr = (ulong)Buffer;
desc->length = Length;
desc->cmd = (1 << 0) | (1 << 1) | (1 << 3);
desc->status = 0;
byte _TXCurr = (byte)TXCurr;
TXCurr = (TXCurr + 1) % 8;
WriteRegister(0x3818, TXCurr);
while ((desc->status & 0xff) == 0) ;
}
}
}