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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [libnetworking/] [pppd/] [modem_example/] [modem.c] - Blame information for rev 173

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 30 unneback
/*
2
 *  Modem device driver for RTEMS
3
 *  Author: Tomasz Domin (dot@comarch.pl)
4
 *  Copyright (C) 1998 by ComArch SA
5
 *  Driver will use termios for character output and ppp specific out procecedures for network protocols
6
 */
7
 
8
#include <bsp.h>
9
#include <rtems.h>
10
#include <rtems/libio.h>
11
#include <sys/ttycom.h>
12
#include <unistd.h>
13
#include <sys/errno.h>
14
#include <rtems/rtems/event.h>
15
#include <rtems/rtems/tasks.h>
16
#include <mpc823.h>
17
#include <sys/param.h>
18
#include <sys/systm.h>
19
#include <sys/proc.h>
20
#include <sys/mbuf.h>
21
#include <sys/socket.h>
22
#include <sys/ioctl.h>
23
#include <sys/file.h>
24
 
25
#include <sys/kernel.h>
26
#include <sys/conf.h>
27
#include <net/if.h>
28
#include <net/ppp_defs.h>
29
#include <sys/fcntl.h>
30
#include "ppp.h"
31
#include <net/if_pppvar.h>
32
#include <net/if_ppp.h>
33
/* RTEMS specific */
34
rtems_id modem_task_id;
35
#include "16550.h"
36
#include <mpc823.h>
37
#define ESCAPE_P(c)     (sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
38
#define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT)
39
 
