Hi,
Okay, I have got the qmeu source, opened the debugging and compiled it.
Initially there was a problem with my device driver code, and the packets were not accepted and were not copied into the rx buffer.
My two main functions for intializing the rtl8139 are here:
Code: Select all
void RTL8139::reset ()
{
unsigned i;
Clock clock;
uint64_t flags;
save_flags( flags );
outb(ChipCmd, CmdReset);
cur_rx = 0;
cur_tx = 0;
enable();
clock.setTimeout(10);
while ( (inb(ChipCmd) & CmdReset) != 0 )
if ( clock.isTimeout() )
break;
restore_flags( flags );
for (int i=0; i<_countof(mac); i++)
outb(MAC0 + i,mac[i]);
outb( ChipCmd, CmdRxEnb | CmdTxEnb);
outl(RxConfig,
(RX_FIFO_THRESH<<13) | (RX_BUF_LEN_IDX<<11) | (RX_DMA_BURST<<8));
outl(TxConfig, (TX_DMA_BURST<<8) | 0x03000000);
// Configure the RX buffer //
outl(RxBuf, (uint64_t) rx_phys);
for (i = 0; i < NUM_TX_DESC; i++)
outw(TxAddr0 + (i * 4), (uint64_t)(tx_phys + (TX_BUF_SIZE*i)));
outw(RxMissed, 0);
outb( ChipCmd, CmdRxEnb | CmdTxEnb);
// outw( IntrMask, IntrDefault);
outw( IntrMask, PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK );
}
int RTL8139::start (bool _promisc)
{
uint64_t flags;
io_base = pciConfigHeader->getPCIBar(PCI_BAR_IO) & ~1;
mem_base = (uint8_t *)(pciConfigHeader->getPCIBar( PCI_BAR_MEM) & ~3);
if ( pciConfigHeader->get_pci_major() == 0x02 &&
pciConfigHeader->get_pci_minor() == 0x00 &&
pciConfigHeader->get_pci_interface() == 0x00)
video.putString("Realtek 8139 correct device interface/class\n" ,COLOR_CYAN,COLOR_BLACK);
else
{
video.putString("Realtek 8139 incorrect device interface/class\n" ,COLOR_RED,COLOR_BLACK);
return -1;
}
local_irq_save( flags );
outb(Config1, 0x00);
register_interrupt_handler(IRQ0+pciConfigHeader->getIntLine(),&handler);
// Read the MAC address //
if (read_eeprom(0) != 0xFFFF)
{
// Read from EEPROM //
video.putString("Reading mac from eeprom\n" ,COLOR_RED,COLOR_BLACK);
unsigned short *ap = (unsigned short *)mac;
for (int i = 0; i < 3; i++)
*ap++ = read_eeprom(i + 7);
}
else
{
video.putString("Reading mac from pciConfig\n" ,COLOR_RED,COLOR_BLACK);
getMac();
}
video.putString("Getting Media Information\n" ,COLOR_RED,COLOR_BLACK);
speed10 = (inb(MediaStatus) & MSRSpeed10) != 0;
fullduplex = (inw(MII_BMCR) & BMCRDuplex) != 0;
if (speed10) video.putString("Speed: 10 Mb\n" ,COLOR_RED,COLOR_BLACK);
else video.putString("Speed: 100 Mb\n" ,COLOR_RED,COLOR_BLACK);
if (fullduplex) video.putString("Full Duplex\n" ,COLOR_RED,COLOR_BLACK);
else video.putString("Half Duplex\n" ,COLOR_RED,COLOR_BLACK);
promisc = _promisc;
video.putString("Initialize the Rx and Tx rings buffer\n" ,COLOR_RED,COLOR_BLACK);
rx_phys = (uint8_t *) kmalloc_ptr->kmalloc_a(RX_BUF_LEN);
rx_ring = rx_phys;
Utils::memset(rx_phys,0,RX_BUF_LEN);
tx_phys = (uint8_t *) kmalloc_ptr->kmalloc_a(TX_BUF_SIZE*NUM_TX_DESC);
tx_ring = tx_phys;
Utils::memset(tx_phys,0,TX_BUF_SIZE*NUM_TX_DESC);
reset ();
if ( inb(TxStatus0) & MSRLinkFail)
video.putString("Cable not connected or other link failure\n" ,COLOR_RED,COLOR_BLACK);
else video.putString("Cable connected\n" ,COLOR_RED,COLOR_BLACK);
outl(IntrStatus,0x1);
local_irq_restore( flags );
local_irq_save( flags );
if ( promisc ) outb(RxConfig, AcceptBroadcast | AcceptMyPhys | AcceptAllPhys);
else outb(RxConfig, AcceptBroadcast | AcceptMyPhys);
local_irq_restore( flags );
return 0;
}
The problem basically was with the last part for the "promisc" condition.
Basically when I execute this without the surrounding local_irq_save and local_irq_restore it overwrites the buffer length configuration command executed earlier in the reset function and all the packets are rejected because of size limitation.
Now, I can see from the debug output that the packets are copied into the buffer, but still the irq interrupt does not fire.
The buffer keeps on filling until it is full and refuse any more packets (Since the handler is not called and consume the buffer) which indicate that the buffering by qemu has no problem now.
I spent the past 2 days trying to find where the part responsible for firing the interupt in qemu source code, but I could not find it; no luck.
The PIC and the keyboard interrupts work fine, so I expect that there is nothing worng
Even if there is a problem woth my interrupt handler for rtl8139, I expect that the irq hub function is called and the couple of prints are executed before calling the rtl8139 handler.
Code: Select all
if (ic->intNo == 43) // This condition is never true in my case and I expect that it should be if the rtl8139 interrupt fires
{
video.setPosition(30,10);
video.putString("Realtec Inetrrupt",COLOR_RED,COLOR_LIGHT_BROWN);
}
if (interrupt_handlers[ic->intNo] != 0)
{
isr_t handler = interrupt_handlers[ic->intNo];
handler();
}
else // This else is never true in my case and I expect that it should be if the rtl8139 interrupt fires and there is no handler assigned for it
{
video.clearScreen(COLOR_RED);
video.setPosition(30,10);
if ( ic->intNo < IRQ0)
{
video.putString(exception_messages[ic->intNo],COLOR_RED,COLOR_LIGHT_BROWN);
video.putString("[",COLOR_RED,COLOR_LIGHT_BROWN);
video.putDecimal(ic->intNo,COLOR_RED,COLOR_LIGHT_BROWN);
video.putString("]\n",COLOR_RED,COLOR_LIGHT_BROWN);
}
else
{
video.putString("Unhandled Interrupt",COLOR_RED,COLOR_LIGHT_BROWN);
video.putString("[",COLOR_RED,COLOR_LIGHT_BROWN);
video.putDecimal(ic->intNo,COLOR_RED,COLOR_LIGHT_BROWN);
video.putString("]\n",COLOR_RED,COLOR_LIGHT_BROWN);
}
for (;;);
}
// Send an EOI (end of interrupt) signal to the PICs.
// If this interrupt involved the slave.
if (ic->intNo >= 40)
{
// Send reset signal to slave.
Ports::outportb(PIC2_COMMAND, 0x20);
}
// Send reset signal to master. (As well as slave, if necessary).
Ports::outportb(PIC1_COMMAND, 0x20);
I have added a couple of comments up there regarding the if conditions I expect to execute if the rtl8139 fires an interrupt.
I just can not proceed any more.
I have one question though, my card is detected at IRQ line 11, and IRQ Pin 1; I don't understand what the pin number indicates, does this affect anything in the way interrupts fire.
Any suggestions or help will be highly appreciated.
Thanks a lot
Karim.