added code to support FEC networking
This commit is contained in:
@@ -67,6 +67,7 @@ CSRCS= \
|
|||||||
bas_string.c \
|
bas_string.c \
|
||||||
BaS.c \
|
BaS.c \
|
||||||
cache.c \
|
cache.c \
|
||||||
|
mmu.c \
|
||||||
mmc.c \
|
mmc.c \
|
||||||
unicode.c \
|
unicode.c \
|
||||||
ff.c \
|
ff.c \
|
||||||
@@ -84,15 +85,18 @@ CSRCS= \
|
|||||||
MCD_dmaApi.c \
|
MCD_dmaApi.c \
|
||||||
MCD_tasks.c \
|
MCD_tasks.c \
|
||||||
MCD_tasksInit.c \
|
MCD_tasksInit.c \
|
||||||
\
|
|
||||||
usb.c \
|
usb.c \
|
||||||
ohci-hcd.c \
|
ohci-hcd.c \
|
||||||
ehci-hcd.c \
|
ehci-hcd.c \
|
||||||
usb_mouse.c \
|
usb_mouse.c \
|
||||||
\
|
|
||||||
ikbd.c \
|
ikbd.c \
|
||||||
\
|
\
|
||||||
fec.c\
|
nbuf.c \
|
||||||
|
queue.c \
|
||||||
|
nif.c \
|
||||||
|
fecbd.c \
|
||||||
|
fec.c \
|
||||||
|
udp.c \
|
||||||
\
|
\
|
||||||
basflash.c \
|
basflash.c \
|
||||||
basflash_start.c
|
basflash_start.c
|
||||||
@@ -101,7 +105,6 @@ ASRCS= \
|
|||||||
startcf.S \
|
startcf.S \
|
||||||
printf_helper.S \
|
printf_helper.S \
|
||||||
exceptions.S \
|
exceptions.S \
|
||||||
mmu.S \
|
|
||||||
xhdi_vec.S
|
xhdi_vec.S
|
||||||
|
|
||||||
SRCS=$(ASRCS) $(CSRCS)
|
SRCS=$(ASRCS) $(CSRCS)
|
||||||
@@ -155,8 +158,8 @@ $(foreach DIR,$(TRGTDIRS),$(eval $(call CC_TEMPLATE,$(DIR))))
|
|||||||
|
|
||||||
# rules for depend
|
# rules for depend
|
||||||
define DEP_TEMPLATE
|
define DEP_TEMPLATE
|
||||||
ifneq (clean,$(MAKECMDGOALS))
|
ifneq (clean,$$(MAKECMDGOALS))
|
||||||
-include $(1)/depend
|
include $(1)/depend
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq (firebee,$(1))
|
ifeq (firebee,$(1))
|
||||||
|
|||||||
@@ -50,6 +50,13 @@ SECTIONS
|
|||||||
OBJDIR/ehci-hcd.o(.text)
|
OBJDIR/ehci-hcd.o(.text)
|
||||||
OBJDIR/wait.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/unicode.o(.text)
|
||||||
OBJDIR/mmc.o(.text)
|
OBJDIR/mmc.o(.text)
|
||||||
OBJDIR/ff.o(.text)
|
OBJDIR/ff.o(.text)
|
||||||
|
|||||||
@@ -35,26 +35,13 @@ typedef struct
|
|||||||
|
|
||||||
/********************************************************************/
|
/********************************************************************/
|
||||||
|
|
||||||
void
|
extern void udp_init(void);
|
||||||
udp_init (void);
|
extern void udp_prime_port(uint16_t);
|
||||||
|
extern uint16_t udp_obtain_free_port(void);
|
||||||
void
|
extern void udp_bind_port( uint16_t, void (*)(NIF *,NBUF *));
|
||||||
udp_prime_port (uint16_t);
|
extern void udp_free_port(uint16_t);
|
||||||
|
extern int udp_send(NIF *, uint8_t *, int, int, NBUF *);
|
||||||
uint16_t
|
extern void udp_handler(NIF *, NBUF *);
|
||||||
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 *);
|
|
||||||
|
|
||||||
/********************************************************************/
|
/********************************************************************/
|
||||||
|
|
||||||
|
|||||||
33
BaS_gcc/net/bootp.c
Normal file
33
BaS_gcc/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 "dma.h"
|
||||||
#include "bas_string.h"
|
#include "bas_string.h"
|
||||||
#include "bas_printf.h"
|
#include "bas_printf.h"
|
||||||
|
#include "util.h"
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#if defined(MACHINE_FIREBEE)
|
#if defined(MACHINE_FIREBEE)
|
||||||
@@ -412,8 +413,8 @@ void fec_reset (uint8_t ch)
|
|||||||
MCF_FEC_ECR(ch) = MCF_FEC_ECR_RESET;
|
MCF_FEC_ECR(ch) = MCF_FEC_ECR_RESET;
|
||||||
|
|
||||||
/* Wait at least 8 clock cycles */
|
/* Wait at least 8 clock cycles */
|
||||||
for (i=0; i<10; ++i)
|
for (i = 0; i < 10; ++i)
|
||||||
nop();
|
NOP();
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************/
|
/********************************************************************/
|
||||||
|
|||||||
226
BaS_gcc/net/fecbd.c
Normal file
226
BaS_gcc/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);
|
||||||
|
}
|
||||||
@@ -4,13 +4,12 @@
|
|||||||
*
|
*
|
||||||
* Notes:
|
* Notes:
|
||||||
*/
|
*/
|
||||||
#include "src/include/dbug.h"
|
#include "queue.h"
|
||||||
#include "src/uif/net/queue.h"
|
#include "net.h"
|
||||||
#include "src/uif/net/net.h"
|
#include "driver_mem.h"
|
||||||
|
#include "exceptions.h"
|
||||||
#ifdef DBUG_NETWORK
|
#include "bas_types.h"
|
||||||
|
#include "bas_printf.h"
|
||||||
/********************************************************************/
|
|
||||||
/*
|
/*
|
||||||
* Queues used for network buffer storage
|
* 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
|
* this, the nbuf data is over-allocated and adjusted. The following
|
||||||
* array keeps track of the original data pointer returned by malloc
|
* 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
|
* Initialize all the network buffer queues
|
||||||
*
|
*
|
||||||
@@ -31,8 +29,7 @@ ADDRESS unaligned_buffers[NBUF_MAX];
|
|||||||
* 0 success
|
* 0 success
|
||||||
* 1 failure
|
* 1 failure
|
||||||
*/
|
*/
|
||||||
int
|
int nbuf_init(void)
|
||||||
nbuf_init(void)
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
NBUF *nbuf;
|
NBUF *nbuf;
|
||||||
@@ -47,22 +44,20 @@ nbuf_init(void)
|
|||||||
printf("Creating %d net buffers of %d bytes\n",NBUF_MAX,NBUF_SZ);
|
printf("Creating %d net buffers of %d bytes\n",NBUF_MAX,NBUF_SZ);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (i=0; i<NBUF_MAX; ++i)
|
for (i = 0; i < NBUF_MAX; ++i)
|
||||||
{
|
{
|
||||||
/* Allocate memory for the network buffer structure */
|
/* Allocate memory for the network buffer structure */
|
||||||
nbuf = (NBUF *)malloc(sizeof(NBUF));
|
nbuf = (NBUF *) driver_mem_alloc(sizeof(NBUF));
|
||||||
if (!nbuf)
|
if (!nbuf)
|
||||||
{
|
{
|
||||||
ASSERT(nbuf);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate memory for the actual data */
|
/* Allocate memory for the actual data */
|
||||||
unaligned_buffers[i] = (ADDRESS)malloc(NBUF_SZ + 16);
|
unaligned_buffers[i] = driver_mem_alloc(NBUF_SZ + 16);
|
||||||
nbuf->data = (uint8 *)((uint32)(unaligned_buffers[i] + 15) & 0xFFFFFFF0);
|
nbuf->data = (uint8_t *)((uint32_t)(unaligned_buffers[i] + 15) & 0xFFFFFFF0);
|
||||||
if (!nbuf->data)
|
if (!nbuf->data)
|
||||||
{
|
{
|
||||||
ASSERT(nbuf->data);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,32 +76,30 @@ nbuf_init(void)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/********************************************************************/
|
|
||||||
/*
|
/*
|
||||||
* Return all the allocated memory to the heap
|
* Return all the allocated memory to the heap
|
||||||
*/
|
*/
|
||||||
void
|
void nbuf_flush(void)
|
||||||
nbuf_flush(void)
|
|
||||||
{
|
{
|
||||||
NBUF *nbuf;
|
NBUF *nbuf;
|
||||||
int i, level = asm_set_ipl(7);
|
int i, level = set_ipl(7);
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
||||||
for (i=0; i<NBUF_MAX; ++i)
|
for (i = 0; i < NBUF_MAX; ++i)
|
||||||
free((uint8*)unaligned_buffers[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;
|
++n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ASSERT(n == NBUF_MAX);
|
set_ipl(level);
|
||||||
asm_set_ipl(level);
|
|
||||||
}
|
}
|
||||||
/********************************************************************/
|
|
||||||
/*
|
/*
|
||||||
* Allocate a network buffer from the free list
|
* Allocate a network buffer from the free list
|
||||||
*
|
*
|
||||||
@@ -114,96 +107,92 @@ nbuf_flush(void)
|
|||||||
* Pointer to a free network buffer
|
* Pointer to a free network buffer
|
||||||
* NULL if none are available
|
* NULL if none are available
|
||||||
*/
|
*/
|
||||||
NBUF *
|
NBUF *nbuf_alloc(void)
|
||||||
nbuf_alloc(void)
|
|
||||||
{
|
{
|
||||||
NBUF *nbuf;
|
NBUF *nbuf;
|
||||||
int level = asm_set_ipl(7);
|
int level = set_ipl(7);
|
||||||
|
|
||||||
|
nbuf = (NBUF *) queue_remove(&nbuf_queue[NBUF_FREE]);
|
||||||
|
set_ipl(level);
|
||||||
|
|
||||||
nbuf = (NBUF *)queue_remove(&nbuf_queue[NBUF_FREE]);
|
|
||||||
asm_set_ipl(level);
|
|
||||||
return nbuf;
|
return nbuf;
|
||||||
}
|
}
|
||||||
/********************************************************************/
|
|
||||||
/*
|
/*
|
||||||
* Add the specified network buffer back to the free list
|
* Add the specified network buffer back to the free list
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* nbuf Buffer to add back to the free list
|
* nbuf Buffer to add back to the free list
|
||||||
*/
|
*/
|
||||||
void
|
void nbuf_free(NBUF *nbuf)
|
||||||
nbuf_free(NBUF *nbuf)
|
|
||||||
{
|
{
|
||||||
int level = asm_set_ipl(7);
|
int level = set_ipl(7);
|
||||||
|
|
||||||
nbuf->offset = 0;
|
nbuf->offset = 0;
|
||||||
nbuf->length = NBUF_SZ;
|
nbuf->length = NBUF_SZ;
|
||||||
queue_add(&nbuf_queue[NBUF_FREE],(QNODE *)nbuf);
|
queue_add(&nbuf_queue[NBUF_FREE],(QNODE *)nbuf);
|
||||||
|
|
||||||
asm_set_ipl(level);
|
set_ipl(level);
|
||||||
}
|
}
|
||||||
/********************************************************************/
|
|
||||||
/*
|
/*
|
||||||
* Remove a network buffer from the specified queue
|
* Remove a network buffer from the specified queue
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* q The index that identifies the queue to pull the buffer from
|
* q The index that identifies the queue to pull the buffer from
|
||||||
*/
|
*/
|
||||||
NBUF *
|
NBUF *nbuf_remove(int q)
|
||||||
nbuf_remove(int q)
|
|
||||||
{
|
{
|
||||||
NBUF *nbuf;
|
NBUF *nbuf;
|
||||||
int level = asm_set_ipl(7);
|
int level = set_ipl(7);
|
||||||
|
|
||||||
|
nbuf = (NBUF *) queue_remove(&nbuf_queue[q]);
|
||||||
|
set_ipl(level);
|
||||||
|
|
||||||
nbuf = (NBUF *)queue_remove(&nbuf_queue[q]);
|
|
||||||
asm_set_ipl(level);
|
|
||||||
return nbuf;
|
return nbuf;
|
||||||
}
|
}
|
||||||
/********************************************************************/
|
|
||||||
/*
|
/*
|
||||||
* Add a network buffer to the specified queue
|
* Add a network buffer to the specified queue
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* q The index that identifies the queue to add the buffer to
|
* q The index that identifies the queue to add the buffer to
|
||||||
*/
|
*/
|
||||||
void
|
void nbuf_add(int q, NBUF *nbuf)
|
||||||
nbuf_add(int q, NBUF *nbuf)
|
|
||||||
{
|
{
|
||||||
int level = asm_set_ipl(7);
|
int level = set_ipl(7);
|
||||||
queue_add(&nbuf_queue[q],(QNODE *)nbuf);
|
queue_add(&nbuf_queue[q],(QNODE *)nbuf);
|
||||||
asm_set_ipl(level);
|
set_ipl(level);
|
||||||
}
|
}
|
||||||
/********************************************************************/
|
|
||||||
/*
|
/*
|
||||||
* Put all the network buffers back into the free list
|
* Put all the network buffers back into the free list
|
||||||
*/
|
*/
|
||||||
void
|
void nbuf_reset(void)
|
||||||
nbuf_reset(void)
|
|
||||||
{
|
{
|
||||||
NBUF *nbuf;
|
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)
|
while ((nbuf = nbuf_remove(i)) != NULL)
|
||||||
nbuf_free(nbuf);
|
nbuf_free(nbuf);
|
||||||
}
|
}
|
||||||
asm_set_ipl(level);
|
set_ipl(level);
|
||||||
}
|
}
|
||||||
/********************************************************************/
|
|
||||||
/*
|
/*
|
||||||
* Display all the nbuf queues
|
* Display all the nbuf queues
|
||||||
*/
|
*/
|
||||||
void
|
void nbuf_debug_dump(void)
|
||||||
nbuf_debug_dump(void)
|
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
NBUF *nbuf;
|
NBUF *nbuf;
|
||||||
int i, j, level;
|
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("\n\nQueue #%d\n\n",i);
|
||||||
printf("\tBuffer Location\tOffset\tLength\n");
|
printf("\tBuffer Location\tOffset\tLength\n");
|
||||||
@@ -219,9 +208,6 @@ nbuf_debug_dump(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
asm_set_ipl(level);
|
set_ipl(level);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
/********************************************************************/
|
|
||||||
|
|
||||||
#endif /* #ifdef DBUG_NETWORK */
|
|
||||||
|
|||||||
118
BaS_gcc/net/nif.c
Normal file
118
BaS_gcc/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
BaS_gcc/net/queue.c
Normal file
114
BaS_gcc/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
BaS_gcc/net/udp.c
Normal file
180
BaS_gcc/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 "ff.h"
|
||||||
#include "s19reader.h"
|
#include "s19reader.h"
|
||||||
#include "dma.h"
|
#include "dma.h"
|
||||||
|
#include "eth.h"
|
||||||
|
#include "nbuf.h"
|
||||||
|
#include "nif.h"
|
||||||
|
|
||||||
/* imported routines */
|
/* imported routines */
|
||||||
extern int mmu_init();
|
extern int mmu_init();
|
||||||
@@ -56,6 +59,11 @@ extern uint8_t _EMUTOS[];
|
|||||||
extern uint8_t _EMUTOS_SIZE[];
|
extern uint8_t _EMUTOS_SIZE[];
|
||||||
#define EMUTOS_SIZE ((uint32_t)_EMUTOS_SIZE) /* size of EmuTOS, in bytes */
|
#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
|
* check if it is possible to transfer data to PIC
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user