40
#define M_DATASTART(m)  \
41
        (M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \
42
            (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
43
 
44
#define M_DATASIZE(m)   \
45
        (M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \
46
            (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
47
 
48
 
49
struct rtems_termios_tty *modem_tty;
50
/*
51
 * RTEMS event used by interrupt handler to signal daemons.
52
 * This must *not* be the same event used by the KA9Q task synchronization.
53
 */
54
#define INTERRUPT_EVENT       RTEMS_EVENT_1
55
#define START_TRANSMIT_EVENT    RTEMS_EVENT_2
56
#define PPP_LOWAT       100     /* Process more output when < LOWAT on queue */
57
#define PPP_HIWAT       400     /* Don't start a new packet if HIWAT on que */
58
 
59
/*
60
 * RTEMS event used to start transmit daemon.
61
 * This must not be the same as INTERRUPT_EVENT.
62
 */
63
 
64
/*static struct modem_tty *tp=&modem_tp;*/
65
static rtems_id modem_rx_task,modem_tx_task;
66
 
67
 
68
 
69
/* internal FIFO buffers for input and output characters */
70
#define MODEM_BUFFER_LENGTH 4096
71
#define RTS_STOP_SIZE MODEM_BUFFER_LENGTH-128
72
#define RTS_START_SIZE 16
73
 
74
int xmt_start,xmt_len;
75
int rcv_start,rcv_len;
76
 
77
static unsigned char xmt_buf[MODEM_BUFFER_LENGTH];
78
static unsigned char rcv_buf[MODEM_BUFFER_LENGTH];
79
 
80
static volatile char _tx_stop = 0 ,_modem_cd=0;
81
struct ModemData
82
{
83
        int t_line;
84
        struct ppp_softc *t_sc;
85
        rtems_id pppsem;
86
        int offhook;
87
} ModemData;
88
 
89
int pppstart(struct tty *ignore);
90
static u_short fcstab[256] = {
91
        0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
92
        0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
93
        0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
94
        0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
95
        0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
96
        0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
97
        0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
98
        0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
99
        0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
100
        0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
101
        0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
102
        0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
103
        0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
104
        0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
105
        0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
106
        0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
107
        0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
108
        0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
109
        0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
110
        0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
111
        0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
112
        0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
113
        0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
114
        0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
115
        0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
116
        0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
117
        0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
118
        0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
119
        0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
120
        0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
121
        0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
122
        0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
123
};
124
 
125
 
126
static u_short
127
pppfcs(fcs, cp, len)
128
    register u_short fcs;
129
    register u_char *cp;
130
    register int len;
131
{
132
    while (len--)
133
        fcs = PPP_FCS(fcs, *cp++);
134
    return (fcs);
135
}
136
 
137
static void
138
ppp_timeout(x)
139
    void *x;
140
{
141
    struct ppp_softc *sc = ModemData.t_sc;
142
    struct tty *tp = (struct tty *) sc->sc_devp;
143
    int s;
144
 
145
    sc->sc_flags &= ~SC_TIMEOUT;
146
    pppstart(tp);
147
}
148
 
149
static void
150
pppasyncrelinq(sc)
151
    struct ppp_softc *sc;
152
{
153
    int s;
154
 
155
    if (sc->sc_outm) {
156
        m_freem(sc->sc_outm);
157
        sc->sc_outm = NULL;
158
    }
159
    if (sc->sc_m) {
160
        m_freem(sc->sc_m);
161
        sc->sc_m = NULL;
162
    }
163
    if (sc->sc_flags & SC_TIMEOUT) {
164
        untimeout(ppp_timeout, (void *) sc);
165
        sc->sc_flags &= ~SC_TIMEOUT;
166
    }
167
}
168
 
169
/* Put data in input queue */
170
int
171
pppstart(struct tty *ignore)
172
{
173
    register struct ppp_softc *sc = ModemData.t_sc;
174
 
175
    /*
176
     * If there is stuff in the output queue, send it now.
177
     * We are being called in lieu of ttstart and must do what it would.
178
     */
179
        rtems_event_send(modem_tx_task,START_TRANSMIT_EVENT);
180
        sc->sc_if.if_flags  |= IFF_OACTIVE;
181
 
182
    /*
183
     * If the transmit queue has drained and the tty has not hung up
184
     * or been disconnected from the ppp unit, then tell if_ppp.c that
185
     * we need more output.
186
     */
187
/*    if (CCOUNT(&tp->t_outq) < PPP_LOWAT
188
        && !((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
189
        && sc != NULL && tp == (struct tty *) sc->sc_devp) {
190
        ppp_restart(sc);
191
    }
192
*/
193
    return 0;
194
}
195
int putc(unsigned char c)
196
{
197
        int level;
198
 
199
        if (xmt_len<MODEM_BUFFER_LENGTH-1)
200
        {
201
                _CPU_ISR_Disable(level);
202
                xmt_buf[(xmt_start+xmt_len)%MODEM_BUFFER_LENGTH]=c;
203
                xmt_len++;
204
                _CPU_ISR_Enable(level);
205
                return 0;
206
        }
207
        return 1;
208
}
209
 
210
void  unputc(void)
211
{
212
        int level;
213
 
214
        if (xmt_len==0)
215
                return;
216
        _CPU_ISR_Disable(level);
217
                xmt_len--;
218
        _CPU_ISR_Enable(level);
219
}
220
 
221
static void
222
pppasyncstart(sc)
223
    register struct ppp_softc *sc;
224
{
225
    /* Call pppstart to start output again if necessary. */
226
    pppstart(sc->sc_devp);
227
 
228
    /*
229
     * This timeout is needed for operation on a pseudo-tty,
230
     * because the pty code doesn't call pppstart after it has
231
     * drained the t_outq.
232
     */
233
/*    if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) {
234
        timeout(ppp_timeout, (void *) sc, 1);
235
        sc->sc_flags |= SC_TIMEOUT;
236
    }
237
*/
238
 
239
}
240
 
241
 
242
void modem_sendpacket()
243
{
244
  struct mbuf *l = NULL;
245
  rtems_unsigned16 status;
246
  int curr;
247
  register struct mbuf *m;
248
  register int len;
249
  register u_char *start, *stop, *cp;
250
  int n, ndone, done, idle;
251
  struct mbuf *m2;
252
  int s;
253
   register struct ppp_softc *sc=ModemData.t_sc;
254
 
255
 
256
   while (xmt_len < PPP_HIWAT) {
257
        /*
258
         * See if we have an existing packet partly sent.
259
         * If not, get a new packet and start sending it.
260
         */
261
        m = sc->sc_outm;
262
        if (m == NULL) {
263
            /*
264
             * Get another packet to be sent.
265
 
266
             */
267
            m = ppp_dequeue(sc);
268
            if (m == NULL)
269
            {
270
                        break;
271
                 }
272
 
273
            /*
274
             * The extra PPP_FLAG will start up a new packet, and thus
275
             * will flush any accumulated garbage.  We do this whenever
276
             * the line may have been idle for some time.
277
             */
278
            if (xmt_len == 0) {
279
                ++sc->sc_stats.ppp_obytes;
280
                         putc(PPP_FLAG);
281
            }
282
 
283
            /* Calculate the FCS for the first mbuf's worth. */
284
            sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
285
            microtime(&sc->sc_if.if_lastchange);
286
        }
287
 
288
        for (;;) {
289
            start = mtod(m, u_char *);
290
            len = m->m_len;
291
            stop = start + len;
292
            while (len > 0) {
293
                /*
294
                 * Find out how many bytes in the string we can
295
                 * handle without doing something special.
296
                 */
297
                for (cp = start; cp < stop; cp++)
298
                    if (ESCAPE_P(*cp))
299
                                break;
300
                n = cp - start;
301
                if (n) {
302
                        register int i;
303
                    /* NetBSD (0.9 or later), 4.3-Reno or similar. */
304
                         for(i=0;i<n;i++)
305
                                if (putc(start[i]))
306
                                        break;
307
                    ndone = i;
308
                    len -= ndone;
309
                    start += ndone;
310
                    sc->sc_stats.ppp_obytes += ndone;
311
 
312
                    if (ndone < n)
313
                        break;  /* packet doesn't fit */
314
                }
315
                /*
316
                 * If there are characters left in the mbuf,
317
                 * the first one must be special.
318
                 * Put it out in a different form.
319
                 */
320
                if (len) {
321
                    if (putc(PPP_ESCAPE))
322
                        break;
323
                    if (putc(*start ^ PPP_TRANS)) {
324
                         unputc();
325
                        break;
326
                    }
327
                    sc->sc_stats.ppp_obytes += 2;
328
                    start++;
329
                    len--;
330
                }
331
            }
332
 
333
            /*
334
             * If we didn't empty this mbuf, remember where we're up to.
335
             * If we emptied the last mbuf, try to add the FCS and closing
336
             * flag, and if we can't, leave sc_outm pointing to m, but with
337
             * m->m_len == 0, to remind us to output the FCS and flag later.
338
             */
339
            done = len == 0;
340
            if (done && m->m_next == NULL) {
341
                u_char *p, *q;
342
                int c;
343
                u_char endseq[8];
344
 
345
                /*
346
                 * We may have to escape the bytes in the FCS.
347
                 */
348
                p = endseq;
349
                c = ~sc->sc_outfcs & 0xFF;
350
                if (ESCAPE_P(c)) {
351
                    *p++ = PPP_ESCAPE;
352
                    *p++ = c ^ PPP_TRANS;
353
                } else
354
                    *p++ = c;
355
                c = (~sc->sc_outfcs >> 8) & 0xFF;
356
                if (ESCAPE_P(c)) {
357
                    *p++ = PPP_ESCAPE;
358
                    *p++ = c ^ PPP_TRANS;
359
                } else
360
                    *p++ = c;
361
                *p++ = PPP_FLAG;
362
 
363
                /*
364
                 * Try to output the FCS and flag.  If the bytes
365
                 * don't all fit, back out.
366
                 */
367
                for (q = endseq; q < p; ++q)
368
                    if (putc(*q)) {
369
                        done = 0;
370
                        for (; q > endseq; --q)
371
                            unputc();
372
                        break;
373
                    }
374
                if (done)
375
                    sc->sc_stats.ppp_obytes += q - endseq;
376
            }
377
 
378
            if (!done) {
379
                /* remember where we got to */
380
                m->m_data = start;
381
                m->m_len = len;
382
                break;
383
            }
384
 
385
            /* Finished with this mbuf; free it and move on. */
386
            MFREE(m, m2);
387
            m = m2;
388
            if (m == NULL) {
389
                /* Finished a packet */
390
                break;
391
            }
392
            sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
393
        }
394
 
395
        /*
396
         * If m == NULL, we have finished a packet.
397
         * If m != NULL, we've either done as much work this time
398
         * as we need to, or else we've filled up the output queue.
399
         */
400
        sc->sc_outm = m;
401
        if (m)
402
            break;
403
    }
404
 
405
}
406
 
407
static void
408
pppasyncctlp(sc)
409
    struct ppp_softc *sc;
410
{
411
        rtems_semaphore_release(ModemData.pppsem);
412
}
413
 
414
 
415
static unsigned paritytab[8] = {
416
    0x96696996, 0x69969669, 0x69969669, 0x96696996,
417
    0x69969669, 0x96696996, 0x96696996, 0x69969669
418
};
419
#define MAX_DUMP_BYTES  128
420
 
421
static void
422
pppdumpb(b, l)
423
    u_char *b;
424
    int l;
425
{
426
    char buf[3*MAX_DUMP_BYTES+4];
427
    char *bp = buf;
428
    static char digits[] = "0123456789abcdef";
429
 
430
    while (l--) {
431
        if (bp >= buf + sizeof(buf) - 3) {
432
            *bp++ = '>';
433
            break;
434
        }
435
        *bp++ = digits[*b >> 4]; /* convert byte to ascii hex */
436
        *bp++ = digits[*b++ & 0xf];
437
        *bp++ = ' ';
438
    }
439
 
440
    *bp = 0;
441
 
442
}
443
 
444
static void
445
ppplogchar(sc, c)
446
    struct ppp_softc *sc;
447
    int c;
448
{
449
    if (c >= 0)
450
        sc->sc_rawin[sc->sc_rawin_count++] = c;
451
    if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
452
        || (c < 0 && sc->sc_rawin_count > 0)) {
453
/*      printf("ppp%d input: ", sc->sc_if.if_unit);
454
*/      pppdumpb(sc->sc_rawin, sc->sc_rawin_count);
455
        sc->sc_rawin_count = 0;
456
    }
457
}
458
static void
459
pppgetm(sc)
460
    register struct ppp_softc *sc;
461
{
462
    struct mbuf *m, **mp;
463
    int len;
464
    mp = &sc->sc_m;
465
    for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
466
        if ((m = *mp) == NULL) {
467
            MGETHDR(m, M_DONTWAIT, MT_DATA);
468
            if (m == NULL)
469
                break;
470
            *mp = m;
471
            MCLGET(m, M_DONTWAIT);
472
        }
473
        len -= M_DATASIZE(m);
474
        mp = &m->m_next;
475
    }
476
}
477
 
478
 
479
int
480
pppinput(c)
481
    int c;
482
 
483
{
484
    register struct ppp_softc *sc=ModemData.t_sc;
485
    struct mbuf *m;
486
    int ilen, s;
487
 
488
    if (sc == NULL )
489
        return 0;
490
 
491
    ++sc->sc_stats.ppp_ibytes;
492
/*
493
    if (c & TTY_FE) {*/
494
        /* framing error or overrun on this char - abort packet */
495
/*      if (sc->sc_flags & SC_DEBUG)
496
            printf("ppp%d: bad char %x\n", sc->sc_if.if_unit, c);
497
        goto flush;
498
    }*/
499
 
500
    c &= 0xff;
501
 
502
    /*
503
     * Handle software flow control of output.
504
     */
505
/*    if (tp->t_iflag & IXON) {
506
        if (c == tp->t_cc[VSTOP] ) {
507
            if ((tp->t_state & TS_TTSTOP) == 0) {
508
                tp->t_state |= TS_TTSTOP;
509
                sccppp_stop_transmission(tp);
510
            }
511
            return 0;
512
        }
513
        if (c == tp->t_cc[VSTART]  ) {
514
            tp->t_state &= ~TS_TTSTOP;
515
                sccppp_start_transmission(tp);
516
            return 0;
517
        }
518
    }
519
*/
520
 
521
    if (c & 0x80)
522
        sc->sc_flags |= SC_RCV_B7_1;
523
    else
524
        sc->sc_flags |= SC_RCV_B7_0;
525
    if (paritytab[c >> 5] & (1 << (c & 0x1F)))
526
        sc->sc_flags |= SC_RCV_ODDP;
527
    else
528
        sc->sc_flags |= SC_RCV_EVNP;
529
 
530
 
531
/*    if (sc->sc_flags & SC_LOG_RAWIN)*/
532
//      ppplogchar(sc, c);
533
 
534
    if (c == PPP_FLAG) {
535
        ilen = sc->sc_ilen;
536
        sc->sc_ilen = 0;
537
 
538
        if (sc->sc_rawin_count > 0)
539
            ppplogchar(sc, -1);
540
 
541
        /*
542
         * If SC_ESCAPED is set, then we've seen the packet
543
         * abort sequence
544
         */
545
        if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
546
            || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
547
            sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */
548
            if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
549
                if (sc->sc_flags & SC_DEBUG)
550
                    printf("ppp%d: bad fcs %x, pkt len %d\n",
551
                           sc->sc_if.if_unit, sc->sc_fcs, ilen);
552
                sc->sc_if.if_ierrors++;
553
                sc->sc_stats.ppp_ierrors++;
554
            } else
555
                sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
556
            return 0;
557
        }
558
 
559
        if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
560
            if (ilen) {
561
                if (sc->sc_flags & SC_DEBUG)
562
/*                  printf("ppp%d: too short (%d)\n", sc->sc_if.if_unit, ilen);
563
*/              sc->sc_if.if_ierrors++;
564
                sc->sc_stats.ppp_ierrors++;
565
                sc->sc_flags |= SC_PKTLOST;
566
                splx(s);
567
            }
568
            return 0;
569
        }
570
 
571
        /*
572
         * Remove FCS trailer.  Somewhat painful...
573
         */
574
        ilen -= 2;
575
        if (--sc->sc_mc->m_len == 0) {
576
            for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
577
                ;
578
            sc->sc_mc = m;
579
        }
580
        sc->sc_mc->m_len--;
581
 
582
        /* excise this mbuf chain */
583
        m = sc->sc_m;
584
        sc->sc_m = sc->sc_mc->m_next;
585
        sc->sc_mc->m_next = NULL;
586
        ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
587
        if (sc->sc_flags & SC_PKTLOST) {
588
            sc->sc_flags &= ~SC_PKTLOST;
589
        }
590
 
591
        pppgetm(sc);
592
        return 0;
593
    }
