// SPDX-License-Identifier: GPL-2.0-or-later /*****************************************************************************/ /* * baycom_ser_fdx.c -- baycom ser12 fullduplex radio modem driver. * * Copyright (C) 1996-2000 Thomas Sailer ([email protected]) * * Please note that the GPL allows you to use the driver, NOT the radio. * In order to use the radio, you need a license from the communications * authority of your country. * * Supported modems * * ser12: This is a very simple 1200 baud AFSK modem. The modem consists only * of a modulator/demodulator chip, usually a TI TCM3105. The computer * is responsible for regenerating the receiver bit clock, as well as * for handling the HDLC protocol. The modem connects to a serial port, * hence the name. Since the serial port is not used as an async serial * port, the kernel driver for serial ports cannot be used, and this * driver only supports standard serial hardware (8250, 16450, 16550A) * * This modem usually draws its supply current out of the otherwise unused * TXD pin of the serial port. Thus a contiguous stream of 0x00-bytes * is transmitted to achieve a positive supply voltage. * * hsk: This is a 4800 baud FSK modem, designed for TNC use. It works fine * in 'baycom-mode' :-) In contrast to the TCM3105 modem, power is * externally supplied. So there's no need to provide the 0x00-byte-stream * when receiving or idle, which drastically reduces interrupt load. * * Command line options (insmod command line) * * mode ser# hardware DCD * ser#* software DCD * ser#+ hardware DCD, inverted signal at DCD pin * '#' denotes the baud rate / 100, eg. ser12* is '1200 baud, soft DCD' * iobase base address of the port; common values are 0x3f8, 0x2f8, 0x3e8, 0x2e8 * baud baud rate (between 300 and 4800) * irq interrupt line of the port; common values are 4,3 * * History: * 0.1 26.06.1996 Adapted from baycom.c and made network driver interface * 18.10.1996 Changed to new user space access routines (copy_{to,from}_user) * 0.3 26.04.1997 init code/data tagged * 0.4 08.07.1997 alternative ser12 decoding algorithm (uses delta CTS ints) * 0.5 11.11.1997 ser12/par96 split into separate files * 0.6 24.01.1998 Thorsten Kranzkowski, dl8bcu and Thomas Sailer: * reduced interrupt load in transmit case * reworked receiver * 0.7 03.08.1999 adapt to Linus' new __setup/__initcall * 0.8 10.08.1999 use module_init/module_exit * 0.9 12.02.2000 adapted to softnet driver interface * 0.10 03.07.2000 fix interface name handling */ /*****************************************************************************/ #include <linux/capability.h> #include <linux/module.h> #include <linux/ioport.h> #include <linux/string.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/hdlcdrv.h> #include <linux/baycom.h> #include <linux/jiffies.h> #include <linux/time64.h> #include <linux/uaccess.h> #include <asm/io.h> #include <asm/irq.h> /* --------------------------------------------------------------------- */ #define BAYCOM_DEBUG /* --------------------------------------------------------------------- */ static const char bc_drvname[] = …; static const char bc_drvinfo[] = …; /* --------------------------------------------------------------------- */ #define NR_PORTS … static struct net_device *baycom_device[NR_PORTS]; /* --------------------------------------------------------------------- */ #define RBR(iobase) … #define THR(iobase) … #define IER(iobase) … #define IIR(iobase) … #define FCR(iobase) … #define LCR(iobase) … #define MCR(iobase) … #define LSR(iobase) … #define MSR(iobase) … #define SCR(iobase) … #define DLL(iobase) … #define DLM(iobase) … #define SER12_EXTENT … /* ---------------------------------------------------------------------- */ /* * Information that need to be kept for each board. */ struct baycom_state { … }; /* --------------------------------------------------------------------- */ static inline void baycom_int_freq(struct baycom_state *bc) { … } /* --------------------------------------------------------------------- */ /* * ===================== SER12 specific routines ========================= */ /* --------------------------------------------------------------------- */ static inline void ser12_set_divisor(struct net_device *dev, unsigned int divisor) { … } static __inline__ void ser12_rx(struct net_device *dev, struct baycom_state *bc, struct timespec64 *ts, unsigned char curs) { … } /* --------------------------------------------------------------------- */ static irqreturn_t ser12_interrupt(int irq, void *dev_id) { … } /* --------------------------------------------------------------------- */ enum uart { … }; static const char *uart_str[] = …; static enum uart ser12_check_uart(unsigned int iobase) { … } /* --------------------------------------------------------------------- */ static int ser12_open(struct net_device *dev) { … } /* --------------------------------------------------------------------- */ static int ser12_close(struct net_device *dev) { … } /* --------------------------------------------------------------------- */ /* * ===================== hdlcdrv driver interface ========================= */ /* --------------------------------------------------------------------- */ static int baycom_ioctl(struct net_device *dev, void __user *data, struct hdlcdrv_ioctl *hi, int cmd); /* --------------------------------------------------------------------- */ static const struct hdlcdrv_ops ser12_ops = …; /* --------------------------------------------------------------------- */ static int baycom_setmode(struct baycom_state *bc, const char *modestr) { … } /* --------------------------------------------------------------------- */ static int baycom_ioctl(struct net_device *dev, void __user *data, struct hdlcdrv_ioctl *hi, int cmd) { … } /* --------------------------------------------------------------------- */ /* * command line settable parameters */ static char *mode[NR_PORTS] = …; static int iobase[NR_PORTS] = …; static int irq[NR_PORTS] = …; static int baud[NR_PORTS] = …; module_param_array(…); MODULE_PARM_DESC(…) …; module_param_hw_array(iobase, int, ioport, NULL, 0); MODULE_PARM_DESC(…) …; module_param_hw_array(irq, int, irq, NULL, 0); MODULE_PARM_DESC(…) …; module_param_array(…); MODULE_PARM_DESC(…) …; MODULE_AUTHOR(…) …; MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …; /* --------------------------------------------------------------------- */ static int __init init_baycomserfdx(void) { … } static void __exit cleanup_baycomserfdx(void) { … } module_init(…) …; module_exit(cleanup_baycomserfdx); /* --------------------------------------------------------------------- */ #ifndef MODULE /* * format: baycom_ser_fdx=io,irq,mode * mode: ser# hardware DCD * ser#* software DCD * ser#+ hardware DCD, inverted signal at DCD pin * '#' denotes the baud rate / 100, eg. ser12* is '1200 baud, soft DCD' */ static int __init baycom_ser_fdx_setup(char *str) { … } __setup(…); #endif /* MODULE */ /* --------------------------------------------------------------------- */