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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [libnetworking/] [rtems/] [rtems_glue.c] - Blame information for rev 30

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

Line No. Rev Author Line
1 30 unneback
/*
2
 *  $Id: rtems_glue.c,v 1.2 2001-09-27 12:02:00 chris Exp $
3
 */
4
 
5
#include <string.h>
6
#include <stdarg.h>
7
#include <stdio.h>
8
#include <errno.h>
9
 
10
#include <rtems.h>
11
#include <rtems/libio.h>
12
#include <rtems/error.h>
13
#include <rtems/rtems_bsdnet.h>
14
#include <sys/types.h>
15
#include <sys/param.h>
16
#include <sys/domain.h>
17
#include <sys/mbuf.h>
18
#include <sys/socketvar.h>
19
#include <sys/socket.h>
20
#include <sys/sockio.h>
21
#include <sys/callout.h>
22
#include <sys/proc.h>
23
#include <sys/ioctl.h>
24
#include <net/if.h>
25
#include <net/route.h>
26
#include <netinet/in.h>
27
#include <vm/vm.h>
28
#include <arpa/inet.h>
29
 
30
#include <net/netisr.h>
31
#include <net/route.h>
32
 
33
/*
34
 * Memory allocation
35
 */
36
static int nmbuf        = (64 * 1024) / MSIZE;
37
       int nmbclusters  = (128 * 1024) / MCLBYTES;
38
 
39
/*
40
 * Socket buffering parameters
41
 */
42
unsigned long sb_efficiency = 8;
43
 
44
/*
45
 * Network task synchronization
46
 */
47
static rtems_id networkSemaphore;
48
static rtems_id networkDaemonTid;
49
static rtems_unsigned32 networkDaemonPriority;
50
static void networkDaemon (void *task_argument);
51
 
52
/*
53
 * Network timing
54
 */
55
int                     rtems_bsdnet_ticks_per_second;
56
int                     rtems_bsdnet_microseconds_per_tick;
57
 
58
/*
59
 * Callout processing
60
 */
61
static rtems_interval   ticksWhenCalloutsLastChecked;
62
static struct callout *callfree, calltodo;
63
 
64
/*
65
 * FreeBSD variables
66
 */
67
int nfs_diskless_valid;
68
 
69
/*
70
 * BOOTP values
71
 */
72
struct in_addr rtems_bsdnet_log_host_address;
73
struct in_addr rtems_bsdnet_bootp_server_address;
74
char *rtems_bsdnet_bootp_boot_file_name;
75
char *rtems_bsdnet_bootp_server_name;
76
char *rtems_bsdnet_domain_name;
77
struct in_addr rtems_bsdnet_nameserver[sizeof rtems_bsdnet_config.name_server /
78
                        sizeof rtems_bsdnet_config.name_server[0]];
79
int rtems_bsdnet_nameserver_count;
80
struct in_addr rtems_bsdnet_ntpserver[sizeof rtems_bsdnet_config.ntp_server /
81
                        sizeof rtems_bsdnet_config.ntp_server[0]];
82
int rtems_bsdnet_ntpserver_count;
83
long rtems_bsdnet_timeoffset;
84
 
85
/*
86
 * Perform FreeBSD memory allocation.
87
 * FIXME: This should be modified to keep memory allocation statistics.
88
 */
89
#undef malloc
90
#undef free
91
extern void *malloc (size_t);
92
extern void free (void *);
93
void *
94
rtems_bsdnet_malloc (unsigned long size, int type, int flags)
95
{
96
        void *p;
97
        int try = 0;
98
 
99
        for (;;) {
100
                p = malloc (size);
101
                if (p || (flags & M_NOWAIT))
102
                        return p;
103
                rtems_bsdnet_semaphore_release ();
104
                if (++try >= 30) {
105
                        printf ("rtems_bsdnet_malloc still waiting.\n");
106
                        try = 0;
107
                }
108
                rtems_task_wake_after (rtems_bsdnet_ticks_per_second);
109
                rtems_bsdnet_semaphore_obtain ();
110
        }
111
}
112
 
113
/*
114
 * Free FreeBSD memory
115
 * FIXME: This should be modified to keep memory allocation statistics.
116
 */
117
void
118
rtems_bsdnet_free (void *addr, int type)
119
{
120
        free (addr);
121
}
122
 
123
/*
124
 * Do the initializations required by the BSD code
125
 */