594
 
595
    if (sc->sc_flags & SC_FLUSH) {
596
        if (sc->sc_flags & SC_LOG_FLUSH)
597
            ppplogchar(sc, c);
598
        return 0;
599
    }
600
 
601
    if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
602
        return 0;
603
 
604
    if (sc->sc_flags & SC_ESCAPED) {
605
        sc->sc_flags &= ~SC_ESCAPED;
606
        c ^= PPP_TRANS;
607
    } else if (c == PPP_ESCAPE) {
608
        sc->sc_flags |= SC_ESCAPED;
609
        return 0;
610
    }
611
 
612
    /*
613
     * Initialize buffer on first octet received.
614
     * First octet could be address or protocol (when compressing
615
     * address/control).
616
     * Second octet is control.
617
     * Third octet is first or second (when compressing protocol)
618
     * octet of protocol.
619
     * Fourth octet is second octet of protocol.
620
     */
621
    if (sc->sc_ilen == 0) {
622
        /* reset the first input mbuf */
623
        if (sc->sc_m == NULL) {
624
            pppgetm(sc);
625
            if (sc->sc_m == NULL) {
626
                if (sc->sc_flags & SC_DEBUG)
627
/*                  printf("ppp%d: no input mbufs!\n", sc->sc_if.if_unit);
628
*/              goto flush;
629
            }
630
        }
631
        m = sc->sc_m;
632
        m->m_len = 0;
633
        m->m_data = M_DATASTART(sc->sc_m);
634
        sc->sc_mc = m;
635
        sc->sc_mp = mtod(m, char *);
636
        sc->sc_fcs = PPP_INITFCS;
637
        if (c != PPP_ALLSTATIONS) {
638
            if (sc->sc_flags & SC_REJ_COMP_AC) {
639
                if (sc->sc_flags & SC_DEBUG)
640
/*                  printf("ppp%d: garbage received: 0x%x (need 0xFF)\n",
641
                           sc->sc_if.if_unit, c);*/
642
                goto flush;
643
            }
644
            *sc->sc_mp++ = PPP_ALLSTATIONS;
645
            *sc->sc_mp++ = PPP_UI;
646
            sc->sc_ilen += 2;
647
            m->m_len += 2;
648
        }
649
    }
