Should I not be flushing the RX/TX buffers before the reset is finished? Am I not allotting enough time for it to fully reset?
Also, I (sometimes) get seemingly random rx_status errors that will light up all the error bits PLUS the ROK bit, which... makes no sense.
bad packet handler:
Code: Select all
Inter_Status = inb(ioaddr + IntrStatus);
Buffer_Status = inb(ioaddr + ChipCmd) & 0x01;
status = inw(ioaddr + IntrStatus);
outw(status & ~(RxFIFOOver | RxOverflow | RxOK), ioaddr + IntrStatus);
ring_offs = eth->cur_rx % RX_BUF_LEN;
rx_status = *(unsigned long*)(eth->rx_ring + ring_offs);
rx_size = (rx_status >> 16) & 0xffff;
if (rx_status & (RxBadSymbol|RxRunt|RxTooLong|RxCRCErr|RxBadAlign))
{
printf("rx_status issue (%x) \n", rx_status);
RTL8139_eth_Reset(eth);
}
else if (rx_size > 1540)
{
printf("rx_size (%x) > 1540! \n", rx_size);
RTL8139_eth_Reset(eth);
}
else if(rx_size == 0)
{
printf("rx_size == 0 \n",0x00);
RTL8139_eth_Reset(eth);
}
else
{/* normal packet interception */}
Code: Select all
static void RTL8139_eth_Reset(eth_t *eth)
{
int i = 0;
unsigned long ioaddr = eth->ioaddr;
printf("Resetting RTL8139: ");
eth->cur_rx = 0; // Reset Rx_Buffer position
eth->cur_tx = 0; // Reset Tx_Buffer position
eth->ring_offs = 0;
eth->DHCP_Completed = 0x00;
eth->server_mode = 0x00;
outportb(ioaddr + 0x37, 0x10); // Software Reset
for(i=0;i<(RX_BUF_LEN + 16);i++)
{eth->rx_ring[i] = '\0';}
for(i=0; i < (1536*4); i++)
{eth->tx_buffer[i] = '\0';}
while(((inportb(ioaddr + 0x37) >> 4) & 0x01) != 0x00); // Wait for reset to finish
outportl(ioaddr + 0x30, (unsigned long)eth->rx_ring); // Set the RX_Buffer memory location
outportb(ioaddr + 0x37, 0x0C); // Enable Transmitter and Reciever
outportw(ioaddr + 0x3C, 0x0001); // Set IMR (ROK only)
outportw(ioaddr + 0x3E, 0x0001); // Set ISR (ROK only)
outportw(ioaddr + 0x40, 0x0200); // Max DMA size = 64 bytes
outportl(ioaddr + 0x44, 0x0000F70F); // Enable Promiscuous Mode || Rx Buffer Length = 64K
outportl(ioaddr + 0x4C, 0x00000000); // Clear RX_Missed
outportb(ioaddr + 0x58, 0x08); // Speed = 100Mbps
outportw(ioaddr + 0x62, 0x2100); // Duplex = Full-Duplex
printf("[OK]\n");
printf("RX_Buffer is @ %x\n",(unsigned long)(eth->rx_ring));
}