]> git.llucax.com Git - z.facultad/66.09/etherled.git/blobdiff - src/dp8390.c
Nueva manejo de buffers, un poco más modular. El proyecto quedó como un echo
[z.facultad/66.09/etherled.git] / src / dp8390.c
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);
 }