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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [net/] [ppp/] [current/] [src/] [ppp_io.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      src/ppp_io.c
4
//
5
//==========================================================================
6
// ####BSDCOPYRIGHTBEGIN####                                    
7
// -------------------------------------------                  
8
// This file is part of eCos, the Embedded Configurable Operating System.
9
//
10
// Portions of this software may have been derived from FreeBSD, OpenBSD,
11
// or other sources, and if so are covered by the appropriate copyright
12
// and license included herein.                                 
13
//
14
// Portions created by the Free Software Foundation are         
15
// Copyright (C) 2003, 2004 Free Software Foundation, Inc.      
16
// -------------------------------------------                  
17
// ####BSDCOPYRIGHTEND####                                      
18
//==========================================================================
19
 
20
/*
21
 * ppp_tty.c - Point-to-Point Protocol (PPP) driver for asynchronous
22
 *             tty devices.
23
 *
24
 * Copyright (c) 1989 Carnegie Mellon University.
25
 * All rights reserved.
26
 *
27
 * Redistribution and use in source and binary forms are permitted
28
 * provided that the above copyright notice and this paragraph are
29
 * duplicated in all such forms and that any documentation,
30
 * advertising materials, and other materials related to such
31
 * distribution and use acknowledge that the software was developed
32
 * by Carnegie Mellon University.  The name of the
33
 * University may not be used to endorse or promote products derived
34
 * from this software without specific prior written permission.
35
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
36
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
37
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
38
 *
39
 * Drew D. Perkins
40
 * Carnegie Mellon University
41
 * 4910 Forbes Ave.
42
 * Pittsburgh, PA 15213
43
 * (412) 268-8576
44
 * ddp@andrew.cmu.edu
45
 *
46
 * Based on:
47
 *      @(#)if_sl.c     7.6.1.2 (Berkeley) 2/15/89
48
 *
49
 * Copyright (c) 1987 Regents of the University of California.
50
 * All rights reserved.
51
 *
52
 * Redistribution and use in source and binary forms are permitted
53
 * provided that the above copyright notice and this paragraph are
54
 * duplicated in all such forms and that any documentation,
55
 * and other materials related to such
56
 * distribution and use acknowledge that the software was developed
57
 * by the University of California, Berkeley.  The name of the
58
 * University may not be used to endorse or promote products derived
59
 * from this software without specific prior written permission.
60
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
61
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
62
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
63
 *
64
 * Serial Line interface
65
 *
66
 * Rick Adams
67
 * Center for Seismic Studies
68
 * 1300 N 17th Street, Suite 1450
69
 * Arlington, Virginia 22209
70
 * (703)276-7900
71
 * rick@seismo.ARPA
72
 * seismo!rick
73
 *
74
 * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris).
75
 * Converted to 4.3BSD Beta by Chris Torek.
76
 * Other changes made at Berkeley, based in part on code by Kirk Smith.
77
 *
78
 * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com)
79
 * Added VJ tcp header compression; more unified ioctls
80
 *
81
 * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au).
82
 * Cleaned up a lot of the mbuf-related code to fix bugs that
83
 * caused system crashes and packet corruption.  Changed pppstart
84
 * so that it doesn't just give up with a "collision" if the whole
85
 * packet doesn't fit in the output ring buffer.
86
 *
87
 * Added priority queueing for interactive IP packets, following
88
 * the model of if_sl.c, plus hooks for bpf.
89
 * Paul Mackerras (paulus@cs.anu.edu.au).
90
 */
91
 
92
/* $FreeBSD: src/sys/net/ppp_tty.c,v 1.43 2000/01/29 16:56:24 peter Exp $ */
93
 
94
#include <pkgconf/system.h>
95
#include <pkgconf/net.h>
96
#include <pkgconf/ppp.h>
97
 
98
#define _KERNEL
99
 
100
#define VJC                     /* XXX for ppp_defs.h */
101
 
102
#include <sys/param.h>
103
#define suser(x) 0
104
#include <sys/mbuf.h>
105
#include <sys/socket.h>
106
#include <sys/uio.h>
107
 
108
#ifdef PPP_FILTER
109
#include <net/bpf.h>
110
#endif
111
#include <cyg/ppp/net/if_ppp.h>
112
#include <cyg/ppp/net/if_pppvar.h>
113
 
114
//==========================================================================
115
 
116
#ifdef __ECOS
117
 
118
#include "cyg/ppp/ppp_io.h"
119
 
120
//#define db_printf diag_printf
121
#define db_printf(fmt, ... )
122
 
123
#define spltty(x) splsoftnet(x)
124
 
125
#define ENOIOCTL ENOSYS
126
 
127
#endif
128
 
129
//==========================================================================
130
 
131
static u_short  pppfcs __P((u_short fcs, u_char *cp, int len));
132
static void     pppasyncstart __P((struct ppp_softc *));
133
static void     pppasyncctlp __P((struct ppp_softc *));
134
static void     pppasyncrelinq __P((struct ppp_softc *));
135
static void     pppasyncsetmtu __P((struct ppp_softc *));
136
static void     pppgetm __P((struct ppp_softc *sc));
137
static void     ppplogchar __P((struct ppp_softc *, int));
138
 
139
/* XXX called from if_ppp.c - layering violation */
140
void            pppasyncattach __P((void *));
141
 
142
//==========================================================================
143
/*
144
 * Some useful mbuf macros not in mbuf.h.
145
 */
146
#define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT)
147
 
148
#define M_DATASTART(m)  \
149
        (M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \
150
            (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
151
 
152
#define M_DATASIZE(m)   \
153
        (M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \
154
            (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
155
 
156
//==========================================================================
157
/*
158
 * Does c need to be escaped?
159
 */
160
#define ESCAPE_P(c)     (sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
161
 
162
//==========================================================================
163
/*
164
 * Procedures for using an async tty interface for PPP.
165
 */
166
 
167
/* This is a FreeBSD-2.X kernel. */
168
//#define CCOUNT(q)     ((q)->c_cc)
169
//#define PPP_LOWAT     100     /* Process more output when < LOWAT on queue */
170
//#define       PPP_HIWAT       400     /* Don't start a new packet if HIWAT on que */
171
 
172
 
173
//==========================================================================
174
/*
175
 * Line specific open routine for async tty devices.
176
 * Attach the given tty to the first available ppp unit.
177
 * Called from device open routine or ttioctl() at >= splsofttty()
178
 */
179
/* ARGSUSED */
180
 
181
int
182
cyg_ppp_pppopen(tp)
183
    struct tty *tp;
184
{
185
    register struct ppp_softc *sc;
186
    int error, s;
187
 
188
    if ((error = suser(p)) != 0)
189
        return (error);
190
 
191
    s = spltty();
192
 
193
    if ((sc = pppalloc(0)) == NULL) {
194
        splx(s);
195
        return ENXIO;
196
    }
197
 
198
    if (sc->sc_relinq)
199
        (*sc->sc_relinq)(sc);   /* get previous owner to relinquish the unit */
200
 
201
    sc->sc_ilen = 0;
202
    sc->sc_m = NULL;
203
    bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
204
    sc->sc_asyncmap[0] = 0xffffffff;
205
    sc->sc_asyncmap[3] = 0x60000000;
206
    sc->sc_rasyncmap = 0;
207
    sc->sc_devp = (void *) tp;
208
    sc->sc_start = pppasyncstart;
209
    sc->sc_ctlp = pppasyncctlp;
210
    sc->sc_relinq = pppasyncrelinq;
211
    sc->sc_setmtu = pppasyncsetmtu;
212
    sc->sc_outm = NULL;
213
    pppgetm(sc);
214
    sc->sc_if.if_flags |= IFF_RUNNING;
215
    getmicrotime(&sc->sc_if.if_lastchange);
216
    tp->t_sc = (caddr_t) sc;
217
 
218
    splx(s);
219
 
220
    return (0);
221
}
222
 
223
//==========================================================================
224
/*
225
 * Line specific close routine, called from device close routine
226
 * and from ttioctl at >= splsofttty().
227
 * Detach the tty from the ppp unit.
228
 * Mimics part of ttyclose().
229
 */
230
 
231
int
232
cyg_ppp_pppclose(tp, flag)
233
    struct tty *tp;
234
    int flag;
235
{
236
    register struct ppp_softc *sc;
237
    int s;
238
 
239
    db_printf("%s called\n", __PRETTY_FUNCTION__);
240
    s = spltty();
241
 
242
    sc = (struct ppp_softc *) tp->t_sc;
243
    if (sc != NULL) {
244
        tp->t_sc = NULL;
245
        if (tp == (struct tty *) sc->sc_devp) {
246
            pppasyncrelinq(sc);
247
            pppdealloc(sc);
248
        }
249
    }
250
    splx(s);
251
    return 0;
252
}
253
 
254
//==========================================================================
255
/*
256
 * Relinquish the interface unit to another device.
257
 */
258
 
259
static void
260
pppasyncrelinq(sc)
261
    struct ppp_softc *sc;
262
{
263
    int s;
264
 
265
    s = spltty();
266
    if (sc->sc_outm) {
267
        m_freem(sc->sc_outm);
268
        sc->sc_outm = NULL;
269
    }
270
    if (sc->sc_m) {
271
        m_freem(sc->sc_m);
272
        sc->sc_m = NULL;
273
    }
274
    if (sc->sc_flags & SC_TIMEOUT) {
275
        sc->sc_flags &= ~SC_TIMEOUT;
276
    }
277
    splx(s);
278
}
279
 
280
//==========================================================================
281
/*
282
 * This gets called from the upper layer to notify a mtu change
283
 */
284
 
285
static void
286
pppasyncsetmtu(sc)
287
register struct ppp_softc *sc;
288
{
289
    db_printf("%s called\n", __PRETTY_FUNCTION__);
290
}
291
 
292
 
293
 
294
//==========================================================================
295
/*
296
 * function to check if data is available
297
 */
298
 
299
int
300
cyg_ppp_pppcheck(tp)
301
    register struct tty *tp;
302
{
303
    register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
304
    int status = 0;
305
    register int s;
306
 
307
    s = spltty();
308
 
309
    if (tp != (struct tty *) sc->sc_devp ) {
310
        splx(s);
311
        return 0;
312
    }
313
    if (sc->sc_inq.ifq_head == NULL)
314
    {
315
        splx(s);
316
        return 0;
317
    }
318
 
319
    // if the queue is not empty
320
    if ( IF_IS_EMPTY(&sc->sc_inq) == false)
321
        status = 1;
322
 
323
    splx(s);
324
 
325
    return(status);
326
}
327
 
328
 
329
//==========================================================================
330
/*
331
 * Line specific (tty) read routine.
332
 * called at zero spl from the device driver in the response to user-level
333
 * reads on the tty file descriptor (ie: pppd).
334
 */
335
 
336
int
337
cyg_ppp_pppread(tp, uio, flag)
338
    register struct tty *tp;
339
    struct uio *uio;
340
    int flag;
341
{
342
    register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
343
    struct mbuf *m, *m0;
344
    register int s;
345
    int error = 0;
346
 
347
    db_printf("%s called\n", __PRETTY_FUNCTION__);
348
 
349
    if (sc == NULL)
350
        return 0;
351
 
352
    // Look for input. If there is none return EWOULDBLOCK, otherwise
353
    // dequeue the next packet and return it.
354
 
355
    s = spltty();
356
 
357
    if (tp != (struct tty *) sc->sc_devp ) {
358
        splx(s);
359
        return 0;
360
    }
361
    if (sc->sc_inq.ifq_head == NULL)
362
    {
363
        splx(s);
364
        return EWOULDBLOCK;
365
    }
366
 
367
    /* Get the packet from the input queue */
368
    IF_DEQUEUE(&sc->sc_inq, m0);
369
    splx(s);
370
 
371
 
372
    for (m = m0; m && uio->uio_resid; m = m->m_next)
373
    {
374
        if ((error = uiomove(mtod(m, caddr_t), m->m_len, uio)) != 0)
375
            break;
376
    }
377
    m_freem(m0);
378
 
379
    return (error);
380
}
381
 
382
//==========================================================================
383
/*
384
 * Line specific (tty) write routine.
385
 * called at zero spl from the device driver in the response to user-level
386
 * writes on the tty file descriptor (ie: pppd).
387
 */
388
 
389
int
390
cyg_ppp_pppwrite(tp, uio, flag)
391
    register struct tty *tp;
392
    struct uio *uio;
393
    int flag;
394
{
395
    register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
396
    struct mbuf *m, *m0, **mp;
397
    struct sockaddr dst;
398
    int len, error, s;
399
 
400
    s = spltty();
401
    for (mp = &m0; uio->uio_resid; mp = &m->m_next) {
402
        MGET(m, M_WAIT, MT_DATA);
403
        if ((*mp = m) == NULL) {
404
            m_freem(m0);
405
            splx(s);
406
            return (ENOBUFS);
407
        }
408
        m->m_len = 0;
409
        if (uio->uio_resid >= MCLBYTES / 2)
410
            MCLGET(m, M_DONTWAIT);
411
        len = M_TRAILINGSPACE(m);
412
        if (len > uio->uio_resid)
413
            len = uio->uio_resid;
414
        if ((error = uiomove(mtod(m, caddr_t), len, uio)) != 0) {
415
            m_freem(m0);
416
            splx(s);
417
            return (error);
418
        }
419
        m->m_len = len;
420
    }
421
    dst.sa_family = AF_UNSPEC;
422
    bcopy(mtod(m0, u_char *), dst.sa_data, PPP_HDRLEN);
423
    m0->m_data += PPP_HDRLEN;
424
    m0->m_len -= PPP_HDRLEN;
425
 
426
    /* call the upper layer to "transmit" it... */
427
    error = pppoutput(&sc->sc_if, m0, &dst, (struct rtentry *)0);
428
    splx(s);
429
    return (error);
430
}
431
 
432
//==========================================================================
433
/*
434
 * Line specific (tty) ioctl routine.
435
 * This discipline requires that tty device drivers call
436
 * the line specific l_ioctl routine from their ioctl routines.
437
 */
438
/* ARGSUSED */
439
int
440
cyg_ppp_ppptioctl(tp, cmd, data, flag)
441
    struct tty *tp;
442
    u_long cmd;
443
    caddr_t data;
444
    int flag;
445
//    struct proc *p;
446
{
447
    struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
448
    int error, s;
449
 
450
    if (sc == NULL || tp != (struct tty *) sc->sc_devp)
451
        return (ENOIOCTL);
452
 
453
    error = 0;
454
    switch (cmd) {
455
    case PPPIOCSASYNCMAP:
456
        sc->sc_asyncmap[0] = *(u_int *)data;
457
        break;
458
 
459
    case PPPIOCGASYNCMAP:
460
        *(u_int *)data = sc->sc_asyncmap[0];
461
        break;
462
 
463
    case PPPIOCSRASYNCMAP:
464
        if ((error = suser(p)) != 0)
465
            break;
466
        sc->sc_rasyncmap = *(u_int *)data;
467
        break;
468
 
469
    case PPPIOCGRASYNCMAP:
470
        *(u_int *)data = sc->sc_rasyncmap;
471
        break;
472
 
473
    case PPPIOCSXASYNCMAP:
474
        s = spltty();
475
        bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
476
        sc->sc_asyncmap[1] = 0;              /* mustn't escape 0x20 - 0x3f */
477
        sc->sc_asyncmap[2] &= ~0x40000000;  /* mustn't escape 0x5e */
478
        sc->sc_asyncmap[3] |= 0x60000000;   /* must escape 0x7d, 0x7e */
479
        splx(s);
480
        break;
481
 
482
    case PPPIOCGXASYNCMAP:
483
        bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
484
        break;
485
 
486
    default:
487
        error = pppioctl(sc, cmd, data, flag, 0);
488
        if (error == 0 && cmd == PPPIOCSMRU)
489
            pppgetm(sc);
490
    }
491
 
492
    return error;
493
}
494
 
495
//==========================================================================
496
/*
497
 * FCS lookup table as calculated by genfcstab.
498
 */
499
static u_short fcstab[256] = {
500
        0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
501
        0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
502
        0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
503
        0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
504
        0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
505
        0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
506
        0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
507
        0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
508
        0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
509
        0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
510
        0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
511
        0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
512
        0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
513
        0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
514
        0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
515
        0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
516
        0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
517
        0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
518
        0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
519
        0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
520
        0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
521
        0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
522
        0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
523
        0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
524
        0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
525
        0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
526
        0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
527
        0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
528
        0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
529
        0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
530
        0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
531
        0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
532
};
533
 
534
//==========================================================================
535
/*
536
 * Calculate a new FCS given the current FCS and the new data.
537
 */
538
static u_short
539
pppfcs(u_short fcs, u_char *cp, int len)
540
{
541
    while (len--)
542
        fcs = PPP_FCS(fcs, *cp++);
543
    return (fcs);
544
}
545
 
546
//==========================================================================
547
 
548
#ifdef __ECOS
549
 
550
// Call pppasyncstart() to kick transmission into life. 
551
int cyg_ppp_pppstart( struct tty *tp )
552
{
553
    struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
554
 
555
    while( sc->sc_outm != NULL )
556
    {
557
        // We wait for the output buffer to drain of all characters
558
        // before we call pppasyncstart(). That way we know there will
559
        // be room for some data. We would really like to just drain
560
        // down to some low water mark, but the drivers don't provide
561
        // that functionality. However, since most devices have
562
        // hardware FIFO's, we have a grace period to get more
563
        // characters into the device, so hopefully there won't be a
564
        // gap on the line.
565
 
566
        cyg_uint32 nb = 0;
567
        cyg_uint32 len = sizeof(nb);
568
        int s;
569
 
570
        cyg_io_get_config( tp->t_handle,
571
                           CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN,
572
                           &nb, &len);
573
 
574
        s = splsoftnet();
575
 
576
        pppasyncstart( sc );
577
 
578
        splx(s);
579
    }
580
 
581
    return 0;
582
}
583
 
584
#endif
585
 
586
 
587
//==========================================================================
588
/*
589
 * This gets called at splsoftnet from if_ppp.c at various times
590
 * when there is data ready to be sent.
591
 */
592
static void
593
pppasyncstart(sc)
594
    register struct ppp_softc *sc;
595
{
596
    register struct tty *tp = (struct tty *) sc->sc_devp;
597
    register struct mbuf *m;
598
    register unsigned int len;
599
    register u_char *start, *stop, *cp;
600
    int n, done, idle;
601
    cyg_uint32 ndone;
602
    struct mbuf *m2;
603
    int s;
604
    idle = 0;
605
#ifdef CYGPKT_PPP_WORKAROUNDS_START_FLAG 
606
    char start_flag = PPP_FLAG;
607
    int start_flag_len = sizeof(start_flag);
608
#endif
609
 
610
    while (1) {
611
        /*
612
         * See if we have an existing packet partly sent.
613
         * If not, get a new packet and start sending it.
614
         */
615
        m = sc->sc_outm;
616
        if (m == NULL) {
617
            /*
618
             * Get another packet to be sent.
619
             */
620
            m = ppp_dequeue(sc);
621
            if (m == NULL) {
622
                idle = 1;
623
                break;
624
            }
625
 
626
            /* Calculate the FCS for the first mbuf's worth. */
627
            sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
628
            getmicrotime(&sc->sc_if.if_lastchange);
629
#ifdef CYGPKT_PPP_WORKAROUNDS_START_FLAG
630
            cyg_io_write(tp->t_handle, &start_flag, &start_flag_len);
631
#endif            
632
        }
633
 
634
        for (;;) {
635
            start = mtod(m, u_char *);
636
            len = m->m_len;
637
            stop = start + len;
638
            while (len > 0) {
639
                /*
640
                 * Find out how many bytes in the string we can
641
                 * handle without doing something special.
642
                 */
643
                for (cp = start; cp < stop; cp++)
644
                    if (ESCAPE_P(*cp))
645
                        break;
646
                n = cp - start;
647
                if (n) {
648
#ifndef __ECOS        
649
                    /* NetBSD (0.9 or later), 4.3-Reno or similar. */
650
                    ndone = n - b_to_q(start, n, &tp->t_outq);
651
#else
652
                    ndone = 0;
653
//                    db_printf("send: data %d\n",ndone);
654
//                    db_dump_buf(start,ndone);
655
                    {
656
                        cyg_serial_buf_info_t info;
657
                        cyg_uint32 ilen = sizeof(info);
658
                        if( cyg_io_get_config( tp->t_handle, CYG_IO_GET_CONFIG_SERIAL_BUFFER_INFO, &info, &ilen ) == 0 )
659
                        {
660
                            ndone = info.tx_bufsize-info.tx_count;
661
                            if( ndone > n )
662
                                ndone = n;
663
                            cyg_io_write( tp->t_handle, start, &ndone);
664
                        }
665
                    }
666
#endif
667
                    len -= ndone;
668
                    start += ndone;
669
                    sc->sc_stats.ppp_obytes += ndone;
670
 
671
                    if (ndone < n)
672
                        break;  /* packet doesn't fit */
673
                }
674
                /*
675
                 * If there are characters left in the mbuf,
676
                 * the first one must be special.
677
                 * Put it out in a different form.
678
                 */
679
                if (len) {
680
                    s = spltty();
681
#ifndef __ECOS        
682
                    if (putc(PPP_ESCAPE, &tp->t_outq)) {
683
                        splx(s);
684
                        break;
685
                    }
686
                    if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
687
                        (void) unputc(&tp->t_outq);
688
                        splx(s);
689
                        break;
690
                    }
691
#else
692
                    {
693
                        cyg_serial_buf_info_t info;
694
                        cyg_uint32 ilen = sizeof(info);
695
                        if( cyg_io_get_config( tp->t_handle, CYG_IO_GET_CONFIG_SERIAL_BUFFER_INFO, &info, &ilen ) == 0 &&
696
                            info.tx_bufsize-info.tx_count >= 2 )
697
                        {
698
                            char buf[2];
699
                            cyg_uint32 blen = 2;
700
                            buf[0] = PPP_ESCAPE;
701
                            buf[1] = *start ^ PPP_TRANS;
702
                            if( cyg_io_write( tp->t_handle, buf, &blen) != 0 ) {
703
                                splx(s);
704
                                break;
705
                            }
706
                        }
707
                        else
708
                        {
709
                            splx(s);
710
                            break;
711
                        }
712
                    }
713
#endif
714
                    splx(s);
715
                    sc->sc_stats.ppp_obytes += 2;
716
                    start++;
717
                    len--;
718
                } // if( len )
719
            } // while (len > 0)
720
 
721
            /*
722
             * If we didn't empty this mbuf, remember where we're up to.
723
             * If we emptied the last mbuf, try to add the FCS and closing
724
             * flag, and if we can't, leave sc_outm pointing to m, but with
725
             * m->m_len == 0, to remind us to output the FCS and flag later.
726
             */
727
            done = len == 0;
728
            if (done && m->m_next == NULL) {
729
                u_char *p, *q;
730
                int c;
731
                u_char endseq[8];
732
 
733
                /*
734
                 * We may have to escape the bytes in the FCS.
735
                 */
736
                p = endseq;
737
                c = ~sc->sc_outfcs & 0xFF;
738
                if (ESCAPE_P(c)) {
739
                    *p++ = PPP_ESCAPE;
740
                    *p++ = c ^ PPP_TRANS;
741
                } else
742
                    *p++ = c;
743
                c = (~sc->sc_outfcs >> 8) & 0xFF;
744
                if (ESCAPE_P(c)) {
745
                    *p++ = PPP_ESCAPE;
746
                    *p++ = c ^ PPP_TRANS;
747
                } else
748
                    *p++ = c;
749
                *p++ = PPP_FLAG;
750
 
751
                /*
752
                 * Try to output the FCS and flag.  If the bytes
753
                 * don't all fit, back out.
754
                 */
755
                s = spltty();
756
#ifndef __ECOS
757
                for (q = endseq; q < p; ++q)
758
                    if (putc(*q, &tp->t_outq)) {
759
                        done = 0;
760
                        for (; q > endseq; --q)
761
                            unputc(&tp->t_outq);
762
                        break;
763
                    }
764
#else
765
                {
766
                    cyg_uint32 elen = p-endseq;
767
                    cyg_serial_buf_info_t info;
768
                    cyg_uint32 ilen = sizeof(info);
769
                    q = p;
770
                    if( (cyg_io_get_config( tp->t_handle, CYG_IO_GET_CONFIG_SERIAL_BUFFER_INFO, &info, &ilen ) == 0) &&
771
                        ((info.tx_bufsize-info.tx_count) >= elen) )
772
                    {
773
                        if( cyg_io_write( tp->t_handle, endseq, &elen) != 0 ) {
774
                            done = 0;
775
                        }
776
                    }
777
                    else
778
                    {
779
                        done = 0;
780
                    }
781
                }
782
#endif
783
                splx(s);
784
                if (done)
785
                    sc->sc_stats.ppp_obytes += q - endseq;
786
            } // if (done && m->m_next == NULL)
787
 
788
            if (!done) {
789
                /* remember where we got to */
790
                m->m_data = (char *)start;
791
                m->m_len = len;
792
                break;
793
            }
794
 
795
            /* Finished with this mbuf; free it and move on. */
796
            MFREE(m, m2);
797
            m = m2;
798
            if (m == NULL) {
799
                /* Finished a packet */
800
                break;
801
            }
802
            sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
803
        } // for(;;)
804
 
805
        /*
806
         * If m == NULL, we have finished a packet.
807
         * If m != NULL, we've either done as much work this time
808
         * as we need to, or else we've filled up the output queue.
809
         */
810
        sc->sc_outm = m;
811
        if (m)
812
            break;
813
    }
814
 
815
#ifndef __ECOS        
816
    /* Call pppstart to start output again if necessary. */
817
    s = spltty();
818
    pppstart(tp);
819
 
820
    /*
821
     * This timeout is needed for operation on a pseudo-tty,
822
     * because the pty code doesn't call pppstart after it has
823
     * drained the t_outq.
824
     */
825
    if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) {
826
        sc->sc_ch = timeout(ppp_timeout, (void *) sc, 1);
827
        sc->sc_flags |= SC_TIMEOUT;
828
    }
829
 
830
    splx(s);
831
 
832
#else
833
 
834
    s = spltty();
835
 
836
    if( sc->sc_outm != NULL &&
837
        cyg_thread_self() != tp->tx_thread )
838
    {
839
        cyg_semaphore_post( &tp->tx_sem );
840
    }
841
 
842
    splx(s);
843
 
844
#endif
845
 
846
}
847
 
848
//==========================================================================
849
/*
850
 * This gets called when a received packet is placed on
851
 * the inq, at splsoftnet. The pppd daemon is to be woken up to do a read().
852
 */
853
static void
854
pppasyncctlp(sc)
855
    struct ppp_softc *sc;
856
{
857
    struct tty *tp;
858
    int s;
859
 
860
    s = spltty();
861
    tp = (struct tty *) sc->sc_devp;
862
 
863
    tp->pppd_wakeup = 1;
864
    if( tp->pppd_thread != cyg_thread_self() )
865
        cyg_thread_release( tp->pppd_thread );
866
 
867
    splx(s);
868
}
869
 
870
//==========================================================================
871
/*
872
 * Allocate enough mbuf to handle current MRU.
873
 */
874
static void
875
pppgetm(sc)
876
    register struct ppp_softc *sc;
877
{
878
    struct mbuf *m, **mp;
879
    int len;
880
 
881
    mp = &sc->sc_m;
882
    for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
883
        if ((m = *mp) == NULL) {
884
            MGETHDR(m, M_DONTWAIT, MT_DATA);
885
            if (m == NULL)
886
                break;
887
            *mp = m;
888
            MCLGET(m, M_DONTWAIT);
889
        }
890
        len -= M_DATASIZE(m);
891
        mp = &m->m_next;
892
    }
893
}
894
 
895
//==========================================================================
896
/*
897
 * tty interface receiver interrupt.
898
 */
899
 
900
static unsigned paritytab[8] = {
901
    0x96696996, 0x69969669, 0x69969669, 0x96696996,
902
    0x69969669, 0x96696996, 0x96696996, 0x69969669
903
};
904
 
905
/*
906
 * Called when character is available from device driver.
907
 * Only guaranteed to be at splsofttty() or spltty()
908
 * This is safe to be called while the upper half's netisr is preempted.
909
 */
910
int
911
cyg_ppp_pppinput(c, tp)
912
    int c;
913
    register struct tty *tp;
914
{
915
    register struct ppp_softc *sc;
916
    struct mbuf *m;
917
    int ilen, s;
918
 
919
    sc = (struct ppp_softc *) tp->t_sc;
920
    if (sc == NULL || tp != (struct tty *) sc->sc_devp)
921
        return 0;
922
 
923
//    ++tk_nin;
924
    ++sc->sc_stats.ppp_ibytes;
925
 
926
    s = spltty();
927
    if (c & 0x80)
928
        sc->sc_flags |= SC_RCV_B7_1;
929
    else
930
        sc->sc_flags |= SC_RCV_B7_0;
931
    if (paritytab[c >> 5] & (1 << (c & 0x1F)))
932
        sc->sc_flags |= SC_RCV_ODDP;
933
    else
934
        sc->sc_flags |= SC_RCV_EVNP;
935
    splx(s);
936
 
937
    if (sc->sc_flags & SC_LOG_RAWIN)
938
        ppplogchar(sc, c);
939
 
940
    if (c == PPP_FLAG) {
941
        ilen = sc->sc_ilen;
942
        sc->sc_ilen = 0;
943
        if (sc->sc_rawin_count > 0)
944
            ppplogchar(sc, -1);
945
 
946
        /*
947
         * If SC_ESCAPED is set, then we've seen the packet
948
         * abort sequence "}~".
949
         */
950
        if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
951
            || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
952
            s = spltty();
953
            sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */
954
            if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
955
#if 1
956
                if (sc->sc_flags & SC_DEBUG)
957
                    diag_printf("ppp%d: bad fcs %x, pkt len %d\n",
958
                                sc->sc_if.if_unit, sc->sc_fcs, ilen);
959
#endif
960
                sc->sc_if.if_ierrors++;
961
                sc->sc_stats.ppp_ierrors++;
962
            } else
963
                sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
964
            splx(s);
965
            return 0;
966
        }
967
 
968
        if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
969
            if (ilen) {
970
                if (sc->sc_flags & SC_DEBUG)
971
                    diag_printf("ppp%d: too short (%d)\n", sc->sc_if.if_unit, ilen);
972
                s = spltty();
973
                sc->sc_if.if_ierrors++;
974
                sc->sc_stats.ppp_ierrors++;
975
                sc->sc_flags |= SC_PKTLOST;
976
                splx(s);
977
            }
978
            return 0;
979
        }
980
 
981
        /*
982
         * Remove FCS trailer.  Somewhat painful...
983
         */
984
        ilen -= 2;
985
        if (--sc->sc_mc->m_len == 0) {
986
            for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
987
                ;
988
            sc->sc_mc = m;
989
        }
990
        sc->sc_mc->m_len--;
991
 
992
        /* excise this mbuf chain */
993
        m = sc->sc_m;
994
        sc->sc_m = sc->sc_mc->m_next;
995
        sc->sc_mc->m_next = NULL;
996
 
997
        ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
998
        if (sc->sc_flags & SC_PKTLOST) {
999
            s = spltty();
1000
            sc->sc_flags &= ~SC_PKTLOST;
1001
            splx(s);
1002
        }
1003
 
1004
        pppgetm(sc);
1005
        return 0;
1006
    }
