mirror of
https://github.com/logicog/RTLPlayground.git
synced 2026-10-29 17:54:14 +08:00
nic: Fix incorrect wrap handling of RX circular buffer
nic: move other nic functions into the dedicated nic files uip: alloc buffer multiple of 8 bytes Signed-off-by: João Silva <jgc3silva@gmail.com>
This commit is contained in:
18 files changed
+435
-117
No files matched your search
@@ -0,0 +1,90 @@
|
||||
#include "rtl837x_common.h"
|
||||
#include "rtl837x_regs.h"
|
||||
#include "rtl837x_sfr.h"
|
||||
#include "rtl837x_nic.h"
|
||||
|
||||
extern __xdata uint8_t rx_headers[16];
|
||||
|
||||
|
||||
#ifndef RTLP_HOST_TEST
|
||||
/* One RX DMA operation, starting inside the configured ring. The hardware
|
||||
* wraps transfers that cross its end; the initial address must be normalized.
|
||||
* Host tests supply a simulated DMA engine for this hardware boundary. */
|
||||
bool nic_rx_dma(__xdata uint8_t *buffer, uint16_t ring_ptr, uint8_t words) __reentrant
|
||||
{
|
||||
uint16_t guard = 0;
|
||||
|
||||
SFR_NIC_DATA_U16LE = (uint16_t)buffer;
|
||||
SFR_NIC_RING_U16LE = ring_ptr;
|
||||
SFR_NIC_CTRL = words;
|
||||
while (SFR_NIC_CTRL != 0) {
|
||||
if (++guard == 0) {
|
||||
print_string("NIC: RX transfer did not complete\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool nic_rx_copy(__xdata uint8_t *buffer, uint16_t ring_ptr, uint8_t words) __reentrant
|
||||
{
|
||||
if (ring_ptr > RTL837X_NIC_RX_RING_BYTES || (ring_ptr & 7))
|
||||
return false;
|
||||
if (ring_ptr == RTL837X_NIC_RX_RING_BYTES)
|
||||
ring_ptr = 0;
|
||||
|
||||
return nic_rx_dma(buffer, ring_ptr, words);
|
||||
}
|
||||
|
||||
|
||||
bool nic_rx_header(uint16_t ring_ptr) __reentrant
|
||||
{
|
||||
if (ring_ptr >= RTL837X_NIC_RX_RING_BYTES)
|
||||
return false;
|
||||
return nic_rx_copy(rx_headers, ring_ptr, 1);
|
||||
}
|
||||
|
||||
|
||||
bool nic_rx_packet(__xdata uint8_t *buffer, uint16_t ring_ptr) __reentrant
|
||||
{
|
||||
uint16_t len = ((uint16_t)rx_headers[5] << 8) | rx_headers[4];
|
||||
|
||||
if (!len || len > UIP_CONF_BUFFER_SIZE)
|
||||
return false;
|
||||
return nic_rx_copy(buffer, ring_ptr, (len + 7) >> 3);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Transfers data in XMEM to the ASIC for transmission by the NIC
|
||||
*/
|
||||
void nic_tx_packet(__xdata uint8_t *buffer, uint16_t len, uint16_t ring_ptr)
|
||||
{
|
||||
uint16_t guard = 0;
|
||||
|
||||
SFR_NIC_DATA_U16LE = (uint16_t)(uintptr_t)buffer;
|
||||
|
||||
#ifdef RXTXDBG
|
||||
print_string("TX: \n");
|
||||
for (uint8_t i = 0; i < 100; i++) {
|
||||
print_byte(uip_buf[i]);
|
||||
write_char(' ');
|
||||
}
|
||||
write_char('\n');
|
||||
#endif
|
||||
|
||||
ring_ptr <<= 3;
|
||||
ring_ptr |= 0x8000;
|
||||
SFR_NIC_RING_U16LE = ring_ptr;
|
||||
|
||||
len += 0xf;
|
||||
len >>= 3;
|
||||
SFR_NIC_CTRL = len;
|
||||
while (SFR_NIC_CTRL != 0) {
|
||||
if (++guard == 0) {
|
||||
print_string("NIC: TX transfer did not complete\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user