~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/net/hamradio/hdlcdrv.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*****************************************************************************/
 
2
 
 
3
/*
 
4
 *      hdlcdrv.c  -- HDLC packet radio network driver.
 
5
 *
 
6
 *      Copyright (C) 1996-2000  Thomas Sailer (sailer@ife.ee.ethz.ch)
 
7
 *
 
8
 *      This program is free software; you can redistribute it and/or modify
 
9
 *      it under the terms of the GNU General Public License as published by
 
10
 *      the Free Software Foundation; either version 2 of the License, or
 
11
 *      (at your option) any later version.
 
12
 *
 
13
 *      This program is distributed in the hope that it will be useful,
 
14
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
 *      GNU General Public License for more details.
 
17
 *
 
18
 *      You should have received a copy of the GNU General Public License
 
19
 *      along with this program; if not, write to the Free Software
 
20
 *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
21
 *
 
22
 *  Please note that the GPL allows you to use the driver, NOT the radio.
 
23
 *  In order to use the radio, you need a license from the communications
 
24
 *  authority of your country.
 
25
 *
 
26
 *  The driver was derived from Donald Beckers skeleton.c
 
27
 *      Written 1993-94 by Donald Becker.
 
28
 *
 
29
 *  History:
 
30
 *   0.1  21.09.1996  Started
 
31
 *        18.10.1996  Changed to new user space access routines 
 
32
 *                    (copy_{to,from}_user)
 
33
 *   0.2  21.11.1996  various small changes
 
34
 *   0.3  03.03.1997  fixed (hopefully) IP not working with ax.25 as a module
 
35
 *   0.4  16.04.1997  init code/data tagged
 
36
 *   0.5  30.07.1997  made HDLC buffers bigger (solves a problem with the
 
37
 *                    soundmodem driver)
 
38
 *   0.6  05.04.1998  add spinlocks
 
39
 *   0.7  03.08.1999  removed some old compatibility cruft
 
40
 *   0.8  12.02.2000  adapted to softnet driver interface
 
41
 */
 
42
 
 
43
/*****************************************************************************/
 
44
 
 
45
#include <linux/capability.h>
 
46
#include <linux/module.h>
 
47
#include <linux/types.h>
 
48
#include <linux/net.h>
 
49
#include <linux/in.h>
 
50
#include <linux/if.h>
 
51
#include <linux/errno.h>
 
52
#include <linux/init.h>
 
53
#include <linux/bitops.h>
 
54
 
 
55
#include <linux/netdevice.h>
 
56
#include <linux/if_arp.h>
 
57
#include <linux/skbuff.h>
 
58
#include <linux/hdlcdrv.h>
 
59
#include <linux/random.h>
 
60
#include <net/ax25.h> 
 
61
#include <asm/uaccess.h>
 
62
 
 
63
#include <linux/crc-ccitt.h>
 
64
 
 
65
/* --------------------------------------------------------------------- */
 
66
 
 
67
#define KISS_VERBOSE
 
68
 
 
69
/* --------------------------------------------------------------------- */
 
70
 
 
71
#define PARAM_TXDELAY   1
 
72
#define PARAM_PERSIST   2
 
73
#define PARAM_SLOTTIME  3
 
74
#define PARAM_TXTAIL    4
 
75
#define PARAM_FULLDUP   5
 
76
#define PARAM_HARDWARE  6
 
77
#define PARAM_RETURN    255
 
78
 
 
79
/* --------------------------------------------------------------------- */
 
80
/*
 
81
 * the CRC routines are stolen from WAMPES
 
82
 * by Dieter Deyke
 
83
 */
 
84
 
 
85
 
 
86
/*---------------------------------------------------------------------------*/
 
87
 
 
88
static inline void append_crc_ccitt(unsigned char *buffer, int len)
 
89
{
 
90
        unsigned int crc = crc_ccitt(0xffff, buffer, len) ^ 0xffff;
 
91
        buffer += len;
 
92
        *buffer++ = crc;
 
93
        *buffer++ = crc >> 8;
 
94
}
 
95
 
 
96
/*---------------------------------------------------------------------------*/
 
97
 
 
98
static inline int check_crc_ccitt(const unsigned char *buf, int cnt)
 
99
{
 
100
        return (crc_ccitt(0xffff, buf, cnt) & 0xffff) == 0xf0b8;
 
101
}
 
102
 
 
103
/*---------------------------------------------------------------------------*/
 
104
 
 
105
#if 0
 
106
static int calc_crc_ccitt(const unsigned char *buf, int cnt)
 
