OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 3:40 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 14 posts ] 
Author Message
 Post subject: [Solved] Help! My E1000 Driver Cannot Receive Anything
PostPosted: Tue Aug 17, 2021 11:04 am 
Offline
Member
Member

Joined: Tue Aug 17, 2021 10:40 am
Posts: 104
Location: CN
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:
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) ;
        }
    }
}

_________________
My github: https://github.com/nifanfa


Last edited by nifanfa on Wed Aug 18, 2021 1:44 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: Help! My E1000 Driver Cannot Receive Anything
PostPosted: Tue Aug 17, 2021 4:57 pm 
Offline
Member
Member

Joined: Tue Aug 17, 2021 10:40 am
Posts: 104
Location: CN
It actually works fine yesterday. and i don't why it suddenly not work and i didn't modified anything of it

Image

_________________
My github: https://github.com/nifanfa


Last edited by nifanfa on Wed Aug 18, 2021 12:05 am, edited 4 times in total.

Top
 Profile  
 
 Post subject: Re: Help! My E1000 Driver Cannot Receive Anything
PostPosted: Tue Aug 17, 2021 5:00 pm 
Offline
Member
Member

Joined: Tue Aug 17, 2021 10:40 am
Posts: 104
Location: CN
The interrupt won't be triggered

_________________
My github: https://github.com/nifanfa


Top
 Profile  
 
 Post subject: Re: Help! My E1000 Driver Cannot Receive Anything
PostPosted: Wed Aug 18, 2021 12:01 am 
Offline
Member
Member

Joined: Tue Aug 17, 2021 10:40 am
Posts: 104
Location: CN
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.

_________________
My github: https://github.com/nifanfa


Top
 Profile  
 
 Post subject: Re: Help! My E1000 Driver Cannot Receive Anything
PostPosted: Wed Aug 18, 2021 12:01 am 
Offline
Member
Member

Joined: Tue Aug 17, 2021 10:40 am
Posts: 104
Location: CN
And i did enabled bus mastering.

_________________
My github: https://github.com/nifanfa


Top
 Profile  
 
 Post subject: Re: Help! My E1000 Driver Cannot Receive Anything
PostPosted: Wed Aug 18, 2021 12:35 am 
Offline
Member
Member

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

_________________
My github: https://github.com/nifanfa


Top
 Profile  
 
 Post subject: Re: Help! My E1000 Driver Cannot Receive Anything
PostPosted: Wed Aug 18, 2021 12:37 am 
Offline
Member
Member

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

_________________
My github: https://github.com/nifanfa


Top
 Profile  
 
 Post subject: Re: Help! My E1000 Driver Cannot Receive Anything
PostPosted: Wed Aug 18, 2021 1:22 am 
Offline
Member
Member

Joined: Tue Aug 17, 2021 10:40 am
Posts: 104
Location: CN
Image

I still don't know where's the problem is. I think i can only use thread temporally

_________________
My github: https://github.com/nifanfa


Top
 Profile  
 
 Post subject: Re: Help! My E1000 Driver Cannot Receive Anything
PostPosted: Wed Aug 18, 2021 8:24 am 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5099
Where is your code to unmask the IRQ in the interrupt controller?


Top
 Profile  
 
 Post subject: Re: Help! My E1000 Driver Cannot Receive Anything
PostPosted: Wed Aug 18, 2021 1:43 pm 
Offline
Member
Member

Joined: Tue Aug 17, 2021 10:40 am
Posts: 104
Location: CN
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 !!!!!!

_________________
My github: https://github.com/nifanfa


Top
 Profile  
 
 Post subject: Re: Help! My E1000 Driver Cannot Receive Anything
PostPosted: Wed Aug 18, 2021 1:50 pm 
Offline
Member
Member

Joined: Tue Aug 17, 2021 10:40 am
Posts: 104
Location: CN
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?

_________________
My github: https://github.com/nifanfa


Top
 Profile  
 
 Post subject: Re: [Solved] Help! My E1000 Driver Cannot Receive Anything
PostPosted: Wed Aug 18, 2021 1:57 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5099
Did the BIOS clear the IRQ12 mask before it loaded your OS?


Top
 Profile  
 
 Post subject: Re: [Solved] Help! My E1000 Driver Cannot Receive Anything
PostPosted: Wed Aug 18, 2021 5:04 pm 
Offline
Member
Member

Joined: Tue Aug 17, 2021 10:40 am
Posts: 104
Location: CN
Octocontrabass wrote:
Did the BIOS clear the IRQ12 mask before it loaded your OS?

i don't know

_________________
My github: https://github.com/nifanfa


Top
 Profile  
 
 Post subject: Re: [Solved] Help! My E1000 Driver Cannot Receive Anything
PostPosted: Wed Aug 18, 2021 5:50 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5099
You can read the interrupt mask register to check.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 14 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Google [Bot] and 69 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group