paquetes enviados.
/** Comienza el envío de un nuevo frame */
void netdev_send_start()
{
+ // Wait until pending transmit operation completes.
+ while (read_reg(CR) & TXP) continue;
+ write_reg(ISR, PTX); // Limpio bit de interrupción
+
// Set remote DMA start address registers to indicate where to load packet.
write_reg(RSAR0, 0u);
write_reg(RSAR1, TX_PAGE_START);
// Issue command for RTL8019AS to transmit packet from it's local buffer.
write_reg(CR, START | TXP);
-
- // Wait until pending transmit operation completes.
- while(read_reg(CR) & TXP) continue;
}
void netdev_write_start(byte len)
{
// Set remote DMA byte count registers to indicate length of packet load.
- write_reg(RBCR0, len); // Tamaño máximo en principio
+ write_reg(RBCR0, len);
+ write_reg(RBCR1, 0u);
+
+ // Initiate DMA transfer of uip_buf & uip_appdata buffers to RTL8019AS.
+ write_reg(CR, WRITE);
+}
+
+void netdev_write_start_at(byte offset, byte len)
+{
+ // Set remote DMA start address registers to packet data.
+ write_reg(RSAR0, offset);
+ write_reg(RSAR1, TX_PAGE_START);
+
+ // Set remote DMA byte count registers to indicate length of packet load.
+ write_reg(RBCR0, len);
write_reg(RBCR1, 0u);
// Initiate DMA transfer of uip_buf & uip_appdata buffers to RTL8019AS.
printb(read_reg(ISR), 0x01);
printb(read_reg(BNRY), 0x02);
printb(current, 0x04);
- ledsb(0x00, 0x00);
+ printb(0x00, 0x00);
reset();
}
return 0;
// Configuración de paǵinas de buffers
#define TX_PAGE_START 0x40 // 0x4000 Tx buffer: 256 bytes (usamos 128)
-#define RX_PAGE_START 0x46 // 0x4600 Rx buffer: 31 * 256 = 7936 bytes
+#define RX_PAGE_START 0x41 // 0x4600 Rx buffer: 31 * 256 = 7936 bytes
#define RX_PAGE_STOP 0x60 // 0x6000
// Register base address
{
byte buf[64]; //XXX
byte i; //XXX
+ byte len;
- if (!netdev_recv_start()) // no recibimos nada (válido)
+ len = netdev_recv_start();
+ if (!len) // no recibimos nada (válido)
continue; // Probamos de nuevo
// Tenemos algo!
//printb(udp_dgram_len, 0x40);
// TODO
// Nuestro protocolo, por ahora un simple echo!
- netdev_read_start(udp_dgram_len-UDP_HEADER_SIZE);
- for (i = 0; i < udp_dgram_len-UDP_HEADER_SIZE; ++i)
- buf[i] = netdev_read_byte();
+ len = udp_dgram_len - UDP_HEADER_SIZE;
+ netdev_read_start(len);
+ for (i = 0; i < len; ++i)
+ buf[i] = udp_read_byte();
netdev_read_end();
+ if (!udp_checksum_ok())
+ goto drop;
netdev_recv_end();
// Respuesta
netdev_send_start();
eth_write_frame_header();
+ //udp_dgram_len = UDP_HEADER_SIZE+len;
+ //ip_packet_len = IP_HEADER_SIZE+udp_dgram_len;
ip_write_packet_header();
udp_write_dgram_header();
- netdev_write_start(udp_dgram_len-UDP_HEADER_SIZE);
- for (i = 0; i < udp_dgram_len-UDP_HEADER_SIZE; ++i)
- netdev_write_byte(buf[i]);
+ netdev_write_start(len);
+ for (i = 0; i < len; ++i)
+ udp_write_byte(buf[i]);
netdev_write_end();
+ udp_write_checksum(ETH_HEADER_SIZE+IP_HEADER_SIZE);
netdev_send_end(ETH_HEADER_SIZE+IP_HEADER_SIZE+udp_dgram_len);
}
}
*/
void netdev_send_end(byte len);
-/** Comienza una transferencia al dispositivo de red
+/** Comienza una escritura a los buffers del dispositivo de red
* @param len Cantidad de bytes a escribir
*/
void netdev_write_start(byte len);
+/** Comienza una escritura a los buffers del dispositivo de red a partir de un
+ * offset dado.
+ * @param offset Offset en donde comenzar a escribir
+ * @param len Cantidad de bytes a escribir
+ */
+void netdev_write_start_at(byte offset, byte len);
+
/** Escribe un byte al buffer de la placa de red para ser enviado
* @precond netdev_write_start() debe haber sido ejecutada
* @param b Byte a enviar
// vim: set et sw=4 sts=4 :
+#include "debug.h"
#include "netdev.h"
#include "ip.h"
#include "udp.h"
/* para calcular checksum */
static uint16 checksum;
+static byte byte_count;
+static byte last_byte;
/* agrega un word al checksum calculado */
static void sum(uint16 w)
netdev_read_start(UDP_HEADER_SIZE);
/* reseteamos checksum */
checksum = 0;
+ byte_count = 0;
/* el UDP tiene un checksum que incluye parte de la cabecera IP */
/* ip de origen */
sum(WORD(ip_addr_remote[0], ip_addr_remote[1]));
return true;
}
-uint16 udp_read_word()
+byte udp_read_byte()
{
- uint16 w = netdev_read_word();
- sum(w);
- return w;
+ byte b;
+ if (byte_count % 2) // impar, tengo 2, sumo
+ {
+ b = netdev_read_byte();
+ sum(WORD(last_byte, b));
+ }
+ else // par, guardo para sumar cuando tenga 2
+ {
+ b = netdev_read_byte();
+ last_byte = b;
+ }
+ ++byte_count;
+ return b;
}
bool udp_checksum_ok()
{
- return (uint16)~checksum;
+ // Verifico si falta sumar algo (UDP debe sumar de a un word)
+ if (byte_count == (udp_dgram_len - UDP_HEADER_SIZE))
+ sum(WORD(last_byte, 0x00)); // Relleno el byte que falta con 0x00
+ return !(uint16)~checksum;
}
void udp_write_dgram_header()
netdev_write_start(UDP_HEADER_SIZE);
/* reseteamos checksum */
checksum = 0;
+ byte_count = 0;
/* el UDP tiene un checksum que incluye parte de la cabecera IP */
/* ip de origen */
sum(WORD(ip_addr_remote[0], ip_addr_remote[1]));
netdev_write_end();
}
-void udp_write_word(uint16 w)
+void udp_write_byte(byte b)
{
- sum(w);
- netdev_write_word(w);
+ if (byte_count % 2) // impar, tengo 2, sumo
+ {
+ netdev_write_byte(b);
+ sum(WORD(last_byte, b));
+ }
+ else // par, guardo para sumar cuando tenga 2
+ {
+ netdev_write_byte(b);
+ last_byte = b;
+ }
+ ++byte_count;
}
-void udp_write_checksum()
+void udp_write_checksum(byte offset)
{
- // XXX TODO FIXME
+ // Verifico si falta sumar algo (UDP debe sumar de a un word)
+ if (byte_count == (udp_dgram_len - UDP_HEADER_SIZE))
+ sum(WORD(last_byte, 0x00)); // Relleno el byte que falta con 0x00
+ // Escribo checksum en el buffer de la placa de red
+ netdev_write_start_at(offset + 6, 2); // 6 bytes de offset hasta el checksum
+ netdev_write_word((uint16)~checksum); // Guardo checksum
+ netdev_write_end();
return;
}
/** Puerto UDP de destino */
extern uint16 udp_port_remote;
-/** Tamaño del datagrama UDP */
+/** Tamaño del datagrama UDP (no soportamos más de 255) */
extern byte udp_dgram_len;
/** Lee la cabecera del datagrama UDP.
*/
bool udp_read_dgram_header();
-/** Recibe un word del payload UDP chequeando el checksum. */
-uint16 udp_read_word();
+/** Recibe un word del payload UDP chequeando el checksum.
+ * @precond Hay que llamar antes a netdev_read_start()
+ */
+byte udp_read_byte();
/* Indica si el checksum calculado está ok */
bool udp_checksum_ok();
*/
void udp_write_dgram_header();
-/** Escribe un word al payload UDP chequeando el checksum. */
-void udp_write_word(uint16 w);
+/** Escribe un word al payload UDP chequeando el checksum.
+ * @precond Hay que llamar antes a netdev_write_start()
+ */
+void udp_write_byte(byte b);
-/* Escribe el checksum calculado al frame a enviar */
-void udp_write_checksum();
+/* Escribe el checksum calculado al frame a enviar
+ * @param offset Offset a partir de donde están las cabeceras UDP.
+ */
+void udp_write_checksum(byte offset);
#endif /* _UDP_H_ */