650
    if (sc->sc_ilen == 1 && c != PPP_UI) {
651
        if (sc->sc_flags & SC_DEBUG)
652
/*          printf("ppp%d: missing UI (0x3), got 0x%x\n",
653
                   sc->sc_if.if_unit, c);
654
*/      goto flush;
655
    }
656
    if (sc->sc_ilen == 2 && (c & 1) == 1) {
657
        /* a compressed protocol */
658
        *sc->sc_mp++ = 0;
659
        sc->sc_ilen++;
660
        sc->sc_mc->m_len++;
661
    }
662
    if (sc->sc_ilen == 3 && (c & 1) == 0) {
663
        if (sc->sc_flags & SC_DEBUG)
664
/*          printf("ppp%d: bad protocol %x\n", sc->sc_if.if_unit,
665
                   (sc->sc_mp[-1] << 8) + c);
666
*/      goto flush;
667
    }
668
 
669
    /* packet beyond configured mru? */
670
    if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
671
        if (sc->sc_flags & SC_DEBUG)
672
/*          printf("ppp%d: packet too big\n", sc->sc_if.if_unit);
673
*/      goto flush;
674
    }
675
 
676
    /* is this mbuf full? */
677
    m = sc->sc_mc;
678
    if (M_TRAILINGSPACE(m) <= 0) {
679
        if (m->m_next == NULL) {
680
            pppgetm(sc);
681
            if (m->m_next == NULL) {
682
                if (sc->sc_flags & SC_DEBUG)
683
/*                  printf("ppp%d: too few input mbufs!\n", sc->sc_if.if_unit);
684
*/              goto flush;
685
            }
686
        }
687
        sc->sc_mc = m = m->m_next;
688
        m->m_len = 0;
689
        m->m_data = M_DATASTART(m);
690
        sc->sc_mp = mtod(m, char *);
691
    }
692
 
693
    ++m->m_len;
694
    *sc->sc_mp++ = c;
695
    sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
696
    return 0;
697
 
698
 flush:
699
    if (!(sc->sc_flags & SC_FLUSH)) {
700
        sc->sc_if.if_ierrors++;
701
        sc->sc_stats.ppp_ierrors++;
702
        sc->sc_flags |= SC_FLUSH;
703
        if (sc->sc_flags & SC_LOG_FLUSH)
704
            ppplogchar(sc, c);
705
    }
706
    return 0;
707
}
708
 
709
 
710
void
711
modem_txDaemon (void *arg)
712
{
713
        rtems_event_set events;
714
        register int level,i,maxonce;
715
        while (1)
716
        {
717
                if (xmt_len==0) //jezeli nic nie ma to czekajmy na event
718
                        rtems_event_receive(START_TRANSMIT_EVENT|INTERRUPT_EVENT,RTEMS_EVENT_ANY | RTEMS_WAIT, RTEMS_NO_TIMEOUT,&events);
719
                /* wait for transmit buffer to become empty */
720
 
721
                while(_tx_stop) //tu czekamy na start transmisji
722
                        rtems_event_receive(INTERRUPT_EVENT|START_TRANSMIT_EVENT,RTEMS_EVENT_ANY | RTEMS_WAIT, RTEMS_NO_TIMEOUT,&events);
723
 
724
                _CPU_ISR_Disable(level);
725
                if (*LSR & THRE) //jezeli nie ma transmisji to wyslijmy pierwsze bajty, jezeli jest, same pojda
726
                {
727
                        maxonce=(xmt_len>14)?14:xmt_len;
728
                        if (maxonce>0)
729
                        {
730
                                for (i=0;i<maxonce;i++)
731
                                {
732
                                        *THR=xmt_buf[xmt_start];
733
                                        xmt_start=(xmt_start+1)%MODEM_BUFFER_LENGTH;
734
                                }
735
                                xmt_len-=maxonce;
736
                        }
737
                }
738
                _CPU_ISR_Enable(level);
739
                if ((ModemData.t_line==PPPDISC))
740
                {
741
                        rtems_bsdnet_semaphore_obtain();
742
                        modem_sendpacket();
743
                        rtems_bsdnet_semaphore_release();
744
                }
745
 
746
        }
747
}
748
 
