added more networking routines

This commit is contained in:
Markus Fröschle
2013-12-23 14:14:25 +00:00
parent 1df1d4d919
commit 02c5812424
9 changed files with 1152 additions and 52 deletions

View File

@@ -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

View File

@@ -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)

View File

@@ -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_ */

View 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
View 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
View 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
View 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;
}

View File

@@ -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
@@ -117,32 +103,30 @@ udp_send ( NIF *nif, uint8 *dest, int sport, int dport, NBUF *pNbuf)
*/ */
udp_frame_hdr *udpframe; udp_frame_hdr *udpframe;
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
@@ -150,7 +134,7 @@ udp_handler (NIF *nif, NBUF *pNbuf)
udp_frame_hdr *udpframe; udp_frame_hdr *udpframe;
void (*handler)(NIF *, NBUF *); void (*handler)(NIF *, NBUF *);
udpframe = (udp_frame_hdr *)&pNbuf->data[pNbuf->offset]; udpframe = (udp_frame_hdr *) &pNbuf->data[pNbuf->offset];
/* /*
* Adjust the length and valid data offset of the packet we are * Adjust the length and valid data offset of the packet we are
@@ -163,18 +147,13 @@ udp_handler (NIF *nif, NBUF *pNbuf)
* Traverse the list of bound ports to see if there is a higher * Traverse the list of bound ports to see if there is a higher
* level protocol to pass the packet on to * level protocol to pass the packet on to
*/ */
if ((handler = (void(*)(NIF*,NBUF*))udp_port_handler(UDP_DEST(udpframe))) != NULL) if ((handler = (void(*)(NIF*, NBUF*)) udp_port_handler(UDP_DEST(udpframe))) != NULL)
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 */

View File

@@ -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;
}