Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*****************************************************************************/
0003 
0004 /*
0005  *  baycom_par.c  -- baycom par96 and picpar radio modem driver.
0006  *
0007  *  Copyright (C) 1996-2000  Thomas Sailer (sailer@ife.ee.ethz.ch)
0008  *
0009  *  Please note that the GPL allows you to use the driver, NOT the radio.
0010  *  In order to use the radio, you need a license from the communications
0011  *  authority of your country.
0012  *
0013  *  Supported modems
0014  *
0015  *  par96:  This is a modem for 9600 baud FSK compatible to the G3RUH standard.
0016  *          The modem does all the filtering and regenerates the receiver clock.
0017  *          Data is transferred from and to the PC via a shift register.
0018  *          The shift register is filled with 16 bits and an interrupt is
0019  *          signalled. The PC then empties the shift register in a burst. This
0020  *          modem connects to the parallel port, hence the name. The modem
0021  *          leaves the implementation of the HDLC protocol and the scrambler
0022  *          polynomial to the PC. This modem is no longer available (at least
0023  *          from Baycom) and has been replaced by the PICPAR modem (see below).
0024  *          You may however still build one from the schematics published in
0025  *          cq-DL :-).
0026  *
0027  *  picpar: This is a redesign of the par96 modem by Henning Rech, DF9IC. The
0028  *          modem is protocol compatible to par96, but uses only three low
0029  *          power ICs and can therefore be fed from the parallel port and
0030  *          does not require an additional power supply. It features
0031  *          built in DCD circuitry. The driver should therefore be configured
0032  *          for hardware DCD.
0033  *
0034  *  Command line options (insmod command line)
0035  *
0036  *  mode     driver mode string. Valid choices are par96 and picpar.
0037  *  iobase   base address of the port; common values are 0x378, 0x278, 0x3bc
0038  *
0039  *  History:
0040  *   0.1  26.06.1996  Adapted from baycom.c and made network driver interface
0041  *        18.10.1996  Changed to new user space access routines (copy_{to,from}_user)
0042  *   0.3  26.04.1997  init code/data tagged
0043  *   0.4  08.07.1997  alternative ser12 decoding algorithm (uses delta CTS ints)
0044  *   0.5  11.11.1997  split into separate files for ser12/par96
0045  *   0.6  03.08.1999  adapt to Linus' new __setup/__initcall
0046  *                    removed some pre-2.2 kernel compatibility cruft
0047  *   0.7  10.08.1999  Check if parport can do SPP and is safe to access during interrupt contexts
0048  *   0.8  12.02.2000  adapted to softnet driver interface
0049  *                    removed direct parport access, uses parport driver methods
0050  *   0.9  03.07.2000  fix interface name handling
0051  */
0052 
0053 /*****************************************************************************/
0054 
0055 #include <linux/module.h>
0056 #include <linux/kernel.h>
0057 #include <linux/types.h>
0058 #include <linux/fcntl.h>
0059 #include <linux/interrupt.h>
0060 #include <linux/ioport.h>
0061 #include <linux/in.h>
0062 #include <linux/string.h>
0063 #include <linux/init.h>
0064 #include <linux/delay.h>
0065 #include <linux/errno.h>
0066 #include <linux/netdevice.h>
0067 #include <linux/hdlcdrv.h>
0068 #include <linux/baycom.h>
0069 #include <linux/parport.h>
0070 #include <linux/bitops.h>
0071 #include <linux/jiffies.h>
0072 
0073 #include <linux/uaccess.h>
0074 
0075 /* --------------------------------------------------------------------- */
0076 
0077 #define BAYCOM_DEBUG
0078 
0079 /*
0080  * modem options; bit mask
0081  */
0082 #define BAYCOM_OPTIONS_SOFTDCD  1
0083 
0084 /* --------------------------------------------------------------------- */
0085 
0086 static const char bc_drvname[] = "baycom_par";
0087 static const char bc_drvinfo[] = KERN_INFO "baycom_par: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n"
0088 "baycom_par: version 0.9\n";
0089 
0090 /* --------------------------------------------------------------------- */
0091 
0092 #define NR_PORTS 4
0093 
0094 static struct net_device *baycom_device[NR_PORTS];
0095 
0096 /* --------------------------------------------------------------------- */
0097 
0098 #define PAR96_BURSTBITS 16
0099 #define PAR96_BURST     4
0100 #define PAR96_PTT       2
0101 #define PAR96_TXBIT     1
0102 #define PAR96_ACK       0x40
0103 #define PAR96_RXBIT     0x20
0104 #define PAR96_DCD       0x10
0105 #define PAR97_POWER     0xf8
0106 
0107 /* ---------------------------------------------------------------------- */
0108 /*
0109  * Information that need to be kept for each board.
0110  */
0111 
0112 struct baycom_state {
0113     struct hdlcdrv_state hdrv;
0114 
0115     struct pardevice *pdev;
0116     unsigned int options;
0117 
0118     struct modem_state {
0119         short arb_divider;
0120         unsigned char flags;
0121         unsigned int shreg;
0122         struct modem_state_par96 {
0123             int dcd_count;
0124             unsigned int dcd_shreg;
0125             unsigned long descram;
0126             unsigned long scram;
0127         } par96;
0128     } modem;
0129 
0130 #ifdef BAYCOM_DEBUG
0131     struct debug_vals {
0132         unsigned long last_jiffies;
0133         unsigned cur_intcnt;
0134         unsigned last_intcnt;
0135         int cur_pllcorr;
0136         int last_pllcorr;
0137     } debug_vals;
0138 #endif /* BAYCOM_DEBUG */
0139 };
0140 
0141 /* --------------------------------------------------------------------- */
0142 
0143 static inline void baycom_int_freq(struct baycom_state *bc)
0144 {
0145 #ifdef BAYCOM_DEBUG
0146     unsigned long cur_jiffies = jiffies;
0147     /*
0148      * measure the interrupt frequency
0149      */
0150     bc->debug_vals.cur_intcnt++;
0151     if (time_after_eq(cur_jiffies, bc->debug_vals.last_jiffies + HZ)) {
0152         bc->debug_vals.last_jiffies = cur_jiffies;
0153         bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt;
0154         bc->debug_vals.cur_intcnt = 0;
0155         bc->debug_vals.last_pllcorr = bc->debug_vals.cur_pllcorr;
0156         bc->debug_vals.cur_pllcorr = 0;
0157     }
0158 #endif /* BAYCOM_DEBUG */
0159 }
0160 
0161 /* --------------------------------------------------------------------- */
0162 /*
0163  * ===================== PAR96 specific routines =========================
0164  */
0165 
0166 #define PAR96_DESCRAM_TAP1 0x20000
0167 #define PAR96_DESCRAM_TAP2 0x01000
0168 #define PAR96_DESCRAM_TAP3 0x00001
0169 
0170 #define PAR96_DESCRAM_TAPSH1 17
0171 #define PAR96_DESCRAM_TAPSH2 12
0172 #define PAR96_DESCRAM_TAPSH3 0
0173 
0174 #define PAR96_SCRAM_TAP1 0x20000 /* X^17 */
0175 #define PAR96_SCRAM_TAPN 0x00021 /* X^0+X^5 */
0176 
0177 /* --------------------------------------------------------------------- */
0178 
0179 static inline void par96_tx(struct net_device *dev, struct baycom_state *bc)
0180 {
0181     int i;
0182     unsigned int data = hdlcdrv_getbits(&bc->hdrv);
0183     struct parport *pp = bc->pdev->port;
0184 
0185     for(i = 0; i < PAR96_BURSTBITS; i++, data >>= 1) {
0186         unsigned char val = PAR97_POWER;
0187         bc->modem.par96.scram = ((bc->modem.par96.scram << 1) |
0188                      (bc->modem.par96.scram & 1));
0189         if (!(data & 1))
0190             bc->modem.par96.scram ^= 1;
0191         if (bc->modem.par96.scram & (PAR96_SCRAM_TAP1 << 1))
0192             bc->modem.par96.scram ^=
0193                 (PAR96_SCRAM_TAPN << 1);
0194         if (bc->modem.par96.scram & (PAR96_SCRAM_TAP1 << 2))
0195             val |= PAR96_TXBIT;
0196         pp->ops->write_data(pp, val);
0197         pp->ops->write_data(pp, val | PAR96_BURST);
0198     }
0199 }
0200 
0201 /* --------------------------------------------------------------------- */
0202 
0203 static inline void par96_rx(struct net_device *dev, struct baycom_state *bc)
0204 {
0205     int i;
0206     unsigned int data, mask, mask2, descx;
0207     struct parport *pp = bc->pdev->port;
0208 
0209     /*
0210      * do receiver; differential decode and descramble on the fly
0211      */
0212     for(data = i = 0; i < PAR96_BURSTBITS; i++) {
0213         bc->modem.par96.descram = (bc->modem.par96.descram << 1);
0214         if (pp->ops->read_status(pp) & PAR96_RXBIT)
0215             bc->modem.par96.descram |= 1;
0216         descx = bc->modem.par96.descram ^
0217             (bc->modem.par96.descram >> 1);
0218         /* now the diff decoded data is inverted in descram */
0219         pp->ops->write_data(pp, PAR97_POWER | PAR96_PTT);
0220         descx ^= ((descx >> PAR96_DESCRAM_TAPSH1) ^
0221               (descx >> PAR96_DESCRAM_TAPSH2));
0222         data >>= 1;
0223         if (!(descx & 1))
0224             data |= 0x8000;
0225         pp->ops->write_data(pp, PAR97_POWER | PAR96_PTT | PAR96_BURST);
0226     }
0227     hdlcdrv_putbits(&bc->hdrv, data);
0228     /*
0229      * do DCD algorithm
0230      */
0231     if (bc->options & BAYCOM_OPTIONS_SOFTDCD) {
0232         bc->modem.par96.dcd_shreg = (bc->modem.par96.dcd_shreg >> 16)
0233             | (data << 16);
0234         /* search for flags and set the dcd counter appropriately */
0235         for(mask = 0x1fe00, mask2 = 0xfc00, i = 0;
0236             i < PAR96_BURSTBITS; i++, mask <<= 1, mask2 <<= 1)
0237             if ((bc->modem.par96.dcd_shreg & mask) == mask2)
0238                 bc->modem.par96.dcd_count = HDLCDRV_MAXFLEN+4;
0239         /* check for abort/noise sequences */
0240         for(mask = 0x1fe00, mask2 = 0x1fe00, i = 0;
0241             i < PAR96_BURSTBITS; i++, mask <<= 1, mask2 <<= 1)
0242             if (((bc->modem.par96.dcd_shreg & mask) == mask2) &&
0243                 (bc->modem.par96.dcd_count >= 0))
0244                 bc->modem.par96.dcd_count -= HDLCDRV_MAXFLEN-10;
0245         /* decrement and set the dcd variable */
0246         if (bc->modem.par96.dcd_count >= 0)
0247             bc->modem.par96.dcd_count -= 2;
0248         hdlcdrv_setdcd(&bc->hdrv, bc->modem.par96.dcd_count > 0);
0249     } else {
0250         hdlcdrv_setdcd(&bc->hdrv, !!(pp->ops->read_status(pp) & PAR96_DCD));
0251     }
0252 }
0253 
0254 /* --------------------------------------------------------------------- */
0255 
0256 static void par96_interrupt(void *dev_id)
0257 {
0258     struct net_device *dev = dev_id;
0259     struct baycom_state *bc = netdev_priv(dev);
0260 
0261     baycom_int_freq(bc);
0262     /*
0263      * check if transmitter active
0264      */
0265     if (hdlcdrv_ptt(&bc->hdrv))
0266         par96_tx(dev, bc);
0267     else {
0268         par96_rx(dev, bc);
0269         if (--bc->modem.arb_divider <= 0) {
0270             bc->modem.arb_divider = 6;
0271             local_irq_enable();
0272             hdlcdrv_arbitrate(dev, &bc->hdrv);
0273         }
0274     }
0275     local_irq_enable();
0276     hdlcdrv_transmitter(dev, &bc->hdrv);
0277     hdlcdrv_receiver(dev, &bc->hdrv);
0278         local_irq_disable();
0279 }
0280 
0281 /* --------------------------------------------------------------------- */
0282 
0283 static void par96_wakeup(void *handle)
0284 {
0285         struct net_device *dev = (struct net_device *)handle;
0286     struct baycom_state *bc = netdev_priv(dev);
0287 
0288     printk(KERN_DEBUG "baycom_par: %s: why am I being woken up?\n", dev->name);
0289     if (!parport_claim(bc->pdev))
0290         printk(KERN_DEBUG "baycom_par: %s: I'm broken.\n", dev->name);
0291 }
0292 
0293 /* --------------------------------------------------------------------- */
0294 
0295 static int par96_open(struct net_device *dev)
0296 {
0297     struct baycom_state *bc = netdev_priv(dev);
0298     struct pardev_cb par_cb;
0299     struct parport *pp;
0300     int i;
0301 
0302     if (!dev || !bc)
0303         return -ENXIO;
0304     pp = parport_find_base(dev->base_addr);
0305     if (!pp) {
0306         printk(KERN_ERR "baycom_par: parport at 0x%lx unknown\n", dev->base_addr);
0307         return -ENXIO;
0308     }
0309     if (pp->irq < 0) {
0310         printk(KERN_ERR "baycom_par: parport at 0x%lx has no irq\n", pp->base);
0311         parport_put_port(pp);
0312         return -ENXIO;
0313     }
0314     if ((~pp->modes) & (PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT)) {
0315         printk(KERN_ERR "baycom_par: parport at 0x%lx cannot be used\n", pp->base);
0316         parport_put_port(pp);
0317         return -ENXIO;
0318     }
0319     memset(&bc->modem, 0, sizeof(bc->modem));
0320     bc->hdrv.par.bitrate = 9600;
0321     memset(&par_cb, 0, sizeof(par_cb));
0322     par_cb.wakeup = par96_wakeup;
0323     par_cb.irq_func = par96_interrupt;
0324     par_cb.private = (void *)dev;
0325     par_cb.flags = PARPORT_DEV_EXCL;
0326     for (i = 0; i < NR_PORTS; i++)
0327         if (baycom_device[i] == dev)
0328             break;
0329 
0330     if (i == NR_PORTS) {
0331         pr_err("%s: no device found\n", bc_drvname);
0332         parport_put_port(pp);
0333         return -ENODEV;
0334     }
0335     bc->pdev = parport_register_dev_model(pp, dev->name, &par_cb, i);
0336     parport_put_port(pp);
0337     if (!bc->pdev) {
0338         printk(KERN_ERR "baycom_par: cannot register parport at 0x%lx\n", dev->base_addr);
0339         return -ENXIO;
0340     }
0341     if (parport_claim(bc->pdev)) {
0342         printk(KERN_ERR "baycom_par: parport at 0x%lx busy\n", pp->base);
0343         parport_unregister_device(bc->pdev);
0344         return -EBUSY;
0345     }
0346     pp = bc->pdev->port;
0347     dev->irq = pp->irq;
0348     pp->ops->data_forward(pp);
0349         bc->hdrv.par.bitrate = 9600;
0350     pp->ops->write_data(pp, PAR96_PTT | PAR97_POWER); /* switch off PTT */
0351     pp->ops->enable_irq(pp);
0352     printk(KERN_INFO "%s: par96 at iobase 0x%lx irq %u options 0x%x\n",
0353            bc_drvname, dev->base_addr, dev->irq, bc->options);
0354     return 0;
0355 }
0356 
0357 /* --------------------------------------------------------------------- */
0358 
0359 static int par96_close(struct net_device *dev)
0360 {
0361     struct baycom_state *bc = netdev_priv(dev);
0362     struct parport *pp;
0363 
0364     if (!dev || !bc)
0365         return -EINVAL;
0366     pp = bc->pdev->port;
0367     /* disable interrupt */
0368     pp->ops->disable_irq(pp);
0369     /* switch off PTT */
0370     pp->ops->write_data(pp, PAR96_PTT | PAR97_POWER);
0371     parport_release(bc->pdev);
0372     parport_unregister_device(bc->pdev);
0373     printk(KERN_INFO "%s: close par96 at iobase 0x%lx irq %u\n",
0374            bc_drvname, dev->base_addr, dev->irq);
0375     return 0;
0376 }
0377 
0378 /* --------------------------------------------------------------------- */
0379 /*
0380  * ===================== hdlcdrv driver interface =========================
0381  */
0382 
0383 static int baycom_ioctl(struct net_device *dev, void __user *data,
0384             struct hdlcdrv_ioctl *hi, int cmd);
0385 
0386 /* --------------------------------------------------------------------- */
0387 
0388 static const struct hdlcdrv_ops par96_ops = {
0389     .drvname = bc_drvname,
0390     .drvinfo = bc_drvinfo,
0391     .open    = par96_open,
0392     .close   = par96_close,
0393     .ioctl   = baycom_ioctl
0394 };
0395 
0396 /* --------------------------------------------------------------------- */
0397 
0398 static int baycom_setmode(struct baycom_state *bc, const char *modestr)
0399 {
0400     if (!strncmp(modestr, "picpar", 6))
0401         bc->options = 0;
0402     else if (!strncmp(modestr, "par96", 5))
0403         bc->options = BAYCOM_OPTIONS_SOFTDCD;
0404     else
0405         bc->options = !!strchr(modestr, '*');
0406     return 0;
0407 }
0408 
0409 /* --------------------------------------------------------------------- */
0410 
0411 static int baycom_ioctl(struct net_device *dev, void __user *data,
0412             struct hdlcdrv_ioctl *hi, int cmd)
0413 {
0414     struct baycom_state *bc;
0415     struct baycom_ioctl bi;
0416 
0417     if (!dev)
0418         return -EINVAL;
0419 
0420     bc = netdev_priv(dev);
0421     BUG_ON(bc->hdrv.magic != HDLCDRV_MAGIC);
0422 
0423     if (cmd != SIOCDEVPRIVATE)
0424         return -ENOIOCTLCMD;
0425     switch (hi->cmd) {
0426     default:
0427         break;
0428 
0429     case HDLCDRVCTL_GETMODE:
0430         strcpy(hi->data.modename, bc->options ? "par96" : "picpar");
0431         if (copy_to_user(data, hi, sizeof(struct hdlcdrv_ioctl)))
0432             return -EFAULT;
0433         return 0;
0434 
0435     case HDLCDRVCTL_SETMODE:
0436         if (netif_running(dev) || !capable(CAP_NET_ADMIN))
0437             return -EACCES;
0438         hi->data.modename[sizeof(hi->data.modename)-1] = '\0';
0439         return baycom_setmode(bc, hi->data.modename);
0440 
0441     case HDLCDRVCTL_MODELIST:
0442         strcpy(hi->data.modename, "par96,picpar");
0443         if (copy_to_user(data, hi, sizeof(struct hdlcdrv_ioctl)))
0444             return -EFAULT;
0445         return 0;
0446 
0447     case HDLCDRVCTL_MODEMPARMASK:
0448         return HDLCDRV_PARMASK_IOBASE;
0449 
0450     }
0451 
0452     if (copy_from_user(&bi, data, sizeof(bi)))
0453         return -EFAULT;
0454     switch (bi.cmd) {
0455     default:
0456         return -ENOIOCTLCMD;
0457 
0458 #ifdef BAYCOM_DEBUG
0459     case BAYCOMCTL_GETDEBUG:
0460         bi.data.dbg.debug1 = bc->hdrv.ptt_keyed;
0461         bi.data.dbg.debug2 = bc->debug_vals.last_intcnt;
0462         bi.data.dbg.debug3 = bc->debug_vals.last_pllcorr;
0463         break;
0464 #endif /* BAYCOM_DEBUG */
0465 
0466     }
0467     if (copy_to_user(data, &bi, sizeof(bi)))
0468         return -EFAULT;
0469     return 0;
0470 
0471 }
0472 
0473 /* --------------------------------------------------------------------- */
0474 
0475 /*
0476  * command line settable parameters
0477  */
0478 static char *mode[NR_PORTS] = { "picpar", };
0479 static int iobase[NR_PORTS] = { 0x378, };
0480 
0481 module_param_array(mode, charp, NULL, 0);
0482 MODULE_PARM_DESC(mode, "baycom operating mode; eg. par96 or picpar");
0483 module_param_hw_array(iobase, int, ioport, NULL, 0);
0484 MODULE_PARM_DESC(iobase, "baycom io base address");
0485 
0486 MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
0487 MODULE_DESCRIPTION("Baycom par96 and picpar amateur radio modem driver");
0488 MODULE_LICENSE("GPL");
0489 
0490 /* --------------------------------------------------------------------- */
0491 
0492 static int baycom_par_probe(struct pardevice *par_dev)
0493 {
0494     struct device_driver *drv = par_dev->dev.driver;
0495     int len = strlen(drv->name);
0496 
0497     if (strncmp(par_dev->name, drv->name, len))
0498         return -ENODEV;
0499 
0500     return 0;
0501 }
0502 
0503 static struct parport_driver baycom_par_driver = {
0504     .name = "bcp",
0505     .probe = baycom_par_probe,
0506     .devmodel = true,
0507 };
0508 
0509 static int __init init_baycompar(void)
0510 {
0511     int i, found = 0, ret;
0512     char set_hw = 1;
0513 
0514     printk(bc_drvinfo);
0515 
0516     ret = parport_register_driver(&baycom_par_driver);
0517     if (ret)
0518         return ret;
0519 
0520     /*
0521      * register net devices
0522      */
0523     for (i = 0; i < NR_PORTS; i++) {
0524         struct net_device *dev;
0525         struct baycom_state *bc;
0526         char ifname[IFNAMSIZ];
0527 
0528         sprintf(ifname, "bcp%d", i);
0529 
0530         if (!mode[i])
0531             set_hw = 0;
0532         if (!set_hw)
0533             iobase[i] = 0;
0534 
0535         dev = hdlcdrv_register(&par96_ops,
0536                        sizeof(struct baycom_state),
0537                        ifname, iobase[i], 0, 0);
0538         if (IS_ERR(dev)) 
0539             break;
0540 
0541         bc = netdev_priv(dev);
0542         if (set_hw && baycom_setmode(bc, mode[i]))
0543             set_hw = 0;
0544         found++;
0545         baycom_device[i] = dev;
0546     }
0547 
0548     if (!found) {
0549         parport_unregister_driver(&baycom_par_driver);
0550         return -ENXIO;
0551     }
0552     return 0;
0553 }
0554 
0555 static void __exit cleanup_baycompar(void)
0556 {
0557     int i;
0558 
0559     for(i = 0; i < NR_PORTS; i++) {
0560         struct net_device *dev = baycom_device[i];
0561 
0562         if (dev)
0563             hdlcdrv_unregister(dev);
0564     }
0565     parport_unregister_driver(&baycom_par_driver);
0566 }
0567 
0568 module_init(init_baycompar);
0569 module_exit(cleanup_baycompar);
0570 
0571 /* --------------------------------------------------------------------- */
0572 
0573 #ifndef MODULE
0574 
0575 /*
0576  * format: baycom_par=io,mode
0577  * mode: par96,picpar
0578  */
0579 
0580 static int __init baycom_par_setup(char *str)
0581 {
0582         static unsigned nr_dev;
0583     int ints[2];
0584 
0585         if (nr_dev >= NR_PORTS)
0586                 return 0;
0587         str = get_options(str, 2, ints);
0588         if (ints[0] < 1)
0589                 return 0;
0590         mode[nr_dev] = str;
0591         iobase[nr_dev] = ints[1];
0592     nr_dev++;
0593     return 1;
0594 }
0595 
0596 __setup("baycom_par=", baycom_par_setup);
0597 
0598 #endif /* MODULE */
0599 /* --------------------------------------------------------------------- */