OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [net/] [bsd_tcpip/] [v2_0/] [src/] [ecos/] [support.c] - Blame information for rev 631

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      src/ecos/support.c
4
//
5
//==========================================================================
6
//####BSDCOPYRIGHTBEGIN####
7
//
8
// -------------------------------------------
9
//
10
// Portions of this software may have been derived from OpenBSD, 
11
// FreeBSD or other sources, and are covered by the appropriate
12
// copyright disclaimers included herein.
13
//
14
// Portions created by Red Hat are
15
// Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
16
//
17
// Copyright (C) 2002 Gary Thomas
18
// -------------------------------------------
19
//
20
//####BSDCOPYRIGHTEND####
21
//==========================================================================
22
 
23
//==========================================================================
24
//
25
//      ecos/support.c
26
//
27
//      eCos wrapper and support functions
28
//
29
//==========================================================================
30
//####BSDCOPYRIGHTBEGIN####
31
//
32
// -------------------------------------------
33
//
34
// Portions of this software may have been derived from OpenBSD or other sources,
35
// and are covered by the appropriate copyright disclaimers included herein.
36
//
37
// -------------------------------------------
38
//
39
//####BSDCOPYRIGHTEND####
40
//==========================================================================
41
//#####DESCRIPTIONBEGIN####
42
//
43
// Author(s):    gthomas, hmt
44
// Contributors: gthomas, hmt
45
// Date:         2000-01-10
46
// Purpose:      
47
// Description:  
48
//              
49
//
50
//####DESCRIPTIONEND####
51
//
52
//==========================================================================
53
 
54
 
55
// Support routines, etc., used by network code
56
 
57
#include <sys/param.h>
58
#include <sys/malloc.h>
59
#include <sys/mbuf.h>
60
#include <sys/domain.h>
61
#include <sys/protosw.h>
62
#include <sys/sockio.h>
63
#include <sys/socket.h>
64
#include <sys/socketvar.h>
65
#include <net/if.h>
66
#include <net/netisr.h>
67
 
68
#include <cyg/infra/diag.h>
69
#include <cyg/hal/hal_intr.h>
70
#include <cyg/kernel/kapi.h>
71
 
72
#include <cyg/infra/cyg_ass.h>
73
 
74
#if !CYGPKG_NET_DRIVER_FRAMEWORK   // Interface
75
#error At least one network driver framework must be defined!
76
#else
77
#include <cyg/io/eth/netdev.h>
78
 
79
// Define table boundaries
80
CYG_HAL_TABLE_BEGIN( __NETDEVTAB__, netdev );
81
CYG_HAL_TABLE_END( __NETDEVTAB_END__, netdev );
82
CYG_HAL_TABLE_BEGIN( __NET_INIT_TAB__, _Net_inits );
83
CYG_HAL_TABLE_END( __NET_INIT_TAB_END__, _Net_inits );
84
extern struct init_tab_entry __NET_INIT_TAB__[], __NET_INIT_TAB_END__;
85
 
86
// Used for system-wide "ticks per second"
87
#undef ticks
88
int hz = 100;
89
int tick = 10000;  // usec per "tick"
90
volatile struct timeval ktime;
91
int proc = 0;  // unused
92
int proc0 = 0;  // unused
93
 
94
volatile struct timeval mono_time;
95
 
96
// Low-level network debugging & logging
97
#ifdef CYGPKG_NET_FREEBSD_LOGGING
98
int cyg_net_log_mask = CYGPKG_NET_FREEBSD_LOGGING;
99
#endif
100
 
101
#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
102
static char netint_stack[STACK_SIZE];
103
static cyg_thread netint_thread_data;
104
static cyg_handle_t netint_thread_handle;
105
 
106
cyg_flag_t netint_flags;
107
#define NETISR_ANY 0xFFFFFFFF  // Any possible bit...
108
 
109
extern void cyg_test_exit(void);  // TEMP
110
void
111
cyg_panic(const char *msg, ...)
112
{
113
    cyg_uint32 old_ints;
114
    CYG_FAIL( msg );
115
    HAL_DISABLE_INTERRUPTS(old_ints);
116
    diag_printf("PANIC: %s\n", msg);
117
    cyg_test_exit();  // FIXME
118
}
119
 
120
#define NET_MEMPOOL_SIZE  roundup(CYGPKG_NET_MEM_USAGE/4,MSIZE)
121
#define NET_MBUFS_SIZE    roundup(CYGPKG_NET_MEM_USAGE/4,MSIZE)
122
#define NET_CLUSTERS_SIZE roundup(CYGPKG_NET_MEM_USAGE/2,MCLBYTES)
123
 