749
static void modem_rxDaemon (void *arg)
750
{
751
        rtems_event_set events;
752
        unsigned char bufor_posr[MODEM_BUFFER_LENGTH];
753
        register unsigned char ch;
754
        int level,i,j;
755
        while(1)
756
        {
757
                /* wait for interrupt */
758
                i=0;
759
                _CPU_ISR_Disable(level);
760
                while(rcv_len>0)
761
                {
762
                                bufor_posr[i++]=rcv_buf[rcv_start];
763
                                rcv_start=(rcv_start+1)%MODEM_BUFFER_LENGTH;
764
                                rcv_len--;
765
                }
766
                _CPU_ISR_Enable(level);
767
                if (ModemData.t_line==PPPDISC)
768
                {
769
                        rtems_bsdnet_semaphore_obtain();
770
                        for(j=0;j<i;j++)
771
                                pppinput(bufor_posr[j]);
772
                        rtems_bsdnet_semaphore_release();
773
                }
774
                else
775
                        if (i!=0)rtems_termios_enqueue_raw_characters(modem_tty,bufor_posr,i);
776
                rtems_event_receive(INTERRUPT_EVENT,RTEMS_EVENT_ANY | RTEMS_WAIT, RTEMS_NO_TIMEOUT,&events);
777
        }
778
}
779
#define CLK_FREQ 1843200
780
void set_modem_speed(int speed)
781
{
782
  *LCR = (char)(DLAB);
783
  *DLL = (char)((int)(CLK_FREQ/speed/16.0+0.5) & 0xFF);
784
  *DLM = (char)(((int)(CLK_FREQ/speed/16.0+0.5) & 0xFF00) >> 8);
785
  *LCR = (char)(WL_8 ); /* 8 bitowe slowo */
786
}
787
 
788
 
789
static void
790
modem_init (int speed)  /* port is the SMC number (i.e. 1 or 2) */
791
{
792
        set_modem_speed(speed);
793
  /* Line control setup */
794
 
795
  *LCR = (char)(WL_8 ); /* 8 bitowe slowo */
796
  /* bylo NSB - bylo 2 jest 1*/
797
 
798
  /* Interrupt setup */
799
  *IER = (char) 0x0f;           /* enable transmit, receive, modem stat int */
800
 
801
  /* FIFO setup */
802
  *FCR = (char)(FIFO_E | 0xc0);
803
 
804
  /* Modem control setup */
805
  *MCR = (char) RTS|DTR|OUT2;
806
 
807
  /* init tx_stop with CTS */
808
  _tx_stop = ( (*MDSR & CTS) ? 0 : 1);
809
}
810
 
811
void set_modem_dtr(int how)
812
{
813
        unsigned char znak;
814
        znak=*MCR;
815
        *MCR=(how)?(znak|DTR):(znak&(~DTR));
816
}
817
void modem_status()
818
{
819
        unsigned char status;
820
        status=*MDSR;
821
 
822
/*      printf("Modem Status %x ",status);
823
*/      if (status&CTS)
824
        {
825
                _tx_stop=0;
826
                rtems_event_send (modem_tx_task, START_TRANSMIT_EVENT|INTERRUPT_EVENT);
827
        }
828
        else
829
        {
830
                _tx_stop=1;
831
        }
832
        if (status&DCD)
833
                _modem_cd=1;
834
        else
835
                _modem_cd=0;
836
}
837
 
838
static rtems_isr
839
modemInterruptHandler (rtems_vector_number v)
840
{
841
  register char a,i,ch;
842
  register int maxonce;
843
        static errcount = 0;
844
  for(;;)
845
  {
846
          a=*IIR & (NIP | IID_MASK); /* read interrupt id register */
847
          switch (a) {
848
                  case 0x04: case 0x0c:
849
                  /*
850
                   * Buffer received?
851
                   */
852
                while( (*LSR & DR) != 0)
853
                {
854
                        ch=*RBR;
855
                        rcv_buf[(rcv_start+rcv_len)%MODEM_BUFFER_LENGTH]=ch;
856
                        rcv_len++;
857
                }
858
            rtems_event_send (modem_rx_task, INTERRUPT_EVENT);
859
            break;
860
          case 0x02:
861
                  /*
862
                   * Buffer transmitted ?
863
                   */
864
                if (*LSR & THRE) //jezeli nie ma transmisji (a nie powinno byc) to wyslijmy  bajty
865
                {
866
                        maxonce=(xmt_len>14)?14:xmt_len;
867
                        if (maxonce>0)
868
                        {
869
                                for (i=0;i<maxonce;i++)
870
                                {
871
                                        *THR=xmt_buf[xmt_start];
872
                                        xmt_start=(xmt_start+1)%MODEM_BUFFER_LENGTH;
873
                                }
874
                                xmt_len-=maxonce;
875
                        }
876
                }
877
                rtems_event_send (modem_tx_task, INTERRUPT_EVENT);
878
           break;
879
          case 0x00:
880
                        modem_status();
881
                        break;
882
          case 0x01:
883
                        return;
884
          case 0x06:
885
                ch=*RBR;
886
                errcount++;
887
                break;
888
 
889
                default:
890
                    break;
891
          }
892
  }
893
}
894
 
895
 
896
void modem_flush(int mode)
897
{
898
        if (mode&FWRITE)
899
        {
900
        }
901
        if (mode&FREAD)
902
        {
903
   }
904
 
905
}
906
 
907
 
908
 
909
int modemWriteTermios(int minor, const char *buf, int len)
910
{
911
        int level;
912
        int i,maxonce;
913
        if (len<=0)
914
                return 0;
915
 
916
        if (ModemData.t_line!=PPPDISC)
917
        {
918
        _CPU_ISR_Disable(level);
919
        for(i=0;i<len;i++)
920
        {
921
                if (xmt_len>=MODEM_BUFFER_LENGTH)
922
                        break;
923
                xmt_buf[(xmt_start+xmt_len)%MODEM_BUFFER_LENGTH]=buf[i];
924
                xmt_len++;
925
        }
926
                _CPU_ISR_Enable(level);
927
        }
928
        rtems_event_send(modem_tx_task,START_TRANSMIT_EVENT);
929
        return i;
930
}
931
 