1007
 
1008
    if (sc->sc_flags & SC_FLUSH) {
1009
        if (sc->sc_flags & SC_LOG_FLUSH)
1010
            ppplogchar(sc, c);
1011
        return 0;
1012
    }
1013
 
1014
    if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
1015
        return 0;
1016
 
1017
    s = spltty();
1018
    if (sc->sc_flags & SC_ESCAPED) {
1019
        sc->sc_flags &= ~SC_ESCAPED;
1020
        c ^= PPP_TRANS;
1021
    } else if (c == PPP_ESCAPE) {
1022
        sc->sc_flags |= SC_ESCAPED;
1023
        splx(s);
1024
        return 0;
1025
    }
1026
    splx(s);
1027
 
1028
    /*
1029
     * Initialize buffer on first octet received.
1030
     * First octet could be address or protocol (when compressing
1031
     * address/control).
1032
     * Second octet is control.
1033
     * Third octet is first or second (when compressing protocol)
1034
     * octet of protocol.
1035
     * Fourth octet is second octet of protocol.
1036
     */
1037
    if (sc->sc_ilen == 0) {
1038
        /* reset the first input mbuf */
1039
        if (sc->sc_m == NULL) {
1040
            pppgetm(sc);
1041
            if (sc->sc_m == NULL) {
1042
                if (sc->sc_flags & SC_DEBUG)
1043
                    diag_printf("ppp%d: no input mbufs!\n", sc->sc_if.if_unit);
1044
                goto flush;
1045
            }
1046
        }
1047
        m = sc->sc_m;
1048
        m->m_len = 0;
1049
        m->m_data = M_DATASTART(sc->sc_m);
1050
        sc->sc_mc = m;
1051
        sc->sc_mp = mtod(m, char *);
1052
        sc->sc_fcs = PPP_INITFCS;
1053
        if (c != PPP_ALLSTATIONS) {
1054
            if (sc->sc_flags & SC_REJ_COMP_AC) {
1055
                if (sc->sc_flags & SC_DEBUG)
1056
                    diag_printf("ppp%d: garbage received: 0x%x (need 0xFF)\n",
1057
                           sc->sc_if.if_unit, c);
1058
                goto flush;
1059
            }
1060
            *sc->sc_mp++ = PPP_ALLSTATIONS;
1061
            *sc->sc_mp++ = PPP_UI;
1062
            sc->sc_ilen += 2;
1063
            m->m_len += 2;
1064
        }
1065
    }