124
static unsigned char net_mempool_area[NET_MEMPOOL_SIZE];
125
static cyg_mempool_var net_mem_pool;
126
static cyg_handle_t    net_mem;
127
static unsigned char net_mbufs_area[NET_MBUFS_SIZE];
128
static cyg_mempool_fix net_mbufs_pool;
129
static cyg_handle_t    net_mbufs;
130
static unsigned char net_clusters_area[NET_CLUSTERS_SIZE];
131
static cyg_mempool_fix net_clusters_pool;
132
static cyg_handle_t    net_clusters;
133
static char            net_clusters_refcnt[(NET_CLUSTERS_SIZE/MCLBYTES)+1];
134
int nmbclusters = (NET_CLUSTERS_SIZE/MCLBYTES);
135
 
136
#ifdef CYGDBG_NET_TIMING_STATS
137
static struct net_stats  stats_malloc, stats_free,
138
    stats_memcpy, stats_memset,
139
    stats_mbuf_alloc, stats_mbuf_free, stats_cluster_alloc;
140
extern struct net_stats stats_in_cksum;
141
 
142
// Display a number of ticks as microseconds
143
// Note: for improved calculation significance, values are kept in ticks*1000
144
static long rtc_resolution[] = CYGNUM_KERNEL_COUNTERS_RTC_RESOLUTION;
145
static long ns_per_system_clock;
146
 
147
static void
148
show_ticks_in_us(cyg_uint32 ticks)
149
{
150
    long long ns;
151
    ns_per_system_clock = 1000000/rtc_resolution[1];
152
    ns = (ns_per_system_clock * ((long long)ticks * 1000)) /
153
        CYGNUM_KERNEL_COUNTERS_RTC_PERIOD;
154
    ns += 5;  // for rounding to .01us
155
    diag_printf("%7d.%02d", (int)(ns/1000), (int)((ns%1000)/10));
156
}
157
 
158
void
159
show_net_stats(struct net_stats *stats, const char *title)
160
{
161
    int ave;
162
    ave = stats->total_time / stats->count;
163
    diag_printf("%s:\n", title);
164
    diag_printf("  count: %6d", stats->count);
165
    diag_printf(", min: ");
166
    show_ticks_in_us(stats->min_time);
167
    diag_printf(", max: ");
168
    show_ticks_in_us(stats->max_time);
169
    diag_printf(", total: ");
170
    show_ticks_in_us(stats->total_time);
171
    diag_printf(", ave: ");
172
    show_ticks_in_us(ave);
173
    diag_printf("\n");
174
    // Reset stats
175
    memset(stats, 0, sizeof(*stats));
176
}
177
 
178
void
179
show_net_times(void)
180
{
181
    show_net_stats(&stats_malloc,        "Net malloc");
182
    show_net_stats(&stats_free,          "Net free");
183
    show_net_stats(&stats_mbuf_alloc,    "Mbuf alloc");
184
    show_net_stats(&stats_mbuf_free,     "Mbuf free");
185
    show_net_stats(&stats_cluster_alloc, "Cluster alloc");
186
    show_net_stats(&stats_in_cksum,      "Checksum");
187
    show_net_stats(&stats_memcpy,        "Net memcpy");
188
    show_net_stats(&stats_memset,        "Net memset");
189
}
190
#endif /* CYGDBG_NET_TIMING_STATS */ 
191
 
192
void *
193
cyg_net_malloc(u_long size, int type, int flags)
194
{
195
    void *res;
196
 
197
    START_STATS();
198
    log(LOG_MDEBUG, "Net malloc[%d] = ", size);
199
    if (flags & M_NOWAIT) {
200
        res = cyg_mempool_var_try_alloc(net_mem, size);
201
    } else {
202
        res = cyg_mempool_var_alloc(net_mem, size);
203
    }
204
    if ((flags & M_ZERO) && res) {
205
      memset(res,0,size);
206
    }
207
    FINISH_STATS(stats_malloc);
208
    log(LOG_MDEBUG, "%p\n", res);
209
    return (res);
210
}
211
 
212
void
213
cyg_net_free(caddr_t addr, int type)
214
{
215
    START_STATS();
216
    cyg_mempool_var_free(net_mem, addr);
217
    FINISH_STATS(stats_free);
218
}
219
 
