#include "eth.h"
#include "dp8390.h"
+/** Tamaño del frame */
+byte netdev_len;
+
/// Datos persistentes del módulo
static union // Unión porque nunca se usan ambos juntos
{
}
persistent;
+/// Estructura de la cabecera del buffer de la placa de red.
+struct buf_hdr_t
+{
+ byte status; ///> Estado del frame recibido
+ byte next; ///> Offset del próximo frame
+ uint16 len; ///> Tamaño del frame
+};
+
+
/// Cambia de página sin modificar los demás bits del CR
#define SELECT_REG_PAGE(page) \
do \
}
/** Comienza la lectura de un nuevo frame
- * @return Cantidad de bytes del frame leído
+ * @precond netdev_recv_start() debe haber sido ejecutada
*/
-byte netdev_recv_start()
+void netdev_recv_start()
{
+ // Limpio tamaño del frame
+ netdev_len = 0;
+
// Check if the rx buffer has overflowed.
if (read_reg(ISR) & OVW)
{
byte current;
- // Select RTL8019AS register page 1.
SELECT_REG_PAGE(1);
-
- // Retrieve current receive buffer page
current = read_reg(CURR);
-
- // Select RTL8019AS register page 1.
SELECT_REG_PAGE(0);
+ // Hack: a veces reporta mal el flag de OVW, así que verificamos que
+ // relamente haya habido overflow.
if (read_reg(BNRY) == current)
{
printb(read_reg(ISR), 0x01);
printb(current, 0x04);
reset();
}
- return 0u;
+ return;
}
// Check if there is a packet in the rx buffer.
else if (read_reg(ISR) & PRX)
{
- struct buf_hdr_t
- {
- byte status; // Estado del frame recibido
- byte next; // Offset del próximo frame
- uint16 len; // Tamaño del frame
- }
- buf_hdr;
+ struct buf_hdr_t buf_hdr;
byte current;
byte bnry;
{
// Clear packet received interrupt flag.
write_reg(ISR, PRX | RXE);
- return 0u;
+ return;
}
// Set remote DMA byte count registers to packet header length.
|| ((buf_hdr.status & 0x0F) != RXSOK)
|| read_reg(RDMA)) // Parte alta del tamaño
{
- // Abort/ complete DMA operation.
+ // Terminamos DMA y pasamos al próximo frame
ABORT_DMA(START);
-
- // Advance boundary pointer to next packet start.
write_reg(BNRY, persistent.next_pkt);
-
- return 0;
+ return;
}
+ // Abort/ complete DMA operation.
+ ABORT_DMA(START);
+
+ // Todo OK, empezamos a recibir así que ponemos bien el tamaño del frame
+ netdev_len = buf_hdr.len;
+
// Set remote DMA start address registers to packet data.
write_reg(RSAR0, sizeof(struct buf_hdr_t));
write_reg(RSAR1, bnry);
// Initiate DMA transfer of packet data.
write_reg(CR, READ);
-
- return buf_hdr.len;
}
- return 0;
}
/** Lee un byte del buffer de la placa de red
*/
void netdev_recv_end()
{
- // Abort/ complete DMA operation.
+ // Termina de leer bytes de padding (si hay)
+ netdev_len += sizeof(struct buf_hdr_t);
+ if (read_reg(CRDA0) < netdev_len)
+ {
+ netdev_len -= read_reg(CRDA0) - 1; // El puntero está adelantado en 1
+ while (netdev_len--)
+ {
+ //printb(read_reg(CRDA0), netdev_len);
+ netdev_recv_byte();
+ }
+ }
+ // Completa DMA
ABORT_DMA(START);
-
- // Advance boundary pointer to next packet start.
+ // Pasa el próximo frame
write_reg(BNRY, persistent.next_pkt);
}
while (1) // Forever
{
byte i;
- byte len = netdev_recv_start();
- printb(len, 0x1);
- if (!len) // no recibimos nada (válido)
+ netdev_recv_start();
+ printb(netdev_len, 0x1);
+ if (!netdev_len) // no recibimos nada (válido)
continue; // Probamos de nuevo
// Tenemos algo!
goto drop; // Tiramos el paquete
printb(udp_dgram_len, 0x40);
- // TODO
// Nuestro protocolo, por ahora un simple echo!
for (i = 8; i < udp_dgram_len; ++i) // 8 por la cabecera UDP
{
printb(netdev_recv_byte(), 0x00);
}
- //i = (udp_dgram_len % 2) ? (udp_dgram_len - 1) : udp_dgram_len;
- for (i += 34; i < len; ++i) // 8 por las cabeceras eth+IP
- netdev_recv_byte();
drop:
netdev_recv_end();
}