QEMU: rtl8139 not filling rx buffer

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
Artyom
Posts: 2
Joined: Wed Jan 09, 2019 5:29 am
Location: Ukraine, Kharkiv

QEMU: rtl8139 not filling rx buffer

Post by Artyom »

Hi! I'm having a problem with my rtl8139 driver. 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 doesn't fill.

Here is my code:

Code: Select all

#define RX_BUF_LEN 8192 + 16 + 1500
#define RX_READ_POINTER_MASK (~3)
uint nic_base;
uint rx_buffer;
uint cpptr;

extern void set_idt_handler(int i, void (*handler));
extern void nic_irq();

void rtl8139_handler()
{
	int status = inw(nic_base + 0x3e);

	if(status & (1 << 0))
	{
		printf("\nrtl8139: debug: received packet");

		u16* pointer = (u16*)(rx_buffer + cpptr);  // packet pointer
		u16  pLen = *(t + 1);                                 // packet len

                // data pointer
		pointer = pointer + 2;
               
		void * packet_data = malloc(pLen);   
		memcpy(packet_data, pointer, pLen);
		mem_dump(packet_data, pLen, 15);

		printf("\n packet len %d", pLen);
		
		cpptr = (cpptr + packet_length + 4 + 3) & RX_READ_POINTER_MASK;

		if (cpptr > RX_BUF_LEN)
			cpptr -= RX_BUF_LEN;

		outw(nic_base + 0x38, cpptr - 0x10);
	}
	outw(nic_base + 0x3E, 0x5);
}

void rtl8139_init()
{
	uint8_t bus;
	uint8_t slot; 
	uint8_t func;

	PCIFindDevice2(&bus, &slot, &func, 0x8139, 0x10EC);
	
	if(bus      == 0xFF) return;
	if(slot      == 0xFF) return;
	if(func     == 0xFF) return;
	
	PciBar bar;
	PciGetBar(&bar, PCI_MAKE_ID(bus, slot, func), 0);

	uint32_t nic_addr = bar.u.port;

	printf("\nrtl8139: driver started");

	// Enable PCI Bus Mastering for NIC
	unsigned short cfg = PciRead16(PCI_MAKE_ID(bus, slot, func), 4);
	PciWrite16(PCI_MAKE_ID(bus, slot, func), 4, cfg | 2);

	// turn on
	outb(bar.u.port + 0x52, 0); 
	printf("\nrtl8139: turned on");

	// Send reset command to NIC
	printf("\nrtl8139: reseting card");
	outb(bar.u.port + 0x37, 0x10);

	// Wait.....
	while(inb(bar.u.port + 0x37) & 0x10){}

	// Allocate rx_buffer
	rx_buffer = malloc(RX_BUF_LEN);

	// set RX-buffer and interrupts
	outl(bar.u.port + 0x30, (uint)rx_buffer);

        // set IMR + ISR
	outw(bar.u.port + 0x3C, 0x0005);
        // Configuring receive buffer (RCR)
	outd(bar.u.port + 0x44, 0xf | (1 << 7));
        // Enable Receive and Transmitter
	outb(bar.u.port + 0x37, 0x0C);

		
	uint8_t irq = (uint8_t)PCIGetIRQ(bus, slot, func);
	__asm("cli");
	set_idt_handler(irq+32, &nic_irq);
	__asm("sti");

	nic_base = bar.u.port;
}
Any help is much appreciated, thanks!
GhelloWorld
Member
Member
Posts: 27
Joined: Thu Apr 19, 2018 5:31 am

Re: QEMU: rtl8139 not filling rx buffer

Post by GhelloWorld »

Hello Artyom,

I have also had some problems with this particular card, luckily those where solved in this post: viewtopic.php?f=1&t=33157. One the biggest problems I had was that my buffer was not aligned, you should really do that.
One other thing to make debugging this card easier is to recompile qemu with DEBUG_RTL8139 Enabled, you can find this line in qemu/hw/rtl8139.c

Greetings,

Remco
Artyom
Posts: 2
Joined: Wed Jan 09, 2019 5:29 am
Location: Ukraine, Kharkiv

Re: QEMU: rtl8139 not filling rx buffer

Post by Artyom »

GhelloWorld wrote:Hello Artyom,

I have also had some problems with this particular card, luckily those where solved in this post: viewtopic.php?f=1&t=33157. One the biggest problems I had was that my buffer was not aligned, you should really do that.
One other thing to make debugging this card easier is to recompile qemu with DEBUG_RTL8139 Enabled, you can find this line in qemu/hw/rtl8139.c

Greetings,

Remco
Thank you so much for your help! It works!
Post Reply