107
{
 
108
        unsigned int crc = 0xffff;
 
109
 
 
110
        for (; cnt > 0; cnt--)
 
111
                crc = (crc >> 8) ^ crc_ccitt_table[(crc ^ *buf++) & 0xff];
 
112
        crc ^= 0xffff;
 
113
        return crc & 0xffff;
 
114
}
 
115
#endif
 
116
 
 
117
/* ---------------------------------------------------------------------- */
 
118
 
 
119
#define tenms_to_2flags(s,tenms) ((tenms * s->par.bitrate) / 100 / 16)
 
120
 
 
121
/* ---------------------------------------------------------------------- */
 
122
/*
 
123
 * The HDLC routines
 
124
 */
 
125
 
 
126
static int hdlc_rx_add_bytes(struct hdlcdrv_state *s, unsigned int bits, 
 
127
                             int num)
 
128
{
 
129
        int added = 0;
 
130
        
 
131
        while (s->hdlcrx.rx_state && num >= 8) {
 
132
                if (s->hdlcrx.len >= sizeof(s->hdlcrx.buffer)) {
 
133
                        s->hdlcrx.rx_state = 0;
 
134
                        return 0;
 
135
                }
 
136
                *s->hdlcrx.bp++ = bits >> (32-num);
 
137
                s->hdlcrx.len++;
 
138
                num -= 8;
 
139
                added += 8;
 
140
        }
 
141
        return added;
 
142
}
 
143
 
 
144
static void hdlc_rx_flag(struct net_device *dev, struct hdlcdrv_state *s)
 
145
{
 
146
        struct sk_buff *skb;
 
147
        int pkt_len;
 
148
        unsigned char *cp;
 
149
 
 
150
        if (s->hdlcrx.len < 4) 
 
151
                return;
 
152
        if (!check_crc_ccitt(s->hdlcrx.buffer, s->hdlcrx.len)) 
 
153
                return;
 
154
        pkt_len = s->hdlcrx.len - 2 + 1; /* KISS kludge */
 
155
        if (!(skb = dev_alloc_skb(pkt_len))) {
 
156
                printk("%s: memory squeeze, dropping packet\n", dev->name);
 
157
                dev->stats.rx_dropped++;
 
158
                return;
 
159
        }
 
160
        cp = skb_put(skb, pkt_len);
 
161
        *cp++ = 0; /* KISS kludge */
 
162
        memcpy(cp, s->hdlcrx.buffer, pkt_len - 1);
 
163
        skb->protocol = ax25_type_trans(skb, dev);
 
164
        netif_rx(skb);
 
165
        dev->stats.rx_packets++;
 
166
}
 
167
 
 
168
void hdlcdrv_receiver(struct net_device *dev, struct hdlcdrv_state *s)
 
169
{
 
170
        int i;
 
171
        unsigned int mask1, mask2, mask3, mask4, mask5, mask6, word;
 
172
        
 
173
        if (!s || s->magic != HDLCDRV_MAGIC) 
 
174
                return;
 
175
        if (test_and_set_bit(0, &s->hdlcrx.in_hdlc_rx))
 
176
                return;
 
177
 
 
178
        while (!hdlcdrv_hbuf_empty(&s->hdlcrx.hbuf)) {
 
179
                word = hdlcdrv_hbuf_get(&s->hdlcrx.hbuf);       
 
180
 
 
181
#ifdef HDLCDRV_DEBUG
 
182
                hdlcdrv_add_bitbuffer_word(&s->bitbuf_hdlc, word);
 
183
#endif /* HDLCDRV_DEBUG */
 
184
                s->hdlcrx.bitstream >>= 16;
 
185
                s->hdlcrx.bitstream |= word << 16;
 
186
                s->hdlcrx.bitbuf >>= 16;
 
187
                s->hdlcrx.bitbuf |= word << 16;
 
188
                s->hdlcrx.numbits += 16;
 
189
                for(i = 15, mask1 = 0x1fc00, mask2 = 0x1fe00, mask3 = 0x0fc00,
 
190
                    mask4 = 0x1f800, mask5 = 0xf800, mask6 = 0xffff; 
 
191
                    i >= 0; 
 
192
                    i--, mask1 <<= 1, mask2 <<= 1, mask3 <<= 1, mask4 <<= 1, 
 
193
                    mask5 <<= 1, mask6 = (mask6 << 1) | 1) {
 
194
                        if ((s->hdlcrx.bitstream & mask1) == mask1)
 
195
                                s->hdlcrx.rx_state = 0; /* abort received */
 
196
                        else if ((s->hdlcrx.bitstream & mask2) == mask3) {
 
197
                                /* flag received */
 
198
                                if (s->hdlcrx.rx_state) {
 
199
                                        hdlc_rx_add_bytes(s, s->hdlcrx.bitbuf 
 
200
                                                          << (8+i),
 
201
                                                          s->hdlcrx.numbits
 
202
                                                          -8-i);
 
203
                                        hdlc_rx_flag(dev, s);
 
204
                                }
 
205
                                s->hdlcrx.len = 0;
 
206
                                s->hdlcrx.bp = s->hdlcrx.buffer;
 
207
                                s->hdlcrx.rx_state = 1;
 
208
                                s->hdlcrx.numbits = i;
 
209
                        } else if ((s->hdlcrx.bitstream & mask4) == mask5) {
 
210
                                /* stuffed bit */
 
211
                                s->hdlcrx.numbits--;
 
212
                                s->hdlcrx.bitbuf = (s->hdlcrx.bitbuf & (~mask6)) |
 
213
                                        ((s->hdlcrx.bitbuf & mask6) << 1);
 
214
                        }
 
215
                }
 
216
                s->hdlcrx.numbits -= hdlc_rx_add_bytes(s, s->hdlcrx.bitbuf,
 
217
                                                       s->hdlcrx.numbits);
 
218
        }
 
219
        clear_bit(0, &s->hdlcrx.in_hdlc_rx);
 
220
}
 
