]> git.llucax.com Git - z.facultad/66.09/etherled.git/commitdiff
Nueva manejo de buffers, un poco más modular. El proyecto quedó como un echo
authorLeandro Lucarella <llucax@gmail.com>
Fri, 9 Dec 2005 02:55:32 +0000 (02:55 +0000)
committerLeandro Lucarella <llucax@gmail.com>
Fri, 9 Dec 2005 02:55:32 +0000 (02:55 +0000)
server de UDP en el puerto 9876, es decir, recibe un paquete y lo contesta con
el mismo contenido a quién lo envió.

src/dp8390.c
src/dp8390.h
src/eth.c
src/eth.h
src/ip.c
src/ip.h
src/main.c
src/netdev.h
src/udp.c
src/udp.h

index 2943554aa0a3339b0827d31ef3048dbf525e3153..c56bb843a2a81658ee69d32ad963944a680c2730 100644 (file)
@@ -7,22 +7,17 @@
 /** Tamaño del frame */
 byte netdev_len;
 
-/// Datos persistentes del módulo
-static union // Unión porque nunca se usan ambos juntos
+// Próximo frame a obtener
+static struct
 {
-    byte send_len; ///> Tamaño del frame que será enviado
-    byte next_pkt; ///> Próximo frame a obtener
+    byte next_buf;
+    byte curr_buf;
+    byte curr_off;
 }
-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
-};
+recv_state;
 
+/// Tamaño de la cabecera de los buffers de la placa de red
+#define BUF_HDR_SIZE 4
 
 /// Cambia de página sin modificar los demás bits del CR
 #define SELECT_REG_PAGE(page)                         \
@@ -249,21 +244,43 @@ bool netdev_init()
 }
 
 
