1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /*****************************************************************************/ |
3 | |
4 | /* |
5 | * baycom_epp.c -- baycom epp radio modem driver. |
6 | * |
7 | * Copyright (C) 1998-2000 |
8 | * Thomas Sailer (sailer@ife.ee.ethz.ch) |
9 | * |
10 | * Please note that the GPL allows you to use the driver, NOT the radio. |
11 | * In order to use the radio, you need a license from the communications |
12 | * authority of your country. |
13 | * |
14 | * History: |
15 | * 0.1 xx.xx.1998 Initial version by Matthias Welwarsky (dg2fef) |
16 | * 0.2 21.04.1998 Massive rework by Thomas Sailer |
17 | * Integrated FPGA EPP modem configuration routines |
18 | * 0.3 11.05.1998 Took FPGA config out and moved it into a separate program |
19 | * 0.4 26.07.1999 Adapted to new lowlevel parport driver interface |
20 | * 0.5 03.08.1999 adapt to Linus' new __setup/__initcall |
21 | * removed some pre-2.2 kernel compatibility cruft |
22 | * 0.6 10.08.1999 Check if parport can do SPP and is safe to access during interrupt contexts |
23 | * 0.7 12.02.2000 adapted to softnet driver interface |
24 | */ |
25 | |
26 | /*****************************************************************************/ |
27 | |
28 | #include <linux/crc-ccitt.h> |
29 | #include <linux/module.h> |
30 | #include <linux/kernel.h> |
31 | #include <linux/init.h> |
32 | #include <linux/sched.h> |
33 | #include <linux/string.h> |
34 | #include <linux/workqueue.h> |
35 | #include <linux/fs.h> |
36 | #include <linux/parport.h> |
37 | #include <linux/if_arp.h> |
38 | #include <linux/hdlcdrv.h> |
39 | #include <linux/baycom.h> |
40 | #include <linux/jiffies.h> |
41 | #include <linux/random.h> |
42 | #include <net/ax25.h> |
43 | #include <linux/uaccess.h> |
44 | |
45 | /* --------------------------------------------------------------------- */ |
46 | |
47 | #define BAYCOM_DEBUG |
48 | #define BAYCOM_MAGIC 19730510 |
49 | |
50 | /* --------------------------------------------------------------------- */ |
51 | |
52 | static const char paranoia_str[] = KERN_ERR |
53 | "baycom_epp: bad magic number for hdlcdrv_state struct in routine %s\n" ; |
54 | |
55 | static const char bc_drvname[] = "baycom_epp" ; |
56 | static const char bc_drvinfo[] = KERN_INFO "baycom_epp: (C) 1998-2000 Thomas Sailer, HB9JNX/AE4WA\n" |
57 | "baycom_epp: version 0.7\n" ; |
58 | |
59 | /* --------------------------------------------------------------------- */ |
60 | |
61 | #define NR_PORTS 4 |
62 | |
63 | static struct net_device *baycom_device[NR_PORTS]; |
64 | |
65 | /* --------------------------------------------------------------------- */ |
66 | |
67 | /* EPP status register */ |
68 | #define EPP_DCDBIT 0x80 |
69 | #define EPP_PTTBIT 0x08 |
70 | #define EPP_NREF 0x01 |
71 | #define EPP_NRAEF 0x02 |
72 | #define EPP_NRHF 0x04 |
73 | #define EPP_NTHF 0x20 |
74 | #define EPP_NTAEF 0x10 |
75 | #define EPP_NTEF EPP_PTTBIT |
76 | |
77 | /* EPP control register */ |
78 | #define EPP_TX_FIFO_ENABLE 0x10 |
79 | #define EPP_RX_FIFO_ENABLE 0x08 |
80 | #define EPP_MODEM_ENABLE 0x20 |
81 | #define EPP_LEDS 0xC0 |
82 | #define EPP_IRQ_ENABLE 0x10 |
83 | |
84 | /* LPT registers */ |
85 | #define LPTREG_ECONTROL 0x402 |
86 | #define LPTREG_CONFIGB 0x401 |
87 | #define LPTREG_CONFIGA 0x400 |
88 | #define LPTREG_EPPDATA 0x004 |
89 | #define LPTREG_EPPADDR 0x003 |
90 | #define LPTREG_CONTROL 0x002 |
91 | #define LPTREG_STATUS 0x001 |
92 | #define LPTREG_DATA 0x000 |
93 | |
94 | /* LPT control register */ |
95 | #define LPTCTRL_PROGRAM 0x04 /* 0 to reprogram */ |
96 | #define LPTCTRL_WRITE 0x01 |
97 | #define LPTCTRL_ADDRSTB 0x08 |
98 | #define LPTCTRL_DATASTB 0x02 |
99 | #define LPTCTRL_INTEN 0x10 |
100 | |
101 | /* LPT status register */ |
102 | #define LPTSTAT_SHIFT_NINTR 6 |
103 | #define LPTSTAT_WAIT 0x80 |
104 | #define LPTSTAT_NINTR (1<<LPTSTAT_SHIFT_NINTR) |
105 | #define LPTSTAT_PE 0x20 |
106 | #define LPTSTAT_DONE 0x10 |
107 | #define LPTSTAT_NERROR 0x08 |
108 | #define LPTSTAT_EPPTIMEOUT 0x01 |
109 | |
110 | /* LPT data register */ |
111 | #define LPTDATA_SHIFT_TDI 0 |
112 | #define LPTDATA_SHIFT_TMS 2 |
113 | #define LPTDATA_TDI (1<<LPTDATA_SHIFT_TDI) |
114 | #define LPTDATA_TCK 0x02 |
115 | #define LPTDATA_TMS (1<<LPTDATA_SHIFT_TMS) |
116 | #define LPTDATA_INITBIAS 0x80 |
117 | |
118 | |
119 | /* EPP modem config/status bits */ |
120 | #define EPP_DCDBIT 0x80 |
121 | #define EPP_PTTBIT 0x08 |
122 | #define EPP_RXEBIT 0x01 |
123 | #define EPP_RXAEBIT 0x02 |
124 | #define EPP_RXHFULL 0x04 |
125 | |
126 | #define EPP_NTHF 0x20 |
127 | #define EPP_NTAEF 0x10 |
128 | #define EPP_NTEF EPP_PTTBIT |
129 | |
130 | #define EPP_TX_FIFO_ENABLE 0x10 |
131 | #define EPP_RX_FIFO_ENABLE 0x08 |
132 | #define EPP_MODEM_ENABLE 0x20 |
133 | #define EPP_LEDS 0xC0 |
134 | #define EPP_IRQ_ENABLE 0x10 |
135 | |
136 | /* Xilinx 4k JTAG instructions */ |
137 | #define XC4K_IRLENGTH 3 |
138 | #define XC4K_EXTEST 0 |
139 | #define XC4K_PRELOAD 1 |
140 | #define XC4K_CONFIGURE 5 |
141 | #define XC4K_BYPASS 7 |
142 | |
143 | #define EPP_CONVENTIONAL 0 |
144 | #define EPP_FPGA 1 |
145 | #define EPP_FPGAEXTSTATUS 2 |
146 | |
147 | #define TXBUFFER_SIZE ((HDLCDRV_MAXFLEN*6/5)+8) |
148 | |
149 | /* ---------------------------------------------------------------------- */ |
150 | /* |
151 | * Information that need to be kept for each board. |
152 | */ |
153 | |
154 | struct baycom_state { |
155 | int magic; |
156 | |
157 | struct pardevice *pdev; |
158 | struct net_device *dev; |
159 | unsigned int work_running; |
160 | struct delayed_work run_work; |
161 | unsigned int modem; |
162 | unsigned int bitrate; |
163 | unsigned char stat; |
164 | |
165 | struct { |
166 | unsigned int intclk; |
167 | unsigned int fclk; |
168 | unsigned int bps; |
169 | unsigned int extmodem; |
170 | unsigned int loopback; |
171 | } cfg; |
172 | |
173 | struct hdlcdrv_channel_params ch_params; |
174 | |
175 | struct { |
176 | unsigned int bitbuf, bitstream, numbits, state; |
177 | unsigned char *bufptr; |
178 | int bufcnt; |
179 | unsigned char buf[TXBUFFER_SIZE]; |
180 | } hdlcrx; |
181 | |
182 | struct { |
183 | int calibrate; |
184 | int slotcnt; |
185 | int flags; |
186 | enum { tx_idle = 0, tx_keyup, tx_data, tx_tail } state; |
187 | unsigned char *bufptr; |
188 | int bufcnt; |
189 | unsigned char buf[TXBUFFER_SIZE]; |
190 | } hdlctx; |
191 | |
192 | unsigned int ptt_keyed; |
193 | struct sk_buff *skb; /* next transmit packet */ |
194 | |
195 | #ifdef BAYCOM_DEBUG |
196 | struct debug_vals { |
197 | unsigned long last_jiffies; |
198 | unsigned cur_intcnt; |
199 | unsigned last_intcnt; |
200 | int cur_pllcorr; |
201 | int last_pllcorr; |
202 | unsigned int mod_cycles; |
203 | unsigned int demod_cycles; |
204 | } debug_vals; |
205 | #endif /* BAYCOM_DEBUG */ |
206 | }; |
207 | |
208 | /* --------------------------------------------------------------------- */ |
209 | |
210 | #define KISS_VERBOSE |
211 | |
212 | /* --------------------------------------------------------------------- */ |
213 | |
214 | #define PARAM_TXDELAY 1 |
215 | #define PARAM_PERSIST 2 |
216 | #define PARAM_SLOTTIME 3 |
217 | #define PARAM_TXTAIL 4 |
218 | #define PARAM_FULLDUP 5 |
219 | #define PARAM_HARDWARE 6 |
220 | #define PARAM_RETURN 255 |
221 | |
222 | /* --------------------------------------------------------------------- */ |
223 | /* |
224 | * the CRC routines are stolen from WAMPES |
225 | * by Dieter Deyke |
226 | */ |
227 | |
228 | |
229 | /*---------------------------------------------------------------------------*/ |
230 | |
231 | #if 0 |
232 | static inline void append_crc_ccitt(unsigned char *buffer, int len) |
233 | { |
234 | unsigned int crc = 0xffff; |
235 | |
236 | for (;len>0;len--) |
237 | crc = (crc >> 8) ^ crc_ccitt_table[(crc ^ *buffer++) & 0xff]; |
238 | crc ^= 0xffff; |
239 | *buffer++ = crc; |
240 | *buffer++ = crc >> 8; |
241 | } |
242 | #endif |
243 | |
244 | /*---------------------------------------------------------------------------*/ |
245 | |
246 | static inline int check_crc_ccitt(const unsigned char *buf, int cnt) |
247 | { |
248 | return (crc_ccitt(crc: 0xffff, buffer: buf, len: cnt) & 0xffff) == 0xf0b8; |
249 | } |
250 | |
251 | /*---------------------------------------------------------------------------*/ |
252 | |
253 | static inline int calc_crc_ccitt(const unsigned char *buf, int cnt) |
254 | { |
255 | return (crc_ccitt(crc: 0xffff, buffer: buf, len: cnt) ^ 0xffff) & 0xffff; |
256 | } |
257 | |
258 | /* ---------------------------------------------------------------------- */ |
259 | |
260 | #define tenms_to_flags(bc,tenms) ((tenms * bc->bitrate) / 800) |
261 | |
262 | /* --------------------------------------------------------------------- */ |
263 | |
264 | static inline void baycom_int_freq(struct baycom_state *bc) |
265 | { |
266 | #ifdef BAYCOM_DEBUG |
267 | unsigned long cur_jiffies = jiffies; |
268 | /* |
269 | * measure the interrupt frequency |
270 | */ |
271 | bc->debug_vals.cur_intcnt++; |
272 | if (time_after_eq(cur_jiffies, bc->debug_vals.last_jiffies + HZ)) { |
273 | bc->debug_vals.last_jiffies = cur_jiffies; |
274 | bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt; |
275 | bc->debug_vals.cur_intcnt = 0; |
276 | bc->debug_vals.last_pllcorr = bc->debug_vals.cur_pllcorr; |
277 | bc->debug_vals.cur_pllcorr = 0; |
278 | } |
279 | #endif /* BAYCOM_DEBUG */ |
280 | } |
281 | |
282 | /* ---------------------------------------------------------------------- */ |
283 | /* |
284 | * eppconfig_path should be setable via /proc/sys. |
285 | */ |
286 | |
287 | static char const eppconfig_path[] = "/usr/sbin/eppfpga" ; |
288 | |
289 | static char *envp[] = { "HOME=/" , "TERM=linux" , "PATH=/usr/bin:/bin" , NULL }; |
290 | |
291 | /* eppconfig: called during ifconfig up to configure the modem */ |
292 | static int eppconfig(struct baycom_state *bc) |
293 | { |
294 | char modearg[256]; |
295 | char portarg[16]; |
296 | char *argv[] = { |
297 | (char *)eppconfig_path, |
298 | "-s" , |
299 | "-p" , portarg, |
300 | "-m" , modearg, |
301 | NULL }; |
302 | |
303 | /* set up arguments */ |
304 | sprintf(buf: modearg, fmt: "%sclk,%smodem,fclk=%d,bps=%d,divider=%d%s,extstat" , |
305 | bc->cfg.intclk ? "int" : "ext" , |
306 | bc->cfg.extmodem ? "ext" : "int" , bc->cfg.fclk, bc->cfg.bps, |
307 | (bc->cfg.fclk + 8 * bc->cfg.bps) / (16 * bc->cfg.bps), |
308 | bc->cfg.loopback ? ",loopback" : "" ); |
309 | sprintf(buf: portarg, fmt: "%ld" , bc->pdev->port->base); |
310 | printk(KERN_DEBUG "%s: %s -s -p %s -m %s\n" , bc_drvname, eppconfig_path, portarg, modearg); |
311 | |
312 | return call_usermodehelper(path: eppconfig_path, argv, envp, UMH_WAIT_PROC); |
313 | } |
314 | |
315 | /* ---------------------------------------------------------------------- */ |
316 | |
317 | static inline void do_kiss_params(struct baycom_state *bc, |
318 | unsigned char *data, unsigned long len) |
319 | { |
320 | |
321 | #ifdef KISS_VERBOSE |
322 | #define PKP(a,b) printk(KERN_INFO "baycomm_epp: channel params: " a "\n", b) |
323 | #else /* KISS_VERBOSE */ |
324 | #define PKP(a,b) |
325 | #endif /* KISS_VERBOSE */ |
326 | |
327 | if (len < 2) |
328 | return; |
329 | switch(data[0]) { |
330 | case PARAM_TXDELAY: |
331 | bc->ch_params.tx_delay = data[1]; |
332 | PKP("TX delay = %ums" , 10 * bc->ch_params.tx_delay); |
333 | break; |
334 | case PARAM_PERSIST: |
335 | bc->ch_params.ppersist = data[1]; |
336 | PKP("p persistence = %u" , bc->ch_params.ppersist); |
337 | break; |
338 | case PARAM_SLOTTIME: |
339 | bc->ch_params.slottime = data[1]; |
340 | PKP("slot time = %ums" , bc->ch_params.slottime); |
341 | break; |
342 | case PARAM_TXTAIL: |
343 | bc->ch_params.tx_tail = data[1]; |
344 | PKP("TX tail = %ums" , bc->ch_params.tx_tail); |
345 | break; |
346 | case PARAM_FULLDUP: |
347 | bc->ch_params.fulldup = !!data[1]; |
348 | PKP("%s duplex" , bc->ch_params.fulldup ? "full" : "half" ); |
349 | break; |
350 | default: |
351 | break; |
352 | } |
353 | #undef PKP |
354 | } |
355 | |
356 | /* --------------------------------------------------------------------- */ |
357 | |
358 | static void encode_hdlc(struct baycom_state *bc) |
359 | { |
360 | struct sk_buff *skb; |
361 | unsigned char *wp, *bp; |
362 | int pkt_len; |
363 | unsigned bitstream, notbitstream, bitbuf, numbit, crc; |
364 | unsigned char crcarr[2]; |
365 | int j; |
366 | |
367 | if (bc->hdlctx.bufcnt > 0) |
368 | return; |
369 | skb = bc->skb; |
370 | if (!skb) |
371 | return; |
372 | bc->skb = NULL; |
373 | pkt_len = skb->len-1; /* strip KISS byte */ |
374 | wp = bc->hdlctx.buf; |
375 | bp = skb->data+1; |
376 | crc = calc_crc_ccitt(buf: bp, cnt: pkt_len); |
377 | crcarr[0] = crc; |
378 | crcarr[1] = crc >> 8; |
379 | *wp++ = 0x7e; |
380 | bitstream = bitbuf = numbit = 0; |
381 | while (pkt_len > -2) { |
382 | bitstream >>= 8; |
383 | bitstream |= ((unsigned int)*bp) << 8; |
384 | bitbuf |= ((unsigned int)*bp) << numbit; |
385 | notbitstream = ~bitstream; |
386 | bp++; |
387 | pkt_len--; |
388 | if (!pkt_len) |
389 | bp = crcarr; |
390 | for (j = 0; j < 8; j++) |
391 | if (unlikely(!(notbitstream & (0x1f0 << j)))) { |
392 | bitstream &= ~(0x100 << j); |
393 | bitbuf = (bitbuf & (((2 << j) << numbit) - 1)) | |
394 | ((bitbuf & ~(((2 << j) << numbit) - 1)) << 1); |
395 | numbit++; |
396 | notbitstream = ~bitstream; |
397 | } |
398 | numbit += 8; |
399 | while (numbit >= 8) { |
400 | *wp++ = bitbuf; |
401 | bitbuf >>= 8; |
402 | numbit -= 8; |
403 | } |
404 | } |
405 | bitbuf |= 0x7e7e << numbit; |
406 | numbit += 16; |
407 | while (numbit >= 8) { |
408 | *wp++ = bitbuf; |
409 | bitbuf >>= 8; |
410 | numbit -= 8; |
411 | } |
412 | bc->hdlctx.bufptr = bc->hdlctx.buf; |
413 | bc->hdlctx.bufcnt = wp - bc->hdlctx.buf; |
414 | dev_kfree_skb(skb); |
415 | bc->dev->stats.tx_packets++; |
416 | } |
417 | |
418 | /* ---------------------------------------------------------------------- */ |
419 | |
420 | static int transmit(struct baycom_state *bc, int cnt, unsigned char stat) |
421 | { |
422 | struct parport *pp = bc->pdev->port; |
423 | unsigned char tmp[128]; |
424 | int i, j; |
425 | |
426 | if (bc->hdlctx.state == tx_tail && !(stat & EPP_PTTBIT)) |
427 | bc->hdlctx.state = tx_idle; |
428 | if (bc->hdlctx.state == tx_idle && bc->hdlctx.calibrate <= 0) { |
429 | if (bc->hdlctx.bufcnt <= 0) |
430 | encode_hdlc(bc); |
431 | if (bc->hdlctx.bufcnt <= 0) |
432 | return 0; |
433 | if (!bc->ch_params.fulldup) { |
434 | if (!(stat & EPP_DCDBIT)) { |
435 | bc->hdlctx.slotcnt = bc->ch_params.slottime; |
436 | return 0; |
437 | } |
438 | if ((--bc->hdlctx.slotcnt) > 0) |
439 | return 0; |
440 | bc->hdlctx.slotcnt = bc->ch_params.slottime; |
441 | if (get_random_u8() > bc->ch_params.ppersist) |
442 | return 0; |
443 | } |
444 | } |
445 | if (bc->hdlctx.state == tx_idle && bc->hdlctx.bufcnt > 0) { |
446 | bc->hdlctx.state = tx_keyup; |
447 | bc->hdlctx.flags = tenms_to_flags(bc, bc->ch_params.tx_delay); |
448 | bc->ptt_keyed++; |
449 | } |
450 | while (cnt > 0) { |
451 | switch (bc->hdlctx.state) { |
452 | case tx_keyup: |
453 | i = min_t(int, cnt, bc->hdlctx.flags); |
454 | cnt -= i; |
455 | bc->hdlctx.flags -= i; |
456 | if (bc->hdlctx.flags <= 0) |
457 | bc->hdlctx.state = tx_data; |
458 | memset(tmp, 0x7e, sizeof(tmp)); |
459 | while (i > 0) { |
460 | j = (i > sizeof(tmp)) ? sizeof(tmp) : i; |
461 | if (j != pp->ops->epp_write_data(pp, tmp, j, 0)) |
462 | return -1; |
463 | i -= j; |
464 | } |
465 | break; |
466 | |
467 | case tx_data: |
468 | if (bc->hdlctx.bufcnt <= 0) { |
469 | encode_hdlc(bc); |
470 | if (bc->hdlctx.bufcnt <= 0) { |
471 | bc->hdlctx.state = tx_tail; |
472 | bc->hdlctx.flags = tenms_to_flags(bc, bc->ch_params.tx_tail); |
473 | break; |
474 | } |
475 | } |
476 | i = min_t(int, cnt, bc->hdlctx.bufcnt); |
477 | bc->hdlctx.bufcnt -= i; |
478 | cnt -= i; |
479 | if (i != pp->ops->epp_write_data(pp, bc->hdlctx.bufptr, i, 0)) |
480 | return -1; |
481 | bc->hdlctx.bufptr += i; |
482 | break; |
483 | |
484 | case tx_tail: |
485 | encode_hdlc(bc); |
486 | if (bc->hdlctx.bufcnt > 0) { |
487 | bc->hdlctx.state = tx_data; |
488 | break; |
489 | } |
490 | i = min_t(int, cnt, bc->hdlctx.flags); |
491 | if (i) { |
492 | cnt -= i; |
493 | bc->hdlctx.flags -= i; |
494 | memset(tmp, 0x7e, sizeof(tmp)); |
495 | while (i > 0) { |
496 | j = (i > sizeof(tmp)) ? sizeof(tmp) : i; |
497 | if (j != pp->ops->epp_write_data(pp, tmp, j, 0)) |
498 | return -1; |
499 | i -= j; |
500 | } |
501 | break; |
502 | } |
503 | fallthrough; |
504 | |
505 | default: |
506 | if (bc->hdlctx.calibrate <= 0) |
507 | return 0; |
508 | i = min_t(int, cnt, bc->hdlctx.calibrate); |
509 | cnt -= i; |
510 | bc->hdlctx.calibrate -= i; |
511 | memset(tmp, 0, sizeof(tmp)); |
512 | while (i > 0) { |
513 | j = (i > sizeof(tmp)) ? sizeof(tmp) : i; |
514 | if (j != pp->ops->epp_write_data(pp, tmp, j, 0)) |
515 | return -1; |
516 | i -= j; |
517 | } |
518 | break; |
519 | } |
520 | } |
521 | return 0; |
522 | } |
523 | |
524 | /* ---------------------------------------------------------------------- */ |
525 | |
526 | static void do_rxpacket(struct net_device *dev) |
527 | { |
528 | struct baycom_state *bc = netdev_priv(dev); |
529 | struct sk_buff *skb; |
530 | unsigned char *cp; |
531 | unsigned pktlen; |
532 | |
533 | if (bc->hdlcrx.bufcnt < 4) |
534 | return; |
535 | if (!check_crc_ccitt(buf: bc->hdlcrx.buf, cnt: bc->hdlcrx.bufcnt)) |
536 | return; |
537 | pktlen = bc->hdlcrx.bufcnt-2+1; /* KISS kludge */ |
538 | if (!(skb = dev_alloc_skb(length: pktlen))) { |
539 | printk("%s: memory squeeze, dropping packet\n" , dev->name); |
540 | dev->stats.rx_dropped++; |
541 | return; |
542 | } |
543 | cp = skb_put(skb, len: pktlen); |
544 | *cp++ = 0; /* KISS kludge */ |
545 | memcpy(cp, bc->hdlcrx.buf, pktlen - 1); |
546 | skb->protocol = ax25_type_trans(skb, dev); |
547 | netif_rx(skb); |
548 | dev->stats.rx_packets++; |
549 | } |
550 | |
551 | static int receive(struct net_device *dev, int cnt) |
552 | { |
553 | struct baycom_state *bc = netdev_priv(dev); |
554 | struct parport *pp = bc->pdev->port; |
555 | unsigned int bitbuf, notbitstream, bitstream, numbits, state; |
556 | unsigned char tmp[128]; |
557 | unsigned char *cp; |
558 | int cnt2, ret = 0; |
559 | int j; |
560 | |
561 | numbits = bc->hdlcrx.numbits; |
562 | state = bc->hdlcrx.state; |
563 | bitstream = bc->hdlcrx.bitstream; |
564 | bitbuf = bc->hdlcrx.bitbuf; |
565 | while (cnt > 0) { |
566 | cnt2 = (cnt > sizeof(tmp)) ? sizeof(tmp) : cnt; |
567 | cnt -= cnt2; |
568 | if (cnt2 != pp->ops->epp_read_data(pp, tmp, cnt2, 0)) { |
569 | ret = -1; |
570 | break; |
571 | } |
572 | cp = tmp; |
573 | for (; cnt2 > 0; cnt2--, cp++) { |
574 | bitstream >>= 8; |
575 | bitstream |= (*cp) << 8; |
576 | bitbuf >>= 8; |
577 | bitbuf |= (*cp) << 8; |
578 | numbits += 8; |
579 | notbitstream = ~bitstream; |
580 | for (j = 0; j < 8; j++) { |
581 | |
582 | /* flag or abort */ |
583 | if (unlikely(!(notbitstream & (0x0fc << j)))) { |
584 | |
585 | /* abort received */ |
586 | if (!(notbitstream & (0x1fc << j))) |
587 | state = 0; |
588 | |
589 | /* flag received */ |
590 | else if ((bitstream & (0x1fe << j)) == (0x0fc << j)) { |
591 | if (state) |
592 | do_rxpacket(dev); |
593 | bc->hdlcrx.bufcnt = 0; |
594 | bc->hdlcrx.bufptr = bc->hdlcrx.buf; |
595 | state = 1; |
596 | numbits = 7-j; |
597 | } |
598 | } |
599 | |
600 | /* stuffed bit */ |
601 | else if (unlikely((bitstream & (0x1f8 << j)) == (0xf8 << j))) { |
602 | numbits--; |
603 | bitbuf = (bitbuf & ((~0xff) << j)) | ((bitbuf & ~((~0xff) << j)) << 1); |
604 | } |
605 | } |
606 | while (state && numbits >= 8) { |
607 | if (bc->hdlcrx.bufcnt >= TXBUFFER_SIZE) { |
608 | state = 0; |
609 | } else { |
610 | *(bc->hdlcrx.bufptr)++ = bitbuf >> (16-numbits); |
611 | bc->hdlcrx.bufcnt++; |
612 | numbits -= 8; |
613 | } |
614 | } |
615 | } |
616 | } |
617 | bc->hdlcrx.numbits = numbits; |
618 | bc->hdlcrx.state = state; |
619 | bc->hdlcrx.bitstream = bitstream; |
620 | bc->hdlcrx.bitbuf = bitbuf; |
621 | return ret; |
622 | } |
623 | |
624 | /* --------------------------------------------------------------------- */ |
625 | |
626 | #define GETTICK(x) \ |
627 | ({ \ |
628 | x = (unsigned int)get_cycles(); \ |
629 | }) |
630 | |
631 | static void epp_bh(struct work_struct *work) |
632 | { |
633 | struct net_device *dev; |
634 | struct baycom_state *bc; |
635 | struct parport *pp; |
636 | unsigned char stat; |
637 | unsigned char tmp[2]; |
638 | unsigned int time1 = 0, time2 = 0, time3 = 0; |
639 | int cnt, cnt2; |
640 | |
641 | bc = container_of(work, struct baycom_state, run_work.work); |
642 | dev = bc->dev; |
643 | if (!bc->work_running) |
644 | return; |
645 | baycom_int_freq(bc); |
646 | pp = bc->pdev->port; |
647 | /* update status */ |
648 | if (pp->ops->epp_read_addr(pp, &stat, 1, 0) != 1) |
649 | goto epptimeout; |
650 | bc->stat = stat; |
651 | bc->debug_vals.last_pllcorr = stat; |
652 | GETTICK(time1); |
653 | if (bc->modem == EPP_FPGAEXTSTATUS) { |
654 | /* get input count */ |
655 | tmp[0] = EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE|1; |
656 | if (pp->ops->epp_write_addr(pp, tmp, 1, 0) != 1) |
657 | goto epptimeout; |
658 | if (pp->ops->epp_read_addr(pp, tmp, 2, 0) != 2) |
659 | goto epptimeout; |
660 | cnt = tmp[0] | (tmp[1] << 8); |
661 | cnt &= 0x7fff; |
662 | /* get output count */ |
663 | tmp[0] = EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE|2; |
664 | if (pp->ops->epp_write_addr(pp, tmp, 1, 0) != 1) |
665 | goto epptimeout; |
666 | if (pp->ops->epp_read_addr(pp, tmp, 2, 0) != 2) |
667 | goto epptimeout; |
668 | cnt2 = tmp[0] | (tmp[1] << 8); |
669 | cnt2 = 16384 - (cnt2 & 0x7fff); |
670 | /* return to normal */ |
671 | tmp[0] = EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE; |
672 | if (pp->ops->epp_write_addr(pp, tmp, 1, 0) != 1) |
673 | goto epptimeout; |
674 | if (transmit(bc, cnt: cnt2, stat)) |
675 | goto epptimeout; |
676 | GETTICK(time2); |
677 | if (receive(dev, cnt)) |
678 | goto epptimeout; |
679 | if (pp->ops->epp_read_addr(pp, &stat, 1, 0) != 1) |
680 | goto epptimeout; |
681 | bc->stat = stat; |
682 | } else { |
683 | /* try to tx */ |
684 | switch (stat & (EPP_NTAEF|EPP_NTHF)) { |
685 | case EPP_NTHF: |
686 | cnt = 2048 - 256; |
687 | break; |
688 | |
689 | case EPP_NTAEF: |
690 | cnt = 2048 - 1793; |
691 | break; |
692 | |
693 | case 0: |
694 | cnt = 0; |
695 | break; |
696 | |
697 | default: |
698 | cnt = 2048 - 1025; |
699 | break; |
700 | } |
701 | if (transmit(bc, cnt, stat)) |
702 | goto epptimeout; |
703 | GETTICK(time2); |
704 | /* do receiver */ |
705 | while ((stat & (EPP_NRAEF|EPP_NRHF)) != EPP_NRHF) { |
706 | switch (stat & (EPP_NRAEF|EPP_NRHF)) { |
707 | case EPP_NRAEF: |
708 | cnt = 1025; |
709 | break; |
710 | |
711 | case 0: |
712 | cnt = 1793; |
713 | break; |
714 | |
715 | default: |
716 | cnt = 256; |
717 | break; |
718 | } |
719 | if (receive(dev, cnt)) |
720 | goto epptimeout; |
721 | if (pp->ops->epp_read_addr(pp, &stat, 1, 0) != 1) |
722 | goto epptimeout; |
723 | } |
724 | cnt = 0; |
725 | if (bc->bitrate < 50000) |
726 | cnt = 256; |
727 | else if (bc->bitrate < 100000) |
728 | cnt = 128; |
729 | while (cnt > 0 && stat & EPP_NREF) { |
730 | if (receive(dev, cnt: 1)) |
731 | goto epptimeout; |
732 | cnt--; |
733 | if (pp->ops->epp_read_addr(pp, &stat, 1, 0) != 1) |
734 | goto epptimeout; |
735 | } |
736 | } |
737 | GETTICK(time3); |
738 | #ifdef BAYCOM_DEBUG |
739 | bc->debug_vals.mod_cycles = time2 - time1; |
740 | bc->debug_vals.demod_cycles = time3 - time2; |
741 | #endif /* BAYCOM_DEBUG */ |
742 | schedule_delayed_work(dwork: &bc->run_work, delay: 1); |
743 | if (!bc->skb) |
744 | netif_wake_queue(dev); |
745 | return; |
746 | epptimeout: |
747 | printk(KERN_ERR "%s: EPP timeout!\n" , bc_drvname); |
748 | } |
749 | |
750 | /* ---------------------------------------------------------------------- */ |
751 | /* |
752 | * ===================== network driver interface ========================= |
753 | */ |
754 | |
755 | static netdev_tx_t baycom_send_packet(struct sk_buff *skb, struct net_device *dev) |
756 | { |
757 | struct baycom_state *bc = netdev_priv(dev); |
758 | |
759 | if (skb->protocol == htons(ETH_P_IP)) |
760 | return ax25_ip_xmit(skb); |
761 | |
762 | if (skb->data[0] != 0) { |
763 | do_kiss_params(bc, data: skb->data, len: skb->len); |
764 | dev_kfree_skb(skb); |
765 | return NETDEV_TX_OK; |
766 | } |
767 | if (bc->skb) { |
768 | dev_kfree_skb(skb); |
769 | return NETDEV_TX_OK; |
770 | } |
771 | /* strip KISS byte */ |
772 | if (skb->len >= HDLCDRV_MAXFLEN+1 || skb->len < 3) { |
773 | dev_kfree_skb(skb); |
774 | return NETDEV_TX_OK; |
775 | } |
776 | netif_stop_queue(dev); |
777 | bc->skb = skb; |
778 | return NETDEV_TX_OK; |
779 | } |
780 | |
781 | /* --------------------------------------------------------------------- */ |
782 | |
783 | static int baycom_set_mac_address(struct net_device *dev, void *addr) |
784 | { |
785 | struct sockaddr *sa = (struct sockaddr *)addr; |
786 | |
787 | /* addr is an AX.25 shifted ASCII mac address */ |
788 | dev_addr_set(dev, addr: sa->sa_data); |
789 | return 0; |
790 | } |
791 | |
792 | /* --------------------------------------------------------------------- */ |
793 | |
794 | static void epp_wakeup(void *handle) |
795 | { |
796 | struct net_device *dev = (struct net_device *)handle; |
797 | struct baycom_state *bc = netdev_priv(dev); |
798 | |
799 | printk(KERN_DEBUG "baycom_epp: %s: why am I being woken up?\n" , dev->name); |
800 | if (!parport_claim(dev: bc->pdev)) |
801 | printk(KERN_DEBUG "baycom_epp: %s: I'm broken.\n" , dev->name); |
802 | } |
803 | |
804 | /* --------------------------------------------------------------------- */ |
805 | |
806 | /* |
807 | * Open/initialize the board. This is called (in the current kernel) |
808 | * sometime after booting when the 'ifconfig' program is run. |
809 | * |
810 | * This routine should set everything up anew at each open, even |
811 | * registers that "should" only need to be set once at boot, so that |
812 | * there is non-reboot way to recover if something goes wrong. |
813 | */ |
814 | |
815 | static int epp_open(struct net_device *dev) |
816 | { |
817 | struct baycom_state *bc = netdev_priv(dev); |
818 | struct parport *pp = parport_find_base(dev->base_addr); |
819 | unsigned int i, j; |
820 | unsigned char tmp[128]; |
821 | unsigned char stat; |
822 | unsigned long tstart; |
823 | struct pardev_cb par_cb; |
824 | |
825 | if (!pp) { |
826 | printk(KERN_ERR "%s: parport at 0x%lx unknown\n" , bc_drvname, dev->base_addr); |
827 | return -ENXIO; |
828 | } |
829 | #if 0 |
830 | if (pp->irq < 0) { |
831 | printk(KERN_ERR "%s: parport at 0x%lx has no irq\n" , bc_drvname, pp->base); |
832 | parport_put_port(pp); |
833 | return -ENXIO; |
834 | } |
835 | #endif |
836 | if ((~pp->modes) & (PARPORT_MODE_TRISTATE | PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT)) { |
837 | printk(KERN_ERR "%s: parport at 0x%lx cannot be used\n" , |
838 | bc_drvname, pp->base); |
839 | parport_put_port(pp); |
840 | return -EIO; |
841 | } |
842 | memset(&bc->modem, 0, sizeof(bc->modem)); |
843 | memset(&par_cb, 0, sizeof(par_cb)); |
844 | par_cb.wakeup = epp_wakeup; |
845 | par_cb.private = (void *)dev; |
846 | par_cb.flags = PARPORT_DEV_EXCL; |
847 | for (i = 0; i < NR_PORTS; i++) |
848 | if (baycom_device[i] == dev) |
849 | break; |
850 | |
851 | if (i == NR_PORTS) { |
852 | pr_err("%s: no device found\n" , bc_drvname); |
853 | parport_put_port(pp); |
854 | return -ENODEV; |
855 | } |
856 | |
857 | bc->pdev = parport_register_dev_model(port: pp, name: dev->name, par_dev_cb: &par_cb, cnt: i); |
858 | parport_put_port(pp); |
859 | if (!bc->pdev) { |
860 | printk(KERN_ERR "%s: cannot register parport at 0x%lx\n" , bc_drvname, pp->base); |
861 | return -ENXIO; |
862 | } |
863 | if (parport_claim(dev: bc->pdev)) { |
864 | printk(KERN_ERR "%s: parport at 0x%lx busy\n" , bc_drvname, pp->base); |
865 | parport_unregister_device(dev: bc->pdev); |
866 | return -EBUSY; |
867 | } |
868 | dev->irq = /*pp->irq*/ 0; |
869 | INIT_DELAYED_WORK(&bc->run_work, epp_bh); |
870 | bc->work_running = 1; |
871 | bc->modem = EPP_CONVENTIONAL; |
872 | if (eppconfig(bc)) |
873 | printk(KERN_INFO "%s: no FPGA detected, assuming conventional EPP modem\n" , bc_drvname); |
874 | else |
875 | bc->modem = /*EPP_FPGA*/ EPP_FPGAEXTSTATUS; |
876 | parport_write_control(pp, LPTCTRL_PROGRAM); /* prepare EPP mode; we aren't using interrupts */ |
877 | /* reset the modem */ |
878 | tmp[0] = 0; |
879 | tmp[1] = EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE; |
880 | if (pp->ops->epp_write_addr(pp, tmp, 2, 0) != 2) |
881 | goto epptimeout; |
882 | /* autoprobe baud rate */ |
883 | tstart = jiffies; |
884 | i = 0; |
885 | while (time_before(jiffies, tstart + HZ/3)) { |
886 | if (pp->ops->epp_read_addr(pp, &stat, 1, 0) != 1) |
887 | goto epptimeout; |
888 | if ((stat & (EPP_NRAEF|EPP_NRHF)) == EPP_NRHF) { |
889 | schedule(); |
890 | continue; |
891 | } |
892 | if (pp->ops->epp_read_data(pp, tmp, 128, 0) != 128) |
893 | goto epptimeout; |
894 | if (pp->ops->epp_read_data(pp, tmp, 128, 0) != 128) |
895 | goto epptimeout; |
896 | i += 256; |
897 | } |
898 | for (j = 0; j < 256; j++) { |
899 | if (pp->ops->epp_read_addr(pp, &stat, 1, 0) != 1) |
900 | goto epptimeout; |
901 | if (!(stat & EPP_NREF)) |
902 | break; |
903 | if (pp->ops->epp_read_data(pp, tmp, 1, 0) != 1) |
904 | goto epptimeout; |
905 | i++; |
906 | } |
907 | tstart = jiffies - tstart; |
908 | bc->bitrate = i * (8 * HZ) / tstart; |
909 | j = 1; |
910 | i = bc->bitrate >> 3; |
911 | while (j < 7 && i > 150) { |
912 | j++; |
913 | i >>= 1; |
914 | } |
915 | printk(KERN_INFO "%s: autoprobed bitrate: %d int divider: %d int rate: %d\n" , |
916 | bc_drvname, bc->bitrate, j, bc->bitrate >> (j+2)); |
917 | tmp[0] = EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE/*|j*/; |
918 | if (pp->ops->epp_write_addr(pp, tmp, 1, 0) != 1) |
919 | goto epptimeout; |
920 | /* |
921 | * initialise hdlc variables |
922 | */ |
923 | bc->hdlcrx.state = 0; |
924 | bc->hdlcrx.numbits = 0; |
925 | bc->hdlctx.state = tx_idle; |
926 | bc->hdlctx.bufcnt = 0; |
927 | bc->hdlctx.slotcnt = bc->ch_params.slottime; |
928 | bc->hdlctx.calibrate = 0; |
929 | /* start the bottom half stuff */ |
930 | schedule_delayed_work(dwork: &bc->run_work, delay: 1); |
931 | netif_start_queue(dev); |
932 | return 0; |
933 | |
934 | epptimeout: |
935 | printk(KERN_ERR "%s: epp timeout during bitrate probe\n" , bc_drvname); |
936 | parport_write_control(pp, 0); /* reset the adapter */ |
937 | parport_release(dev: bc->pdev); |
938 | parport_unregister_device(dev: bc->pdev); |
939 | return -EIO; |
940 | } |
941 | |
942 | /* --------------------------------------------------------------------- */ |
943 | |
944 | static int epp_close(struct net_device *dev) |
945 | { |
946 | struct baycom_state *bc = netdev_priv(dev); |
947 | struct parport *pp = bc->pdev->port; |
948 | unsigned char tmp[1]; |
949 | |
950 | bc->work_running = 0; |
951 | cancel_delayed_work_sync(dwork: &bc->run_work); |
952 | bc->stat = EPP_DCDBIT; |
953 | tmp[0] = 0; |
954 | pp->ops->epp_write_addr(pp, tmp, 1, 0); |
955 | parport_write_control(pp, 0); /* reset the adapter */ |
956 | parport_release(dev: bc->pdev); |
957 | parport_unregister_device(dev: bc->pdev); |
958 | dev_kfree_skb(bc->skb); |
959 | bc->skb = NULL; |
960 | printk(KERN_INFO "%s: close epp at iobase 0x%lx irq %u\n" , |
961 | bc_drvname, dev->base_addr, dev->irq); |
962 | return 0; |
963 | } |
964 | |
965 | /* --------------------------------------------------------------------- */ |
966 | |
967 | static int baycom_setmode(struct baycom_state *bc, const char *modestr) |
968 | { |
969 | const char *cp; |
970 | |
971 | if (strstr(modestr,"intclk" )) |
972 | bc->cfg.intclk = 1; |
973 | if (strstr(modestr,"extclk" )) |
974 | bc->cfg.intclk = 0; |
975 | if (strstr(modestr,"intmodem" )) |
976 | bc->cfg.extmodem = 0; |
977 | if (strstr(modestr,"extmodem" )) |
978 | bc->cfg.extmodem = 1; |
979 | if (strstr(modestr,"loopback" )) |
980 | bc->cfg.loopback = 1; |
981 | if (strstr(modestr, "noloopback" )) |
982 | bc->cfg.loopback = 0; |
983 | if ((cp = strstr(modestr,"fclk=" ))) { |
984 | bc->cfg.fclk = simple_strtoul(cp+5, NULL, 0); |
985 | if (bc->cfg.fclk < 1000000) |
986 | bc->cfg.fclk = 1000000; |
987 | if (bc->cfg.fclk > 25000000) |
988 | bc->cfg.fclk = 25000000; |
989 | } |
990 | if ((cp = strstr(modestr,"bps=" ))) { |
991 | bc->cfg.bps = simple_strtoul(cp+4, NULL, 0); |
992 | if (bc->cfg.bps < 1000) |
993 | bc->cfg.bps = 1000; |
994 | if (bc->cfg.bps > 1500000) |
995 | bc->cfg.bps = 1500000; |
996 | } |
997 | return 0; |
998 | } |
999 | |
1000 | /* --------------------------------------------------------------------- */ |
1001 | |
1002 | static int baycom_siocdevprivate(struct net_device *dev, struct ifreq *ifr, |
1003 | void __user *data, int cmd) |
1004 | { |
1005 | struct baycom_state *bc = netdev_priv(dev); |
1006 | struct hdlcdrv_ioctl hi; |
1007 | |
1008 | if (cmd != SIOCDEVPRIVATE) |
1009 | return -ENOIOCTLCMD; |
1010 | |
1011 | if (copy_from_user(to: &hi, from: data, n: sizeof(hi))) |
1012 | return -EFAULT; |
1013 | switch (hi.cmd) { |
1014 | default: |
1015 | return -ENOIOCTLCMD; |
1016 | |
1017 | case HDLCDRVCTL_GETCHANNELPAR: |
1018 | hi.data.cp.tx_delay = bc->ch_params.tx_delay; |
1019 | hi.data.cp.tx_tail = bc->ch_params.tx_tail; |
1020 | hi.data.cp.slottime = bc->ch_params.slottime; |
1021 | hi.data.cp.ppersist = bc->ch_params.ppersist; |
1022 | hi.data.cp.fulldup = bc->ch_params.fulldup; |
1023 | break; |
1024 | |
1025 | case HDLCDRVCTL_SETCHANNELPAR: |
1026 | if (!capable(CAP_NET_ADMIN)) |
1027 | return -EACCES; |
1028 | bc->ch_params.tx_delay = hi.data.cp.tx_delay; |
1029 | bc->ch_params.tx_tail = hi.data.cp.tx_tail; |
1030 | bc->ch_params.slottime = hi.data.cp.slottime; |
1031 | bc->ch_params.ppersist = hi.data.cp.ppersist; |
1032 | bc->ch_params.fulldup = hi.data.cp.fulldup; |
1033 | bc->hdlctx.slotcnt = 1; |
1034 | return 0; |
1035 | |
1036 | case HDLCDRVCTL_GETMODEMPAR: |
1037 | hi.data.mp.iobase = dev->base_addr; |
1038 | hi.data.mp.irq = dev->irq; |
1039 | hi.data.mp.dma = dev->dma; |
1040 | hi.data.mp.dma2 = 0; |
1041 | hi.data.mp.seriobase = 0; |
1042 | hi.data.mp.pariobase = 0; |
1043 | hi.data.mp.midiiobase = 0; |
1044 | break; |
1045 | |
1046 | case HDLCDRVCTL_SETMODEMPAR: |
1047 | if ((!capable(CAP_SYS_RAWIO)) || netif_running(dev)) |
1048 | return -EACCES; |
1049 | dev->base_addr = hi.data.mp.iobase; |
1050 | dev->irq = /*hi.data.mp.irq*/0; |
1051 | dev->dma = /*hi.data.mp.dma*/0; |
1052 | return 0; |
1053 | |
1054 | case HDLCDRVCTL_GETSTAT: |
1055 | hi.data.cs.ptt = !!(bc->stat & EPP_PTTBIT); |
1056 | hi.data.cs.dcd = !(bc->stat & EPP_DCDBIT); |
1057 | hi.data.cs.ptt_keyed = bc->ptt_keyed; |
1058 | hi.data.cs.tx_packets = dev->stats.tx_packets; |
1059 | hi.data.cs.tx_errors = dev->stats.tx_errors; |
1060 | hi.data.cs.rx_packets = dev->stats.rx_packets; |
1061 | hi.data.cs.rx_errors = dev->stats.rx_errors; |
1062 | break; |
1063 | |
1064 | case HDLCDRVCTL_OLDGETSTAT: |
1065 | hi.data.ocs.ptt = !!(bc->stat & EPP_PTTBIT); |
1066 | hi.data.ocs.dcd = !(bc->stat & EPP_DCDBIT); |
1067 | hi.data.ocs.ptt_keyed = bc->ptt_keyed; |
1068 | break; |
1069 | |
1070 | case HDLCDRVCTL_CALIBRATE: |
1071 | if (!capable(CAP_SYS_RAWIO)) |
1072 | return -EACCES; |
1073 | bc->hdlctx.calibrate = hi.data.calibrate * bc->bitrate / 8; |
1074 | return 0; |
1075 | |
1076 | case HDLCDRVCTL_DRIVERNAME: |
1077 | strscpy_pad(dest: hi.data.drivername, src: "baycom_epp" , count: sizeof(hi.data.drivername)); |
1078 | break; |
1079 | |
1080 | case HDLCDRVCTL_GETMODE: |
1081 | sprintf(buf: hi.data.modename, fmt: "%sclk,%smodem,fclk=%d,bps=%d%s" , |
1082 | bc->cfg.intclk ? "int" : "ext" , |
1083 | bc->cfg.extmodem ? "ext" : "int" , bc->cfg.fclk, bc->cfg.bps, |
1084 | bc->cfg.loopback ? ",loopback" : "" ); |
1085 | break; |
1086 | |
1087 | case HDLCDRVCTL_SETMODE: |
1088 | if (!capable(CAP_NET_ADMIN) || netif_running(dev)) |
1089 | return -EACCES; |
1090 | hi.data.modename[sizeof(hi.data.modename)-1] = '\0'; |
1091 | return baycom_setmode(bc, modestr: hi.data.modename); |
1092 | |
1093 | case HDLCDRVCTL_MODELIST: |
1094 | strscpy_pad(dest: hi.data.modename, src: "intclk,extclk,intmodem,extmodem,divider=x" , |
1095 | count: sizeof(hi.data.modename)); |
1096 | break; |
1097 | |
1098 | case HDLCDRVCTL_MODEMPARMASK: |
1099 | return HDLCDRV_PARMASK_IOBASE; |
1100 | |
1101 | } |
1102 | if (copy_to_user(to: data, from: &hi, n: sizeof(hi))) |
1103 | return -EFAULT; |
1104 | return 0; |
1105 | } |
1106 | |
1107 | /* --------------------------------------------------------------------- */ |
1108 | |
1109 | static const struct net_device_ops baycom_netdev_ops = { |
1110 | .ndo_open = epp_open, |
1111 | .ndo_stop = epp_close, |
1112 | .ndo_siocdevprivate = baycom_siocdevprivate, |
1113 | .ndo_start_xmit = baycom_send_packet, |
1114 | .ndo_set_mac_address = baycom_set_mac_address, |
1115 | }; |
1116 | |
1117 | /* |
1118 | * Check for a network adaptor of this type, and return '0' if one exists. |
1119 | * If dev->base_addr == 0, probe all likely locations. |
1120 | * If dev->base_addr == 1, always return failure. |
1121 | * If dev->base_addr == 2, allocate space for the device and return success |
1122 | * (detachable devices only). |
1123 | */ |
1124 | static void baycom_probe(struct net_device *dev) |
1125 | { |
1126 | const struct hdlcdrv_channel_params dflt_ch_params = { |
1127 | 20, 2, 10, 40, 0 |
1128 | }; |
1129 | struct baycom_state *bc; |
1130 | |
1131 | /* |
1132 | * not a real probe! only initialize data structures |
1133 | */ |
1134 | bc = netdev_priv(dev); |
1135 | /* |
1136 | * initialize the baycom_state struct |
1137 | */ |
1138 | bc->ch_params = dflt_ch_params; |
1139 | bc->ptt_keyed = 0; |
1140 | |
1141 | /* |
1142 | * initialize the device struct |
1143 | */ |
1144 | |
1145 | /* Fill in the fields of the device structure */ |
1146 | bc->skb = NULL; |
1147 | |
1148 | dev->netdev_ops = &baycom_netdev_ops; |
1149 | dev->header_ops = &ax25_header_ops; |
1150 | |
1151 | dev->type = ARPHRD_AX25; /* AF_AX25 device */ |
1152 | dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN; |
1153 | dev->mtu = AX25_DEF_PACLEN; /* eth_mtu is the default */ |
1154 | dev->addr_len = AX25_ADDR_LEN; /* sizeof an ax.25 address */ |
1155 | memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN); |
1156 | dev_addr_set(dev, addr: (u8 *)&null_ax25_address); |
1157 | dev->tx_queue_len = 16; |
1158 | |
1159 | /* New style flags */ |
1160 | dev->flags = 0; |
1161 | } |
1162 | |
1163 | /* --------------------------------------------------------------------- */ |
1164 | |
1165 | /* |
1166 | * command line settable parameters |
1167 | */ |
1168 | static char *mode[NR_PORTS] = { "" , }; |
1169 | static int iobase[NR_PORTS] = { 0x378, }; |
1170 | |
1171 | module_param_array(mode, charp, NULL, 0); |
1172 | MODULE_PARM_DESC(mode, "baycom operating mode" ); |
1173 | module_param_hw_array(iobase, int, ioport, NULL, 0); |
1174 | MODULE_PARM_DESC(iobase, "baycom io base address" ); |
1175 | |
1176 | MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu" ); |
1177 | MODULE_DESCRIPTION("Baycom epp amateur radio modem driver" ); |
1178 | MODULE_LICENSE("GPL" ); |
1179 | |
1180 | /* --------------------------------------------------------------------- */ |
1181 | |
1182 | static int baycom_epp_par_probe(struct pardevice *par_dev) |
1183 | { |
1184 | struct device_driver *drv = par_dev->dev.driver; |
1185 | int len = strlen(drv->name); |
1186 | |
1187 | if (strncmp(par_dev->name, drv->name, len)) |
1188 | return -ENODEV; |
1189 | |
1190 | return 0; |
1191 | } |
1192 | |
1193 | static struct parport_driver baycom_epp_par_driver = { |
1194 | .name = "bce" , |
1195 | .probe = baycom_epp_par_probe, |
1196 | .devmodel = true, |
1197 | }; |
1198 | |
1199 | static void __init baycom_epp_dev_setup(struct net_device *dev) |
1200 | { |
1201 | struct baycom_state *bc = netdev_priv(dev); |
1202 | |
1203 | /* |
1204 | * initialize part of the baycom_state struct |
1205 | */ |
1206 | bc->dev = dev; |
1207 | bc->magic = BAYCOM_MAGIC; |
1208 | bc->cfg.fclk = 19666600; |
1209 | bc->cfg.bps = 9600; |
1210 | /* |
1211 | * initialize part of the device struct |
1212 | */ |
1213 | baycom_probe(dev); |
1214 | } |
1215 | |
1216 | static int __init init_baycomepp(void) |
1217 | { |
1218 | int i, found = 0, ret; |
1219 | char set_hw = 1; |
1220 | |
1221 | printk(bc_drvinfo); |
1222 | |
1223 | ret = parport_register_driver(&baycom_epp_par_driver); |
1224 | if (ret) |
1225 | return ret; |
1226 | |
1227 | /* |
1228 | * register net devices |
1229 | */ |
1230 | for (i = 0; i < NR_PORTS; i++) { |
1231 | struct net_device *dev; |
1232 | |
1233 | dev = alloc_netdev(sizeof(struct baycom_state), "bce%d" , |
1234 | NET_NAME_UNKNOWN, baycom_epp_dev_setup); |
1235 | |
1236 | if (!dev) { |
1237 | printk(KERN_WARNING "bce%d : out of memory\n" , i); |
1238 | return found ? 0 : -ENOMEM; |
1239 | } |
1240 | |
1241 | sprintf(buf: dev->name, fmt: "bce%d" , i); |
1242 | dev->base_addr = iobase[i]; |
1243 | |
1244 | if (!mode[i]) |
1245 | set_hw = 0; |
1246 | if (!set_hw) |
1247 | iobase[i] = 0; |
1248 | |
1249 | if (register_netdev(dev)) { |
1250 | printk(KERN_WARNING "%s: cannot register net device %s\n" , bc_drvname, dev->name); |
1251 | free_netdev(dev); |
1252 | break; |
1253 | } |
1254 | if (set_hw && baycom_setmode(bc: netdev_priv(dev), modestr: mode[i])) |
1255 | set_hw = 0; |
1256 | baycom_device[i] = dev; |
1257 | found++; |
1258 | } |
1259 | |
1260 | if (found == 0) { |
1261 | parport_unregister_driver(&baycom_epp_par_driver); |
1262 | return -ENXIO; |
1263 | } |
1264 | |
1265 | return 0; |
1266 | } |
1267 | |
1268 | static void __exit cleanup_baycomepp(void) |
1269 | { |
1270 | int i; |
1271 | |
1272 | for(i = 0; i < NR_PORTS; i++) { |
1273 | struct net_device *dev = baycom_device[i]; |
1274 | |
1275 | if (dev) { |
1276 | struct baycom_state *bc = netdev_priv(dev); |
1277 | if (bc->magic == BAYCOM_MAGIC) { |
1278 | unregister_netdev(dev); |
1279 | free_netdev(dev); |
1280 | } else |
1281 | printk(paranoia_str, "cleanup_module" ); |
1282 | } |
1283 | } |
1284 | parport_unregister_driver(&baycom_epp_par_driver); |
1285 | } |
1286 | |
1287 | module_init(init_baycomepp); |
1288 | module_exit(cleanup_baycomepp); |
1289 | |
1290 | /* --------------------------------------------------------------------- */ |
1291 | |
1292 | #ifndef MODULE |
1293 | |
1294 | /* |
1295 | * format: baycom_epp=io,mode |
1296 | * mode: fpga config options |
1297 | */ |
1298 | |
1299 | static int __init baycom_epp_setup(char *str) |
1300 | { |
1301 | static unsigned __initdata nr_dev = 0; |
1302 | int ints[2]; |
1303 | |
1304 | if (nr_dev >= NR_PORTS) |
1305 | return 0; |
1306 | str = get_options(str, nints: 2, ints); |
1307 | if (ints[0] < 1) |
1308 | return 0; |
1309 | mode[nr_dev] = str; |
1310 | iobase[nr_dev] = ints[1]; |
1311 | nr_dev++; |
1312 | return 1; |
1313 | } |
1314 | |
1315 | __setup("baycom_epp=" , baycom_epp_setup); |
1316 | |
1317 | #endif /* MODULE */ |
1318 | /* --------------------------------------------------------------------- */ |
1319 | |