126
static int
127
bsd_init (void)
128
{
129
        int i;
130
        char *p;
131
 
132
        /*
133
         * Set up mbuf cluster data strutures
134
         */
135
        p = malloc ((nmbclusters*MCLBYTES)+MCLBYTES-1);
136
        p = (char *)(((unsigned long)p + (MCLBYTES-1)) & ~(MCLBYTES-1));
137
        if (p == NULL) {
138
                printf ("Can't get network cluster memory.\n");
139
                return -1;
140
        }
141
        mbutl = (struct mbuf *)p;
142
        for (i = 0; i < nmbclusters; i++) {
143
                ((union mcluster *)p)->mcl_next = mclfree;
144
                mclfree = (union mcluster *)p;
145
                p += MCLBYTES;
146
                mbstat.m_clfree++;
147
        }
148
        mbstat.m_clusters = nmbclusters;
149
        mclrefcnt = malloc (nmbclusters);
150
        if (mclrefcnt == NULL) {
151
                printf ("Can't get mbuf cluster reference counts memory.\n");
152
                return -1;
153
        }
154
        memset (mclrefcnt, '\0', nmbclusters);
155
 
156
        /*
157
         * Set up mbuf data structures
158
         */
159
 
160
        p = malloc(nmbuf * MSIZE + MSIZE - 1);
161
        p = (char *)(((unsigned int)p + MSIZE - 1) & ~(MSIZE - 1));
162
        if (p == NULL) {
163
                printf ("Can't get network memory.\n");
164
                return -1;
165
        }
166
        for (i = 0; i < nmbuf; i++) {
167
                ((struct mbuf *)p)->m_next = mmbfree;
168
                mmbfree = (struct mbuf *)p;
169
                p += MSIZE;
170
        }
171
        mbstat.m_mbufs = nmbuf;
172
        mbstat.m_mtypes[MT_FREE] = nmbuf;
173
 
174
        /*
175
         * Set up domains
176
         */
177
        {
178
        extern struct domain routedomain;
179
        extern struct domain inetdomain;
180
 
181
        routedomain.dom_next = domains;
182
        domains = &routedomain;
183
        inetdomain.dom_next = domains;
184
        domains = &inetdomain;
185
        domaininit (NULL);
186
        }
187
 
188
        /*
189
         * Set up interfaces
190
         */
191
        ifinit (NULL);
192
        return 0;
193
}
194
 
195
/*
196
 * Initialize and start network operations
197
 */
198
static int
199
rtems_bsdnet_initialize (void)
200
{
201
        rtems_status_code sc;
202
 
203
        /*
204
         * Set the priority of all network tasks
205
         */
206
        if (rtems_bsdnet_config.network_task_priority == 0)
207
                networkDaemonPriority = 100;
208
        else
209
                networkDaemonPriority = rtems_bsdnet_config.network_task_priority;
210
 
211
        /*
212
         * Set the memory allocation limits
213
         */
214
        if (rtems_bsdnet_config.mbuf_bytecount)
215
                nmbuf = rtems_bsdnet_config.mbuf_bytecount / MSIZE;
216
        if (rtems_bsdnet_config.mbuf_cluster_bytecount)
217
                nmbclusters = rtems_bsdnet_config.mbuf_cluster_bytecount / MCLBYTES;
218
 
219
        /*
220
         * Create the task-synchronization semaphore
221
         */
222
        sc = rtems_semaphore_create (rtems_build_name('B', 'S', 'D', 'n'),
223
                                        0,
224
                                        RTEMS_FIFO |
225
                                                RTEMS_BINARY_SEMAPHORE |
226
                                                RTEMS_NO_INHERIT_PRIORITY |
227
                                                RTEMS_NO_PRIORITY_CEILING |
228
                                                RTEMS_LOCAL,
229
                                        0,
230
                                        &networkSemaphore);
231
        if (sc != RTEMS_SUCCESSFUL) {
232
                printf ("Can't create network seamphore: `%s'\n", rtems_status_text (sc));
233
                return -1;
234
        }
235
 
236
        /*
237
         * Compute clock tick conversion factors
238
         */
239
        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &rtems_bsdnet_ticks_per_second);
240
        if (rtems_bsdnet_ticks_per_second <= 0)
241
                rtems_bsdnet_ticks_per_second = 1;