1066
    if (sc->sc_ilen == 1 && c != PPP_UI) {
1067
        if (sc->sc_flags & SC_DEBUG)
1068
            diag_printf("ppp%d: missing UI (0x3), got 0x%x\n",
1069
                   sc->sc_if.if_unit, c);
1070
        goto flush;
1071
    }
1072
    if (sc->sc_ilen == 2 && (c & 1) == 1) {
1073
        /* a compressed protocol */
1074
        *sc->sc_mp++ = 0;
1075
        sc->sc_ilen++;
1076
        sc->sc_mc->m_len++;
1077
    }
1078
    if (sc->sc_ilen == 3 && (c & 1) == 0) {
1079
        if (sc->sc_flags & SC_DEBUG)
1080
            diag_printf("ppp%d: bad protocol %x\n", sc->sc_if.if_unit,
1081
                        (sc->sc_mp[-1] << 8) + c);
1082
        goto flush;
1083
    }
1084
 
1085
    /* packet beyond configured mru? */
1086
    if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
1087
        if (sc->sc_flags & SC_DEBUG)
1088
            diag_printf("ppp%d: packet too big\n", sc->sc_if.if_unit);
1089
        goto flush;
1090
    }
1091
 
1092
    /* is this mbuf full? */
1093
    m = sc->sc_mc;