-/** Comienza el envío de un nuevo frame
- * @param len Tamaño del frame a enviar
- */
+/** Comienza el envío de un nuevo frame */
 void netdev_send_start()
 {
-    persistent.send_len = 0;
-    // Wait until pending transmit operation completes.
-    while(read_reg(CR) & TXP) continue;
-
     // Set remote DMA start address registers to indicate where to load packet.
     write_reg(RSAR0, 0u);
     write_reg(RSAR1, TX_PAGE_START);
+}
+
+/** Finaliza el envío del frame
+ * @precond netdev_send_start() debe haber sido ejecutada
+ * @precond se copiaron datos al dispositivo para enviar
+ * @param len Cantidad de bytes a transmitir
+ */
+void netdev_send_end(byte len)
+{
+    // Set transmit page start to indicate packet start.
+    write_reg(TPSR, TX_PAGE_START);
+
+    // Ethernet packets must be > 60 bytes, otherwise are rejected as runts.
+    if (len < MIN_PACKET_LEN)
+        len = MIN_PACKET_LEN;
+
+    // Set transmit byte count registers to indicate packet length.
+    write_reg(TBCR0, len);
+    write_reg(TBCR1, 0u);
+
+    // 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, MAX_PACKET_LEN); // Tamaño máximo en principio
+    write_reg(RBCR0, len); // Tamaño máximo en principio
     write_reg(RBCR1, 0u);
 
     // Initiate DMA transfer of uip_buf & uip_appdata buffers to RTL8019AS.
@@ -274,9 +291,8 @@ void netdev_send_start()
  * @precond netdev_send_start() debe haber sido ejecutada
  * @param b Byte a enviar
  */
-void netdev_send_byte(byte b)
+void netdev_write_byte(byte b)
 {
-    persistent.send_len++;
     write_reg(RDMA, b);
 }
 
@@ -284,46 +300,23 @@ void netdev_send_byte(byte b)
  * @precond netdev_send_start() debe haber sido ejecutada
  * @param w Word a enviar
  */
-void netdev_send_word(uint16 w)
+void netdev_write_word(uint16 w)
 {
-    persistent.send_len += 2;
     write_reg(RDMA, HIGH(w));
     write_reg(RDMA, LOW(w));
 }
 
-/** Finaliza el envío del frame
- * @precond netdev_send_start() debe haber sido ejecutada
- */
-void netdev_send_end()
+void netdev_write_end()
 {
     // Abort/ complete DMA operation.
     ABORT_DMA(START);
-
-    // Set transmit page start to indicate packet start.
-    write_reg(TPSR, TX_PAGE_START);
-
-    // Ethernet packets must be > 60 bytes, otherwise are rejected as runts.
-    if (persistent.send_len < MIN_PACKET_LEN)
-    {
-        persistent.send_len = MIN_PACKET_LEN;
-    }
-
-    // Set transmit byte count registers to indicate packet length.
-    write_reg(TBCR0, LOW(persistent.send_len));
-    write_reg(TBCR1, 0u);
-
-    // Issue command for RTL8019AS to transmit packet from it's local buffer.
-    write_reg(CR, START | TXP);
 }
 
 /** Comienza la lectura de un nuevo frame
- * @precond netdev_recv_start() debe haber sido ejecutada
+ * @return Cantidad de bytes a recibir
  */
-void netdev_recv_start()
+byte netdev_recv_start()
 {
-    // Limpio tamaño del frame
-    netdev_len = 0;
-
     // Check if the rx buffer has overflowed.
     if (read_reg(ISR) & OVW)
     {
@@ -340,25 +333,24 @@ void netdev_recv_start()
             printb(read_reg(ISR), 0x01);
             printb(read_reg(BNRY), 0x02);
             printb(current, 0x04);
+            ledsb(0x00, 0x00);
             reset();
         }
-        return;
+        return 0;
     }
     // Check if there is a packet in the rx buffer.
     else if (read_reg(ISR) & PRX)
     {
-        struct buf_hdr_t buf_hdr;
+        byte status;
+        byte len;
         byte current;
-        byte bnry;
 
         // Retrieve packet header. (status, next_ptr, length_l, length_h)
 
-        // Set remote DMA start address registers to packet header.
-        bnry = read_reg(BNRY) + 1;
-        if (bnry >= RX_PAGE_STOP)
-            bnry = RX_PAGE_START;
-        write_reg(RSAR0, 0u);
-        write_reg(RSAR1, bnry);
+        // Obtiene el buffer a leer actualmente
+        recv_state.curr_buf = read_reg(BNRY) + 1;
+        if (recv_state.curr_buf >= RX_PAGE_STOP)
+            recv_state.curr_buf = RX_PAGE_START;
 
         // Select RTL8019AS register page 1.
         SELECT_REG_PAGE(1);
@@ -370,70 +362,74 @@ void netdev_recv_start()
         SELECT_REG_PAGE(0);
 
         // Check if last packet has been removed from rx buffer.
-        if(bnry == current)
+        if(recv_state.curr_buf == current)
         {
             // Clear packet received interrupt flag.
             write_reg(ISR, PRX | RXE);
-            return;
+            return 0;
         }
 
         // Set remote DMA byte count registers to packet header length.
-        write_reg(RBCR0, sizeof(struct buf_hdr_t));
-        write_reg(RBCR1, 0x00);
-
-        // Clear remote DMA complete interrupt status register bit.
-        write_reg(ISR, RDC);
-
-        // Initiate DMA transfer of packet header.
-        write_reg(CR, READ);
+        recv_state.curr_off = 0;
+        netdev_read_start(BUF_HDR_SIZE);
 
         // Packet status.
-        buf_hdr.status = read_reg(RDMA);
+        status = netdev_read_byte();
 
         // Save next packet pointer.
-        buf_hdr.next = read_reg(RDMA);
-
-        // Indicamos cual es el próximo paquete para cuando termine
-        // FIXME poner más lindo para que consuma menos memoria
-        persistent.next_pkt = buf_hdr.next - 1;
+        recv_state.next_buf = netdev_read_byte() - 1;
 
         // Retrieve packet data length and subtract CRC bytes.
-        buf_hdr.len = read_reg(RDMA) - sizeof(struct buf_hdr_t);
+        len = netdev_read_byte() - BUF_HDR_SIZE;
 
         // Si es muy grande, muy chico o hubo error, lo descartamos
-        if ((buf_hdr.len < MIN_PACKET_LEN) || (buf_hdr.len > MAX_PACKET_LEN)
-                || ((buf_hdr.status & 0x0F) != RXSOK)
-                || read_reg(RDMA)) // Parte alta del tamaño
+        if ((len < MIN_PACKET_LEN) || (len > MAX_PACKET_LEN)
+                || ((status & 0x0F) != RXSOK)
+                || netdev_read_byte()) // Parte alta del tamaño
         {
             // Terminamos DMA y pasamos al próximo frame
-            ABORT_DMA(START);
-            write_reg(BNRY, persistent.next_pkt);
-            return;
+            netdev_read_end();
+            write_reg(BNRY, recv_state.next_buf);
+            return 0;
         }
 
         // Abort/ complete DMA operation.
-        ABORT_DMA(START);
+        netdev_read_end();
 
-        // Todo OK, empezamos a recibir así que ponemos bien el tamaño del frame
-        netdev_len = buf_hdr.len;
+        return len;
+    }
 
-        // Set remote DMA start address registers to packet data.
-        write_reg(RSAR0, sizeof(struct buf_hdr_t));
-        write_reg(RSAR1, bnry);
+    return 0;
+}
 