242
        rtems_bsdnet_microseconds_per_tick = 1000000 / rtems_bsdnet_ticks_per_second;
243
 
244
        /*
245
         * Ensure that `seconds' is greater than 0
246
         */
247
        rtems_task_wake_after (rtems_bsdnet_ticks_per_second);
248
 
249
        /*
250
         * Set up BSD-style sockets
251
         */
252
        if (bsd_init () < 0)
253
                return -1;
254
 
255
        /*
256
         * Start network daemon
257
         */
258
        networkDaemonTid = rtems_bsdnet_newproc ("ntwk", 4096, networkDaemon, NULL);
259
 
260
        /*
261
         * Let other network tasks begin
262
         */
263
        rtems_bsdnet_semaphore_release ();
264
        return 0;
265
}
266
 
267
/*
268
 * Obtain network mutex
269
 */
270
void
271
rtems_bsdnet_semaphore_obtain (void)
272
{
273
        rtems_status_code sc;
274
 
275
        sc = rtems_semaphore_obtain (networkSemaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
276
        if (sc != RTEMS_SUCCESSFUL)
277
                rtems_panic ("Can't obtain network semaphore: `%s'\n", rtems_status_text (sc));
278
}
279
 
280
/*
281
 * Release network mutex
282
 */
283
void
284
rtems_bsdnet_semaphore_release (void)
285
{
286
        rtems_status_code sc;
287
 
288
        sc = rtems_semaphore_release (networkSemaphore);
289
        if (sc != RTEMS_SUCCESSFUL)
290
                rtems_panic ("Can't release network semaphore: `%s'\n", rtems_status_text (sc));
291
                                                                                }
292
 
293
/*
294
 * Wait for something to happen to a socket buffer
295
 */
296
int
297
sbwait(sb)
298
        struct sockbuf *sb;
299
{
300
        rtems_event_set events;
301
        rtems_id tid;
302
        rtems_status_code sc;
303
 
304
        /*
305
         * Soak up any pending events.
306
         * The sleep/wakeup synchronization in the FreeBSD
307
         * kernel has no memory.
308
         */
309
        rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT, &events);
310
 
311
        /*
312
         * Set this task as the target of the wakeup operation.
313
         */
314
        rtems_task_ident (RTEMS_SELF, 0, &tid);
315
        sb->sb_sel.si_pid = tid;
316
 
317
        /*
318
         * Show that socket is waiting
319
         */
320
        sb->sb_flags |= SB_WAIT;
321
 
322
        /*
323
         * Release the network semaphore.
324
         */
325
        rtems_bsdnet_semaphore_release ();
326
 
327
        /*
328
         * Wait for the wakeup event.
329
         */
330
        sc = rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, sb->sb_timeo, &events);
331
 
332
        /*
333
         * Reobtain the network semaphore.
334
         */
335
        rtems_bsdnet_semaphore_obtain ();
336
 
337
        /*
338
         * Return the status of the wait.
339
         */
340
        switch (sc) {
341
        case RTEMS_SUCCESSFUL:  return 0;
342
        case RTEMS_TIMEOUT:     return EWOULDBLOCK;
343
        default:                return ENXIO;
344
        }
345
}
346
 
347
 
348
/*
349
 * Wake up the task waiting on a socket buffer.
350
 */
351
void
352
sowakeup(so, sb)
353
        register struct socket *so;
354
        register struct sockbuf *sb;
355
{
356
        if (sb->sb_flags & SB_WAIT) {
357
                sb->sb_flags &= ~SB_WAIT;
358
                rtems_event_send (sb->sb_sel.si_pid, SBWAIT_EVENT);
359
        }
360
        if (sb->sb_wakeup) {
361
                (*sb->sb_wakeup) (so, sb->sb_wakeuparg);
362
        }
363
}
364
 
365
/*
366
 * For now, a socket can be used by only one task at a time.
367
 */
368
int
369
sb_lock(sb)
370
        register struct sockbuf *sb;
371
{
372
        rtems_panic ("Socket buffer is already in use.");
373
        return 0;
374
}
375
void
376
wakeup (void *p)
377
{
378
        rtems_panic ("Wakeup called");
379
}
380
 
381
/*
382
 * Wait for a connection/disconnection event.
383
 */
