RTL8139 not filling buffer in QEMU

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
User avatar
Jezze
Member
Member
Posts: 395
Joined: Thu Jul 26, 2007 1:53 am
Libera.chat IRC: jfu
Contact:

RTL8139 not filling buffer in QEMU

Post by Jezze »

Hi,

I have this weird problem and I'm looking for ideas on what could be wrong.

I'm trying to write a driver for the RTL8139 network card which is supported in QEMU. I receive interrupts from it when data packets come in but for some reason the RX buffer that it is suppose to fill with incoming packets does not fill.

This is how I initialize the card:

Code: Select all

outb(self->io + RTL8139_CONFIG1, 0x00); // Power on
outb(self->io + RTL8139_CR, 0x10); // Send reset
while (inb(self->io + RTL8139_CR) & 0x10);  // Wait for reset to complete
outw(self->io + RTL8139_IMR, RTL8139_ISR_ROK); // Unmask receive ok interrupt
outd(self->io + RTL8139_RBSTART, (unsigned int)self->rx); // Tell the nic to use the self->rx buffer (defined as a char[0x2600])
outd(self->io + RTL8139_RCR, 0xF); // Tell the nic to accept all valid packages
After initializing I set up a simple handler for when irq happens. It looks like this:

Code: Select all

unsigned int status = inw(driver->io + RTL8139_ISR); // Read isr status

if (status & RTL8139_ISR_ROK)
    outw(driver->io + RTL8139_ISR, RTL8139_ISR_ROK);
All this interrupt handler does is that it writes back the same bit it received. This is to just tell the nic that this type of interrupts has been handled. This actually works, I do receive this interrupt when I send data to it (from the host OS). The problem is that later using another entrance I try to read data from the self->rx buffer but it is just empty. The interrupt tells me there is data to be read but still the data isn't stored in the buffer. I can also see that the register that says how much data is currently in the buffer has increased.

My first idea was that perhaps the RBSTART address is just pointing to something else and fills in the data somewhere it shouldn't but I have tripple checked that and even hard-coded a physical memory address instead of using the self->rx address but that made no difference what so ever. All memory in this case is also identity mapped so the virtual addresses are the same as the physical ones.

This is the parameters I use for qemu in order to enable RTL8139 for QEMU:

Code: Select all

-net nic,model=rtl8139 -net tap,script=no,downscript=no,ifname=tap0 
ANY help would be so much appreciated.
Fudge - Simplicity, clarity and speed.
http://github.com/Jezze/fudge/
User avatar
dozniak
Member
Member
Posts: 723
Joined: Thu Jul 12, 2012 7:29 am
Location: Tallinn, Estonia

Re: RTL8139 not filling buffer in QEMU

Post by dozniak »

First of all, have you tried the same in bochs?
Learn to read.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: RTL8139 not filling buffer in QEMU

Post by Combuster »

My crystal ball says that your NIC doesn't do paging.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
Jezze
Member
Member
Posts: 395
Joined: Thu Jul 26, 2007 1:53 am
Libera.chat IRC: jfu
Contact:

Re: RTL8139 not filling buffer in QEMU

Post by Jezze »

Well it is quite obvious to me now that the DMA for the NIC that is supposed to write the packets to memory is somehow not allowed to write there. Perhaps this is what you ment Combuster? I don't know how to fix it though. Is there some permissions I need to change or something? Could it be some sort of cache problem perhaps?
Fudge - Simplicity, clarity and speed.
http://github.com/Jezze/fudge/
User avatar
dozniak
Member
Member
Posts: 723
Joined: Thu Jul 12, 2012 7:29 am
Location: Tallinn, Estonia

Re: RTL8139 not filling buffer in QEMU

Post by dozniak »

Jezze wrote:Well it is quite obvious to me now that the DMA for the NIC that is supposed to write the packets to memory is somehow not allowed to write there. Perhaps this is what you ment Combuster? I don't know how to fix it though. Is there some permissions I need to change or something? Could it be some sort of cache problem perhaps?
As Combuster said, the problem is most likely that DMA works directly with physical RAM and completely ignores any paging you have set up in the CPU.
Learn to read.
Opcode
Member
Member
Posts: 29
Joined: Mon Apr 01, 2013 2:50 pm

Re: RTL8139 not filling buffer in QEMU

Post by Opcode »

Jezze wrote: My first idea was that perhaps the RBSTART address is just pointing to something else and fills in the data somewhere it shouldn't but I have tripple checked that and even hard-coded a physical memory address instead of using the self->rx address but that made no difference what so ever. All memory in this case is also identity mapped so the virtual addresses are the same as the physical ones.
User avatar
Kazinsal
Member
Member
Posts: 559
Joined: Wed Jul 13, 2011 7:38 pm
Libera.chat IRC: Kazinsal
Location: Vancouver
Contact:

Re: RTL8139 not filling buffer in QEMU

Post by Kazinsal »

Jezze wrote:Well it is quite obvious to me now that the DMA for the NIC that is supposed to write the packets to memory is somehow not allowed to write there. Perhaps this is what you ment Combuster? I don't know how to fix it though. Is there some permissions I need to change or something? Could it be some sort of cache problem perhaps?
Translate the address of the RX buffer from a paged virtual address to a non-paged physical address and give the DMA controller the non-paged physical address.

DMA works directly on physical memory and ignores the CPU altogether -- thus, direct memory access.
User avatar
Jezze
Member
Member
Posts: 395
Joined: Thu Jul 26, 2007 1:53 am
Libera.chat IRC: jfu
Contact:

Re: RTL8139 not filling buffer in QEMU

Post by Jezze »

Unless I've done something complete wrong the physical and virtual addresses are the same since I have the first 4 megabytes in my kernel identity mapped and the RX buffer is within these 4 megabytes.

I'm currently debugging QEMU. I'm tracking the data flow as the data is passed to the pci_dma_write() function. Previously it used something called cpu_physical_memory_write() and I believe it is this change that stopped my rtl8139 driver from working.
Fudge - Simplicity, clarity and speed.
http://github.com/Jezze/fudge/
brho
Posts: 3
Joined: Thu Sep 15, 2011 1:46 pm

Re: RTL8139 not filling buffer in QEMU

Post by brho »

Jezze -

Did you ever trace this down? I'm having a similar problem with a different RTL8139 driver (one that I've been told was tested and used before).

My RBSTART is set to a physical address (like 0x2000), and whenever I receive a packet rx IRQ, all of that memory remains zero - no status or anything.

On a similar note, whenever I send packets, my network dump tells me it just sent all 0s, as if the NIC sent from some other address. My hunch is the two problems are linked.
brho
Posts: 3
Joined: Thu Sep 15, 2011 1:46 pm

Re: (solved) RTL8139 not filling buffer in QEMU

Post by brho »

Ah, I see it's been solved in this post: http://forum.osdev.org/viewtopic.php?f=1&t=26938
Post Reply