-        // Set remote DMA byte count registers to packet data length.
-        write_reg(RBCR0, buf_hdr.len);
-        write_reg(RBCR1, 0u);
+/** Finaliza la recepción del frame
+ * @precond netdev_recv_start() debe haber sido ejecutada
+ */
+void netdev_recv_end()
+{
+    // Pasa el próximo frame
+    write_reg(BNRY, recv_state.next_buf);
+}
 
-        // Initiate DMA transfer of packet data.
-        write_reg(CR, READ);
-    }
+void netdev_read_start(byte len)
+{
+    // Set remote DMA start address registers to packet data.
+    write_reg(RSAR0, recv_state.curr_off);
+    write_reg(RSAR1, recv_state.curr_buf);
+    recv_state.curr_off += len;
+
+    // Set remote DMA byte count registers to packet data length.
+    write_reg(RBCR0, len);
+    write_reg(RBCR1, 0);
+
+    // Initiate DMA transfer of packet data.
+    write_reg(CR, READ);
 }
 
 /** Lee un byte del buffer de la placa de red
  * @precond netdev_recv_start() debe haber sido ejecutada
  */
-byte netdev_recv_byte()
+byte netdev_read_byte()
 {
     return read_reg(RDMA);
 }
@@ -441,31 +437,18 @@ byte netdev_recv_byte()
 /** Lee un word del buffer de la placa de red
  * @precond netdev_recv_start() debe haber sido ejecutada
  */
-uint16 netdev_recv_word()
+uint16 netdev_read_word()
 {
-    uint16 w = netdev_recv_byte() << 8;
-    return w + netdev_recv_byte();
+    uint16 w = read_reg(RDMA) << 8;
+    return w + read_reg(RDMA);
 }
 
 /** Finaliza la lectura del frame
  * @precond netdev_recv_start() debe haber sido ejecutada
  */
-void netdev_recv_end()
+void netdev_read_end()
 {
-    // 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);
-    // Pasa el próximo frame
-    write_reg(BNRY, persistent.next_pkt);
 }
 
index a11854cfc839e711e3eb862dcf4871b004df1563..7587ec3743e1b0328074c7dda826dbc677af8532 100644 (file)
@@ -24,15 +24,15 @@ sbit IOR = CTRL_PORT^5;     // ISA slot pin B14, RTL8019AS pin 29, active low
 sbit NICE = CTRL_PORT^2;    // A7, usado para activar placa de red
 #endif
 
-// Configuración de paǵinas de buffers
-#define TX_PAGE_START  0x40      // 0x4000 Tx buffer:  6 * 256 = 1536 bytes
-#define RX_PAGE_START  0x46      // 0x4600 Rx buffer: 26 * 256 = 6656 bytes
-#define RX_PAGE_STOP   0x60      // 0x6000
-
 // Límites de tamaño de paquete
 #define MIN_PACKET_LEN 60u  // Mínimo permitido por 802.3
 #define MAX_PACKET_LEN 128u // Mínimo permitido por nuestra escasa memoria =)
 