384
int
385
soconnsleep (struct socket *so)
386
{
387
        rtems_event_set events;
388
        rtems_id tid;
389
        rtems_status_code sc;
390
 
391
        /*
392
         * Soak up any pending events.
393
         * The sleep/wakeup synchronization in the FreeBSD
394
         * kernel has no memory.
395
         */
396
        rtems_event_receive (SOSLEEP_EVENT, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT, &events);
397
 
398
        /*
399
         * Set this task as the target of the wakeup operation.
400
         */
401
        if (so->so_pgid)
402
                rtems_panic ("Another task is already sleeping on that socket");
403
        rtems_task_ident (RTEMS_SELF, 0, &tid);
404
        so->so_pgid = tid;
405
 
406
        /*
407
         * Wait for the wakeup event.
408
         */
409
        sc = rtems_bsdnet_event_receive (SOSLEEP_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, so->so_rcv.sb_timeo, &events);
410
 
411
        /*
412
         * Relinquish ownership of the socket.
413
         */
414
        so->so_pgid = 0;
415
 
416
        switch (sc) {
417
        case RTEMS_SUCCESSFUL:  return 0;
418
        case RTEMS_TIMEOUT:     return EWOULDBLOCK;
419
        default:                return ENXIO;
420
        }
421
}
422
 
423
/*
424
 * Wake up a task waiting for a connection/disconnection to complete.
425
 */
426
void
427
soconnwakeup (struct socket *so)
428
{
429
        if (so->so_pgid)
430
                rtems_event_send (so->so_pgid, SOSLEEP_EVENT);
431
}
432
 
433
/*
434
 * Send an event to the network daemon.
435
 * This corresponds to sending a software interrupt in the BSD kernel.
436
 */
437
void
438
rtems_bsdnet_schednetisr (int n)
439
{
440
        rtems_event_send (networkDaemonTid, 1 << n);
441
}
442
 
443
/*
444
 * The network daemon
445
 * This provides a context to run BSD software interrupts
446
 */
447
static void
448
networkDaemon (void *task_argument)
449
{
450
        rtems_event_set events;
451
        rtems_interval now;
452
        int ticksPassed;
453
        unsigned32 timeout;
454
        struct callout *c;
455
 
456
        for (;;) {
457
                c = calltodo.c_next;
458
                if (c)
459
                        timeout = c->c_time;
460
                else
461
                        timeout = RTEMS_NO_TIMEOUT;
462
                rtems_bsdnet_event_receive (NETISR_EVENTS,
463
                                                RTEMS_EVENT_ANY | RTEMS_WAIT,
464
                                                timeout,
465
                                                &events);
466
                if (events & NETISR_IP_EVENT)
467
                        ipintr ();
468
                if (events & NETISR_ARP_EVENT)
469
                        arpintr ();
470
                rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
471
                ticksPassed = now - ticksWhenCalloutsLastChecked;
472
                if (ticksPassed != 0) {
473
                        ticksWhenCalloutsLastChecked = now;
474
 
475
                        c = calltodo.c_next;
476
                        if (c) {
477
                                c->c_time -= ticksPassed;
478
                                while ((c = calltodo.c_next) != NULL && c->c_time <= 0) {
479
                                        void *arg;
480
                                        void (*func) (void *);
481
 
482
                                        func = c->c_func;
483
                                        arg = c->c_arg;
484
                                        calltodo.c_next = c->c_next;
485
                                        c->c_next = callfree;
486
                                        callfree = c;
487
                                        (*func)(arg);
488
                                }
489
                        }
490
                }
491
        }
492
}
493
 
494
/*
495
 * Structure passed to task-start stub
496
 */
497
struct newtask {
498
        void (*entry)(void *);
499
        void *arg;
500
};
501
 
502
/*
503
 * Task-start stub
504
 */
505
static void
506
taskEntry (rtems_task_argument arg)
507
{
508
        struct newtask t;
509
 
510
        /*
511
         * Pick up task information and free
512
         * the memory allocated to pass the
513
         * information to this task.
514
         */
515
        t = *(struct newtask *)arg;
516
        free ((struct newtask *)arg);
517
 
518
        /*
519
         * Enter the competition for the network semaphore
520
         */
521
        rtems_bsdnet_semaphore_obtain ();
522
 
523
        /*
524
         * Enter the task
525
         */
526
        (*t.entry)(t.arg);
527
        rtems_panic ("Network task returned!\n");
528
}
529
 
530
/*
531
 * Start a network task
532
 */
