1 /*****************************************************************************/
4 * hdlcdrv.c -- HDLC packet radio network driver.
6 * Copyright (C) 1996-1999 Thomas Sailer (sailer@ife.ee.ethz.ch)
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.
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.
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.
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.
26 * The driver was derived from Donald Beckers skeleton.c
27 * Written 1993-94 by Donald Becker.
30 * 0.1 21.09.96 Started
31 * 18.10.96 Changed to new user space access routines
32 * (copy_{to,from}_user)
33 * 0.2 21.11.96 various small changes
34 * 0.3 03.03.97 fixed (hopefully) IP not working with ax.25 as a module
35 * 0.4 16.04.97 init code/data tagged
36 * 0.5 30.07.97 made HDLC buffers bigger (solves a problem with the
38 * 0.6 05.04.98 add spinlocks
39 * 0.7 03.08.99 removed some old compatibility cruft
42 /*****************************************************************************/
44 #include <linux/config.h>
45 #include <linux/version.h>
46 #include <linux/module.h>
47 #include <linux/types.h>
48 #include <linux/net.h>
51 #include <linux/malloc.h>
52 #include <linux/errno.h>
53 #include <linux/init.h>
54 #include <asm/bitops.h>
55 #include <asm/uaccess.h>
57 #include <linux/netdevice.h>
58 #include <linux/if_arp.h>
59 #include <linux/etherdevice.h>
60 #include <linux/skbuff.h>
61 #include <linux/hdlcdrv.h>
62 /* prototypes for ax25_encapsulate and ax25_rebuild_header */
65 /* make genksyms happy */
67 #include <linux/udp.h>
68 #include <linux/tcp.h>
70 /* --------------------------------------------------------------------- */
73 * The name of the card. Is used for messages and in the requests for
74 * io regions, irqs and dma channels
77 static char ax25_bcast
[AX25_ADDR_LEN
] =
78 {'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1};
79 static char ax25_nocall
[AX25_ADDR_LEN
] =
80 {'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1};
82 /* --------------------------------------------------------------------- */
86 /* --------------------------------------------------------------------- */
88 #define PARAM_TXDELAY 1
89 #define PARAM_PERSIST 2
90 #define PARAM_SLOTTIME 3
91 #define PARAM_TXTAIL 4
92 #define PARAM_FULLDUP 5
93 #define PARAM_HARDWARE 6
94 #define PARAM_RETURN 255
96 /* --------------------------------------------------------------------- */
98 #define min(a, b) (((a) < (b)) ? (a) : (b))
99 #define max(a, b) (((a) > (b)) ? (a) : (b))
101 /* --------------------------------------------------------------------- */
103 * the CRC routines are stolen from WAMPES
107 static const unsigned short crc_ccitt_table
[] = {
108 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
109 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
110 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
111 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
112 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
113 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
114 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
115 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
116 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
117 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
118 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
119 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
120 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
121 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
122 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
123 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
124 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
125 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
126 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
127 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
128 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
129 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
130 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
131 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
132 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
133 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
134 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
135 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
136 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
137 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
138 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
139 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
142 /*---------------------------------------------------------------------------*/
144 static inline void append_crc_ccitt(unsigned char *buffer
, int len
)
146 unsigned int crc
= 0xffff;
149 crc
= (crc
>> 8) ^ crc_ccitt_table
[(crc
^ *buffer
++) & 0xff];
152 *buffer
++ = crc
>> 8;
155 /*---------------------------------------------------------------------------*/
157 static inline int check_crc_ccitt(const unsigned char *buf
, int cnt
)
159 unsigned int crc
= 0xffff;
161 for (; cnt
> 0; cnt
--)
162 crc
= (crc
>> 8) ^ crc_ccitt_table
[(crc
^ *buf
++) & 0xff];
163 return (crc
& 0xffff) == 0xf0b8;
166 /*---------------------------------------------------------------------------*/
169 static int calc_crc_ccitt(const unsigned char *buf
, int cnt
)
171 unsigned int crc
= 0xffff;
173 for (; cnt
> 0; cnt
--)
174 crc
= (crc
>> 8) ^ crc_ccitt_table
[(crc
^ *buf
++) & 0xff];
176 return (crc
& 0xffff);
180 /* ---------------------------------------------------------------------- */
182 #define tenms_to_2flags(s,tenms) ((tenms * s->par.bitrate) / 100 / 16)
184 /* ---------------------------------------------------------------------- */
189 static int hdlc_rx_add_bytes(struct hdlcdrv_state
*s
, unsigned int bits
,
194 while (s
->hdlcrx
.rx_state
&& num
>= 8) {
195 if (s
->hdlcrx
.len
>= sizeof(s
->hdlcrx
.buffer
)) {
196 s
->hdlcrx
.rx_state
= 0;
199 *s
->hdlcrx
.bp
++ = bits
>> (32-num
);
207 static void hdlc_rx_flag(struct net_device
*dev
, struct hdlcdrv_state
*s
)
213 if (s
->hdlcrx
.len
< 4)
215 if (!check_crc_ccitt(s
->hdlcrx
.buffer
, s
->hdlcrx
.len
))
217 pkt_len
= s
->hdlcrx
.len
- 2 + 1; /* KISS kludge */
218 if (!(skb
= dev_alloc_skb(pkt_len
))) {
219 printk("%s: memory squeeze, dropping packet\n",
221 s
->stats
.rx_dropped
++;
225 cp
= skb_put(skb
, pkt_len
);
226 *cp
++ = 0; /* KISS kludge */
227 memcpy(cp
, s
->hdlcrx
.buffer
, pkt_len
- 1);
228 skb
->protocol
= htons(ETH_P_AX25
);
229 skb
->mac
.raw
= skb
->data
;
231 s
->stats
.rx_packets
++;
234 void hdlcdrv_receiver(struct net_device
*dev
, struct hdlcdrv_state
*s
)
237 unsigned int mask1
, mask2
, mask3
, mask4
, mask5
, mask6
, word
;
239 if (!s
|| s
->magic
!= HDLCDRV_MAGIC
)
241 if (test_and_set_bit(0, &s
->hdlcrx
.in_hdlc_rx
))
244 while (!hdlcdrv_hbuf_empty(&s
->hdlcrx
.hbuf
)) {
245 word
= hdlcdrv_hbuf_get(&s
->hdlcrx
.hbuf
);
248 hdlcdrv_add_bitbuffer_word(&s
->bitbuf_hdlc
, word
);
249 #endif /* HDLCDRV_DEBUG */
250 s
->hdlcrx
.bitstream
>>= 16;
251 s
->hdlcrx
.bitstream
|= word
<< 16;
252 s
->hdlcrx
.bitbuf
>>= 16;
253 s
->hdlcrx
.bitbuf
|= word
<< 16;
254 s
->hdlcrx
.numbits
+= 16;
255 for(i
= 15, mask1
= 0x1fc00, mask2
= 0x1fe00, mask3
= 0x0fc00,
256 mask4
= 0x1f800, mask5
= 0xf800, mask6
= 0xffff;
258 i
--, mask1
<<= 1, mask2
<<= 1, mask3
<<= 1, mask4
<<= 1,
259 mask5
<<= 1, mask6
= (mask6
<< 1) | 1) {
260 if ((s
->hdlcrx
.bitstream
& mask1
) == mask1
)
261 s
->hdlcrx
.rx_state
= 0; /* abort received */
262 else if ((s
->hdlcrx
.bitstream
& mask2
) == mask3
) {
264 if (s
->hdlcrx
.rx_state
) {
265 hdlc_rx_add_bytes(s
, s
->hdlcrx
.bitbuf
269 hdlc_rx_flag(dev
, s
);
272 s
->hdlcrx
.bp
= s
->hdlcrx
.buffer
;
273 s
->hdlcrx
.rx_state
= 1;
274 s
->hdlcrx
.numbits
= i
;
275 } else if ((s
->hdlcrx
.bitstream
& mask4
) == mask5
) {
278 s
->hdlcrx
.bitbuf
= (s
->hdlcrx
.bitbuf
& (~mask6
)) |
279 ((s
->hdlcrx
.bitbuf
& mask6
) << 1);
282 s
->hdlcrx
.numbits
-= hdlc_rx_add_bytes(s
, s
->hdlcrx
.bitbuf
,
285 clear_bit(0, &s
->hdlcrx
.in_hdlc_rx
);
288 /* ---------------------------------------------------------------------- */
290 static void inline do_kiss_params(struct hdlcdrv_state
*s
,
291 unsigned char *data
, unsigned long len
)
295 #define PKP(a,b) printk(KERN_INFO "%s: channel params: " a "\n", s->ifname, b)
296 #else /* KISS_VERBOSE */
298 #endif /* KISS_VERBOSE */
304 s
->ch_params
.tx_delay
= data
[1];
305 PKP("TX delay = %ums", 10 * s
->ch_params
.tx_delay
);
308 s
->ch_params
.ppersist
= data
[1];
309 PKP("p persistence = %u", s
->ch_params
.ppersist
);
312 s
->ch_params
.slottime
= data
[1];
313 PKP("slot time = %ums", s
->ch_params
.slottime
);
316 s
->ch_params
.tx_tail
= data
[1];
317 PKP("TX tail = %ums", s
->ch_params
.tx_tail
);
320 s
->ch_params
.fulldup
= !!data
[1];
321 PKP("%s duplex", s
->ch_params
.fulldup
? "full" : "half");
329 /* ---------------------------------------------------------------------- */
331 void hdlcdrv_transmitter(struct net_device
*dev
, struct hdlcdrv_state
*s
)
333 unsigned int mask1
, mask2
, mask3
;
338 if (!s
|| s
->magic
!= HDLCDRV_MAGIC
)
340 if (test_and_set_bit(0, &s
->hdlctx
.in_hdlc_tx
))
343 if (s
->hdlctx
.numbits
>= 16) {
344 if (hdlcdrv_hbuf_full(&s
->hdlctx
.hbuf
)) {
345 clear_bit(0, &s
->hdlctx
.in_hdlc_tx
);
348 hdlcdrv_hbuf_put(&s
->hdlctx
.hbuf
, s
->hdlctx
.bitbuf
);
349 s
->hdlctx
.bitbuf
>>= 16;
350 s
->hdlctx
.numbits
-= 16;
352 switch (s
->hdlctx
.tx_state
) {
354 clear_bit(0, &s
->hdlctx
.in_hdlc_tx
);
358 if (s
->hdlctx
.numflags
) {
359 s
->hdlctx
.numflags
--;
361 0x7e7e << s
->hdlctx
.numbits
;
362 s
->hdlctx
.numbits
+= 16;
365 if (s
->hdlctx
.tx_state
== 1) {
366 clear_bit(0, &s
->hdlctx
.in_hdlc_tx
);
369 if (!(skb
= skb_dequeue(&s
->send_queue
))) {
370 int flgs
= tenms_to_2flags
371 (s
, s
->ch_params
.tx_tail
);
374 s
->hdlctx
.tx_state
= 1;
375 s
->hdlctx
.numflags
= flgs
;
378 if (skb
->data
[0] != 0) {
379 do_kiss_params(s
, skb
->data
, skb
->len
);
383 pkt_len
= skb
->len
-1; /* strip KISS byte */
384 if (pkt_len
>= HDLCDRV_MAXFLEN
|| pkt_len
< 2) {
385 s
->hdlctx
.tx_state
= 0;
386 s
->hdlctx
.numflags
= 1;
390 memcpy(s
->hdlctx
.buffer
, skb
->data
+1, pkt_len
);
392 s
->hdlctx
.bp
= s
->hdlctx
.buffer
;
393 append_crc_ccitt(s
->hdlctx
.buffer
, pkt_len
);
394 s
->hdlctx
.len
= pkt_len
+2; /* the appended CRC */
395 s
->hdlctx
.tx_state
= 2;
396 s
->hdlctx
.bitstream
= 0;
397 s
->stats
.tx_packets
++;
400 if (!s
->hdlctx
.len
) {
401 s
->hdlctx
.tx_state
= 0;
402 s
->hdlctx
.numflags
= 1;
406 s
->hdlctx
.bitbuf
|= *s
->hdlctx
.bp
<<
408 s
->hdlctx
.bitstream
>>= 8;
409 s
->hdlctx
.bitstream
|= (*s
->hdlctx
.bp
++) << 16;
412 mask3
= 0xffffffff >> (31-s
->hdlctx
.numbits
);
413 s
->hdlctx
.numbits
+= 8;
414 for(i
= 0; i
< 8; i
++, mask1
<<= 1, mask2
<<= 1,
415 mask3
= (mask3
<< 1) | 1) {
416 if ((s
->hdlctx
.bitstream
& mask1
) != mask1
)
418 s
->hdlctx
.bitstream
&= ~mask2
;
420 (s
->hdlctx
.bitbuf
& mask3
) |
424 mask3
= (mask3
<< 1) | 1;
431 /* ---------------------------------------------------------------------- */
433 static void start_tx(struct net_device
*dev
, struct hdlcdrv_state
*s
)
435 s
->hdlctx
.tx_state
= 0;
436 s
->hdlctx
.numflags
= tenms_to_2flags(s
, s
->ch_params
.tx_delay
);
437 s
->hdlctx
.bitbuf
= s
->hdlctx
.bitstream
= s
->hdlctx
.numbits
= 0;
438 hdlcdrv_transmitter(dev
, s
);
443 /* ---------------------------------------------------------------------- */
445 static unsigned short random_seed
;
447 static inline unsigned short random_num(void)
449 random_seed
= 28629 * random_seed
+ 157;
453 /* ---------------------------------------------------------------------- */
455 void hdlcdrv_arbitrate(struct net_device
*dev
, struct hdlcdrv_state
*s
)
457 if (!s
|| s
->magic
!= HDLCDRV_MAGIC
|| s
->hdlctx
.ptt
||
458 skb_queue_empty(&s
->send_queue
))
460 if (s
->ch_params
.fulldup
) {
465 s
->hdlctx
.slotcnt
= s
->ch_params
.slottime
;
468 if ((--s
->hdlctx
.slotcnt
) > 0)
470 s
->hdlctx
.slotcnt
= s
->ch_params
.slottime
;
471 if ((random_num() % 256) > s
->ch_params
.ppersist
)
476 /* --------------------------------------------------------------------- */
478 * ===================== network driver interface =========================
481 static inline int hdlcdrv_paranoia_check(struct net_device
*dev
,
484 if (!dev
|| !dev
->priv
||
485 ((struct hdlcdrv_state
*)dev
->priv
)->magic
!= HDLCDRV_MAGIC
) {
486 printk(KERN_ERR
"hdlcdrv: bad magic number for hdlcdrv_state "
487 "struct in routine %s\n", routine
);
493 /* --------------------------------------------------------------------- */
495 static int hdlcdrv_send_packet(struct sk_buff
*skb
, struct net_device
*dev
)
497 struct hdlcdrv_state
*sm
;
499 if (hdlcdrv_paranoia_check(dev
, "hdlcdrv_send_packet"))
501 sm
= (struct hdlcdrv_state
*)dev
->priv
;
502 skb_queue_tail(&sm
->send_queue
, skb
);
503 dev
->trans_start
= jiffies
;
507 /* --------------------------------------------------------------------- */
509 static int hdlcdrv_set_mac_address(struct net_device
*dev
, void *addr
)
511 struct sockaddr
*sa
= (struct sockaddr
*)addr
;
513 /* addr is an AX.25 shifted ASCII mac address */
514 memcpy(dev
->dev_addr
, sa
->sa_data
, dev
->addr_len
);
518 /* --------------------------------------------------------------------- */
520 static struct net_device_stats
*hdlcdrv_get_stats(struct net_device
*dev
)
522 struct hdlcdrv_state
*sm
;
524 if (hdlcdrv_paranoia_check(dev
, "hdlcdrv_get_stats"))
526 sm
= (struct hdlcdrv_state
*)dev
->priv
;
528 * Get the current statistics. This may be called with the
529 * card open or closed.
534 /* --------------------------------------------------------------------- */
536 * Open/initialize the board. This is called (in the current kernel)
537 * sometime after booting when the 'ifconfig' program is run.
539 * This routine should set everything up anew at each open, even
540 * registers that "should" only need to be set once at boot, so that
541 * there is non-reboot way to recover if something goes wrong.
544 static int hdlcdrv_open(struct net_device
*dev
)
546 struct hdlcdrv_state
*s
;
549 if (hdlcdrv_paranoia_check(dev
, "hdlcdrv_open"))
551 s
= (struct hdlcdrv_state
*)dev
->priv
;
555 if (!s
->ops
|| !s
->ops
->open
)
560 * initialise some variables
562 s
->hdlcrx
.hbuf
.rd
= s
->hdlcrx
.hbuf
.wr
= 0;
563 s
->hdlcrx
.in_hdlc_rx
= 0;
564 s
->hdlcrx
.rx_state
= 0;
566 s
->hdlctx
.hbuf
.rd
= s
->hdlctx
.hbuf
.wr
= 0;
567 s
->hdlctx
.in_hdlc_tx
= 0;
568 s
->hdlctx
.tx_state
= 1;
569 s
->hdlctx
.numflags
= 0;
570 s
->hdlctx
.bitstream
= s
->hdlctx
.bitbuf
= s
->hdlctx
.numbits
= 0;
572 s
->hdlctx
.slotcnt
= s
->ch_params
.slottime
;
573 s
->hdlctx
.calibrate
= 0;
575 i
= s
->ops
->open(dev
);
587 /* --------------------------------------------------------------------- */
589 * The inverse routine to hdlcdrv_open().
592 static int hdlcdrv_close(struct net_device
*dev
)
594 struct hdlcdrv_state
*s
;
598 if (hdlcdrv_paranoia_check(dev
, "hdlcdrv_close"))
600 s
= (struct hdlcdrv_state
*)dev
->priv
;
607 if (s
->ops
&& s
->ops
->close
)
608 i
= s
->ops
->close(dev
);
609 /* Free any buffers left in the hardware transmit queue */
610 while ((skb
= skb_dequeue(&s
->send_queue
)))
615 /* --------------------------------------------------------------------- */
617 static int hdlcdrv_ioctl(struct net_device
*dev
, struct ifreq
*ifr
, int cmd
)
619 struct hdlcdrv_state
*s
;
620 struct hdlcdrv_ioctl bi
;
622 if (hdlcdrv_paranoia_check(dev
, "hdlcdrv_ioctl"))
624 s
= (struct hdlcdrv_state
*)dev
->priv
;
626 if (cmd
!= SIOCDEVPRIVATE
) {
627 if (s
->ops
&& s
->ops
->ioctl
)
628 return s
->ops
->ioctl(dev
, ifr
, &bi
, cmd
);
631 if (copy_from_user(&bi
, ifr
->ifr_data
, sizeof(bi
)))
636 if (s
->ops
&& s
->ops
->ioctl
)
637 return s
->ops
->ioctl(dev
, ifr
, &bi
, cmd
);
640 case HDLCDRVCTL_GETCHANNELPAR
:
641 bi
.data
.cp
.tx_delay
= s
->ch_params
.tx_delay
;
642 bi
.data
.cp
.tx_tail
= s
->ch_params
.tx_tail
;
643 bi
.data
.cp
.slottime
= s
->ch_params
.slottime
;
644 bi
.data
.cp
.ppersist
= s
->ch_params
.ppersist
;
645 bi
.data
.cp
.fulldup
= s
->ch_params
.fulldup
;
648 case HDLCDRVCTL_SETCHANNELPAR
:
651 s
->ch_params
.tx_delay
= bi
.data
.cp
.tx_delay
;
652 s
->ch_params
.tx_tail
= bi
.data
.cp
.tx_tail
;
653 s
->ch_params
.slottime
= bi
.data
.cp
.slottime
;
654 s
->ch_params
.ppersist
= bi
.data
.cp
.ppersist
;
655 s
->ch_params
.fulldup
= bi
.data
.cp
.fulldup
;
656 s
->hdlctx
.slotcnt
= 1;
659 case HDLCDRVCTL_GETMODEMPAR
:
660 bi
.data
.mp
.iobase
= dev
->base_addr
;
661 bi
.data
.mp
.irq
= dev
->irq
;
662 bi
.data
.mp
.dma
= dev
->dma
;
663 bi
.data
.mp
.dma2
= s
->ptt_out
.dma2
;
664 bi
.data
.mp
.seriobase
= s
->ptt_out
.seriobase
;
665 bi
.data
.mp
.pariobase
= s
->ptt_out
.pariobase
;
666 bi
.data
.mp
.midiiobase
= s
->ptt_out
.midiiobase
;
669 case HDLCDRVCTL_SETMODEMPAR
:
670 if ((!suser()) || dev
->start
)
672 dev
->base_addr
= bi
.data
.mp
.iobase
;
673 dev
->irq
= bi
.data
.mp
.irq
;
674 dev
->dma
= bi
.data
.mp
.dma
;
675 s
->ptt_out
.dma2
= bi
.data
.mp
.dma2
;
676 s
->ptt_out
.seriobase
= bi
.data
.mp
.seriobase
;
677 s
->ptt_out
.pariobase
= bi
.data
.mp
.pariobase
;
678 s
->ptt_out
.midiiobase
= bi
.data
.mp
.midiiobase
;
681 case HDLCDRVCTL_GETSTAT
:
682 bi
.data
.cs
.ptt
= hdlcdrv_ptt(s
);
683 bi
.data
.cs
.dcd
= s
->hdlcrx
.dcd
;
684 bi
.data
.cs
.ptt_keyed
= s
->ptt_keyed
;
685 bi
.data
.cs
.tx_packets
= s
->stats
.tx_packets
;
686 bi
.data
.cs
.tx_errors
= s
->stats
.tx_errors
;
687 bi
.data
.cs
.rx_packets
= s
->stats
.rx_packets
;
688 bi
.data
.cs
.rx_errors
= s
->stats
.rx_errors
;
691 case HDLCDRVCTL_OLDGETSTAT
:
692 bi
.data
.ocs
.ptt
= hdlcdrv_ptt(s
);
693 bi
.data
.ocs
.dcd
= s
->hdlcrx
.dcd
;
694 bi
.data
.ocs
.ptt_keyed
= s
->ptt_keyed
;
697 case HDLCDRVCTL_CALIBRATE
:
698 s
->hdlctx
.calibrate
= bi
.data
.calibrate
* s
->par
.bitrate
/ 16;
701 case HDLCDRVCTL_GETSAMPLES
:
702 #ifndef HDLCDRV_DEBUG
704 #else /* HDLCDRV_DEBUG */
705 if (s
->bitbuf_channel
.rd
== s
->bitbuf_channel
.wr
)
708 s
->bitbuf_channel
.buffer
[s
->bitbuf_channel
.rd
];
709 s
->bitbuf_channel
.rd
= (s
->bitbuf_channel
.rd
+1) %
710 sizeof(s
->bitbuf_channel
.buffer
);
712 #endif /* HDLCDRV_DEBUG */
714 case HDLCDRVCTL_GETBITS
:
715 #ifndef HDLCDRV_DEBUG
717 #else /* HDLCDRV_DEBUG */
718 if (s
->bitbuf_hdlc
.rd
== s
->bitbuf_hdlc
.wr
)
721 s
->bitbuf_hdlc
.buffer
[s
->bitbuf_hdlc
.rd
];
722 s
->bitbuf_hdlc
.rd
= (s
->bitbuf_hdlc
.rd
+1) %
723 sizeof(s
->bitbuf_hdlc
.buffer
);
725 #endif /* HDLCDRV_DEBUG */
727 case HDLCDRVCTL_DRIVERNAME
:
728 if (s
->ops
&& s
->ops
->drvname
) {
729 strncpy(bi
.data
.drivername
, s
->ops
->drvname
,
730 sizeof(bi
.data
.drivername
));
733 bi
.data
.drivername
[0] = '\0';
737 if (copy_to_user(ifr
->ifr_data
, &bi
, sizeof(bi
)))
743 /* --------------------------------------------------------------------- */
746 * Check for a network adaptor of this type, and return '0' if one exists.
747 * If dev->base_addr == 0, probe all likely locations.
748 * If dev->base_addr == 1, always return failure.
749 * If dev->base_addr == 2, allocate space for the device and return success
750 * (detachable devices only).
752 static int hdlcdrv_probe(struct net_device
*dev
)
754 const struct hdlcdrv_channel_params dflt_ch_params
= {
757 struct hdlcdrv_state
*s
;
762 * not a real probe! only initialize data structures
764 s
= (struct hdlcdrv_state
*)dev
->priv
;
766 * initialize the hdlcdrv_state struct
768 s
->ch_params
= dflt_ch_params
;
771 spin_lock_init(&s
->hdlcrx
.hbuf
.lock
);
772 s
->hdlcrx
.hbuf
.rd
= s
->hdlcrx
.hbuf
.wr
= 0;
773 s
->hdlcrx
.in_hdlc_rx
= 0;
774 s
->hdlcrx
.rx_state
= 0;
776 spin_lock_init(&s
->hdlctx
.hbuf
.lock
);
777 s
->hdlctx
.hbuf
.rd
= s
->hdlctx
.hbuf
.wr
= 0;
778 s
->hdlctx
.in_hdlc_tx
= 0;
779 s
->hdlctx
.tx_state
= 1;
780 s
->hdlctx
.numflags
= 0;
781 s
->hdlctx
.bitstream
= s
->hdlctx
.bitbuf
= s
->hdlctx
.numbits
= 0;
783 s
->hdlctx
.slotcnt
= s
->ch_params
.slottime
;
784 s
->hdlctx
.calibrate
= 0;
787 s
->bitbuf_channel
.rd
= s
->bitbuf_channel
.wr
= 0;
788 s
->bitbuf_channel
.shreg
= 0x80;
790 s
->bitbuf_hdlc
.rd
= s
->bitbuf_hdlc
.wr
= 0;
791 s
->bitbuf_hdlc
.shreg
= 0x80;
792 #endif /* HDLCDRV_DEBUG */
795 * initialize the device struct
797 dev
->open
= hdlcdrv_open
;
798 dev
->stop
= hdlcdrv_close
;
799 dev
->do_ioctl
= hdlcdrv_ioctl
;
800 dev
->hard_start_xmit
= hdlcdrv_send_packet
;
801 dev
->get_stats
= hdlcdrv_get_stats
;
803 /* Fill in the fields of the device structure */
805 dev_init_buffers(dev
);
807 skb_queue_head_init(&s
->send_queue
);
809 #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
810 dev
->hard_header
= ax25_encapsulate
;
811 dev
->rebuild_header
= ax25_rebuild_header
;
812 #else /* CONFIG_AX25 || CONFIG_AX25_MODULE */
813 dev
->hard_header
= NULL
;
814 dev
->rebuild_header
= NULL
;
815 #endif /* CONFIG_AX25 || CONFIG_AX25_MODULE */
816 dev
->set_mac_address
= hdlcdrv_set_mac_address
;
818 dev
->type
= ARPHRD_AX25
; /* AF_AX25 device */
819 dev
->hard_header_len
= AX25_MAX_HEADER_LEN
+ AX25_BPQ_HEADER_LEN
;
820 dev
->mtu
= AX25_DEF_PACLEN
; /* eth_mtu is the default */
821 dev
->addr_len
= AX25_ADDR_LEN
; /* sizeof an ax.25 address */
822 memcpy(dev
->broadcast
, ax25_bcast
, AX25_ADDR_LEN
);
823 memcpy(dev
->dev_addr
, ax25_nocall
, AX25_ADDR_LEN
);
825 /* New style flags */
831 /* --------------------------------------------------------------------- */
833 int hdlcdrv_register_hdlcdrv(struct net_device
*dev
, const struct hdlcdrv_ops
*ops
,
834 unsigned int privsize
, char *ifname
,
835 unsigned int baseaddr
, unsigned int irq
,
838 struct hdlcdrv_state
*s
;
842 if (privsize
< sizeof(struct hdlcdrv_state
))
843 privsize
= sizeof(struct hdlcdrv_state
);
844 memset(dev
, 0, sizeof(struct net_device
));
845 if (!(s
= dev
->priv
= kmalloc(privsize
, GFP_KERNEL
)))
848 * initialize part of the hdlcdrv_state struct
850 memset(s
, 0, privsize
);
851 s
->magic
= HDLCDRV_MAGIC
;
852 strncpy(s
->ifname
, ifname
, sizeof(s
->ifname
));
855 * initialize part of the device struct
857 dev
->name
= s
->ifname
;
859 dev
->init
= hdlcdrv_probe
;
862 dev
->base_addr
= baseaddr
;
865 if (register_netdev(dev
)) {
866 printk(KERN_WARNING
"hdlcdrv: cannot register net "
867 "device %s\n", s
->ifname
);
875 /* --------------------------------------------------------------------- */
877 int hdlcdrv_unregister_hdlcdrv(struct net_device
*dev
)
879 struct hdlcdrv_state
*s
;
883 if (!(s
= (struct hdlcdrv_state
*)dev
->priv
))
885 if (s
->magic
!= HDLCDRV_MAGIC
)
887 if (dev
->start
&& s
->ops
->close
)
889 unregister_netdev(dev
);
895 /* --------------------------------------------------------------------- */
897 EXPORT_SYMBOL(hdlcdrv_receiver
);
898 EXPORT_SYMBOL(hdlcdrv_transmitter
);
899 EXPORT_SYMBOL(hdlcdrv_arbitrate
);
900 EXPORT_SYMBOL(hdlcdrv_register_hdlcdrv
);
901 EXPORT_SYMBOL(hdlcdrv_unregister_hdlcdrv
);
903 /* --------------------------------------------------------------------- */
907 MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
908 MODULE_DESCRIPTION("Packet Radio network interface HDLC encoder/decoder");
910 /* --------------------------------------------------------------------- */
912 int __init
init_module(void)
914 printk(KERN_INFO
"hdlcdrv: (C) 1996 Thomas Sailer HB9JNX/AE4WA\n");
915 printk(KERN_INFO
"hdlcdrv: version 0.7 compiled " __TIME__
" " __DATE__
"\n");
919 /* --------------------------------------------------------------------- */
921 void cleanup_module(void)
923 printk(KERN_INFO
"hdlcdrv: cleanup\n");
927 /* --------------------------------------------------------------------- */