1094
    if (M_TRAILINGSPACE(m) <= 0) {
1095
        if (m->m_next == NULL) {
1096
            pppgetm(sc);
1097
            if (m->m_next == NULL) {
1098
                if (sc->sc_flags & SC_DEBUG)
1099
                    diag_printf("ppp%d: too few input mbufs!\n", sc->sc_if.if_unit);
1100
                goto flush;
1101
            }
1102
        }
1103
        sc->sc_mc = m = m->m_next;
1104
        m->m_len = 0;
1105
        m->m_data = M_DATASTART(m);
1106
        sc->sc_mp = mtod(m, char *);
1107
    }
1108
 
1109
    ++m->m_len;
1110
    *sc->sc_mp++ = c;
1111
    sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
1112
 
1113
    return 0;
1114
 
1115
 flush:
1116
    if (!(sc->sc_flags & SC_FLUSH)) {
1117
        s = spltty();
1118
        sc->sc_if.if_ierrors++;
1119
        sc->sc_stats.ppp_ierrors++;
1120
        sc->sc_flags |= SC_FLUSH;
1121
        splx(s);
1122
        if (sc->sc_flags & SC_LOG_FLUSH)
1123
            ppplogchar(sc, c);
1124
    }
1125
    return 0;
1126
}
1127
 
1128
//==========================================================================
1129
 
1130
#define MAX_DUMP_BYTES  128
1131
 
1132
static void
1133
ppplogchar(sc, c)
1134
    struct ppp_softc *sc;
1135
    int c;
1136
{
1137
    if (c >= 0)
1138
        sc->sc_rawin[sc->sc_rawin_count++] = c;
1139
    if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
1140
        || (c < 0 && sc->sc_rawin_count > 0)) {
1141
        diag_printf("ppp%d input:\n",sc->sc_if.if_unit);
1142
        diag_vdump_buf_with_offset( diag_printf, sc->sc_rawin, sc->sc_rawin_count, sc->sc_rawin );
1143
        sc->sc_rawin_count = 0;
1144
    }
1145
}
1146
 
1147
//==========================================================================
1148
// End of ppp_io.c
1149
 

powered by: WebSVN 2.1.0

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