932
 
933
/*
934
 * Initialize and register the device
935
 */
936
rtems_device_driver modem_initialize(
937
  rtems_device_major_number  major,
938
  rtems_device_minor_number  minor,
939
  void                      *arg
940
)
941
{
942
        rtems_status_code status;
943
        rtems_isr_entry old_handler;
944
        rtems_status_code sc;
945
   rtems_termios_initialize ();
946
        sc = rtems_semaphore_create (
947
                        rtems_build_name ('M', 'D', 'M', 'P'),
948
                        0,
949
                        RTEMS_COUNTING_SEMAPHORE,
950
                        RTEMS_NO_PRIORITY_CEILING,
951
                        &ModemData.pppsem);
952
        if (sc != RTEMS_SUCCESSFUL)
953
                rtems_fatal_error_occurred (sc);
954
        modem_init(9600);
955
 
956
        sc = rtems_interrupt_catch (modemInterruptHandler,
957
                                                PPC_IRQ_IRQ4,
958
                                                &old_handler);
959
 
960
        /*
961
         * Register the devices
962
         */
963
        modem_tx_task=0;
964
        modem_rx_task=0;
965
        status = rtems_io_register_name ("/dev/modem", major, 0);
966
        if (status != RTEMS_SUCCESSFUL)
967
                rtems_fatal_error_occurred (status);
968
        return RTEMS_SUCCESSFUL;
969
}
970
 
971
rtems_device_driver modem_first_open(
972
  rtems_device_major_number major,
973
  rtems_device_minor_number minor,
974
  void                    * arg
975
)
976
{
977
        modem_tty=(struct rtems_termios_tty *)(((rtems_libio_open_close_args_t *)arg)->iop->data1);
978
        return RTEMS_SUCCESSFUL;
979
}
980
rtems_device_driver modem_last_close(
981
  rtems_device_major_number major,
982
  rtems_device_minor_number minor,
983
  void                    * arg
984
)
985
{
986
  m823.siu.simask &=(~M823_SIMASK_IRM4); /* block the interrupts */
987
        return RTEMS_SUCCESSFUL;
988
}
989
 
990
static int
991
modemSetAttr(int minor, const struct termios *t)
992
{
993
  int baud;
994
 
995
  switch (t->c_cflag & CBAUD)
996
    {
997
    case B50:
998
      baud = 50;
999
      break;
1000
    case B75:
1001
      baud = 75;
1002
      break;
1003
    case B110:
1004
      baud = 110;
1005
      break;
1006
    case B134:
1007
      baud = 134;
1008
      break;
1009
    case B150:
1010
      baud = 150;
1011
      break;
1012
    case B200:
1013
      baud = 200;
1014
      break;
1015
    case B300:
1016
      baud = 300;
1017
      break;
1018
    case B600:
1019
      baud = 600;
1020
      break;
1021
    case B1200:
1022
      baud = 1200;
1023
      break;
1024
    case B1800:
1025
      baud = 1800;
1026
      break;
1027
    case B2400:
1028
      baud = 2400;
1029
      break;
1030
    case B4800:
1031
      baud = 4800;
1032
      break;
1033
    case B9600:
1034
      baud = 9600;
1035
      break;
1036
    case B19200:
1037
      baud = 19200;
1038
      break;
1039
    case B38400:
1040
      baud = 38400;
1041
      break;
1042
    case B57600:
1043
      baud = 57600;
1044
      break;
1045
    case B115200:
1046
      baud = 115200;
1047
      break;
1048
    default:
1049
      baud = 0;
1050
      rtems_fatal_error_occurred (RTEMS_INTERNAL_ERROR);
1051
      return 0;
1052
    }
1053
        set_modem_speed(baud);
1054
        return RTEMS_SUCCESSFUL;
1055
}
1056
 
1057
 
1058
/*
1059
 * Open the device
1060
 */
1061
 
1062
 
1063
 
1064
rtems_device_driver modem_open(
1065
  rtems_device_major_number major,
1066
  rtems_device_minor_number minor,
1067
  void                    * arg
1068
)
1069
{
1070
    int error, s;
1071
  rtems_status_code              status;
1072
   register struct ppp_softc *sc;
1073
  static rtems_termios_callbacks cb =
1074
  {
1075
    modem_first_open,                 /* firstOpen */
1076
    modem_last_close,       /* lastClose */
1077
    NULL,                     /* poll read  */
1078
    modemWriteTermios, /* write */
1079
    modemSetAttr,                     /* setAttributes */
1080
    NULL,                     /* stopRemoteTx */
1081
    NULL,                     /* startRemoteTx */
1082
 
1083
  };
1084
 
1085
        if (ModemData.t_line == PPPDISC)
1086
        {
1087
                sc = ModemData.t_sc;
1088
                if (sc != NULL && sc->sc_devp == (void *) &ModemData)
1089
                {
1090
                        return (0);
1091
                }
1092
        }
1093
 
1094
        if ((ModemData.t_sc= sc = pppalloc(1)) == NULL)
1095
                return 2;
1096
 
1097
    if (sc->sc_relinq)
1098
        (*sc->sc_relinq)(sc);   /* get previous owner to relinquish the unit */
1099
 
1100
    sc->sc_ilen = 0;
1101
    sc->sc_m = NULL;
1102
    bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
1103
    sc->sc_asyncmap[0] = 0xffffffff;
1104
    sc->sc_asyncmap[3] = 0x60000000;
1105
    sc->sc_rasyncmap = 0;
1106
    sc->sc_devp = &ModemData;
1107
    sc->sc_start = pppasyncstart;
1108
    sc->sc_ctlp = pppasyncctlp;
1109
    sc->sc_relinq = pppasyncrelinq;
1110
    sc->sc_outm = NULL;
1111
    pppgetm(sc);
1112
    sc->sc_if.if_flags |= IFF_RUNNING;
1113
    sc->sc_if.if_baudrate = 38400;
1114
 
1115
        status = rtems_termios_open (major, minor, arg, &cb);
1116
  if(status != RTEMS_SUCCESSFUL)
1117
    {
1118
/*      printf("Error openning console device\n");
1119
*/      return status;
1120
    }
1121
 
1122
 
1123
/* init rx and tx task for device */
1124
        xmt_start=xmt_len=0;
1125
        rcv_start=rcv_len=0;
1126
 
1127
        if (modem_rx_task==0 && modem_tx_task==0)
1128
        {
1129
        rtems_status_code sc;
1130
        sc = rtems_task_create (rtems_build_name ('M', 'D', 't', 'x'),
1131
                        101,
1132
                        16*1024,
1133
                        RTEMS_PREEMPT|RTEMS_TIMESLICE|RTEMS_NO_ASR|RTEMS_INTERRUPT_LEVEL(0),
1134
                        RTEMS_NO_FLOATING_POINT|RTEMS_LOCAL,
1135
                        &modem_tx_task);
1136
        if (sc != RTEMS_SUCCESSFUL) {
1137
 
1138
        }
1139
 
1140
        sc = rtems_task_start (modem_tx_task, (void *)modem_txDaemon, 0);
1141
        if (sc != RTEMS_SUCCESSFUL) {
1142
 
1143
        }
1144
 
1145
        sc = rtems_task_create (rtems_build_name ('M', 'D', 'r', 'x'),
1146
                        101,
1147
                        16*1024,
1148
                        RTEMS_PREEMPT|RTEMS_TIMESLICE|RTEMS_NO_ASR|RTEMS_INTERRUPT_LEVEL(0),
1149
                        RTEMS_NO_FLOATING_POINT|RTEMS_LOCAL,
1150
                        &modem_rx_task);
1151
        if (sc != RTEMS_SUCCESSFUL) {
1152
 
1153
        }
1154
 
1155
        sc = rtems_task_start (modem_rx_task, (void *)modem_rxDaemon, 0);
1156
        if (sc != RTEMS_SUCCESSFUL) {
1157
 
1158
        }
1159
 
1160
        }
1161
  /* Enable modem interrupts */
1162
  m823.siu.simask |= M823_SIMASK_IRM4;
1163
 
1164
  return RTEMS_SUCCESSFUL;
1165
}
1166
 
