[Solved] Help! My E1000 Driver Cannot Receive Anything

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
nifanfa
Member
Member
Posts: 104
Joined: Tue Aug 17, 2021 10:40 am
Libera.chat IRC: visitor
Location: CN
Contact:

[Solved] Help! My E1000 Driver Cannot Receive Anything

Post by nifanfa »

Hello! I'm trying to implement E1000 support for MOSA.
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) ;
        }
    }
}
Last edited by nifanfa on Wed Aug 18, 2021 1:44 pm, edited 1 time in total.
nifanfa
Member
Member
Posts: 104
Joined: Tue Aug 17, 2021 10:40 am
Libera.chat IRC: visitor
Location: CN
Contact:

Re: Help! My E1000 Driver Cannot Receive Anything

Post by nifanfa »

It actually works fine yesterday. and i don't why it suddenly not work and i didn't modified anything of it

Image
Last edited by nifanfa on Wed Aug 18, 2021 12:05 am, edited 4 times in total.
nifanfa
Member
Member
Posts: 104
Joined: Tue Aug 17, 2021 10:40 am
Libera.chat IRC: visitor
Location: CN
Contact:

Re: Help! My E1000 Driver Cannot Receive Anything

Post by nifanfa »

The interrupt won't be triggered
nifanfa
Member
Member
Posts: 104
Joined: Tue Aug 17, 2021 10:40 am
Libera.chat IRC: visitor
Location: CN
Contact:

Re: Help! My E1000 Driver Cannot Receive Anything

Post by nifanfa »

and there's another same situation. i wrote a rtl8139 driver. it cannot receive the buffer neither. but both e1000 and rtl8139 can send buffer successfully to windows host.
nifanfa
Member
Member
Posts: 104
Joined: Tue Aug 17, 2021 10:40 am
Libera.chat IRC: visitor
Location: CN
Contact:

Re: Help! My E1000 Driver Cannot Receive Anything

Post by nifanfa »

And i did enabled bus mastering.
nifanfa
Member
Member
Posts: 104
Joined: Tue Aug 17, 2021 10:40 am
Libera.chat IRC: visitor
Location: CN
Contact:

Re: Help! My E1000 Driver Cannot Receive Anything

Post by nifanfa »

Um. i can make it work if i use IRQ0 instead of the InterruptLine. But i don't wish to do that...
nifanfa
Member
Member
Posts: 104
Joined: Tue Aug 17, 2021 10:40 am
Libera.chat IRC: visitor
Location: CN
Contact:

Re: Help! My E1000 Driver Cannot Receive Anything

Post by nifanfa »

The situation is I can send or receive(Use IRQ0 PIT Clock Interrupt) buffers. But i cannot use the interrupt from InterruptLine.
nifanfa
Member
Member
Posts: 104
Joined: Tue Aug 17, 2021 10:40 am
Libera.chat IRC: visitor
Location: CN
Contact:

Re: Help! My E1000 Driver Cannot Receive Anything

Post by nifanfa »

Image

I still don't know where's the problem is. I think i can only use thread temporally
Octocontrabass
Member
Member
Posts: 5563
Joined: Mon Mar 25, 2013 7:01 pm

Re: Help! My E1000 Driver Cannot Receive Anything

Post by Octocontrabass »

Where is your code to unmask the IRQ in the interrupt controller?
nifanfa
Member
Member
Posts: 104
Joined: Tue Aug 17, 2021 10:40 am
Libera.chat IRC: visitor
Location: CN
Contact:

Re: Help! My E1000 Driver Cannot Receive Anything

Post by nifanfa »

Octocontrabass wrote:Where is your code to unmask the IRQ in the interrupt controller?
Thank you very much. that's why i can't receive interrupt !!!!!!
nifanfa
Member
Member
Posts: 104
Joined: Tue Aug 17, 2021 10:40 am
Libera.chat IRC: visitor
Location: CN
Contact:

Re: Help! My E1000 Driver Cannot Receive Anything

Post by nifanfa »

Octocontrabass wrote:Where is your code to unmask the IRQ in the interrupt controller?
Hey. and i got a question. why i don't clear the mask of Mouse Interrupt (IRQ12) but i can still receive it? but why if i don't clear the mask of netcard it just not work?
Octocontrabass
Member
Member
Posts: 5563
Joined: Mon Mar 25, 2013 7:01 pm

Re: [Solved] Help! My E1000 Driver Cannot Receive Anything

Post by Octocontrabass »

Did the BIOS clear the IRQ12 mask before it loaded your OS?
nifanfa
Member
Member
Posts: 104
Joined: Tue Aug 17, 2021 10:40 am
Libera.chat IRC: visitor
Location: CN
Contact:

Re: [Solved] Help! My E1000 Driver Cannot Receive Anything

Post by nifanfa »

Octocontrabass wrote:Did the BIOS clear the IRQ12 mask before it loaded your OS?
i don't know
Octocontrabass
Member
Member
Posts: 5563
Joined: Mon Mar 25, 2013 7:01 pm

Re: [Solved] Help! My E1000 Driver Cannot Receive Anything

Post by Octocontrabass »

You can read the interrupt mask register to check.
Post Reply