+// 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_STOP   0x60 // 0x6000
+
 // Register base address
 #define REG_BASE 0x0000 // Hardwired to 0x0300
 
index 9085dbb553e634539c14b7700a32acc455051e03..ee40aacbf83f89a301c7821dba5e59b3c4751c7c 100644 (file)
--- a/src/eth.c
+++ b/src/eth.c
@@ -17,15 +17,16 @@ bool eth_read_frame_header()
 {
     /* variable para iterar */
     byte i;
+    netdev_read_start(ETH_HEADER_SIZE);
     /* descarto MAC de destino, acepto broadcasts */
     for (i = 0; i < ETH_ADDR_SIZE; ++i)
-        netdev_recv_byte();
+        netdev_read_byte();
     /* obtenemos MAC de origen */
     for (i = 0; i < ETH_ADDR_SIZE; ++i)
-        eth_addr_remote[i] = netdev_recv_byte();
+        eth_addr_remote[i] = netdev_read_byte();
     /* obtenemos tipo de protocolo transportado por el frame, (sólo
      * aceptamos IP y ARP) */
-    switch (netdev_recv_word())
+    switch (netdev_read_word())
     {
         case IP:
             eth_proto = ETH_IP;
@@ -34,8 +35,10 @@ bool eth_read_frame_header()
             eth_proto = ETH_ARP;
             break;
         default:
+            netdev_read_end();
             return false; /* drop */
     }
+    netdev_read_end();
     return true;
 }
 
@@ -43,13 +46,15 @@ void eth_write_frame_header()
 {
     /* variable para iterar */
     byte i;
+    netdev_write_start(ETH_HEADER_SIZE);
     /* mandamos como MAC de destino la remota */
     for (i = 0; i < ETH_ADDR_SIZE; ++i)
-        netdev_send_byte(eth_addr_remote[i]);
+        netdev_write_byte(eth_addr_remote[i]);
     /* y como fuente la nuestra */
     for (i = 0; i < ETH_ADDR_SIZE; ++i)
-        netdev_send_byte(eth_addr_local[i]);
+        netdev_write_byte(eth_addr_local[i]);
     /* escribimos el tipo de paquete que transporta el frame */
-    netdev_send_word((eth_proto == ETH_IP) ? IP : ARP);
+    netdev_write_word((eth_proto == ETH_IP) ? IP : ARP);
+    netdev_write_end();
 }
 
index 9a640de86b572d97aeee6b4907f665c957dbc8de..f65f5d28dadd6c97f42c0f5b981e35acbc20e42c 100644 (file)
--- a/src/eth.h
+++ b/src/eth.h
@@ -23,6 +23,9 @@
 /** Tamaño de dirección MAC (en bytes) */
 #define ETH_ADDR_SIZE 6
 
+/** Tamaño de cabecera ethernet */
+#define ETH_HEADER_SIZE 14
+
 /** Tipos de frame ethernet */
 typedef enum { ETH_IP, ETH_ARP } eth_proto_t;
 
index 0b4b2e27b5892f76b88b12a1cb6c15404fd8fd14..f60c3d4b125a6ee144b3997e7bc480d81101e560 100644 (file)
--- a/src/ip.c
+++ b/src/ip.c
@@ -1,6 +1,7 @@
 // vim: set et sw=4 sts=4 :    
 
 #include "netdev.h"
+#include "debug.h"
 #include "ip.h"
 
 /** protocolos soportados */