220
void *
221
cyg_net_mbuf_alloc(int type, int flags)
222
{
223
    void *res;
224
 
225
    START_STATS();
226
    log(LOG_MDEBUG, "Alloc mbuf = ");
227
    mbstat.m_mbufs++;
228
    if (flags & M_NOWAIT) {
229
        res = cyg_mempool_fix_try_alloc(net_mbufs);
230
    } else {
231
        res = cyg_mempool_fix_alloc(net_mbufs);
232
    }
233
    FINISH_STATS(stats_mbuf_alloc);
234
    // Check that this nastiness works OK
235
    CYG_ASSERT( dtom(res) == res, "dtom failed, base of mbuf" );
236
    CYG_ASSERT( dtom((char *)res + MSIZE/2) == res, "dtom failed, mid mbuf" );
237
    log(LOG_MDEBUG, "%p\n", res);
238
    return (res);
239
}
240
 
241
void
242
cyg_net_mbuf_free(caddr_t addr, int type)
243
{
244
    START_STATS();
245
    mbstat.m_mbufs--;
246
    cyg_mempool_fix_free(net_mbufs, addr);
247
    FINISH_STATS(stats_mbuf_free);
248
}
249
 
250
void *
251
cyg_net_cluster_alloc(void)
252
{
253
    void *res;
254
 
255
    START_STATS();
256
    log(LOG_MDEBUG, "Allocate cluster = ");
257
    res = cyg_mempool_fix_try_alloc(net_clusters);
258
    FINISH_STATS(stats_cluster_alloc);
259
    log(LOG_MDEBUG, "%p\n", res);
260
    return res;
261
}
262
 
263
static struct vm_zone *vm_zones = (struct vm_zone *)NULL;
264
 
265
vm_zone_t
266
zinit(char *name, int size, int nentries, int flags, int zalloc)
267
{
268
    void *res;
269
    vm_zone_t zone = (vm_zone_t)0;
270
    elem *p;
271
 
272
    log(LOG_MDEBUG, "zinit '%s', size: %d, num: %d, flags: %d, alloc: %d\n",
273
        name, size, nentries, flags, zalloc);
274
    res = cyg_mempool_var_try_alloc(net_mem, sizeof(struct vm_zone));
275
    if (res) {
276
        zone = (vm_zone_t)res;
277
        res = cyg_mempool_var_try_alloc(net_mem, size*nentries);
278
    }
279
    if (!res) {
280
        log(LOG_MDEBUG, "Can't allocate memory for %s\n", name);
281
        panic("zinit: Out of memory\n");
282
    }
283
    p = (elem *)res;
284
    zone->pool = (elem *)0;
285
    zone->elem_size = size;
286
    zone->name = name;
287
    zone->free = zone->total = nentries;
288
    zone->next = vm_zones;
289
    zone->alloc_tries = zone->alloc_fails = zone->alloc_frees = 0;
290
    vm_zones = zone;
291
    while (nentries-- > 0) {
292
        p->next = zone->pool;
293
        zone->pool = p;
294
        p = (elem *)((char *)p + size);
295
    }
296
    p = zone->pool;
297
#if 0
298
    while (p) {
299
        log(LOG_MDEBUG, "p: %p, next: %p\n", p, p->next);
300
        p = p->next;
301
    }
302
#endif
303
    return zone;
304
}
305
 
306
void *
307
zalloci(vm_zone_t zone)
308
{
309
    elem *p;
310
 
311
    p = zone->pool;
312
    zone->alloc_tries++;
313
    if (p) {
314
        zone->pool = p->next;
315
        zone->free--;
316
    } else {
317
        zone->alloc_fails++;
318
    }
319
    log(LOG_MDEBUG, "zalloci from %s => %p\n", zone->name, p);
320
    return (void *)p;
321
}
322
 
323
void
324
zfreei(vm_zone_t zone, void *item)
325
{
326
    elem *p = (elem *)item;
327
 
328
    log(LOG_MDEBUG, "zfreei to %s <= %p\n", zone->name, p);
329
    p->next = zone->pool;
330
    zone->pool = p;
331
    zone->free++;
332
    zone->alloc_frees++;
333
}
334
 
335
static void
336
cyg_kmem_init(void)
337
{
338
    unsigned char *p;
339
#ifdef CYGPKG_NET_DEBUG
340
    diag_printf("Network stack using %d bytes for misc space\n", NET_MEMPOOL_SIZE);
341
    diag_printf("                    %d bytes for mbufs\n", NET_MBUFS_SIZE);
342
    diag_printf("                    %d bytes for mbuf clusters\n", NET_CLUSTERS_SIZE);
343
#endif
344
    cyg_mempool_var_create(&net_mempool_area,
345
                           NET_MEMPOOL_SIZE,
346
                           &net_mem,
347
                           &net_mem_pool);
348
    // Align the mbufs on MSIZE boudaries so that dtom() can work.
349
    p = (unsigned char *)(((long)(&net_mbufs_area) + MSIZE - 1) & ~(MSIZE-1));
350
    cyg_mempool_fix_create(p,
351
                           ((&(net_mbufs_area[NET_MBUFS_SIZE])) - p) & ~(MSIZE-1),
352
                           MSIZE,
353
                           &net_mbufs,
354
                           &net_mbufs_pool);
355
    cyg_mempool_fix_create(&net_clusters_area,
356
                           NET_CLUSTERS_SIZE,
357
                           MCLBYTES,
358
                           &net_clusters,
359
                           &net_clusters_pool);
360
    mbutl = (struct mbuf *)&net_clusters_area;
361
    mclrefcnt = net_clusters_refcnt;
362
}
363
 