221
 
 
222
/* ---------------------------------------------------------------------- */
 
223
 
 
224
static inline void do_kiss_params(struct hdlcdrv_state *s,
 
225
                                  unsigned char *data, unsigned long len)
 
226
{
 
227
 
 
228
#ifdef KISS_VERBOSE
 
229
#define PKP(a,b) printk(KERN_INFO "hdlcdrv.c: channel params: " a "\n", b)
 
230
#else /* KISS_VERBOSE */              
 
231
#define PKP(a,b) 
 
232
#endif /* KISS_VERBOSE */             
 
233
 
 
234
        if (len < 2)
 
235
                return;
 
236
        switch(data[0]) {
 
237
        case PARAM_TXDELAY:
 
238
                s->ch_params.tx_delay = data[1];
 
239
                PKP("TX delay = %ums", 10 * s->ch_params.tx_delay);
 
240
                break;
 
241
        case PARAM_PERSIST:   
 
242
                s->ch_params.ppersist = data[1];
 
243
                PKP("p persistence = %u", s->ch_params.ppersist);
 
244
                break;
 
245
        case PARAM_SLOTTIME:  
 
246
                s->ch_params.slottime = data[1];
 
247
                PKP("slot time = %ums", s->ch_params.slottime);
 
248
                break;
 
249
        case PARAM_TXTAIL:    
 
250
                s->ch_params.tx_tail = data[1];
 
251
                PKP("TX tail = %ums", s->ch_params.tx_tail);
 
252
                break;
 
253
        case PARAM_FULLDUP:   
 
254
                s->ch_params.fulldup = !!data[1];
 
255
                PKP("%s duplex", s->ch_params.fulldup ? "full" : "half");
 
256
                break;
 
257
        default:
 
258
                break;
 
259
        }
 
260
#undef PKP
 
261
}
 
262
 
 
263
/* ---------------------------------------------------------------------- */
 
264
 
 
265
void hdlcdrv_transmitter(struct net_device *dev, struct hdlcdrv_state *s)
 