@@ -29,41 +30,43 @@ bool ip_read_packet_header()
 {
     /* variables utilitarias (iterar y/o buffer) */
     byte h, l;
+    bit ok = true;
+    netdev_read_start(IP_HEADER_SIZE);
     /* reseteamos checksum */
     checksum = 0;
     /* versión y tamaño de cabecera vienen en el 1er byte */
-    h = netdev_recv_byte();
+    h = netdev_read_byte();
     /* sólo soportamos versión 4 */
     if ((h >> 4) != 4)
-        return false; /* drop */
+        ok = false;
     /* tamaño de cabecera */
     if ((h & 0x0F) != 5) /* no aceptamos opciones raras =) */
-        return false; /* drop */
+        ok = false;
     /* ignoramos el TOS y vamos calculando checksum */
-    sum(WORD(h, netdev_recv_byte()));
+    sum(WORD(h, netdev_read_byte()));
     /* obtenemos tamaño del paquete */
-    if (h = netdev_recv_byte()) /* tiene más de 255 bytes (no lo soportamos) */
-        return false; /* drop */
-    ip_packet_len = netdev_recv_byte(); /* hasta 255 bytes tienen los nuestros */
+    if (h = netdev_read_byte()) /* tiene más de 255 bytes (no lo soportamos) */
+        ok = false;
+    ip_packet_len = netdev_read_byte(); /* hasta 255 bytes tienen los nuestros */
     /* vamos calculando checksum */
     sum(WORD(h, ip_packet_len));
     /* ignoramos identificación (2 bytes) y vamos calculando checksum */
-    sum(netdev_recv_word());
+    sum(netdev_read_word());
     /* si tiene prendido el bit de MF (More Fragments, bit 5 del byte, bit 2
      * de los flags de la cabecera) o si tiene un offset de fragmento (bits
      * del 4 al 0 y todos los bits del byte siguiente), dropeamos (no
      * soportamos fragmentación) */
-    h = netdev_recv_byte();
-    l = netdev_recv_byte();
+    h = netdev_read_byte();
+    l = netdev_read_byte();
     if ((h & 0x3F) || l)
-        return false; /* drop */
+        ok = false;
     /* seguimos calculando checksum */
     sum(WORD(h, l));
     /* no le damos bola al TTL (no le vamos a hacer lío si ya llegó hasta
      * acá el pobre =) */
-    h = netdev_recv_byte();
+    h = netdev_read_byte();
     /* protocolo (sólo soportamos UDP e ICMP) */
-    l = netdev_recv_byte();
+    l = netdev_read_byte();
     switch (l)
     {
         case ICMP:
@@ -73,16 +76,16 @@ bool ip_read_packet_header()
             ip_proto = IP_UDP;
             break;
         default:
-            return false; /* drop */
+            ok = false;
     }
     /* sigo calculando checksum */
     sum(WORD(h, l));
     /* obtenemos checksum y seguimos el cálculo */
-    sum(netdev_recv_word());
+    sum(netdev_read_word());
     /* obtenemos IP de origen (mientras seguimos calculando el checksum) */
     for (l = 0; l < IP_ADDR_SIZE; ++l)
     {
-        ip_addr_remote[l] = netdev_recv_byte();
+        ip_addr_remote[l] = netdev_read_byte();
         if (l % 2)
             sum(WORD(h, ip_addr_remote[l]));
         else
@@ -93,8 +96,8 @@ bool ip_read_packet_header()
     // TODO si soportamos DHCP hay que aceptar broadcasts!
     for (l = 0; l < IP_ADDR_SIZE; ++l)
     {
-        if (ip_addr_local[l] != netdev_recv_byte()) 
-            return false; /* drop (no es para nosotros) */
+        if (ip_addr_local[l] != netdev_read_byte()) 
+            ok = false;
         if (l % 2)
             sum(WORD(h, ip_addr_local[l]));
         else
@@ -102,8 +105,9 @@ bool ip_read_packet_header()
     }
     /* verificamos checksum */
     if ((uint16)~checksum)
-        return false; /* checksum malo, drop */
-    return true;
+        ok = false;
+    netdev_read_end();
+    return ok;
 }
 
 void ip_write_packet_header()
@@ -114,28 +118,29 @@ void ip_write_packet_header()
     static uint16 id;
     /* reseteamos checksum */
     checksum = 0;
+    netdev_write_start(IP_HEADER_SIZE);
     /* versión (4) y tamaño de cabecera (5 words de 4 bytes = 20 bytes) */
-    netdev_send_byte(h = 0x45);
+    netdev_write_byte(h = 0x45);
     /* TOS (0xc0 = Internetwork Control, 0x00 = normal) */
     l = (ip_proto == IP_ICMP) ? 0xc0 : 0x00;
-    netdev_send_byte(l);
+    netdev_write_byte(l);
     sum(WORD(h, l)); /* actualizamos checksum */
     /* escribimos tamaño del paquete */
-    netdev_send_byte(h = 0x00); /* nunca vamos a mandar algo de más de 255 bytes */
-    netdev_send_byte(ip_packet_len);
+    netdev_write_byte(h = 0x00); /* nunca vamos a mandar algo de más de 255 bytes */
+    netdev_write_byte(ip_packet_len);
     sum(WORD(h, ip_packet_len)); /* actualizamos checksum */
     /* identificación (sirve para reensamblar paquetes) */
-    netdev_send_word(id);
+    netdev_write_word(++id);
     sum(id); /* actualizamos checksum */
     /* pedimos que no se fragmente */
-    netdev_send_byte(h = 0x40); /* Don't Fragment (DF) = 1 */
-    netdev_send_byte(l = 0x00); /* offset de fragmento = 0 */
+    netdev_write_byte(h = 0x40); /* Don't Fragment (DF) = 1 */
+    netdev_write_byte(l = 0x00); /* offset de fragmento = 0 */
     sum(WORD(h, l)); /* actualizamos checksum */
     /* TTL de 64 saltos porque está de moda */
-    netdev_send_byte(h = 0x40);
+    netdev_write_byte(h = 0x40);
     /* protocolo (sólo soportamos UDP e ICMP) */
     l = (ip_proto == IP_ICMP) ? ICMP : UDP;
-    netdev_send_byte(l);
+    netdev_write_byte(l);
     sum(WORD(h, l)); /* actualizamos checksum */
     /* checksum: antes de poder escribir el checksum hay que terminar de
      * calcularlo según las direcciones IP de origen y destino, así que eso
@@ -151,13 +156,14 @@ void ip_write_packet_header()
         else
             h = ip_addr_remote[l];
     /* ahora sí grabamos el checksum */
-    netdev_send_word(~checksum);
+    netdev_write_word(~checksum);
     /* ahora sí, continuamos poniendo las direcciones */
     /* ponemos como dirección IP de origen la nuestra */
     for (l = 0; l < IP_ADDR_SIZE; ++l)
-        netdev_send_byte(ip_addr_local[l]);
+        netdev_write_byte(ip_addr_local[l]);
     /* IP de destino, la remota */
     for (l = 0; l < IP_ADDR_SIZE; ++l)
-        netdev_send_byte(ip_addr_remote[l]);
+        netdev_write_byte(ip_addr_remote[l]);
+    netdev_write_end();
 }
 
