+++ /dev/null
-
-CC=sdcc
-LD=sdcc
-CFLAGS=-DDEBUG
-
-all: el.hex
-
-reg51.h: reg51sdcc.h
-
-netdev.h: types.h
-
-dp8390.h: types.h reg51.h netdev.h
-
-dp8390.rel: dp8390.c dp8390.h
- $(CC) $(CFLAGS) -c dp8390.c
-
-eth.rel: eth.c eth.h netdev.h types.h
- $(CC) $(CFLAGS) -c eth.c
-
-ip.rel: ip.c ip.h netdev.h types.h
- $(CC) $(CFLAGS) -c ip.c
-
-udp.rel: udp.c udp.h ip.h netdev.h types.h
- $(CC) $(CFLAGS) -c udp.c
-
-main.rel: main.c netdev.h eth.h ip.h udp.h
- $(CC) $(CFLAGS) -c main.c
-
-el.hex: main.rel dp8390.rel eth.rel ip.rel udp.rel
- $(LD) $(LDFLAGS) -o el.hex main.rel dp8390.rel eth.rel ip.rel udp.rel
-
-clean:
- @rm -vf el.hex *.rel *.asm *.lst *.map *.lnk *.mem *.sym
-
-.PHONY: clean
+++ /dev/null
-// vim: set et sw=4 sts=4 :
-
-#ifndef _CONFIG_H_
-#define _CONFIG_H_
-
-#define NET_RECV_CALLBACK eth_recv
-
-#define
-
-#endif // _CONFIG_H_
+++ /dev/null
-// vim: set et sw=4 sts=4 :
-
-#ifndef _DEBUG_H_
-#define _DEBUG_H_
-
-#ifdef DEBUG
-
-#include "types.h"
-#include "leds.h"
-
-#define sleep(t) \
- do \
- { \
- uint16 i; \
- byte j; \
- for (i = 0; i < 0xffff; ++i) \
- for (j = 0; j < t; ++j); \
- } \
- while (0)
-
-#define print(w) \
- do \
- { \
- leds(w); \
- sleep(8); \
- } \
- while (0)
-
-#define printb(bh, bl) \
- do \
- { \
- ledsb(bh, bl); \
- sleep(8); \
- } \
- while (0)
-
-#else // NO DEBUG
-
-#define sleep(t) ;
-#define print(w) ;
-#define printb(b1, b2) ;
-
-#endif // DEBUG
-
-#endif // _DEBUG_H_
+++ /dev/null
-// vim: set et sw=4 sts=4 :
-
-#include "debug.h"
-#include "eth.h"
-#include "dp8390.h"
-
-/** Tamaño del frame */
-byte netdev_len;
-
-// Próximo frame a obtener
-static struct
-{
- byte next_buf;
- byte curr_buf;
- byte curr_off;
-}
-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) \
- do \
- { \
- write_reg(CR, read_reg(CR) & ~(PS1 | PS0)); \
- write_reg(CR, read_reg(CR) | (page << 6)); \
- } \
- while (0)
-
-/// Aborta (o completa) el DMA limpiando el ISR
-#define ABORT_DMA(flags) \
- do \
- { \
- write_reg(CR, flags); \
- write_reg(ISR, RDC); \
- } \
- while (0)
-
-
-static void write_reg(unsigned char reg, unsigned char wr_data)
-{
- // Select register address.
- ADDR_PORT &= ~ADDR_PORT_MASK;
- ADDR_PORT |= reg;
-
- // Output register data to port.
- DATA_PORT = wr_data;
-
- // Clock register data into RTL8019AS.
- // IOR & IOW are both active low.
- NICE = 0;
- IOW = 0;
- IOW = 1;
- NICE = 1;
-
- // Set register data port as input again.
- DATA_PORT = DATA_PORT_MASK;
-}
-
-
-static unsigned char read_reg(unsigned char reg)
-{
- // Select register address.
- ADDR_PORT &= ~ADDR_PORT_MASK;
- ADDR_PORT |= reg;
-
- // Enable register data output from RTL8019AS.
- NICE = 0;
- IOR = 0;
-
- // Read register data from port.
- reg = DATA_PORT;
-
- // Disable register data output from RTL8019AS.
- IOR = 1;
- NICE = 1;
-
- return reg;
-}
-
-/** Resetea placa de red en caso de buffer overflow */
-static void reset()
-{
- bit retransmit = read_reg(CR) & TXP;
-
- // If the receive buffer ring has overflowed we dump the whole
- // thing and start over. There is no way of knowing whether the
- // data it contains is uncorrupted, or will cause us grief.
-
- // Stop RTL8019AS and abort DMA operation.
- write_reg(CR, STOP);
-
- // Wait for controller to halt after any current tx completes.
- while(!(read_reg(ISR) & RST)) continue;
-
- // Reset remote byte count registers.
- write_reg(RBCR0, 0x00);
- write_reg(RBCR1, 0x00);
-
- // Check whether currently transmitting a packet.
- if(retransmit)
- {
- // If neither a successful transmission nor a tx abort error
- // has occured, then flag current tx packet for resend.
- if(read_reg(ISR) & (PTX | TXE))
- {
- retransmit = 0;
- }
- }
-
- // Set transmit configuration register to loopback internally.
- write_reg(TCR, MODE1);
-
- // Restart the RTL8019AS.
- write_reg(CR, START);
-
- // Re-initialise last receive buffer read pointer.
- write_reg(BNRY, RX_PAGE_START);
-
- // Select RTL8019AS register page 1.
- SELECT_REG_PAGE(1);
-
- // Re-initialise current packet receive buffer page pointer.
- write_reg(CURR, RX_PAGE_START + 1);
-
- // Select RTL8019AS register page 0.
- SELECT_REG_PAGE(0);
-
- // Clear rx buffer overflow & packet received interrupt flags.
- write_reg(ISR, PRX | OVW);
-
- // Re-itialise transmit configuration reg for normal operation.
- write_reg(TCR, MODE0);
-
- if(retransmit)
- {
- // Retransmit packet in RTL8019AS local tx buffer.
- write_reg(CR, START | TXP);
- }
-}
-
-
-/** Inicializa dispositivo de red
- * @return true si se inicializó correctamente, false si no
- */
-bool netdev_init()
-{
- byte i;
-
- // Set IOR & IOW as they're active low.
- IOR = 1;
- IOW = 1;
- NICE = 1;
-
- // Set register data port as input.
- DATA_PORT = DATA_PORT_MASK;
-
- // Configure RTL8019AS ethernet controller.
-
- // Keil startup code takes 4ms to execute (18.432MHz, X1 mode).
- // That leaves plenty of time for the RTL8019AS to read it's
- // configuration in from the 9346 EEPROM before we get here.
-
- // Select RTL8019AS register page 0.
- SELECT_REG_PAGE(0);
-
- // Check if RTL8019AS fully reset.
- if(!(read_reg(ISR) & RST))
- {
- return 0;
- }
-
- // Stop RTL8019AS, select page 0 and abort DMA operation.
- write_reg(CR, STOP);
-
- // Initialise data configuration register.
- // FIFO threshold 8 bytes, no loopback, don't use auto send packet.
- write_reg(DCR, FT1 | LS);
-
- // Reset remote byte count registers.
- write_reg(RBCR0, 0u);
- write_reg(RBCR1, 0u);
-
- // Receive configuration register to monitor mode.
- write_reg(RCR, MON);
-
- // Initialise transmit configuration register to loopback internally.
- write_reg(TCR, MODE1);
-
- // Clear interrupt status register bits by writing 1 to each.
- write_reg(ISR, ALL);
-
- // Mask all interrupts in mask register.
- write_reg(IMR, NONE);
-
- // Obtengo MAC de la placa
- write_reg(RBCR0, 12u); // Vamos a leer 12 bytes (2 x 6)
- write_reg(RBCR1, 0u);
- write_reg(RSAR0, 0u); // En la dirección 0x0000
- write_reg(RSAR1, 0u);
- write_reg(CR, READ); // Comienza lectura
- for (i = 0; i < ETH_ADDR_SIZE; ++i)
- {
- eth_addr_local[i] = read_reg(RDMA);
- read_reg(RDMA); // Ignoramos porque viene como un word
- }
-
- // Abort/ complete DMA operation.
- ABORT_DMA(STOP);
-
- // Set transmit page start.
- write_reg(TPSR, TX_PAGE_START);
-
- // Set receive buffer page start.
- write_reg(PSTART, RX_PAGE_START);
-
- // Initialise last receive buffer read pointer.
- write_reg(BNRY, RX_PAGE_START);
-
- // Set receive buffer page stop.
- write_reg(PSTOP, RX_PAGE_STOP);
-
- // Select RTL8019AS register page 1.
- SELECT_REG_PAGE(1);
-
- // Initialise current packet receive buffer page pointer
- write_reg(CURR, RX_PAGE_START + 1);
-
- // Set physical address
- for (i = 0; i < ETH_ADDR_SIZE; ++i)
- write_reg(PAR_BASE + i, eth_addr_local[i]);
-
- // Restart RTL8019AS.
- write_reg(CR, START);
-
- // Initialise transmit configuration register for normal operation.
- write_reg(TCR, MODE0);
-
- // Receive configuration register to accept broadcast packets.
- write_reg(RCR, AB);
-
- return 1;
-}
-
-
-/** 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);
-}
-
-/** 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);
-}
-
-void netdev_write_start(byte len)
-{
- // 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.
- 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.
- write_reg(CR, WRITE);
-}
-
-/** Escribe un byte al buffer de la placa de red para ser enviado
- * @precond netdev_send_start() debe haber sido ejecutada
- * @param b Byte a enviar
- */
-void netdev_write_byte(byte b)
-{
- write_reg(RDMA, b);
-}
-
-/** Escribe un word al buffer de la placa de red para ser enviado
- * @precond netdev_send_start() debe haber sido ejecutada
- * @param w Word a enviar
- */
-void netdev_write_word(uint16 w)
-{
- write_reg(RDMA, HIGH(w));
- write_reg(RDMA, LOW(w));
-}
-
-void netdev_write_end()
-{
- // Abort/ complete DMA operation.
- ABORT_DMA(START);
-}
-
-/** Comienza la lectura de un nuevo frame
- * @return Cantidad de bytes a recibir
- */
-byte netdev_recv_start()
-{
- // Check if the rx buffer has overflowed.
- if (read_reg(ISR) & OVW)
- {
- byte current;
-
- SELECT_REG_PAGE(1);
- current = read_reg(CURR);
- 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(read_reg(BNRY), 0x02);
- printb(current, 0x04);
- printb(0x00, 0x00);
- reset();
- }
- return 0;
- }
- // Check if there is a packet in the rx buffer.
- else if (read_reg(ISR) & PRX)
- {
- byte status;
- byte len;
- byte current;
-
- // Retrieve packet header. (status, next_ptr, length_l, length_h)
-
- // 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);
-
- // Retrieve current receive buffer page
- current = read_reg(CURR);
-
- // Select RTL8019AS register page 1.
- SELECT_REG_PAGE(0);
-
- // Check if last packet has been removed from rx buffer.
- if(recv_state.curr_buf == current)
- {
- // Clear packet received interrupt flag.
- write_reg(ISR, PRX | RXE);
- return 0;
- }
-
- // Set remote DMA byte count registers to packet header length.
- recv_state.curr_off = 0;
- netdev_read_start(BUF_HDR_SIZE);
-
- // Packet status.
- status = netdev_read_byte();
-
- // Save next packet pointer.
- recv_state.next_buf = netdev_read_byte() - 1;
-
- // Retrieve packet data length and subtract CRC bytes.
- len = netdev_read_byte() - BUF_HDR_SIZE;
-
- // Si es muy grande, muy chico o hubo error, lo descartamos
- 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
- netdev_read_end();
- write_reg(BNRY, recv_state.next_buf);
- return 0;
- }
-
- // Abort/ complete DMA operation.
- netdev_read_end();
-
- return len;
- }
-
- return 0;
-}
-
-/** 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);
-}
-
-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_read_byte()
-{
- return read_reg(RDMA);
-}
-
-/** Lee un word del buffer de la placa de red
- * @precond netdev_recv_start() debe haber sido ejecutada
- */
-uint16 netdev_read_word()
-{
- 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_read_end()
-{
- // Completa DMA
- ABORT_DMA(START);
-}
-
+++ /dev/null
-// vim: set et sw=4 sts=4 :
-
-#ifndef _DP8390_H_
-#define _DP8390_H_
-
-#include "reg51.h"
-#include "types.h"
-#include "netdev.h"
-
-// Configuración de puertos para comunicarse con la placa de red
-#define DATA_PORT P2 // Adjust this to suit hardware.
-#define DATA_PORT_MASK 0xFF // Máscara para leer del puerto
-#define ADDR_PORT P1 // Adjust this to suit hardware.
-#define ADDR_PORT_MASK 0x1F // Máscara de direcciones (para no cambiar
- // bits que no se usan)
-#ifdef SDCC
-sbit at 0xB4 IOW; // ISA slot pin B13, RTL8019AS pin 30, active low
-sbit at 0xB5 IOR; // ISA slot pin B14, RTL8019AS pin 29, active low
-sbit at 0xB2 NICE; // A7, usado para activar placa de red
-#else
-#define CTRL_PORT P3 // Adjust this to suit hardware.
-sbit IOW = CTRL_PORT^4; // ISA slot pin B13, RTL8019AS pin 30, active low
-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
-
-// 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 0x41 // 0x4600 Rx buffer: 31 * 256 = 7936 bytes
-#define RX_PAGE_STOP 0x60 // 0x6000
-
-// Register base address
-#define REG_BASE 0x0000 // Hardwired to 0x0300
-
-// Registers common to all pages.
-#define CR REG_BASE + 0x00 // Control register
- // Control register bits
- #define PS1 0x80 // Page select bit 1
- #define PS0 0x40 // Page select bit 0
- #define RD2 0x20 // Remote DMA control bit 2
- #define RD1 0x10 // Remote DMA control bit 1
- #define RD0 0x08 // Remote DMA control bit 0
- #define TXP 0x04 // Transmit packet bit
- #define STA 0x02 // Start bit (a flag only)
- #define STP 0x01 // Stop bit transceiver ctrl
- // Shortcuts
- #define PAGE0 0x00 // Page 0
- #define PAGE1 PS0 // Page 1
- #define PAGE2 PS1 // Page 2
- #define PAGE3 (PS0 | PS1) // Page 3 (Reserved!)
- #define ABORT RD2 // Abort/Complete DMA
- #define READ (RD0 | STA) // Remote Read
- #define WRITE (RD1 | STA) // Remote Write
- #define SENDPKT (RD0 | RD1 | STA) // Send Packet
- #define STOP (ABORT | STP) // Para la placa de red
- #define START (ABORT | STA) // Inicia la placa de red
-
-#define RDMA 0x10 // Remote DMA port
-#define RESET 0x18 // Reset port
-
-// Page 0 read/write registers.
-#define BNRY REG_BASE + 0x03 // Boundary register
-#define ISR REG_BASE + 0x07 // Interrupt status register
- // Interrupt status register bits
- #define RST 0x80 // Reset state indicator bit
- #define RDC 0x40 // Remote DMA complete bit
- #define CNT 0x20 // Network tally counter MSB set
- #define OVW 0x10 // Receive buffer exhausted
- #define TXE 0x08 // Transmit abort error bit
- #define RXE 0x04 // Receive error report bit
- #define PTX 0x02 // Successful packet transmit
- #define PRX 0x01 // Successful packet receive
- // Shortcuts
- #define ALL 0xFF // Todos los bits
- #define NONE 0x00 // Ninguno
-
-// Page 0 read only registers.
-#define CLDA0 REG_BASE + 0x01
-#define CLDA1 REG_BASE + 0x02
-#define TSR REG_BASE + 0x04
-#define NCR REG_BASE + 0x05
-#define FIFO REG_BASE + 0x06
-#define CRDA0 REG_BASE + 0x08
-#define CRDA1 REG_BASE + 0x09
-#define CONFIGA REG_BASE + 0x0A
-#define CONFIGB REG_BASE + 0x0B
-#define RSR REG_BASE + 0x0C
-#define CNTR0 REG_BASE + 0x0D
-#define CNTR1 REG_BASE + 0x0E
-#define CNTR2 REG_BASE + 0x0F
-
-// Page 0 write only registers.
-#define PSTART REG_BASE + 0x01 // Receive page start register
-#define PSTOP REG_BASE + 0x02 // Receive page stop register
-#define TPSR REG_BASE + 0x04 // Transmit page start register
-#define TBCR0 REG_BASE + 0x05 // Transmit byte count register 0
-#define TBCR1 REG_BASE + 0x06 // Transmit byte count register 1
-#define RSAR0 REG_BASE + 0x08 // Remote start address register 0
-#define RSAR1 REG_BASE + 0x09 // Remote start address register 0
-#define RBCR0 REG_BASE + 0x0A // Remote byte count register 0
-#define RBCR1 REG_BASE + 0x0B // Remote byte count register 1
-#define RCR REG_BASE + 0x0C // Receive configuration register
- // Receive configuration register bits (write in page 0, read in page 2)
- #define MON 0x20 // Monitor mode select bit
- #define PRO 0x10 // Promiscuous mode select bit
- #define AM 0x08 // Multicast packet accept bit
- #define AB 0x04 // Broadcast packet accept bit
- #define AR 0x02 // Runt packet accept bit
- #define SEP 0x01 // Error packet accept bit
-#define TCR REG_BASE + 0x0D // Transmit configuration register
- // Transmit configuration register bits
- #define OFST 0x10 // Collision offset enable bit
- #define ATD 0x08 // Auto transmit disable select bit
- #define LB1 0x04 // Loopback mode select bit 1
- #define LB0 0x02 // Loopback mode select bit 0
- #define CRC 0x01 // CRC generation inhibit bit
- // Shortcuts
- #define MODE0 0x00 // Loopback mode 0
- #define MODE1 LB0 // Loopback mode 1
- #define MODE2 LB1 // Loopback mode 2
- #define MODE3 (LB0 | LB1) // Loopback mode 3
-#define DCR REG_BASE + 0x0E // Data configuration register
- // Data configuration register bits (write in page 0, read in page 2)
- #define FT1 0x40 // FIFO threshold select bit 1
- #define FT0 0x20 // FIFO threshold select bit 0
- #define ARM 0x10 // Auto-initialise remote
- #define LS 0x08 // Loopback select bit
- #define LAS 0x04 // Set to 0 (pwrup = 1)
- #define BOS 0x02 // Byte order select bit
- #define WTS 0x01 // Word transfer select bit
-#define IMR REG_BASE + 0x0F // Interrupt mask register
- // Interrupt mask register bits
- // Each enable bit correspons with an interrupt flag in ISR
-
-// Page 1 read/write registers.
-#define PAR_BASE REG_BASE + 0x01 // Physical address register base address
-#define PAR0 REG_BASE + 0x01 // Physical address register 0
-#define PAR1 REG_BASE + 0x02 // Physical address register 1
-#define PAR2 REG_BASE + 0x03 // Physical address register 2
-#define PAR3 REG_BASE + 0x04 // Physical address register 3
-#define PAR4 REG_BASE + 0x05 // Physical address register 4
-#define PAR5 REG_BASE + 0x06 // Physical address register 5
-#define CURR REG_BASE + 0x07 // Current receive buffer page
-#define MAR0 REG_BASE + 0x08
-#define MAR1 REG_BASE + 0x09
-#define MAR2 REG_BASE + 0x0A
-#define MAR3 REG_BASE + 0x0B
-#define MAR4 REG_BASE + 0x0C
-#define MAR5 REG_BASE + 0x0D
-#define MAR6 REG_BASE + 0x0E
-#define MAR7 REG_BASE + 0x0F
-
-// Page 2 read only registers.
-// Each previously defined in page 0 write only.
-//#define PSTART REG_BASE + 0x01
-//#define PSTOP REG_BASE + 0x02
-//#define TPSR REG_BASE + 0x04
-//#define RCR REG_BASE + 0x0C
-//#define TCR REG_BASE + 0x0D
-//#define DCR REG_BASE + 0x0E
-//#define IMR REG_BASE + 0x0F
-
-// Page 3 read/write registers.
-#define _9346CR REG_BASE + 0x01 // 9346 EEPROM command register
- // 9346 EEPROM command register bits
- #define EEM1 0x80 // RTL8019AS operating mode bit 1
- #define EEM0 0x40 // RTL8019AS operating mode bit 0
- #define EECS 0x08 // 9346 EEPROM chip select bit
- #define EESK 0x04 // 9346 EEPROM serial clock bit
- #define EEDI 0x02 // 9346 EEPROM data input bit
- #define EEDO 0x01 // 9346 EEPROM data output bit
-#define BPAGE REG_BASE + 0x02
-#define CONFIG1 REG_BASE + 0x04 // RTL9019AS config register 1
- // RTL9019AS config register 1 bits
- #define IRQEN 0x80 // IRQ enable bit (WR protected)
- #define IRQS2 0x40 // IRQ line select bit 2
- #define IRQS1 0x20 // IRQ line select bit 1
- #define IRQS0 0x10 // IRQ line select bit 0
- #define IOS3 0x08 // I/O base address select bit 3
- #define IOS2 0x04 // I/O base address select bit 2
- #define IOS1 0x02 // I/O base address select bit 1
- #define IOS0 0x01 // I/O base address select bit 0
-#define CONFIG2 REG_BASE + 0x05 //
- // RTL9019AS config register 2 bits
- #define PL1 0x80 // Network medium type select bit 1
- #define PL0 0x40 // Network medium type select bit 0
- #define BSELB 0x20 // Boot ROM disable (WR protected)
- #define BS4 0x10 // Boot ROM configuration bit 4
- #define BS3 0x08 // Boot ROM configuration bit 3
- #define BS2 0x04 // Boot ROM configuration bit 2
- #define BS1 0x02 // Boot ROM configuration bit 1
- #define BS0 0x01 // Boot ROM configuration bit 0
-#define CONFIG3 REG_BASE + 0x06 // RTL9019AS config register 3
- // RTL9019AS config register 3 bits
- #define PNP 0x80 // Plug & play mode indicator bit
- #define FUDUP 0x40 // Full duplex mode select bit
- #define LEDS1 0x20 // LED output select bit 1
- #define LEDS0 0x10 // LED output select bit 0
- #define SLEEP 0x04 // Sleep mode select bit
- #define PWRDN 0x02 // Power down mode select bit
- #define ACTIVEB 0x01 // Inverse of bit 0, PNP active reg
-
-// Page 3 read only registers.
-#define CONFIG0 REG_BASE + 0x03 // RTL9019AS config register 0
- // RTL9019AS config register 0 bits
- #define VERID1 0x80 // RTL9019AS version ID bit 1 (R/W)
- #define VERID0 0x40 // RTL9019AS version ID bit 0 (R/W)
- #define AUI 0x20 // AUI input pin state bit
- #define PNPJP 0x10 // PNP jumper pin state bit
- #define JP 0x08 // JP input pin state bit
- #define BNC 0x04 // Thinnet mode indication bit
-#define CSNSAV REG_BASE + 0x08
-#define INTR REG_BASE + 0x0B
-#define CONFIG4 REG_BASE + 0x0D
-
-// Page 3 write only registers.
-#define TEST REG_BASE + 0x07
-#define HLTCLK REG_BASE + 0x09
-#define FMWP REG_BASE + 0x0C
-
-
-// Bits del byte de status del frame recibido
-#define RXSOK 0x01 /* Received a good packet */
-#define RXSCRC 0x02 /* CRC error */
-#define RXSFAE 0x04 /* frame alignment error */
-#define RXSFO 0x08 /* FIFO overrun */
-#define RXSMPA 0x10 /* missed pkt */
-#define RXSPHY 0x20 /* physical/multicast address */
-#define RXSDIS 0x40 /* receiver disable. set in monitor mode */
-#define RXSDEF 0x80 /* deferring */
-
-#endif
+++ /dev/null
-// vim: set et sw=4 sts=4 :
-
-#include "debug.h"
-#include "netdev.h"
-#include "eth.h"
-
-/** tipos de paquetes transportados soportados */
-enum { IP = 0x0800, ARP = 0x0806 };
-
-byte eth_addr_local[ETH_ADDR_SIZE];
-
-byte eth_addr_remote[ETH_ADDR_SIZE];
-
-eth_proto_t eth_proto;
-
-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_read_byte();
- /* obtenemos MAC de origen */
- for (i = 0; i < ETH_ADDR_SIZE; ++i)
- eth_addr_remote[i] = netdev_read_byte();
- /* obtenemos tipo de protocolo transportado por el frame, (sólo
- * aceptamos IP y ARP) */
- switch (netdev_read_word())
- {
- case IP:
- eth_proto = ETH_IP;
- break;
- case ARP:
- eth_proto = ETH_ARP;
- break;
- default:
- netdev_read_end();
- return false; /* drop */
- }
- netdev_read_end();
- return true;
-}
-
-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_write_byte(eth_addr_remote[i]);
- /* y como fuente la nuestra */
- for (i = 0; i < ETH_ADDR_SIZE; ++i)
- netdev_write_byte(eth_addr_local[i]);
- /* escribimos el tipo de paquete que transporta el frame */
- netdev_write_word((eth_proto == ETH_IP) ? IP : ARP);
- netdev_write_end();
-}
-
+++ /dev/null
-// vim: set et sw=4 sts=4 :
-
-#ifndef _ETH_H_
-#define _ETH_H_
-
-#include "types.h"
-
-/** @file
- * Estructura de un frame ethernet.
- *
- * <pre>
- * /--- 8 ----/--- 6 ----/--- 6 ----/- 2 --/- 46-1500 -/- 4 -/ bytes
- * +----------+----------+----------+------+-----------+-----+
- * | preamble | dst addr | src addr | type | data | crc |
- * +----------+----------+----------+------+-----------+-----+
- * </pre>
- *
- * type es 0x0800 para IP y 0x0806 para ARP, los únicos dos protocolos que
- * soportamos sobre ethernet.
- * El preamble y el crc los pone la placa de red automáticamente.
- */
-
-/** 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;
-
-/** Dirección MAC nuestra */
-extern byte eth_addr_local[ETH_ADDR_SIZE];
-
-/** Dirección MAC de destino */
-extern byte eth_addr_remote[ETH_ADDR_SIZE];
-
-/** Indica que protocolo está transportando el frame */
-extern eth_proto_t eth_proto;
-
-/**
- * Lee la cabecera del frame ethernet.
- *
- * Deja en mac_addr_remote la MAC de origen y eth_frame_arp en 1 si es ARP.
- * Si devuelve false (0) hay un error o es un frame no soportado, por lo que
- * hay que descartarlo.
- */
-bool eth_read_frame_header();
-
-/**
- * Escribe la cabecera del frame ethernet.
- *
- * Pone como destino a mac_addr_remote, como origen a mac_addr_local y como
- * tipo ARP si eth_frame_arp está en 1 (si no el tipo es IP).
- */
-void eth_write_frame_header();
-
-#endif /* _ETH_H_ */
+++ /dev/null
-### uVision2 Project, (C) Keil Software\r
-### Do not modify !\r
-\r
-Target (etherled), 0x0000 // Tools: 'MCS-51'\r
-\r
-Group (net)\r
-Group (common)\r
-\r
-File 1,5,<.\netdev.h><netdev.h> 0x0 \r
-File 1,5,<.\dp8390.h><dp8390.h> 0x0 \r
-File 1,1,<.\dp8390.c><dp8390.c> 0x0 \r
-File 1,5,<.\eth.h><eth.h> 0x0 \r
-File 1,1,<.\eth.c><eth.c> 0x0 \r
-File 1,5,<.\ip.h><ip.h> 0x0 \r
-File 1,1,<.\ip.c><ip.c> 0x0 \r
-File 1,5,<.\udp.h><udp.h> 0x0 \r
-File 1,1,<.\udp.c><udp.c> 0x0 \r
-File 2,1,<.\main.c><main.c> 0x0 \r
-File 2,5,<.\reg51.h><reg51.h> 0x0 \r
-File 2,2,<.\startup.a51><startup.a51> 0x0 \r
-File 2,5,<.\types.h><types.h> 0x0 \r
-File 2,5,<.\reg51keil.h><reg51keil.h> 0x0 \r
-\r
-\r
-Options 1,0,0 // Target 'etherled'\r
- Device (AT89S8252)\r
- Vendor (Atmel)\r
- Cpu (IRAM(0-0xFF) IROM(0-0x1FFF) CLOCK(24000000) MODA2)\r
- FlashUt ()\r
- StupF ("LIB\STARTUP.A51" ("Standard 8051 Startup Code"))\r
- FlashDR ()\r
- DevID ()\r
- Rgf (REG8252.H)\r
- Mem ()\r
- C ()\r
- A ()\r
- RL ()\r
- OH ()\r
- DBC_IFX ()\r
- DBC_CMS ()\r
- DBC_AMS ()\r
- DBC_LMS ()\r
- UseEnv=0\r
- EnvBin ()\r
- EnvInc ()\r
- EnvLib ()\r
- EnvReg (ÿAtmel\)\r
- OrgReg (ÿAtmel\)\r
- TgStat=27\r
- OutDir (.\)\r
- OutName (etherled)\r
- GenApp=1\r
- GenLib=0\r
- GenHex=1\r
- Debug=1\r
- Browse=1\r
- LstDir (.\)\r
- HexSel=0\r
- MG32K=0\r
- TGMORE=0\r
- RunUsr 0 0 <>\r
- RunUsr 1 0 <>\r
- BrunUsr 0 0 <>\r
- BrunUsr 1 0 <>\r
- SVCSID <>\r
- MODEL5=0\r
- RTOS5=0\r
- ROMSZ5=2\r
- DHOLD5=0\r
- XHOLD5=0\r
- T51FL=208\r
- XT51FL=0\r
- CBANKS5=0\r
- XBANKS5=0\r
- RCB51 { 0,0,0,0,0,255,255,0,0 }\r
- RXB51 { 0,0,0,0,0,0,0,0,0 }\r
- OCM51 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }\r
- OCR51 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }\r
- IRO51 { 1,0,0,0,0,0,32,0,0 }\r
- IRA51 { 0,0,0,0,0,0,1,0,0 }\r
- XRA51 { 0,0,0,0,0,0,0,0,0 }\r
- XRA512 { 0,0,0,0,0,0,0,0,0 }\r
- IROM512 { 0,0,0,0,0,0,0,0,0 }\r
- C51FL=21630224\r
- C51VA=0\r
- C51MSC ()\r
- C51DEF ()\r
- C51UDF ()\r
- INCC5 ()\r
- AX51FL=4\r
- AX51MSC ()\r
- AX51SET ()\r
- AX51RST ()\r
- INCA5 ()\r
- PropFld { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }\r
- IncBld=1\r
- AlwaysBuild=0\r
- GenAsm=0\r
- AsmAsm=0\r
- PublicsOnly=0\r
- StopCode=3\r
- CustArgs ()\r
- LibMods ()\r
- BankNo=65535\r
- LX51FL=292\r
- LX51OVL ()\r
- LX51MSC ()\r
- LX51DWN ()\r
- LX51LFI ()\r
- LX51ASN ()\r
- LX51RES ()\r
- LX51CCL ()\r
- LX51UCL ()\r
- LX51CSC ()\r
- LX51UCS ()\r
- LX51COB ()\r
- LX51XDB ()\r
- LX51PDB ()\r
- LX51BIB ()\r
- LX51DAB ()\r
- LX51IDB ()\r
- LX51PRC ()\r
- LX51STK ()\r
- LX51COS ()\r
- LX51XDS ()\r
- LX51BIS ()\r
- LX51DAS ()\r
- LX51IDS ()\r
- OPTDL (S8051.DLL)()(DP51.DLL)(-p8252)(S8051.DLL)()(TP51.DLL)(-p8252)\r
- OPTDBG 48125,0,()()()()()()()()()() ()()()()\r
- FLASH1 { 0,0,0,0,0,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0 }\r
- FLASH2 ()\r
- FLASH3 ()\r
- FLASH4 ()\r
-EndOpt\r
-\r
+++ /dev/null
-// vim: set et sw=4 sts=4 :
-
-#include "netdev.h"
-#include "debug.h"
-#include "ip.h"
-
-/** protocolos soportados */
-enum { ICMP = 0x01, UDP = 0x11 };
-
-byte ip_addr_local[IP_ADDR_SIZE];
-
-byte ip_addr_remote[IP_ADDR_SIZE];
-
-byte ip_packet_len;
-
-ip_proto_t ip_proto;
-
-/* para calcular checksum */
-static uint16 checksum;
-
-/* agrega un word al checksum calculado */
-static void sum(uint16 w)
-{
- checksum += w;
- if (checksum < w) /* corrección de carry (hubo OV) */
- ++checksum;
-}
-
-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_read_byte();
- /* sólo soportamos versión 4 */
- if ((h >> 4) != 4)
- ok = false;
- /* tamaño de cabecera */
- if ((h & 0x0F) != 5) /* no aceptamos opciones raras =) */
- ok = false;
- /* ignoramos el TOS y vamos calculando checksum */
- sum(WORD(h, netdev_read_byte()));
- /* obtenemos tamaño del paquete */
- 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_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_read_byte();
- l = netdev_read_byte();
- if ((h & 0x3F) || l)
- 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_read_byte();
- /* protocolo (sólo soportamos UDP e ICMP) */
- l = netdev_read_byte();
- switch (l)
- {
- case ICMP:
- ip_proto = IP_ICMP;
- break;
- case UDP:
- ip_proto = IP_UDP;
- break;
- default:
- ok = false;
- }
- /* sigo calculando checksum */
- sum(WORD(h, l));
- /* obtenemos checksum y seguimos el cálculo */
- 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_read_byte();
- if (l % 2)
- sum(WORD(h, ip_addr_remote[l]));
- else
- h = ip_addr_remote[l];
- }
- /* vemos si el paquete es para nosotros (ningún soportar broadcast =)
- * (mientras seguimos calculando el checksum) */
- // TODO si soportamos DHCP hay que aceptar broadcasts!
- for (l = 0; l < IP_ADDR_SIZE; ++l)
- {
- if (ip_addr_local[l] != netdev_read_byte())
- ok = false;
- if (l % 2)
- sum(WORD(h, ip_addr_local[l]));
- else
- h = ip_addr_local[l];
- }
- /* verificamos checksum */
- if ((uint16)~checksum)
- ok = false;
- netdev_read_end();
- return ok;
-}
-
-void ip_write_packet_header()
-{
- /* variables utilitarias (iterar y/o buffer) */
- byte h, l;
- /* identificador del paquete IP (incrementa con cada paquete) */
- 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_write_byte(h = 0x45);
- /* TOS (0xc0 = Internetwork Control, 0x00 = normal) */
- l = (ip_proto == IP_ICMP) ? 0xc0 : 0x00;
- netdev_write_byte(l);
- sum(WORD(h, l)); /* actualizamos checksum */
- /* escribimos tamaño del paquete */
- 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_write_word(++id);
- sum(id); /* actualizamos checksum */
- /* pedimos que no se fragmente */
- 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_write_byte(h = 0x40);
- /* protocolo (sólo soportamos UDP e ICMP) */
- l = (ip_proto == IP_ICMP) ? ICMP : UDP;
- 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
- * hacemos */
- for (l = 0; l < IP_ADDR_SIZE; ++l) /* origen = local */
- if (l % 2)
- sum(WORD(h, ip_addr_local[l]));
- else
- h = ip_addr_local[l];
- for (l = 0; l < IP_ADDR_SIZE; ++l) /* destino = remota */
- if (l % 2)
- sum(WORD(h, ip_addr_remote[l]));
- else
- h = ip_addr_remote[l];
- /* ahora sí grabamos el 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_write_byte(ip_addr_local[l]);
- /* IP de destino, la remota */
- for (l = 0; l < IP_ADDR_SIZE; ++l)
- netdev_write_byte(ip_addr_remote[l]);
- netdev_write_end();
-}
-
+++ /dev/null
-// vim: set et sw=4 sts=4 :
-
-#ifndef _IP_H_
-#define _IP_H_
-
-#include "types.h"
-
-/** @file
- * Paquete IP.
- *
- * 0 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * |Version| IHL |Type of Service| Total Length |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Identification |Flags| Fragment Offset |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Time to Live | Protocol | Header Checksum |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Source Address |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Destination Address |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Options | Padding |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Data |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *
- * Nosotros sólo implementamos la versión 4, sin opciones, con tamaño de paquete
- * como máximo de 255 bytes, sin fragmentación y sólo los protocolos UDP e ICMP
- * (este último sólo para responder al ping). Todos los paquetes que no cumplan
- * con estas restricciones son descartados.
- */
-
-/** 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;
-
-/** Dirección IP nuestra */
-extern byte ip_addr_local[IP_ADDR_SIZE];
-
-/** Dirección IP de destino */
-extern byte ip_addr_remote[IP_ADDR_SIZE];
-
-/** Tamaño del paquete IP */
-extern byte ip_packet_len;
-
-/** Indica si el paquete es ICMP (si no es UDP) */
-extern ip_proto_t ip_proto;
-
-/** Lee la cabecera del paquete IP.
- *
- * Deja en ip_addr_remote la ip de origen.
- * Si devuelve false (0) es que hubo un error o es un paquete no soportado, por
- * lo que hay que descartarlo.
- */
-bool ip_read_packet_header();
-
-/** Escribe la cabecera del paquete IP.
- *
- * Pone como destino a ip_addr_remote, como origen a ip_addr_local, el protocolo
- * lo especifica según ip_proto_icmp y como tamaño pone ip_packet_len.
- */
-void ip_write_packet_header();
-
-#endif /* _IP_H_ */
+++ /dev/null
-// vim: set et sw=4 sts=4 :
-
-#ifndef _LEDS_H_
-#define _LEDS_H_
-
-#include "types.h"
-
-#ifdef SDCC
-static xdata at 0x0080 byte leds0;
-static xdata at 0x00c0 byte leds1;
-#else
-static byte xdata leds0 _at_ 0x0080;
-static byte xdata leds1 _at_ 0x00c0;
-#endif
-
-#define leds(word) \
- do \
- { \
- uint16 w = word; \
- leds0 = ~LOW(w); \
- leds1 = ~HIGH(w); \
- } \
- while (0)
-
-#define ledsb(bh, bl) \
- do \
- { \
- leds0 = ~(bl); \
- leds1 = ~(bh); \
- } \
- while (0)
-
-#endif // _LEDS_H_
+++ /dev/null
-// vim: set et sw=4 sts=4 :
-
-#include "debug.h"
-#include "leds.h"
-#include "netdev.h"
-#include "eth.h"
-#include "ip.h"
-#include "udp.h"
-
-void main(void)
-{
- // Apagamos todos los leds
- leds(0);
-
- // Inicializamos dispositivo de red
- if (!netdev_init())
- {
- leds(0xFFFF);
- while(1); // Si falla init nos quedamos bobos
- }
-
- // Inicializo IP
- ip_addr_local[0] = 10;
- ip_addr_local[1] = 10;
- ip_addr_local[2] = 10;
- ip_addr_local[3] = 100;
-
- // Inicializo puerto UDP
- udp_port_local = 9876;
-
- while (1) // Forever
- {
- byte buf[64]; //XXX
- byte i; //XXX
- byte len;
-
- len = netdev_recv_start();
- if (!len) // no recibimos nada (válido)
- continue; // Probamos de nuevo
-
- // Tenemos algo!
- //print(0x2);
-
- // Parseamos cabecera ethernet
- if (!eth_read_frame_header()) // No es un buen header
- goto drop; // Tiramos el paquete
- //print(0x4);
-
- // Vemos que protocolo transporta
- switch (eth_proto)
- {
- case ETH_ARP: // TODO: implementar ARP!
- goto drop; // Tiramos el paquete
-
- case ETH_IP:
- //print(0x8);
- // Parseamos cabecera IP
- if (!ip_read_packet_header()) // No es un buen header
- goto drop; // Tiramos el paquete
- //print(0x10);
-
- // Vemos que protocolo transporta
- switch (ip_proto)
- {
- case IP_ICMP: // TODO: implementar ICMP!
- goto drop; // Tiramos el paquete
-
- case IP_UDP:
- //print(0x20);
- // Parseamos cabecera UDP
- if (!udp_read_dgram_header()) // No es un buen header
- goto drop; // Tiramos el paquete
-
- //printb(udp_dgram_len, 0x40);
- // TODO
- // Nuestro protocolo, por ahora un simple echo!
- 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(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);
- }
- }
- continue;
-drop:
- netdev_recv_end();
- }
-}
-
+++ /dev/null
-// vim: set et sw=4 sts=4 :
-
-#ifndef _NETDEV_H_
-#define _NETDEV_H_
-
-#include "types.h"
-
-/** Tamaño del frame */
-extern byte netdev_len;
-
-/** Inicializa dispositivo de red
- * @return true si se inicializó correctamente, false si no
- */
-bool netdev_init();
-
-/** Comienza el envío de un nuevo frame */
-void netdev_send_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);
-
-/** 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
- */
-void netdev_write_byte(byte b);
-
-/** Escribe un word al buffer de la placa de red para ser enviado
- * @precond netdev_write_start() debe haber sido ejecutada
- * @param w Word a enviar
- */
-void netdev_write_word(uint16 w);
-
-/** 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_write_end();
-
-/** Comienza la recepción de un nuevo frame
- * @return Cantidad de bytes a recibir
- */
-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_read_byte();
-
-/** Lee un word del buffer de la placa de red
- * @precond netdev_recv_start() debe haber sido ejecutada
- */
-uint16 netdev_read_word();
-
-/** Finaliza la lectura del frame
- * @precond netdev_recv_start() debe haber sido ejecutada
- */
-void netdev_read_end();
-
-#endif // _NETDEV_H_
+++ /dev/null
-#ifndef _REG51_H_
-#define _REG51_H_
-
-#ifdef SDCC
-# include "reg51sdcc.h"
-#else
-# include "reg51keil.h"
-#endif
-
-#endif /* _REG51_H_ */
+++ /dev/null
-#ifndef _REG51KEIL_H_
-#define _REG51KEIL_H_
-
-/* BYTE Register */
-sfr P0 = 0x80;
-sfr P1 = 0x90;
-sfr P2 = 0xA0;
-sfr P3 = 0xB0;
-sfr PSW = 0xD0;
-sfr ACC = 0xE0;
-sfr B = 0xF0;
-sfr SP = 0x81;
-sfr DPL = 0x82;
-sfr DPH = 0x83;
-sfr PCON = 0x87;
-sfr TCON = 0x88;
-sfr TMOD = 0x89;
-sfr TL0 = 0x8A;
-sfr TL1 = 0x8B;
-sfr TH0 = 0x8C;
-sfr TH1 = 0x8D;
-sfr IE = 0xA8;
-sfr IP = 0xB8;
-sfr SCON = 0x98;
-sfr SBUF = 0x99;
-
-/* BIT Register */
-/* PSW */
-sbit CY = 0xD7;
-sbit AC = 0xD6;
-sbit F0 = 0xD5;
-sbit RS1 = 0xD4;
-sbit RS0 = 0xD3;
-sbit OV = 0xD2;
-sbit P = 0xD0;
-
-/* TCON */
-sbit TF1 = 0x8F;
-sbit TR1 = 0x8E;
-sbit TF0 = 0x8D;
-sbit TR0 = 0x8C;
-sbit IE1 = 0x8B;
-sbit IT1 = 0x8A;
-sbit IE0 = 0x89;
-sbit IT0 = 0x88;
-
-/* IE */
-sbit EA = 0xAF;
-sbit ES = 0xAC;
-sbit ET1 = 0xAB;
-sbit EX1 = 0xAA;
-sbit ET0 = 0xA9;
-sbit EX0 = 0xA8;
-
-/* IP */
-sbit PS = 0xBC;
-sbit PT1 = 0xBB;
-sbit PX1 = 0xBA;
-sbit PT0 = 0xB9;
-sbit PX0 = 0xB8;
-
-/* P3 */
-sbit RD = 0xB7;
-sbit WR = 0xB6;
-sbit T1 = 0xB5;
-sbit T0 = 0xB4;
-sbit INT1 = 0xB3;
-sbit INT0 = 0xB2;
-sbit TXD = 0xB1;
-sbit RXD = 0xB0;
-
-/* SCON */
-sbit SM0 = 0x9F;
-sbit SM1 = 0x9E;
-sbit SM2 = 0x9D;
-sbit REN = 0x9C;
-sbit TB8 = 0x9B;
-sbit RB8 = 0x9A;
-sbit TI = 0x99;
-sbit RI = 0x98;
-
-#endif /* _REG51KEIL_H_ */
+++ /dev/null
-#ifndef _REG51SDCC_H_
-#define _REG51SDCC_H_
-
-/* BYTE Register */
-sfr at 0x80 P0;
-sfr at 0x90 P1;
-sfr at 0xA0 P2;
-sfr at 0xB0 P3;
-sfr at 0xD0 PSW;
-sfr at 0xE0 ACC;
-sfr at 0xF0 B;
-sfr at 0x81 SP;
-sfr at 0x82 DPL;
-sfr at 0x83 DPH;
-sfr at 0x87 PCON;
-sfr at 0x88 TCON;
-sfr at 0x89 TMOD;
-sfr at 0x8A TL0;
-sfr at 0x8B TL1;
-sfr at 0x8C TH0;
-sfr at 0x8D TH1;
-sfr at 0xA8 IE;
-sfr at 0xB8 IP;
-sfr at 0x98 SCON;
-sfr at 0x99 SBUF;
-
-/* BIT Register */
-/* PSW */
-sbit at 0xD7 CY;
-sbit at 0xD6 AC;
-sbit at 0xD5 F0;
-sbit at 0xD4 RS1;
-sbit at 0xD3 RS0;
-sbit at 0xD2 OV;
-sbit at 0xD0 P;
-
-/* TCON */
-sbit at 0x8F TF1;
-sbit at 0x8E TR1;
-sbit at 0x8D TF0;
-sbit at 0x8C TR0;
-sbit at 0x8B IE1;
-sbit at 0x8A IT1;
-sbit at 0x89 IE0;
-sbit at 0x88 IT0;
-
-/* IE */
-sbit at 0xAF EA;
-sbit at 0xAC ES;
-sbit at 0xAB ET1;
-sbit at 0xAA EX1;
-sbit at 0xA9 ET0;
-sbit at 0xA8 EX0;
-
-/* IP */
-sbit at 0xBC PS;
-sbit at 0xBB PT1;
-sbit at 0xBA PX1;
-sbit at 0xB9 PT0;
-sbit at 0xB8 PX0;
-
-/* P3 */
-sbit at 0xB7 RD;
-sbit at 0xB6 WR;
-sbit at 0xB5 T1;
-sbit at 0xB4 T0;
-sbit at 0xB3 INT1;
-sbit at 0xB2 INT0;
-sbit at 0xB1 TXD;
-sbit at 0xB0 RXD;
-
-/* SCON */
-sbit at 0x9F SM0;
-sbit at 0x9E SM1;
-sbit at 0x9D SM2;
-sbit at 0x9C REN;
-sbit at 0x9B TB8;
-sbit at 0x9A RB8;
-sbit at 0x99 TI;
-sbit at 0x98 RI;
-
-#endif /* _REG51SDCC_H_ */
+++ /dev/null
-$NOMOD51
-;------------------------------------------------------------------------------
-; This file is part of the C51 Compiler package
-; Copyright (c) 1988-2002 Keil Elektronik GmbH and Keil Software, Inc.
-;------------------------------------------------------------------------------
-; STARTUP.A51: This code is executed after processor reset.
-;
-; To translate this file use A51 with the following invocation:
-;
-; A51 STARTUP.A51
-;
-; To link the modified STARTUP.OBJ file to your application use the following
-; BL51 invocation:
-;
-; BL51 <your object file list>, STARTUP.OBJ <controls>
-;
-;------------------------------------------------------------------------------
-;
-; User-defined Power-On Initialization of Memory
-;
-; With the following EQU statements the initialization of memory
-; at processor reset can be defined:
-;
-; ; the absolute start-address of IDATA memory is always 0
-IDATALEN EQU 80H ; the length of IDATA memory in bytes.
-;
-XDATASTART EQU 0H ; the absolute start-address of XDATA memory
-XDATALEN EQU 400H ; the length of XDATA memory in bytes.
-;
-PDATASTART EQU 0H ; the absolute start-address of PDATA memory
-PDATALEN EQU 0H ; the length of PDATA memory in bytes.
-;
-; Notes: The IDATA space overlaps physically the DATA and BIT areas of the
-; 8051 CPU. At minimum the memory space occupied from the C51
-; run-time routines must be set to zero.
-;------------------------------------------------------------------------------
-;
-; Reentrant Stack Initilization
-;
-; The following EQU statements define the stack pointer for reentrant
-; functions and initialized it:
-;
-; Stack Space for reentrant functions in the SMALL model.
-IBPSTACK EQU 0 ; set to 1 if small reentrant is used.
-IBPSTACKTOP EQU 0FFH+1 ; set top of stack to highest location+1.
-;
-; Stack Space for reentrant functions in the LARGE model.
-XBPSTACK EQU 0 ; set to 1 if large reentrant is used.
-XBPSTACKTOP EQU 0FFFFH+1; set top of stack to highest location+1.
-;
-; Stack Space for reentrant functions in the COMPACT model.
-PBPSTACK EQU 0 ; set to 1 if compact reentrant is used.
-PBPSTACKTOP EQU 0FFFFH+1; set top of stack to highest location+1.
-;
-;------------------------------------------------------------------------------
-;
-; Page Definition for Using the Compact Model with 64 KByte xdata RAM
-;
-; The following EQU statements define the xdata page used for pdata
-; variables. The EQU PPAGE must conform with the PPAGE control used
-; in the linker invocation.
-;
-PPAGEENABLE EQU 0 ; set to 1 if pdata object are used.
-;
-PPAGE EQU 0 ; define PPAGE number.
-;
-PPAGE_SFR DATA 0A0H ; SFR that supplies uppermost address byte
-; (most 8051 variants use P2 as uppermost address byte)
-;
-;------------------------------------------------------------------------------
-
-; Standard SFR Symbols
-ACC DATA 0E0H
-B DATA 0F0H
-SP DATA 81H
-DPL DATA 82H
-DPH DATA 83H
-
- NAME ?C_STARTUP
-
-
-?C_C51STARTUP SEGMENT CODE
-?STACK SEGMENT IDATA
-
- RSEG ?STACK
- DS 1
-
- EXTRN CODE (?C_START)
- PUBLIC ?C_STARTUP
-
- CSEG AT 0
-?C_STARTUP: LJMP STARTUP1
-
- RSEG ?C_C51STARTUP
-
-STARTUP1:
-
-IF IDATALEN <> 0
- MOV R0,#IDATALEN - 1
- CLR A
-IDATALOOP: MOV @R0,A
- DJNZ R0,IDATALOOP
-ENDIF
-
-IF XDATALEN <> 0
- MOV DPTR,#XDATASTART
- MOV R7,#LOW (XDATALEN)
- IF (LOW (XDATALEN)) <> 0
- MOV R6,#(HIGH (XDATALEN)) +1
- ELSE
- MOV R6,#HIGH (XDATALEN)
- ENDIF
- CLR A
-XDATALOOP: MOVX @DPTR,A
- INC DPTR
- DJNZ R7,XDATALOOP
- DJNZ R6,XDATALOOP
-ENDIF
-
-IF PPAGEENABLE <> 0
- MOV PPAGE_SFR,#PPAGE
-ENDIF
-
-IF PDATALEN <> 0
- MOV R0,#LOW (PDATASTART)
- MOV R7,#LOW (PDATALEN)
- CLR A
-PDATALOOP: MOVX @R0,A
- INC R0
- DJNZ R7,PDATALOOP
-ENDIF
-
-IF IBPSTACK <> 0
-EXTRN DATA (?C_IBP)
-
- MOV ?C_IBP,#LOW IBPSTACKTOP
-ENDIF
-
-IF XBPSTACK <> 0
-EXTRN DATA (?C_XBP)
-
- MOV ?C_XBP,#HIGH XBPSTACKTOP
- MOV ?C_XBP+1,#LOW XBPSTACKTOP
-ENDIF
-
-IF PBPSTACK <> 0
-EXTRN DATA (?C_PBP)
- MOV ?C_PBP,#LOW PBPSTACKTOP
-ENDIF
-
- MOV SP,#?STACK-1
-; This code is required if you use L51_BANK.A51 with Banking Mode 4
-; EXTRN CODE (?B_SWITCH0)
-; CALL ?B_SWITCH0 ; init bank mechanism to code bank 0
- LJMP ?C_START
-
- END
+++ /dev/null
-#ifndef _TYPES_H_
-#define _TYPES_H_
-
-#if 0 /* i386 */
-#include <stdint.h>
-
-/** booleano */
-typedef unsigned char bool;
-
-/** entero sin signo de 8 bits */
-typedef uint8_t byte;
-
-/** entero sin signo de 16 bits */
-typedef uint16_t uint16;
-
-#endif
-
-#if 1 /* 8051 */
-
-/** entero sin signo de 8 bits */
-typedef unsigned char byte;
-
-/** entero sin signo de 16 bits */
-typedef unsigned int uint16;
-
-#ifdef SDCC
-/** booleano */
-typedef byte bool;
-#else
-/** booleano */
-typedef bit bool;
-#endif
-
-#endif
-
-/** valores posibles de un booleano */
-enum { false = 0, true = 1 };
-
-/** convierte 2 bytes (high, low) en un word */
-#define WORD(high, low) ((uint16)((uint16)((high) << 8) + (uint16)(low)))
-
-/** obtiene parte alta de un word */
-#define HIGH(word) ((byte)((word) >> 8))
-
-/** obtiene parte baja de un word */
-#define LOW(word) ((byte)((word) & 0xFF))
-
-#endif /* _TYPES_H_ */
+++ /dev/null
-// vim: set et sw=4 sts=4 :
-
-#include "debug.h"
-#include "netdev.h"
-#include "ip.h"
-#include "udp.h"
-
-uint16 udp_port_local;
-
-uint16 udp_port_remote;
-
-byte udp_dgram_len;
-
-/* 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)
-{
- checksum += w;
- if (checksum < w) /* corrección de carry (hubo OV) */
- ++checksum;
-}
-
-bool udp_read_dgram_header()
-{
- byte tmp;
- bit ok = true;
- 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]));
- sum(WORD(ip_addr_remote[2], ip_addr_remote[3]));
- /* ip de destino */
- sum(WORD(ip_addr_local[0], ip_addr_local[1]));
- sum(WORD(ip_addr_local[2], ip_addr_local[3]));
- /* protocolo expresado en 16 bits (0x11 es UDP) */
- sum(0x0011);
- /* tamaño del paquete UDP (sin las cabeceras que son 20 bytes) */
- 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_read_word();
- /* agregamos puerto de origen al checksum */
- sum(udp_port_remote);
- /* sólo aceptamos datagramas a nuestro puerto */
- 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_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 */
- ok = false; /* drop */
- /* agregamos tamaño al checksum */
- sum(WORD(tmp, udp_dgram_len));
- /* agregamos checksum al checksum */
- 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;
-}
-
-byte udp_read_byte()
-{
- 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()
-{
- // 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]));
- sum(WORD(ip_addr_remote[2], ip_addr_remote[3]));
- /* ip de destino */
- sum(WORD(ip_addr_local[0], ip_addr_local[1]));
- sum(WORD(ip_addr_local[2], ip_addr_local[3]));
- /* protocolo expresado en 16 bits (0x11 es UDP) */
- sum(0x0011);
- /* tamaño del paquete UDP (IP sin las cabeceras, que son 20 bytes) */
- sum(ip_packet_len - 20); // FIXME
- /* puerto origen */
- netdev_write_word(udp_port_local);
- sum(udp_port_local);
- /* puerto destino */
- netdev_write_word(udp_port_remote);
- sum(udp_port_remote);
- /* tamaño del datagrama */
- 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_write_word(0x0000);
- sum(0x0000);
- netdev_write_end();
-}
-
-void udp_write_byte(byte b)
-{
- 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(byte offset)
-{
- // 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;
-}
-
+++ /dev/null
-// vim: set et sw=4 sts=4 :
-
-#ifndef _UDP_H_
-#define _UDP_H_
-
-#include "types.h"
-
-/** @file
- * Datagrama UDP.
- *
- * <pre>
- * 0 7 8 15 16 23 24 31
- * +--------+--------+--------+--------+
- * | Source | Destination |
- * | Port | Port |
- * +--------+--------+--------+--------+
- * | | |
- * | Length | Checksum |
- * +--------+--------+--------+--------+
- * |
- * | data octets ...
- * +---------------- ...
- * </pre>
- *
- * Aceptamos sólo datagramas UDP que vayan a el puerto de nuestra aplicación y
- * cuyo tamaño sea menor a 255. El resto es descartado.
- * El Length es tanto de la cabecera como datos, por lo tanto el tamaño mínimo
- * es 8.
- *
- * El checksum se calcula utilizando algunos datos de la capa inferior e incluye
- * a los datos (completando con 0 al final si no es múltiplo de 2). Entonces es
- * calculado sobre el siguiente paquete 'virtual':
- *
- * <pre>
- * 0 7 8 15 16 23 24 31
- * +--------+--------+--------+--------+
- * | ip source address |
- * +--------+--------+--------+--------+
- * | ip destination address |
- * +--------+--------+--------+--------+
- * | zero |protocol| UDP length |
- * +--------+--------+--------+--------+
- * | Source | Destination |
- * | Port | Port |
- * +--------+--------+--------+--------+
- * | | |
- * | Length | Checksum |
- * +--------+--------+--------+--------+
- * |
- * | data octets ... (padding)
- * +---------------- ...
- * </pre>
- */
-
-/** Tamaño de la cabecera UDP */
-#define UDP_HEADER_SIZE 8
-
-/** Puerto UDP nuestro */
-extern uint16 udp_port_local;
-
-/** Puerto UDP de destino */
-extern uint16 udp_port_remote;
-
-/** Tamaño del datagrama UDP (no soportamos más de 255) */
-extern byte udp_dgram_len;
-
-/** Lee la cabecera del datagrama UDP.
- *
- * Deja en udp_port_remote el puerto de origen.
- * Si devuelve false (0) es que hubo un error o es un datagrama no soportado,
- * por lo que hay que descartarlo.
- */
-bool udp_read_dgram_header();
-
-/** 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();
-
-/** Escribe la cabecera del datagrama UDP.
- *
- * Pone como puerto destino a udp_port_remote, como origen udp_port_local y como
- * tamaño a udp_dgram_len (en la parte baja y 0 en la parte alta).
- */
-void udp_write_dgram_header();
-
-/** 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
- * @param offset Offset a partir de donde están las cabeceras UDP.
- */
-void udp_write_checksum(byte offset);
-
-#endif /* _UDP_H_ */