266
{
 
267
        unsigned int mask1, mask2, mask3;
 
268
        int i;
 
269
        struct sk_buff *skb;
 
270
        int pkt_len;
 
271
 
 
272
        if (!s || s->magic != HDLCDRV_MAGIC) 
 
273
                return;
 
274
        if (test_and_set_bit(0, &s->hdlctx.in_hdlc_tx))
 
275
                return;
 
276
        for (;;) {
 
277
                if (s->hdlctx.numbits >= 16) {
 
278
                        if (hdlcdrv_hbuf_full(&s->hdlctx.hbuf)) {
 
279
                                clear_bit(0, &s->hdlctx.in_hdlc_tx);
 
280
                                return;
 
281
                        }
 
282
                        hdlcdrv_hbuf_put(&s->hdlctx.hbuf, s->hdlctx.bitbuf);
 
283
                        s->hdlctx.bitbuf >>= 16;
 
284
                        s->hdlctx.numbits -= 16;
 
285
                }
 
286
                switch (s->hdlctx.tx_state) {
 
287
                default:
 
288
                        clear_bit(0, &s->hdlctx.in_hdlc_tx);
 
289
                        return;
 
290
                case 0:
 
291
                case 1:
 
292
                        if (s->hdlctx.numflags) {
 
293
                                s->hdlctx.numflags--;
 
294
                                s->hdlctx.bitbuf |= 
 
295
                                        0x7e7e << s->hdlctx.numbits;
 
296
                                s->hdlctx.numbits += 16;
 
297
                                break;
 
298
                        }
 
299
                        if (s->hdlctx.tx_state == 1) {
 
300
                                clear_bit(0, &s->hdlctx.in_hdlc_tx);
 
301
                                return;
 
302
                        }
 
303
                        if (!(skb = s->skb)) {
 
304
                                int flgs = tenms_to_2flags(s, s->ch_params.tx_tail);
 
305
                                if (flgs < 2)
 
306
                                        flgs = 2;
 
307
                                s->hdlctx.tx_state = 1;
 
308
                                s->hdlctx.numflags = flgs;
 
309
                                break;
 
310
                        }
 
311
                        s->skb = NULL;
 
312
                        netif_wake_queue(dev);
 
313
                        pkt_len = skb->len-1; /* strip KISS byte */
 
314
                        if (pkt_len >= HDLCDRV_MAXFLEN || pkt_len < 2) {
 
315
                                s->hdlctx.tx_state = 0;
 
316
                                s->hdlctx.numflags = 1;
 
317
                                dev_kfree_skb_irq(skb);
 
318
                                break;
 
319
                        }
 
320
                        skb_copy_from_linear_data_offset(skb, 1,
 
321
                                                         s->hdlctx.buffer,
 
322
                                                         pkt_len);
 
323
                        dev_kfree_skb_irq(skb);
 
324
                        s->hdlctx.bp = s->hdlctx.buffer;
 
325
                        append_crc_ccitt(s->hdlctx.buffer, pkt_len);
 
326
                        s->hdlctx.len = pkt_len+2; /* the appended CRC */
 
327
                        s->hdlctx.tx_state = 2;
 
328
                        s->hdlctx.bitstream = 0;
 
329
                        dev->stats.tx_packets++;
 
330
                        break;
 
331
                case 2:
 
332
                        if (!s->hdlctx.len) {
 
333
                                s->hdlctx.tx_state = 0;
 
334
                                s->hdlctx.numflags = 1;
 
335
                                break;
 
336
                        }
 
337
                        s->hdlctx.len--;
 
338
                        s->hdlctx.bitbuf |= *s->hdlctx.bp <<
 
339
                                s->hdlctx.numbits;
 
340
                        s->hdlctx.bitstream >>= 8;
 
341
                        s->hdlctx.bitstream |= (*s->hdlctx.bp++) << 16;
 
342
                        mask1 = 0x1f000;
 
343
                        mask2 = 0x10000;
 
344
                        mask3 = 0xffffffff >> (31-s->hdlctx.numbits);
 
345
                        s->hdlctx.numbits += 8;
 
346
                        for(i = 0; i < 8; i++, mask1 <<= 1, mask2 <<= 1, 
 
347
                            mask3 = (mask3 << 1) | 1) {
 
348
                                if ((s->hdlctx.bitstream & mask1) != mask1) 
 
349
                                        continue;
 
350
                                s->hdlctx.bitstream &= ~mask2;
 
351
                                s->hdlctx.bitbuf = 
 
352
                                        (s->hdlctx.bitbuf & mask3) |
 
353
                                                ((s->hdlctx.bitbuf & 
 
354
                                                 (~mask3)) << 1);
 
355
                                s->hdlctx.numbits++;
 
356
                                mask3 = (mask3 << 1) | 1;
 
357
                        }
 
358
                        break;
 
359
                }
 
360
        }
 
361
}
 
362
 
 
363
/* ---------------------------------------------------------------------- */
 
364
 
 
365
static void start_tx(struct net_device *dev, struct hdlcdrv_state *s)
 
366
{
 
367
        s->hdlctx.tx_state = 0;
 
368
        s->hdlctx.numflags = tenms_to_2flags(s, s->ch_params.tx_delay);
 
369
        s->hdlctx.bitbuf = s->hdlctx.bitstream = s->hdlctx.numbits = 0;
 
370
        hdlcdrv_transmitter(dev, s);
 
371
        s->hdlctx.ptt = 1;
 
372
        s->ptt_keyed++;
 
373
}
 
374
 
 
375
/* ---------------------------------------------------------------------- */
 
376
 
 
377
void hdlcdrv_arbitrate(struct net_device *dev, struct hdlcdrv_state *s)
 
