added code to support FEC networking
This commit is contained in:
17
Makefile
17
Makefile
@@ -67,6 +67,7 @@ CSRCS= \
|
||||
bas_string.c \
|
||||
BaS.c \
|
||||
cache.c \
|
||||
mmu.c \
|
||||
mmc.c \
|
||||
unicode.c \
|
||||
ff.c \
|
||||
@@ -84,15 +85,18 @@ CSRCS= \
|
||||
MCD_dmaApi.c \
|
||||
MCD_tasks.c \
|
||||
MCD_tasksInit.c \
|
||||
\
|
||||
usb.c \
|
||||
ohci-hcd.c \
|
||||
ehci-hcd.c \
|
||||
usb_mouse.c \
|
||||
\
|
||||
ikbd.c \
|
||||
\
|
||||
fec.c\
|
||||
nbuf.c \
|
||||
queue.c \
|
||||
nif.c \
|
||||
fecbd.c \
|
||||
fec.c \
|
||||
udp.c \
|
||||
\
|
||||
basflash.c \
|
||||
basflash_start.c
|
||||
@@ -101,9 +105,8 @@ ASRCS= \
|
||||
startcf.S \
|
||||
printf_helper.S \
|
||||
exceptions.S \
|
||||
mmu.S \
|
||||
xhdi_vec.S
|
||||
|
||||
|
||||
SRCS=$(ASRCS) $(CSRCS)
|
||||
COBJS=$(patsubst %.c,%.o,$(CSRCS))
|
||||
AOBJS=$(patsubst %.S,%.o,$(ASRCS))
|
||||
@@ -155,8 +158,8 @@ $(foreach DIR,$(TRGTDIRS),$(eval $(call CC_TEMPLATE,$(DIR))))
|
||||
|
||||
# rules for depend
|
||||
define DEP_TEMPLATE
|
||||
ifneq (clean,$(MAKECMDGOALS))
|
||||
-include $(1)/depend
|
||||
ifneq (clean,$$(MAKECMDGOALS))
|
||||
include $(1)/depend
|
||||
endif
|
||||
|
||||
ifeq (firebee,$(1))
|
||||
|
||||
@@ -50,6 +50,13 @@ SECTIONS
|
||||
OBJDIR/ehci-hcd.o(.text)
|
||||
OBJDIR/wait.o(.text)
|
||||
|
||||
OBJDIR/nbuf.o(.text)
|
||||
OBJDIR/queue.o(.text)
|
||||
OBJDIR/nif.o(.text)
|
||||
OBJDIR/fecbd.o(.text)
|
||||
OBJDIR/fec.o(.text)
|
||||
OBJDIR/udp.o(text)
|
||||
|
||||
OBJDIR/unicode.o(.text)
|
||||
OBJDIR/mmc.o(.text)
|
||||
OBJDIR/ff.o(.text)
|
||||
|
||||
@@ -35,26 +35,13 @@ typedef struct
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
void
|
||||
udp_init (void);
|
||||
|
||||
void
|
||||
udp_prime_port (uint16_t);
|
||||
|
||||
uint16_t
|
||||
udp_obtain_free_port (void);
|
||||
|
||||
void
|
||||
udp_bind_port ( uint16_t, void (*)(NIF *,NBUF *));
|
||||
|
||||
void
|
||||
udp_free_port (uint16_t);
|
||||
|
||||
int
|
||||
udp_send (NIF *, uint8_t *, int, int, NBUF *);
|
||||
|
||||
void
|
||||
udp_handler (NIF *, NBUF *);
|
||||
extern void udp_init(void);
|
||||
extern void udp_prime_port(uint16_t);
|
||||
extern uint16_t udp_obtain_free_port(void);
|
||||
extern void udp_bind_port( uint16_t, void (*)(NIF *,NBUF *));
|
||||
extern void udp_free_port(uint16_t);
|
||||
extern int udp_send(NIF *, uint8_t *, int, int, NBUF *);
|
||||
extern void udp_handler(NIF *, NBUF *);
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
|
||||
33
net/bootp.c
Normal file
33
net/bootp.c
Normal file
@@ -0,0 +1,33 @@
|
||||
#include "bas_types.h"
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
static bool bootp_initialized = false;
|
||||
|
||||
/*
|
||||
* bootp client state
|
||||
*/
|
||||
|
||||
struct bootp_client
|
||||
{
|
||||
uint8_t state;
|
||||
uint8_t mode;
|
||||
uint8_t socket_handle;
|
||||
uint16_t timer_handle;
|
||||
uint16_t boot_secs;
|
||||
};
|
||||
|
||||
static struct bootp_client client;
|
||||
|
||||
int bootpc_init(int mode)
|
||||
{
|
||||
if (bootp_initialized)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* get socket handle
|
||||
*/
|
||||
client.socket_handle = udp_getsocket
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "dma.h"
|
||||
#include "bas_string.h"
|
||||
#include "bas_printf.h"
|
||||
#include "util.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#if defined(MACHINE_FIREBEE)
|
||||
@@ -412,8 +413,8 @@ void fec_reset (uint8_t ch)
|
||||
MCF_FEC_ECR(ch) = MCF_FEC_ECR_RESET;
|
||||
|
||||
/* Wait at least 8 clock cycles */
|
||||
for (i=0; i<10; ++i)
|
||||
nop();
|
||||
for (i = 0; i < 10; ++i)
|
||||
NOP();
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
226
net/fecbd.c
Normal file
226
net/fecbd.c
Normal file
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
* File: fecbd.c
|
||||
* Purpose: Provide a simple buffer management driver
|
||||
*
|
||||
* Notes:
|
||||
*/
|
||||
#include "MCD_dma.h"
|
||||
#include "fecbd.h"
|
||||
#include "nbuf.h"
|
||||
#include "eth.h"
|
||||
#include "bas_printf.h"
|
||||
#include <stddef.h>
|
||||
|
||||
/*
|
||||
* This implements a simple static buffer descriptor
|
||||
* ring for each channel and each direction
|
||||
*
|
||||
* FEC Buffer Descriptors need to be aligned to a 4-byte boundary.
|
||||
* In order to accomplish this, data is over-allocated and manually
|
||||
* aligned at runtime
|
||||
*
|
||||
* Enough space is allocated for each of the two FEC channels to have
|
||||
* NRXBD Rx BDs and NTXBD Tx BDs
|
||||
*
|
||||
*/
|
||||
|
||||
FECBD unaligned_bds[(2 * NRXBD) + (2 * NTXBD) + 1];
|
||||
|
||||
/*
|
||||
* These pointers are used to reference into the chunck of data set
|
||||
* aside for buffer descriptors
|
||||
*/
|
||||
FECBD *RxBD;
|
||||
FECBD *TxBD;
|
||||
|
||||
/*
|
||||
* Macros to easier access to the BD ring
|
||||
*/
|
||||
#define RxBD(ch,i) RxBD[(ch * NRXBD) + i]
|
||||
#define TxBD(ch,i) TxBD[(ch * NTXBD) + i]
|
||||
|
||||
/*
|
||||
* Buffer descriptor indexes
|
||||
*/
|
||||
static int iTxbd_new;
|
||||
static int iTxbd_old;
|
||||
static int iRxbd;
|
||||
|
||||
/*
|
||||
* Initialize the FEC Buffer Descriptor ring
|
||||
* Buffer Descriptor format is defined by the MCDAPI
|
||||
*
|
||||
* Parameters:
|
||||
* ch FEC channel
|
||||
*/
|
||||
void fecbd_init(uint8_t ch)
|
||||
{
|
||||
NBUF *nbuf;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Align Buffer Descriptors to 4-byte boundary
|
||||
*/
|
||||
RxBD = (FECBD *)(((int)unaligned_bds + 3) & 0xFFFFFFFC);
|
||||
TxBD = (FECBD *)((int)RxBD + (sizeof(FECBD) * 2 * NRXBD));
|
||||
|
||||
/*
|
||||
* Initialize the Rx Buffer Descriptor ring
|
||||
*/
|
||||
for (i = 0; i < NRXBD; ++i)
|
||||
{
|
||||
/* Grab a network buffer from the free list */
|
||||
nbuf = nbuf_alloc();
|
||||
if (nbuf == NULL)
|
||||
{
|
||||
xprintf("%s: could not allocate network buffer\r\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Initialize the BD */
|
||||
RxBD(ch,i).status = RX_BD_E | RX_BD_INTERRUPT;
|
||||
RxBD(ch,i).length = RX_BUF_SZ;
|
||||
RxBD(ch,i).data = nbuf->data;
|
||||
|
||||
/* Add the network buffer to the Rx queue */
|
||||
nbuf_add(NBUF_RX_RING, nbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the WRAP bit on the last one
|
||||
*/
|
||||
RxBD(ch,i-1).status |= RX_BD_W;
|
||||
|
||||
/*
|
||||
* Initialize the Tx Buffer Descriptor ring
|
||||
*/
|
||||
for (i = 0; i < NTXBD; ++i)
|
||||
{
|
||||
TxBD(ch,i).status = TX_BD_INTERRUPT;
|
||||
TxBD(ch,i).length = 0;
|
||||
TxBD(ch,i).data = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the WRAP bit on the last one
|
||||
*/
|
||||
TxBD(ch,i-1).status |= TX_BD_W;
|
||||
|
||||
/*
|
||||
* Initialize the buffer descriptor indexes
|
||||
*/
|
||||
iTxbd_new = iTxbd_old = iRxbd = 0;
|
||||
}
|
||||
|
||||
void fecbd_dump(uint8_t ch)
|
||||
{
|
||||
#ifdef DEBUG_PRINT
|
||||
int i;
|
||||
|
||||
printf("\n------------ FEC%d BDs -----------\n",ch);
|
||||
printf("RxBD Ring\n");
|
||||
for (i=0; i<NRXBD; i++)
|
||||
{
|
||||
printf("%02d: BD Addr=0x%08x, Ctrl=0x%04x, Lgth=%04d, DataPtr=0x%08x\n",
|
||||
i, &RxBD(ch,i),
|
||||
RxBD(ch,i).status,
|
||||
RxBD(ch,i).length,
|
||||
RxBD(ch,i).data);
|
||||
}
|
||||
printf("TxBD Ring\n");
|
||||
for (i=0; i<NTXBD; i++)
|
||||
{
|
||||
printf("%02d: BD Addr=0x%08x, Ctrl=0x%04x, Lgth=%04d, DataPtr=0x%08x\n",
|
||||
i, &TxBD(ch,i),
|
||||
TxBD(ch,i).status,
|
||||
TxBD(ch,i).length,
|
||||
TxBD(ch,i).data);
|
||||
}
|
||||
printf("--------------------------------\n\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the address of the first buffer descriptor in the ring.
|
||||
*
|
||||
* Parameters:
|
||||
* ch FEC channel
|
||||
* direction Rx or Tx Macro
|
||||
*
|
||||
* Return Value:
|
||||
* The start address of the selected Buffer Descriptor ring
|
||||
*/
|
||||
uint32_t fecbd_get_start(uint8_t ch, uint8_t direction)
|
||||
{
|
||||
switch (direction)
|
||||
{
|
||||
case Rx:
|
||||
return (uint32_t)((int)RxBD + (ch * sizeof(FECBD) * NRXBD));
|
||||
case Tx:
|
||||
default:
|
||||
return (uint32_t)((int)TxBD + (ch * sizeof(FECBD) * NTXBD));
|
||||
}
|
||||
}
|
||||
|
||||
FECBD *fecbd_rx_alloc(uint8_t ch)
|
||||
{
|
||||
int i = iRxbd;
|
||||
|
||||
/* Check to see if the ring of BDs is full */
|
||||
if (RxBD(ch,i).status & RX_BD_E)
|
||||
return NULL;
|
||||
|
||||
/* Increment the circular index */
|
||||
iRxbd = (uint8_t)((iRxbd + 1) % NRXBD);
|
||||
|
||||
return &RxBD(ch,i);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function keeps track of the next available Tx BD in the ring
|
||||
*
|
||||
* Parameters:
|
||||
* ch FEC channel
|
||||
*
|
||||
* Return Value:
|
||||
* Pointer to next available buffer descriptor.
|
||||
* NULL if the BD ring is full
|
||||
*/
|
||||
FECBD *fecbd_tx_alloc(uint8_t ch)
|
||||
{
|
||||
int i = iTxbd_new;
|
||||
|
||||
/* Check to see if the ring of BDs is full */
|
||||
if (TxBD(ch,i).status & TX_BD_R)
|
||||
return NULL;
|
||||
|
||||
/* Increment the circular index */
|
||||
iTxbd_new = (uint8_t)((iTxbd_new + 1) % NTXBD);
|
||||
|
||||
return &TxBD(ch,i);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function keeps track of the Tx BDs that have already been
|
||||
* processed by the FEC
|
||||
*
|
||||
* Parameters:
|
||||
* ch FEC channel
|
||||
*
|
||||
* Return Value:
|
||||
* Pointer to the oldest buffer descriptor that has already been sent
|
||||
* by the FEC, NULL if the BD ring is empty
|
||||
*/
|
||||
FECBD *fecbd_tx_free(uint8_t ch)
|
||||
{
|
||||
int i = iTxbd_old;
|
||||
|
||||
/* Check to see if the ring of BDs is empty */
|
||||
if ((TxBD(ch,i).data == NULL) || (TxBD(ch,i).status & TX_BD_R))
|
||||
return NULL;
|
||||
|
||||
/* Increment the circular index */
|
||||
iTxbd_old = (uint8_t)((iTxbd_old + 1) % NTXBD);
|
||||
|
||||
return &TxBD(ch,i);
|
||||
}
|
||||
120
net/nbuf.c
120
net/nbuf.c
@@ -4,13 +4,12 @@
|
||||
*
|
||||
* Notes:
|
||||
*/
|
||||
#include "src/include/dbug.h"
|
||||
#include "src/uif/net/queue.h"
|
||||
#include "src/uif/net/net.h"
|
||||
|
||||
#ifdef DBUG_NETWORK
|
||||
|
||||
/********************************************************************/
|
||||
#include "queue.h"
|
||||
#include "net.h"
|
||||
#include "driver_mem.h"
|
||||
#include "exceptions.h"
|
||||
#include "bas_types.h"
|
||||
#include "bas_printf.h"
|
||||
/*
|
||||
* Queues used for network buffer storage
|
||||
*/
|
||||
@@ -21,9 +20,8 @@ QUEUE nbuf_queue[NBUF_MAXQ];
|
||||
* this, the nbuf data is over-allocated and adjusted. The following
|
||||
* array keeps track of the original data pointer returned by malloc
|
||||
*/
|
||||
ADDRESS unaligned_buffers[NBUF_MAX];
|
||||
uint8_t *unaligned_buffers[NBUF_MAX];
|
||||
|
||||
/********************************************************************/
|
||||
/*
|
||||
* Initialize all the network buffer queues
|
||||
*
|
||||
@@ -31,8 +29,7 @@ ADDRESS unaligned_buffers[NBUF_MAX];
|
||||
* 0 success
|
||||
* 1 failure
|
||||
*/
|
||||
int
|
||||
nbuf_init(void)
|
||||
int nbuf_init(void)
|
||||
{
|
||||
int i;
|
||||
NBUF *nbuf;
|
||||
@@ -47,23 +44,21 @@ nbuf_init(void)
|
||||
printf("Creating %d net buffers of %d bytes\n",NBUF_MAX,NBUF_SZ);
|
||||
#endif
|
||||
|
||||
for (i=0; i<NBUF_MAX; ++i)
|
||||
for (i = 0; i < NBUF_MAX; ++i)
|
||||
{
|
||||
/* Allocate memory for the network buffer structure */
|
||||
nbuf = (NBUF *)malloc(sizeof(NBUF));
|
||||
nbuf = (NBUF *) driver_mem_alloc(sizeof(NBUF));
|
||||
if (!nbuf)
|
||||
{
|
||||
ASSERT(nbuf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Allocate memory for the actual data */
|
||||
unaligned_buffers[i] = (ADDRESS)malloc(NBUF_SZ + 16);
|
||||
nbuf->data = (uint8 *)((uint32)(unaligned_buffers[i] + 15) & 0xFFFFFFF0);
|
||||
if (!nbuf->data)
|
||||
unaligned_buffers[i] = driver_mem_alloc(NBUF_SZ + 16);
|
||||
nbuf->data = (uint8_t *)((uint32_t)(unaligned_buffers[i] + 15) & 0xFFFFFFF0);
|
||||
if (!nbuf->data)
|
||||
{
|
||||
ASSERT(nbuf->data);
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Initialize the network buffer */
|
||||
@@ -81,32 +76,30 @@ nbuf_init(void)
|
||||
|
||||
return 0;
|
||||
}
|
||||
/********************************************************************/
|
||||
|
||||
/*
|
||||
* Return all the allocated memory to the heap
|
||||
*/
|
||||
void
|
||||
nbuf_flush(void)
|
||||
void nbuf_flush(void)
|
||||
{
|
||||
NBUF *nbuf;
|
||||
int i, level = asm_set_ipl(7);
|
||||
int i, level = set_ipl(7);
|
||||
int n = 0;
|
||||
|
||||
for (i=0; i<NBUF_MAX; ++i)
|
||||
free((uint8*)unaligned_buffers[i]);
|
||||
for (i = 0; i < NBUF_MAX; ++i)
|
||||
driver_mem_free((uint8_t *) unaligned_buffers[i]);
|
||||
|
||||
for (i=0; i<NBUF_MAXQ; ++i)
|
||||
for (i = 0; i < NBUF_MAXQ; ++i)
|
||||
{
|
||||
while ((nbuf = (NBUF *)queue_remove(&nbuf_queue[i])) != NULL)
|
||||
while ((nbuf = (NBUF *) queue_remove(&nbuf_queue[i])) != NULL)
|
||||
{
|
||||
free(nbuf);
|
||||
driver_mem_free(nbuf);
|
||||
++n;
|
||||
}
|
||||
}
|
||||
ASSERT(n == NBUF_MAX);
|
||||
asm_set_ipl(level);
|
||||
set_ipl(level);
|
||||
}
|
||||
/********************************************************************/
|
||||
|
||||
/*
|
||||
* Allocate a network buffer from the free list
|
||||
*
|
||||
@@ -114,96 +107,92 @@ nbuf_flush(void)
|
||||
* Pointer to a free network buffer
|
||||
* NULL if none are available
|
||||
*/
|
||||
NBUF *
|
||||
nbuf_alloc(void)
|
||||
NBUF *nbuf_alloc(void)
|
||||
{
|
||||
NBUF *nbuf;
|
||||
int level = asm_set_ipl(7);
|
||||
int level = set_ipl(7);
|
||||
|
||||
nbuf = (NBUF *)queue_remove(&nbuf_queue[NBUF_FREE]);
|
||||
asm_set_ipl(level);
|
||||
nbuf = (NBUF *) queue_remove(&nbuf_queue[NBUF_FREE]);
|
||||
set_ipl(level);
|
||||
|
||||
return nbuf;
|
||||
}
|
||||
/********************************************************************/
|
||||
|
||||
/*
|
||||
* Add the specified network buffer back to the free list
|
||||
*
|
||||
* Parameters:
|
||||
* nbuf Buffer to add back to the free list
|
||||
*/
|
||||
void
|
||||
nbuf_free(NBUF *nbuf)
|
||||
void nbuf_free(NBUF *nbuf)
|
||||
{
|
||||
int level = asm_set_ipl(7);
|
||||
int level = set_ipl(7);
|
||||
|
||||
nbuf->offset = 0;
|
||||
nbuf->length = NBUF_SZ;
|
||||
queue_add(&nbuf_queue[NBUF_FREE],(QNODE *)nbuf);
|
||||
|
||||
asm_set_ipl(level);
|
||||
set_ipl(level);
|
||||
}
|
||||
/********************************************************************/
|
||||
|
||||
/*
|
||||
* Remove a network buffer from the specified queue
|
||||
*
|
||||
* Parameters:
|
||||
* q The index that identifies the queue to pull the buffer from
|
||||
*/
|
||||
NBUF *
|
||||
nbuf_remove(int q)
|
||||
NBUF *nbuf_remove(int q)
|
||||
{
|
||||
NBUF *nbuf;
|
||||
int level = asm_set_ipl(7);
|
||||
int level = set_ipl(7);
|
||||
|
||||
nbuf = (NBUF *)queue_remove(&nbuf_queue[q]);
|
||||
asm_set_ipl(level);
|
||||
nbuf = (NBUF *) queue_remove(&nbuf_queue[q]);
|
||||
set_ipl(level);
|
||||
|
||||
return nbuf;
|
||||
}
|
||||
/********************************************************************/
|
||||
|
||||
/*
|
||||
* Add a network buffer to the specified queue
|
||||
*
|
||||
* Parameters:
|
||||
* q The index that identifies the queue to add the buffer to
|
||||
*/
|
||||
void
|
||||
nbuf_add(int q, NBUF *nbuf)
|
||||
void nbuf_add(int q, NBUF *nbuf)
|
||||
{
|
||||
int level = asm_set_ipl(7);
|
||||
int level = set_ipl(7);
|
||||
queue_add(&nbuf_queue[q],(QNODE *)nbuf);
|
||||
asm_set_ipl(level);
|
||||
set_ipl(level);
|
||||
}
|
||||
/********************************************************************/
|
||||
|
||||
/*
|
||||
* Put all the network buffers back into the free list
|
||||
*/
|
||||
void
|
||||
nbuf_reset(void)
|
||||
void nbuf_reset(void)
|
||||
{
|
||||
NBUF *nbuf;
|
||||
int i, level = asm_set_ipl(7);
|
||||
int i, level = set_ipl(7);
|
||||
|
||||
for (i=1; i<NBUF_MAXQ; ++i)
|
||||
for (i = 1; i < NBUF_MAXQ; ++i)
|
||||
{
|
||||
while ((nbuf = nbuf_remove(i)) != NULL)
|
||||
nbuf_free(nbuf);
|
||||
}
|
||||
asm_set_ipl(level);
|
||||
set_ipl(level);
|
||||
}
|
||||
/********************************************************************/
|
||||
|
||||
/*
|
||||
* Display all the nbuf queues
|
||||
*/
|
||||
void
|
||||
nbuf_debug_dump(void)
|
||||
void nbuf_debug_dump(void)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
NBUF *nbuf;
|
||||
int i, j, level;
|
||||
|
||||
level = asm_set_ipl(7);
|
||||
level = set_ipl(7);
|
||||
|
||||
for (i=0; i<NBUF_MAXQ; ++i)
|
||||
for (i = 0; i < NBUF_MAXQ; ++i)
|
||||
{
|
||||
printf("\n\nQueue #%d\n\n",i);
|
||||
printf("\tBuffer Location\tOffset\tLength\n");
|
||||
@@ -219,9 +208,6 @@ nbuf_debug_dump(void)
|
||||
}
|
||||
}
|
||||
|
||||
asm_set_ipl(level);
|
||||
set_ipl(level);
|
||||
#endif
|
||||
}
|
||||
/********************************************************************/
|
||||
|
||||
#endif /* #ifdef DBUG_NETWORK */
|
||||
|
||||
118
net/nif.c
Normal file
118
net/nif.c
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* File: nif.c
|
||||
* Purpose: Network InterFace routines
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* Modifications:
|
||||
*
|
||||
*/
|
||||
#include "net.h"
|
||||
#include "bas_types.h"
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
int nif_protocol_exist(NIF *nif, uint16_t protocol)
|
||||
{
|
||||
/*
|
||||
* This function searches the list of supported protocols
|
||||
* on the particular NIF and if a protocol handler exists,
|
||||
* true is returned. This function is useful for network cards
|
||||
* that needn't read in the entire frame but can discard frames
|
||||
* arbitrarily.
|
||||
*/
|
||||
int index;
|
||||
|
||||
for (index = 0; index < nif->num_protocol; ++index)
|
||||
{
|
||||
if (nif->protocol[index].protocol == protocol)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void nif_protocol_handler(NIF *nif, uint16_t protocol, NBUF *pNbuf)
|
||||
{
|
||||
/*
|
||||
* This function searches the list of supported protocols
|
||||
* on the particular NIF and if a protocol handler exists,
|
||||
* the protocol handler is invoked. This routine called by
|
||||
* network device driver after receiving a frame.
|
||||
*/
|
||||
int index;
|
||||
|
||||
for (index = 0; index < nif->num_protocol; ++index)
|
||||
{
|
||||
if (nif->protocol[index].protocol == protocol)
|
||||
nif->protocol[index].handler(nif,pNbuf);
|
||||
}
|
||||
}
|
||||
|
||||
void *nif_get_protocol_info (NIF *nif, uint16_t protocol)
|
||||
{
|
||||
/*
|
||||
* This function searches the list of supported protocols
|
||||
* on the particular NIF and returns a pointer to the
|
||||
* config info for 'protocol', otherwise NULL is returned.
|
||||
*/
|
||||
int index;
|
||||
|
||||
for (index = 0; index < nif->num_protocol; ++index)
|
||||
{
|
||||
if (nif->protocol[index].protocol == protocol)
|
||||
return (void *)nif->protocol[index].info;
|
||||
}
|
||||
return (void *)0;
|
||||
}
|
||||
|
||||
int nif_bind_protocol (NIF *nif, uint16_t protocol,
|
||||
void (*handler)(NIF *,NBUF *),
|
||||
void *info)
|
||||
{
|
||||
/*
|
||||
* This function registers 'protocol' as a supported
|
||||
* protocol in 'nif'.
|
||||
*/
|
||||
if (nif->num_protocol < (MAX_SUP_PROTO - 1))
|
||||
{
|
||||
nif->protocol[nif->num_protocol].protocol = protocol;
|
||||
nif->protocol[nif->num_protocol].handler = (void(*)(NIF*,NBUF*))handler;
|
||||
nif->protocol[nif->num_protocol].info = info;
|
||||
++nif->num_protocol;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
NIF *nif_init (NIF *nif)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ETH_ADDR_LEN; ++i)
|
||||
{
|
||||
nif->hwa[i] = 0;
|
||||
nif->broadcast[i] = 0xFF;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_SUP_PROTO; ++i)
|
||||
{
|
||||
nif->protocol[i].protocol = 0;
|
||||
nif->protocol[i].handler = 0;
|
||||
nif->protocol[i].info = 0;
|
||||
}
|
||||
nif->num_protocol = 0;
|
||||
|
||||
nif->mtu = 0;
|
||||
nif->ch = 0;
|
||||
nif->send = 0;
|
||||
|
||||
nif->f_rx = 0;
|
||||
nif->f_tx = 0;
|
||||
nif->f_rx_err = 0;
|
||||
nif->f_tx_err = 0;
|
||||
nif->f_err = 0;
|
||||
|
||||
return nif;
|
||||
}
|
||||
114
net/queue.c
Normal file
114
net/queue.c
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* File: queue.c
|
||||
* Purpose: Implement a first in, first out linked list
|
||||
*
|
||||
* Notes:
|
||||
*/
|
||||
#include "bas_string.h"
|
||||
#include "queue.h"
|
||||
|
||||
/*
|
||||
* Initialize the specified queue to an empty state
|
||||
*
|
||||
* Parameters:
|
||||
* q Pointer to queue structure
|
||||
*/
|
||||
void queue_init(QUEUE *q)
|
||||
{
|
||||
q->head = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for an empty queue
|
||||
*
|
||||
* Parameters:
|
||||
* q Pointer to queue structure
|
||||
*
|
||||
* Return Value:
|
||||
* 1 if Queue is empty
|
||||
* 0 otherwise
|
||||
*/
|
||||
int queue_isempty(QUEUE *q)
|
||||
{
|
||||
return (q->head == NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add an item to the end of the queue
|
||||
*
|
||||
* Parameters:
|
||||
* q Pointer to queue structure
|
||||
* node New node to add to the queue
|
||||
*/
|
||||
void queue_add(QUEUE *q, QNODE *node)
|
||||
{
|
||||
if (queue_isempty(q))
|
||||
{
|
||||
q->head = q->tail = node;
|
||||
}
|
||||
else
|
||||
{
|
||||
q->tail->next = node;
|
||||
q->tail = node;
|
||||
}
|
||||
|
||||
node->next = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove and return first (oldest) entry from the specified queue
|
||||
*
|
||||
* Parameters:
|
||||
* q Pointer to queue structure
|
||||
*
|
||||
* Return Value:
|
||||
* Node at head of queue - NULL if queue is empty
|
||||
*/
|
||||
QNODE *queue_remove(QUEUE *q)
|
||||
{
|
||||
QNODE *oldest;
|
||||
|
||||
if (queue_isempty(q))
|
||||
return NULL;
|
||||
|
||||
oldest = q->head;
|
||||
q->head = oldest->next;
|
||||
return oldest;
|
||||
}
|
||||
|
||||
/*
|
||||
* Peek into the queue and return pointer to first (oldest) entry.
|
||||
* The queue is not modified
|
||||
*
|
||||
* Parameters:
|
||||
* q Pointer to queue structure
|
||||
*
|
||||
* Return Value:
|
||||
* Node at head of queue - NULL if queue is empty
|
||||
*/
|
||||
QNODE *queue_peek(QUEUE *q)
|
||||
{
|
||||
return q->head;
|
||||
}
|
||||
|
||||
/*
|
||||
* Move entire contents of one queue to the other
|
||||
*
|
||||
* Parameters:
|
||||
* src Pointer to source queue
|
||||
* dst Pointer to destination queue
|
||||
*/
|
||||
void queue_move(QUEUE *dst, QUEUE *src)
|
||||
{
|
||||
if (queue_isempty(src))
|
||||
return;
|
||||
|
||||
if (queue_isempty(dst))
|
||||
dst->head = src->head;
|
||||
else
|
||||
dst->tail->next = src->head;
|
||||
|
||||
dst->tail = src->tail;
|
||||
src->head = NULL;
|
||||
return;
|
||||
}
|
||||
180
net/udp.c
Normal file
180
net/udp.c
Normal file
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* File: udp.c
|
||||
* Purpose: User Datagram Protocol driver
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* Modifications:
|
||||
*
|
||||
*/
|
||||
#include "bas_types.h"
|
||||
#include "net.h"
|
||||
|
||||
#ifdef DBUG_NETWORK
|
||||
|
||||
/********************************************************************/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t port;
|
||||
void (*handler)(NIF *, NBUF *);
|
||||
} UDP_BOUND_PORT;
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
#define UDP_MAX_PORTS (5) /* plenty for this implementation */
|
||||
|
||||
|
||||
static UDP_BOUND_PORT
|
||||
udp_port_table[UDP_MAX_PORTS];
|
||||
|
||||
static uint16
|
||||
udp_port;
|
||||
|
||||
/********************************************************************/
|
||||
void
|
||||
udp_init (void)
|
||||
{
|
||||
int index;
|
||||
|
||||
for (index = 0; index < UDP_MAX_PORTS; ++index)
|
||||
{
|
||||
udp_port_table[index].port = 0;
|
||||
}
|
||||
|
||||
udp_port = DEFAULT_UDP_PORT; /* next free port */
|
||||
}
|
||||
/********************************************************************/
|
||||
void
|
||||
udp_prime_port (uint16 init_port)
|
||||
{
|
||||
udp_port = init_port;
|
||||
}
|
||||
/********************************************************************/
|
||||
void
|
||||
udp_bind_port (uint16 port, void (*handler)(NIF *, NBUF *))
|
||||
{
|
||||
int index;
|
||||
|
||||
for (index = 0; index < UDP_MAX_PORTS; ++index)
|
||||
{
|
||||
if (udp_port_table[index].port == 0)
|
||||
{
|
||||
udp_port_table[index].port = port;
|
||||
udp_port_table[index].handler = handler;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
/********************************************************************/
|
||||
void
|
||||
udp_free_port (uint16 port)
|
||||
{
|
||||
int index;
|
||||
|
||||
for (index = 0; index < UDP_MAX_PORTS; ++index)
|
||||
{
|
||||
if (udp_port_table[index].port == port)
|
||||
{
|
||||
udp_port_table[index].port = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
/********************************************************************/
|
||||
static void *
|
||||
udp_port_handler (uint16 port)
|
||||
{
|
||||
int index;
|
||||
|
||||
for (index = 0; index < UDP_MAX_PORTS; ++index)
|
||||
{
|
||||
if (udp_port_table[index].port == port)
|
||||
{
|
||||
return (void *)udp_port_table[index].handler;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/********************************************************************/
|
||||
uint16
|
||||
udp_obtain_free_port (void)
|
||||
{
|
||||
uint16 port;
|
||||
|
||||
port = udp_port;
|
||||
if (--udp_port <= 255)
|
||||
udp_port = DEFAULT_UDP_PORT;
|
||||
|
||||
return port;
|
||||
}
|
||||
/********************************************************************/
|
||||
int
|
||||
udp_send ( NIF *nif, uint8 *dest, int sport, int dport, NBUF *pNbuf)
|
||||
{
|
||||
/*
|
||||
* This function takes data and creates a UDP frame and
|
||||
* passes it onto the IP layer
|
||||
*/
|
||||
udp_frame_hdr *udpframe;
|
||||
|
||||
udpframe = (udp_frame_hdr *)&pNbuf->data[UDP_HDR_OFFSET];
|
||||
|
||||
/* Set UDP source port */
|
||||
udpframe->src_port = (uint16)sport;
|
||||
|
||||
/* Set UDP destination port */
|
||||
udpframe->dest_port = (uint16)dport;
|
||||
|
||||
/* Set length */
|
||||
udpframe->length = (uint16)(pNbuf->length + UDP_HDR_SIZE);
|
||||
|
||||
/* No checksum calcualation needed */
|
||||
udpframe->chksum = (uint16)0;
|
||||
|
||||
/* Add the length of the UDP packet to the total length of the packet */
|
||||
pNbuf->length += 8;
|
||||
|
||||
return (ip_send(nif,
|
||||
dest,
|
||||
ip_get_myip(nif_get_protocol_info(nif,ETH_FRM_IP)),
|
||||
IP_PROTO_UDP,
|
||||
pNbuf));
|
||||
}
|
||||
/********************************************************************/
|
||||
void
|
||||
udp_handler (NIF *nif, NBUF *pNbuf)
|
||||
{
|
||||
/*
|
||||
* This function handles incoming UDP packets
|
||||
*/
|
||||
udp_frame_hdr *udpframe;
|
||||
void (*handler)(NIF *, NBUF *);
|
||||
|
||||
udpframe = (udp_frame_hdr *)&pNbuf->data[pNbuf->offset];
|
||||
|
||||
/*
|
||||
* Adjust the length and valid data offset of the packet we are
|
||||
* passing on
|
||||
*/
|
||||
pNbuf->length -= UDP_HDR_SIZE;
|
||||
pNbuf->offset += UDP_HDR_SIZE;
|
||||
|
||||
/*
|
||||
* Traverse the list of bound ports to see if there is a higher
|
||||
* level protocol to pass the packet on to
|
||||
*/
|
||||
if ((handler = (void(*)(NIF*,NBUF*))udp_port_handler(UDP_DEST(udpframe))) != NULL)
|
||||
handler(nif, pNbuf);
|
||||
else
|
||||
{
|
||||
#ifdef DBUG_PRINT
|
||||
printf("Received UDP packet for non-supported port\n");
|
||||
#endif
|
||||
nbuf_free(pNbuf);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
/********************************************************************/
|
||||
|
||||
#endif /* #ifdef DBUG_NETWORK */
|
||||
@@ -39,6 +39,9 @@
|
||||
#include "ff.h"
|
||||
#include "s19reader.h"
|
||||
#include "dma.h"
|
||||
#include "eth.h"
|
||||
#include "nbuf.h"
|
||||
#include "nif.h"
|
||||
|
||||
/* imported routines */
|
||||
extern int mmu_init();
|
||||
@@ -56,6 +59,11 @@ extern uint8_t _EMUTOS[];
|
||||
extern uint8_t _EMUTOS_SIZE[];
|
||||
#define EMUTOS_SIZE ((uint32_t)_EMUTOS_SIZE) /* size of EmuTOS, in bytes */
|
||||
|
||||
NIF nif1;
|
||||
#ifdef MACHINE_M5484LITE
|
||||
NIF nif2;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* check if it is possible to transfer data to PIC
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user