QEMU: rtl8139 not filling rx buffer
Posted: Wed Jan 09, 2019 6:01 am
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:
Any help is much appreciated, thanks!
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;
}