index 0b3fff19b5ff8a58cf64d5e91092712431e267c0..a40693a812bb97130f8d2afb1a64ce745bce67c7 100644 (file)
--- a/src/ip.h
+++ b/src/ip.h
@@ -35,6 +35,9 @@
 /** Tamaño de dirección IP (en bytes) */
 #define IP_ADDR_SIZE 4
 
+/** Tamaño de cabecera IP (en bytes) */
+#define IP_HEADER_SIZE 20
+
 /** Tipos de paquete IP */
 typedef enum { IP_UDP, IP_ICMP } ip_proto_t;
 
index 787f025e56be6ee3e65267724c624763ed04fefa..18df51295b9c65c96089325ecd27930d43a5250c 100644 (file)
@@ -26,14 +26,14 @@ void main(void)
     ip_addr_local[3] = 100;
 
     // Inicializo puerto UDP
-    udp_port_local = 9000;
+    udp_port_local = 9876;
 
     while (1) // Forever
     {
-        byte i;
-        netdev_recv_start();
-        printb(netdev_len, 0x1);
-        if (!netdev_len) // no recibimos nada (válido)
+        byte buf[64]; //XXX
+        byte i; //XXX
+
+        if (!netdev_recv_start()) // no recibimos nada (válido)
             continue; // Probamos de nuevo
 
         // Tenemos algo!
@@ -47,7 +47,7 @@ void main(void)
         // Vemos que protocolo transporta
         switch (eth_proto)
         {
-            case ETH_ARP: // FIXME, implementar ARP!
+            case ETH_ARP: // TODO: implementar ARP!
                 goto drop; // Tiramos el paquete
 
             case ETH_IP:
@@ -60,7 +60,7 @@ void main(void)
                 // Vemos que protocolo transporta
                 switch (ip_proto)
                 {
-                    case IP_ICMP: // FIXME, implementar ICMP!
+                    case IP_ICMP: // TODO: implementar ICMP!
                         goto drop; // Tiramos el paquete
 
                     case IP_UDP:
@@ -69,16 +69,30 @@ void main(void)
                         if (!udp_read_dgram_header()) // No es un buen header
                             goto drop; // Tiramos el paquete
 
-                        printb(udp_dgram_len, 0x40);
+                        //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);
-                        }
-drop:
+                        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();
+                        netdev_read_end();
                         netdev_recv_end();
+
+                        // Respuesta
+                        netdev_send_start();
+                        eth_write_frame_header();
+                        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_end();
+                        netdev_send_end(ETH_HEADER_SIZE+IP_HEADER_SIZE+udp_dgram_len);
                 }
         }