364
void cyg_kmem_print_stats( void )
365
{
366
    cyg_mempool_info info;
367
    struct vm_zone *zone;
368
 
369
    diag_printf( "Network stack mbuf stats:\n" );
370
    diag_printf( "   mbufs %d, clusters %d, free clusters %d\n",
371
                 mbstat.m_mbufs,        /* mbufs obtained from page pool */
372
                 mbstat.m_clusters,     /* clusters obtained from page pool */
373
                 /* mbstat.m_spare, */  /* spare field */
374
                 mbstat.m_clfree        /* free clusters */
375
        );
376
    diag_printf( "   Failed to get %d times\n"
377
                 "   Waited to get %d times\n"
378
                 "   Drained queues to get %d times\n",
379
                 mbstat.m_drops,        /* times failed to find space */
380
                 mbstat.m_wait,         /* times waited for space */
381
                 mbstat.m_drain         /* times drained protocols for space */
382
                 /* mbstat.m_mtypes[256]; type specific mbuf allocations */
383
        );
384
 
385
    zone = vm_zones;
386
    while (zone) {
387
        diag_printf("VM zone '%s':\n", zone->name);
388
        diag_printf("  Total: %d, Free: %d, Allocs: %d, Frees: %d, Fails: %d\n",
389
                    zone->total, zone->free,
390
                    zone->alloc_tries, zone->alloc_frees, zone->alloc_fails);
391
        zone = zone->next;
392
    }
393
 
394
    cyg_mempool_var_get_info( net_mem, &info );
395
    diag_printf( "Misc mpool: total %7d, free %7d, max free block %d\n",
396
                 info.totalmem,
397
                 info.freemem,
398
                 info.maxfree
399
        );
400
 
401
    cyg_mempool_fix_get_info( net_mbufs, &info );
402
    diag_printf( "Mbufs pool: total %7d, free %7d, blocksize %4d\n",
403
                 info.totalmem,
404
                 info.freemem,
405
                 info.blocksize
406
        );
407
 
408
 
409
    cyg_mempool_fix_get_info( net_clusters, &info );
410
    diag_printf( "Clust pool: total %7d, free %7d, blocksize %4d\n",
411
                 info.totalmem,
412
                 info.freemem,
413
                 info.blocksize
414
        );
415
}
416
 
417
// This API is for our own automated network tests.  It's not in any header
418
// files because it's not at all supported.
419
int cyg_net_get_mem_stats( int which, cyg_mempool_info *p )
420
{
421
    CYG_CHECK_DATA_PTR( p, "Bad pointer to mempool_info" );
422
    CYG_ASSERT( 0 <= which, "Mempool selector underflow" );
423
    CYG_ASSERT( 2 >=which, "Mempool selector overflow" );
424
 
425
    if ( p )
426
        switch ( which ) {
427
        case 0:
428
            cyg_mempool_var_get_info( net_mem, p );
429
            break;
430
        case 1:
431
            cyg_mempool_fix_get_info( net_mbufs, p );
432
            break;
433
        case 2:
434
            cyg_mempool_fix_get_info( net_clusters, p );
435
            break;
436
        default:
437
            return 0;
438
        }
439
    return (int)p;
440
}
441
 
442
int
443
cyg_mtocl(u_long x)
444
{
445
    int res;
446
    res = (((u_long)(x) - (u_long)mbutl) >> MCLSHIFT);
447
    return res;
448
}
449
 
450
struct mbuf *
451
cyg_cltom(u_long x)
452
{
453
    struct mbuf *res;
454
    res = (struct mbuf *)((caddr_t)((u_long)mbutl + ((u_long)(x) << MCLSHIFT)));
455
    return res;
456
}
457
 
458
externC void
459
net_memcpy(void *d, void *s, int n)
460
{
461
    START_STATS();
462
    memcpy(d, s, n);
463
    FINISH_STATS(stats_memcpy);
464
}
465
 
