📄 support.c
字号:
//==========================================================================
//
// ecos/support.c
//
// eCos wrapper and support functions
//
//==========================================================================
//####BSDCOPYRIGHTBEGIN####
//
// -------------------------------------------
//
// Portions of this software may have been derived from OpenBSD or other sources,
// and are covered by the appropriate copyright disclaimers included herein.
//
// -------------------------------------------
//
//####BSDCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): gthomas, hmt
// Contributors: gthomas, hmt
// Date: 2000-01-10
// Purpose:
// Description:
//
//
//####DESCRIPTIONEND####
//
//==========================================================================
// Support routines, etc., used by network code
#include <sys/param.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/domain.h>
#include <sys/protosw.h>
#include <sys/sockio.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <net/if.h>
#include <net/route.h>
#include <net/netisr.h>
#include <netinet/in.h>
#include <netinet/in_var.h>
#include <arpa/inet.h>
#include <machine/cpu.h>
#include <pkgconf/net.h>
#include <cyg/infra/diag.h>
#include <cyg/hal/hal_intr.h>
#include <cyg/kernel/kapi.h>
#include <cyg/infra/cyg_ass.h>
#if !CYGPKG_NET_DRIVER_FRAMEWORK // Interface
#error At least one network driver framework must be defined!
#else
#include <cyg/io/eth/netdev.h>
// Define table boundaries
CYG_HAL_TABLE_BEGIN( __NETDEVTAB__, netdev );
CYG_HAL_TABLE_END( __NETDEVTAB_END__, netdev );
// Used for system-wide "ticks per second"
int hz = 100;
int tick = 10000; // usec per "tick"
volatile struct timeval mono_time;
volatile struct timeval ktime;
// Low-level network debugging
int net_debug = 0;
#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
static char netint_stack[STACK_SIZE];
static cyg_thread netint_thread_data;
static cyg_handle_t netint_thread_handle;
cyg_flag_t netint_flags;
#define NETISR_ANY 0xFFFFFFFF // Any possible bit...
extern void cyg_test_exit(void); // TEMP
void
cyg_panic(const char *msg, ...)
{
cyg_uint32 old_ints;
CYG_FAIL( msg );
HAL_DISABLE_INTERRUPTS(old_ints);
diag_printf("PANIC: %s\n", msg);
cyg_test_exit(); // FIXME
}
// Round a number 'n' up to a multiple of 'm'
#define round(n,m) ((((n)+((m)-1))/(m))*(m))
#define NET_MEMPOOL_SIZE round(CYGPKG_NET_MEM_USAGE/4,MSIZE)
#define NET_MBUFS_SIZE round(CYGPKG_NET_MEM_USAGE/4,MSIZE)
#define NET_CLUSTERS_SIZE round(CYGPKG_NET_MEM_USAGE/2,MCLBYTES)
static unsigned char net_mempool_area[NET_MEMPOOL_SIZE];
static cyg_mempool_var net_mem_pool;
static cyg_handle_t net_mem;
static unsigned char net_mbufs_area[NET_MBUFS_SIZE];
static cyg_mempool_fix net_mbufs_pool;
static cyg_handle_t net_mbufs;
static unsigned char net_clusters_area[NET_CLUSTERS_SIZE];
static cyg_mempool_fix net_clusters_pool;
static cyg_handle_t net_clusters;
static char net_clusters_refcnt[(NET_CLUSTERS_SIZE/MCLBYTES)+1];
#ifdef CYGDBG_NET_TIMING_STATS
static struct net_stats stats_malloc, stats_free,
stats_memcpy, stats_memset,
stats_mbuf_alloc, stats_mbuf_free, stats_cluster_alloc;
extern struct net_stats stats_in_cksum;
// Display a number of ticks as microseconds
// Note: for improved calculation significance, values are kept in ticks*1000
static long rtc_resolution[] = CYGNUM_KERNEL_COUNTERS_RTC_RESOLUTION;
static long ns_per_system_clock;
static void
show_ticks_in_us(cyg_uint32 ticks)
{
long long ns;
ns_per_system_clock = 1000000/rtc_resolution[1];
ns = (ns_per_system_clock * ((long long)ticks * 1000)) /
CYGNUM_KERNEL_COUNTERS_RTC_PERIOD;
ns += 5; // for rounding to .01us
diag_printf("%7d.%02d", (int)(ns/1000), (int)((ns%1000)/10));
}
void
show_net_stats(struct net_stats *stats, const char *title)
{
int ave;
ave = stats->total_time / stats->count;
diag_printf("%s:\n", title);
diag_printf(" count: %6d", stats->count);
diag_printf(", min: ");
show_ticks_in_us(stats->min_time);
diag_printf(", max: ");
show_ticks_in_us(stats->max_time);
diag_printf(", total: ");
show_ticks_in_us(stats->total_time);
diag_printf(", ave: ");
show_ticks_in_us(ave);
diag_printf("\n");
// Reset stats
memset(stats, 0, sizeof(*stats));
}
void
show_net_times(void)
{
show_net_stats(&stats_malloc, "Net malloc");
show_net_stats(&stats_free, "Net free");
show_net_stats(&stats_mbuf_alloc, "Mbuf alloc");
show_net_stats(&stats_mbuf_free, "Mbuf free");
show_net_stats(&stats_cluster_alloc, "Cluster alloc");
show_net_stats(&stats_in_cksum, "Checksum");
show_net_stats(&stats_memcpy, "Net memcpy");
show_net_stats(&stats_memset, "Net memset");
}
#endif /* CYGDBG_NET_TIMING_STATS */
void *
cyg_net_malloc(u_long size, int type, int flags)
{
void *res;
START_STATS();
if (flags & M_NOWAIT) {
res = cyg_mempool_var_try_alloc(net_mem, size);
} else {
res = cyg_mempool_var_alloc(net_mem, size);
}
FINISH_STATS(stats_malloc);
return (res);
}
void
cyg_net_free(caddr_t addr, int type)
{
START_STATS();
cyg_mempool_var_free(net_mem, addr);
FINISH_STATS(stats_free);
}
void *
cyg_net_mbuf_alloc(int type, int flags)
{
void *res;
START_STATS();
mbstat.m_mbufs++;
if (flags & M_NOWAIT) {
res = cyg_mempool_fix_try_alloc(net_mbufs);
} else {
res = cyg_mempool_fix_alloc(net_mbufs);
}
FINISH_STATS(stats_mbuf_alloc);
// Check that this nastiness works OK
CYG_ASSERT( dtom(res) == res, "dtom failed, base of mbuf" );
CYG_ASSERT( dtom((char *)res + MSIZE/2) == res, "dtom failed, mid mbuf" );
return (res);
}
void
cyg_net_mbuf_free(caddr_t addr, int type)
{
START_STATS();
mbstat.m_mbufs--;
cyg_mempool_fix_free(net_mbufs, addr);
FINISH_STATS(stats_mbuf_free);
}
void *
cyg_net_cluster_alloc(void)
{
void *res;
START_STATS();
res = cyg_mempool_fix_try_alloc(net_clusters);
FINISH_STATS(stats_cluster_alloc);
return res;
}
static void
cyg_kmem_init(void)
{
unsigned char *p;
#ifdef CYGPKG_NET_DEBUG
diag_printf("Network stack using %d bytes for misc space\n", NET_MEMPOOL_SIZE);
diag_printf(" %d bytes for mbufs\n", NET_MBUFS_SIZE);
diag_printf(" %d bytes for mbuf clusters\n", NET_CLUSTERS_SIZE);
#endif
cyg_mempool_var_create(&net_mempool_area,
NET_MEMPOOL_SIZE,
&net_mem,
&net_mem_pool);
// Align the mbufs on MSIZE boudaries so that dtom() can work.
p = (unsigned char *)(((long)(&net_mbufs_area) + MSIZE - 1) & ~(MSIZE-1));
cyg_mempool_fix_create(p,
((&(net_mbufs_area[NET_MBUFS_SIZE])) - p) & ~(MSIZE-1),
MSIZE,
&net_mbufs,
&net_mbufs_pool);
cyg_mempool_fix_create(&net_clusters_area,
NET_CLUSTERS_SIZE,
MCLBYTES,
&net_clusters,
&net_clusters_pool);
mbutl = (struct mbuf *)&net_clusters_area;
mclrefcnt = net_clusters_refcnt;
}
void cyg_kmem_print_stats( void )
{
cyg_mempool_info info;
diag_printf( "Network stack mbuf stats:\n" );
diag_printf( " mbufs %d, clusters %d, free clusters %d\n",
mbstat.m_mbufs, /* mbufs obtained from page pool */
mbstat.m_clusters, /* clusters obtained from page pool */
/* mbstat.m_spare, */ /* spare field */
mbstat.m_clfree /* free clusters */
);
diag_printf( " Failed to get %d times\n"
" Waited to get %d times\n"
" Drained queues to get %d times\n",
mbstat.m_drops, /* times failed to find space */
mbstat.m_wait, /* times waited for space */
mbstat.m_drain /* times drained protocols for space */
/* mbstat.m_mtypes[256]; type specific mbuf allocations */
);
cyg_mempool_var_get_info( net_mem, &info );
diag_printf( "Misc mpool: total %7d, free %7d, max free block %d\n",
info.totalmem,
info.freemem,
info.maxfree
);
cyg_mempool_fix_get_info( net_mbufs, &info );
diag_printf( "Mbufs pool: total %7d, free %7d, blocksize %4d\n",
info.totalmem,
info.freemem,
info.blocksize
);
cyg_mempool_fix_get_info( net_clusters, &info );
diag_printf( "Clust pool: total %7d, free %7d, blocksize %4d\n",
info.totalmem,
info.freemem,
info.blocksize
);
}
// This API is for our own automated network tests. It's not in any header
// files because it's not at all supported.
int cyg_net_get_mem_stats( int which, cyg_mempool_info *p )
{
CYG_CHECK_DATA_PTR( p, "Bad pointer to mempool_info" );
CYG_ASSERT( 0 <= which, "Mempool selector underflow" );
CYG_ASSERT( 2 >=which, "Mempool selector overflow" );
if ( p )
switch ( which ) {
case 0:
cyg_mempool_var_get_info( net_mem, p );
break;
case 1:
cyg_mempool_fix_get_info( net_mbufs, p );
break;
case 2:
cyg_mempool_fix_get_info( net_clusters, p );
break;
default:
return 0;
}
return (int)p;
}
int
cyg_mtocl(u_long x)
{
int res;
res = (((u_long)(x) - (u_long)mbutl) >> MCLSHIFT);
return res;
}
struct mbuf *
cyg_cltom(u_long x)
{
struct mbuf *res;
res = (struct mbuf *)((caddr_t)((u_long)mbutl + ((u_long)(x) << MCLSHIFT)));
return res;
}
externC void
net_memcpy(void *d, void *s, int n)
{
START_STATS();
memcpy(d, s, n);
FINISH_STATS(stats_memcpy);
}
externC void
net_memset(void *s, int v, int n)
{
START_STATS();
memset(s, v, n);
FINISH_STATS(stats_memset);
}
// Rather than bring in the whole BSD 'random' code...
int
arc4random(void)
{
cyg_uint32 res;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -