added more networking routines
This commit is contained in:
@@ -93,10 +93,13 @@ CSRCS= \
|
|||||||
\
|
\
|
||||||
nbuf.c \
|
nbuf.c \
|
||||||
queue.c \
|
queue.c \
|
||||||
|
net_timer.c \
|
||||||
nif.c \
|
nif.c \
|
||||||
fecbd.c \
|
fecbd.c \
|
||||||
fec.c \
|
fec.c \
|
||||||
|
ip.c \
|
||||||
udp.c \
|
udp.c \
|
||||||
|
arp.c \
|
||||||
\
|
\
|
||||||
basflash.c \
|
basflash.c \
|
||||||
basflash_start.c
|
basflash_start.c
|
||||||
|
|||||||
@@ -51,11 +51,14 @@ SECTIONS
|
|||||||
OBJDIR/wait.o(.text)
|
OBJDIR/wait.o(.text)
|
||||||
|
|
||||||
OBJDIR/nbuf.o(.text)
|
OBJDIR/nbuf.o(.text)
|
||||||
|
OBJDIR/net_timer.o(.text)
|
||||||
OBJDIR/queue.o(.text)
|
OBJDIR/queue.o(.text)
|
||||||
OBJDIR/nif.o(.text)
|
OBJDIR/nif.o(.text)
|
||||||
OBJDIR/fecbd.o(.text)
|
OBJDIR/fecbd.o(.text)
|
||||||
OBJDIR/fec.o(.text)
|
OBJDIR/fec.o(.text)
|
||||||
|
OBJDIR/ip.o(.text)
|
||||||
OBJDIR/udp.o(text)
|
OBJDIR/udp.o(text)
|
||||||
|
OBJDIR/arp.o(text)
|
||||||
|
|
||||||
OBJDIR/unicode.o(.text)
|
OBJDIR/unicode.o(.text)
|
||||||
OBJDIR/mmc.o(.text)
|
OBJDIR/mmc.o(.text)
|
||||||
|
|||||||
@@ -97,4 +97,11 @@
|
|||||||
|
|
||||||
extern int register_interrupt_handler(uint8_t source, uint8_t level, uint8_t priority, uint8_t intr, void (*handler)(void));
|
extern int register_interrupt_handler(uint8_t source, uint8_t level, uint8_t priority, uint8_t intr, void (*handler)(void));
|
||||||
|
|
||||||
|
#define ISR_DBUG_ISR 0x01
|
||||||
|
#define ISR_USER_ISR 0x02
|
||||||
|
|
||||||
|
extern void isr_init(void);
|
||||||
|
extern int isr_register_handler(int type, int vector, int (*handler)(void *, void *), void *hdev, void *harg);
|
||||||
|
extern void isr_remove_handler(int type ,int (*handler)(void *, void *));
|
||||||
|
extern bool isr_execute_handler(int vector);
|
||||||
#endif /* _INTERRUPTS_H_ */
|
#endif /* _INTERRUPTS_H_ */
|
||||||
|
|||||||
33
BaS_gcc/include/net_timer.h
Normal file
33
BaS_gcc/include/net_timer.h
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* File: net_timer.h
|
||||||
|
* Purpose: Provide a timer use by the dBUG network as a timeout
|
||||||
|
* indicator
|
||||||
|
*
|
||||||
|
* Notes:
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TIMER_H_
|
||||||
|
#define _TIMER_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t ch; /* which channel is this structure for? */
|
||||||
|
uint8_t lvl; /* Interrupt level for this channel */
|
||||||
|
uint8_t pri; /* Interrupt priority for this channel */
|
||||||
|
uint8_t reference; /* timeout indicator */
|
||||||
|
uint32_t gms; /* mode select register value */
|
||||||
|
uint16_t pre; /* prescale value */
|
||||||
|
uint16_t cnt; /* prescaled clocks for timeout */
|
||||||
|
} NET_TIMER;
|
||||||
|
|
||||||
|
|
||||||
|
extern bool timer_init(uint8_t, uint8_t, uint8_t);
|
||||||
|
|
||||||
|
/* Vector numbers for all the timer channels */
|
||||||
|
#define TIMER_VECTOR(x) (126-x)
|
||||||
|
|
||||||
|
#endif /* _TIMER_H_ */
|
||||||
462
BaS_gcc/net/arp.c
Normal file
462
BaS_gcc/net/arp.c
Normal file
@@ -0,0 +1,462 @@
|
|||||||
|
/*
|
||||||
|
* File: arp.c
|
||||||
|
* Purpose: Address Resolution Protocol routines.
|
||||||
|
*
|
||||||
|
* Notes:
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "net.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#define TIMER_NETWORK 0
|
||||||
|
|
||||||
|
static uint8_t *arp_find_pair(ARP_INFO *arptab, uint16_t protocol, uint8_t *hwa, uint8_t *pa)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This function searches through the ARP table for the
|
||||||
|
* specified <protocol,hwa> or <protocol,pa> address pair.
|
||||||
|
* If it is found, then a a pointer to the non-specified
|
||||||
|
* address is returned. Otherwise NULL is returned.
|
||||||
|
* If you pass in <protocol,pa> then you get <hwa> out.
|
||||||
|
* If you pass in <protocol,hwa> then you get <pa> out.
|
||||||
|
*/
|
||||||
|
int slot, i, match = false;
|
||||||
|
uint8_t *rvalue;
|
||||||
|
|
||||||
|
if (((hwa == 0) && (pa == 0)) || (arptab == 0))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
rvalue = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check each protocol address for a match
|
||||||
|
*/
|
||||||
|
for (slot = 0; slot < arptab->tab_size; slot++)
|
||||||
|
{
|
||||||
|
if ((arptab->table[slot].longevity != ARP_ENTRY_EMPTY) &&
|
||||||
|
(arptab->table[slot].protocol == protocol))
|
||||||
|
{
|
||||||
|
match = true;
|
||||||
|
if (hwa != 0)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Check the Hardware Address field
|
||||||
|
*/
|
||||||
|
rvalue = &arptab->table[slot].pa[0];
|
||||||
|
for (i = 0; i < arptab->table[slot].hwa_size; i++)
|
||||||
|
{
|
||||||
|
if (arptab->table[slot].hwa[i] != hwa[i])
|
||||||
|
{
|
||||||
|
match = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Check the Protocol Address field
|
||||||
|
*/
|
||||||
|
rvalue = &arptab->table[slot].hwa[0];
|
||||||
|
for (i = 0; i < arptab->table[slot].pa_size; i++)
|
||||||
|
{
|
||||||
|
if (arptab->table[slot].pa[i] != pa[i])
|
||||||
|
{
|
||||||
|
match = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (match)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match)
|
||||||
|
return rvalue;
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void arp_merge(ARP_INFO *arptab, uint16_t protocol, int hwa_size, uint8_t *hwa,
|
||||||
|
int pa_size, uint8_t *pa, int longevity)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This function merges an entry into the ARP table. If
|
||||||
|
* either piece is NULL, the function exits, otherwise
|
||||||
|
* the entry is merged or added, provided there is space.
|
||||||
|
*/
|
||||||
|
int i, slot;
|
||||||
|
uint8_t *ta;
|
||||||
|
|
||||||
|
if ((hwa == NULL) || (pa == NULL) || (arptab == NULL) ||
|
||||||
|
((longevity != ARP_ENTRY_TEMP) &&
|
||||||
|
(longevity != ARP_ENTRY_PERM)))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* First search ARP table for existing entry */
|
||||||
|
if ((ta = arp_find_pair(arptab,protocol,NULL,pa)) != 0)
|
||||||
|
{
|
||||||
|
/* Update hardware address */
|
||||||
|
for (i = 0; i < hwa_size; i++)
|
||||||
|
ta[i] = hwa[i];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Next try to find an empty slot */
|
||||||
|
slot = -1;
|
||||||
|
for (i = 0; i < MAX_ARP_ENTRY; i++)
|
||||||
|
{
|
||||||
|
if (arptab->table[i].longevity == ARP_ENTRY_EMPTY)
|
||||||
|
{
|
||||||
|
slot = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if no empty slot was found, pick a temp slot */
|
||||||
|
if (slot == -1)
|
||||||
|
{
|
||||||
|
for (i = 0; i < MAX_ARP_ENTRY; i++)
|
||||||
|
{
|
||||||
|
if (arptab->table[i].longevity == ARP_ENTRY_TEMP)
|
||||||
|
{
|
||||||
|
slot = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if after all this, still no slot found, add in last slot */
|
||||||
|
if (slot == -1)
|
||||||
|
slot = (MAX_ARP_ENTRY -1);
|
||||||
|
|
||||||
|
/* add the entry into the slot */
|
||||||
|
arptab->table[slot].protocol = protocol;
|
||||||
|
|
||||||
|
arptab->table[slot].hwa_size = (uint8_t) hwa_size;
|
||||||
|
for (i = 0; i < hwa_size; i++)
|
||||||
|
arptab->table[slot].hwa[i] = hwa[i];
|
||||||
|
|
||||||
|
arptab->table[slot].pa_size = (uint8_t) pa_size;
|
||||||
|
for (i = 0; i < pa_size; i++)
|
||||||
|
arptab->table[slot].pa[i] = pa[i];
|
||||||
|
|
||||||
|
arptab->table[slot].longevity = longevity;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void arp_remove(ARP_INFO *arptab, uint16_t protocol, uint8_t *hwa, uint8_t *pa)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This function removes an entry from the ARP table. The
|
||||||
|
* ARP table is searched according to the non-NULL address
|
||||||
|
* that is provided.
|
||||||
|
*/
|
||||||
|
int slot, i, match;
|
||||||
|
|
||||||
|
if (((hwa == 0) && (pa == 0)) || (arptab == 0))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* check each hardware adress for a match */
|
||||||
|
for (slot = 0; slot < arptab->tab_size; slot++)
|
||||||
|
{
|
||||||
|
if ((arptab->table[slot].longevity != ARP_ENTRY_EMPTY) &&
|
||||||
|
(arptab->table[slot].protocol == protocol))
|
||||||
|
{
|
||||||
|
match = true;
|
||||||
|
if (hwa != 0)
|
||||||
|
{
|
||||||
|
/* Check Hardware Address field */
|
||||||
|
for (i = 0; i < arptab->table[slot].hwa_size; i++)
|
||||||
|
{
|
||||||
|
if (arptab->table[slot].hwa[i] != hwa[i])
|
||||||
|
{
|
||||||
|
match = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Check Protocol Address field */
|
||||||
|
for (i = 0; i < arptab->table[slot].pa_size; i++)
|
||||||
|
{
|
||||||
|
if (arptab->table[slot].pa[i] != pa[i])
|
||||||
|
{
|
||||||
|
match = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (match)
|
||||||
|
{
|
||||||
|
for (i = 0; i < arptab->table[slot].hwa_size; i++)
|
||||||
|
arptab->table[slot].hwa[i] = 0;
|
||||||
|
for (i = 0; i < arptab->table[slot].pa_size; i++)
|
||||||
|
arptab->table[slot].pa[i] = 0;
|
||||||
|
arptab->table[slot].longevity = ARP_ENTRY_EMPTY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void arp_request(NIF *nif, uint8_t *pa)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This function broadcasts an ARP request for the protocol
|
||||||
|
* address "pa"
|
||||||
|
*/
|
||||||
|
uint8_t *addr;
|
||||||
|
NBUF *pNbuf;
|
||||||
|
arp_frame_hdr *arpframe;
|
||||||
|
int i, result;
|
||||||
|
|
||||||
|
pNbuf = nbuf_alloc();
|
||||||
|
if (pNbuf == NULL)
|
||||||
|
{
|
||||||
|
#if defined(DEBUG_PRINT)
|
||||||
|
printf("ARP: arp_request couldn't allocate Tx buffer\n");
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
arpframe = (arp_frame_hdr *)&pNbuf->data[ARP_HDR_OFFSET];
|
||||||
|
|
||||||
|
/* Build the ARP request packet */
|
||||||
|
arpframe->ar_hrd = ETHERNET;
|
||||||
|
arpframe->ar_pro = ETH_FRM_IP;
|
||||||
|
arpframe->ar_hln = 6;
|
||||||
|
arpframe->ar_pln = 4;
|
||||||
|
arpframe->opcode = ARP_REQUEST;
|
||||||
|
|
||||||
|
addr = &nif->hwa[0];
|
||||||
|
for (i = 0; i < 6; i++)
|
||||||
|
arpframe->ar_sha[i] = addr[i];
|
||||||
|
|
||||||
|
addr = ip_get_myip(nif_get_protocol_info(nif,ETH_FRM_IP));
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
arpframe->ar_spa[i] = addr[i];
|
||||||
|
|
||||||
|
for (i = 0; i < 6; i++)
|
||||||
|
arpframe->ar_tha[i] = 0x00;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
arpframe->ar_tpa[i] = pa[i];
|
||||||
|
|
||||||
|
pNbuf->length = ARP_HDR_LEN;
|
||||||
|
|
||||||
|
/* Send the ARP request */
|
||||||
|
result = nif->send(nif, nif->broadcast, nif->hwa, ETH_FRM_ARP, pNbuf);
|
||||||
|
|
||||||
|
if (result == 0)
|
||||||
|
nbuf_free(pNbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int arp_resolve_pa(NIF *nif, uint16_t protocol, uint8_t *pa, uint8_t **ha)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This function accepts a pointer to a protocol address and
|
||||||
|
* searches the ARP table for a hardware address match. If no
|
||||||
|
* no match found, false is returned.
|
||||||
|
*/
|
||||||
|
ARP_INFO *arptab;
|
||||||
|
|
||||||
|
if ((pa == NULL) || (nif == NULL) || (protocol == 0))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
arptab = nif_get_protocol_info (nif,ETH_FRM_ARP);
|
||||||
|
*ha = arp_find_pair(arptab,protocol,0,pa);
|
||||||
|
|
||||||
|
if (*ha == NULL)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *arp_resolve(NIF *nif, uint16_t protocol, uint8_t *pa)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uint8_t *hwa;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check to see if the necessary MAC-to-IP translation information
|
||||||
|
* is in table already
|
||||||
|
*/
|
||||||
|
if (arp_resolve_pa (nif, protocol, pa, &hwa))
|
||||||
|
return hwa;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ok, it's not, so we need to try to obtain it by broadcasting
|
||||||
|
* an ARP request. Hopefully the desired host is listening and
|
||||||
|
* will respond with it's MAC address
|
||||||
|
*/
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
arp_request (nif, pa);
|
||||||
|
|
||||||
|
timer_set_secs(TIMER_NETWORK, ARP_TIMEOUT);
|
||||||
|
while (timer_get_reference(TIMER_NETWORK))
|
||||||
|
{
|
||||||
|
if (arp_resolve_pa (nif, protocol, pa, &hwa))
|
||||||
|
return hwa;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void arp_init(ARP_INFO *arptab)
|
||||||
|
{
|
||||||
|
int slot, i;
|
||||||
|
|
||||||
|
arptab->tab_size = MAX_ARP_ENTRY;
|
||||||
|
for (slot = 0; slot < arptab->tab_size; slot++)
|
||||||
|
{
|
||||||
|
for (i = 0; i < MAX_HWA_SIZE; i++)
|
||||||
|
arptab->table[slot].hwa[i] = 0;
|
||||||
|
for (i = 0; i < MAX_PA_SIZE; i++)
|
||||||
|
arptab->table[slot].pa[i] = 0;
|
||||||
|
arptab->table[slot].longevity = ARP_ENTRY_EMPTY;
|
||||||
|
arptab->table[slot].hwa_size = 0;
|
||||||
|
arptab->table[slot].pa_size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void arp_handler(NIF *nif, NBUF *pNbuf)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* ARP protocol handler
|
||||||
|
*/
|
||||||
|
uint8_t *addr;
|
||||||
|
ARP_INFO *arptab;
|
||||||
|
int longevity;
|
||||||
|
arp_frame_hdr *rx_arpframe, *tx_arpframe;
|
||||||
|
|
||||||
|
arptab = nif_get_protocol_info(nif, ETH_FRM_ARP);
|
||||||
|
rx_arpframe = (arp_frame_hdr *) &pNbuf->data[pNbuf->offset];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for an appropriate ARP packet
|
||||||
|
*/
|
||||||
|
if ((pNbuf->length < ARP_HDR_LEN) ||
|
||||||
|
(rx_arpframe->ar_hrd != ETHERNET) ||
|
||||||
|
(rx_arpframe->ar_hln != 6) ||
|
||||||
|
(rx_arpframe->ar_pro != ETH_FRM_IP) ||
|
||||||
|
(rx_arpframe->ar_pln != 4))
|
||||||
|
{
|
||||||
|
nbuf_free(pNbuf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check to see if it was addressed to me - if it was, keep this
|
||||||
|
* ARP entry in the table permanently; if not, mark it so that it
|
||||||
|
* can be displaced later if necessary
|
||||||
|
*/
|
||||||
|
addr = ip_get_myip(nif_get_protocol_info(nif,ETH_FRM_IP));
|
||||||
|
if ((rx_arpframe->ar_tpa[0] == addr[0]) &&
|
||||||
|
(rx_arpframe->ar_tpa[1] == addr[1]) &&
|
||||||
|
(rx_arpframe->ar_tpa[2] == addr[2]) &&
|
||||||
|
(rx_arpframe->ar_tpa[3] == addr[3]) )
|
||||||
|
{
|
||||||
|
longevity = ARP_ENTRY_PERM;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
longevity = ARP_ENTRY_TEMP;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add ARP info into the table
|
||||||
|
*/
|
||||||
|
arp_merge(arptab,
|
||||||
|
rx_arpframe->ar_pro,
|
||||||
|
rx_arpframe->ar_hln,
|
||||||
|
&rx_arpframe->ar_sha[0],
|
||||||
|
rx_arpframe->ar_pln,
|
||||||
|
&rx_arpframe->ar_spa[0],
|
||||||
|
longevity
|
||||||
|
);
|
||||||
|
|
||||||
|
switch (rx_arpframe->opcode)
|
||||||
|
{
|
||||||
|
case ARP_REQUEST:
|
||||||
|
/*
|
||||||
|
* Check to see if request is directed to me
|
||||||
|
*/
|
||||||
|
if ((rx_arpframe->ar_tpa[0] == addr[0]) &&
|
||||||
|
(rx_arpframe->ar_tpa[1] == addr[1]) &&
|
||||||
|
(rx_arpframe->ar_tpa[2] == addr[2]) &&
|
||||||
|
(rx_arpframe->ar_tpa[3] == addr[3]) )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Reuse the current network buffer to assemble an ARP reply
|
||||||
|
*/
|
||||||
|
tx_arpframe = (arp_frame_hdr *)&pNbuf->data[ARP_HDR_OFFSET];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Build new ARP frame from the received data
|
||||||
|
*/
|
||||||
|
tx_arpframe->ar_hrd = ETHERNET;
|
||||||
|
tx_arpframe->ar_pro = ETH_FRM_IP;
|
||||||
|
tx_arpframe->ar_hln = 6;
|
||||||
|
tx_arpframe->ar_pln = 4;
|
||||||
|
tx_arpframe->opcode = ARP_REPLY;
|
||||||
|
tx_arpframe->ar_tha[0] = rx_arpframe->ar_sha[0];
|
||||||
|
tx_arpframe->ar_tha[1] = rx_arpframe->ar_sha[1];
|
||||||
|
tx_arpframe->ar_tha[2] = rx_arpframe->ar_sha[2];
|
||||||
|
tx_arpframe->ar_tha[3] = rx_arpframe->ar_sha[3];
|
||||||
|
tx_arpframe->ar_tha[4] = rx_arpframe->ar_sha[4];
|
||||||
|
tx_arpframe->ar_tha[5] = rx_arpframe->ar_sha[5];
|
||||||
|
tx_arpframe->ar_tpa[0] = rx_arpframe->ar_spa[0];
|
||||||
|
tx_arpframe->ar_tpa[1] = rx_arpframe->ar_spa[1];
|
||||||
|
tx_arpframe->ar_tpa[2] = rx_arpframe->ar_spa[2];
|
||||||
|
tx_arpframe->ar_tpa[3] = rx_arpframe->ar_spa[3];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now copy in the new information
|
||||||
|
*/
|
||||||
|
addr = &nif->hwa[0];
|
||||||
|
tx_arpframe->ar_sha[0] = addr[0];
|
||||||
|
tx_arpframe->ar_sha[1] = addr[1];
|
||||||
|
tx_arpframe->ar_sha[2] = addr[2];
|
||||||
|
tx_arpframe->ar_sha[3] = addr[3];
|
||||||
|
tx_arpframe->ar_sha[4] = addr[4];
|
||||||
|
tx_arpframe->ar_sha[5] = addr[5];
|
||||||
|
|
||||||
|
addr = ip_get_myip(nif_get_protocol_info(nif,ETH_FRM_IP));
|
||||||
|
tx_arpframe->ar_spa[0] = addr[0];
|
||||||
|
tx_arpframe->ar_spa[1] = addr[1];
|
||||||
|
tx_arpframe->ar_spa[2] = addr[2];
|
||||||
|
tx_arpframe->ar_spa[3] = addr[3];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save the length of my packet in the buffer structure
|
||||||
|
*/
|
||||||
|
pNbuf->length = ARP_HDR_LEN;
|
||||||
|
|
||||||
|
nif->send(nif,
|
||||||
|
&tx_arpframe->ar_tha[0],
|
||||||
|
&tx_arpframe->ar_sha[0],
|
||||||
|
ETH_FRM_ARP,
|
||||||
|
pNbuf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
nbuf_free(pNbuf);
|
||||||
|
break;
|
||||||
|
case ARP_REPLY:
|
||||||
|
/*
|
||||||
|
* The ARP Reply case is already taken care of
|
||||||
|
*/
|
||||||
|
default:
|
||||||
|
nbuf_free(pNbuf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
293
BaS_gcc/net/ip.c
Normal file
293
BaS_gcc/net/ip.c
Normal file
@@ -0,0 +1,293 @@
|
|||||||
|
/*
|
||||||
|
* File: ip.c
|
||||||
|
* Purpose: Internet Protcol device driver
|
||||||
|
*
|
||||||
|
* Notes:
|
||||||
|
*
|
||||||
|
* Modifications:
|
||||||
|
*/
|
||||||
|
#include "net.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
|
||||||
|
void ip_init(IP_INFO *info, IP_ADDR_P myip, IP_ADDR_P gateway, IP_ADDR_P netmask)
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
|
||||||
|
for (index = 0; index < sizeof(IP_ADDR); index++)
|
||||||
|
{
|
||||||
|
info->myip[index] = myip[index];
|
||||||
|
info->gateway[index] = gateway[index];
|
||||||
|
info->netmask[index] = netmask[index];
|
||||||
|
info->broadcast[index] = 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
info->rx = 0;
|
||||||
|
info->rx_unsup = 0;
|
||||||
|
info->tx = 0;
|
||||||
|
info->err = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *ip_get_myip(IP_INFO *info)
|
||||||
|
{
|
||||||
|
if (info != 0)
|
||||||
|
{
|
||||||
|
return (uint8_t *) &info->myip[0];
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ip_addr_compare(IP_ADDR_P addr1, IP_ADDR_P addr2)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(IP_ADDR); i++)
|
||||||
|
{
|
||||||
|
if (addr1[i] != addr2[i])
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *ip_resolve_route(NIF *nif, IP_ADDR_P destip)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This function determines whether or not an outgoing IP
|
||||||
|
* packet needs to be transmitted on the local net or sent
|
||||||
|
* to the router for transmission.
|
||||||
|
*/
|
||||||
|
IP_INFO *info;
|
||||||
|
IP_ADDR mask,result;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
info = nif_get_protocol_info(nif,ETH_FRM_IP);
|
||||||
|
|
||||||
|
/* create mask for local IP */
|
||||||
|
for (i = 0; i < sizeof(IP_ADDR); i++)
|
||||||
|
{
|
||||||
|
mask[i] = info->myip[i] & info->netmask[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* apply mask to the destination IP */
|
||||||
|
for (i = 0; i < sizeof(IP_ADDR); i++)
|
||||||
|
{
|
||||||
|
result[i] = mask[i] & destip[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* See if destination IP is local or not */
|
||||||
|
if (ip_addr_compare(mask,result))
|
||||||
|
{
|
||||||
|
/* The destination IP is on the local net */
|
||||||
|
return arp_resolve(nif,ETH_FRM_IP,destip);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The destination IP is not on the local net */
|
||||||
|
return arp_resolve(nif,ETH_FRM_IP,info->gateway);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ip_send(NIF *nif, uint8_t *dest, uint8_t *src, uint8_t protocol, NBUF *pNbuf)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This function assembles an IP datagram and passes it
|
||||||
|
* onto the hardware to be sent over the network.
|
||||||
|
*/
|
||||||
|
uint8_t *route;
|
||||||
|
ip_frame_hdr *ipframe;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Construct the IP header
|
||||||
|
*/
|
||||||
|
ipframe = (ip_frame_hdr*) &pNbuf->data[IP_HDR_OFFSET];
|
||||||
|
|
||||||
|
/* IP version 4, Internet Header Length of 5 32-bit words */
|
||||||
|
ipframe->version_ihl = 0x45;
|
||||||
|
|
||||||
|
/* Type of Service == 0, normal and routine */
|
||||||
|
ipframe->service_type = 0x00;
|
||||||
|
|
||||||
|
/* Total length of data */
|
||||||
|
ipframe->total_length = (uint16_t) (pNbuf->length + IP_HDR_SIZE);
|
||||||
|
|
||||||
|
/* User defined identification */
|
||||||
|
ipframe->identification = 0x0000;
|
||||||
|
|
||||||
|
/* Fragment Flags and Offset -- Don't fragment, last frag */
|
||||||
|
ipframe->flags_frag_offset = 0x0000;
|
||||||
|
|
||||||
|
/* Time To Live */
|
||||||
|
ipframe->ttl = 0xFF;
|
||||||
|
|
||||||
|
/* Protocol */
|
||||||
|
ipframe->protocol = protocol;
|
||||||
|
|
||||||
|
/* Checksum, computed later, zeroed for computation */
|
||||||
|
ipframe->checksum = 0x0000;
|
||||||
|
|
||||||
|
/* source IP address */
|
||||||
|
ipframe->source_addr[0] = src[0];
|
||||||
|
ipframe->source_addr[1] = src[1];
|
||||||
|
ipframe->source_addr[2] = src[2];
|
||||||
|
ipframe->source_addr[3] = src[3];
|
||||||
|
|
||||||
|
/* dest IP address */
|
||||||
|
ipframe->dest_addr[0] = dest[0];
|
||||||
|
ipframe->dest_addr[1] = dest[1];
|
||||||
|
ipframe->dest_addr[2] = dest[2];
|
||||||
|
ipframe->dest_addr[3] = dest[3];
|
||||||
|
|
||||||
|
/* Compute checksum */
|
||||||
|
ipframe->checksum = ip_chksum((uint16_t *) ipframe, IP_HDR_SIZE);
|
||||||
|
|
||||||
|
/* Increment the packet length by the size of the IP header */
|
||||||
|
pNbuf->length += IP_HDR_SIZE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine the hardware address of the recipient
|
||||||
|
*/
|
||||||
|
route = ip_resolve_route(nif, dest);
|
||||||
|
if (route == NULL)
|
||||||
|
{
|
||||||
|
xprintf("Unable to locate %d.%d.%d.%d\n",
|
||||||
|
dest[0],dest[1],dest[2],dest[3]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nif->send(nif,
|
||||||
|
route,
|
||||||
|
&nif->hwa[0],
|
||||||
|
ETH_FRM_IP,
|
||||||
|
pNbuf
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(DEBUG_PRINT)
|
||||||
|
void
|
||||||
|
dump_ip_frame (ip_frame_hdr *ipframe)
|
||||||
|
{
|
||||||
|
printf("Version: %02X\n", ((ipframe->version_ihl & 0x00f0) >> 4));
|
||||||
|
printf("IHL: %02X\n", ipframe->version_ihl & 0x000f);
|
||||||
|
printf("Service: %02X\n", ipframe->service_type);
|
||||||
|
printf("Length: %04X\n", ipframe->total_length);
|
||||||
|
printf("Ident: %04X\n", ipframe->identification);
|
||||||
|
printf("Flags: %02X\n", ((ipframe->flags_frag_offset & 0xC000) >> 14));
|
||||||
|
printf("Frag: %04X\n", ipframe->flags_frag_offset & 0x3FFF);
|
||||||
|
printf("TTL: %02X\n", ipframe->ttl);
|
||||||
|
printf("Protocol: %02X\n", ipframe->protocol);
|
||||||
|
printf("Chksum: %04X\n", ipframe->checksum);
|
||||||
|
printf("Source : %d.%d.%d.%d\n",
|
||||||
|
ipframe->source_addr[0],
|
||||||
|
ipframe->source_addr[1],
|
||||||
|
ipframe->source_addr[2],
|
||||||
|
ipframe->source_addr[3]);
|
||||||
|
printf("Dest : %d.%d.%d.%d\n",
|
||||||
|
ipframe->dest_addr[0],
|
||||||
|
ipframe->dest_addr[1],
|
||||||
|
ipframe->dest_addr[2],
|
||||||
|
ipframe->dest_addr[3]);
|
||||||
|
printf("Options: %08X\n", ipframe->options);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t ip_chksum(uint16_t *data, int num)
|
||||||
|
{
|
||||||
|
int chksum, ichksum;
|
||||||
|
uint16_t temp;
|
||||||
|
|
||||||
|
chksum = 0;
|
||||||
|
num = num >> 1; /* from bytes to words */
|
||||||
|
for (; num; num--, data++)
|
||||||
|
{
|
||||||
|
temp = *data;
|
||||||
|
ichksum = chksum + temp;
|
||||||
|
ichksum = ichksum & 0x0000FFFF;
|
||||||
|
if ((ichksum < temp) || (ichksum < chksum))
|
||||||
|
{
|
||||||
|
ichksum += 1;
|
||||||
|
ichksum = ichksum & 0x0000FFFF;
|
||||||
|
}
|
||||||
|
chksum = ichksum;
|
||||||
|
}
|
||||||
|
return (uint16_t) ~chksum;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int validate_ip_hdr(NIF *nif, ip_frame_hdr *ipframe)
|
||||||
|
{
|
||||||
|
int index, chksum;
|
||||||
|
IP_INFO *info;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check the IP Version
|
||||||
|
*/
|
||||||
|
if (IP_VERSION(ipframe) != 4)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check Internet Header Length
|
||||||
|
*/
|
||||||
|
if (IP_IHL(ipframe) < 5)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check the destination IP address
|
||||||
|
*/
|
||||||
|
info = nif_get_protocol_info(nif,ETH_FRM_IP);
|
||||||
|
for (index = 0; index < sizeof(IP_ADDR); index++)
|
||||||
|
if (info->myip[index] != ipframe->dest_addr[index])
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check the checksum
|
||||||
|
*/
|
||||||
|
chksum = (int)((uint16_t) IP_CHKSUM(ipframe));
|
||||||
|
IP_CHKSUM(ipframe) = 0;
|
||||||
|
|
||||||
|
if (ip_chksum((uint16_t *) ipframe,IP_IHL(ipframe)*4) != chksum)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
IP_CHKSUM(ipframe) = (uint16_t) chksum;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ip_handler(NIF *nif, NBUF *pNbuf)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* IP packet handler
|
||||||
|
*/
|
||||||
|
ip_frame_hdr *ipframe;
|
||||||
|
|
||||||
|
ipframe = (ip_frame_hdr *)&pNbuf->data[pNbuf->offset];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Verify valid IP header and destination IP
|
||||||
|
*/
|
||||||
|
if (!validate_ip_hdr(nif,ipframe))
|
||||||
|
{
|
||||||
|
nbuf_free(pNbuf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pNbuf->offset += (IP_IHL(ipframe) * 4);
|
||||||
|
pNbuf->length = (uint16_t)(IP_LENGTH(ipframe) - (IP_IHL(ipframe) * 4));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Call the appriopriate handler
|
||||||
|
*/
|
||||||
|
switch (IP_PROTOCOL(ipframe))
|
||||||
|
{
|
||||||
|
case IP_PROTO_ICMP:
|
||||||
|
// FIXME: icmp_handler(nif,pNbuf);
|
||||||
|
break;
|
||||||
|
case IP_PROTO_UDP:
|
||||||
|
udp_handler(nif,pNbuf);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
nbuf_free(pNbuf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
176
BaS_gcc/net/net_timer.c
Normal file
176
BaS_gcc/net/net_timer.c
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
/*
|
||||||
|
* File: net_timer.c
|
||||||
|
* Purpose: Provide a timer use by the dBUG network as a timeout
|
||||||
|
* indicator
|
||||||
|
*
|
||||||
|
* Notes:
|
||||||
|
*/
|
||||||
|
#include "net_timer.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "MCF5475.h"
|
||||||
|
#include "interrupts.h"
|
||||||
|
|
||||||
|
#if defined(MACHINE_FIREBEE)
|
||||||
|
#include "firebee.h"
|
||||||
|
#elif defined(MACHINE_M5484LITE)
|
||||||
|
#include "m5484l.h"
|
||||||
|
#else
|
||||||
|
#error unknown machine!
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static NET_TIMER net_timer[4] = {{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, 0}};
|
||||||
|
|
||||||
|
|
||||||
|
int timer_default_isr(void *not_used, NET_TIMER *t)
|
||||||
|
{
|
||||||
|
(void) not_used;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clear the pending event
|
||||||
|
*/
|
||||||
|
MCF_GPT_GMS(t->ch) = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clear the reference - the desired seconds have expired
|
||||||
|
*/
|
||||||
|
t->reference = 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void timer_irq_enable(uint8_t ch)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Setup the appropriate ICR
|
||||||
|
*/
|
||||||
|
MCF_INTC_ICR(TIMER_VECTOR(ch) - 64) =
|
||||||
|
(uint8_t)(0
|
||||||
|
| MCF_INTC_ICR_IP(net_timer[ch].pri)
|
||||||
|
| MCF_INTC_ICR_IL(net_timer[ch].lvl));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unmask the FEC interrupt in the interrupt controller
|
||||||
|
*/
|
||||||
|
if (ch == 3)
|
||||||
|
MCF_INTC_IMRH &= ~MCF_INTC_IMRH_INT_MASK59;
|
||||||
|
else if (ch == 2)
|
||||||
|
MCF_INTC_IMRH &= ~MCF_INTC_IMRH_INT_MASK60;
|
||||||
|
else if (ch == 1)
|
||||||
|
MCF_INTC_IMRH &= ~MCF_INTC_IMRH_INT_MASK61;
|
||||||
|
else
|
||||||
|
MCF_INTC_IMRH &= ~MCF_INTC_IMRH_INT_MASK62;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool timer_set_secs(uint8_t ch, uint32_t secs)
|
||||||
|
{
|
||||||
|
uint16_t timeout;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset the timer
|
||||||
|
*/
|
||||||
|
MCF_GPT_GMS(ch) = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the timeout in seconds
|
||||||
|
*/
|
||||||
|
timeout = (uint16_t)(secs * net_timer[ch].cnt);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the reference indicating that we have not yet reached the
|
||||||
|
* desired timeout
|
||||||
|
*/
|
||||||
|
net_timer[ch].reference = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enable timer interrupt to the processor
|
||||||
|
*/
|
||||||
|
timer_irq_enable(ch);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enable the timer using the pre-calculated values
|
||||||
|
*/
|
||||||
|
MCF_GPT_GCIR(ch) = (0
|
||||||
|
| MCF_GPT_GCIR_CNT(timeout)
|
||||||
|
| MCF_GPT_GCIR_PRE(net_timer[ch].pre)
|
||||||
|
);
|
||||||
|
MCF_GPT_GMS(ch) = net_timer[ch].gms;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t timer_get_reference(uint8_t ch)
|
||||||
|
{
|
||||||
|
return (uint32_t) net_timer[ch].reference;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool timer_init(uint8_t ch, uint8_t lvl, uint8_t pri)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Initialize the timer to expire after one second
|
||||||
|
*
|
||||||
|
* This routine should only be called by the project (board) specific
|
||||||
|
* initialization code.
|
||||||
|
*/
|
||||||
|
if (!((ch <= 3) && (lvl <= 7) && (lvl >= 1) && (pri <= 7)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset the timer
|
||||||
|
*/
|
||||||
|
MCF_GPT_GMS(ch) = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save off the channel, and interrupt lvl/pri information
|
||||||
|
*/
|
||||||
|
net_timer[ch].ch = ch;
|
||||||
|
net_timer[ch].lvl = lvl;
|
||||||
|
net_timer[ch].pri = pri;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Register the timer interrupt handler
|
||||||
|
*/
|
||||||
|
if (!isr_register_handler(ISR_DBUG_ISR,
|
||||||
|
TIMER_VECTOR(ch),
|
||||||
|
(int (*)(void *,void *)) timer_default_isr,
|
||||||
|
NULL,
|
||||||
|
(void *) &net_timer[ch])
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculate the require CNT value to get a 1 second timeout
|
||||||
|
*
|
||||||
|
* 1 sec = CNT * Clk Period * PRE
|
||||||
|
* CNT = 1 sec / (Clk Period * PRE)
|
||||||
|
* CNT = Clk Freq / PRE
|
||||||
|
*
|
||||||
|
* The system clock frequency is defined as SYSTEM_CLOCK and
|
||||||
|
* is given in MHz. We need to multiple it by 1000000 to get the
|
||||||
|
* true value. If we assume PRE to be the maximum of 0xFFFF,
|
||||||
|
* then the CNT value needed to achieve a 1 second timeout is
|
||||||
|
* given by:
|
||||||
|
*
|
||||||
|
* CNT = SYSTEM_CLOCK * (1000000/0xFFFF)
|
||||||
|
*/
|
||||||
|
net_timer[ch].pre = 0xFFFF;
|
||||||
|
net_timer[ch].cnt = (uint16_t) (SYSCLK * (1000000 / 0xFFFF));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save off the appropriate mode select register value
|
||||||
|
*/
|
||||||
|
net_timer[ch].gms = (0
|
||||||
|
| MCF_GPT_GMS_TMS_GPIO
|
||||||
|
| MCF_GPT_GMS_IEN
|
||||||
|
| MCF_GPT_GMS_SC
|
||||||
|
| MCF_GPT_GMS_CE
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -9,30 +9,22 @@
|
|||||||
*/
|
*/
|
||||||
#include "bas_types.h"
|
#include "bas_types.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
#ifdef DBUG_NETWORK
|
|
||||||
|
|
||||||
/********************************************************************/
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
void (*handler)(NIF *, NBUF *);
|
void (*handler)(NIF *, NBUF *);
|
||||||
} UDP_BOUND_PORT;
|
} UDP_BOUND_PORT;
|
||||||
|
|
||||||
/********************************************************************/
|
|
||||||
|
|
||||||
#define UDP_MAX_PORTS (5) /* plenty for this implementation */
|
#define UDP_MAX_PORTS (5) /* plenty for this implementation */
|
||||||
|
|
||||||
|
|
||||||
static UDP_BOUND_PORT
|
static UDP_BOUND_PORT udp_port_table[UDP_MAX_PORTS];
|
||||||
udp_port_table[UDP_MAX_PORTS];
|
|
||||||
|
|
||||||
static uint16
|
static uint16_t udp_port;
|
||||||
udp_port;
|
|
||||||
|
|
||||||
/********************************************************************/
|
void udp_init(void)
|
||||||
void
|
|
||||||
udp_init (void)
|
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
@@ -43,15 +35,13 @@ udp_init (void)
|
|||||||
|
|
||||||
udp_port = DEFAULT_UDP_PORT; /* next free port */
|
udp_port = DEFAULT_UDP_PORT; /* next free port */
|
||||||
}
|
}
|
||||||
/********************************************************************/
|
|
||||||
void
|
void udp_prime_port(uint16_t init_port)
|
||||||
udp_prime_port (uint16 init_port)
|
|
||||||
{
|
{
|
||||||
udp_port = init_port;
|
udp_port = init_port;
|
||||||
}
|
}
|
||||||
/********************************************************************/
|
|
||||||
void
|
void udp_bind_port(uint16_t port, void (*handler)(NIF *, NBUF *))
|
||||||
udp_bind_port (uint16 port, void (*handler)(NIF *, NBUF *))
|
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
@@ -65,9 +55,8 @@ udp_bind_port (uint16 port, void (*handler)(NIF *, NBUF *))
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/********************************************************************/
|
|
||||||
void
|
void udp_free_port(uint16_t port)
|
||||||
udp_free_port (uint16 port)
|
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
@@ -80,9 +69,8 @@ udp_free_port (uint16 port)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/********************************************************************/
|
|
||||||
static void *
|
static void *udp_port_handler(uint16_t port)
|
||||||
udp_port_handler (uint16 port)
|
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
@@ -95,11 +83,10 @@ udp_port_handler (uint16 port)
|
|||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
/********************************************************************/
|
|
||||||
uint16
|
uint16_t udp_obtain_free_port(void)
|
||||||
udp_obtain_free_port (void)
|
|
||||||
{
|
{
|
||||||
uint16 port;
|
uint16_t port;
|
||||||
|
|
||||||
port = udp_port;
|
port = udp_port;
|
||||||
if (--udp_port <= 255)
|
if (--udp_port <= 255)
|
||||||
@@ -107,9 +94,8 @@ udp_obtain_free_port (void)
|
|||||||
|
|
||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
/********************************************************************/
|
|
||||||
int
|
int udp_send(NIF *nif, uint8_t *dest, int sport, int dport, NBUF *pNbuf)
|
||||||
udp_send ( NIF *nif, uint8 *dest, int sport, int dport, NBUF *pNbuf)
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* This function takes data and creates a UDP frame and
|
* This function takes data and creates a UDP frame and
|
||||||
@@ -120,29 +106,27 @@ udp_send ( NIF *nif, uint8 *dest, int sport, int dport, NBUF *pNbuf)
|
|||||||
udpframe = (udp_frame_hdr *) &pNbuf->data[UDP_HDR_OFFSET];
|
udpframe = (udp_frame_hdr *) &pNbuf->data[UDP_HDR_OFFSET];
|
||||||
|
|
||||||
/* Set UDP source port */
|
/* Set UDP source port */
|
||||||
udpframe->src_port = (uint16)sport;
|
udpframe->src_port = (uint16_t) sport;
|
||||||
|
|
||||||
/* Set UDP destination port */
|
/* Set UDP destination port */
|
||||||
udpframe->dest_port = (uint16)dport;
|
udpframe->dest_port = (uint16_t) dport;
|
||||||
|
|
||||||
/* Set length */
|
/* Set length */
|
||||||
udpframe->length = (uint16)(pNbuf->length + UDP_HDR_SIZE);
|
udpframe->length = (uint16_t) (pNbuf->length + UDP_HDR_SIZE);
|
||||||
|
|
||||||
/* No checksum calcualation needed */
|
/* No checksum calcualation needed */
|
||||||
udpframe->chksum = (uint16)0;
|
udpframe->chksum = (uint16_t) 0;
|
||||||
|
|
||||||
/* Add the length of the UDP packet to the total length of the packet */
|
/* Add the length of the UDP packet to the total length of the packet */
|
||||||
pNbuf->length += 8;
|
pNbuf->length += 8;
|
||||||
|
|
||||||
return (ip_send(nif,
|
return (ip_send(nif, dest,
|
||||||
dest,
|
|
||||||
ip_get_myip(nif_get_protocol_info(nif, ETH_FRM_IP)),
|
ip_get_myip(nif_get_protocol_info(nif, ETH_FRM_IP)),
|
||||||
IP_PROTO_UDP,
|
IP_PROTO_UDP,
|
||||||
pNbuf));
|
pNbuf));
|
||||||
}
|
}
|
||||||
/********************************************************************/
|
|
||||||
void
|
void udp_handler(NIF *nif, NBUF *pNbuf)
|
||||||
udp_handler (NIF *nif, NBUF *pNbuf)
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* This function handles incoming UDP packets
|
* This function handles incoming UDP packets
|
||||||
@@ -167,14 +151,9 @@ udp_handler (NIF *nif, NBUF *pNbuf)
|
|||||||
handler(nif, pNbuf);
|
handler(nif, pNbuf);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#ifdef DBUG_PRINT
|
xprintf("Received UDP packet for non-supported port\n");
|
||||||
printf("Received UDP packet for non-supported port\n");
|
|
||||||
#endif
|
|
||||||
nbuf_free(pNbuf);
|
nbuf_free(pNbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/********************************************************************/
|
|
||||||
|
|
||||||
#endif /* #ifdef DBUG_NETWORK */
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include "MCF5475.h"
|
#include "MCF5475.h"
|
||||||
#include "bas_utils.h"
|
#include "bas_utils.h"
|
||||||
#include "bas_printf.h"
|
#include "bas_printf.h"
|
||||||
@@ -79,3 +80,146 @@ int register_interrupt_handler(uint8_t source, uint8_t level, uint8_t priority,
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef UIF_MAX_ISR_ENTRY
|
||||||
|
#define UIF_MAX_ISR_ENTRY (20)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int vector;
|
||||||
|
int type;
|
||||||
|
int (*handler)(void *, void *);
|
||||||
|
void *hdev;
|
||||||
|
void *harg;
|
||||||
|
} ISRENTRY;
|
||||||
|
|
||||||
|
ISRENTRY isrtab[UIF_MAX_ISR_ENTRY];
|
||||||
|
|
||||||
|
|
||||||
|
void isr_init(void)
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
|
||||||
|
for (index = 0; index < UIF_MAX_ISR_ENTRY; index++)
|
||||||
|
{
|
||||||
|
isrtab[index].vector = 0;
|
||||||
|
isrtab[index].type = 0;
|
||||||
|
isrtab[index].handler = 0;
|
||||||
|
isrtab[index].hdev = 0;
|
||||||
|
isrtab[index].harg = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int isr_register_handler (
|
||||||
|
int type, int vector,
|
||||||
|
int (*handler)(void *, void *), void *hdev, void *harg)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This function places an interrupt handler in the ISR table,
|
||||||
|
* thereby registering it so that the low-level handler may call it.
|
||||||
|
*
|
||||||
|
* The two parameters are intended for the first arg to be a
|
||||||
|
* pointer to the device itself, and the second a pointer to a data
|
||||||
|
* structure used by the device driver for that particular device.
|
||||||
|
*/
|
||||||
|
int index;
|
||||||
|
|
||||||
|
if ((vector == 0) ||
|
||||||
|
((type != ISR_DBUG_ISR) && (type != ISR_USER_ISR)) ||
|
||||||
|
(handler == NULL))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (index = 0; index < UIF_MAX_ISR_ENTRY; index++)
|
||||||
|
{
|
||||||
|
if ((isrtab[index].vector == vector) &&
|
||||||
|
(isrtab[index].type == type))
|
||||||
|
{
|
||||||
|
/* only one entry of each type per vector */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isrtab[index].vector == 0)
|
||||||
|
{
|
||||||
|
isrtab[index].vector = vector;
|
||||||
|
isrtab[index].type = type;
|
||||||
|
isrtab[index].handler = handler;
|
||||||
|
isrtab[index].hdev = hdev;
|
||||||
|
isrtab[index].harg = harg;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false; /* no available slots */
|
||||||
|
}
|
||||||
|
|
||||||
|
void isr_remove_handler(int type, int (*handler)(void *, void *))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This routine removes from the ISR table all
|
||||||
|
* entries that matches 'type' and 'handler'.
|
||||||
|
*/
|
||||||
|
int index;
|
||||||
|
|
||||||
|
for (index = 0; index < UIF_MAX_ISR_ENTRY; index++)
|
||||||
|
{
|
||||||
|
if ((isrtab[index].handler == handler) &&
|
||||||
|
(isrtab[index].type == type))
|
||||||
|
{
|
||||||
|
isrtab[index].vector = 0;
|
||||||
|
isrtab[index].type = 0;
|
||||||
|
isrtab[index].handler = 0;
|
||||||
|
isrtab[index].hdev = 0;
|
||||||
|
isrtab[index].harg = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool isr_execute_handler(int vector)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This routine searches the ISR table for an entry that matches
|
||||||
|
* 'vector'. If one is found, then 'handler' is executed.
|
||||||
|
*/
|
||||||
|
int index;
|
||||||
|
bool retval = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First locate a dBUG Interrupt Service Routine handler.
|
||||||
|
*/
|
||||||
|
for (index = 0; index < UIF_MAX_ISR_ENTRY; index++)
|
||||||
|
{
|
||||||
|
if ((isrtab[index].vector == vector) &&
|
||||||
|
(isrtab[index].type == ISR_DBUG_ISR))
|
||||||
|
{
|
||||||
|
if (isrtab[index].handler(isrtab[index].hdev,isrtab[index].harg))
|
||||||
|
{
|
||||||
|
retval = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try to locate a user-registered Interrupt Service Routine handler.
|
||||||
|
*/
|
||||||
|
for (index = 0; index < UIF_MAX_ISR_ENTRY; index++)
|
||||||
|
{
|
||||||
|
if ((isrtab[index].vector == vector) &&
|
||||||
|
(isrtab[index].type == ISR_USER_ISR))
|
||||||
|
{
|
||||||
|
if (isrtab[index].handler(isrtab[index].hdev,isrtab[index].harg))
|
||||||
|
{
|
||||||
|
retval = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user