466
externC void
467
net_memset(void *s, int v, int n)
468
{
469
    START_STATS();
470
    memset(s, v, n);
471
    FINISH_STATS(stats_memset);
472
}
473
 
474
// Rather than bring in the whole BSD 'random' code...
475
int
476
arc4random(void)
477
{
478
    cyg_uint32 res;
479
    static unsigned long seed = 0xDEADB00B;
480
    HAL_CLOCK_READ(&res);  // Not so bad... (but often 0..N where N is small)
481
    seed = ((seed & 0x007F00FF) << 7) ^
482
        ((seed & 0x0F80FF00) >> 8) ^ // be sure to stir those low bits
483
        (res << 13) ^ (res >> 9);    // using the clock too!
484
    return (int)seed;
485
}
486
 
487
void
488
get_random_bytes(void *buf, size_t len)
489
{
490
    unsigned long ranbuf, *lp;
491
    lp = (unsigned long *)buf;
492
    while (len > 0) {
493
        ranbuf = arc4random();
494
        *lp++ = ranbuf;
495
        len -= sizeof(ranbuf);
496
    }
497
}
498
 
499
void
500
read_random_unlimited(void *buf, size_t len)
501
{
502
    get_random_bytes(buf, len);
503
}
504
 
505
void
506
microtime(struct timeval *tp)
507
{
508
    *tp = ktime;
509
    log(LOG_DEBUG, "%s: = %d.%d\n", __FUNCTION__, tp->tv_sec, tp->tv_usec);
510
    ktime.tv_usec++;  // In case clock isn't running yet
511
}
512
 
513
void
514
getmicrotime(struct timeval *tp)
515
{
516
    *tp = ktime;
517
    log(LOG_DEBUG, "%s: = %d.%d\n", __FUNCTION__, tp->tv_sec, tp->tv_usec);
518
    ktime.tv_usec++;  // In case clock isn't running yet
519
}
520
 
521
void
522
getmicrouptime(struct timeval *tp)
523
{
524
    *tp = ktime;
525
    log(LOG_DEBUG, "%s: = %d.%d\n", __FUNCTION__, tp->tv_sec, tp->tv_usec);
526
    ktime.tv_usec++;  // In case clock isn't running yet
527
}
528
 
529
// Taken from kern/kern_clock.c
530
/*
531
 * Compute number of ticks in the specified amount of time.
532
 */
533
#ifndef LONG_MAX
534
#define LONG_MAX 0x7FFFFFFF
535
#endif
536
int
537
tvtohz(struct timeval *tv)
538
{
539
        register unsigned long ticks;
540
        register long sec, usec;
541
 
542
        /*
543
         * If the number of usecs in the whole seconds part of the time
544
         * difference fits in a long, then the total number of usecs will
545
         * fit in an unsigned long.  Compute the total and convert it to
546
         * ticks, rounding up and adding 1 to allow for the current tick
547
         * to expire.  Rounding also depends on unsigned long arithmetic
548
         * to avoid overflow.
549
         *
550
         * Otherwise, if the number of ticks in the whole seconds part of
551
         * the time difference fits in a long, then convert the parts to
552
         * ticks separately and add, using similar rounding methods and
553
         * overflow avoidance.  This method would work in the previous
554
         * case but it is slightly slower and assumes that hz is integral.
555
         *
556
         * Otherwise, round the time difference down to the maximum
557
         * representable value.
558
         *
559
         * If ints have 32 bits, then the maximum value for any timeout in
560
         * 10ms ticks is 248 days.
561
         */
562
        sec = tv->tv_sec;
563
        usec = tv->tv_usec;
564
        if (usec < 0) {
565
                sec--;
566
                usec += 1000000;
567
        }
568
        if (sec < 0) {
569
#ifdef DIAGNOSTIC
570
                if (usec > 0) {
571
                        sec++;
572
                        usec -= 1000000;
573
                }
574
                printf("tvotohz: negative time difference %ld sec %ld usec\n",
575
                       sec, usec);
576
#endif
577
                ticks = 1;
578
        } else if (sec <= LONG_MAX / 1000000)
579
                ticks = (sec * 1000000 + (unsigned long)usec + (tick - 1))
580
                        / tick + 1;
581
        else if (sec <= LONG_MAX / hz)
582
                ticks = sec * hz
583
                        + ((unsigned long)usec + (tick - 1)) / tick + 1;
584
        else
585
                ticks = LONG_MAX;
586
        if (ticks > INT_MAX)
587
                ticks = INT_MAX;
588
        return ((int)ticks);
589
}
590
 
591
void
592
get_mono_time(void)
593
{
594
    panic("get_mono_time");
595
}
596
 