378
{
 
379
        if (!s || s->magic != HDLCDRV_MAGIC || s->hdlctx.ptt || !s->skb) 
 
380
                return;
 
381
        if (s->ch_params.fulldup) {
 
382
                start_tx(dev, s);
 
383
                return;
 
384
        }
 
385
        if (s->hdlcrx.dcd) {
 
386
                s->hdlctx.slotcnt = s->ch_params.slottime;
 
387
                return;
 
388
        }
 
389
        if ((--s->hdlctx.slotcnt) > 0)
 
390
                return;
 
391
        s->hdlctx.slotcnt = s->ch_params.slottime;
 
392
        if ((random32() % 256) > s->ch_params.ppersist)
 
393
                return;
 
394
        start_tx(dev, s);
 
395
}
 
396
 
 
397
/* --------------------------------------------------------------------- */
 
398
/*
 
399
 * ===================== network driver interface =========================
 
400
 */
 
401
 
 
402
static netdev_tx_t hdlcdrv_send_packet(struct sk_buff *skb,
 
403
                                       struct net_device *dev)
 
404
{
 
405
        struct hdlcdrv_state *sm = netdev_priv(dev);
 
406
 
 
407
        if (skb->data[0] != 0) {
 
408
                do_kiss_params(sm, skb->data, skb->len);
 
409
                dev_kfree_skb(skb);
 
410
                return NETDEV_TX_OK;
 
411
        }
 
412
        if (sm->skb)
 
413
                return NETDEV_TX_LOCKED;
 
414
        netif_stop_queue(dev);
 
415
        sm->skb = skb;
 
416
        return NETDEV_TX_OK;
 
417
}
 
418
 
 
419
/* --------------------------------------------------------------------- */
 
420
 
 
421
static int hdlcdrv_set_mac_address(struct net_device *dev, void *addr)
 
422
{
 
423
        struct sockaddr *sa = (struct sockaddr *)addr;
 
424
 
 
425
        /* addr is an AX.25 shifted ASCII mac address */
 
426
        memcpy(dev->dev_addr, sa->sa_data, dev->addr_len); 
 
427
        return 0;                                         
 
428
}
 
429
 
 
430
/* --------------------------------------------------------------------- */
 
431
/*
 
432
 * Open/initialize the board. This is called (in the current kernel)
 
433
 * sometime after booting when the 'ifconfig' program is run.
 
434
 *
 
435
 * This routine should set everything up anew at each open, even
 
436
 * registers that "should" only need to be set once at boot, so that
 
437
 * there is non-reboot way to recover if something goes wrong.
 
438
 */
 
439
 
 
440
static int hdlcdrv_open(struct net_device *dev)
 
441
{
 
442
        struct hdlcdrv_state *s = netdev_priv(dev);
 
443
        int i;
 
444
 
 
445
        if (!s->ops || !s->ops->open)
 
446
                return -ENODEV;
 
447
 
 
448
        /*
 
449
         * initialise some variables
 
450
         */
 
451
        s->opened = 1;
 
452
        s->hdlcrx.hbuf.rd = s->hdlcrx.hbuf.wr = 0;
 
453
        s->hdlcrx.in_hdlc_rx = 0;
 
454
        s->hdlcrx.rx_state = 0;
 
455
        
 
456
        s->hdlctx.hbuf.rd = s->hdlctx.hbuf.wr = 0;
 
457
        s->hdlctx.in_hdlc_tx = 0;
 
458
        s->hdlctx.tx_state = 1;
 
459
        s->hdlctx.numflags = 0;
 
460
        s->hdlctx.bitstream = s->hdlctx.bitbuf = s->hdlctx.numbits = 0;
 
461
        s->hdlctx.ptt = 0;
 
462
        s->hdlctx.slotcnt = s->ch_params.slottime;
 
463
        s->hdlctx.calibrate = 0;
 
464
 
 
465
        i = s->ops->open(dev);
 
466
        if (i)
 
467
                return i;
 
468
        netif_start_queue(dev);
 
469
        return 0;
 
470
}
 
471
 
 
472
/* --------------------------------------------------------------------- */
 
473
/* 
 
474
 * The inverse routine to hdlcdrv_open(). 
 
475
 */
 
476
 
 
477
static int hdlcdrv_close(struct net_device *dev)
 
478
{
 
479
        struct hdlcdrv_state *s = netdev_priv(dev);
 
480
        int i = 0;
 
481
 
 
482
        netif_stop_queue(dev);
 
483
 
 
484
        if (s->ops && s->ops->close)
 
485
                i = s->ops->close(dev);
 
486
        if (s->skb)
 
487
                dev_kfree_skb(s->skb);
 
488
        s->skb = NULL;
 
489
        s->opened = 0;
 
490
        return i;
 
491
}
 
492
 
 
493
/* --------------------------------------------------------------------- */
 
