Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
baycom_par.c
Go to the documentation of this file.
1 /*****************************************************************************/
2 
3 /*
4  * baycom_par.c -- baycom par96 and picpar radio modem driver.
5  *
6  * Copyright (C) 1996-2000 Thomas Sailer ([email protected])
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  *
22  * Please note that the GPL allows you to use the driver, NOT the radio.
23  * In order to use the radio, you need a license from the communications
24  * authority of your country.
25  *
26  *
27  * Supported modems
28  *
29  * par96: This is a modem for 9600 baud FSK compatible to the G3RUH standard.
30  * The modem does all the filtering and regenerates the receiver clock.
31  * Data is transferred from and to the PC via a shift register.
32  * The shift register is filled with 16 bits and an interrupt is
33  * signalled. The PC then empties the shift register in a burst. This
34  * modem connects to the parallel port, hence the name. The modem
35  * leaves the implementation of the HDLC protocol and the scrambler
36  * polynomial to the PC. This modem is no longer available (at least
37  * from Baycom) and has been replaced by the PICPAR modem (see below).
38  * You may however still build one from the schematics published in
39  * cq-DL :-).
40  *
41  * picpar: This is a redesign of the par96 modem by Henning Rech, DF9IC. The
42  * modem is protocol compatible to par96, but uses only three low
43  * power ICs and can therefore be fed from the parallel port and
44  * does not require an additional power supply. It features
45  * built in DCD circuitry. The driver should therefore be configured
46  * for hardware DCD.
47  *
48  *
49  * Command line options (insmod command line)
50  *
51  * mode driver mode string. Valid choices are par96 and picpar.
52  * iobase base address of the port; common values are 0x378, 0x278, 0x3bc
53  *
54  *
55  * History:
56  * 0.1 26.06.1996 Adapted from baycom.c and made network driver interface
57  * 18.10.1996 Changed to new user space access routines (copy_{to,from}_user)
58  * 0.3 26.04.1997 init code/data tagged
59  * 0.4 08.07.1997 alternative ser12 decoding algorithm (uses delta CTS ints)
60  * 0.5 11.11.1997 split into separate files for ser12/par96
61  * 0.6 03.08.1999 adapt to Linus' new __setup/__initcall
62  * removed some pre-2.2 kernel compatibility cruft
63  * 0.7 10.08.1999 Check if parport can do SPP and is safe to access during interrupt contexts
64  * 0.8 12.02.2000 adapted to softnet driver interface
65  * removed direct parport access, uses parport driver methods
66  * 0.9 03.07.2000 fix interface name handling
67  */
68 
69 /*****************************************************************************/
70 
71 #include <linux/module.h>
72 #include <linux/kernel.h>
73 #include <linux/types.h>
74 #include <linux/fcntl.h>
75 #include <linux/interrupt.h>
76 #include <linux/ioport.h>
77 #include <linux/in.h>
78 #include <linux/string.h>
79 #include <linux/init.h>
80 #include <linux/delay.h>
81 #include <linux/errno.h>
82 #include <linux/netdevice.h>
83 #include <linux/hdlcdrv.h>
84 #include <linux/baycom.h>
85 #include <linux/parport.h>
86 #include <linux/bitops.h>
87 #include <linux/jiffies.h>
88 
89 #include <asm/uaccess.h>
90 
91 /* --------------------------------------------------------------------- */
92 
93 #define BAYCOM_DEBUG
94 
95 /*
96  * modem options; bit mask
97  */
98 #define BAYCOM_OPTIONS_SOFTDCD 1
99 
100 /* --------------------------------------------------------------------- */
101 
102 static const char bc_drvname[] = "baycom_par";
103 static const char bc_drvinfo[] = KERN_INFO "baycom_par: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n"
104 "baycom_par: version 0.9\n";
105 
106 /* --------------------------------------------------------------------- */
107 
108 #define NR_PORTS 4
109 
110 static struct net_device *baycom_device[NR_PORTS];
111 
112 /* --------------------------------------------------------------------- */
113 
114 #define PAR96_BURSTBITS 16
115 #define PAR96_BURST 4
116 #define PAR96_PTT 2
117 #define PAR96_TXBIT 1
118 #define PAR96_ACK 0x40
119 #define PAR96_RXBIT 0x20
120 #define PAR96_DCD 0x10
121 #define PAR97_POWER 0xf8
122 
123 /* ---------------------------------------------------------------------- */
124 /*
125  * Information that need to be kept for each board.
126  */
127 
128 struct baycom_state {
130 
131  struct pardevice *pdev;
132  unsigned int options;
133 
134  struct modem_state {
135  short arb_divider;
136  unsigned char flags;
137  unsigned int shreg;
140  unsigned int dcd_shreg;
141  unsigned long descram;
142  unsigned long scram;
143  } par96;
144  } modem;
145 
146 #ifdef BAYCOM_DEBUG
147  struct debug_vals {
148  unsigned long last_jiffies;
149  unsigned cur_intcnt;
150  unsigned last_intcnt;
151  int cur_pllcorr;
152  int last_pllcorr;
153  } debug_vals;
154 #endif /* BAYCOM_DEBUG */
155 };
156 
157 /* --------------------------------------------------------------------- */
158 
159 static void __inline__ baycom_int_freq(struct baycom_state *bc)
160 {
161 #ifdef BAYCOM_DEBUG
162  unsigned long cur_jiffies = jiffies;
163  /*
164  * measure the interrupt frequency
165  */
166  bc->debug_vals.cur_intcnt++;
167  if (time_after_eq(cur_jiffies, bc->debug_vals.last_jiffies + HZ)) {
168  bc->debug_vals.last_jiffies = cur_jiffies;
169  bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt;
170  bc->debug_vals.cur_intcnt = 0;
171  bc->debug_vals.last_pllcorr = bc->debug_vals.cur_pllcorr;
172  bc->debug_vals.cur_pllcorr = 0;
173  }
174 #endif /* BAYCOM_DEBUG */
175 }
176 
177 /* --------------------------------------------------------------------- */
178 /*
179  * ===================== PAR96 specific routines =========================
180  */
181 
182 #define PAR96_DESCRAM_TAP1 0x20000
183 #define PAR96_DESCRAM_TAP2 0x01000
184 #define PAR96_DESCRAM_TAP3 0x00001
185 
186 #define PAR96_DESCRAM_TAPSH1 17
187 #define PAR96_DESCRAM_TAPSH2 12
188 #define PAR96_DESCRAM_TAPSH3 0
189 
190 #define PAR96_SCRAM_TAP1 0x20000 /* X^17 */
191 #define PAR96_SCRAM_TAPN 0x00021 /* X^0+X^5 */
192 
193 /* --------------------------------------------------------------------- */
194 
195 static __inline__ void par96_tx(struct net_device *dev, struct baycom_state *bc)
196 {
197  int i;
198  unsigned int data = hdlcdrv_getbits(&bc->hdrv);
199  struct parport *pp = bc->pdev->port;
200 
201  for(i = 0; i < PAR96_BURSTBITS; i++, data >>= 1) {
202  unsigned char val = PAR97_POWER;
203  bc->modem.par96.scram = ((bc->modem.par96.scram << 1) |
204  (bc->modem.par96.scram & 1));
205  if (!(data & 1))
206  bc->modem.par96.scram ^= 1;
207  if (bc->modem.par96.scram & (PAR96_SCRAM_TAP1 << 1))
208  bc->modem.par96.scram ^=
209  (PAR96_SCRAM_TAPN << 1);
210  if (bc->modem.par96.scram & (PAR96_SCRAM_TAP1 << 2))
211  val |= PAR96_TXBIT;
212  pp->ops->write_data(pp, val);
213  pp->ops->write_data(pp, val | PAR96_BURST);
214  }
215 }
216 
217 /* --------------------------------------------------------------------- */
218 
219 static __inline__ void par96_rx(struct net_device *dev, struct baycom_state *bc)
220 {
221  int i;
222  unsigned int data, mask, mask2, descx;
223  struct parport *pp = bc->pdev->port;
224 
225  /*
226  * do receiver; differential decode and descramble on the fly
227  */
228  for(data = i = 0; i < PAR96_BURSTBITS; i++) {
229  bc->modem.par96.descram = (bc->modem.par96.descram << 1);
230  if (pp->ops->read_status(pp) & PAR96_RXBIT)
231  bc->modem.par96.descram |= 1;
232  descx = bc->modem.par96.descram ^
233  (bc->modem.par96.descram >> 1);
234  /* now the diff decoded data is inverted in descram */
235  pp->ops->write_data(pp, PAR97_POWER | PAR96_PTT);
236  descx ^= ((descx >> PAR96_DESCRAM_TAPSH1) ^
237  (descx >> PAR96_DESCRAM_TAPSH2));
238  data >>= 1;
239  if (!(descx & 1))
240  data |= 0x8000;
241  pp->ops->write_data(pp, PAR97_POWER | PAR96_PTT | PAR96_BURST);
242  }
243  hdlcdrv_putbits(&bc->hdrv, data);
244  /*
245  * do DCD algorithm
246  */
247  if (bc->options & BAYCOM_OPTIONS_SOFTDCD) {
248  bc->modem.par96.dcd_shreg = (bc->modem.par96.dcd_shreg >> 16)
249  | (data << 16);
250  /* search for flags and set the dcd counter appropriately */
251  for(mask = 0x1fe00, mask2 = 0xfc00, i = 0;
252  i < PAR96_BURSTBITS; i++, mask <<= 1, mask2 <<= 1)
253  if ((bc->modem.par96.dcd_shreg & mask) == mask2)
254  bc->modem.par96.dcd_count = HDLCDRV_MAXFLEN+4;
255  /* check for abort/noise sequences */
256  for(mask = 0x1fe00, mask2 = 0x1fe00, i = 0;
257  i < PAR96_BURSTBITS; i++, mask <<= 1, mask2 <<= 1)
258  if (((bc->modem.par96.dcd_shreg & mask) == mask2) &&
259  (bc->modem.par96.dcd_count >= 0))
260  bc->modem.par96.dcd_count -= HDLCDRV_MAXFLEN-10;
261  /* decrement and set the dcd variable */
262  if (bc->modem.par96.dcd_count >= 0)
263  bc->modem.par96.dcd_count -= 2;
264  hdlcdrv_setdcd(&bc->hdrv, bc->modem.par96.dcd_count > 0);
265  } else {
266  hdlcdrv_setdcd(&bc->hdrv, !!(pp->ops->read_status(pp) & PAR96_DCD));
267  }
268 }
269 
270 /* --------------------------------------------------------------------- */
271 
272 static void par96_interrupt(void *dev_id)
273 {
274  struct net_device *dev = dev_id;
275  struct baycom_state *bc = netdev_priv(dev);
276 
277  baycom_int_freq(bc);
278  /*
279  * check if transmitter active
280  */
281  if (hdlcdrv_ptt(&bc->hdrv))
282  par96_tx(dev, bc);
283  else {
284  par96_rx(dev, bc);
285  if (--bc->modem.arb_divider <= 0) {
286  bc->modem.arb_divider = 6;
288  hdlcdrv_arbitrate(dev, &bc->hdrv);
289  }
290  }
292  hdlcdrv_transmitter(dev, &bc->hdrv);
293  hdlcdrv_receiver(dev, &bc->hdrv);
295 }
296 
297 /* --------------------------------------------------------------------- */
298 
299 static void par96_wakeup(void *handle)
300 {
301  struct net_device *dev = (struct net_device *)handle;
302  struct baycom_state *bc = netdev_priv(dev);
303 
304  printk(KERN_DEBUG "baycom_par: %s: why am I being woken up?\n", dev->name);
305  if (!parport_claim(bc->pdev))
306  printk(KERN_DEBUG "baycom_par: %s: I'm broken.\n", dev->name);
307 }
308 
309 /* --------------------------------------------------------------------- */
310 
311 static int par96_open(struct net_device *dev)
312 {
313  struct baycom_state *bc = netdev_priv(dev);
314  struct parport *pp;
315 
316  if (!dev || !bc)
317  return -ENXIO;
318  pp = parport_find_base(dev->base_addr);
319  if (!pp) {
320  printk(KERN_ERR "baycom_par: parport at 0x%lx unknown\n", dev->base_addr);
321  return -ENXIO;
322  }
323  if (pp->irq < 0) {
324  printk(KERN_ERR "baycom_par: parport at 0x%lx has no irq\n", pp->base);
325  parport_put_port(pp);
326  return -ENXIO;
327  }
329  printk(KERN_ERR "baycom_par: parport at 0x%lx cannot be used\n", pp->base);
330  parport_put_port(pp);
331  return -ENXIO;
332  }
333  memset(&bc->modem, 0, sizeof(bc->modem));
334  bc->hdrv.par.bitrate = 9600;
335  bc->pdev = parport_register_device(pp, dev->name, NULL, par96_wakeup,
336  par96_interrupt, PARPORT_DEV_EXCL, dev);
337  parport_put_port(pp);
338  if (!bc->pdev) {
339  printk(KERN_ERR "baycom_par: cannot register parport at 0x%lx\n", dev->base_addr);
340  return -ENXIO;
341  }
342  if (parport_claim(bc->pdev)) {
343  printk(KERN_ERR "baycom_par: parport at 0x%lx busy\n", pp->base);
345  return -EBUSY;
346  }
347  pp = bc->pdev->port;
348  dev->irq = pp->irq;
349  pp->ops->data_forward(pp);
350  bc->hdrv.par.bitrate = 9600;
351  pp->ops->write_data(pp, PAR96_PTT | PAR97_POWER); /* switch off PTT */
352  pp->ops->enable_irq(pp);
353  printk(KERN_INFO "%s: par96 at iobase 0x%lx irq %u options 0x%x\n",
354  bc_drvname, dev->base_addr, dev->irq, bc->options);
355  return 0;
356 }
357 
358 /* --------------------------------------------------------------------- */
359 
360 static int par96_close(struct net_device *dev)
361 {
362  struct baycom_state *bc = netdev_priv(dev);
363  struct parport *pp;
364 
365  if (!dev || !bc)
366  return -EINVAL;
367  pp = bc->pdev->port;
368  /* disable interrupt */
369  pp->ops->disable_irq(pp);
370  /* switch off PTT */
371  pp->ops->write_data(pp, PAR96_PTT | PAR97_POWER);
372  parport_release(bc->pdev);
374  printk(KERN_INFO "%s: close par96 at iobase 0x%lx irq %u\n",
375  bc_drvname, dev->base_addr, dev->irq);
376  return 0;
377 }
378 
379 /* --------------------------------------------------------------------- */
380 /*
381  * ===================== hdlcdrv driver interface =========================
382  */
383 
384 static int baycom_ioctl(struct net_device *dev, struct ifreq *ifr,
385  struct hdlcdrv_ioctl *hi, int cmd);
386 
387 /* --------------------------------------------------------------------- */
388 
389 static struct hdlcdrv_ops par96_ops = {
390  .drvname = bc_drvname,
391  .drvinfo = bc_drvinfo,
392  .open = par96_open,
393  .close = par96_close,
394  .ioctl = baycom_ioctl
395 };
396 
397 /* --------------------------------------------------------------------- */
398 
399 static int baycom_setmode(struct baycom_state *bc, const char *modestr)
400 {
401  if (!strncmp(modestr, "picpar", 6))
402  bc->options = 0;
403  else if (!strncmp(modestr, "par96", 5))
405  else
406  bc->options = !!strchr(modestr, '*');
407  return 0;
408 }
409 
410 /* --------------------------------------------------------------------- */
411 
412 static int baycom_ioctl(struct net_device *dev, struct ifreq *ifr,
413  struct hdlcdrv_ioctl *hi, int cmd)
414 {
415  struct baycom_state *bc;
416  struct baycom_ioctl bi;
417 
418  if (!dev)
419  return -EINVAL;
420 
421  bc = netdev_priv(dev);
422  BUG_ON(bc->hdrv.magic != HDLCDRV_MAGIC);
423 
424  if (cmd != SIOCDEVPRIVATE)
425  return -ENOIOCTLCMD;
426  switch (hi->cmd) {
427  default:
428  break;
429 
430  case HDLCDRVCTL_GETMODE:
431  strcpy(hi->data.modename, bc->options ? "par96" : "picpar");
432  if (copy_to_user(ifr->ifr_data, hi, sizeof(struct hdlcdrv_ioctl)))
433  return -EFAULT;
434  return 0;
435 
436  case HDLCDRVCTL_SETMODE:
437  if (netif_running(dev) || !capable(CAP_NET_ADMIN))
438  return -EACCES;
439  hi->data.modename[sizeof(hi->data.modename)-1] = '\0';
440  return baycom_setmode(bc, hi->data.modename);
441 
442  case HDLCDRVCTL_MODELIST:
443  strcpy(hi->data.modename, "par96,picpar");
444  if (copy_to_user(ifr->ifr_data, hi, sizeof(struct hdlcdrv_ioctl)))
445  return -EFAULT;
446  return 0;
447 
449  return HDLCDRV_PARMASK_IOBASE;
450 
451  }
452 
453  if (copy_from_user(&bi, ifr->ifr_data, sizeof(bi)))
454  return -EFAULT;
455  switch (bi.cmd) {
456  default:
457  return -ENOIOCTLCMD;
458 
459 #ifdef BAYCOM_DEBUG
460  case BAYCOMCTL_GETDEBUG:
461  bi.data.dbg.debug1 = bc->hdrv.ptt_keyed;
462  bi.data.dbg.debug2 = bc->debug_vals.last_intcnt;
463  bi.data.dbg.debug3 = bc->debug_vals.last_pllcorr;
464  break;
465 #endif /* BAYCOM_DEBUG */
466 
467  }
468  if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi)))
469  return -EFAULT;
470  return 0;
471 
472 }
473 
474 /* --------------------------------------------------------------------- */
475 
476 /*
477  * command line settable parameters
478  */
479 static char *mode[NR_PORTS] = { "picpar", };
480 static int iobase[NR_PORTS] = { 0x378, };
481 
482 module_param_array(mode, charp, NULL, 0);
483 MODULE_PARM_DESC(mode, "baycom operating mode; eg. par96 or picpar");
484 module_param_array(iobase, int, NULL, 0);
485 MODULE_PARM_DESC(iobase, "baycom io base address");
486 
488 MODULE_DESCRIPTION("Baycom par96 and picpar amateur radio modem driver");
489 MODULE_LICENSE("GPL");
490 
491 /* --------------------------------------------------------------------- */
492 
493 static int __init init_baycompar(void)
494 {
495  int i, found = 0;
496  char set_hw = 1;
497 
498  printk(bc_drvinfo);
499  /*
500  * register net devices
501  */
502  for (i = 0; i < NR_PORTS; i++) {
503  struct net_device *dev;
504  struct baycom_state *bc;
505  char ifname[IFNAMSIZ];
506 
507  sprintf(ifname, "bcp%d", i);
508 
509  if (!mode[i])
510  set_hw = 0;
511  if (!set_hw)
512  iobase[i] = 0;
513 
514  dev = hdlcdrv_register(&par96_ops,
515  sizeof(struct baycom_state),
516  ifname, iobase[i], 0, 0);
517  if (IS_ERR(dev))
518  break;
519 
520  bc = netdev_priv(dev);
521  if (set_hw && baycom_setmode(bc, mode[i]))
522  set_hw = 0;
523  found++;
524  baycom_device[i] = dev;
525  }
526 
527  if (!found)
528  return -ENXIO;
529  return 0;
530 }
531 
532 static void __exit cleanup_baycompar(void)
533 {
534  int i;
535 
536  for(i = 0; i < NR_PORTS; i++) {
537  struct net_device *dev = baycom_device[i];
538 
539  if (dev)
540  hdlcdrv_unregister(dev);
541  }
542 }
543 
544 module_init(init_baycompar);
545 module_exit(cleanup_baycompar);
546 
547 /* --------------------------------------------------------------------- */
548 
549 #ifndef MODULE
550 
551 /*
552  * format: baycom_par=io,mode
553  * mode: par96,picpar
554  */
555 
556 static int __init baycom_par_setup(char *str)
557 {
558  static unsigned nr_dev;
559  int ints[2];
560 
561  if (nr_dev >= NR_PORTS)
562  return 0;
563  str = get_options(str, 2, ints);
564  if (ints[0] < 1)
565  return 0;
566  mode[nr_dev] = str;
567  iobase[nr_dev] = ints[1];
568  nr_dev++;
569  return 1;
570 }
571 
572 __setup("baycom_par=", baycom_par_setup);
573 
574 #endif /* MODULE */
575 /* --------------------------------------------------------------------- */