Page 1 of 1

RTL8139 not filling buffer in QEMU

Posted: Tue Apr 16, 2013 1:02 pm
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.

Re: RTL8139 not filling buffer in QEMU

Posted: Tue Apr 16, 2013 2:12 pm
by dozniak
First of all, have you tried the same in bochs?

Re: RTL8139 not filling buffer in QEMU

Posted: Tue Apr 16, 2013 3:44 pm
by Combuster
My crystal ball says that your NIC doesn't do paging.

Re: RTL8139 not filling buffer in QEMU

Posted: Wed Apr 17, 2013 9:51 am
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?

Re: RTL8139 not filling buffer in QEMU

Posted: Thu Apr 18, 2013 12:07 am
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.

Re: RTL8139 not filling buffer in QEMU

Posted: Thu Apr 18, 2013 12:40 am
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.

Re: RTL8139 not filling buffer in QEMU

Posted: Thu Apr 18, 2013 3:20 pm
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.

Re: RTL8139 not filling buffer in QEMU

Posted: Thu Apr 18, 2013 5:12 pm
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.

Re: RTL8139 not filling buffer in QEMU

Posted: Fri Oct 18, 2013 2:32 pm
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.

Re: (solved) RTL8139 not filling buffer in QEMU

Posted: Fri Oct 18, 2013 2:52 pm
by brho
Ah, I see it's been solved in this post: http://forum.osdev.org/viewtopic.php?f=1&t=26938