494
 
 
495
static int hdlcdrv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 
496
{
 
497
        struct hdlcdrv_state *s = netdev_priv(dev);
 
498
        struct hdlcdrv_ioctl bi;
 
499
 
 
500
        if (cmd != SIOCDEVPRIVATE) {
 
501
                if (s->ops && s->ops->ioctl)
 
502
                        return s->ops->ioctl(dev, ifr, &bi, cmd);
 
503
                return -ENOIOCTLCMD;
 
504
        }
 
505
        if (copy_from_user(&bi, ifr->ifr_data, sizeof(bi)))
 
506
                return -EFAULT;
 
507
 
 
508
        switch (bi.cmd) {
 
509
        default:
 
510
                if (s->ops && s->ops->ioctl)
 
511
                        return s->ops->ioctl(dev, ifr, &bi, cmd);
 
512
                return -ENOIOCTLCMD;
 
513
 
 
514
        case HDLCDRVCTL_GETCHANNELPAR:
 
515
                bi.data.cp.tx_delay = s->ch_params.tx_delay;
 
516
                bi.data.cp.tx_tail = s->ch_params.tx_tail;
 
517
                bi.data.cp.slottime = s->ch_params.slottime;
 
518
                bi.data.cp.ppersist = s->ch_params.ppersist;
 
519
                bi.data.cp.fulldup = s->ch_params.fulldup;
 
520
                break;
 
521
 
 
522
        case HDLCDRVCTL_SETCHANNELPAR:
 
523
                if (!capable(CAP_NET_ADMIN))
 
524
                        return -EACCES;
 
525
                s->ch_params.tx_delay = bi.data.cp.tx_delay;
 
526
                s->ch_params.tx_tail = bi.data.cp.tx_tail;
 
527
                s->ch_params.slottime = bi.data.cp.slottime;
 
528
                s->ch_params.ppersist = bi.data.cp.ppersist;
 
529
                s->ch_params.fulldup = bi.data.cp.fulldup;
 
530
                s->hdlctx.slotcnt = 1;
 
531
                return 0;
 
532
                
 
533
        case HDLCDRVCTL_GETMODEMPAR:
 
534
                bi.data.mp.iobase = dev->base_addr;
 
535
                bi.data.mp.irq = dev->irq;
 
536
                bi.data.mp.dma = dev->dma;
 
537
                bi.data.mp.dma2 = s->ptt_out.dma2;
 
538
                bi.data.mp.seriobase = s->ptt_out.seriobase;
 
539
                bi.data.mp.pariobase = s->ptt_out.pariobase;
 
540
                bi.data.mp.midiiobase = s->ptt_out.midiiobase;
 
541
                break;
 
542
 
 
543
        case HDLCDRVCTL_SETMODEMPAR:
 
544
                if ((!capable(CAP_SYS_RAWIO)) || netif_running(dev))
 
545
                        return -EACCES;
 
546
                dev->base_addr = bi.data.mp.iobase;
 
547
                dev->irq = bi.data.mp.irq;
 
548
                dev->dma = bi.data.mp.dma;
 
549
                s->ptt_out.dma2 = bi.data.mp.dma2;
 
550
                s->ptt_out.seriobase = bi.data.mp.seriobase;
 
551
                s->ptt_out.pariobase = bi.data.mp.pariobase;
 
552
                s->ptt_out.midiiobase = bi.data.mp.midiiobase;
 
553
                return 0;       
 
554
        
 
555
        case HDLCDRVCTL_GETSTAT:
 
556
                bi.data.cs.ptt = hdlcdrv_ptt(s);
 
557
                bi.data.cs.dcd = s->hdlcrx.dcd;
 
558
                bi.data.cs.ptt_keyed = s->ptt_keyed;
 
559
                bi.data.cs.tx_packets = dev->stats.tx_packets;
 
560
                bi.data.cs.tx_errors = dev->stats.tx_errors;
 
561
                bi.data.cs.rx_packets = dev->stats.rx_packets;
 
562
                bi.data.cs.rx_errors = dev->stats.rx_errors;
 
563
                break;          
 
564
 
 
565
        case HDLCDRVCTL_OLDGETSTAT:
 
566
                bi.data.ocs.ptt = hdlcdrv_ptt(s);
 
567
                bi.data.ocs.dcd = s->hdlcrx.dcd;
 
568
                bi.data.ocs.ptt_keyed = s->ptt_keyed;
 
569
                break;          
 
570
 
 
571
        case HDLCDRVCTL_CALIBRATE:
 
572
                if(!capable(CAP_SYS_RAWIO))
 
573
                        return -EPERM;
 
574
                s->hdlctx.calibrate = bi.data.calibrate * s->par.bitrate / 16;
 
575
                return 0;
 
576
 
 
577
        case HDLCDRVCTL_GETSAMPLES:
 
578
#ifndef HDLCDRV_DEBUG
 
579
                return -EPERM;
 
580
#else /* HDLCDRV_DEBUG */
 
581
                if (s->bitbuf_channel.rd == s->bitbuf_channel.wr) 
 
582
                        return -EAGAIN;
 
583
                bi.data.bits = 
 
584
                        s->bitbuf_channel.buffer[s->bitbuf_channel.rd];
 
585
                s->bitbuf_channel.rd = (s->bitbuf_channel.rd+1) %
 
586
                        sizeof(s->bitbuf_channel.buffer);
 
587
                break;
 
588
#endif /* HDLCDRV_DEBUG */
 
589
                                
 
590
        case HDLCDRVCTL_GETBITS:
 
591
#ifndef HDLCDRV_DEBUG
 
592
                return -EPERM;
 
593
#else /* HDLCDRV_DEBUG */
 
594
                if (s->bitbuf_hdlc.rd == s->bitbuf_hdlc.wr) 
 
595
                        return -EAGAIN;
 
596
                bi.data.bits = 
 
597
                        s->bitbuf_hdlc.buffer[s->bitbuf_hdlc.rd];
 
598
                s->bitbuf_hdlc.rd = (s->bitbuf_hdlc.rd+1) %
 
599
                        sizeof(s->bitbuf_hdlc.buffer);
 
600
                break;          
 
601
#endif /* HDLCDRV_DEBUG */
 
602
 
 
603
        case HDLCDRVCTL_DRIVERNAME:
 
604
                if (s->ops && s->ops->drvname) {
 
605
                        strncpy(bi.data.drivername, s->ops->drvname, 
 
606
                                sizeof(bi.data.drivername));
 
607
                        break;
 
608
                }
 
609
                bi.data.drivername[0] = '\0';
 
610
                break;
 
611
                
 
612
        }
 
613
        if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi)))
 