+        continue;
+drop:
+        netdev_recv_end();
     }
 }
 
index e8246661b5a02021b7b824cb79e3aa76c9d06d26..175313c5b111be865ca07c4c97fb0eb8abe8312d 100644 (file)
@@ -13,46 +13,67 @@ extern byte netdev_len;
  */
 bool netdev_init();
 
-/** Comienza el envío de un nuevo frame
- * @param len Tamaño del frame a enviar
- */
+/** Comienza el envío de un nuevo frame */
 void netdev_send_start();
 
-/** Escribe un byte al buffer de la placa de red para ser enviado
+/** Finaliza el envío del frame
  * @precond netdev_send_start() debe haber sido ejecutada
+ * @precond se copiaron datos al dispositivo para enviar
+ * @param len Cantidad de bytes a transmitir
+ */
+void netdev_send_end(byte len);
+
+/** Comienza una transferencia al dispositivo de red
+ * @param len Cantidad de bytes a escribir
+ */
+void netdev_write_start(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
  */
-void netdev_send_byte(byte b);
+void netdev_write_byte(byte b);
 
 /** Escribe un word al buffer de la placa de red para ser enviado
- * @precond netdev_send_start() debe haber sido ejecutada
+ * @precond netdev_write_start() debe haber sido ejecutada
  * @param w Word a enviar
  */
-void netdev_send_word(uint16 w);
+void netdev_write_word(uint16 w);
 
-/** Finaliza el envío del frame
- * @precond netdev_send_start() debe haber sido ejecutada
+/** Finaliza una transferencia al dispositivo de red
+ * @precond netdev_write_start() fue llamada y se ecribió la cantidad de bytes
+ *          en ella especificada
  */
-void netdev_send_end();
+void netdev_write_end();
 
-/** Comienza la lectura de un nuevo frame
- * @postcond Deja en netdev_len el tamaño del frame recibido
+/** Comienza la recepción de un nuevo frame
+ * @return Cantidad de bytes a recibir
  */
-void netdev_recv_start();
+byte netdev_recv_start();
+
+/** Finaliza la lectura del frame
+ * @precond netdev_recv_start() debe haber sido ejecutada
+ */
+void netdev_recv_end();
+
+/** Comienza a leer bytes del dispositivo de red
+ * @param len Cantidad de bytes a leer
+ */
+void netdev_read_start(byte len);
 
 /** Lee un byte del buffer de la placa de red
  * @precond netdev_recv_start() debe haber sido ejecutada
  */
-byte netdev_recv_byte();
+byte netdev_read_byte();
 
 /** Lee un word del buffer de la placa de red
  * @precond netdev_recv_start() debe haber sido ejecutada
  */
-uint16 netdev_recv_word();
+uint16 netdev_read_word();
 
 /** Finaliza la lectura del frame
  * @precond netdev_recv_start() debe haber sido ejecutada
  */
-void netdev_recv_end();
+void netdev_read_end();
 
 #endif // _NETDEV_H_
index 9738341a243bbba08d4333241557ca0331b5bb54..f8264b12d5b18badf8d4fdad9266f9b7c1f40282 100644 (file)
--- a/src/udp.c
+++ b/src/udp.c
@@ -24,6 +24,8 @@ static void sum(uint16 w)
 bool udp_read_dgram_header()
 {
     byte tmp;
+    bit ok = true;
+    netdev_read_start(UDP_HEADER_SIZE);
     /* reseteamos checksum */
     checksum = 0;
     /* el UDP tiene un checksum que incluye parte de la cabecera IP */
@@ -39,33 +41,34 @@ bool udp_read_dgram_header()
     sum(ip_packet_len - 20);
     /* de ahora en más todos los datos del checksum corresponden a UDP */
     /* puerto origen (remoto) */
-    udp_port_remote = netdev_recv_word();
+    udp_port_remote = netdev_read_word();
     /* agregamos puerto de origen al checksum */
     sum(udp_port_remote);
     /* sólo aceptamos datagramas a nuestro puerto */
-    if (netdev_recv_word() != udp_port_local)
-        return false; /* drop */
+    if (netdev_read_word() != udp_port_local)
+        ok = false; /* drop */
     /* agregamos puerto de destino al checksum */
     sum(udp_port_local);
     /* tamaño del datagrama */
-    if (tmp = netdev_recv_byte()) /* no soportamos más de 255 bytes */
-        return false; /* drop */
-    udp_dgram_len = netdev_recv_byte(); /* parte baja */
+    if (tmp = netdev_read_byte()) /* no soportamos más de 255 bytes */
+        ok = false; /* drop */
+    udp_dgram_len = netdev_read_byte(); /* parte baja */
     if (udp_dgram_len < 8) /* no puede ser más chico que sus cabeceras */
-        return false; /* drop */
+        ok = false; /* drop */
     /* agregamos tamaño al checksum */
     sum(WORD(tmp, udp_dgram_len));
     /* agregamos checksum al checksum */
-    sum(netdev_recv_word());
+    sum(netdev_read_word());
     /* falta agregar el cuerpo del mensaje para verificar la suma
      * esto debe hacerlo el protocolo que sigue para poder seguir obteniendo
      * los datos de la placa de red byte a byte */
+    netdev_read_end();
     return true;
 }
 
 uint16 udp_read_word()
 {
-    uint16 w = netdev_recv_word();
+    uint16 w = netdev_read_word();
     sum(w);
     return w;
 }
@@ -77,6 +80,7 @@ bool udp_checksum_ok()
 
 void udp_write_dgram_header()
 {
+    netdev_write_start(UDP_HEADER_SIZE);
     /* reseteamos checksum */
     checksum = 0;
     /* el UDP tiene un checksum que incluye parte de la cabecera IP */
@@ -91,24 +95,25 @@ void udp_write_dgram_header()
     /* tamaño del paquete UDP (IP sin las cabeceras, que son 20 bytes) */
     sum(ip_packet_len - 20); // FIXME
     /* puerto origen */
-    netdev_send_word(udp_port_local);
+    netdev_write_word(udp_port_local);
     sum(udp_port_local);
     /* puerto destino */
-    netdev_send_word(udp_port_remote);
+    netdev_write_word(udp_port_remote);
     sum(udp_port_remote);
     /* tamaño del datagrama */
-    netdev_send_byte(0x00); /* parte alta en 0 porque no soportamos más de 255 */
-    netdev_send_byte(udp_dgram_len);
+    netdev_write_byte(0x00); /* parte alta en 0 porque no soportamos más de 255 */
+    netdev_write_byte(udp_dgram_len);
     sum(WORD(0x00, udp_dgram_len));
     /* indicamos que no se usa checksum */
-    netdev_send_word(0x0000);
+    netdev_write_word(0x0000);
     sum(0x0000);
+    netdev_write_end();
 }
 
 void udp_write_word(uint16 w)
 {
     sum(w);
-    netdev_send_word(w);
+    netdev_write_word(w);
 }
 
 void udp_write_checksum()
index e9092f73039282939dade71589c2ab1d7c8176d6..d6367767f15af9dfc40db3a044298d0657aacfdf 100644 (file)
--- a/src/udp.h
+++ b/src/udp.h
@@ -52,6 +52,9 @@
  * </pre>
  */
 
+/** Tamaño de la cabecera UDP */
+#define UDP_HEADER_SIZE 8
+
 /** Puerto UDP nuestro */
 extern uint16 udp_port_local;