597
void
598
csignal(pid_t pgid, int signum, uid_t uid, uid_t euid)
599
{
600
    panic("csignal");
601
}
602
 
603
int
604
bcmp(const void *_p1, const void *_p2, size_t len)
605
{
606
    int res = 0;
607
    unsigned char *p1 = (unsigned char *)_p1;
608
    unsigned char *p2 = (unsigned char *)_p2;
609
    while (len-- > 0) {
610
        res = *p1++ - *p2++;
611
        if (res) break;
612
    }
613
    return res;
614
}
615
 
616
int
617
copyout(const void *s, void *d, size_t len)
618
{
619
    memcpy(d, s, len);
620
    return 0;
621
}
622
 
623
int
624
copyin(const void *s, void *d, size_t len)
625
{
626
    memcpy(d, s, len);
627
    return 0;
628
}
629
 
630
void
631
ovbcopy(const void *s, void *d, size_t len)
632
{
633
    memmove(d, s, len);
634
}
635
 
636
 
637
// ------------------------------------------------------------------------
638
// THE NETWORK THREAD ITSELF
639
//
640
// Network software interrupt handler
641
//   This function is run as a separate thread to allow
642
// processing of network events (mostly incoming packets)
643
// at "user level" instead of at interrupt time.
644
//
645
// The actual handlers are 'registered' at system startup
646
//
647
 
648
// The set of handlers
649
static netisr_t *_netisr_handlers[NETISR_MAX+1];
650
struct ifqueue  ipintrq;
651
#ifdef INET6
652
struct ifqueue  ip6intrq;
653
#endif
654
char *hostname = "eCos_node";
655
 
656
// Register a 'netisr' handler for a given level
657
int
658
register_netisr(int level, netisr_t *fun)
659
{
660
    CYG_ASSERT(level <= NETISR_MAX, "invalid netisr level");
661
    CYG_ASSERT(_netisr_handlers[level] == 0, "re-registered netisr");
662
    _netisr_handlers[level] = fun;
663
    return 0;  // ignored
664
}
665
 
666
//int unregister_netisr __P((int));
667
 
668
static void
669
cyg_netint(cyg_addrword_t param)
670
{
671
    cyg_flag_value_t curisr;
672
    int lvl, spl;
673
 
674
    while (true) {
675
        curisr = cyg_flag_wait(&netint_flags, NETISR_ANY,
676
                               CYG_FLAG_WAITMODE_OR|CYG_FLAG_WAITMODE_CLR);
677
        spl = splsoftnet(); // Prevent any overlapping "stack" processing
678
        for (lvl = NETISR_MIN;  lvl <= NETISR_MAX;  lvl++) {
679
            if (curisr & (1<<lvl)) {
680
                CYG_ASSERT(_netisr_handlers[lvl] != 0, "unregistered netisr handler");
681
                (*_netisr_handlers[lvl])();
682
            }
683
        }
684
        splx(spl);
685
    }
686
}
687
 
688
 
689
// This just sets one of the pseudo-ISR bits used above.
690
void
691
setsoftnet(void)
692
{
693
    // This is called if we are out of MBUFs - it doesn't do anything, and
694
    // that situation is handled OK, so don't bother with the diagnostic:
695
 
696
    // diag_printf("setsoftnet\n");
697
 
698
    // No need to do this because it is ignored anyway:
699
    // schednetisr(NETISR_SOFTNET);
700
}
701
 
702
 
703
/* Update the kernel globel ktime. */
704
static void
705
cyg_ktime_func(cyg_handle_t alarm,cyg_addrword_t data)
706
{
707
    cyg_tick_count_t now = cyg_current_time();
708
 
709
    ktime.tv_usec = (now % hz) * tick;
710
    ktime.tv_sec = 1 + now / hz;
711
}
712
 
713
static void
714
cyg_ktime_init(void)
715
{
716
    cyg_handle_t ktime_alarm_handle;
717
    static cyg_alarm ktime_alarm;
718
    cyg_handle_t counter;
719
 
720
    // Do not start at 0 - net stack thinks 0 an invalid time;
721
    // Have a valid time available from right now:
722
    ktime.tv_usec = 0;
723
    ktime.tv_sec = 1;
724
 
725
    cyg_clock_to_counter(cyg_real_time_clock(),&counter);
726
    cyg_alarm_create(counter,
727
                     cyg_ktime_func,
728
                     0,
729
                     &ktime_alarm_handle,
730
                     &ktime_alarm);
731
 
732
    /* We want one alarm every 10ms. */
733
    cyg_alarm_initialize(ktime_alarm_handle,cyg_current_time()+1,1);
734
    cyg_alarm_enable(ktime_alarm_handle);
735
}
736
 