614
                return -EFAULT;
 
615
        return 0;
 
616
 
 
617
}
 
618
 
 
619
/* --------------------------------------------------------------------- */
 
620
 
 
621
static const struct net_device_ops hdlcdrv_netdev = {
 
622
        .ndo_open       = hdlcdrv_open,
 
623
        .ndo_stop       = hdlcdrv_close,
 
624
        .ndo_start_xmit = hdlcdrv_send_packet,
 
625
        .ndo_do_ioctl   = hdlcdrv_ioctl,
 
626
        .ndo_set_mac_address = hdlcdrv_set_mac_address,
 
627
};
 
628
 
 
629
/*
 
630
 * Initialize fields in hdlcdrv
 
631
 */
 
632
static void hdlcdrv_setup(struct net_device *dev)
 
633
{
 
634
        static const struct hdlcdrv_channel_params dflt_ch_params = { 
 
635
                20, 2, 10, 40, 0 
 
636
        };
 
637
        struct hdlcdrv_state *s = netdev_priv(dev);
 
638
 
 
639
        /*
 
640
         * initialize the hdlcdrv_state struct
 
641
         */
 
642
        s->ch_params = dflt_ch_params;
 
643
        s->ptt_keyed = 0;
 
644
 
 
645
        spin_lock_init(&s->hdlcrx.hbuf.lock);
 
646
        s->hdlcrx.hbuf.rd = s->hdlcrx.hbuf.wr = 0;
 
647
        s->hdlcrx.in_hdlc_rx = 0;
 
648
        s->hdlcrx.rx_state = 0;
 
649
        
 
650
        spin_lock_init(&s->hdlctx.hbuf.lock);
 
651
        s->hdlctx.hbuf.rd = s->hdlctx.hbuf.wr = 0;
 
652
        s->hdlctx.in_hdlc_tx = 0;
 
653
        s->hdlctx.tx_state = 1;
 
654
        s->hdlctx.numflags = 0;
 
655
        s->hdlctx.bitstream = s->hdlctx.bitbuf = s->hdlctx.numbits = 0;
 
656
        s->hdlctx.ptt = 0;
 
657
        s->hdlctx.slotcnt = s->ch_params.slottime;
 
658
        s->hdlctx.calibrate = 0;
 
659
 
 
660
#ifdef HDLCDRV_DEBUG
 
661
        s->bitbuf_channel.rd = s->bitbuf_channel.wr = 0;
 
662
        s->bitbuf_channel.shreg = 0x80;
 
663
 
 
664
        s->bitbuf_hdlc.rd = s->bitbuf_hdlc.wr = 0;
 
665
        s->bitbuf_hdlc.shreg = 0x80;
 
666
#endif /* HDLCDRV_DEBUG */
 
667
 
 
668
 
 
669
        /* Fill in the fields of the device structure */
 
670
 
 
671
        s->skb = NULL;
 
672
        
 
673
        dev->netdev_ops = &hdlcdrv_netdev;
 
674
        dev->header_ops = &ax25_header_ops;
 
675
        
 
676
        dev->type = ARPHRD_AX25;           /* AF_AX25 device */
 
677
        dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN;
 
678
        dev->mtu = AX25_DEF_PACLEN;        /* eth_mtu is the default */
 
679
        dev->addr_len = AX25_ADDR_LEN;     /* sizeof an ax.25 address */
 
680
        memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);
 