1167
/*
1168
 * Close the device
1169
 */
1170
rtems_device_driver modem_close(
1171
  rtems_device_major_number major,
1172
  rtems_device_minor_number minor,
1173
  void                    * arg
1174
)
1175
{
1176
    register struct ppp_softc *sc;
1177
    modem_flush( FREAD|FWRITE);
1178
 
1179
    ModemData.t_line = 0;
1180
    sc = ModemData.t_sc;
1181
    if (sc != NULL) {
1182
                ModemData.t_sc = NULL;
1183
                if (&ModemData == (struct tty *) sc->sc_devp) {
1184
                rtems_bsdnet_semaphore_obtain();
1185
            pppasyncrelinq(sc);
1186
            pppdealloc(sc);
1187
                rtems_bsdnet_semaphore_release();
1188
        }
1189
    }
1190
    return RTEMS_SUCCESSFUL;
1191
}
1192
 
1193
/* for now works only as serial device */
1194
 
1195
 
1196
rtems_device_driver modem_read(
1197
  rtems_device_major_number major,
1198
  rtems_device_minor_number minor,
1199
  void                    * arg
1200
)
1201
{
1202
  rtems_libio_rw_args_t *rw_args=  (rtems_libio_rw_args_t *)arg;
1203
  char *buffer;
1204
  int count=0,maximum;
1205
  rtems_status_code              sc;
1206
 
1207
  buffer = rw_args->buffer;
1208
  maximum = rw_args->count;
1209
  if (ModemData.t_line==PPPDISC)
1210
  {
1211
 
1212
    struct mbuf *m, *m0;
1213
    register int s;
1214
    int error = 0;
1215
    rtems_status_code status;
1216
    rtems_interval    ticks;
1217
        register struct ppp_softc *sc = (struct ppp_softc *)ModemData.t_sc;
1218
         ticks=1000000/rtems_bsdnet_microseconds_per_tick;
1219
 
1220
    if (sc == NULL)
1221
        return 0;
1222
    /*
1223
     * Loop waiting for input, checking that nothing disasterous
1224
     * happens in the meantime.
1225
     */
1226
    for (;;) {
1227
                if (sc->sc_inq.ifq_head != NULL)
1228
                {
1229
/*            printf("Read : Dane sa w buforze\n");
1230
*/                      break;
1231
                }
1232
/*      printf("Read : Czekam na dane\n");
1233
*/
1234
                status=rtems_semaphore_obtain(ModemData.pppsem,RTEMS_WAIT,ticks);
1235
                if (_modem_cd==0)
1236
                {
1237
                        rw_args->bytes_moved =0;
1238
                        return RTEMS_SUCCESSFUL;
1239
                }
1240
 
1241
                if (status==RTEMS_TIMEOUT)
1242
                        return status;
1243
        }
1244
        rtems_bsdnet_semaphore_obtain();
1245
    IF_DEQUEUE(&sc->sc_inq, m0);
1246
        rtems_bsdnet_semaphore_release();
1247
 
1248
  for (m = m0; m && (count+m->m_next->m_len<maximum); m = m->m_next) /* check if packet will fit in buffer */
1249
  {
1250
                memcpy(buffer,mtod(m, u_char *),m->m_len);
1251
                count+=m->m_len;
1252
                buffer+=m->m_len;
1253
  }
1254
   m_freem(m0);
1255
  rw_args->bytes_moved = count;
1256
 
1257
  }
1258
        else
1259
                  sc = rtems_termios_read (arg);
1260
 
1261
  count=rw_args->bytes_moved;
1262
  return (count >= 0) ? RTEMS_SUCCESSFUL : RTEMS_UNSATISFIED;
1263
}
1264
 
1265
/*
1266
 * Write to the device
1267
 */