737
int
738
cyg_ticks(void)
739
{
740
    cyg_tick_count_t now = cyg_current_time();
741
    return (int)now;
742
}
743
 
744
//
745
// Network initialization
746
//   This function is called during system initialization to setup the whole
747
// networking environment.
748
 
749
// Linker magic to execute this function as 'init'
750
extern void cyg_do_net_init(void);
751
 
752
extern void ifinit(void);
753
extern void loopattach(int);
754
extern void bridgeattach(int);
755
 
756
// Internal init functions:
757
extern void cyg_alarm_timeout_init(void);
758
extern void cyg_tsleep_init(void);
759
 
760
static void
761
cyg_net_init_devs(void *ignored)
762
{
763
    cyg_netdevtab_entry_t *t;
764
    // Initialize all network devices
765
    for (t = &__NETDEVTAB__[0]; t != &__NETDEVTAB_END__; t++) {
766
        log(LOG_INIT, "Init device '%s'\n", t->name);
767
        if (t->init(t)) {
768
            t->status = CYG_NETDEVTAB_STATUS_AVAIL;
769
        } else {
770
            // What to do if device init fails?
771
            t->status = 0;  // Device not [currently] available
772
        }
773
    }
774
#if 0  // Bridge code not available yet
775
#if NBRIDGE > 0
776
    bridgeattach(0);
777
#endif
778
#endif
779
}
780
SYSINIT(devs, SI_SUB_DEVICES, SI_ORDER_FIRST, cyg_net_init_devs, NULL)
781
 
782
void
783
cyg_net_init(void)
784
{
785
    static int _init = false;
786
    struct init_tab_entry *init_entry;
787
 
788
    if (_init) return;
789
 
790
    cyg_do_net_init();  // Just forces linking in the initializer/constructor
791
    // Initialize interrupt "flags"
792
    cyg_flag_init(&netint_flags);
793
    // Initialize timeouts and net service thread (pseudo-DSRs)
794
    cyg_alarm_timeout_init();
795
    // Initialize tsleep/wakeup support
796
    cyg_tsleep_init();
797
    // Initialize network memory system
798
    cyg_kmem_init();
799
    // Initialize network time
800
    cyg_ktime_init();
801
    // Create network background thread
802
    cyg_thread_create(CYGPKG_NET_THREAD_PRIORITY, // Priority
803
                      cyg_netint,               // entry
804
                      0,                        // entry parameter
805
                      "Network support",        // Name
806
                      &netint_stack[0],         // Stack
807
                      STACK_SIZE,               // Size
808
                      &netint_thread_handle,    // Handle
809
                      &netint_thread_data       // Thread data structure
810
        );
811
    cyg_thread_resume(netint_thread_handle);    // Start it
812
 
813
    // Run through dynamic initializers
814
    for (init_entry = __NET_INIT_TAB__; init_entry != &__NET_INIT_TAB_END__;  init_entry++) {
815
        log(LOG_INIT, "[%s] Init: %s(%p)\n", __FUNCTION__, init_entry->name, init_entry->data);
816
        (*init_entry->fun)(init_entry->data);
817
    }
818
    log(LOG_INIT, "[%s] Done\n", __FUNCTION__);
819
 
820
    // Done
821
    _init = true;
822
}
823
 
824
 
825
#include <net/if.h>
826
#include <net/netdb.h>
827
#include <net/route.h>
828
externC void if_indextoname(int indx, char *buf, int len);
829
 
830
typedef void pr_fun(char *fmt, ...);
831
 
832
static void
833
_mask(struct sockaddr *sa, char *buf, int _len)
834
{
835
    char *cp = ((char *)sa) + 4;
836
    int len = sa->sa_len - 4;
837
    int tot = 0;
838
 
839
    while (len-- > 0) {
840
        if (tot) *buf++ = '.';
841
        buf += diag_sprintf(buf, "%d", *cp++);
842
        tot++;
843
    }
844
 
845
    while (tot < 4) {
846
        if (tot) *buf++ = '.';
847
        buf += diag_sprintf(buf, "%d", 0);
848
        tot++;
849
    }
850
}
851
 