533
rtems_id
534
rtems_bsdnet_newproc (char *name, int stacksize, void(*entry)(void *), void *arg)
535
{
536
        struct newtask *t;
537
        char nm[4];
538
        rtems_id tid;
539
        rtems_status_code sc;
540
 
541
        strncpy (nm, name, 4);
542
        sc = rtems_task_create (rtems_build_name(nm[0], nm[1], nm[2], nm[3]),
543
                networkDaemonPriority,
544
                stacksize,
545
                RTEMS_PREEMPT|RTEMS_NO_TIMESLICE|RTEMS_NO_ASR|RTEMS_INTERRUPT_LEVEL(0),
546
                RTEMS_NO_FLOATING_POINT|RTEMS_LOCAL,
547
                &tid);
548
        if (sc != RTEMS_SUCCESSFUL)
549
                rtems_panic ("Can't create network daemon `%s': `%s'\n", name, rtems_status_text (sc));
550
 
551
        /*
552
         * Set up task arguments
553
         */
554
        t = malloc (sizeof *t);
555
        t->entry = entry;
556
        t->arg = arg;
557
 
558
        /*
559
         * Start the task
560
         */
561
        sc = rtems_task_start (tid, taskEntry, (rtems_task_argument)t);
562
        if (sc != RTEMS_SUCCESSFUL)
563
                rtems_panic ("Can't start network daemon `%s': `%s'\n", name, rtems_status_text (sc));
564
 
565
        /*
566
         * Let our caller know the i.d. of the new task
567
         */
568
        return tid;
569
}
570
 
571
rtems_status_code rtems_bsdnet_event_receive (
572
  rtems_event_set  event_in,
573
  rtems_option     option_set,
574
  rtems_interval   ticks,
575
  rtems_event_set *event_out)
576
{
577
        rtems_status_code sc;
578
 
579
        rtems_bsdnet_semaphore_release ();
580
        sc = rtems_event_receive (event_in, option_set, ticks, event_out);
581
        rtems_bsdnet_semaphore_obtain ();
582
        return sc;
583
}
584
 
585
/*
586
 * Return time since startup
587
 */
588
void
589
microtime (struct timeval *t)
590
{
591
        rtems_interval now;
592
 
593
        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
594
        t->tv_sec = now / rtems_bsdnet_ticks_per_second;
595
        t->tv_usec = (now % rtems_bsdnet_ticks_per_second) * rtems_bsdnet_microseconds_per_tick;
596
}
597
 
598
unsigned long
599
rtems_bsdnet_seconds_since_boot (void)
600
{
601
        rtems_interval now;
602
 
603
        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
604
        return now / rtems_bsdnet_ticks_per_second;
605
}
606
 
607
/*
608
 * Fake random number generator
609
 */
610
unsigned long
611
rtems_bsdnet_random (void)
612
{
613
        rtems_interval now;
614
 
615
        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
616
        return (now * 99991);
617
}
618
 
619
/*
620
 * Callout list processing
621
 */
622
void
623
timeout(void (*ftn)(void *), void *arg, int ticks)
624
{
625
        register struct callout *new, *p, *t;
626
 
627
        if (ticks <= 0)
628
                ticks = 1;
629
 
630
        /* Fill in the next free callout structure. */
631
        if (callfree == NULL) {
632
                callfree = malloc (sizeof *callfree);
633
                if (callfree == NULL)
634
                        rtems_panic ("No memory for timeout table entry");
635
                callfree->c_next = NULL;
636
        }
637
 
638
        new = callfree;
639
        callfree = new->c_next;
640
        new->c_arg = arg;
641
        new->c_func = ftn;
642
 
643
        /*
644
         * The time for each event is stored as a difference from the time
645
         * of the previous event on the queue.  Walk the queue, correcting
646
         * the ticks argument for queue entries passed.  Correct the ticks
647
         * value for the queue entry immediately after the insertion point
648
         * as well.  Watch out for negative c_time values; these represent
649
         * overdue events.
650
         */
651
        for (p = &calltodo;
652
            (t = p->c_next) != NULL && ticks > t->c_time; p = t)
653
                if (t->c_time > 0)
654
                        ticks -= t->c_time;
655
        new->c_time = ticks;
656
        if (t != NULL)
657
                t->c_time -= ticks;
658
 
659
        /* Insert the new entry into the queue. */
660
        p->c_next = new;
661
        new->c_next = t;
662
}
663
 
