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