852
static void
853
_show_ifp(struct ifnet *ifp, pr_fun *pr)
854
{
855
    struct ifaddr *ifa;
856
    char name[64], addr[64], netmask[64], broadcast[64];
857
 
858
    if_indextoname(ifp->if_index, name, 64);
859
    (*pr)("%-8s", name);
860
    TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
861
        if (ifa->ifa_addr->sa_family != AF_LINK) {
862
            getnameinfo (ifa->ifa_addr, ifa->ifa_addr->sa_len, addr, sizeof(addr), 0, 0, 0);
863
            getnameinfo (ifa->ifa_dstaddr, ifa->ifa_dstaddr->sa_len, broadcast, sizeof(broadcast), 0, 0, 0);
864
            _mask(ifa->ifa_netmask, netmask, 64);
865
            (*pr)("IP: %s, Broadcast: %s, Netmask: %s\n", addr, broadcast, netmask);
866
            (*pr)("        ");
867
            if ((ifp->if_flags & IFF_UP)) (*pr)("UP ");
868
            if ((ifp->if_flags & IFF_BROADCAST)) (*pr)("BROADCAST ");
869
            if ((ifp->if_flags & IFF_LOOPBACK)) (*pr)("LOOPBACK ");
870
            if ((ifp->if_flags & IFF_RUNNING)) (*pr)("RUNNING ");
871
            if ((ifp->if_flags & IFF_PROMISC)) (*pr)("PROMISC ");
872
            if ((ifp->if_flags & IFF_MULTICAST)) (*pr)("MULTICAST ");
873
            if ((ifp->if_flags & IFF_ALLMULTI)) (*pr)("ALLMULTI ");
874
            (*pr)("MTU: %d, Metric: %d\n", ifp->if_mtu, ifp->if_metric);
875
            (*pr)("        Rx - Packets: %d, Bytes: %d", ifa->if_data.ifi_ipackets, ifa->if_data.ifi_ibytes);
876
            (*pr)(", Tx - Packets: %d, Bytes: %d\n", ifa->if_data.ifi_opackets, ifa->if_data.ifi_obytes);
877
        }
878
    }
879
}
880
 
881
static int
882
_dumpentry(struct radix_node *rn, void *vw)
883
{
884
    struct rtentry *rt = (struct rtentry *)rn;
885
    struct sockaddr *dst, *gate, *netmask, *genmask;
886
    char addr[32], *cp;
887
    pr_fun *pr = (pr_fun *)vw;
888
 
889
    dst = rt_key(rt);
890
    gate = rt->rt_gateway;
891
    netmask = rt_mask(rt);
892
    genmask = rt->rt_genmask;
893
    if ((rt->rt_flags & (RTF_UP | RTF_WASCLONED)) == RTF_UP) {
894
        if (netmask == NULL) {
895
            return 0;
896
        }
897
        _inet_ntop(dst, addr, sizeof(addr));
898
        (*pr)("%-15s ", addr);
899
        if (gate != NULL) {
900
            _inet_ntop(gate, addr, sizeof(addr));
901
            (*pr)("%-15s ", addr);
902
        } else {
903
            (*pr)("%-15s ", " ");
904
        }
905
        if (netmask != NULL) {
906
            _mask(netmask, addr, sizeof(addr));
907
            (*pr)("%-15s ", addr);
908
        } else {
909
            (*pr)("%-15s ", " ");
910
        }
911
        cp = addr;
912
        if ((rt->rt_flags & RTF_UP)) *cp++ = 'U';
913
        if ((rt->rt_flags & RTF_GATEWAY)) *cp++ = 'G';
914
        if ((rt->rt_flags & RTF_STATIC)) *cp++ = 'S';
915
        if ((rt->rt_flags & RTF_DYNAMIC)) *cp++ = 'D';
916
        *cp = '\0';
917
        (*pr)("%-8s ", addr);  // Flags
918
        if_indextoname(rt->rt_ifp->if_index, addr, 64);
919
        (*pr)("%-8s ", addr);
920
        (*pr)("\n");
921
    }
922
    return 0;
923
}
924
 
925
void
926
show_network_tables(pr_fun *pr)
927
{
928
    int i, error;
929
    struct radix_node_head *rnh;
930
    struct ifnet *ifp;
931
 
932
    cyg_scheduler_lock();
933
    (*pr)("Routing tables\n");
934
    (*pr)("Destination     Gateway         Mask            Flags    Interface\n");
935
    for (i = 1; i <= AF_MAX; i++) {
936
        if ((rnh = rt_tables[i]) != NULL) {
937
            error = rnh->rnh_walktree(rnh, _dumpentry, pr);
938
        }
939
    }
940
 
941
    (*pr)("Interface statistics\n");
942
    for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) {
943
        _show_ifp(ifp, pr);
944
    }
945
    cyg_scheduler_unlock();
946
}
947
 
948
#endif // CYGPKG_NET_DRIVER_FRAMEWORK
949
 
950
// EOF support.c

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.