664
/*
665
 * Ticks till specified time
666
 * XXX: This version worries only about seconds, but that's good
667
 * enough for the way the network code uses this routine.
668
 */
669
int
670
hzto(struct timeval *tv)
671
{
672
        long diff = tv->tv_sec - rtems_bsdnet_seconds_since_boot();
673
 
674
        if (diff <= 0)
675
                return 1;
676
        return diff * rtems_bsdnet_ticks_per_second;
677
}
678
 
679
/*
680
 * Kernel debugging
681
 */
682
int rtems_bsdnet_log_priority;
683
void
684
rtems_bsdnet_log (int priority, const char *fmt, ...)
685
{
686
        va_list args;
687
 
688
        if (priority & rtems_bsdnet_log_priority) {
689
                va_start (args, fmt);
690
                vprintf (fmt, args);
691
                va_end (args);
692
        }
693
}
694
 
695
/*
696
 * IP header checksum routine for processors which don't have an inline version
697
 */
698
u_int
699
in_cksum_hdr (const void *ip)
700
{
701
        rtems_unsigned32 sum;
702
        const rtems_unsigned16 *sp;
703
        int i;
704
 
705
        sum = 0;
706
        sp = (rtems_unsigned16 *)ip;
707
        for (i = 0 ; i < 10 ; i++)
708
                sum += *sp++;
709
        while (sum > 0xFFFF)
710
                sum = (sum & 0xffff) + (sum >> 16);
711
        return ~sum & 0xFFFF;
712
}
713
 
714
/*
715
 * Manipulate routing tables
716
 */
717
int rtems_bsdnet_rtrequest (
718
    int req,
719
    struct sockaddr *dst,
720
    struct sockaddr *gateway,
721
    struct sockaddr *netmask,
722
    int flags,
723
    struct rtentry **net_nrt)
724
{
725
        int error;
726
 
727
        rtems_bsdnet_semaphore_obtain ();
728
        error = rtrequest (req, dst, gateway, netmask, flags, net_nrt);
729
        rtems_bsdnet_semaphore_release ();
730
        if (error) {
731
                errno = error;
732
                return -1;
733
        }
734
        return 0;
735
}
736
 