1268
rtems_device_driver modem_write(
1269
  rtems_device_major_number major,
1270
  rtems_device_minor_number minor,
1271
  void                    * arg
1272
)
1273
{
1274
  int count,len;
1275
  rtems_libio_rw_args_t *rw_args;
1276
  char *out_buffer;
1277
  int n,maximum;
1278
  rw_args = (rtems_libio_rw_args_t *) arg;
1279
 
1280
  out_buffer = rw_args->buffer;
1281
  maximum = rw_args->count;
1282
 
1283
        if (ModemData.t_line==PPPDISC)
1284
        {
1285
                register struct ppp_softc *sc = (struct ppp_softc *)ModemData.t_sc;
1286
           struct sockaddr dst;
1287
                struct mbuf *m, *m0, **mp;
1288
                rtems_bsdnet_semaphore_obtain();
1289
                for (mp = &m0; maximum; mp = &m->m_next)
1290
                {
1291
                        MGET(m, M_WAIT, MT_DATA);
1292
                        if ((*mp = m) == NULL)
1293
                        {
1294
                                rtems_bsdnet_semaphore_release();
1295
                            m_freem(m0);
1296
                            return (ENOBUFS);
1297
                        }
1298
                        m->m_len = 0;
1299
                        if (maximum>= MCLBYTES / 2)
1300
                    MCLGET(m, M_DONTWAIT);
1301
                        len = M_TRAILINGSPACE(m);
1302
                        if (len > maximum)
1303
                        {
1304
                                memcpy(mtod(m, u_char *),out_buffer,maximum);
1305
                                m->m_len=maximum;
1306
                                maximum=0;
1307
                        }
1308
                        else
1309
                        {
1310
                                memcpy(mtod(m, u_char *),out_buffer,len);
1311
                                maximum-=len;
1312
                                m->m_len=len;
1313
                                out_buffer+=len;
1314
                        }
1315
                }
1316
 
1317
            dst.sa_family = AF_UNSPEC;
1318
            bcopy(mtod(m0, u_char *), dst.sa_data, PPP_HDRLEN);
1319
            m0->m_data += PPP_HDRLEN;
1320
            m0->m_len -= PPP_HDRLEN;
1321
 
1322
/*              printf("Wysylam %d bajtow \n",m0->m_len);
1323
*/              n=pppoutput(&sc->sc_if, m0, &dst, (struct rtentry *)0);
1324
                rtems_bsdnet_semaphore_release();
1325
                return n;
1326
        }
1327
        else
1328
           return rtems_termios_write (arg);
1329
}
1330
 
1331
 
1332
 
1333
/*
1334
 * Handle ioctl request.
1335
 * Should set hardware line speed, bits/char, etc.
1336
 */
1337
rtems_device_driver modem_control(
1338
  rtems_device_major_number major,
1339
  rtems_device_minor_number minor,
1340
  void                    * arg
1341
)
1342
{
1343
        rtems_libio_ioctl_args_t *args=(rtems_libio_ioctl_args_t *)arg;
1344
        struct ppp_softc *sc=ModemData.t_sc;
1345
    int cmd;
1346
    caddr_t data;
1347
    int error=RTEMS_SUCCESSFUL;
1348
 
1349
        data=args->buffer;
1350
        cmd=args->command;
1351
 
1352
    switch (cmd) {
1353
        case RTEMS_IO_GET_ATTRIBUTES:
1354
        case RTEMS_IO_SET_ATTRIBUTES:
1355
        case RTEMS_IO_TCDRAIN:
1356
                return rtems_termios_ioctl (arg);
1357
        break;
1358
   case PPPIOCSASYNCMAP:
1359
                sc->sc_asyncmap[0] = *(u_int *)data;
1360
                break;
1361
 
1362
   case PPPIOCGASYNCMAP:
1363
                *(u_int *)data = sc->sc_asyncmap[0];
1364
        break;
1365
 
1366
        case PPPIOCSRASYNCMAP:
1367
                sc->sc_rasyncmap = *(u_int *)data;
1368
        break;
1369
 
1370
        case TIOCSETD:
1371
                ModemData.t_line=*(int*)data;
1372
        break;
1373
        case TIOCGETD:
1374
                *(int*)data=ModemData.t_line;
1375
        break;
1376
        case TIOCMBIS:
1377
                if ((*(int*)data)&TIOCM_DTR)
1378
                        set_modem_dtr(1);
1379
                break;
1380
        case TIOCMBIC:
1381
                if ((*(int*)data)&TIOCM_DTR)
1382
                        set_modem_dtr(0);
1383
                break;
1384
   case PPPIOCGRASYNCMAP:
1385
                *(u_int *)data = sc->sc_rasyncmap;
1386
        break;
1387
 
1388
        case PPPIOCSXASYNCMAP:
1389
                bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
1390
                sc->sc_asyncmap[1] = 0;              /* mustn't escape 0x20 - 0x3f */
1391
                sc->sc_asyncmap[2] &= ~0x40000000;  /* mustn't escape 0x5e */
1392
                sc->sc_asyncmap[3] |= 0x60000000;   /* must escape 0x7d, 0x7e */
1393
                break;
1394
 
1395
   case PPPIOCGXASYNCMAP:
1396
                bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
1397
                break;
1398
 
1399
        default:
1400
        rtems_bsdnet_semaphore_obtain();
1401
        error = pppioctl(sc, cmd, data, 0, NULL);
1402
                if (error == 0 && cmd == PPPIOCSMRU)
1403
                        pppgetm(sc);
1404
        rtems_bsdnet_semaphore_release();
1405
 
1406
        }
1407
        return error;
1408
 
1409
}
1410
 
1411
 
1412
 
1413
void
1414
wait_input(timo)
1415
    struct timeval *timo;
1416
{
1417
    int n;
1418
    rtems_event_set events;
1419
    rtems_interval    ticks;
1420
  rtems_status_code              err;
1421
        int czekaj=1;
1422
    register struct ppp_softc *sc = (struct ppp_softc *)ModemData.t_sc;
1423
    ticks = 1+(timo->tv_sec*1000000+timo->tv_usec)/rtems_bsdnet_microseconds_per_tick;
1424
        while (czekaj)
1425
        {
1426
 
1427
                if (sc->sc_inq.ifq_head != NULL)
1428
                        break;
1429
/*      printf("Wait : Czekam na dane przez %d ticks\n",ticks);
1430
*/              err=rtems_semaphore_obtain(ModemData.pppsem,RTEMS_WAIT,ticks);
1431
                if (err==RTEMS_TIMEOUT)
1432
                {
1433
/*                      printf("TIMEOUT :Brak danych\n");
1434
*/                      break;
1435
                }
1436
        }
1437
 
1438
}

powered by: WebSVN 2.1.0

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