681
        memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN);
 
682
        dev->tx_queue_len = 16;
 
683
}
 
684
 
 
685
/* --------------------------------------------------------------------- */
 
686
struct net_device *hdlcdrv_register(const struct hdlcdrv_ops *ops,
 
687
                                    unsigned int privsize, const char *ifname,
 
688
                                    unsigned int baseaddr, unsigned int irq, 
 
689
                                    unsigned int dma) 
 
690
{
 
691
        struct net_device *dev;
 
692
        struct hdlcdrv_state *s;
 
693
        int err;
 
694
 
 
695
        BUG_ON(ops == NULL);
 
696
 
 
697
        if (privsize < sizeof(struct hdlcdrv_state))
 
698
                privsize = sizeof(struct hdlcdrv_state);
 
699
 
 
700
        dev = alloc_netdev(privsize, ifname, hdlcdrv_setup);
 
701
        if (!dev)
 
702
                return ERR_PTR(-ENOMEM);
 
703
 
 
704
        /*
 
705
         * initialize part of the hdlcdrv_state struct
 
706
         */
 
707
        s = netdev_priv(dev);
 
708
        s->magic = HDLCDRV_MAGIC;
 
709
        s->ops = ops;
 
710
        dev->base_addr = baseaddr;
 
711
        dev->irq = irq;
 
712
        dev->dma = dma;
 
713
 
 
714
        err = register_netdev(dev);
 
715
        if (err < 0) {
 
716
                printk(KERN_WARNING "hdlcdrv: cannot register net "
 
717
                       "device %s\n", dev->name);
 
718
                free_netdev(dev);
 
719
                dev = ERR_PTR(err);
 
720
        }
 
721
        return dev;
 
722
}
 
723
 
 
724
/* --------------------------------------------------------------------- */
 
725
 
 
726
void hdlcdrv_unregister(struct net_device *dev) 
 
727
{
 
728
        struct hdlcdrv_state *s = netdev_priv(dev);
 
729
 
 
730
        BUG_ON(s->magic != HDLCDRV_MAGIC);
 
731
 
 
732
        if (s->opened && s->ops->close)
 
733
                s->ops->close(dev);
 
734
        unregister_netdev(dev);
 
735
        
 
736
        free_netdev(dev);
 
737
}
 
738
 
 
739
/* --------------------------------------------------------------------- */
 
740
 
 
741
EXPORT_SYMBOL(hdlcdrv_receiver);
 
742
EXPORT_SYMBOL(hdlcdrv_transmitter);
 
743
EXPORT_SYMBOL(hdlcdrv_arbitrate);
 
744
EXPORT_SYMBOL(hdlcdrv_register);
 
745
EXPORT_SYMBOL(hdlcdrv_unregister);
 
746
 
 
747
/* --------------------------------------------------------------------- */
 
748
 
 
749
static int __init hdlcdrv_init_driver(void)
 
750
{
 
751
        printk(KERN_INFO "hdlcdrv: (C) 1996-2000 Thomas Sailer HB9JNX/AE4WA\n");
 
752
        printk(KERN_INFO "hdlcdrv: version 0.8\n");
 
753
        return 0;
 
754
}
 
755
 
 
756
/* --------------------------------------------------------------------- */
 
757
 
 
758
static void __exit hdlcdrv_cleanup_driver(void)
 
759
{
 
760
        printk(KERN_INFO "hdlcdrv: cleanup\n");
 
761
}
 
762
 
 
763
/* --------------------------------------------------------------------- */
 
764
 
 
765
MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
 
766
MODULE_DESCRIPTION("Packet Radio network interface HDLC encoder/decoder");
 
767
MODULE_LICENSE("GPL");
 
768
module_init(hdlcdrv_init_driver);
 
769
module_exit(hdlcdrv_cleanup_driver);
 
770
 
 
771
/* --------------------------------------------------------------------- */