737
static int
738
rtems_bsdnet_setup (void)
739
{
740
        struct rtems_bsdnet_ifconfig *ifp;
741
        int s;
742
        struct ifreq ifreq;
743
        struct sockaddr_in address;
744
        struct sockaddr_in netmask;
745
        struct sockaddr_in broadcast;
746
        struct sockaddr_in gateway;
747
        int i;
748
        extern char *strdup (const char *cp);
749
 
750
        /*
751
         * Set local parameters
752
         */
753
        if (rtems_bsdnet_config.hostname)
754
                sethostname (rtems_bsdnet_config.hostname,
755
                                        strlen (rtems_bsdnet_config.hostname));
756
        if (rtems_bsdnet_config.domainname)
757
                rtems_bsdnet_domain_name =
758
                                        strdup (rtems_bsdnet_config.domainname);
759
        if (rtems_bsdnet_config.log_host)
760
                rtems_bsdnet_log_host_address.s_addr =
761
                                inet_addr (rtems_bsdnet_config.log_host);
762
        for (i = 0 ; i < sizeof rtems_bsdnet_config.name_server /
763
                        sizeof rtems_bsdnet_config.name_server[0] ; i++) {
764
                if (!rtems_bsdnet_config.name_server[i])
765
                        break;
766
                rtems_bsdnet_nameserver[rtems_bsdnet_nameserver_count++].s_addr
767
                        = inet_addr (rtems_bsdnet_config.name_server[i]);
768
        }
769
        for (i = 0 ; i < sizeof rtems_bsdnet_config.ntp_server /
770
                        sizeof rtems_bsdnet_config.ntp_server[0] ; i++) {
771
                if (!rtems_bsdnet_config.ntp_server[i])
772
                        break;
773
                rtems_bsdnet_ntpserver[rtems_bsdnet_ntpserver_count++].s_addr
774
                        = inet_addr (rtems_bsdnet_config.ntp_server[i]);
775
        }
776
 
777
        /*
778
         * Configure interfaces
779
         */
780
        s = socket (AF_INET, SOCK_DGRAM, 0);
781
        if (s < 0) {
782
                printf ("Can't create initial socket: %s\n", strerror (errno));
783
                return -1;
784
        }
785
        for (ifp = rtems_bsdnet_config.ifconfig ; ifp ; ifp = ifp->next) {
786
                if (ifp->ip_address == NULL)
787
                        continue;
788
 
789
                /*
790
                 * Get the interface flags
791
                 */
792
                strcpy (ifreq.ifr_name, ifp->name);
793
                if (ioctl (s, SIOCGIFFLAGS, &ifreq) < 0) {
794
                        printf ("Can't get %s flags: %s\n", ifp->name, strerror (errno));
795
                        return -1;
796
                }
797
 
798
                /*
799
                 * Bring interface up
800
                 */
801
                ifreq.ifr_flags |= IFF_UP;
802
                if (ioctl (s, SIOCSIFFLAGS, &ifreq) < 0) {
803
                        printf ("Can't bring %s up: %s\n", ifp->name, strerror (errno));
804
                        return -1;
805
                }
806
 
807
                /*
808
                 * Set interface netmask
809
                 */
810
                memset (&netmask, '\0', sizeof netmask);
811
                netmask.sin_len = sizeof netmask;
812
                netmask.sin_family = AF_INET;
813
                netmask.sin_addr.s_addr = inet_addr (ifp->ip_netmask);
814
                memcpy (&ifreq.ifr_addr, &netmask, sizeof netmask);
815
                if (ioctl (s, SIOCSIFNETMASK, &ifreq) < 0) {
816
                        printf ("Can't set %s netmask: %s\n", ifp->name, strerror (errno));
817
                        return -1;
818
                }
819
 
820
                /*
821
                 * Set interface address
822
                 */
823
                memset (&address, '\0', sizeof address);
824
                address.sin_len = sizeof address;
825
                address.sin_family = AF_INET;
826
                address.sin_addr.s_addr = inet_addr (ifp->ip_address);
827
                memcpy (&ifreq.ifr_addr, &address, sizeof address);
828
                if (ioctl (s, SIOCSIFADDR, &ifreq) < 0) {
829
                        printf ("Can't set %s address: %s\n", ifp->name, strerror (errno));
830
                        return -1;
831
                }
832
 
833
                /*
834
                 * Set interface broadcast address
835
                 */
836
                memset (&broadcast, '\0', sizeof broadcast);
837
                broadcast.sin_len = sizeof broadcast;
838
                broadcast.sin_family = AF_INET;
839
                broadcast.sin_addr.s_addr = address.sin_addr.s_addr | ~netmask.sin_addr.s_addr;
840
                memcpy (&ifreq.ifr_broadaddr, &broadcast, sizeof broadcast);
841
                if (ioctl (s, SIOCSIFBRDADDR, &ifreq) < 0)
842
                        printf ("Can't set %s broadcast address: %s\n", ifp->name, strerror (errno));
843
        }
844
 
845
        /*
846
         * We're done with the dummy socket
847
         */
848
        close (s);
849
 
850
        /*
851
         * Set default route
852
         */
853
        if (rtems_bsdnet_config.gateway) {
854
                address.sin_addr.s_addr = INADDR_ANY;
855
                netmask.sin_addr.s_addr = INADDR_ANY;
856
                memset (&gateway, '\0', sizeof gateway);
857
                gateway.sin_len = sizeof gateway;
858
                gateway.sin_family = AF_INET;
859
                gateway.sin_addr.s_addr = inet_addr (rtems_bsdnet_config.gateway);
860
                if (rtems_bsdnet_rtrequest (
861
                                RTM_ADD,
862
                                (struct sockaddr *)&address,
863
                                (struct sockaddr *)&gateway,
864
                                (struct sockaddr *)&netmask,
865
                                (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL) < 0) {
866
                        printf ("Can't set default route: %s\n", strerror (errno));
867
                        return -1;
868
                }
869
        }
870
        return 0;
871
}
872
 
873
/*
874
 * Initialize the network
875
 */
876
int
877
rtems_bsdnet_initialize_network (void)
878
{
879
        struct rtems_bsdnet_ifconfig *ifp;
880
 
881
        /*
882
         * Start network tasks.
883
         * Initialize BSD network data structures.
884
         */
885
        if (rtems_bsdnet_initialize () < 0)
886
                return -1;
887
 
888
        /*
889
         * Attach interfaces
890
         */
891
        for (ifp = rtems_bsdnet_config.ifconfig ; ifp ; ifp = ifp->next) {
892
                rtems_bsdnet_semaphore_obtain ();
893
                (ifp->attach)(ifp);
894
                rtems_bsdnet_semaphore_release ();
895
        }
896
 
897
        /*
898
         * Bring up the network
899
         */
900
        if (rtems_bsdnet_setup () < 0)
901
                return -1;
902
        if (rtems_bsdnet_config.bootp)
903
                (*rtems_bsdnet_config.bootp)();
904
        return 0;
905
}
906
 
907
/*
908
 * Parse a network driver name into a name and a unit number
909
 */
910
int
911
rtems_bsdnet_parse_driver_name (const struct rtems_bsdnet_ifconfig *config, char **namep)
912
{
913
        const char *cp = config->name;
914
        char c;
915
        int unitNumber = 0;
916
 
917
        if (cp == NULL) {
918
                printf ("No network driver name.\n");
919
                return -1;
920
        }
921
        while ((c = *cp++) != '\0') {
922
                if ((c >= '0') && (c <= '9')) {
923
                        int len = cp - config->name;
924
                        if ((len < 2) || (len > 50))
925
                                break;
926
                        for (;;) {
927
                                unitNumber = (unitNumber * 10) + (c - '0');
928
                                c = *cp++;
929
                                if (c == '\0') {
930
                                        char *unitName = malloc (len);
931
                                        if (unitName == NULL) {
932
                                                printf ("No memory.\n");
933
                                                return -1;
934
                                        }
935
                                        strncpy (unitName, config->name, len - 1);
936
                                        unitName[len-1] = '\0';
937
                                        *namep = unitName;
938
                                        return unitNumber;
939
                                }
940
                                if ((c < '0') || (c > '9'))
941
                                        break;
942
                        }
943
                        break;
944
                }
945
        }
946
        printf ("Bad network driver name `%s'.\n", config->name);
947
        return -1;
948
}
949
 
950
/*
951
 * Handle requests for more network memory
952
 * XXX: Another possibility would be to use a semaphore here with
953
 *      a release in the mbuf free macro.  I have chosen this `polling'
954
 *      approach because:
955
 *      1) It is simpler.
956
 *      2) It adds no complexity to the free macro.
957
 *      3) Running out of mbufs should be a rare
958
 *         condition -- predeployment testing of
959
 *         an application should indicate the
960
 *         required mbuf pool size.
961
 * XXX: Should there be a panic if a task is stuck in the loop for
962
 *      more than a minute or so?
963
 */
964
int
965
m_mballoc (int nmb, int nowait)
966
{
967
        if (nowait)
968
                return 0;
969
        m_reclaim ();
970
        if (mmbfree == NULL) {
971
                int try = 0;
972
                int print_limit = 30 * rtems_bsdnet_ticks_per_second;
973
 
974
                mbstat.m_wait++;
975
                for (;;) {
976
                        rtems_bsdnet_semaphore_release ();
977
                        rtems_task_wake_after (1);
978
                        rtems_bsdnet_semaphore_obtain ();
979
                        if (mmbfree)
980
                                break;
981
                        if (++try >= print_limit) {
982
                                printf ("Still waiting for mbuf.\n");
983
                                try = 0;
984
                        }
985
                }
986
        }
987
        else {
988
                mbstat.m_drops++;
989
        }
990
        return 1;
991
}
992
 
993
int
994
m_clalloc(ncl, nowait)
995
{
996
        if (nowait)
997
                return 0;
998
        m_reclaim ();
999
        if (mclfree == NULL) {
1000
                int try = 0;
1001
                int print_limit = 30 * rtems_bsdnet_ticks_per_second;
1002
 
1003
                mbstat.m_wait++;
1004
                for (;;) {
1005
                        rtems_bsdnet_semaphore_release ();
1006
                        rtems_task_wake_after (1);
1007
                        rtems_bsdnet_semaphore_obtain ();
1008
                        if (mclfree)
1009
                                break;
1010
                        if (++try >= print_limit) {
1011
                                printf ("Still waiting for mbuf cluster.\n");
1012
                                try = 0;
1013
                        }
1014
                }
1015
        }
1016
        else {
1017
                mbstat.m_drops++;
1018
        }
1019
        return 1;
1020
}

powered by: WebSVN 2.1.0

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