Linux-2.6.12-rc2

Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.

Let it rip!
This commit is contained in:
Linus Torvalds
2005-04-16 15:20:36 -07:00
commit 1da177e4c3
17291 changed files with 6718755 additions and 0 deletions

1051
drivers/net/hamradio/6pack.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,191 @@
config MKISS
tristate "Serial port KISS driver"
depends on AX25 && BROKEN_ON_SMP
---help---
KISS is a protocol used for the exchange of data between a computer
and a Terminal Node Controller (a small embedded system commonly
used for networking over AX.25 amateur radio connections; it
connects the computer's serial port with the radio's microphone
input and speaker output).
Although KISS is less advanced than the 6pack protocol, it has
the advantage that it is already supported by most modern TNCs
without the need for a firmware upgrade.
To compile this driver as a module, choose M here: the module
will be called mkiss.
config 6PACK
tristate "Serial port 6PACK driver"
depends on AX25 && BROKEN_ON_SMP
---help---
6pack is a transmission protocol for the data exchange between your
PC and your TNC (the Terminal Node Controller acts as a kind of
modem connecting your computer's serial port to your radio's
microphone input and speaker output). This protocol can be used as
an alternative to KISS for networking over AX.25 amateur radio
connections, but it has some extended functionality.
Note that this driver is still experimental and might cause
problems. For details about the features and the usage of the
driver, read <file:Documentation/networking/6pack.txt>.
To compile this driver as a module, choose M here: the module
will be called 6pack.
config BPQETHER
tristate "BPQ Ethernet driver"
depends on AX25
help
AX.25 is the protocol used for computer communication over amateur
radio. If you say Y here, you will be able to send and receive AX.25
traffic over Ethernet (also called "BPQ AX.25"), which could be
useful if some other computer on your local network has a direct
amateur radio connection.
config DMASCC
tristate "High-speed (DMA) SCC driver for AX.25"
depends on ISA && AX25 && BROKEN_ON_SMP
---help---
This is a driver for high-speed SCC boards, i.e. those supporting
DMA on one port. You usually use those boards to connect your
computer to an amateur radio modem (such as the WA4DSY 56kbps
modem), in order to send and receive AX.25 packet radio network
traffic.
Currently, this driver supports Ottawa PI/PI2, Paccomm/Gracilis
PackeTwin, and S5SCC/DMA boards. They are detected automatically.
If you have one of these cards, say Y here and read the AX25-HOWTO,
available from <http://www.tldp.org/docs.html#howto>.
This driver can operate multiple boards simultaneously. If you
compile it as a module (by saying M instead of Y), it will be called
dmascc. If you don't pass any parameter to the driver, all
possible I/O addresses are probed. This could irritate other devices
that are currently not in use. You may specify the list of addresses
to be probed by "dmascc=addr1,addr2,..." (when compiled into the
kernel image) or "io=addr1,addr2,..." (when loaded as a module). The
network interfaces will be called dmascc0 and dmascc1 for the board
detected first, dmascc2 and dmascc3 for the second one, and so on.
Before you configure each interface with ifconfig, you MUST set
certain parameters, such as channel access timing, clock mode, and
DMA channel. This is accomplished with a small utility program,
dmascc_cfg, available at
<http://cacofonix.nt.tuwien.ac.at/~oe1kib/Linux/>. Please be sure to
get at least version 1.27 of dmascc_cfg, as older versions will not
work with the current driver.
config SCC
tristate "Z8530 SCC driver"
depends on ISA && AX25
---help---
These cards are used to connect your Linux box to an amateur radio
in order to communicate with other computers. If you want to use
this, read <file:Documentation/networking/z8530drv.txt> and the
AX25-HOWTO, available from
<http://www.tldp.org/docs.html#howto>. Also make sure to say Y
to "Amateur Radio AX.25 Level 2" support.
To compile this driver as a module, choose M here: the module
will be called scc.
config SCC_DELAY
bool "additional delay for PA0HZP OptoSCC compatible boards"
depends on SCC
help
Say Y here if you experience problems with the SCC driver not
working properly; please read
<file:Documentation/networking/z8530drv.txt> for details.
If unsure, say N.
config SCC_TRXECHO
bool "support for TRX that feedback the tx signal to rx"
depends on SCC
help
Some transmitters feed the transmitted signal back to the receive
line. Say Y here to foil this by explicitly disabling the receiver
during data transmission.
If in doubt, say Y.
config BAYCOM_SER_FDX
tristate "BAYCOM ser12 fullduplex driver for AX.25"
depends on AX25
select CRC_CCITT
---help---
This is one of two drivers for Baycom style simple amateur radio
modems that connect to a serial interface. The driver supports the
ser12 design in full-duplex mode. In addition, it allows the
baudrate to be set between 300 and 4800 baud (however not all modems
support all baudrates). This is the preferred driver. The next
driver, "BAYCOM ser12 half-duplex driver for AX.25" is the old
driver and still provided in case this driver does not work with
your serial interface chip. To configure the driver, use the sethdlc
utility available in the standard ax25 utilities package. For
information on the modems, see <http://www.baycom.de/> and
<file:Documentation/networking/baycom.txt>.
To compile this driver as a module, choose M here: the module
will be called baycom_ser_fdx. This is recommended.
config BAYCOM_SER_HDX
tristate "BAYCOM ser12 halfduplex driver for AX.25"
depends on AX25
select CRC_CCITT
---help---
This is one of two drivers for Baycom style simple amateur radio
modems that connect to a serial interface. The driver supports the
ser12 design in full-duplex mode. This is the old driver. It is
still provided in case your serial interface chip does not work with
the full-duplex driver. This driver is depreciated. To configure
the driver, use the sethdlc utility available in the standard ax25
utilities package. For information on the modems, see
<http://www.baycom.de/> and
<file:Documentation/networking/baycom.txt>.
To compile this driver as a module, choose M here: the module
will be called baycom_ser_hdx. This is recommended.
config BAYCOM_PAR
tristate "BAYCOM picpar and par96 driver for AX.25"
depends on PARPORT && AX25
select CRC_CCITT
---help---
This is a driver for Baycom style simple amateur radio modems that
connect to a parallel interface. The driver supports the picpar and
par96 designs. To configure the driver, use the sethdlc utility
available in the standard ax25 utilities package. For information on
the modems, see <http://www.baycom.de/> and the file
<file:Documentation/networking/baycom.txt>.
To compile this driver as a module, choose M here: the module
will be called baycom_par. This is recommended.
config BAYCOM_EPP
tristate "BAYCOM epp driver for AX.25"
depends on PARPORT && AX25 && !64BIT
select CRC_CCITT
---help---
This is a driver for Baycom style simple amateur radio modems that
connect to a parallel interface. The driver supports the EPP
designs. To configure the driver, use the sethdlc utility available
in the standard ax25 utilities package. For information on the
modems, see <http://www.baycom.de/> and the file
<file:Documentation/networking/baycom.txt>.
To compile this driver as a module, choose M here: the module
will be called baycom_epp. This is recommended.
config YAM
tristate "YAM driver for AX.25"
depends on AX25
help
The YAM is a modem for packet radio which connects to the serial
port and includes some of the functions of a Terminal Node
Controller. If you have one of those, say Y here.
To compile this driver as a module, choose M here: the module
will be called yam.

View File

@@ -0,0 +1,22 @@
#
# Makefile for the Linux AX.25 and HFMODEM device drivers.
#
#
# 19971130 Moved the amateur radio related network drivers from
# drivers/net/ to drivers/hamradio for easier maintainance.
# Joerg Reuter DL1BKE <jreuter@yaina.de>
#
# 20000806 Rewritten to use lists instead of if-statements.
# Christoph Hellwig <hch@infradead.org>
#
obj-$(CONFIG_DMASCC) += dmascc.o
obj-$(CONFIG_SCC) += scc.o
obj-$(CONFIG_MKISS) += mkiss.o
obj-$(CONFIG_6PACK) += 6pack.o
obj-$(CONFIG_YAM) += yam.o
obj-$(CONFIG_BPQETHER) += bpqether.o
obj-$(CONFIG_BAYCOM_SER_FDX) += baycom_ser_fdx.o hdlcdrv.o
obj-$(CONFIG_BAYCOM_SER_HDX) += baycom_ser_hdx.o hdlcdrv.o
obj-$(CONFIG_BAYCOM_PAR) += baycom_par.o hdlcdrv.o
obj-$(CONFIG_BAYCOM_EPP) += baycom_epp.o hdlcdrv.o

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,576 @@
/*****************************************************************************/
/*
* baycom_par.c -- baycom par96 and picpar radio modem driver.
*
* Copyright (C) 1996-2000 Thomas Sailer (sailer@ife.ee.ethz.ch)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* 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
*
* par96: This is a modem for 9600 baud FSK compatible to the G3RUH standard.
* The modem does all the filtering and regenerates the receiver clock.
* Data is transferred from and to the PC via a shift register.
* The shift register is filled with 16 bits and an interrupt is
* signalled. The PC then empties the shift register in a burst. This
* modem connects to the parallel port, hence the name. The modem
* leaves the implementation of the HDLC protocol and the scrambler
* polynomial to the PC. This modem is no longer available (at least
* from Baycom) and has been replaced by the PICPAR modem (see below).
* You may however still build one from the schematics published in
* cq-DL :-).
*
* picpar: This is a redesign of the par96 modem by Henning Rech, DF9IC. The
* modem is protocol compatible to par96, but uses only three low
* power ICs and can therefore be fed from the parallel port and
* does not require an additional power supply. It features
* built in DCD circuitry. The driver should therefore be configured
* for hardware DCD.
*
*
* Command line options (insmod command line)
*
* mode driver mode string. Valid choices are par96 and picpar.
* iobase base address of the port; common values are 0x378, 0x278, 0x3bc
*
*
* 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 split into separate files for ser12/par96
* 0.6 03.08.1999 adapt to Linus' new __setup/__initcall
* removed some pre-2.2 kernel compatibility cruft
* 0.7 10.08.1999 Check if parport can do SPP and is safe to access during interrupt contexts
* 0.8 12.02.2000 adapted to softnet driver interface
* removed direct parport access, uses parport driver methods
* 0.9 03.07.2000 fix interface name handling
*/
/*****************************************************************************/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/in.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/hdlcdrv.h>
#include <linux/baycom.h>
#include <linux/parport.h>
#include <linux/bitops.h>
#include <asm/bug.h>
#include <asm/system.h>
#include <asm/uaccess.h>
/* --------------------------------------------------------------------- */
#define BAYCOM_DEBUG
/*
* modem options; bit mask
*/
#define BAYCOM_OPTIONS_SOFTDCD 1
/* --------------------------------------------------------------------- */
static const char bc_drvname[] = "baycom_par";
static const char bc_drvinfo[] = KERN_INFO "baycom_par: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n"
KERN_INFO "baycom_par: version 0.9 compiled " __TIME__ " " __DATE__ "\n";
/* --------------------------------------------------------------------- */
#define NR_PORTS 4
static struct net_device *baycom_device[NR_PORTS];
/* --------------------------------------------------------------------- */
#define PAR96_BURSTBITS 16
#define PAR96_BURST 4
#define PAR96_PTT 2
#define PAR96_TXBIT 1
#define PAR96_ACK 0x40
#define PAR96_RXBIT 0x20
#define PAR96_DCD 0x10
#define PAR97_POWER 0xf8
/* ---------------------------------------------------------------------- */
/*
* Information that need to be kept for each board.
*/
struct baycom_state {
struct hdlcdrv_state hdrv;
struct pardevice *pdev;
unsigned int options;
struct modem_state {
short arb_divider;
unsigned char flags;
unsigned int shreg;
struct modem_state_par96 {
int dcd_count;
unsigned int dcd_shreg;
unsigned long descram;
unsigned long scram;
} par96;
} modem;
#ifdef BAYCOM_DEBUG
struct debug_vals {
unsigned long last_jiffies;
unsigned cur_intcnt;
unsigned last_intcnt;
int cur_pllcorr;
int last_pllcorr;
} debug_vals;
#endif /* BAYCOM_DEBUG */
};
/* --------------------------------------------------------------------- */
static void __inline__ baycom_int_freq(struct baycom_state *bc)
{
#ifdef BAYCOM_DEBUG
unsigned long cur_jiffies = jiffies;
/*
* measure the interrupt frequency
*/
bc->debug_vals.cur_intcnt++;
if ((cur_jiffies - bc->debug_vals.last_jiffies) >= HZ) {
bc->debug_vals.last_jiffies = cur_jiffies;
bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt;
bc->debug_vals.cur_intcnt = 0;
bc->debug_vals.last_pllcorr = bc->debug_vals.cur_pllcorr;
bc->debug_vals.cur_pllcorr = 0;
}
#endif /* BAYCOM_DEBUG */
}
/* --------------------------------------------------------------------- */
/*
* ===================== PAR96 specific routines =========================
*/
#define PAR96_DESCRAM_TAP1 0x20000
#define PAR96_DESCRAM_TAP2 0x01000
#define PAR96_DESCRAM_TAP3 0x00001
#define PAR96_DESCRAM_TAPSH1 17
#define PAR96_DESCRAM_TAPSH2 12
#define PAR96_DESCRAM_TAPSH3 0
#define PAR96_SCRAM_TAP1 0x20000 /* X^17 */
#define PAR96_SCRAM_TAPN 0x00021 /* X^0+X^5 */
/* --------------------------------------------------------------------- */
static __inline__ void par96_tx(struct net_device *dev, struct baycom_state *bc)
{
int i;
unsigned int data = hdlcdrv_getbits(&bc->hdrv);
struct parport *pp = bc->pdev->port;
for(i = 0; i < PAR96_BURSTBITS; i++, data >>= 1) {
unsigned char val = PAR97_POWER;
bc->modem.par96.scram = ((bc->modem.par96.scram << 1) |
(bc->modem.par96.scram & 1));
if (!(data & 1))
bc->modem.par96.scram ^= 1;
if (bc->modem.par96.scram & (PAR96_SCRAM_TAP1 << 1))
bc->modem.par96.scram ^=
(PAR96_SCRAM_TAPN << 1);
if (bc->modem.par96.scram & (PAR96_SCRAM_TAP1 << 2))
val |= PAR96_TXBIT;
pp->ops->write_data(pp, val);
pp->ops->write_data(pp, val | PAR96_BURST);
}
}
/* --------------------------------------------------------------------- */
static __inline__ void par96_rx(struct net_device *dev, struct baycom_state *bc)
{
int i;
unsigned int data, mask, mask2, descx;
struct parport *pp = bc->pdev->port;
/*
* do receiver; differential decode and descramble on the fly
*/
for(data = i = 0; i < PAR96_BURSTBITS; i++) {
bc->modem.par96.descram = (bc->modem.par96.descram << 1);
if (pp->ops->read_status(pp) & PAR96_RXBIT)
bc->modem.par96.descram |= 1;
descx = bc->modem.par96.descram ^
(bc->modem.par96.descram >> 1);
/* now the diff decoded data is inverted in descram */
pp->ops->write_data(pp, PAR97_POWER | PAR96_PTT);
descx ^= ((descx >> PAR96_DESCRAM_TAPSH1) ^
(descx >> PAR96_DESCRAM_TAPSH2));
data >>= 1;
if (!(descx & 1))
data |= 0x8000;
pp->ops->write_data(pp, PAR97_POWER | PAR96_PTT | PAR96_BURST);
}
hdlcdrv_putbits(&bc->hdrv, data);
/*
* do DCD algorithm
*/
if (bc->options & BAYCOM_OPTIONS_SOFTDCD) {
bc->modem.par96.dcd_shreg = (bc->modem.par96.dcd_shreg >> 16)
| (data << 16);
/* search for flags and set the dcd counter appropriately */
for(mask = 0x1fe00, mask2 = 0xfc00, i = 0;
i < PAR96_BURSTBITS; i++, mask <<= 1, mask2 <<= 1)
if ((bc->modem.par96.dcd_shreg & mask) == mask2)
bc->modem.par96.dcd_count = HDLCDRV_MAXFLEN+4;
/* check for abort/noise sequences */
for(mask = 0x1fe00, mask2 = 0x1fe00, i = 0;
i < PAR96_BURSTBITS; i++, mask <<= 1, mask2 <<= 1)
if (((bc->modem.par96.dcd_shreg & mask) == mask2) &&
(bc->modem.par96.dcd_count >= 0))
bc->modem.par96.dcd_count -= HDLCDRV_MAXFLEN-10;
/* decrement and set the dcd variable */
if (bc->modem.par96.dcd_count >= 0)
bc->modem.par96.dcd_count -= 2;
hdlcdrv_setdcd(&bc->hdrv, bc->modem.par96.dcd_count > 0);
} else {
hdlcdrv_setdcd(&bc->hdrv, !!(pp->ops->read_status(pp) & PAR96_DCD));
}
}
/* --------------------------------------------------------------------- */
static void par96_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = (struct net_device *)dev_id;
struct baycom_state *bc = netdev_priv(dev);
baycom_int_freq(bc);
/*
* check if transmitter active
*/
if (hdlcdrv_ptt(&bc->hdrv))
par96_tx(dev, bc);
else {
par96_rx(dev, bc);
if (--bc->modem.arb_divider <= 0) {
bc->modem.arb_divider = 6;
local_irq_enable();
hdlcdrv_arbitrate(dev, &bc->hdrv);
}
}
local_irq_enable();
hdlcdrv_transmitter(dev, &bc->hdrv);
hdlcdrv_receiver(dev, &bc->hdrv);
local_irq_disable();
}
/* --------------------------------------------------------------------- */
static void par96_wakeup(void *handle)
{
struct net_device *dev = (struct net_device *)handle;
struct baycom_state *bc = netdev_priv(dev);
printk(KERN_DEBUG "baycom_par: %s: why am I being woken up?\n", dev->name);
if (!parport_claim(bc->pdev))
printk(KERN_DEBUG "baycom_par: %s: I'm broken.\n", dev->name);
}
/* --------------------------------------------------------------------- */
static int par96_open(struct net_device *dev)
{
struct baycom_state *bc = netdev_priv(dev);
struct parport *pp;
if (!dev || !bc)
return -ENXIO;
pp = parport_find_base(dev->base_addr);
if (!pp) {
printk(KERN_ERR "baycom_par: parport at 0x%lx unknown\n", dev->base_addr);
return -ENXIO;
}
if (pp->irq < 0) {
printk(KERN_ERR "baycom_par: parport at 0x%lx has no irq\n", pp->base);
parport_put_port(pp);
return -ENXIO;
}
if ((~pp->modes) & (PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT)) {
printk(KERN_ERR "baycom_par: parport at 0x%lx cannot be used\n", pp->base);
parport_put_port(pp);
return -ENXIO;
}
memset(&bc->modem, 0, sizeof(bc->modem));
bc->hdrv.par.bitrate = 9600;
bc->pdev = parport_register_device(pp, dev->name, NULL, par96_wakeup,
par96_interrupt, PARPORT_DEV_EXCL, dev);
parport_put_port(pp);
if (!bc->pdev) {
printk(KERN_ERR "baycom_par: cannot register parport at 0x%lx\n", dev->base_addr);
return -ENXIO;
}
if (parport_claim(bc->pdev)) {
printk(KERN_ERR "baycom_par: parport at 0x%lx busy\n", pp->base);
parport_unregister_device(bc->pdev);
return -EBUSY;
}
pp = bc->pdev->port;
dev->irq = pp->irq;
pp->ops->data_forward(pp);
bc->hdrv.par.bitrate = 9600;
pp->ops->write_data(pp, PAR96_PTT | PAR97_POWER); /* switch off PTT */
pp->ops->enable_irq(pp);
printk(KERN_INFO "%s: par96 at iobase 0x%lx irq %u options 0x%x\n",
bc_drvname, dev->base_addr, dev->irq, bc->options);
return 0;
}
/* --------------------------------------------------------------------- */
static int par96_close(struct net_device *dev)
{
struct baycom_state *bc = netdev_priv(dev);
struct parport *pp;
if (!dev || !bc)
return -EINVAL;
pp = bc->pdev->port;
/* disable interrupt */
pp->ops->disable_irq(pp);
/* switch off PTT */
pp->ops->write_data(pp, PAR96_PTT | PAR97_POWER);
parport_release(bc->pdev);
parport_unregister_device(bc->pdev);
printk(KERN_INFO "%s: close par96 at iobase 0x%lx irq %u\n",
bc_drvname, dev->base_addr, dev->irq);
return 0;
}
/* --------------------------------------------------------------------- */
/*
* ===================== hdlcdrv driver interface =========================
*/
static int baycom_ioctl(struct net_device *dev, struct ifreq *ifr,
struct hdlcdrv_ioctl *hi, int cmd);
/* --------------------------------------------------------------------- */
static struct hdlcdrv_ops par96_ops = {
.drvname = bc_drvname,
.drvinfo = bc_drvinfo,
.open = par96_open,
.close = par96_close,
.ioctl = baycom_ioctl
};
/* --------------------------------------------------------------------- */
static int baycom_setmode(struct baycom_state *bc, const char *modestr)
{
if (!strncmp(modestr, "picpar", 6))
bc->options = 0;
else if (!strncmp(modestr, "par96", 5))
bc->options = BAYCOM_OPTIONS_SOFTDCD;
else
bc->options = !!strchr(modestr, '*');
return 0;
}
/* --------------------------------------------------------------------- */
static int baycom_ioctl(struct net_device *dev, struct ifreq *ifr,
struct hdlcdrv_ioctl *hi, int cmd)
{
struct baycom_state *bc;
struct baycom_ioctl bi;
if (!dev)
return -EINVAL;
bc = netdev_priv(dev);
BUG_ON(bc->hdrv.magic != HDLCDRV_MAGIC);
if (cmd != SIOCDEVPRIVATE)
return -ENOIOCTLCMD;
switch (hi->cmd) {
default:
break;
case HDLCDRVCTL_GETMODE:
strcpy(hi->data.modename, bc->options ? "par96" : "picpar");
if (copy_to_user(ifr->ifr_data, hi, sizeof(struct hdlcdrv_ioctl)))
return -EFAULT;
return 0;
case HDLCDRVCTL_SETMODE:
if (netif_running(dev) || !capable(CAP_NET_ADMIN))
return -EACCES;
hi->data.modename[sizeof(hi->data.modename)-1] = '\0';
return baycom_setmode(bc, hi->data.modename);
case HDLCDRVCTL_MODELIST:
strcpy(hi->data.modename, "par96,picpar");
if (copy_to_user(ifr->ifr_data, hi, sizeof(struct hdlcdrv_ioctl)))
return -EFAULT;
return 0;
case HDLCDRVCTL_MODEMPARMASK:
return HDLCDRV_PARMASK_IOBASE;
}
if (copy_from_user(&bi, ifr->ifr_data, sizeof(bi)))
return -EFAULT;
switch (bi.cmd) {
default:
return -ENOIOCTLCMD;
#ifdef BAYCOM_DEBUG
case BAYCOMCTL_GETDEBUG:
bi.data.dbg.debug1 = bc->hdrv.ptt_keyed;
bi.data.dbg.debug2 = bc->debug_vals.last_intcnt;
bi.data.dbg.debug3 = bc->debug_vals.last_pllcorr;
break;
#endif /* BAYCOM_DEBUG */
}
if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi)))
return -EFAULT;
return 0;
}
/* --------------------------------------------------------------------- */
/*
* command line settable parameters
*/
static const char *mode[NR_PORTS] = { "picpar", };
static int iobase[NR_PORTS] = { 0x378, };
module_param_array(mode, charp, NULL, 0);
MODULE_PARM_DESC(mode, "baycom operating mode; eg. par96 or picpar");
module_param_array(iobase, int, NULL, 0);
MODULE_PARM_DESC(iobase, "baycom io base address");
MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
MODULE_DESCRIPTION("Baycom par96 and picpar amateur radio modem driver");
MODULE_LICENSE("GPL");
/* --------------------------------------------------------------------- */
static int __init init_baycompar(void)
{
int i, found = 0;
char set_hw = 1;
printk(bc_drvinfo);
/*
* register net devices
*/
for (i = 0; i < NR_PORTS; i++) {
struct net_device *dev;
struct baycom_state *bc;
char ifname[IFNAMSIZ];
sprintf(ifname, "bcp%d", i);
if (!mode[i])
set_hw = 0;
if (!set_hw)
iobase[i] = 0;
dev = hdlcdrv_register(&par96_ops,
sizeof(struct baycom_state),
ifname, iobase[i], 0, 0);
if (IS_ERR(dev))
break;
bc = netdev_priv(dev);
if (set_hw && baycom_setmode(bc, mode[i]))
set_hw = 0;
found++;
baycom_device[i] = dev;
}
if (!found)
return -ENXIO;
return 0;
}
static void __exit cleanup_baycompar(void)
{
int i;
for(i = 0; i < NR_PORTS; i++) {
struct net_device *dev = baycom_device[i];
if (dev)
hdlcdrv_unregister(dev);
}
}
module_init(init_baycompar);
module_exit(cleanup_baycompar);
/* --------------------------------------------------------------------- */
#ifndef MODULE
/*
* format: baycom_par=io,mode
* mode: par96,picpar
*/
static int __init baycom_par_setup(char *str)
{
static unsigned nr_dev;
int ints[2];
if (nr_dev >= NR_PORTS)
return 0;
str = get_options(str, 2, ints);
if (ints[0] < 1)
return 0;
mode[nr_dev] = str;
iobase[nr_dev] = ints[1];
nr_dev++;
return 1;
}
__setup("baycom_par=", baycom_par_setup);
#endif /* MODULE */
/* --------------------------------------------------------------------- */

View File

@@ -0,0 +1,704 @@
/*****************************************************************************/
/*
* baycom_ser_fdx.c -- baycom ser12 fullduplex radio modem driver.
*
* Copyright (C) 1996-2000 Thomas Sailer (sailer@ife.ee.ethz.ch)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* 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 contignuous 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/module.h>
#include <linux/ioport.h>
#include <linux/string.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/hdlcdrv.h>
#include <linux/baycom.h>
/* --------------------------------------------------------------------- */
#define BAYCOM_DEBUG
/* --------------------------------------------------------------------- */
static const char bc_drvname[] = "baycom_ser_fdx";
static const char bc_drvinfo[] = KERN_INFO "baycom_ser_fdx: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n"
KERN_INFO "baycom_ser_fdx: version 0.10 compiled " __TIME__ " " __DATE__ "\n";
/* --------------------------------------------------------------------- */
#define NR_PORTS 4
static struct net_device *baycom_device[NR_PORTS];
/* --------------------------------------------------------------------- */
#define RBR(iobase) (iobase+0)
#define THR(iobase) (iobase+0)
#define IER(iobase) (iobase+1)
#define IIR(iobase) (iobase+2)
#define FCR(iobase) (iobase+2)
#define LCR(iobase) (iobase+3)
#define MCR(iobase) (iobase+4)
#define LSR(iobase) (iobase+5)
#define MSR(iobase) (iobase+6)
#define SCR(iobase) (iobase+7)
#define DLL(iobase) (iobase+0)
#define DLM(iobase) (iobase+1)
#define SER12_EXTENT 8
/* ---------------------------------------------------------------------- */
/*
* Information that need to be kept for each board.
*/
struct baycom_state {
struct hdlcdrv_state hdrv;
unsigned int baud, baud_us, baud_arbdiv, baud_uartdiv, baud_dcdtimeout;
int opt_dcd;
struct modem_state {
unsigned char flags;
unsigned char ptt;
unsigned int shreg;
struct modem_state_ser12 {
unsigned char tx_bit;
unsigned char last_rxbit;
int dcd_sum0, dcd_sum1, dcd_sum2;
int dcd_time;
unsigned int pll_time;
unsigned int txshreg;
} ser12;
} modem;
#ifdef BAYCOM_DEBUG
struct debug_vals {
unsigned long last_jiffies;
unsigned cur_intcnt;
unsigned last_intcnt;
int cur_pllcorr;
int last_pllcorr;
} debug_vals;
#endif /* BAYCOM_DEBUG */
};
/* --------------------------------------------------------------------- */
static inline void baycom_int_freq(struct baycom_state *bc)
{
#ifdef BAYCOM_DEBUG
unsigned long cur_jiffies = jiffies;
/*
* measure the interrupt frequency
*/
bc->debug_vals.cur_intcnt++;
if ((cur_jiffies - bc->debug_vals.last_jiffies) >= HZ) {
bc->debug_vals.last_jiffies = cur_jiffies;
bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt;
bc->debug_vals.cur_intcnt = 0;
bc->debug_vals.last_pllcorr = bc->debug_vals.cur_pllcorr;
bc->debug_vals.cur_pllcorr = 0;
}
#endif /* BAYCOM_DEBUG */
}
/* --------------------------------------------------------------------- */
/*
* ===================== SER12 specific routines =========================
*/
/* --------------------------------------------------------------------- */
static inline void ser12_set_divisor(struct net_device *dev,
unsigned int divisor)
{
outb(0x81, LCR(dev->base_addr)); /* DLAB = 1 */
outb(divisor, DLL(dev->base_addr));
outb(divisor >> 8, DLM(dev->base_addr));
outb(0x01, LCR(dev->base_addr)); /* word length = 6 */
/*
* make sure the next interrupt is generated;
* 0 must be used to power the modem; the modem draws its
* power from the TxD line
*/
outb(0x00, THR(dev->base_addr));
/*
* it is important not to set the divider while transmitting;
* this reportedly makes some UARTs generating interrupts
* in the hundredthousands per second region
* Reported by: Ignacio.Arenaza@studi.epfl.ch (Ignacio Arenaza Nuno)
*/
}
/* --------------------------------------------------------------------- */
#if 0
static inline unsigned int hweight16(unsigned int w)
__attribute__ ((unused));
static inline unsigned int hweight8(unsigned int w)
__attribute__ ((unused));
static inline unsigned int hweight16(unsigned int w)
{
unsigned short res = (w & 0x5555) + ((w >> 1) & 0x5555);
res = (res & 0x3333) + ((res >> 2) & 0x3333);
res = (res & 0x0F0F) + ((res >> 4) & 0x0F0F);
return (res & 0x00FF) + ((res >> 8) & 0x00FF);
}
static inline unsigned int hweight8(unsigned int w)
{
unsigned short res = (w & 0x55) + ((w >> 1) & 0x55);
res = (res & 0x33) + ((res >> 2) & 0x33);
return (res & 0x0F) + ((res >> 4) & 0x0F);
}
#endif
/* --------------------------------------------------------------------- */
static __inline__ void ser12_rx(struct net_device *dev, struct baycom_state *bc, struct timeval *tv, unsigned char curs)
{
int timediff;
int bdus8 = bc->baud_us >> 3;
int bdus4 = bc->baud_us >> 2;
int bdus2 = bc->baud_us >> 1;
timediff = 1000000 + tv->tv_usec - bc->modem.ser12.pll_time;
while (timediff >= 500000)
timediff -= 1000000;
while (timediff >= bdus2) {
timediff -= bc->baud_us;
bc->modem.ser12.pll_time += bc->baud_us;
bc->modem.ser12.dcd_time--;
/* first check if there is room to add a bit */
if (bc->modem.shreg & 1) {
hdlcdrv_putbits(&bc->hdrv, (bc->modem.shreg >> 1) ^ 0xffff);
bc->modem.shreg = 0x10000;
}
/* add a one bit */
bc->modem.shreg >>= 1;
}
if (bc->modem.ser12.dcd_time <= 0) {
if (!bc->opt_dcd)
hdlcdrv_setdcd(&bc->hdrv, (bc->modem.ser12.dcd_sum0 +
bc->modem.ser12.dcd_sum1 +
bc->modem.ser12.dcd_sum2) < 0);
bc->modem.ser12.dcd_sum2 = bc->modem.ser12.dcd_sum1;
bc->modem.ser12.dcd_sum1 = bc->modem.ser12.dcd_sum0;
bc->modem.ser12.dcd_sum0 = 2; /* slight bias */
bc->modem.ser12.dcd_time += 120;
}
if (bc->modem.ser12.last_rxbit != curs) {
bc->modem.ser12.last_rxbit = curs;
bc->modem.shreg |= 0x10000;
/* adjust the PLL */
if (timediff > 0)
bc->modem.ser12.pll_time += bdus8;
else
bc->modem.ser12.pll_time += 1000000 - bdus8;
/* update DCD */
if (abs(timediff) > bdus4)
bc->modem.ser12.dcd_sum0 += 4;
else
bc->modem.ser12.dcd_sum0--;
#ifdef BAYCOM_DEBUG
bc->debug_vals.cur_pllcorr = timediff;
#endif /* BAYCOM_DEBUG */
}
while (bc->modem.ser12.pll_time >= 1000000)
bc->modem.ser12.pll_time -= 1000000;
}
/* --------------------------------------------------------------------- */
static irqreturn_t ser12_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = (struct net_device *)dev_id;
struct baycom_state *bc = netdev_priv(dev);
struct timeval tv;
unsigned char iir, msr;
unsigned int txcount = 0;
if (!bc || bc->hdrv.magic != HDLCDRV_MAGIC)
return IRQ_NONE;
/* fast way out for shared irq */
if ((iir = inb(IIR(dev->base_addr))) & 1)
return IRQ_NONE;
/* get current time */
do_gettimeofday(&tv);
msr = inb(MSR(dev->base_addr));
/* delta DCD */
if ((msr & 8) && bc->opt_dcd)
hdlcdrv_setdcd(&bc->hdrv, !((msr ^ bc->opt_dcd) & 0x80));
do {
switch (iir & 6) {
case 6:
inb(LSR(dev->base_addr));
break;
case 4:
inb(RBR(dev->base_addr));
break;
case 2:
/*
* make sure the next interrupt is generated;
* 0 must be used to power the modem; the modem draws its
* power from the TxD line
*/
outb(0x00, THR(dev->base_addr));
baycom_int_freq(bc);
txcount++;
/*
* first output the last bit (!) then call HDLC transmitter,
* since this may take quite long
*/
if (bc->modem.ptt)
outb(0x0e | (!!bc->modem.ser12.tx_bit), MCR(dev->base_addr));
else
outb(0x0d, MCR(dev->base_addr)); /* transmitter off */
break;
default:
msr = inb(MSR(dev->base_addr));
/* delta DCD */
if ((msr & 8) && bc->opt_dcd)
hdlcdrv_setdcd(&bc->hdrv, !((msr ^ bc->opt_dcd) & 0x80));
break;
}
iir = inb(IIR(dev->base_addr));
} while (!(iir & 1));
ser12_rx(dev, bc, &tv, msr & 0x10); /* CTS */
if (bc->modem.ptt && txcount) {
if (bc->modem.ser12.txshreg <= 1) {
bc->modem.ser12.txshreg = 0x10000 | hdlcdrv_getbits(&bc->hdrv);
if (!hdlcdrv_ptt(&bc->hdrv)) {
ser12_set_divisor(dev, 115200/100/8);
bc->modem.ptt = 0;
goto end_transmit;
}
}
bc->modem.ser12.tx_bit = !(bc->modem.ser12.tx_bit ^ (bc->modem.ser12.txshreg & 1));
bc->modem.ser12.txshreg >>= 1;
}
end_transmit:
local_irq_enable();
if (!bc->modem.ptt && txcount) {
hdlcdrv_arbitrate(dev, &bc->hdrv);
if (hdlcdrv_ptt(&bc->hdrv)) {
ser12_set_divisor(dev, bc->baud_uartdiv);
bc->modem.ser12.txshreg = 1;
bc->modem.ptt = 1;
}
}
hdlcdrv_transmitter(dev, &bc->hdrv);
hdlcdrv_receiver(dev, &bc->hdrv);
local_irq_disable();
return IRQ_HANDLED;
}
/* --------------------------------------------------------------------- */
enum uart { c_uart_unknown, c_uart_8250,
c_uart_16450, c_uart_16550, c_uart_16550A};
static const char *uart_str[] = {
"unknown", "8250", "16450", "16550", "16550A"
};
static enum uart ser12_check_uart(unsigned int iobase)
{
unsigned char b1,b2,b3;
enum uart u;
enum uart uart_tab[] =
{ c_uart_16450, c_uart_unknown, c_uart_16550, c_uart_16550A };
b1 = inb(MCR(iobase));
outb(b1 | 0x10, MCR(iobase)); /* loopback mode */
b2 = inb(MSR(iobase));
outb(0x1a, MCR(iobase));
b3 = inb(MSR(iobase)) & 0xf0;
outb(b1, MCR(iobase)); /* restore old values */
outb(b2, MSR(iobase));
if (b3 != 0x90)
return c_uart_unknown;
inb(RBR(iobase));
inb(RBR(iobase));
outb(0x01, FCR(iobase)); /* enable FIFOs */
u = uart_tab[(inb(IIR(iobase)) >> 6) & 3];
if (u == c_uart_16450) {
outb(0x5a, SCR(iobase));
b1 = inb(SCR(iobase));
outb(0xa5, SCR(iobase));
b2 = inb(SCR(iobase));
if ((b1 != 0x5a) || (b2 != 0xa5))
u = c_uart_8250;
}
return u;
}
/* --------------------------------------------------------------------- */
static int ser12_open(struct net_device *dev)
{
struct baycom_state *bc = netdev_priv(dev);
enum uart u;
if (!dev || !bc)
return -ENXIO;
if (!dev->base_addr || dev->base_addr > 0x1000-SER12_EXTENT ||
dev->irq < 2 || dev->irq > 15)
return -ENXIO;
if (bc->baud < 300 || bc->baud > 4800)
return -EINVAL;
if (!request_region(dev->base_addr, SER12_EXTENT, "baycom_ser_fdx")) {
printk(KERN_WARNING "BAYCOM_SER_FSX: I/O port 0x%04lx busy \n",
dev->base_addr);
return -EACCES;
}
memset(&bc->modem, 0, sizeof(bc->modem));
bc->hdrv.par.bitrate = bc->baud;
bc->baud_us = 1000000/bc->baud;
bc->baud_uartdiv = (115200/8)/bc->baud;
if ((u = ser12_check_uart(dev->base_addr)) == c_uart_unknown){
release_region(dev->base_addr, SER12_EXTENT);
return -EIO;
}
outb(0, FCR(dev->base_addr)); /* disable FIFOs */
outb(0x0d, MCR(dev->base_addr));
outb(0, IER(dev->base_addr));
if (request_irq(dev->irq, ser12_interrupt, SA_INTERRUPT | SA_SHIRQ,
"baycom_ser_fdx", dev)) {
release_region(dev->base_addr, SER12_EXTENT);
return -EBUSY;
}
/*
* set the SIO to 6 Bits/character; during receive,
* the baud rate is set to produce 100 ints/sec
* to feed the channel arbitration process,
* during transmit to baud ints/sec to run
* the transmitter
*/
ser12_set_divisor(dev, 115200/100/8);
/*
* enable transmitter empty interrupt and modem status interrupt
*/
outb(0x0a, IER(dev->base_addr));
/*
* make sure the next interrupt is generated;
* 0 must be used to power the modem; the modem draws its
* power from the TxD line
*/
outb(0x00, THR(dev->base_addr));
hdlcdrv_setdcd(&bc->hdrv, 0);
printk(KERN_INFO "%s: ser_fdx at iobase 0x%lx irq %u baud %u uart %s\n",
bc_drvname, dev->base_addr, dev->irq, bc->baud, uart_str[u]);
return 0;
}
/* --------------------------------------------------------------------- */
static int ser12_close(struct net_device *dev)
{
struct baycom_state *bc = netdev_priv(dev);
if (!dev || !bc)
return -EINVAL;
/*
* disable interrupts
*/
outb(0, IER(dev->base_addr));
outb(1, MCR(dev->base_addr));
free_irq(dev->irq, dev);
release_region(dev->base_addr, SER12_EXTENT);
printk(KERN_INFO "%s: close ser_fdx at iobase 0x%lx irq %u\n",
bc_drvname, dev->base_addr, dev->irq);
return 0;
}
/* --------------------------------------------------------------------- */
/*
* ===================== hdlcdrv driver interface =========================
*/
/* --------------------------------------------------------------------- */
static int baycom_ioctl(struct net_device *dev, struct ifreq *ifr,
struct hdlcdrv_ioctl *hi, int cmd);
/* --------------------------------------------------------------------- */
static struct hdlcdrv_ops ser12_ops = {
.drvname = bc_drvname,
.drvinfo = bc_drvinfo,
.open = ser12_open,
.close = ser12_close,
.ioctl = baycom_ioctl,
};
/* --------------------------------------------------------------------- */
static int baycom_setmode(struct baycom_state *bc, const char *modestr)
{
unsigned int baud;
if (!strncmp(modestr, "ser", 3)) {
baud = simple_strtoul(modestr+3, NULL, 10);
if (baud >= 3 && baud <= 48)
bc->baud = baud*100;
}
if (strchr(modestr, '*'))
bc->opt_dcd = 0;
else if (strchr(modestr, '+'))
bc->opt_dcd = -1;
else
bc->opt_dcd = 1;
return 0;
}
/* --------------------------------------------------------------------- */
static int baycom_ioctl(struct net_device *dev, struct ifreq *ifr,
struct hdlcdrv_ioctl *hi, int cmd)
{
struct baycom_state *bc;
struct baycom_ioctl bi;
if (!dev)
return -EINVAL;
bc = netdev_priv(dev);
BUG_ON(bc->hdrv.magic != HDLCDRV_MAGIC);
if (cmd != SIOCDEVPRIVATE)
return -ENOIOCTLCMD;
switch (hi->cmd) {
default:
break;
case HDLCDRVCTL_GETMODE:
sprintf(hi->data.modename, "ser%u", bc->baud / 100);
if (bc->opt_dcd <= 0)
strcat(hi->data.modename, (!bc->opt_dcd) ? "*" : "+");
if (copy_to_user(ifr->ifr_data, hi, sizeof(struct hdlcdrv_ioctl)))
return -EFAULT;
return 0;
case HDLCDRVCTL_SETMODE:
if (netif_running(dev) || !capable(CAP_NET_ADMIN))
return -EACCES;
hi->data.modename[sizeof(hi->data.modename)-1] = '\0';
return baycom_setmode(bc, hi->data.modename);
case HDLCDRVCTL_MODELIST:
strcpy(hi->data.modename, "ser12,ser3,ser24");
if (copy_to_user(ifr->ifr_data, hi, sizeof(struct hdlcdrv_ioctl)))
return -EFAULT;
return 0;
case HDLCDRVCTL_MODEMPARMASK:
return HDLCDRV_PARMASK_IOBASE | HDLCDRV_PARMASK_IRQ;
}
if (copy_from_user(&bi, ifr->ifr_data, sizeof(bi)))
return -EFAULT;
switch (bi.cmd) {
default:
return -ENOIOCTLCMD;
#ifdef BAYCOM_DEBUG
case BAYCOMCTL_GETDEBUG:
bi.data.dbg.debug1 = bc->hdrv.ptt_keyed;
bi.data.dbg.debug2 = bc->debug_vals.last_intcnt;
bi.data.dbg.debug3 = bc->debug_vals.last_pllcorr;
break;
#endif /* BAYCOM_DEBUG */
}
if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi)))
return -EFAULT;
return 0;
}
/* --------------------------------------------------------------------- */
/*
* command line settable parameters
*/
static char *mode[NR_PORTS] = { "ser12*", };
static int iobase[NR_PORTS] = { 0x3f8, };
static int irq[NR_PORTS] = { 4, };
static int baud[NR_PORTS] = { [0 ... NR_PORTS-1] = 1200 };
module_param_array(mode, charp, NULL, 0);
MODULE_PARM_DESC(mode, "baycom operating mode; * for software DCD");
module_param_array(iobase, int, NULL, 0);
MODULE_PARM_DESC(iobase, "baycom io base address");
module_param_array(irq, int, NULL, 0);
MODULE_PARM_DESC(irq, "baycom irq number");
module_param_array(baud, int, NULL, 0);
MODULE_PARM_DESC(baud, "baycom baud rate (300 to 4800)");
MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
MODULE_DESCRIPTION("Baycom ser12 full duplex amateur radio modem driver");
MODULE_LICENSE("GPL");
/* --------------------------------------------------------------------- */
static int __init init_baycomserfdx(void)
{
int i, found = 0;
char set_hw = 1;
printk(bc_drvinfo);
/*
* register net devices
*/
for (i = 0; i < NR_PORTS; i++) {
struct net_device *dev;
struct baycom_state *bc;
char ifname[IFNAMSIZ];
sprintf(ifname, "bcsf%d", i);
if (!mode[i])
set_hw = 0;
if (!set_hw)
iobase[i] = irq[i] = 0;
dev = hdlcdrv_register(&ser12_ops,
sizeof(struct baycom_state),
ifname, iobase[i], irq[i], 0);
if (IS_ERR(dev))
break;
bc = netdev_priv(dev);
if (set_hw && baycom_setmode(bc, mode[i]))
set_hw = 0;
bc->baud = baud[i];
found++;
baycom_device[i] = dev;
}
if (!found)
return -ENXIO;
return 0;
}
static void __exit cleanup_baycomserfdx(void)
{
int i;
for(i = 0; i < NR_PORTS; i++) {
struct net_device *dev = baycom_device[i];
if (dev)
hdlcdrv_unregister(dev);
}
}
module_init(init_baycomserfdx);
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)
{
static unsigned nr_dev;
int ints[4];
if (nr_dev >= NR_PORTS)
return 0;
str = get_options(str, 4, ints);
if (ints[0] < 2)
return 0;
mode[nr_dev] = str;
iobase[nr_dev] = ints[1];
irq[nr_dev] = ints[2];
if (ints[0] >= 3)
baud[nr_dev] = ints[3];
nr_dev++;
return 1;
}
__setup("baycom_ser_fdx=", baycom_ser_fdx_setup);
#endif /* MODULE */
/* --------------------------------------------------------------------- */

View File

@@ -0,0 +1,740 @@
/*****************************************************************************/
/*
* baycom_ser_hdx.c -- baycom ser12 halfduplex radio modem driver.
*
* Copyright (C) 1996-2000 Thomas Sailer (sailer@ife.ee.ethz.ch)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* 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)
*
*
* Command line options (insmod command line)
*
* mode ser12 hardware DCD
* ser12* software DCD
* ser12@ hardware/software DCD, i.e. no explicit DCD signal but hardware
* mutes audio input to the modem
* ser12+ hardware DCD, inverted signal at DCD pin
* iobase base address of the port; common values are 0x3f8, 0x2f8, 0x3e8, 0x2e8
* 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 14.04.1998 cleanups
* 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/module.h>
#include <linux/ioport.h>
#include <linux/string.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/hdlcdrv.h>
#include <linux/baycom.h>
/* --------------------------------------------------------------------- */
#define BAYCOM_DEBUG
/* --------------------------------------------------------------------- */
static const char bc_drvname[] = "baycom_ser_hdx";
static const char bc_drvinfo[] = KERN_INFO "baycom_ser_hdx: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n"
KERN_INFO "baycom_ser_hdx: version 0.10 compiled " __TIME__ " " __DATE__ "\n";
/* --------------------------------------------------------------------- */
#define NR_PORTS 4
static struct net_device *baycom_device[NR_PORTS];
/* --------------------------------------------------------------------- */
#define RBR(iobase) (iobase+0)
#define THR(iobase) (iobase+0)
#define IER(iobase) (iobase+1)
#define IIR(iobase) (iobase+2)
#define FCR(iobase) (iobase+2)
#define LCR(iobase) (iobase+3)
#define MCR(iobase) (iobase+4)
#define LSR(iobase) (iobase+5)
#define MSR(iobase) (iobase+6)
#define SCR(iobase) (iobase+7)
#define DLL(iobase) (iobase+0)
#define DLM(iobase) (iobase+1)
#define SER12_EXTENT 8
/* ---------------------------------------------------------------------- */
/*
* Information that need to be kept for each board.
*/
struct baycom_state {
struct hdlcdrv_state hdrv;
int opt_dcd;
struct modem_state {
short arb_divider;
unsigned char flags;
unsigned int shreg;
struct modem_state_ser12 {
unsigned char tx_bit;
int dcd_sum0, dcd_sum1, dcd_sum2;
unsigned char last_sample;
unsigned char last_rxbit;
unsigned int dcd_shreg;
unsigned int dcd_time;
unsigned int bit_pll;
unsigned char interm_sample;
} ser12;
} modem;
#ifdef BAYCOM_DEBUG
struct debug_vals {
unsigned long last_jiffies;
unsigned cur_intcnt;
unsigned last_intcnt;
int cur_pllcorr;
int last_pllcorr;
} debug_vals;
#endif /* BAYCOM_DEBUG */
};
/* --------------------------------------------------------------------- */
static inline void baycom_int_freq(struct baycom_state *bc)
{
#ifdef BAYCOM_DEBUG
unsigned long cur_jiffies = jiffies;
/*
* measure the interrupt frequency
*/
bc->debug_vals.cur_intcnt++;
if ((cur_jiffies - bc->debug_vals.last_jiffies) >= HZ) {
bc->debug_vals.last_jiffies = cur_jiffies;
bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt;
bc->debug_vals.cur_intcnt = 0;
bc->debug_vals.last_pllcorr = bc->debug_vals.cur_pllcorr;
bc->debug_vals.cur_pllcorr = 0;
}
#endif /* BAYCOM_DEBUG */
}
/* --------------------------------------------------------------------- */
/*
* ===================== SER12 specific routines =========================
*/
static inline void ser12_set_divisor(struct net_device *dev,
unsigned char divisor)
{
outb(0x81, LCR(dev->base_addr)); /* DLAB = 1 */
outb(divisor, DLL(dev->base_addr));
outb(0, DLM(dev->base_addr));
outb(0x01, LCR(dev->base_addr)); /* word length = 6 */
/*
* make sure the next interrupt is generated;
* 0 must be used to power the modem; the modem draws its
* power from the TxD line
*/
outb(0x00, THR(dev->base_addr));
/*
* it is important not to set the divider while transmitting;
* this reportedly makes some UARTs generating interrupts
* in the hundredthousands per second region
* Reported by: Ignacio.Arenaza@studi.epfl.ch (Ignacio Arenaza Nuno)
*/
}
/* --------------------------------------------------------------------- */
/*
* must call the TX arbitrator every 10ms
*/
#define SER12_ARB_DIVIDER(bc) (bc->opt_dcd ? 24 : 36)
#define SER12_DCD_INTERVAL(bc) (bc->opt_dcd ? 12 : 240)
static inline void ser12_tx(struct net_device *dev, struct baycom_state *bc)
{
/* one interrupt per channel bit */
ser12_set_divisor(dev, 12);
/*
* first output the last bit (!) then call HDLC transmitter,
* since this may take quite long
*/
outb(0x0e | (!!bc->modem.ser12.tx_bit), MCR(dev->base_addr));
if (bc->modem.shreg <= 1)
bc->modem.shreg = 0x10000 | hdlcdrv_getbits(&bc->hdrv);
bc->modem.ser12.tx_bit = !(bc->modem.ser12.tx_bit ^
(bc->modem.shreg & 1));
bc->modem.shreg >>= 1;
}
/* --------------------------------------------------------------------- */
static inline void ser12_rx(struct net_device *dev, struct baycom_state *bc)
{
unsigned char cur_s;
/*
* do demodulator
*/
cur_s = inb(MSR(dev->base_addr)) & 0x10; /* the CTS line */
hdlcdrv_channelbit(&bc->hdrv, cur_s);
bc->modem.ser12.dcd_shreg = (bc->modem.ser12.dcd_shreg << 1) |
(cur_s != bc->modem.ser12.last_sample);
bc->modem.ser12.last_sample = cur_s;
if(bc->modem.ser12.dcd_shreg & 1) {
if (!bc->opt_dcd) {
unsigned int dcdspos, dcdsneg;
dcdspos = dcdsneg = 0;
dcdspos += ((bc->modem.ser12.dcd_shreg >> 1) & 1);
if (!(bc->modem.ser12.dcd_shreg & 0x7ffffffe))
dcdspos += 2;
dcdsneg += ((bc->modem.ser12.dcd_shreg >> 2) & 1);
dcdsneg += ((bc->modem.ser12.dcd_shreg >> 3) & 1);
dcdsneg += ((bc->modem.ser12.dcd_shreg >> 4) & 1);
bc->modem.ser12.dcd_sum0 += 16*dcdspos - dcdsneg;
} else
bc->modem.ser12.dcd_sum0--;
}
if(!bc->modem.ser12.dcd_time) {
hdlcdrv_setdcd(&bc->hdrv, (bc->modem.ser12.dcd_sum0 +
bc->modem.ser12.dcd_sum1 +
bc->modem.ser12.dcd_sum2) < 0);
bc->modem.ser12.dcd_sum2 = bc->modem.ser12.dcd_sum1;
bc->modem.ser12.dcd_sum1 = bc->modem.ser12.dcd_sum0;
/* offset to ensure DCD off on silent input */
bc->modem.ser12.dcd_sum0 = 2;
bc->modem.ser12.dcd_time = SER12_DCD_INTERVAL(bc);
}
bc->modem.ser12.dcd_time--;
if (!bc->opt_dcd) {
/*
* PLL code for the improved software DCD algorithm
*/
if (bc->modem.ser12.interm_sample) {
/*
* intermediate sample; set timing correction to normal
*/
ser12_set_divisor(dev, 4);
} else {
/*
* do PLL correction and call HDLC receiver
*/
switch (bc->modem.ser12.dcd_shreg & 7) {
case 1: /* transition too late */
ser12_set_divisor(dev, 5);
#ifdef BAYCOM_DEBUG
bc->debug_vals.cur_pllcorr++;
#endif /* BAYCOM_DEBUG */
break;
case 4: /* transition too early */
ser12_set_divisor(dev, 3);
#ifdef BAYCOM_DEBUG
bc->debug_vals.cur_pllcorr--;
#endif /* BAYCOM_DEBUG */
break;
default:
ser12_set_divisor(dev, 4);
break;
}
bc->modem.shreg >>= 1;
if (bc->modem.ser12.last_sample ==
bc->modem.ser12.last_rxbit)
bc->modem.shreg |= 0x10000;
bc->modem.ser12.last_rxbit =
bc->modem.ser12.last_sample;
}
if (++bc->modem.ser12.interm_sample >= 3)
bc->modem.ser12.interm_sample = 0;
/*
* DCD stuff
*/
if (bc->modem.ser12.dcd_shreg & 1) {
unsigned int dcdspos, dcdsneg;
dcdspos = dcdsneg = 0;
dcdspos += ((bc->modem.ser12.dcd_shreg >> 1) & 1);
dcdspos += (!(bc->modem.ser12.dcd_shreg & 0x7ffffffe))
<< 1;
dcdsneg += ((bc->modem.ser12.dcd_shreg >> 2) & 1);
dcdsneg += ((bc->modem.ser12.dcd_shreg >> 3) & 1);
dcdsneg += ((bc->modem.ser12.dcd_shreg >> 4) & 1);
bc->modem.ser12.dcd_sum0 += 16*dcdspos - dcdsneg;
}
} else {
/*
* PLL algorithm for the hardware squelch DCD algorithm
*/
if (bc->modem.ser12.interm_sample) {
/*
* intermediate sample; set timing correction to normal
*/
ser12_set_divisor(dev, 6);
} else {
/*
* do PLL correction and call HDLC receiver
*/
switch (bc->modem.ser12.dcd_shreg & 3) {
case 1: /* transition too late */
ser12_set_divisor(dev, 7);
#ifdef BAYCOM_DEBUG
bc->debug_vals.cur_pllcorr++;
#endif /* BAYCOM_DEBUG */
break;
case 2: /* transition too early */
ser12_set_divisor(dev, 5);
#ifdef BAYCOM_DEBUG
bc->debug_vals.cur_pllcorr--;
#endif /* BAYCOM_DEBUG */
break;
default:
ser12_set_divisor(dev, 6);
break;
}
bc->modem.shreg >>= 1;
if (bc->modem.ser12.last_sample ==
bc->modem.ser12.last_rxbit)
bc->modem.shreg |= 0x10000;
bc->modem.ser12.last_rxbit =
bc->modem.ser12.last_sample;
}
bc->modem.ser12.interm_sample = !bc->modem.ser12.interm_sample;
/*
* DCD stuff
*/
bc->modem.ser12.dcd_sum0 -= (bc->modem.ser12.dcd_shreg & 1);
}
outb(0x0d, MCR(dev->base_addr)); /* transmitter off */
if (bc->modem.shreg & 1) {
hdlcdrv_putbits(&bc->hdrv, bc->modem.shreg >> 1);
bc->modem.shreg = 0x10000;
}
if(!bc->modem.ser12.dcd_time) {
if (bc->opt_dcd & 1)
hdlcdrv_setdcd(&bc->hdrv, !((inb(MSR(dev->base_addr)) ^ bc->opt_dcd) & 0x80));
else
hdlcdrv_setdcd(&bc->hdrv, (bc->modem.ser12.dcd_sum0 +
bc->modem.ser12.dcd_sum1 +
bc->modem.ser12.dcd_sum2) < 0);
bc->modem.ser12.dcd_sum2 = bc->modem.ser12.dcd_sum1;
bc->modem.ser12.dcd_sum1 = bc->modem.ser12.dcd_sum0;
/* offset to ensure DCD off on silent input */
bc->modem.ser12.dcd_sum0 = 2;
bc->modem.ser12.dcd_time = SER12_DCD_INTERVAL(bc);
}
bc->modem.ser12.dcd_time--;
}
/* --------------------------------------------------------------------- */
static irqreturn_t ser12_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = (struct net_device *)dev_id;
struct baycom_state *bc = netdev_priv(dev);
unsigned char iir;
if (!dev || !bc || bc->hdrv.magic != HDLCDRV_MAGIC)
return IRQ_NONE;
/* fast way out */
if ((iir = inb(IIR(dev->base_addr))) & 1)
return IRQ_NONE;
baycom_int_freq(bc);
do {
switch (iir & 6) {
case 6:
inb(LSR(dev->base_addr));
break;
case 4:
inb(RBR(dev->base_addr));
break;
case 2:
/*
* check if transmitter active
*/
if (hdlcdrv_ptt(&bc->hdrv))
ser12_tx(dev, bc);
else {
ser12_rx(dev, bc);
bc->modem.arb_divider--;
}
outb(0x00, THR(dev->base_addr));
break;
default:
inb(MSR(dev->base_addr));
break;
}
iir = inb(IIR(dev->base_addr));
} while (!(iir & 1));
if (bc->modem.arb_divider <= 0) {
bc->modem.arb_divider = SER12_ARB_DIVIDER(bc);
local_irq_enable();
hdlcdrv_arbitrate(dev, &bc->hdrv);
}
local_irq_enable();
hdlcdrv_transmitter(dev, &bc->hdrv);
hdlcdrv_receiver(dev, &bc->hdrv);
local_irq_disable();
return IRQ_HANDLED;
}
/* --------------------------------------------------------------------- */
enum uart { c_uart_unknown, c_uart_8250,
c_uart_16450, c_uart_16550, c_uart_16550A};
static const char *uart_str[] = {
"unknown", "8250", "16450", "16550", "16550A"
};
static enum uart ser12_check_uart(unsigned int iobase)
{
unsigned char b1,b2,b3;
enum uart u;
enum uart uart_tab[] =
{ c_uart_16450, c_uart_unknown, c_uart_16550, c_uart_16550A };
b1 = inb(MCR(iobase));
outb(b1 | 0x10, MCR(iobase)); /* loopback mode */
b2 = inb(MSR(iobase));
outb(0x1a, MCR(iobase));
b3 = inb(MSR(iobase)) & 0xf0;
outb(b1, MCR(iobase)); /* restore old values */
outb(b2, MSR(iobase));
if (b3 != 0x90)
return c_uart_unknown;
inb(RBR(iobase));
inb(RBR(iobase));
outb(0x01, FCR(iobase)); /* enable FIFOs */
u = uart_tab[(inb(IIR(iobase)) >> 6) & 3];
if (u == c_uart_16450) {
outb(0x5a, SCR(iobase));
b1 = inb(SCR(iobase));
outb(0xa5, SCR(iobase));
b2 = inb(SCR(iobase));
if ((b1 != 0x5a) || (b2 != 0xa5))
u = c_uart_8250;
}
return u;
}
/* --------------------------------------------------------------------- */
static int ser12_open(struct net_device *dev)
{
struct baycom_state *bc = netdev_priv(dev);
enum uart u;
if (!dev || !bc)
return -ENXIO;
if (!dev->base_addr || dev->base_addr > 0x1000-SER12_EXTENT ||
dev->irq < 2 || dev->irq > 15)
return -ENXIO;
if (!request_region(dev->base_addr, SER12_EXTENT, "baycom_ser12"))
return -EACCES;
memset(&bc->modem, 0, sizeof(bc->modem));
bc->hdrv.par.bitrate = 1200;
if ((u = ser12_check_uart(dev->base_addr)) == c_uart_unknown) {
release_region(dev->base_addr, SER12_EXTENT);
return -EIO;
}
outb(0, FCR(dev->base_addr)); /* disable FIFOs */
outb(0x0d, MCR(dev->base_addr));
outb(0, IER(dev->base_addr));
if (request_irq(dev->irq, ser12_interrupt, SA_INTERRUPT | SA_SHIRQ,
"baycom_ser12", dev)) {
release_region(dev->base_addr, SER12_EXTENT);
return -EBUSY;
}
/*
* enable transmitter empty interrupt
*/
outb(2, IER(dev->base_addr));
/*
* set the SIO to 6 Bits/character and 19200 or 28800 baud, so that
* we get exactly (hopefully) 2 or 3 interrupts per radio symbol,
* depending on the usage of the software DCD routine
*/
ser12_set_divisor(dev, bc->opt_dcd ? 6 : 4);
printk(KERN_INFO "%s: ser12 at iobase 0x%lx irq %u uart %s\n",
bc_drvname, dev->base_addr, dev->irq, uart_str[u]);
return 0;
}
/* --------------------------------------------------------------------- */
static int ser12_close(struct net_device *dev)
{
struct baycom_state *bc = netdev_priv(dev);
if (!dev || !bc)
return -EINVAL;
/*
* disable interrupts
*/
outb(0, IER(dev->base_addr));
outb(1, MCR(dev->base_addr));
free_irq(dev->irq, dev);
release_region(dev->base_addr, SER12_EXTENT);
printk(KERN_INFO "%s: close ser12 at iobase 0x%lx irq %u\n",
bc_drvname, dev->base_addr, dev->irq);
return 0;
}
/* --------------------------------------------------------------------- */
/*
* ===================== hdlcdrv driver interface =========================
*/
/* --------------------------------------------------------------------- */
static int baycom_ioctl(struct net_device *dev, struct ifreq *ifr,
struct hdlcdrv_ioctl *hi, int cmd);
/* --------------------------------------------------------------------- */
static struct hdlcdrv_ops ser12_ops = {
.drvname = bc_drvname,
.drvinfo = bc_drvinfo,
.open = ser12_open,
.close = ser12_close,
.ioctl = baycom_ioctl,
};
/* --------------------------------------------------------------------- */
static int baycom_setmode(struct baycom_state *bc, const char *modestr)
{
if (strchr(modestr, '*'))
bc->opt_dcd = 0;
else if (strchr(modestr, '+'))
bc->opt_dcd = -1;
else if (strchr(modestr, '@'))
bc->opt_dcd = -2;
else
bc->opt_dcd = 1;
return 0;
}
/* --------------------------------------------------------------------- */
static int baycom_ioctl(struct net_device *dev, struct ifreq *ifr,
struct hdlcdrv_ioctl *hi, int cmd)
{
struct baycom_state *bc;
struct baycom_ioctl bi;
if (!dev)
return -EINVAL;
bc = netdev_priv(dev);
BUG_ON(bc->hdrv.magic != HDLCDRV_MAGIC);
if (cmd != SIOCDEVPRIVATE)
return -ENOIOCTLCMD;
switch (hi->cmd) {
default:
break;
case HDLCDRVCTL_GETMODE:
strcpy(hi->data.modename, "ser12");
if (bc->opt_dcd <= 0)
strcat(hi->data.modename, (!bc->opt_dcd) ? "*" : (bc->opt_dcd == -2) ? "@" : "+");
if (copy_to_user(ifr->ifr_data, hi, sizeof(struct hdlcdrv_ioctl)))
return -EFAULT;
return 0;
case HDLCDRVCTL_SETMODE:
if (netif_running(dev) || !capable(CAP_NET_ADMIN))
return -EACCES;
hi->data.modename[sizeof(hi->data.modename)-1] = '\0';
return baycom_setmode(bc, hi->data.modename);
case HDLCDRVCTL_MODELIST:
strcpy(hi->data.modename, "ser12");
if (copy_to_user(ifr->ifr_data, hi, sizeof(struct hdlcdrv_ioctl)))
return -EFAULT;
return 0;
case HDLCDRVCTL_MODEMPARMASK:
return HDLCDRV_PARMASK_IOBASE | HDLCDRV_PARMASK_IRQ;
}
if (copy_from_user(&bi, ifr->ifr_data, sizeof(bi)))
return -EFAULT;
switch (bi.cmd) {
default:
return -ENOIOCTLCMD;
#ifdef BAYCOM_DEBUG
case BAYCOMCTL_GETDEBUG:
bi.data.dbg.debug1 = bc->hdrv.ptt_keyed;
bi.data.dbg.debug2 = bc->debug_vals.last_intcnt;
bi.data.dbg.debug3 = bc->debug_vals.last_pllcorr;
break;
#endif /* BAYCOM_DEBUG */
}
if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi)))
return -EFAULT;
return 0;
}
/* --------------------------------------------------------------------- */
/*
* command line settable parameters
*/
static char *mode[NR_PORTS] = { "ser12*", };
static int iobase[NR_PORTS] = { 0x3f8, };
static int irq[NR_PORTS] = { 4, };
module_param_array(mode, charp, NULL, 0);
MODULE_PARM_DESC(mode, "baycom operating mode; * for software DCD");
module_param_array(iobase, int, NULL, 0);
MODULE_PARM_DESC(iobase, "baycom io base address");
module_param_array(irq, int, NULL, 0);
MODULE_PARM_DESC(irq, "baycom irq number");
MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
MODULE_DESCRIPTION("Baycom ser12 half duplex amateur radio modem driver");
MODULE_LICENSE("GPL");
/* --------------------------------------------------------------------- */
static int __init init_baycomserhdx(void)
{
int i, found = 0;
char set_hw = 1;
printk(bc_drvinfo);
/*
* register net devices
*/
for (i = 0; i < NR_PORTS; i++) {
struct net_device *dev;
struct baycom_state *bc;
char ifname[IFNAMSIZ];
sprintf(ifname, "bcsh%d", i);
if (!mode[i])
set_hw = 0;
if (!set_hw)
iobase[i] = irq[i] = 0;
dev = hdlcdrv_register(&ser12_ops,
sizeof(struct baycom_state),
ifname, iobase[i], irq[i], 0);
if (IS_ERR(dev))
break;
bc = netdev_priv(dev);
if (set_hw && baycom_setmode(bc, mode[i]))
set_hw = 0;
found++;
baycom_device[i] = dev;
}
if (!found)
return -ENXIO;
return 0;
}
static void __exit cleanup_baycomserhdx(void)
{
int i;
for(i = 0; i < NR_PORTS; i++) {
struct net_device *dev = baycom_device[i];
if (dev)
hdlcdrv_unregister(dev);
}
}
module_init(init_baycomserhdx);
module_exit(cleanup_baycomserhdx);
/* --------------------------------------------------------------------- */
#ifndef MODULE
/*
* format: baycom_ser_hdx=io,irq,mode
* mode: ser12 hardware DCD
* ser12* software DCD
* ser12@ hardware/software DCD, i.e. no explicit DCD signal but hardware
* mutes audio input to the modem
* ser12+ hardware DCD, inverted signal at DCD pin
*/
static int __init baycom_ser_hdx_setup(char *str)
{
static unsigned nr_dev;
int ints[3];
if (nr_dev >= NR_PORTS)
return 0;
str = get_options(str, 3, ints);
if (ints[0] < 2)
return 0;
mode[nr_dev] = str;
iobase[nr_dev] = ints[1];
irq[nr_dev] = ints[2];
nr_dev++;
return 1;
}
__setup("baycom_ser_hdx=", baycom_ser_hdx_setup);
#endif /* MODULE */
/* --------------------------------------------------------------------- */

View File

@@ -0,0 +1,643 @@
/*
* G8BPQ compatible "AX.25 via ethernet" driver release 004
*
* This code REQUIRES 2.0.0 or higher/ NET3.029
*
* This module:
* This module is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* This is a "pseudo" network driver to allow AX.25 over Ethernet
* using G8BPQ encapsulation. It has been extracted from the protocol
* implementation because
*
* - things got unreadable within the protocol stack
* - to cure the protocol stack from "feature-ism"
* - a protocol implementation shouldn't need to know on
* which hardware it is running
* - user-level programs like the AX.25 utilities shouldn't
* need to know about the hardware.
* - IP over ethernet encapsulated AX.25 was impossible
* - rxecho.c did not work
* - to have room for extensions
* - it just deserves to "live" as an own driver
*
* This driver can use any ethernet destination address, and can be
* limited to accept frames from one dedicated ethernet card only.
*
* Note that the driver sets up the BPQ devices automagically on
* startup or (if started before the "insmod" of an ethernet device)
* on "ifconfig up". It hopefully will remove the BPQ on "rmmod"ing
* the ethernet device (in fact: as soon as another ethernet or bpq
* device gets "ifconfig"ured).
*
* I have heard that several people are thinking of experiments
* with highspeed packet radio using existing ethernet cards.
* Well, this driver is prepared for this purpose, just add
* your tx key control and a txdelay / tailtime algorithm,
* probably some buffering, and /voila/...
*
* History
* BPQ 001 Joerg(DL1BKE) Extracted BPQ code from AX.25
* protocol stack and added my own
* yet existing patches
* BPQ 002 Joerg(DL1BKE) Scan network device list on
* startup.
* BPQ 003 Joerg(DL1BKE) Ethernet destination address
* and accepted source address
* can be configured by an ioctl()
* call.
* Fixed to match Linux networking
* changes - 2.1.15.
* BPQ 004 Joerg(DL1BKE) Fixed to not lock up on ifconfig.
*/
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/net.h>
#include <net/ax25.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <linux/skbuff.h>
#include <net/sock.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/notifier.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/netfilter.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/rtnetlink.h>
#include <net/ip.h>
#include <net/arp.h>
#include <linux/bpqether.h>
static char banner[] __initdata = KERN_INFO "AX.25: bpqether driver version 004\n";
static unsigned char ax25_bcast[AX25_ADDR_LEN] =
{'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1};
static unsigned char ax25_defaddr[AX25_ADDR_LEN] =
{'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1};
static char bcast_addr[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
static char bpq_eth_addr[6];
static int bpq_rcv(struct sk_buff *, struct net_device *, struct packet_type *);
static int bpq_device_event(struct notifier_block *, unsigned long, void *);
static const char *bpq_print_ethaddr(const unsigned char *);
static struct packet_type bpq_packet_type = {
.type = __constant_htons(ETH_P_BPQ),
.func = bpq_rcv,
};
static struct notifier_block bpq_dev_notifier = {
.notifier_call =bpq_device_event,
};
struct bpqdev {
struct list_head bpq_list; /* list of bpq devices chain */
struct net_device *ethdev; /* link to ethernet device */
struct net_device *axdev; /* bpq device (bpq#) */
struct net_device_stats stats; /* some statistics */
char dest_addr[6]; /* ether destination address */
char acpt_addr[6]; /* accept ether frames from this address only */
};
static LIST_HEAD(bpq_devices);
/* ------------------------------------------------------------------------ */
/*
* Get the ethernet device for a BPQ device
*/
static inline struct net_device *bpq_get_ether_dev(struct net_device *dev)
{
struct bpqdev *bpq = netdev_priv(dev);
return bpq ? bpq->ethdev : NULL;
}
/*
* Get the BPQ device for the ethernet device
*/
static inline struct net_device *bpq_get_ax25_dev(struct net_device *dev)
{
struct bpqdev *bpq;
list_for_each_entry(bpq, &bpq_devices, bpq_list) {
if (bpq->ethdev == dev)
return bpq->axdev;
}
return NULL;
}
static inline int dev_is_ethdev(struct net_device *dev)
{
return (
dev->type == ARPHRD_ETHER
&& strncmp(dev->name, "dummy", 5)
);
}
/* ------------------------------------------------------------------------ */
/*
* Receive an AX.25 frame via an ethernet interface.
*/
static int bpq_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype)
{
int len;
char * ptr;
struct ethhdr *eth;
struct bpqdev *bpq;
if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
return NET_RX_DROP;
if (!pskb_may_pull(skb, sizeof(struct ethhdr)))
goto drop;
rcu_read_lock();
dev = bpq_get_ax25_dev(dev);
if (dev == NULL || !netif_running(dev))
goto drop_unlock;
/*
* if we want to accept frames from just one ethernet device
* we check the source address of the sender.
*/
bpq = netdev_priv(dev);
eth = eth_hdr(skb);
if (!(bpq->acpt_addr[0] & 0x01) &&
memcmp(eth->h_source, bpq->acpt_addr, ETH_ALEN))
goto drop_unlock;
if (skb_cow(skb, sizeof(struct ethhdr)))
goto drop_unlock;
len = skb->data[0] + skb->data[1] * 256 - 5;
skb_pull(skb, 2); /* Remove the length bytes */
skb_trim(skb, len); /* Set the length of the data */
bpq->stats.rx_packets++;
bpq->stats.rx_bytes += len;
ptr = skb_push(skb, 1);
*ptr = 0;
skb->dev = dev;
skb->protocol = htons(ETH_P_AX25);
skb->mac.raw = skb->data;
skb->pkt_type = PACKET_HOST;
netif_rx(skb);
dev->last_rx = jiffies;
unlock:
rcu_read_unlock();
return 0;
drop_unlock:
kfree_skb(skb);
goto unlock;
drop:
kfree_skb(skb);
return 0;
}
/*
* Send an AX.25 frame via an ethernet interface
*/
static int bpq_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct sk_buff *newskb;
unsigned char *ptr;
struct bpqdev *bpq;
int size;
/*
* Just to be *really* sure not to send anything if the interface
* is down, the ethernet device may have gone.
*/
if (!netif_running(dev)) {
kfree_skb(skb);
return -ENODEV;
}
skb_pull(skb, 1);
size = skb->len;
/*
* The AX.25 code leaves enough room for the ethernet header, but
* sendto() does not.
*/
if (skb_headroom(skb) < AX25_BPQ_HEADER_LEN) { /* Ough! */
if ((newskb = skb_realloc_headroom(skb, AX25_BPQ_HEADER_LEN)) == NULL) {
printk(KERN_WARNING "bpqether: out of memory\n");
kfree_skb(skb);
return -ENOMEM;
}
if (skb->sk != NULL)
skb_set_owner_w(newskb, skb->sk);
kfree_skb(skb);
skb = newskb;
}
skb->protocol = htons(ETH_P_AX25);
ptr = skb_push(skb, 2);
*ptr++ = (size + 5) % 256;
*ptr++ = (size + 5) / 256;
bpq = netdev_priv(dev);
if ((dev = bpq_get_ether_dev(dev)) == NULL) {
bpq->stats.tx_dropped++;
kfree_skb(skb);
return -ENODEV;
}
skb->dev = dev;
skb->nh.raw = skb->data;
dev->hard_header(skb, dev, ETH_P_BPQ, bpq->dest_addr, NULL, 0);
bpq->stats.tx_packets++;
bpq->stats.tx_bytes+=skb->len;
dev_queue_xmit(skb);
netif_wake_queue(dev);
return 0;
}
/*
* Statistics
*/
static struct net_device_stats *bpq_get_stats(struct net_device *dev)
{
struct bpqdev *bpq = netdev_priv(dev);
return &bpq->stats;
}
/*
* Set AX.25 callsign
*/
static int bpq_set_mac_address(struct net_device *dev, void *addr)
{
struct sockaddr *sa = (struct sockaddr *)addr;
memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
return 0;
}
/* Ioctl commands
*
* SIOCSBPQETHOPT reserved for enhancements
* SIOCSBPQETHADDR set the destination and accepted
* source ethernet address (broadcast
* or multicast: accept all)
*/
static int bpq_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
struct bpq_ethaddr __user *ethaddr = ifr->ifr_data;
struct bpqdev *bpq = netdev_priv(dev);
struct bpq_req req;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
switch (cmd) {
case SIOCSBPQETHOPT:
if (copy_from_user(&req, ifr->ifr_data, sizeof(struct bpq_req)))
return -EFAULT;
switch (req.cmd) {
case SIOCGBPQETHPARAM:
case SIOCSBPQETHPARAM:
default:
return -EINVAL;
}
break;
case SIOCSBPQETHADDR:
if (copy_from_user(bpq->dest_addr, ethaddr->destination, ETH_ALEN))
return -EFAULT;
if (copy_from_user(bpq->acpt_addr, ethaddr->accept, ETH_ALEN))
return -EFAULT;
break;
default:
return -EINVAL;
}
return 0;
}
/*
* open/close a device
*/
static int bpq_open(struct net_device *dev)
{
netif_start_queue(dev);
return 0;
}
static int bpq_close(struct net_device *dev)
{
netif_stop_queue(dev);
return 0;
}
/* ------------------------------------------------------------------------ */
/*
* Proc filesystem
*/
static const char * bpq_print_ethaddr(const unsigned char *e)
{
static char buf[18];
sprintf(buf, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
e[0], e[1], e[2], e[3], e[4], e[5]);
return buf;
}
static void *bpq_seq_start(struct seq_file *seq, loff_t *pos)
{
int i = 1;
struct bpqdev *bpqdev;
rcu_read_lock();
if (*pos == 0)
return SEQ_START_TOKEN;
list_for_each_entry(bpqdev, &bpq_devices, bpq_list) {
if (i == *pos)
return bpqdev;
}
return NULL;
}
static void *bpq_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
struct list_head *p;
++*pos;
if (v == SEQ_START_TOKEN)
p = bpq_devices.next;
else
p = ((struct bpqdev *)v)->bpq_list.next;
return (p == &bpq_devices) ? NULL
: list_entry(p, struct bpqdev, bpq_list);
}
static void bpq_seq_stop(struct seq_file *seq, void *v)
{
rcu_read_unlock();
}
static int bpq_seq_show(struct seq_file *seq, void *v)
{
if (v == SEQ_START_TOKEN)
seq_puts(seq,
"dev ether destination accept from\n");
else {
const struct bpqdev *bpqdev = v;
seq_printf(seq, "%-5s %-10s %s ",
bpqdev->axdev->name, bpqdev->ethdev->name,
bpq_print_ethaddr(bpqdev->dest_addr));
seq_printf(seq, "%s\n",
(bpqdev->acpt_addr[0] & 0x01) ? "*"
: bpq_print_ethaddr(bpqdev->acpt_addr));
}
return 0;
}
static struct seq_operations bpq_seqops = {
.start = bpq_seq_start,
.next = bpq_seq_next,
.stop = bpq_seq_stop,
.show = bpq_seq_show,
};
static int bpq_info_open(struct inode *inode, struct file *file)
{
return seq_open(file, &bpq_seqops);
}
static struct file_operations bpq_info_fops = {
.owner = THIS_MODULE,
.open = bpq_info_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};
/* ------------------------------------------------------------------------ */
static void bpq_setup(struct net_device *dev)
{
dev->hard_start_xmit = bpq_xmit;
dev->open = bpq_open;
dev->stop = bpq_close;
dev->set_mac_address = bpq_set_mac_address;
dev->get_stats = bpq_get_stats;
dev->do_ioctl = bpq_ioctl;
dev->destructor = free_netdev;
memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
memcpy(dev->dev_addr, ax25_defaddr, AX25_ADDR_LEN);
dev->flags = 0;
#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
dev->hard_header = ax25_encapsulate;
dev->rebuild_header = ax25_rebuild_header;
#endif
dev->type = ARPHRD_AX25;
dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN;
dev->mtu = AX25_DEF_PACLEN;
dev->addr_len = AX25_ADDR_LEN;
}
/*
* Setup a new device.
*/
static int bpq_new_device(struct net_device *edev)
{
int err;
struct net_device *ndev;
struct bpqdev *bpq;
ndev = alloc_netdev(sizeof(struct bpqdev), "bpq%d",
bpq_setup);
if (!ndev)
return -ENOMEM;
bpq = netdev_priv(ndev);
dev_hold(edev);
bpq->ethdev = edev;
bpq->axdev = ndev;
memcpy(bpq->dest_addr, bcast_addr, sizeof(bpq_eth_addr));
memcpy(bpq->acpt_addr, bcast_addr, sizeof(bpq_eth_addr));
err = dev_alloc_name(ndev, ndev->name);
if (err < 0)
goto error;
err = register_netdevice(ndev);
if (err)
goto error;
/* List protected by RTNL */
list_add_rcu(&bpq->bpq_list, &bpq_devices);
return 0;
error:
dev_put(edev);
free_netdev(ndev);
return err;
}
static void bpq_free_device(struct net_device *ndev)
{
struct bpqdev *bpq = netdev_priv(ndev);
dev_put(bpq->ethdev);
list_del_rcu(&bpq->bpq_list);
unregister_netdevice(ndev);
}
/*
* Handle device status changes.
*/
static int bpq_device_event(struct notifier_block *this,unsigned long event, void *ptr)
{
struct net_device *dev = (struct net_device *)ptr;
if (!dev_is_ethdev(dev))
return NOTIFY_DONE;
rcu_read_lock();
switch (event) {
case NETDEV_UP: /* new ethernet device -> new BPQ interface */
if (bpq_get_ax25_dev(dev) == NULL)
bpq_new_device(dev);
break;
case NETDEV_DOWN: /* ethernet device closed -> close BPQ interface */
if ((dev = bpq_get_ax25_dev(dev)) != NULL)
dev_close(dev);
break;
case NETDEV_UNREGISTER: /* ethernet device removed -> free BPQ interface */
if ((dev = bpq_get_ax25_dev(dev)) != NULL)
bpq_free_device(dev);
break;
default:
break;
}
rcu_read_unlock();
return NOTIFY_DONE;
}
/* ------------------------------------------------------------------------ */
/*
* Initialize driver. To be called from af_ax25 if not compiled as a
* module
*/
static int __init bpq_init_driver(void)
{
#ifdef CONFIG_PROC_FS
if (!proc_net_fops_create("bpqether", S_IRUGO, &bpq_info_fops)) {
printk(KERN_ERR
"bpq: cannot create /proc/net/bpqether entry.\n");
return -ENOENT;
}
#endif /* CONFIG_PROC_FS */
dev_add_pack(&bpq_packet_type);
register_netdevice_notifier(&bpq_dev_notifier);
printk(banner);
return 0;
}
static void __exit bpq_cleanup_driver(void)
{
struct bpqdev *bpq;
dev_remove_pack(&bpq_packet_type);
unregister_netdevice_notifier(&bpq_dev_notifier);
proc_net_remove("bpqether");
rtnl_lock();
while (!list_empty(&bpq_devices)) {
bpq = list_entry(bpq_devices.next, struct bpqdev, bpq_list);
bpq_free_device(bpq->axdev);
}
rtnl_unlock();
}
MODULE_AUTHOR("Joerg Reuter DL1BKE <jreuter@yaina.de>");
MODULE_DESCRIPTION("Transmit and receive AX.25 packets over Ethernet");
MODULE_LICENSE("GPL");
module_init(bpq_init_driver);
module_exit(bpq_cleanup_driver);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,817 @@
/*****************************************************************************/
/*
* hdlcdrv.c -- HDLC packet radio network driver.
*
* Copyright (C) 1996-2000 Thomas Sailer (sailer@ife.ee.ethz.ch)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* 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.
*
* The driver was derived from Donald Beckers skeleton.c
* Written 1993-94 by Donald Becker.
*
* History:
* 0.1 21.09.1996 Started
* 18.10.1996 Changed to new user space access routines
* (copy_{to,from}_user)
* 0.2 21.11.1996 various small changes
* 0.3 03.03.1997 fixed (hopefully) IP not working with ax.25 as a module
* 0.4 16.04.1997 init code/data tagged
* 0.5 30.07.1997 made HDLC buffers bigger (solves a problem with the
* soundmodem driver)
* 0.6 05.04.1998 add spinlocks
* 0.7 03.08.1999 removed some old compatibility cruft
* 0.8 12.02.2000 adapted to softnet driver interface
*/
/*****************************************************************************/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/net.h>
#include <linux/in.h>
#include <linux/if.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/bitops.h>
#include <asm/uaccess.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/hdlcdrv.h>
/* prototypes for ax25_encapsulate and ax25_rebuild_header */
#include <net/ax25.h>
/* make genksyms happy */
#include <linux/ip.h>
#include <linux/udp.h>
#include <linux/tcp.h>
#include <linux/crc-ccitt.h>
/* --------------------------------------------------------------------- */
/*
* The name of the card. Is used for messages and in the requests for
* io regions, irqs and dma channels
*/
static char ax25_bcast[AX25_ADDR_LEN] =
{'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1};
static char ax25_nocall[AX25_ADDR_LEN] =
{'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1};
/* --------------------------------------------------------------------- */
#define KISS_VERBOSE
/* --------------------------------------------------------------------- */
#define PARAM_TXDELAY 1
#define PARAM_PERSIST 2
#define PARAM_SLOTTIME 3
#define PARAM_TXTAIL 4
#define PARAM_FULLDUP 5
#define PARAM_HARDWARE 6
#define PARAM_RETURN 255
/* --------------------------------------------------------------------- */
/*
* the CRC routines are stolen from WAMPES
* by Dieter Deyke
*/
/*---------------------------------------------------------------------------*/
static inline void append_crc_ccitt(unsigned char *buffer, int len)
{
unsigned int crc = crc_ccitt(0xffff, buffer, len) ^ 0xffff;
*buffer++ = crc;
*buffer++ = crc >> 8;
}
/*---------------------------------------------------------------------------*/
static inline int check_crc_ccitt(const unsigned char *buf, int cnt)
{
return (crc_ccitt(0xffff, buf, cnt) & 0xffff) == 0xf0b8;
}
/*---------------------------------------------------------------------------*/
#if 0
static int calc_crc_ccitt(const unsigned char *buf, int cnt)
{
unsigned int crc = 0xffff;
for (; cnt > 0; cnt--)
crc = (crc >> 8) ^ crc_ccitt_table[(crc ^ *buf++) & 0xff];
crc ^= 0xffff;
return (crc & 0xffff);
}
#endif
/* ---------------------------------------------------------------------- */
#define tenms_to_2flags(s,tenms) ((tenms * s->par.bitrate) / 100 / 16)
/* ---------------------------------------------------------------------- */
/*
* The HDLC routines
*/
static int hdlc_rx_add_bytes(struct hdlcdrv_state *s, unsigned int bits,
int num)
{
int added = 0;
while (s->hdlcrx.rx_state && num >= 8) {
if (s->hdlcrx.len >= sizeof(s->hdlcrx.buffer)) {
s->hdlcrx.rx_state = 0;
return 0;
}
*s->hdlcrx.bp++ = bits >> (32-num);
s->hdlcrx.len++;
num -= 8;
added += 8;
}
return added;
}
static void hdlc_rx_flag(struct net_device *dev, struct hdlcdrv_state *s)
{
struct sk_buff *skb;
int pkt_len;
unsigned char *cp;
if (s->hdlcrx.len < 4)
return;
if (!check_crc_ccitt(s->hdlcrx.buffer, s->hdlcrx.len))
return;
pkt_len = s->hdlcrx.len - 2 + 1; /* KISS kludge */
if (!(skb = dev_alloc_skb(pkt_len))) {
printk("%s: memory squeeze, dropping packet\n", dev->name);
s->stats.rx_dropped++;
return;
}
skb->dev = dev;
cp = skb_put(skb, pkt_len);
*cp++ = 0; /* KISS kludge */
memcpy(cp, s->hdlcrx.buffer, pkt_len - 1);
skb->protocol = htons(ETH_P_AX25);
skb->mac.raw = skb->data;
netif_rx(skb);
dev->last_rx = jiffies;
s->stats.rx_packets++;
}
void hdlcdrv_receiver(struct net_device *dev, struct hdlcdrv_state *s)
{
int i;
unsigned int mask1, mask2, mask3, mask4, mask5, mask6, word;
if (!s || s->magic != HDLCDRV_MAGIC)
return;
if (test_and_set_bit(0, &s->hdlcrx.in_hdlc_rx))
return;
while (!hdlcdrv_hbuf_empty(&s->hdlcrx.hbuf)) {
word = hdlcdrv_hbuf_get(&s->hdlcrx.hbuf);
#ifdef HDLCDRV_DEBUG
hdlcdrv_add_bitbuffer_word(&s->bitbuf_hdlc, word);
#endif /* HDLCDRV_DEBUG */
s->hdlcrx.bitstream >>= 16;
s->hdlcrx.bitstream |= word << 16;
s->hdlcrx.bitbuf >>= 16;
s->hdlcrx.bitbuf |= word << 16;
s->hdlcrx.numbits += 16;
for(i = 15, mask1 = 0x1fc00, mask2 = 0x1fe00, mask3 = 0x0fc00,
mask4 = 0x1f800, mask5 = 0xf800, mask6 = 0xffff;
i >= 0;
i--, mask1 <<= 1, mask2 <<= 1, mask3 <<= 1, mask4 <<= 1,
mask5 <<= 1, mask6 = (mask6 << 1) | 1) {
if ((s->hdlcrx.bitstream & mask1) == mask1)
s->hdlcrx.rx_state = 0; /* abort received */
else if ((s->hdlcrx.bitstream & mask2) == mask3) {
/* flag received */
if (s->hdlcrx.rx_state) {
hdlc_rx_add_bytes(s, s->hdlcrx.bitbuf
<< (8+i),
s->hdlcrx.numbits
-8-i);
hdlc_rx_flag(dev, s);
}
s->hdlcrx.len = 0;
s->hdlcrx.bp = s->hdlcrx.buffer;
s->hdlcrx.rx_state = 1;
s->hdlcrx.numbits = i;
} else if ((s->hdlcrx.bitstream & mask4) == mask5) {
/* stuffed bit */
s->hdlcrx.numbits--;
s->hdlcrx.bitbuf = (s->hdlcrx.bitbuf & (~mask6)) |
((s->hdlcrx.bitbuf & mask6) << 1);
}
}
s->hdlcrx.numbits -= hdlc_rx_add_bytes(s, s->hdlcrx.bitbuf,
s->hdlcrx.numbits);
}
clear_bit(0, &s->hdlcrx.in_hdlc_rx);
}
/* ---------------------------------------------------------------------- */
static inline void do_kiss_params(struct hdlcdrv_state *s,
unsigned char *data, unsigned long len)
{
#ifdef KISS_VERBOSE
#define PKP(a,b) printk(KERN_INFO "hdlcdrv.c: channel params: " a "\n", b)
#else /* KISS_VERBOSE */
#define PKP(a,b)
#endif /* KISS_VERBOSE */
if (len < 2)
return;
switch(data[0]) {
case PARAM_TXDELAY:
s->ch_params.tx_delay = data[1];
PKP("TX delay = %ums", 10 * s->ch_params.tx_delay);
break;
case PARAM_PERSIST:
s->ch_params.ppersist = data[1];
PKP("p persistence = %u", s->ch_params.ppersist);
break;
case PARAM_SLOTTIME:
s->ch_params.slottime = data[1];
PKP("slot time = %ums", s->ch_params.slottime);
break;
case PARAM_TXTAIL:
s->ch_params.tx_tail = data[1];
PKP("TX tail = %ums", s->ch_params.tx_tail);
break;
case PARAM_FULLDUP:
s->ch_params.fulldup = !!data[1];
PKP("%s duplex", s->ch_params.fulldup ? "full" : "half");
break;
default:
break;
}
#undef PKP
}
/* ---------------------------------------------------------------------- */
void hdlcdrv_transmitter(struct net_device *dev, struct hdlcdrv_state *s)
{
unsigned int mask1, mask2, mask3;
int i;
struct sk_buff *skb;
int pkt_len;
if (!s || s->magic != HDLCDRV_MAGIC)
return;
if (test_and_set_bit(0, &s->hdlctx.in_hdlc_tx))
return;
for (;;) {
if (s->hdlctx.numbits >= 16) {
if (hdlcdrv_hbuf_full(&s->hdlctx.hbuf)) {
clear_bit(0, &s->hdlctx.in_hdlc_tx);
return;
}
hdlcdrv_hbuf_put(&s->hdlctx.hbuf, s->hdlctx.bitbuf);
s->hdlctx.bitbuf >>= 16;
s->hdlctx.numbits -= 16;
}
switch (s->hdlctx.tx_state) {
default:
clear_bit(0, &s->hdlctx.in_hdlc_tx);
return;
case 0:
case 1:
if (s->hdlctx.numflags) {
s->hdlctx.numflags--;
s->hdlctx.bitbuf |=
0x7e7e << s->hdlctx.numbits;
s->hdlctx.numbits += 16;
break;
}
if (s->hdlctx.tx_state == 1) {
clear_bit(0, &s->hdlctx.in_hdlc_tx);
return;
}
if (!(skb = s->skb)) {
int flgs = tenms_to_2flags(s, s->ch_params.tx_tail);
if (flgs < 2)
flgs = 2;
s->hdlctx.tx_state = 1;
s->hdlctx.numflags = flgs;
break;
}
s->skb = NULL;
netif_wake_queue(dev);
pkt_len = skb->len-1; /* strip KISS byte */
if (pkt_len >= HDLCDRV_MAXFLEN || pkt_len < 2) {
s->hdlctx.tx_state = 0;
s->hdlctx.numflags = 1;
dev_kfree_skb_irq(skb);
break;
}
memcpy(s->hdlctx.buffer, skb->data+1, pkt_len);
dev_kfree_skb_irq(skb);
s->hdlctx.bp = s->hdlctx.buffer;
append_crc_ccitt(s->hdlctx.buffer, pkt_len);
s->hdlctx.len = pkt_len+2; /* the appended CRC */
s->hdlctx.tx_state = 2;
s->hdlctx.bitstream = 0;
s->stats.tx_packets++;
break;
case 2:
if (!s->hdlctx.len) {
s->hdlctx.tx_state = 0;
s->hdlctx.numflags = 1;
break;
}
s->hdlctx.len--;
s->hdlctx.bitbuf |= *s->hdlctx.bp <<
s->hdlctx.numbits;
s->hdlctx.bitstream >>= 8;
s->hdlctx.bitstream |= (*s->hdlctx.bp++) << 16;
mask1 = 0x1f000;
mask2 = 0x10000;
mask3 = 0xffffffff >> (31-s->hdlctx.numbits);
s->hdlctx.numbits += 8;
for(i = 0; i < 8; i++, mask1 <<= 1, mask2 <<= 1,
mask3 = (mask3 << 1) | 1) {
if ((s->hdlctx.bitstream & mask1) != mask1)
continue;
s->hdlctx.bitstream &= ~mask2;
s->hdlctx.bitbuf =
(s->hdlctx.bitbuf & mask3) |
((s->hdlctx.bitbuf &
(~mask3)) << 1);
s->hdlctx.numbits++;
mask3 = (mask3 << 1) | 1;
}
break;
}
}
}
/* ---------------------------------------------------------------------- */
static void start_tx(struct net_device *dev, struct hdlcdrv_state *s)
{
s->hdlctx.tx_state = 0;
s->hdlctx.numflags = tenms_to_2flags(s, s->ch_params.tx_delay);
s->hdlctx.bitbuf = s->hdlctx.bitstream = s->hdlctx.numbits = 0;
hdlcdrv_transmitter(dev, s);
s->hdlctx.ptt = 1;
s->ptt_keyed++;
}
/* ---------------------------------------------------------------------- */
static unsigned short random_seed;
static inline unsigned short random_num(void)
{
random_seed = 28629 * random_seed + 157;
return random_seed;
}
/* ---------------------------------------------------------------------- */
void hdlcdrv_arbitrate(struct net_device *dev, struct hdlcdrv_state *s)
{
if (!s || s->magic != HDLCDRV_MAGIC || s->hdlctx.ptt || !s->skb)
return;
if (s->ch_params.fulldup) {
start_tx(dev, s);
return;
}
if (s->hdlcrx.dcd) {
s->hdlctx.slotcnt = s->ch_params.slottime;
return;
}
if ((--s->hdlctx.slotcnt) > 0)
return;
s->hdlctx.slotcnt = s->ch_params.slottime;
if ((random_num() % 256) > s->ch_params.ppersist)
return;
start_tx(dev, s);
}
/* --------------------------------------------------------------------- */
/*
* ===================== network driver interface =========================
*/
static int hdlcdrv_send_packet(struct sk_buff *skb, struct net_device *dev)
{
struct hdlcdrv_state *sm = netdev_priv(dev);
if (skb->data[0] != 0) {
do_kiss_params(sm, skb->data, skb->len);
dev_kfree_skb(skb);
return 0;
}
if (sm->skb)
return -1;
netif_stop_queue(dev);
sm->skb = skb;
return 0;
}
/* --------------------------------------------------------------------- */
static int hdlcdrv_set_mac_address(struct net_device *dev, void *addr)
{
struct sockaddr *sa = (struct sockaddr *)addr;
/* addr is an AX.25 shifted ASCII mac address */
memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
return 0;
}
/* --------------------------------------------------------------------- */
static struct net_device_stats *hdlcdrv_get_stats(struct net_device *dev)
{
struct hdlcdrv_state *sm = netdev_priv(dev);
/*
* Get the current statistics. This may be called with the
* card open or closed.
*/
return &sm->stats;
}
/* --------------------------------------------------------------------- */
/*
* Open/initialize the board. This is called (in the current kernel)
* sometime after booting when the 'ifconfig' program is run.
*
* This routine should set everything up anew at each open, even
* registers that "should" only need to be set once at boot, so that
* there is non-reboot way to recover if something goes wrong.
*/
static int hdlcdrv_open(struct net_device *dev)
{
struct hdlcdrv_state *s = netdev_priv(dev);
int i;
if (!s->ops || !s->ops->open)
return -ENODEV;
/*
* initialise some variables
*/
s->opened = 1;
s->hdlcrx.hbuf.rd = s->hdlcrx.hbuf.wr = 0;
s->hdlcrx.in_hdlc_rx = 0;
s->hdlcrx.rx_state = 0;
s->hdlctx.hbuf.rd = s->hdlctx.hbuf.wr = 0;
s->hdlctx.in_hdlc_tx = 0;
s->hdlctx.tx_state = 1;
s->hdlctx.numflags = 0;
s->hdlctx.bitstream = s->hdlctx.bitbuf = s->hdlctx.numbits = 0;
s->hdlctx.ptt = 0;
s->hdlctx.slotcnt = s->ch_params.slottime;
s->hdlctx.calibrate = 0;
i = s->ops->open(dev);
if (i)
return i;
netif_start_queue(dev);
return 0;
}
/* --------------------------------------------------------------------- */
/*
* The inverse routine to hdlcdrv_open().
*/
static int hdlcdrv_close(struct net_device *dev)
{
struct hdlcdrv_state *s = netdev_priv(dev);
int i = 0;
netif_stop_queue(dev);
if (s->ops && s->ops->close)
i = s->ops->close(dev);
if (s->skb)
dev_kfree_skb(s->skb);
s->skb = NULL;
s->opened = 0;
return i;
}
/* --------------------------------------------------------------------- */
static int hdlcdrv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
struct hdlcdrv_state *s = netdev_priv(dev);
struct hdlcdrv_ioctl bi;
if (cmd != SIOCDEVPRIVATE) {
if (s->ops && s->ops->ioctl)
return s->ops->ioctl(dev, ifr, &bi, cmd);
return -ENOIOCTLCMD;
}
if (copy_from_user(&bi, ifr->ifr_data, sizeof(bi)))
return -EFAULT;
switch (bi.cmd) {
default:
if (s->ops && s->ops->ioctl)
return s->ops->ioctl(dev, ifr, &bi, cmd);
return -ENOIOCTLCMD;
case HDLCDRVCTL_GETCHANNELPAR:
bi.data.cp.tx_delay = s->ch_params.tx_delay;
bi.data.cp.tx_tail = s->ch_params.tx_tail;
bi.data.cp.slottime = s->ch_params.slottime;
bi.data.cp.ppersist = s->ch_params.ppersist;
bi.data.cp.fulldup = s->ch_params.fulldup;
break;
case HDLCDRVCTL_SETCHANNELPAR:
if (!capable(CAP_NET_ADMIN))
return -EACCES;
s->ch_params.tx_delay = bi.data.cp.tx_delay;
s->ch_params.tx_tail = bi.data.cp.tx_tail;
s->ch_params.slottime = bi.data.cp.slottime;
s->ch_params.ppersist = bi.data.cp.ppersist;
s->ch_params.fulldup = bi.data.cp.fulldup;
s->hdlctx.slotcnt = 1;
return 0;
case HDLCDRVCTL_GETMODEMPAR:
bi.data.mp.iobase = dev->base_addr;
bi.data.mp.irq = dev->irq;
bi.data.mp.dma = dev->dma;
bi.data.mp.dma2 = s->ptt_out.dma2;
bi.data.mp.seriobase = s->ptt_out.seriobase;
bi.data.mp.pariobase = s->ptt_out.pariobase;
bi.data.mp.midiiobase = s->ptt_out.midiiobase;
break;
case HDLCDRVCTL_SETMODEMPAR:
if ((!capable(CAP_SYS_RAWIO)) || netif_running(dev))
return -EACCES;
dev->base_addr = bi.data.mp.iobase;
dev->irq = bi.data.mp.irq;
dev->dma = bi.data.mp.dma;
s->ptt_out.dma2 = bi.data.mp.dma2;
s->ptt_out.seriobase = bi.data.mp.seriobase;
s->ptt_out.pariobase = bi.data.mp.pariobase;
s->ptt_out.midiiobase = bi.data.mp.midiiobase;
return 0;
case HDLCDRVCTL_GETSTAT:
bi.data.cs.ptt = hdlcdrv_ptt(s);
bi.data.cs.dcd = s->hdlcrx.dcd;
bi.data.cs.ptt_keyed = s->ptt_keyed;
bi.data.cs.tx_packets = s->stats.tx_packets;
bi.data.cs.tx_errors = s->stats.tx_errors;
bi.data.cs.rx_packets = s->stats.rx_packets;
bi.data.cs.rx_errors = s->stats.rx_errors;
break;
case HDLCDRVCTL_OLDGETSTAT:
bi.data.ocs.ptt = hdlcdrv_ptt(s);
bi.data.ocs.dcd = s->hdlcrx.dcd;
bi.data.ocs.ptt_keyed = s->ptt_keyed;
break;
case HDLCDRVCTL_CALIBRATE:
if(!capable(CAP_SYS_RAWIO))
return -EPERM;
s->hdlctx.calibrate = bi.data.calibrate * s->par.bitrate / 16;
return 0;
case HDLCDRVCTL_GETSAMPLES:
#ifndef HDLCDRV_DEBUG
return -EPERM;
#else /* HDLCDRV_DEBUG */
if (s->bitbuf_channel.rd == s->bitbuf_channel.wr)
return -EAGAIN;
bi.data.bits =
s->bitbuf_channel.buffer[s->bitbuf_channel.rd];
s->bitbuf_channel.rd = (s->bitbuf_channel.rd+1) %
sizeof(s->bitbuf_channel.buffer);
break;
#endif /* HDLCDRV_DEBUG */
case HDLCDRVCTL_GETBITS:
#ifndef HDLCDRV_DEBUG
return -EPERM;
#else /* HDLCDRV_DEBUG */
if (s->bitbuf_hdlc.rd == s->bitbuf_hdlc.wr)
return -EAGAIN;
bi.data.bits =
s->bitbuf_hdlc.buffer[s->bitbuf_hdlc.rd];
s->bitbuf_hdlc.rd = (s->bitbuf_hdlc.rd+1) %
sizeof(s->bitbuf_hdlc.buffer);
break;
#endif /* HDLCDRV_DEBUG */
case HDLCDRVCTL_DRIVERNAME:
if (s->ops && s->ops->drvname) {
strncpy(bi.data.drivername, s->ops->drvname,
sizeof(bi.data.drivername));
break;
}
bi.data.drivername[0] = '\0';
break;
}
if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi)))
return -EFAULT;
return 0;
}
/* --------------------------------------------------------------------- */
/*
* Initialize fields in hdlcdrv
*/
static void hdlcdrv_setup(struct net_device *dev)
{
static const struct hdlcdrv_channel_params dflt_ch_params = {
20, 2, 10, 40, 0
};
struct hdlcdrv_state *s = netdev_priv(dev);
/*
* initialize the hdlcdrv_state struct
*/
s->ch_params = dflt_ch_params;
s->ptt_keyed = 0;
spin_lock_init(&s->hdlcrx.hbuf.lock);
s->hdlcrx.hbuf.rd = s->hdlcrx.hbuf.wr = 0;
s->hdlcrx.in_hdlc_rx = 0;
s->hdlcrx.rx_state = 0;
spin_lock_init(&s->hdlctx.hbuf.lock);
s->hdlctx.hbuf.rd = s->hdlctx.hbuf.wr = 0;
s->hdlctx.in_hdlc_tx = 0;
s->hdlctx.tx_state = 1;
s->hdlctx.numflags = 0;
s->hdlctx.bitstream = s->hdlctx.bitbuf = s->hdlctx.numbits = 0;
s->hdlctx.ptt = 0;
s->hdlctx.slotcnt = s->ch_params.slottime;
s->hdlctx.calibrate = 0;
#ifdef HDLCDRV_DEBUG
s->bitbuf_channel.rd = s->bitbuf_channel.wr = 0;
s->bitbuf_channel.shreg = 0x80;
s->bitbuf_hdlc.rd = s->bitbuf_hdlc.wr = 0;
s->bitbuf_hdlc.shreg = 0x80;
#endif /* HDLCDRV_DEBUG */
/*
* initialize the device struct
*/
dev->open = hdlcdrv_open;
dev->stop = hdlcdrv_close;
dev->do_ioctl = hdlcdrv_ioctl;
dev->hard_start_xmit = hdlcdrv_send_packet;
dev->get_stats = hdlcdrv_get_stats;
/* Fill in the fields of the device structure */
s->skb = NULL;
#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
dev->hard_header = ax25_encapsulate;
dev->rebuild_header = ax25_rebuild_header;
#else /* CONFIG_AX25 || CONFIG_AX25_MODULE */
dev->hard_header = NULL;
dev->rebuild_header = NULL;
#endif /* CONFIG_AX25 || CONFIG_AX25_MODULE */
dev->set_mac_address = hdlcdrv_set_mac_address;
dev->type = ARPHRD_AX25; /* AF_AX25 device */
dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN;
dev->mtu = AX25_DEF_PACLEN; /* eth_mtu is the default */
dev->addr_len = AX25_ADDR_LEN; /* sizeof an ax.25 address */
memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
memcpy(dev->dev_addr, ax25_nocall, AX25_ADDR_LEN);
dev->tx_queue_len = 16;
}
/* --------------------------------------------------------------------- */
struct net_device *hdlcdrv_register(const struct hdlcdrv_ops *ops,
unsigned int privsize, const char *ifname,
unsigned int baseaddr, unsigned int irq,
unsigned int dma)
{
struct net_device *dev;
struct hdlcdrv_state *s;
int err;
BUG_ON(ops == NULL);
if (privsize < sizeof(struct hdlcdrv_state))
privsize = sizeof(struct hdlcdrv_state);
dev = alloc_netdev(privsize, ifname, hdlcdrv_setup);
if (!dev)
return ERR_PTR(-ENOMEM);
/*
* initialize part of the hdlcdrv_state struct
*/
s = netdev_priv(dev);
s->magic = HDLCDRV_MAGIC;
s->ops = ops;
dev->base_addr = baseaddr;
dev->irq = irq;
dev->dma = dma;
err = register_netdev(dev);
if (err < 0) {
printk(KERN_WARNING "hdlcdrv: cannot register net "
"device %s\n", dev->name);
free_netdev(dev);
dev = ERR_PTR(err);
}
return dev;
}
/* --------------------------------------------------------------------- */
void hdlcdrv_unregister(struct net_device *dev)
{
struct hdlcdrv_state *s = netdev_priv(dev);
BUG_ON(s->magic != HDLCDRV_MAGIC);
if (s->opened && s->ops->close)
s->ops->close(dev);
unregister_netdev(dev);
free_netdev(dev);
}
/* --------------------------------------------------------------------- */
EXPORT_SYMBOL(hdlcdrv_receiver);
EXPORT_SYMBOL(hdlcdrv_transmitter);
EXPORT_SYMBOL(hdlcdrv_arbitrate);
EXPORT_SYMBOL(hdlcdrv_register);
EXPORT_SYMBOL(hdlcdrv_unregister);
/* --------------------------------------------------------------------- */
static int __init hdlcdrv_init_driver(void)
{
printk(KERN_INFO "hdlcdrv: (C) 1996-2000 Thomas Sailer HB9JNX/AE4WA\n");
printk(KERN_INFO "hdlcdrv: version 0.8 compiled " __TIME__ " " __DATE__ "\n");
return 0;
}
/* --------------------------------------------------------------------- */
static void __exit hdlcdrv_cleanup_driver(void)
{
printk(KERN_INFO "hdlcdrv: cleanup\n");
}
/* --------------------------------------------------------------------- */
MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
MODULE_DESCRIPTION("Packet Radio network interface HDLC encoder/decoder");
MODULE_LICENSE("GPL");
module_init(hdlcdrv_init_driver);
module_exit(hdlcdrv_cleanup_driver);
/* --------------------------------------------------------------------- */

View File

@@ -0,0 +1,951 @@
/*
* MKISS Driver
*
* This module:
* This module is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* This module implements the AX.25 protocol for kernel-based
* devices like TTYs. It interfaces between a raw TTY, and the
* kernel's AX.25 protocol layers, just like slip.c.
* AX.25 needs to be separated from slip.c while slip.c is no
* longer a static kernel device since it is a module.
* This method clears the way to implement other kiss protocols
* like mkiss smack g8bpq ..... so far only mkiss is implemented.
*
* Hans Alblas <hans@esrac.ele.tue.nl>
*
* History
* Jonathan (G4KLX) Fixed to match Linux networking changes - 2.1.15.
* Matthias (DG2FEF) Added support for FlexNet CRC (on special request)
* Fixed bug in ax25_close(): dev_lock_wait() was
* called twice, causing a deadlock.
* Jeroen (PE1RXQ) Removed old MKISS_MAGIC stuff and calls to
* MOD_*_USE_COUNT
* Remove cli() and fix rtnl lock usage.
*/
#include <linux/config.h>
#include <linux/module.h>
#include <asm/system.h>
#include <linux/bitops.h>
#include <asm/uaccess.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/in.h>
#include <linux/inet.h>
#include <linux/tty.h>
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/major.h>
#include <linux/init.h>
#include <linux/rtnetlink.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/if_arp.h>
#include <net/ax25.h>
#include "mkiss.h"
#ifdef CONFIG_INET
#include <linux/ip.h>
#include <linux/tcp.h>
#endif
static char banner[] __initdata = KERN_INFO "mkiss: AX.25 Multikiss, Hans Albas PE1AYX\n";
typedef struct ax25_ctrl {
struct ax_disp ctrl; /* */
struct net_device dev; /* the device */
} ax25_ctrl_t;
static ax25_ctrl_t **ax25_ctrls;
int ax25_maxdev = AX25_MAXDEV; /* Can be overridden with insmod! */
static struct tty_ldisc ax_ldisc;
static int ax25_init(struct net_device *);
static int kiss_esc(unsigned char *, unsigned char *, int);
static int kiss_esc_crc(unsigned char *, unsigned char *, unsigned short, int);
static void kiss_unesc(struct ax_disp *, unsigned char);
/*---------------------------------------------------------------------------*/
static const unsigned short Crc_flex_table[] = {
0x0f87, 0x1e0e, 0x2c95, 0x3d1c, 0x49a3, 0x582a, 0x6ab1, 0x7b38,
0x83cf, 0x9246, 0xa0dd, 0xb154, 0xc5eb, 0xd462, 0xe6f9, 0xf770,
0x1f06, 0x0e8f, 0x3c14, 0x2d9d, 0x5922, 0x48ab, 0x7a30, 0x6bb9,
0x934e, 0x82c7, 0xb05c, 0xa1d5, 0xd56a, 0xc4e3, 0xf678, 0xe7f1,
0x2e85, 0x3f0c, 0x0d97, 0x1c1e, 0x68a1, 0x7928, 0x4bb3, 0x5a3a,
0xa2cd, 0xb344, 0x81df, 0x9056, 0xe4e9, 0xf560, 0xc7fb, 0xd672,
0x3e04, 0x2f8d, 0x1d16, 0x0c9f, 0x7820, 0x69a9, 0x5b32, 0x4abb,
0xb24c, 0xa3c5, 0x915e, 0x80d7, 0xf468, 0xe5e1, 0xd77a, 0xc6f3,
0x4d83, 0x5c0a, 0x6e91, 0x7f18, 0x0ba7, 0x1a2e, 0x28b5, 0x393c,
0xc1cb, 0xd042, 0xe2d9, 0xf350, 0x87ef, 0x9666, 0xa4fd, 0xb574,
0x5d02, 0x4c8b, 0x7e10, 0x6f99, 0x1b26, 0x0aaf, 0x3834, 0x29bd,
0xd14a, 0xc0c3, 0xf258, 0xe3d1, 0x976e, 0x86e7, 0xb47c, 0xa5f5,
0x6c81, 0x7d08, 0x4f93, 0x5e1a, 0x2aa5, 0x3b2c, 0x09b7, 0x183e,
0xe0c9, 0xf140, 0xc3db, 0xd252, 0xa6ed, 0xb764, 0x85ff, 0x9476,
0x7c00, 0x6d89, 0x5f12, 0x4e9b, 0x3a24, 0x2bad, 0x1936, 0x08bf,
0xf048, 0xe1c1, 0xd35a, 0xc2d3, 0xb66c, 0xa7e5, 0x957e, 0x84f7,
0x8b8f, 0x9a06, 0xa89d, 0xb914, 0xcdab, 0xdc22, 0xeeb9, 0xff30,
0x07c7, 0x164e, 0x24d5, 0x355c, 0x41e3, 0x506a, 0x62f1, 0x7378,
0x9b0e, 0x8a87, 0xb81c, 0xa995, 0xdd2a, 0xcca3, 0xfe38, 0xefb1,
0x1746, 0x06cf, 0x3454, 0x25dd, 0x5162, 0x40eb, 0x7270, 0x63f9,
0xaa8d, 0xbb04, 0x899f, 0x9816, 0xeca9, 0xfd20, 0xcfbb, 0xde32,
0x26c5, 0x374c, 0x05d7, 0x145e, 0x60e1, 0x7168, 0x43f3, 0x527a,
0xba0c, 0xab85, 0x991e, 0x8897, 0xfc28, 0xeda1, 0xdf3a, 0xceb3,
0x3644, 0x27cd, 0x1556, 0x04df, 0x7060, 0x61e9, 0x5372, 0x42fb,
0xc98b, 0xd802, 0xea99, 0xfb10, 0x8faf, 0x9e26, 0xacbd, 0xbd34,
0x45c3, 0x544a, 0x66d1, 0x7758, 0x03e7, 0x126e, 0x20f5, 0x317c,
0xd90a, 0xc883, 0xfa18, 0xeb91, 0x9f2e, 0x8ea7, 0xbc3c, 0xadb5,
0x5542, 0x44cb, 0x7650, 0x67d9, 0x1366, 0x02ef, 0x3074, 0x21fd,
0xe889, 0xf900, 0xcb9b, 0xda12, 0xaead, 0xbf24, 0x8dbf, 0x9c36,
0x64c1, 0x7548, 0x47d3, 0x565a, 0x22e5, 0x336c, 0x01f7, 0x107e,
0xf808, 0xe981, 0xdb1a, 0xca93, 0xbe2c, 0xafa5, 0x9d3e, 0x8cb7,
0x7440, 0x65c9, 0x5752, 0x46db, 0x3264, 0x23ed, 0x1176, 0x00ff
};
/*---------------------------------------------------------------------------*/
static unsigned short calc_crc_flex(unsigned char *cp, int size)
{
unsigned short crc = 0xffff;
while (size--)
crc = (crc << 8) ^ Crc_flex_table[((crc >> 8) ^ *cp++) & 0xff];
return crc;
}
/*---------------------------------------------------------------------------*/
static int check_crc_flex(unsigned char *cp, int size)
{
unsigned short crc = 0xffff;
if (size < 3)
return -1;
while (size--)
crc = (crc << 8) ^ Crc_flex_table[((crc >> 8) ^ *cp++) & 0xff];
if ((crc & 0xffff) != 0x7070)
return -1;
return 0;
}
/*---------------------------------------------------------------------------*/
/* Find a free channel, and link in this `tty' line. */
static inline struct ax_disp *ax_alloc(void)
{
ax25_ctrl_t *axp=NULL;
int i;
for (i = 0; i < ax25_maxdev; i++) {
axp = ax25_ctrls[i];
/* Not allocated ? */
if (axp == NULL)
break;
/* Not in use ? */
if (!test_and_set_bit(AXF_INUSE, &axp->ctrl.flags))
break;
}
/* Sorry, too many, all slots in use */
if (i >= ax25_maxdev)
return NULL;
/* If no channels are available, allocate one */
if (axp == NULL && (ax25_ctrls[i] = kmalloc(sizeof(ax25_ctrl_t), GFP_KERNEL)) != NULL) {
axp = ax25_ctrls[i];
}
memset(axp, 0, sizeof(ax25_ctrl_t));
/* Initialize channel control data */
set_bit(AXF_INUSE, &axp->ctrl.flags);
sprintf(axp->dev.name, "ax%d", i++);
axp->ctrl.tty = NULL;
axp->dev.base_addr = i;
axp->dev.priv = (void *)&axp->ctrl;
axp->dev.next = NULL;
axp->dev.init = ax25_init;
if (axp != NULL) {
/*
* register device so that it can be ifconfig'ed
* ax25_init() will be called as a side-effect
* SIDE-EFFECT WARNING: ax25_init() CLEARS axp->ctrl !
*/
if (register_netdev(&axp->dev) == 0) {
/* (Re-)Set the INUSE bit. Very Important! */
set_bit(AXF_INUSE, &axp->ctrl.flags);
axp->ctrl.dev = &axp->dev;
axp->dev.priv = (void *) &axp->ctrl;
return &axp->ctrl;
} else {
clear_bit(AXF_INUSE,&axp->ctrl.flags);
printk(KERN_ERR "mkiss: ax_alloc() - register_netdev() failure.\n");
}
}
return NULL;
}
/* Free an AX25 channel. */
static inline void ax_free(struct ax_disp *ax)
{
/* Free all AX25 frame buffers. */
if (ax->rbuff)
kfree(ax->rbuff);
ax->rbuff = NULL;
if (ax->xbuff)
kfree(ax->xbuff);
ax->xbuff = NULL;
if (!test_and_clear_bit(AXF_INUSE, &ax->flags))
printk(KERN_ERR "mkiss: %s: ax_free for already free unit.\n", ax->dev->name);
}
static void ax_changedmtu(struct ax_disp *ax)
{
struct net_device *dev = ax->dev;
unsigned char *xbuff, *rbuff, *oxbuff, *orbuff;
int len;
len = dev->mtu * 2;
/*
* allow for arrival of larger UDP packets, even if we say not to
* also fixes a bug in which SunOS sends 512-byte packets even with
* an MSS of 128
*/
if (len < 576 * 2)
len = 576 * 2;
xbuff = kmalloc(len + 4, GFP_ATOMIC);
rbuff = kmalloc(len + 4, GFP_ATOMIC);
if (xbuff == NULL || rbuff == NULL) {
printk(KERN_ERR "mkiss: %s: unable to grow ax25 buffers, MTU change cancelled.\n",
ax->dev->name);
dev->mtu = ax->mtu;
if (xbuff != NULL)
kfree(xbuff);
if (rbuff != NULL)
kfree(rbuff);
return;
}
spin_lock_bh(&ax->buflock);
oxbuff = ax->xbuff;
ax->xbuff = xbuff;
orbuff = ax->rbuff;
ax->rbuff = rbuff;
if (ax->xleft) {
if (ax->xleft <= len) {
memcpy(ax->xbuff, ax->xhead, ax->xleft);
} else {
ax->xleft = 0;
ax->tx_dropped++;
}
}
ax->xhead = ax->xbuff;
if (ax->rcount) {
if (ax->rcount <= len) {
memcpy(ax->rbuff, orbuff, ax->rcount);
} else {
ax->rcount = 0;
ax->rx_over_errors++;
set_bit(AXF_ERROR, &ax->flags);
}
}
ax->mtu = dev->mtu + 73;
ax->buffsize = len;
spin_unlock_bh(&ax->buflock);
if (oxbuff != NULL)
kfree(oxbuff);
if (orbuff != NULL)
kfree(orbuff);
}
/* Set the "sending" flag. This must be atomic. */
static inline void ax_lock(struct ax_disp *ax)
{
netif_stop_queue(ax->dev);
}
/* Clear the "sending" flag. This must be atomic. */
static inline void ax_unlock(struct ax_disp *ax)
{
netif_start_queue(ax->dev);
}
/* Send one completely decapsulated AX.25 packet to the AX.25 layer. */
static void ax_bump(struct ax_disp *ax)
{
struct sk_buff *skb;
int count;
spin_lock_bh(&ax->buflock);
if (ax->rbuff[0] > 0x0f) {
if (ax->rbuff[0] & 0x20) {
ax->crcmode = CRC_MODE_FLEX;
if (check_crc_flex(ax->rbuff, ax->rcount) < 0) {
ax->rx_errors++;
return;
}
ax->rcount -= 2;
/* dl9sau bugfix: the trailling two bytes flexnet crc
* will not be passed to the kernel. thus we have
* to correct the kissparm signature, because it
* indicates a crc but there's none
*/
*ax->rbuff &= ~0x20;
}
}
spin_unlock_bh(&ax->buflock);
count = ax->rcount;
if ((skb = dev_alloc_skb(count)) == NULL) {
printk(KERN_ERR "mkiss: %s: memory squeeze, dropping packet.\n", ax->dev->name);
ax->rx_dropped++;
return;
}
skb->dev = ax->dev;
spin_lock_bh(&ax->buflock);
memcpy(skb_put(skb,count), ax->rbuff, count);
spin_unlock_bh(&ax->buflock);
skb->mac.raw = skb->data;
skb->protocol = htons(ETH_P_AX25);
netif_rx(skb);
ax->dev->last_rx = jiffies;
ax->rx_packets++;
ax->rx_bytes+=count;
}
/* Encapsulate one AX.25 packet and stuff into a TTY queue. */
static void ax_encaps(struct ax_disp *ax, unsigned char *icp, int len)
{
unsigned char *p;
int actual, count;
if (ax->mtu != ax->dev->mtu + 73) /* Someone has been ifconfigging */
ax_changedmtu(ax);
if (len > ax->mtu) { /* Sigh, shouldn't occur BUT ... */
len = ax->mtu;
printk(KERN_ERR "mkiss: %s: truncating oversized transmit packet!\n", ax->dev->name);
ax->tx_dropped++;
ax_unlock(ax);
return;
}
p = icp;
spin_lock_bh(&ax->buflock);
switch (ax->crcmode) {
unsigned short crc;
case CRC_MODE_FLEX:
*p |= 0x20;
crc = calc_crc_flex(p, len);
count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
break;
default:
count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
break;
}
ax->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
actual = ax->tty->driver->write(ax->tty, ax->xbuff, count);
ax->tx_packets++;
ax->tx_bytes+=actual;
ax->dev->trans_start = jiffies;
ax->xleft = count - actual;
ax->xhead = ax->xbuff + actual;
spin_unlock_bh(&ax->buflock);
}
/*
* Called by the driver when there's room for more data. If we have
* more packets to send, we send them here.
*/
static void ax25_write_wakeup(struct tty_struct *tty)
{
int actual;
struct ax_disp *ax = (struct ax_disp *) tty->disc_data;
/* First make sure we're connected. */
if (ax == NULL || ax->magic != AX25_MAGIC || !netif_running(ax->dev))
return;
if (ax->xleft <= 0) {
/* Now serial buffer is almost free & we can start
* transmission of another packet
*/
tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
netif_wake_queue(ax->dev);
return;
}
actual = tty->driver->write(tty, ax->xhead, ax->xleft);
ax->xleft -= actual;
ax->xhead += actual;
}
/* Encapsulate an AX.25 packet and kick it into a TTY queue. */
static int ax_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct ax_disp *ax = netdev_priv(dev);
if (!netif_running(dev)) {
printk(KERN_ERR "mkiss: %s: xmit call when iface is down\n", dev->name);
return 1;
}
if (netif_queue_stopped(dev)) {
/*
* May be we must check transmitter timeout here ?
* 14 Oct 1994 Dmitry Gorodchanin.
*/
if (jiffies - dev->trans_start < 20 * HZ) {
/* 20 sec timeout not reached */
return 1;
}
printk(KERN_ERR "mkiss: %s: transmit timed out, %s?\n", dev->name,
(ax->tty->driver->chars_in_buffer(ax->tty) || ax->xleft) ?
"bad line quality" : "driver error");
ax->xleft = 0;
ax->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
ax_unlock(ax);
}
/* We were not busy, so we are now... :-) */
if (skb != NULL) {
ax_lock(ax);
ax_encaps(ax, skb->data, skb->len);
kfree_skb(skb);
}
return 0;
}
#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
/* Return the frame type ID */
static int ax_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
void *daddr, void *saddr, unsigned len)
{
#ifdef CONFIG_INET
if (type != htons(ETH_P_AX25))
return ax25_encapsulate(skb, dev, type, daddr, saddr, len);
#endif
return 0;
}
static int ax_rebuild_header(struct sk_buff *skb)
{
#ifdef CONFIG_INET
return ax25_rebuild_header(skb);
#else
return 0;
#endif
}
#endif /* CONFIG_{AX25,AX25_MODULE} */
/* Open the low-level part of the AX25 channel. Easy! */
static int ax_open(struct net_device *dev)
{
struct ax_disp *ax = netdev_priv(dev);
unsigned long len;
if (ax->tty == NULL)
return -ENODEV;
/*
* Allocate the frame buffers:
*
* rbuff Receive buffer.
* xbuff Transmit buffer.
*/
len = dev->mtu * 2;
/*
* allow for arrival of larger UDP packets, even if we say not to
* also fixes a bug in which SunOS sends 512-byte packets even with
* an MSS of 128
*/
if (len < 576 * 2)
len = 576 * 2;
if ((ax->rbuff = kmalloc(len + 4, GFP_KERNEL)) == NULL)
goto norbuff;
if ((ax->xbuff = kmalloc(len + 4, GFP_KERNEL)) == NULL)
goto noxbuff;
ax->mtu = dev->mtu + 73;
ax->buffsize = len;
ax->rcount = 0;
ax->xleft = 0;
ax->flags &= (1 << AXF_INUSE); /* Clear ESCAPE & ERROR flags */
spin_lock_init(&ax->buflock);
netif_start_queue(dev);
return 0;
noxbuff:
kfree(ax->rbuff);
norbuff:
return -ENOMEM;
}
/* Close the low-level part of the AX25 channel. Easy! */
static int ax_close(struct net_device *dev)
{
struct ax_disp *ax = netdev_priv(dev);
if (ax->tty == NULL)
return -EBUSY;
ax->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
netif_stop_queue(dev);
return 0;
}
static int ax25_receive_room(struct tty_struct *tty)
{
return 65536; /* We can handle an infinite amount of data. :-) */
}
/*
* Handle the 'receiver data ready' interrupt.
* This function is called by the 'tty_io' module in the kernel when
* a block of data has been received, which can now be decapsulated
* and sent on to the AX.25 layer for further processing.
*/
static void ax25_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
{
struct ax_disp *ax = (struct ax_disp *) tty->disc_data;
if (ax == NULL || ax->magic != AX25_MAGIC || !netif_running(ax->dev))
return;
/*
* Argh! mtu change time! - costs us the packet part received
* at the change
*/
if (ax->mtu != ax->dev->mtu + 73)
ax_changedmtu(ax);
/* Read the characters out of the buffer */
while (count--) {
if (fp != NULL && *fp++) {
if (!test_and_set_bit(AXF_ERROR, &ax->flags))
ax->rx_errors++;
cp++;
continue;
}
kiss_unesc(ax, *cp++);
}
}
static int ax25_open(struct tty_struct *tty)
{
struct ax_disp *ax = (struct ax_disp *) tty->disc_data;
int err;
/* First make sure we're not already connected. */
if (ax && ax->magic == AX25_MAGIC)
return -EEXIST;
/* OK. Find a free AX25 channel to use. */
if ((ax = ax_alloc()) == NULL)
return -ENFILE;
ax->tty = tty;
tty->disc_data = ax;
if (tty->driver->flush_buffer)
tty->driver->flush_buffer(tty);
/* Restore default settings */
ax->dev->type = ARPHRD_AX25;
/* Perform the low-level AX25 initialization. */
if ((err = ax_open(ax->dev)))
return err;
/* Done. We have linked the TTY line to a channel. */
return ax->dev->base_addr;
}
static void ax25_close(struct tty_struct *tty)
{
struct ax_disp *ax = (struct ax_disp *) tty->disc_data;
/* First make sure we're connected. */
if (ax == NULL || ax->magic != AX25_MAGIC)
return;
unregister_netdev(ax->dev);
tty->disc_data = NULL;
ax->tty = NULL;
ax_free(ax);
}
static struct net_device_stats *ax_get_stats(struct net_device *dev)
{
static struct net_device_stats stats;
struct ax_disp *ax = netdev_priv(dev);
memset(&stats, 0, sizeof(struct net_device_stats));
stats.rx_packets = ax->rx_packets;
stats.tx_packets = ax->tx_packets;
stats.rx_bytes = ax->rx_bytes;
stats.tx_bytes = ax->tx_bytes;
stats.rx_dropped = ax->rx_dropped;
stats.tx_dropped = ax->tx_dropped;
stats.tx_errors = ax->tx_errors;
stats.rx_errors = ax->rx_errors;
stats.rx_over_errors = ax->rx_over_errors;
return &stats;
}
/************************************************************************
* STANDARD ENCAPSULATION *
************************************************************************/
static int kiss_esc(unsigned char *s, unsigned char *d, int len)
{
unsigned char *ptr = d;
unsigned char c;
/*
* Send an initial END character to flush out any
* data that may have accumulated in the receiver
* due to line noise.
*/
*ptr++ = END;
while (len-- > 0) {
switch (c = *s++) {
case END:
*ptr++ = ESC;
*ptr++ = ESC_END;
break;
case ESC:
*ptr++ = ESC;
*ptr++ = ESC_ESC;
break;
default:
*ptr++ = c;
break;
}
}
*ptr++ = END;
return ptr - d;
}
/*
* MW:
* OK its ugly, but tell me a better solution without copying the
* packet to a temporary buffer :-)
*/
static int kiss_esc_crc(unsigned char *s, unsigned char *d, unsigned short crc, int len)
{
unsigned char *ptr = d;
unsigned char c=0;
*ptr++ = END;
while (len > 0) {
if (len > 2)
c = *s++;
else if (len > 1)
c = crc >> 8;
else if (len > 0)
c = crc & 0xff;
len--;
switch (c) {
case END:
*ptr++ = ESC;
*ptr++ = ESC_END;
break;
case ESC:
*ptr++ = ESC;
*ptr++ = ESC_ESC;
break;
default:
*ptr++ = c;
break;
}
}
*ptr++ = END;
return ptr - d;
}
static void kiss_unesc(struct ax_disp *ax, unsigned char s)
{
switch (s) {
case END:
/* drop keeptest bit = VSV */
if (test_bit(AXF_KEEPTEST, &ax->flags))
clear_bit(AXF_KEEPTEST, &ax->flags);
if (!test_and_clear_bit(AXF_ERROR, &ax->flags) && (ax->rcount > 2))
ax_bump(ax);
clear_bit(AXF_ESCAPE, &ax->flags);
ax->rcount = 0;
return;
case ESC:
set_bit(AXF_ESCAPE, &ax->flags);
return;
case ESC_ESC:
if (test_and_clear_bit(AXF_ESCAPE, &ax->flags))
s = ESC;
break;
case ESC_END:
if (test_and_clear_bit(AXF_ESCAPE, &ax->flags))
s = END;
break;
}
spin_lock_bh(&ax->buflock);
if (!test_bit(AXF_ERROR, &ax->flags)) {
if (ax->rcount < ax->buffsize) {
ax->rbuff[ax->rcount++] = s;
spin_unlock_bh(&ax->buflock);
return;
}
ax->rx_over_errors++;
set_bit(AXF_ERROR, &ax->flags);
}
spin_unlock_bh(&ax->buflock);
}
static int ax_set_mac_address(struct net_device *dev, void __user *addr)
{
if (copy_from_user(dev->dev_addr, addr, AX25_ADDR_LEN))
return -EFAULT;
return 0;
}
static int ax_set_dev_mac_address(struct net_device *dev, void *addr)
{
struct sockaddr *sa = addr;
memcpy(dev->dev_addr, sa->sa_data, AX25_ADDR_LEN);
return 0;
}
/* Perform I/O control on an active ax25 channel. */
static int ax25_disp_ioctl(struct tty_struct *tty, void *file, int cmd, void __user *arg)
{
struct ax_disp *ax = (struct ax_disp *) tty->disc_data;
unsigned int tmp;
/* First make sure we're connected. */
if (ax == NULL || ax->magic != AX25_MAGIC)
return -EINVAL;
switch (cmd) {
case SIOCGIFNAME:
if (copy_to_user(arg, ax->dev->name, strlen(ax->dev->name) + 1))
return -EFAULT;
return 0;
case SIOCGIFENCAP:
return put_user(4, (int __user *)arg);
case SIOCSIFENCAP:
if (get_user(tmp, (int __user *)arg))
return -EFAULT;
ax->mode = tmp;
ax->dev->addr_len = AX25_ADDR_LEN; /* sizeof an AX.25 addr */
ax->dev->hard_header_len = AX25_KISS_HEADER_LEN + AX25_MAX_HEADER_LEN + 3;
ax->dev->type = ARPHRD_AX25;
return 0;
case SIOCSIFHWADDR:
return ax_set_mac_address(ax->dev, arg);
default:
return -ENOIOCTLCMD;
}
}
static int ax_open_dev(struct net_device *dev)
{
struct ax_disp *ax = netdev_priv(dev);
if (ax->tty == NULL)
return -ENODEV;
return 0;
}
/* Initialize the driver. Called by network startup. */
static int ax25_init(struct net_device *dev)
{
struct ax_disp *ax = netdev_priv(dev);
static char ax25_bcast[AX25_ADDR_LEN] =
{'Q'<<1,'S'<<1,'T'<<1,' '<<1,' '<<1,' '<<1,'0'<<1};
static char ax25_test[AX25_ADDR_LEN] =
{'L'<<1,'I'<<1,'N'<<1,'U'<<1,'X'<<1,' '<<1,'1'<<1};
if (ax == NULL) /* Allocation failed ?? */
return -ENODEV;
/* Set up the "AX25 Control Block". (And clear statistics) */
memset(ax, 0, sizeof (struct ax_disp));
ax->magic = AX25_MAGIC;
ax->dev = dev;
/* Finish setting up the DEVICE info. */
dev->mtu = AX_MTU;
dev->hard_start_xmit = ax_xmit;
dev->open = ax_open_dev;
dev->stop = ax_close;
dev->get_stats = ax_get_stats;
dev->set_mac_address = ax_set_dev_mac_address;
dev->hard_header_len = 0;
dev->addr_len = 0;
dev->type = ARPHRD_AX25;
dev->tx_queue_len = 10;
dev->hard_header = ax_header;
dev->rebuild_header = ax_rebuild_header;
memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN);
/* New-style flags. */
dev->flags = IFF_BROADCAST | IFF_MULTICAST;
return 0;
}
/* ******************************************************************** */
/* * Init MKISS driver * */
/* ******************************************************************** */
static int __init mkiss_init_driver(void)
{
int status;
printk(banner);
if (ax25_maxdev < 4)
ax25_maxdev = 4; /* Sanity */
if ((ax25_ctrls = kmalloc(sizeof(void *) * ax25_maxdev, GFP_KERNEL)) == NULL) {
printk(KERN_ERR "mkiss: Can't allocate ax25_ctrls[] array!\n");
return -ENOMEM;
}
/* Clear the pointer array, we allocate devices when we need them */
memset(ax25_ctrls, 0, sizeof(void*) * ax25_maxdev); /* Pointers */
/* Fill in our line protocol discipline, and register it */
ax_ldisc.magic = TTY_LDISC_MAGIC;
ax_ldisc.name = "mkiss";
ax_ldisc.open = ax25_open;
ax_ldisc.close = ax25_close;
ax_ldisc.ioctl = (int (*)(struct tty_struct *, struct file *,
unsigned int, unsigned long))ax25_disp_ioctl;
ax_ldisc.receive_buf = ax25_receive_buf;
ax_ldisc.receive_room = ax25_receive_room;
ax_ldisc.write_wakeup = ax25_write_wakeup;
if ((status = tty_register_ldisc(N_AX25, &ax_ldisc)) != 0) {
printk(KERN_ERR "mkiss: can't register line discipline (err = %d)\n", status);
kfree(ax25_ctrls);
}
return status;
}
static void __exit mkiss_exit_driver(void)
{
int i;
for (i = 0; i < ax25_maxdev; i++) {
if (ax25_ctrls[i]) {
/*
* VSV = if dev->start==0, then device
* unregistered while close proc.
*/
if (netif_running(&ax25_ctrls[i]->dev))
unregister_netdev(&ax25_ctrls[i]->dev);
kfree(ax25_ctrls[i]);
}
}
kfree(ax25_ctrls);
ax25_ctrls = NULL;
if ((i = tty_register_ldisc(N_AX25, NULL)))
printk(KERN_ERR "mkiss: can't unregister line discipline (err = %d)\n", i);
}
MODULE_AUTHOR("Hans Albas PE1AYX <hans@esrac.ele.tue.nl>");
MODULE_DESCRIPTION("KISS driver for AX.25 over TTYs");
MODULE_PARM(ax25_maxdev, "i");
MODULE_PARM_DESC(ax25_maxdev, "number of MKISS devices");
MODULE_LICENSE("GPL");
MODULE_ALIAS_LDISC(N_AX25);
module_init(mkiss_init_driver);
module_exit(mkiss_exit_driver);

View File

@@ -0,0 +1,62 @@
/****************************************************************************
* Defines for the Multi-KISS driver.
****************************************************************************/
#define AX25_MAXDEV 16 /* MAX number of AX25 channels;
This can be overridden with
insmod -oax25_maxdev=nnn */
#define AX_MTU 236
/* SLIP/KISS protocol characters. */
#define END 0300 /* indicates end of frame */
#define ESC 0333 /* indicates byte stuffing */
#define ESC_END 0334 /* ESC ESC_END means END 'data' */
#define ESC_ESC 0335 /* ESC ESC_ESC means ESC 'data' */
struct ax_disp {
int magic;
/* Various fields. */
struct tty_struct *tty; /* ptr to TTY structure */
struct net_device *dev; /* easy for intr handling */
/* These are pointers to the malloc()ed frame buffers. */
unsigned char *rbuff; /* receiver buffer */
int rcount; /* received chars counter */
unsigned char *xbuff; /* transmitter buffer */
unsigned char *xhead; /* pointer to next byte to XMIT */
int xleft; /* bytes left in XMIT queue */
/* SLIP interface statistics. */
unsigned long rx_packets; /* inbound frames counter */
unsigned long tx_packets; /* outbound frames counter */
unsigned long rx_bytes; /* inbound bytes counter */
unsigned long tx_bytes; /* outbound bytes counter */
unsigned long rx_errors; /* Parity, etc. errors */
unsigned long tx_errors; /* Planned stuff */
unsigned long rx_dropped; /* No memory for skb */
unsigned long tx_dropped; /* When MTU change */
unsigned long rx_over_errors; /* Frame bigger then SLIP buf. */
/* Detailed SLIP statistics. */
int mtu; /* Our mtu (to spot changes!) */
int buffsize; /* Max buffers sizes */
unsigned long flags; /* Flag values/ mode etc */
/* long req'd: used by set_bit --RR */
#define AXF_INUSE 0 /* Channel in use */
#define AXF_ESCAPE 1 /* ESC received */
#define AXF_ERROR 2 /* Parity, etc. error */
#define AXF_KEEPTEST 3 /* Keepalive test flag */
#define AXF_OUTWAIT 4 /* is outpacket was flag */
int mode;
int crcmode; /* MW: for FlexNet, SMACK etc. */
#define CRC_MODE_NONE 0
#define CRC_MODE_FLEX 1
#define CRC_MODE_SMACK 2
spinlock_t buflock; /* lock for rbuf and xbuf */
};
#define AX25_MAGIC 0x5316

2191
drivers/net/hamradio/scc.c Normal file

File diff suppressed because it is too large Load Diff

1218
drivers/net/hamradio/yam.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,343 @@
/*
*
* File yam1k2b5.mcs converted to h format by mcs2h
*
* (C) F6FBB 1998
*
* Tue Aug 25 20:24:08 1998
*
*/
static unsigned char bits_1200[]= {
0xff,0xf2,0x00,0xa5,0xad,0xff,0xfe,0x9f,0xff,0xef,0xf3,0xcb,0xff,0xdb,0xfc,0xf2,
0xff,0xf6,0xff,0x3c,0xbf,0xfd,0xbf,0xdf,0x6e,0x3f,0x6f,0xf1,0x7d,0xb4,0xfd,0xbf,
0xdf,0x6f,0x3f,0x6f,0xf7,0x0b,0xff,0xdb,0xfd,0xf2,0xff,0xf6,0xff,0xff,0xff,0xff,
0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xdf,0xff,0xff,0xff,0xef,0xff,0xff,0xff,
0xfd,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xbf,
0xff,0xff,0xf7,0xff,0xff,0xfb,0xff,0xff,0xff,0xfc,0xff,0xfe,0xff,0xff,0xff,0xf0,
0x5f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xf7,0xff,0xff,0xff,0xf1,0xff,0xff,0xfe,0x7f,0xbf,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf7,0xff,0xfb,0xff,0xff,0xff,0xf0,0x9f,
0xff,0xff,0xff,0xfe,0xff,0xfd,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xf7,0xff,
0xff,0xff,0xfb,0xff,0xfb,0xff,0xff,0xff,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xf7,0xff,0xff,0xfb,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xef,0xff,0xf0,0x5f,0xff,
0xff,0xff,0xfe,0xff,0xff,0xef,0xff,0xff,0xfb,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xbf,0xff,0xff,0xdf,0xf7,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xfb,0xfe,0xff,0xff,0xff,0xff,0xff,0xf0,0xff,0xff,0xff,
0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xeb,
0xff,0xff,0xff,0xfd,0xff,0xbf,0xf1,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xfb,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x6f,0xff,0xff,0xff,
0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xf7,0xff,0xff,0xf1,0xff,0xff,0xf7,0xbf,0xe7,0xff,0xff,0xff,0xff,0xfb,
0xff,0xff,0xff,0xff,0xff,0xff,0x77,0xff,0xff,0xff,0xf0,0xff,0xff,0xff,0xff,0xfe,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x1f,0xff,0xff,0xff,0xfe,0xdb,
0xff,0xff,0xf5,0xa5,0xfd,0x4b,0x6e,0xef,0x33,0x32,0xdd,0xd3,0x4a,0xd6,0x92,0xfe,
0xb3,0x3f,0xbd,0xf1,0xfa,0xdb,0xfe,0xf7,0xf6,0x96,0xbd,0xbd,0xff,0xbd,0xff,0xed,
0x7f,0x6b,0x7f,0xfb,0xdf,0xfe,0xfb,0xfe,0x90,0xcf,0xff,0xff,0xff,0xfe,0xbe,0xef,
0xff,0xff,0xdb,0x5f,0xf6,0xff,0xf6,0x8f,0xfd,0xa5,0xdd,0xff,0xff,0xff,0xff,0x6f,
0x7f,0xdb,0xf1,0xfc,0xbf,0xff,0x6f,0xff,0xef,0xfc,0x5b,0x5d,0xda,0xdf,0xf4,0xff,
0xf2,0xff,0xfd,0xbf,0xff,0xff,0xff,0xd0,0x1f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,
0xff,0xfb,0xef,0xb7,0xfc,0x33,0xff,0xfb,0xff,0x04,0x6a,0xf3,0x3c,0x36,0xff,0xf0,
0x0f,0xf1,0x0f,0xff,0xff,0xff,0xf3,0x15,0x72,0x0f,0xf1,0x6f,0xff,0xfe,0x94,0x3f,
0xff,0xff,0xff,0x7b,0xff,0xff,0xf0,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf0,
0xf7,0xef,0xb7,0xfc,0x33,0xff,0xff,0xff,0x04,0x6a,0xf3,0x3c,0x36,0xff,0xf0,0x0f,
0xf1,0x0f,0xff,0xff,0xff,0xf3,0x15,0x73,0x8f,0xf2,0x6f,0xff,0xfe,0x94,0x3f,0xff,
0xff,0xff,0x7d,0x9f,0xff,0xf0,0x0f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0x9e,
0xff,0xfc,0xef,0xd3,0xfb,0xff,0x7f,0xf5,0x5f,0xfe,0x59,0xff,0xff,0xff,0xfc,0xf1,
0xfe,0x7f,0xff,0xff,0xfa,0x17,0xff,0xe7,0xef,0xef,0xff,0xff,0x3f,0xf1,0xff,0xff,
0xff,0xff,0xff,0xff,0xf0,0xff,0xff,0xff,0xff,0xfe,0xf5,0xff,0xbf,0xff,0xfc,0xea,
0xff,0xf0,0xff,0xff,0xbf,0xf9,0x3f,0xb1,0xef,0xff,0xd7,0xff,0xfb,0xff,0xf0,0xff,
0xff,0xf3,0xff,0xdf,0xff,0x7b,0xff,0xfd,0xff,0xf6,0xff,0xbf,0xff,0xff,0xbf,0xff,
0xff,0xff,0xda,0xf0,0xff,0xff,0xff,0xff,0xfe,0xf2,0xc0,0x01,0x00,0x00,0x02,0x02,
0x02,0x02,0x00,0x40,0x40,0x40,0x10,0x00,0x00,0x00,0x20,0x00,0x00,0x01,0x00,0x00,
0x00,0x00,0x00,0x00,0x19,0x00,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,
0x00,0x3c,0xf0,0xaf,0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xff,0xfb,0xff,0xfd,0xff,
0xff,0x7f,0xff,0xff,0xbf,0xff,0xef,0xff,0xff,0xfd,0xff,0xff,0xf1,0xff,0xdf,0xff,
0xff,0xff,0xff,0xff,0xff,0xbf,0xfe,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xdf,
0xdb,0xf0,0x6f,0xff,0xff,0xff,0xfe,0xf0,0xbf,0xdf,0xff,0x7f,0xff,0xff,0xff,0xff,
0xdf,0xdf,0xff,0xef,0xff,0x9e,0xef,0xff,0xff,0x7f,0xff,0xf1,0xef,0xff,0xff,0xff,
0xf7,0xfa,0xbf,0xff,0xff,0xfe,0x47,0xef,0xff,0xbd,0xf6,0xff,0xff,0xdf,0xf5,0xf0,
0xf0,0xef,0xff,0xff,0xff,0xfe,0xf8,0x30,0x00,0x00,0x00,0x04,0x00,0x01,0x02,0x08,
0x16,0x00,0x00,0x00,0x80,0x00,0x01,0x02,0x00,0x80,0x01,0x0c,0x02,0x00,0x00,0x01,
0x00,0x00,0x20,0x00,0x00,0x06,0x00,0x20,0x00,0x10,0x00,0x14,0x00,0x04,0xc1,0xf0,
0x2f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfb,0xff,0xff,0x7f,
0xec,0xff,0xff,0xfa,0xff,0xbf,0xff,0x6f,0xff,0xe1,0xff,0xff,0xff,0xff,0xbd,0xfe,
0x46,0xff,0xef,0x7f,0xcd,0xdf,0xff,0xff,0xfd,0xff,0xbd,0xff,0x7f,0x7f,0xf0,0x4f,
0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,
0xff,0xff,0xfe,0xff,0xff,0xff,0xfd,0xa4,0xbc,0xcd,0x6d,0x6b,0x6f,0x5b,0xdc,0x33,
0x5a,0xf6,0xf7,0xf6,0xb3,0x3f,0xbd,0xc1,0xfa,0x5a,0xf6,0xf6,0xb6,0xf7,0xff,0xbd,
0xbb,0x3c,0xce,0xcf,0x34,0xef,0x33,0xbb,0xcc,0xff,0xff,0xff,0xf0,0x4f,0xff,0xff,
0xff,0xfe,0xbf,0xff,0xff,0xff,0xdb,0xff,0xf6,0xd6,0xff,0xfd,0xfd,0xbf,0xff,0xad,
0xbf,0xf9,0x7f,0x6f,0xfc,0xdb,0xf1,0xfd,0xbf,0xff,0x6f,0xff,0xff,0xda,0xdb,0xfc,
0xdb,0xff,0x76,0x8f,0xf6,0xff,0xcd,0xab,0xfe,0xfb,0xff,0xd0,0xff,0xff,0xff,0xff,
0xfe,0xff,0x9f,0xff,0xf4,0x20,0xaf,0x6d,0x0b,0xc1,0x7b,0xff,0xff,0xff,0xcb,0xff,
0x3f,0xf0,0xef,0x7f,0x0f,0xf1,0xc3,0x3c,0xff,0xff,0xff,0xff,0xff,0xff,0xf8,0x0b,
0x1d,0x6a,0x64,0x05,0x6b,0x99,0x01,0xff,0xfd,0xef,0xf0,0x2f,0xff,0xff,0xff,0xfe,
0xff,0xff,0xff,0xf4,0x00,0x2f,0xcc,0x0b,0xc3,0x7f,0xff,0xff,0xff,0x0a,0xdf,0xbf,
0xfd,0x7f,0xff,0xff,0xf1,0xc3,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x4a,0x0e,
0x96,0x64,0x02,0x97,0x99,0x10,0xff,0xff,0xff,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xff,
0xff,0xff,0xfe,0x84,0xf9,0xd5,0x27,0xf1,0x7f,0xff,0xf8,0xeb,0xdf,0xf3,0xcf,0x3f,
0x1f,0xff,0xf7,0x11,0xff,0xcf,0xff,0xfe,0x67,0xff,0xff,0xff,0xff,0xc4,0xff,0xff,
0xb3,0xa1,0xff,0xf9,0xe0,0xff,0xff,0xff,0xf0,0xef,0xff,0xff,0xff,0xfe,0xf5,0xff,
0xff,0xfb,0x7f,0xe0,0xff,0xc7,0xfe,0x7f,0x3f,0xff,0xfd,0x77,0x8d,0x7f,0x0f,0xff,
0xc3,0xff,0xf1,0xbf,0x8f,0xcf,0xff,0xff,0xdd,0x7b,0xff,0xf6,0xfa,0xf7,0xff,0x40,
0x9f,0xf9,0x7f,0xd8,0xff,0xff,0xfa,0xf0,0x1f,0xff,0xff,0xff,0xfe,0xf1,0xc0,0x00,
0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x10,0x00,0x00,0x10,
0x00,0x01,0x00,0x10,0x20,0x20,0x00,0x00,0x10,0x00,0x04,0x01,0x05,0x00,0x00,0x00,
0x00,0x40,0x40,0x00,0x00,0x3c,0xf0,0x1f,0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xff,
0xff,0xff,0xfe,0x7f,0x7f,0xff,0xef,0xff,0xff,0xdf,0xff,0xff,0xdf,0xff,0xef,0xf7,
0xf1,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xf7,0xff,0xff,0xff,0xfc,0xfd,0xff,0x7f,
0x7e,0xff,0xff,0xff,0xdb,0xf0,0x6f,0xff,0xff,0xff,0xfe,0xf0,0xbb,0xff,0xff,0xff,
0xff,0xff,0xfe,0xeb,0xfd,0x6f,0xff,0xf7,0xfe,0xf5,0x7f,0xff,0xff,0x7f,0xbf,0xb1,
0xff,0xff,0x9f,0xbf,0xfb,0xff,0xfe,0xff,0xfe,0xff,0xf7,0xeb,0xdf,0xbf,0x5f,0xdd,
0xff,0xdb,0xfd,0xd0,0xf0,0x6f,0xff,0xff,0xff,0xfe,0xf8,0x30,0x20,0x00,0x42,0x00,
0x00,0x00,0x30,0x18,0x04,0x08,0x09,0x21,0x82,0x80,0x02,0x00,0x08,0x00,0x01,0x00,
0x00,0x00,0x0c,0x20,0x10,0x00,0x11,0x00,0x44,0x84,0x00,0x20,0x20,0x84,0x80,0x00,
0x00,0x00,0xc1,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xff,0xf7,0xff,0xfb,0xdd,0xf9,0xff,
0xda,0xff,0xdc,0xdd,0xfc,0xfb,0xff,0xbf,0xfb,0x3e,0xd7,0x96,0xfe,0x61,0xf7,0xff,
0x7f,0xff,0x3f,0xfd,0xff,0xdf,0xcf,0xf7,0xdf,0xf7,0xbf,0xfd,0xff,0xfe,0xef,0xef,
0xfe,0xff,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xf0,0x2f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf3,0xbd,0xfd,0x4b,0x74,0xcf,
0x73,0x5b,0xcb,0x3b,0xdf,0xfe,0xf7,0xfe,0xd3,0x75,0xac,0xa1,0xfb,0xdf,0xfe,0xf7,
0x76,0x96,0xb5,0x24,0xbd,0xa5,0xad,0x49,0x2f,0x69,0x2b,0x52,0x5b,0xbd,0xff,0xff,
0xf0,0xcf,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,0xff,0xdb,0xff,0xf6,0xfe,0xff,0xcc,
0xa7,0xfb,0xad,0xff,0x7f,0x6f,0xff,0x6d,0x7f,0xdb,0xf1,0xfd,0xbf,0xff,0x6f,0xff,
0x6f,0xff,0xdb,0xff,0xdb,0xff,0xf6,0x97,0xf6,0xff,0xb5,0xb5,0xff,0xff,0xff,0xd0,
0xef,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xfd,0xa5,0xbc,0x43,0xfc,0x7c,0x03,0xe7,
0xff,0xff,0x20,0xff,0xff,0xff,0xcc,0xfd,0x7d,0xf1,0xff,0xff,0xff,0xff,0xd5,0x59,
0xba,0x56,0x66,0x6a,0xad,0x9a,0xa9,0x9a,0x97,0xa5,0xaa,0xbb,0xff,0xff,0xf0,0x0f,
0xff,0xff,0xff,0xfe,0xfe,0xfb,0xff,0xfd,0xf7,0xfd,0x43,0xff,0xfd,0x6b,0xe7,0xff,
0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0x3f,0xf1,0xff,0xff,0xff,0xff,0xd5,0x59,0xb5,
0xa6,0x66,0x6a,0xad,0x9a,0xa9,0x99,0x6b,0x5a,0xaa,0xff,0xff,0xb7,0xf0,0x3f,0xff,
0xff,0xff,0xfe,0xff,0xff,0xff,0xfe,0x9c,0xf7,0xfd,0xd2,0x41,0xff,0xff,0xf2,0x7f,
0x8f,0xff,0xff,0x3d,0xf3,0xff,0x17,0xf1,0xff,0xff,0xff,0xff,0xff,0x7f,0xdf,0xfc,
0x8f,0x38,0xff,0xef,0x23,0xff,0xfb,0xf7,0xc8,0xff,0xff,0xff,0xf0,0x9f,0xff,0xff,
0xff,0xfe,0xf5,0x7f,0xff,0xfd,0xff,0xe4,0xff,0xeb,0xff,0xcf,0xbf,0xfa,0xff,0xab,
0xef,0xff,0xfb,0xff,0xf3,0xfd,0x61,0xff,0xff,0xff,0xff,0xfa,0xff,0xfb,0xfd,0x0d,
0xff,0xfe,0xff,0x43,0x7f,0xfe,0xbf,0xd0,0xfd,0xff,0xfa,0xf0,0x3f,0xff,0xff,0xff,
0xfe,0xf3,0xc0,0x00,0x00,0x00,0x02,0x00,0x02,0x01,0x00,0x60,0xc0,0x40,0x00,0x00,
0x00,0x00,0x34,0x04,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x88,0x00,
0x00,0x03,0x00,0x00,0x40,0x00,0x40,0x00,0x00,0x3c,0xf0,0x3f,0xff,0xff,0xff,0xfe,
0xfd,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x7f,0xbf,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xf7,0xf1,0xff,0xff,0xff,0xff,0xff,0xf7,0xff,0xff,0xff,0xfd,0xff,
0xff,0xff,0xff,0xfe,0xfe,0x5f,0xff,0xff,0xcb,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xf0,
0xff,0xff,0xfd,0xff,0xef,0xe3,0xde,0xee,0xd9,0xc5,0x93,0xff,0xff,0xfe,0xfe,0xff,
0xfb,0xee,0xfe,0xf1,0xff,0xff,0xff,0xff,0xff,0xfd,0xff,0xbf,0xf7,0xff,0xff,0x7f,
0xaf,0xbd,0xdf,0xdf,0xfb,0xf3,0xf3,0xf0,0xf0,0xaf,0xff,0xff,0xff,0xfe,0xf8,0x34,
0x00,0x06,0x61,0x00,0x18,0x01,0xa0,0x05,0x17,0x00,0x20,0x05,0x28,0x20,0x00,0x00,
0x05,0x00,0x41,0x00,0x00,0x40,0x00,0x09,0x00,0x01,0x20,0x86,0x82,0x08,0x40,0x03,
0x80,0x30,0x70,0x08,0x14,0x02,0xc1,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,
0xff,0xff,0xbd,0xef,0xfb,0xff,0xff,0xfb,0x9c,0x7f,0xef,0xdf,0xff,0xbf,0xeb,0xde,
0xff,0xc1,0x7f,0xff,0xfb,0x7f,0xff,0xff,0xff,0x5f,0xff,0xff,0xff,0xdf,0xbf,0xef,
0x3f,0xf7,0x8f,0xef,0x7f,0xff,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xf0,0x3f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xbd,
0xdf,0xef,0x7d,0x6d,0x2b,0x5a,0x5d,0xd2,0xdf,0xf6,0x92,0xb6,0xb2,0xb3,0xac,0xa1,
0xfb,0xdf,0xfe,0xf1,0xee,0xf5,0xf6,0xbc,0x6b,0xbd,0x7d,0xaf,0x1a,0xef,0x5f,0x6b,
0xc6,0xff,0xff,0xff,0xf0,0x5f,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,0xff,0xdb,0xff,
0xf6,0xff,0xf6,0xb7,0xfd,0xad,0xfd,0xbf,0xf3,0x6f,0xff,0x6f,0xff,0xdb,0xd1,0xfd,
0xbf,0xff,0x6f,0xf5,0x6b,0xbc,0x5b,0x3c,0xda,0xef,0x16,0xaf,0x16,0xff,0xcd,0xab,
0xff,0x6f,0xff,0xd0,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xfc,0xbf,0xff,0xff,
0xff,0x6c,0x03,0x10,0xc1,0xf3,0xff,0xf3,0x3a,0xf3,0xca,0xff,0xaf,0xf1,0xff,0xff,
0xff,0xff,0xd9,0x96,0xa6,0x65,0xa6,0x66,0x6a,0x95,0x69,0x69,0x6a,0x5a,0x5a,0xff,
0xff,0x5f,0xf0,0x1f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xbf,0xff,0xff,0xff,
0xea,0x0f,0x50,0xc3,0xf3,0x7f,0xff,0xf3,0xf3,0xc3,0xff,0xaf,0xf1,0xff,0xff,0xff,
0xff,0xd9,0x96,0xa6,0x65,0xa6,0x66,0x6a,0x95,0x69,0x69,0x6a,0x5a,0x5a,0xff,0xff,
0xff,0xf0,0x3f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xd7,0xff,0xff,0x5f,0xc1,
0x3f,0xf7,0x5e,0xf5,0xce,0x9e,0x5f,0x3f,0x17,0xff,0xf3,0xe1,0xff,0xff,0xff,0xff,
0xd8,0xff,0xfa,0xfe,0x67,0xff,0xfe,0xbf,0x5a,0xff,0xff,0xaf,0xf5,0xff,0xff,0xff,
0xf0,0x2f,0xff,0xff,0xff,0xfe,0xf5,0xff,0xff,0xfd,0xff,0xf7,0xff,0xfd,0x4e,0x3d,
0x3f,0xe7,0x0b,0xbf,0x8f,0xf9,0xff,0xeb,0xe3,0xff,0xe1,0xff,0xff,0xfc,0xff,0xc7,
0x9f,0xff,0x3e,0x39,0xe5,0xff,0xcf,0x9b,0xf9,0xff,0xff,0xc5,0xff,0xff,0xfa,0xf0,
0x5f,0xff,0xff,0xff,0xfe,0xf3,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,
0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x20,0x00,0x20,
0x00,0x01,0x10,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0xf0,0x4f,
0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xbf,
0x3f,0xff,0xff,0xbf,0xff,0xff,0xff,0xfb,0xf1,0xff,0xff,0xff,0xff,0xf7,0xff,0xf7,
0xff,0xed,0xff,0xfb,0xfe,0xff,0x7f,0xff,0x7f,0xdf,0xff,0xff,0xdd,0xf0,0x3f,0xff,
0xff,0xff,0xfe,0xf0,0xff,0xff,0xf3,0xff,0xf7,0xff,0xfe,0x5f,0xff,0xf7,0xff,0xff,
0xdf,0xff,0xff,0xff,0xf7,0xfe,0x7b,0xf1,0xff,0xfd,0xfd,0xff,0xdf,0xdf,0xff,0x7d,
0x73,0xf9,0xff,0xc3,0x7e,0xfe,0xff,0xef,0xd7,0xff,0xcf,0xd0,0xf0,0x6f,0xff,0xff,
0xff,0xfe,0xf8,0x30,0x00,0x00,0x40,0x04,0x00,0x01,0x41,0x20,0x00,0x04,0x00,0x02,
0xd5,0x09,0x00,0x02,0x80,0x02,0x01,0x00,0x00,0x00,0x0a,0x04,0x00,0x07,0x00,0x01,
0x50,0x01,0x80,0x02,0x61,0x40,0x41,0x0c,0x14,0x08,0xc1,0xf0,0x9f,0xff,0xff,0xff,
0xfe,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xfe,0xdf,0xcb,0x5f,0xfe,0xef,0xff,0xfe,
0xff,0x3f,0xff,0x7f,0xfd,0xc1,0xff,0xff,0x7f,0xff,0xdf,0xfd,0xfc,0xfd,0xf7,0xee,
0xff,0xff,0x4e,0xff,0xdf,0xcf,0xdb,0xeb,0xff,0xff,0xf0,0x1f,0xff,0xff,0xff,0xfe,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x2f,0xff,0xff,0xff,0xfe,0x7f,
0xff,0xff,0xff,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,
0xf7,0xfb,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0x7f,0xff,0xff,0xff,0x7f,0xff,0xf0,0x1f,0xff,0xff,0xff,0xfe,0xdd,0xff,
0xff,0xff,0xa5,0xff,0x6f,0x6b,0xe9,0x6f,0xda,0xca,0xfb,0xdd,0xee,0xf7,0xf6,0xb2,
0xb3,0xa4,0xa1,0x5b,0x5b,0xf6,0xd7,0xf4,0xf7,0x7b,0xbd,0xbd,0xad,0xcf,0xef,0x7f,
0x6b,0x7f,0x3b,0xdf,0xdb,0xff,0xff,0x30,0xcf,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,
0xff,0xff,0xff,0xf6,0xfe,0x96,0xff,0xfd,0xb5,0xfd,0xbf,0xad,0x7f,0xff,0x6f,0xff,
0xde,0xd1,0xad,0xad,0xe9,0xff,0xf1,0xec,0xef,0xde,0x3f,0xcb,0xff,0xf6,0xff,0x32,
0xff,0xc5,0xbd,0xff,0xff,0xff,0xd0,0xbf,0xff,0xff,0xff,0xfe,0xfe,0xfb,0xff,0xf4,
0x28,0xbf,0xff,0xfd,0xfb,0xd3,0xff,0xff,0x42,0xff,0xff,0xff,0xea,0xb3,0xfc,0xc3,
0xc1,0xff,0x33,0xff,0xc0,0x15,0x6b,0x70,0xff,0xf0,0xf2,0x4f,0xff,0xfc,0x3e,0x97,
0x3c,0xff,0xff,0xfd,0xef,0xf0,0xbf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xfe,0x78,
0xbf,0xff,0xfd,0xf3,0xef,0x55,0xff,0x7e,0xff,0xff,0xff,0xea,0xb3,0xfc,0xc3,0xc1,
0xff,0x33,0xff,0xc0,0x15,0x6f,0xff,0x0f,0xf0,0xf0,0x0f,0xff,0xfc,0x3d,0x6b,0xc3,
0xff,0xff,0xfe,0xf7,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xfc,0xff,
0xff,0x23,0xf8,0x7f,0xff,0x4e,0xff,0xff,0xff,0xfb,0xf9,0x17,0xff,0xf6,0xf1,0xff,
0xcf,0xef,0xff,0xff,0x13,0xdf,0xe6,0x2f,0xc7,0xff,0xff,0xe7,0xc1,0xfd,0xff,0xfe,
0xff,0xff,0xff,0xf0,0x4f,0xff,0xff,0xff,0xfe,0xf5,0xff,0xff,0xff,0xfe,0xae,0xff,
0xff,0x7f,0x3b,0x3f,0xfc,0x7f,0xfc,0xef,0xff,0xfc,0xe2,0x7b,0xff,0xf1,0xfd,0xed,
0xef,0xff,0xff,0x35,0x73,0xff,0xff,0xfe,0xfa,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,
0xff,0xfa,0xf0,0x8f,0xff,0xff,0xff,0xfe,0xf1,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x80,0x00,0x00,0x40,0x00,0x00,0x00,0x0c,0x04,0x01,0x40,0x40,0x00,
0x00,0x30,0x28,0x04,0x00,0x08,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,
0x38,0xf0,0x0f,0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xff,0xff,0xff,0xfb,0xff,0x7f,
0xff,0xff,0x9f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xdf,0xdf,0xff,
0xff,0xff,0xff,0xed,0xff,0xfd,0xff,0xff,0xff,0xff,0xff,0xbf,0xbf,0xff,0xff,0xc3,
0xf0,0x3f,0xff,0xff,0xff,0xfe,0xf0,0xbf,0xfd,0xff,0xbf,0xff,0xff,0xfd,0xff,0xff,
0xff,0xff,0xff,0xfd,0x7b,0xff,0x7f,0xff,0xbd,0xff,0xf1,0xef,0xff,0xff,0xfd,0xdf,
0xfd,0xfb,0xff,0xff,0xbf,0xbe,0xff,0xcd,0x7f,0xfc,0xf7,0xf7,0x6f,0xbf,0xd8,0xf0,
0xef,0xff,0xff,0xff,0xfe,0xf8,0x30,0x00,0x00,0x00,0x04,0x00,0x00,0xa0,0x00,0x00,
0xc0,0x00,0x00,0x20,0x34,0x00,0x00,0x00,0x0c,0x81,0x00,0x20,0xa4,0x20,0x00,0x10,
0x08,0x04,0x48,0x08,0x00,0x40,0x93,0x00,0x10,0x00,0x38,0x18,0x20,0xc1,0xf0,0x3f,
0xff,0xff,0xff,0xfe,0xff,0xfb,0xff,0xff,0xb9,0xdf,0xfe,0xb3,0xff,0xff,0xe7,0xfd,
0xff,0xff,0x3b,0xff,0x7f,0xff,0xbf,0xff,0xc1,0xff,0xfc,0xff,0xff,0x3f,0x77,0xfe,
0xfe,0xcf,0xff,0xbf,0xfd,0xbf,0xff,0xfe,0xed,0xf2,0xfd,0xf7,0xff,0xf0,0x2f,0xff,
0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xbf,0xff,0xff,
0xff,0xfe,0xff,0xff,0xff,0xf3,0xad,0xcf,0xef,0x70,0xc9,0x73,0x3b,0xdf,0x5b,0x4a,
0xf6,0xb7,0xfe,0xd7,0xf5,0xbc,0xc1,0x33,0xca,0xd6,0xb7,0x6e,0xf7,0xfb,0xbd,0xc5,
0x24,0xcf,0x6f,0x2f,0x4d,0x2b,0xba,0x5a,0xff,0xff,0xff,0xf0,0xaf,0xff,0xff,0xff,
0xfe,0xbf,0xff,0xff,0xff,0xff,0xf6,0xf6,0xd7,0xff,0xff,0xad,0xbd,0xff,0xff,0xff,
0xef,0xf7,0x7f,0xfc,0x5b,0xb1,0xfd,0xbd,0x75,0x6f,0xef,0x6a,0xfd,0x5b,0xfb,0xdb,
0x3a,0xbf,0x8e,0x9f,0xff,0xbf,0xfd,0xff,0x6f,0xff,0xd0,0x6f,0xff,0xff,0xff,0xfe,
0xff,0xbb,0xff,0xf0,0x3f,0xff,0xff,0xfd,0xfb,0x7f,0xde,0xff,0xff,0x5a,0xd6,0xbf,
0xd8,0x2a,0xbf,0xbf,0xf1,0xe5,0xff,0xcc,0xc0,0xa9,0x70,0xff,0xf3,0x3c,0x3c,0xfd,
0x57,0xfd,0x98,0x03,0x00,0xc3,0xff,0xff,0xff,0xf0,0xaf,0xff,0xff,0xff,0xfe,0xff,
0xff,0xff,0xff,0x3d,0xbf,0xff,0xfd,0xfb,0xff,0xdb,0xff,0xff,0x0f,0xfc,0x3f,0xd8,
0x2a,0xbf,0xbf,0xf1,0xef,0xff,0xcc,0xc0,0x96,0xbe,0xff,0xf3,0x3f,0xff,0xfd,0x57,
0xfd,0x99,0x0f,0xff,0xc3,0xff,0xff,0xff,0xf0,0x4f,0xff,0xff,0xff,0xfe,0xff,0xff,
0xff,0xf1,0xe7,0xff,0xff,0xf3,0x8e,0x7b,0xff,0xa8,0xff,0xdf,0x7f,0x8e,0x78,0x73,
0xff,0xf1,0x51,0x62,0xff,0xfc,0x4b,0xff,0xf3,0xff,0x7e,0xcf,0xf9,0xff,0xfd,0xff,
0xff,0x7f,0xff,0xe0,0xff,0xff,0xff,0xf0,0x4f,0xff,0xff,0xff,0xfe,0xf5,0xff,0xff,
0xfb,0xfd,0xae,0xff,0xfc,0xfe,0x6f,0x3f,0xf8,0xfd,0x77,0xaf,0xfe,0x37,0xfe,0x7b,
0xff,0xb1,0x8c,0xff,0xef,0xfd,0xf8,0xe7,0xbf,0xff,0xf1,0xfe,0x3e,0xf7,0xfe,0x95,
0x3e,0xbf,0xff,0xff,0xff,0xfa,0xf0,0xbf,0xff,0xff,0xff,0xfe,0xf1,0xc0,0x00,0x00,
0x01,0x04,0x00,0x00,0x00,0x00,0x80,0x02,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x08,
0x41,0x80,0x10,0x00,0x00,0x08,0x10,0x84,0x00,0x0c,0x04,0x02,0x61,0x00,0x00,0x81,
0x00,0x00,0x00,0x00,0x3d,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xff,0xff,
0xff,0xff,0x7f,0xff,0xfe,0xfd,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,
0x7f,0xbf,0xf7,0x7f,0xef,0xff,0xef,0xff,0xf7,0xfd,0xff,0xff,0xfd,0x7f,0xff,0xbe,
0xdf,0xff,0xff,0xd9,0xf0,0xbf,0xff,0xff,0xff,0xfe,0xf0,0xbb,0xff,0x7f,0xfb,0xff,
0xfb,0xff,0xbf,0xff,0xf3,0x7f,0xfb,0xfd,0xeb,0x7f,0xdf,0xfa,0xff,0xde,0xf0,0xed,
0xff,0xb1,0xf7,0xf9,0x1f,0xb5,0x5b,0xfe,0x7e,0xf7,0xbe,0xfd,0x7f,0x5f,0xb5,0xf7,
0xff,0xff,0xd0,0xf0,0x4f,0xff,0xff,0xff,0xfe,0xf8,0x30,0x01,0x00,0x07,0x42,0x01,
0x00,0x6a,0x18,0x50,0x80,0x00,0x00,0x02,0x40,0x01,0x01,0x20,0x01,0x01,0x24,0x14,
0x21,0x10,0x02,0x08,0x07,0x08,0x00,0x40,0x10,0x80,0x58,0x00,0x84,0x80,0x18,0x10,
0x40,0xc1,0xf0,0xbf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf7,0xff,0xdb,0xb7,0xf3,
0xdf,0x7c,0xf8,0x74,0xff,0xff,0x6f,0x7d,0x3f,0x7e,0xec,0x7f,0xc1,0xf5,0xff,0xcf,
0x6f,0x9f,0xf9,0xdf,0xbe,0xe5,0xe7,0xff,0xd7,0xf3,0xdd,0xfb,0xff,0xfc,0xff,0xbf,
0xff,0xf0,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xf0,0x2f,0xff,0xff,0xff,0xfe,0xd7,0xff,0xff,0xff,0xb4,0xcf,0xef,0x77,0x6f,0x73,
0x3a,0x4a,0x3a,0xcb,0xd4,0xf7,0x2e,0xd6,0xbd,0xbd,0xa1,0x3b,0xdf,0xd6,0xf7,0xee,
0xd3,0x35,0xbd,0xfb,0xbd,0xce,0xeb,0x2b,0x4d,0x2f,0xbb,0xda,0xff,0xff,0xfe,0xb0,
0x5f,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,0xff,0xdf,0x5f,0x36,0xaf,0x3f,0xed,0xb7,
0xf5,0xfd,0xf3,0x2b,0xef,0x77,0xff,0xfb,0xda,0xb1,0xbd,0xa3,0x77,0x69,0x7f,0x4f,
0xff,0xdb,0xfa,0x5b,0xff,0xf2,0xfe,0xff,0x96,0xff,0xff,0xfe,0xdf,0xff,0xd0,0xaf,
0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xfd,0x8f,0xfd,0x40,0x6f,0x9e,0x83,0x5a,0x0f,
0xfa,0xc3,0xff,0xff,0xfc,0xe9,0x7f,0xf3,0x01,0xd0,0x00,0xfe,0xbf,0xcd,0x3f,0xf0,
0xef,0xfc,0xc5,0x0c,0x3f,0xfd,0x68,0x0b,0xff,0xff,0xff,0xfe,0xdf,0xf0,0xff,0xff,
0xff,0xff,0xfe,0xff,0xbb,0xff,0xfd,0x85,0xff,0xd4,0x6f,0x9f,0xc3,0x5a,0x0f,0xff,
0xff,0xff,0xff,0xfc,0xe9,0x7f,0xf3,0x01,0xf0,0xfb,0xc2,0xbf,0xfc,0x00,0x37,0xef,
0xfc,0xcd,0xbc,0x3f,0xff,0x0c,0xbf,0xff,0xff,0xff,0xff,0xff,0xf0,0x5f,0xff,0xff,
0xff,0xfe,0xff,0xff,0xff,0xff,0xd9,0xf7,0xd1,0xb7,0x7e,0x7f,0xf1,0xe4,0xfd,0xff,
0xfb,0xfb,0xff,0x5f,0xff,0x7f,0xb1,0xbc,0x0f,0x67,0xeb,0xb8,0x3f,0xff,0xe2,0xff,
0xe9,0xff,0xfd,0xe3,0xff,0x3f,0x9f,0xc2,0xff,0xff,0xff,0xf0,0x9f,0xff,0xff,0xff,
0xfe,0xf5,0x7f,0xff,0xf0,0x3f,0xbc,0xff,0xd5,0xf5,0xce,0x3f,0xfe,0xff,0xfe,0x6d,
0xff,0xf1,0xbf,0x7b,0xff,0xf1,0xfd,0xff,0x4f,0xff,0x87,0xff,0xae,0xff,0xb1,0xf8,
0xfe,0xff,0xff,0x78,0x01,0xb9,0xff,0xff,0xff,0xfa,0xf0,0x2f,0xff,0xff,0xff,0xfe,
0xf3,0xc0,0x00,0x00,0x00,0x04,0x02,0x13,0x02,0x00,0x80,0x40,0x00,0x90,0x10,0x00,
0x10,0x00,0x02,0x00,0x01,0x20,0x80,0x12,0x10,0x00,0x40,0x08,0x00,0x04,0x00,0x00,
0x02,0x00,0x01,0x40,0x00,0x80,0x00,0x00,0x3c,0xf0,0xef,0xff,0xff,0xff,0xfe,0xfd,
0x1f,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x7f,0xff,0x7f,0xf7,0xdf,0xf7,0xff,
0xf7,0xfb,0xeb,0xd1,0xff,0xff,0xff,0xff,0xef,0xf7,0xff,0xff,0xfb,0xff,0xfe,0xff,
0xff,0x7e,0xff,0xfb,0xff,0xff,0xff,0xdb,0xf0,0xff,0xff,0xff,0xff,0xfe,0xf0,0xff,
0xff,0xb7,0xeb,0xf7,0xdf,0xff,0xfe,0xf5,0x6b,0xe7,0xed,0xf7,0x3e,0xec,0xff,0x54,
0xef,0x6f,0xf1,0xf5,0xaf,0x6f,0xf6,0xfd,0xff,0xdd,0x7b,0xff,0xef,0xbf,0x7f,0xff,
0xff,0xf7,0xff,0xf3,0x5f,0xf7,0xd0,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xf8,0x30,0x00,
0x80,0x40,0x04,0x00,0x81,0x2c,0x04,0x24,0x00,0x02,0x01,0xc8,0x02,0x00,0x02,0x24,
0x00,0x01,0xb4,0x42,0xdc,0x44,0x02,0x15,0x90,0x02,0x03,0x48,0x39,0x10,0x02,0x24,
0xa0,0xba,0x00,0x00,0x40,0xc1,0xf0,0xbf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,
0xfe,0xfc,0xf7,0xf0,0xee,0xb6,0x5d,0xfd,0xf5,0xff,0xdb,0xf7,0x7f,0x7f,0xbe,0xff,
0xc1,0xfe,0xbf,0xfa,0xfa,0x5f,0xff,0xad,0xff,0xef,0xff,0x7f,0xdf,0x7f,0xfe,0xbf,
0xb7,0x94,0xbf,0xff,0xff,0xf0,0x9f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xf0,0x8f,0xff,0xff,0xff,0xfe,0xd7,0xff,0xff,0xfb,0xb5,0xff,
0xef,0x7c,0xeb,0x2b,0x52,0x5b,0x3b,0xda,0xd4,0xf3,0x36,0x96,0xb5,0xbd,0xf1,0xfb,
0xda,0xee,0xf6,0xfe,0xd3,0x35,0xbd,0xdf,0xad,0xcf,0xef,0x7e,0xcd,0x6b,0xbb,0xdf,
0xff,0xff,0xfd,0xb0,0xef,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,0xff,0xd3,0x5f,0xf6,
0xff,0xf6,0xff,0xfd,0xad,0xfd,0xff,0x7f,0xef,0xff,0x6f,0x7f,0xdb,0xf1,0xa5,0xa3,
0x7f,0x6f,0x6b,0x4f,0xff,0xdb,0xfb,0xcb,0xff,0xf6,0xff,0xf4,0xd7,0xfd,0xbf,0xfe,
0xdf,0xff,0xd0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf7,0xdf,0xff,0xff,0xff,
0x3f,0x7f,0xfc,0xe5,0xff,0x20,0xfe,0xff,0xff,0xdf,0x7f,0xff,0xf1,0x7f,0xff,0xfe,
0xff,0xf0,0x7c,0x3d,0x4f,0xf3,0xc3,0x3f,0xff,0xff,0x6f,0xc3,0xff,0x0f,0xff,0xff,
0xaf,0xf0,0x2f,0xff,0xff,0xff,0xfe,0xff,0xff,0xfb,0xb7,0xe0,0x0f,0xff,0xff,0x2b,
0xff,0x7d,0xbf,0xff,0xdf,0xff,0xff,0xf8,0x9f,0x7f,0xff,0xf1,0x55,0xff,0xff,0xff,
0xfd,0x7c,0x3c,0xff,0xf3,0xc3,0x3f,0xff,0xff,0xef,0xc3,0xff,0xdf,0xff,0xff,0xff,
0xf0,0x9f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xef,0xff,0xff,0x9f,0xbf,0x7f,
0xf9,0x19,0x47,0x8e,0xe7,0x9f,0x3f,0x17,0xff,0xfc,0x81,0xc1,0x7e,0xf3,0xd9,0xf9,
0x73,0xdf,0xf4,0x7f,0xfa,0xff,0xff,0xff,0xfb,0x7f,0x77,0xc7,0xff,0xff,0xff,0xf0,
0x2f,0xff,0xff,0xff,0xfe,0xf5,0xf7,0xff,0xfb,0xff,0xf7,0x3f,0xfc,0xbf,0x3e,0x3f,
0xec,0xff,0x81,0xaf,0xfe,0x4f,0xf3,0xbb,0xff,0xf0,0x7e,0xff,0x6f,0xff,0x87,0xff,
0xbb,0xff,0xd5,0xfc,0xff,0x7f,0xfc,0x6f,0xff,0xef,0xe7,0xff,0xff,0xfa,0xf0,0x3f,
0xff,0xff,0xff,0xfe,0xf3,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,
0x00,0x30,0x10,0x60,0x20,0x00,0x08,0x00,0x01,0x20,0x80,0x00,0x10,0x00,0x04,0x00,
0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x80,0x40,0x00,0x08,0x20,0x3c,0xf0,0x6f,0xff,
0xff,0xff,0xfe,0xf5,0xbf,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0x7f,0xfe,0x3f,0xff,
0xff,0xff,0xff,0xff,0xef,0xff,0xff,0xf1,0xdf,0xdf,0xff,0xff,0xff,0x7f,0xdf,0xff,
0xfd,0xbd,0xff,0xff,0xff,0xfb,0xdf,0xff,0xff,0xff,0xff,0x5b,0xf0,0xff,0xff,0xff,
0xff,0xfe,0xf0,0xbf,0xbf,0xbf,0xff,0xf7,0xfb,0xff,0xfe,0xee,0xfa,0xff,0xff,0xff,
0x3d,0x3b,0xff,0xff,0xfe,0xfb,0xf1,0xff,0xbf,0x7b,0xff,0xff,0xef,0xff,0xbf,0xff,
0xff,0xff,0xff,0xff,0xfe,0xff,0xf7,0xef,0xff,0xfb,0xd0,0xf0,0xdf,0xff,0xff,0xff,
0xfe,0xf8,0x30,0x00,0x00,0x00,0x00,0x00,0x0b,0x10,0x05,0x01,0x00,0x08,0x00,0x02,
0x01,0x01,0x00,0x00,0x10,0x01,0xc8,0x08,0x00,0x00,0x00,0x00,0x42,0x02,0x00,0x00,
0x00,0x80,0x02,0x00,0x00,0x40,0x24,0x80,0x00,0xc1,0xf0,0x3f,0xff,0xff,0xff,0xfe,
0xff,0xff,0xff,0xff,0xf7,0xfd,0xf7,0xfa,0xef,0xee,0xf9,0xfd,0xff,0xf7,0xfe,0xbf,
0x1f,0xfd,0x9e,0xfd,0xd1,0xef,0xff,0xf7,0x7f,0x9f,0xff,0xef,0xff,0xf6,0xff,0xfe,
0xfe,0x7b,0xff,0xbd,0xff,0x7e,0xff,0xff,0xff,0xf0,0x3f,0xff,0xff,0xff,0xfe,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xaf,0xff,0xff,0xff,0xfe,0xff,0xff,
0xff,0xf7,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xdf,0xfd,0xff,0xff,0xdf,0xff,
0xff,0x5f,0xf1,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xff,0xef,0xff,
0xf7,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0xfb,0xff,0xff,0xef,0xfb,0xfd,
0xff,0xf1,0xff,0xff,0xfb,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x2f,0xff,0xff,0xff,0xfe,0xf7,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xe7,0xff,
0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xf0,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xcf,0xff,0xfb,0xff,0xfb,0xf1,
0xff,0xff,0xfb,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xf0,0x2f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7b,0xff,0xff,0xff,0x7f,0xff,0xf1,0xff,
0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xef,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0x57,0xff,0xfe,0xbf,0xfb,0xf1,0xff,0xff,
0xfd,0xf7,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xd7,0xff,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf7,0xdb,0xff,0xdb,0xfd,
0xf6,0xff,0xf6,0xff,0x3c,0xbc,0xbc,0xbf,0xdf,0x6f,0xef,0x2f,0xf1,0x3c,0xbf,0xbc,
0xbf,0xdf,0x6f,0xff,0x6f,0xf7,0xdb,0xff,0xdb,0xfd,0xf6,0xff,0xf6,0xff,0xff,0xff,
0x01,0xe2,0xef,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff };

View File

@@ -0,0 +1,343 @@
/*
*
* File yam111.mcs converted to h format by mcs2h
*
* (C) F6FBB 1998
*
* Tue Aug 25 20:23:03 1998
*
*/
static unsigned char bits_9600[]= {
0xff,0xf2,0x00,0xa5,0xad,0xff,0xfe,0x9f,0xff,0xef,0xfb,0xcb,0xff,0xdb,0xfe,0xf2,
0xff,0xf6,0xff,0x9c,0xbf,0xfd,0xbf,0xef,0x2e,0x3f,0x6f,0xf1,0xfd,0xb4,0xfd,0xbf,
0xff,0x6f,0xff,0x6f,0xff,0x0b,0xff,0xdb,0xff,0xf2,0xff,0xf6,0xff,0xff,0xff,0xff,
0xf0,0x6f,0xff,0xff,0xff,0xfe,0xff,0xfd,0xdf,0xff,0xff,0xff,0xf7,0xff,0xff,0xff,
0xfb,0xff,0xff,0xf7,0xff,0xff,0xff,0xfe,0xff,0x7f,0xf1,0xff,0xfe,0xff,0xbf,0xbf,
0xff,0xff,0xff,0xff,0xff,0xf7,0xff,0xff,0xff,0xfe,0xff,0xfe,0xff,0xff,0xff,0xf0,
0xef,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0xff,0xff,0xff,0xf7,
0xff,0xff,0xf7,0xef,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0x7e,0xff,0xff,
0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0xfd,0xff,0xff,0xff,0xf0,0xdf,
0xff,0xff,0xff,0xfe,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xef,0xff,0xf3,0xfb,0xfe,0xff,0xf1,0xff,0xfd,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xdf,0xff,0xf0,0x7f,0xff,
0xff,0xff,0xfe,0xff,0xff,0xef,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xdf,0xff,0xff,0xff,0xf7,0xf1,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,
0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf5,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x2f,0xff,0xff,0xff,
0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xfb,0xff,0xff,0xff,0xef,0xff,0x7f,0xff,0xef,
0xff,0xef,0xff,0x7f,0xef,0xf1,0xff,0xef,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xf0,0x9f,0xff,0xff,0xff,0xfe,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xbf,0xff,0xff,0xff,0xfe,0xff,
0xff,0xff,0xff,0xbd,0xff,0xef,0x7f,0xef,0x7f,0xfb,0xdf,0xd3,0x5a,0xfe,0xd7,0xd6,
0xf7,0x7f,0xbd,0xf1,0xbb,0x5d,0xd6,0xf7,0xfe,0x96,0xff,0xbd,0xaf,0xad,0xbf,0xef,
0x7f,0x6b,0x7f,0xfb,0xd6,0xfe,0xf7,0xff,0x10,0xef,0xff,0xff,0xff,0xfe,0xbe,0xef,
0xff,0xff,0xdb,0xff,0xf6,0xff,0xf6,0xff,0xfd,0xbf,0xfd,0xbf,0xff,0x7f,0xff,0x7f,
0xdf,0xdb,0xf1,0xfd,0x35,0xff,0x6f,0xff,0x6f,0xff,0xdb,0xff,0xcb,0xff,0xf6,0xff,
0xf2,0xfd,0xfd,0xbf,0xff,0xff,0xff,0xd0,0xef,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x55,0xff,0xcc,0xc0,0x3f,0xff,
0xff,0xf1,0x24,0xf0,0xff,0xff,0xcf,0xef,0x3f,0xff,0xf0,0xff,0xff,0xff,0xfc,0x3f,
0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x55,0xff,0xcc,0xc0,0x3f,0xff,0xff,
0xf1,0x00,0xf0,0xff,0xff,0xcf,0xdf,0xff,0xff,0xf0,0xff,0xff,0xff,0xfc,0x3f,0xff,
0xff,0xff,0x7d,0xff,0xff,0xf0,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0xfe,0x7f,0xdf,0xff,0xff,0xff,0xf1,
0xff,0xcf,0xff,0xf3,0xff,0x97,0xff,0xff,0x8f,0xe7,0xff,0xff,0xfc,0x71,0xff,0xff,
0xff,0xff,0xff,0xff,0xf0,0xef,0xff,0xff,0xff,0xfe,0xf5,0xff,0xbf,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xe3,0xf7,0xef,0xff,0xff,0xfc,0x7b,0xff,0xf1,0x3f,
0xff,0xef,0xff,0xcf,0xe3,0xe3,0xff,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0xbf,0xff,
0xbf,0xff,0xda,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xf2,0xc0,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,
0x01,0x3c,0xf0,0xaf,0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xdb,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0x9f,0xff,
0xff,0xff,0xf7,0xff,0xef,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xdb,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xf0,0xbb,0xdf,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xfb,0xdf,0xbf,0xf1,0xfe,0xfd,0xf7,0xff,
0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x77,0xfd,0xf2,
0xf0,0x1f,0xff,0xff,0xff,0xfe,0xf8,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,
0x00,0x00,0x00,0x02,0x00,0x90,0x00,0x00,0x00,0x0c,0x01,0x00,0x00,0x04,0x24,0x00,
0x40,0x01,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x01,0xc0,0xf0,
0x4f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xbf,0xff,0xff,0x6f,0xff,0xdf,0xff,0xd1,0xff,0xfe,0xff,0xff,0xff,0xff,
0xff,0xff,0xdf,0xff,0xfb,0xff,0xfb,0xef,0xff,0xff,0xee,0xff,0xff,0x7f,0xf0,0xdf,
0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x8f,0xff,
0xff,0xff,0xfe,0xff,0xff,0xff,0xf5,0xad,0xff,0x69,0x2a,0xed,0x6b,0xfb,0xdf,0x3a,
0xdc,0xf4,0x96,0xee,0xb3,0x3d,0x35,0xc1,0xbb,0xdd,0xfe,0xf6,0xfe,0xd6,0xb5,0xad,
0xbf,0xa5,0xad,0x49,0x2f,0x4f,0x2b,0xda,0x5f,0xff,0xff,0xff,0xf0,0x2f,0xff,0xff,
0xff,0xfe,0xbf,0xff,0xff,0xfb,0x5b,0xf7,0xf6,0xff,0xf6,0xff,0xfd,0xbf,0xfd,0xa5,
0xf3,0x6f,0xf3,0x6e,0xfa,0x7b,0xd1,0xfd,0xb5,0x77,0x6f,0xe9,0x6f,0xff,0xdb,0xfb,
0xdb,0xdf,0xf6,0xff,0xf6,0xff,0xfd,0x3f,0xfe,0xf7,0xff,0xd0,0x4f,0xff,0xff,0xff,
0xfe,0xff,0x9f,0xff,0xff,0x0f,0xff,0xc0,0x3f,0x9c,0x03,0xff,0xff,0x8b,0xa5,0xfe,
0x80,0x3e,0xc2,0xbf,0xac,0xb1,0x24,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0xff,0xa3,
0xff,0xfd,0x6b,0xff,0xff,0xf0,0xa5,0xff,0xff,0xff,0xf0,0xaf,0xff,0xff,0xff,0xfe,
0xff,0xff,0xff,0xff,0x0f,0xff,0xc0,0x3f,0xd4,0x6b,0xff,0xff,0xdb,0xff,0xfe,0x86,
0xbf,0xc2,0xbf,0x30,0xa1,0x24,0xff,0xff,0xff,0xff,0xcc,0xff,0x0f,0xff,0xa3,0xff,
0x05,0x6b,0xff,0xff,0xf0,0xa5,0xff,0xff,0xff,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xff,
0xff,0xff,0xfb,0xc7,0xff,0xc4,0xff,0xff,0x7f,0xff,0xec,0xfe,0x7f,0xdf,0xd8,0xb9,
0x47,0xfc,0x36,0xc1,0xdf,0xff,0xff,0xf9,0xff,0xf3,0xff,0xf7,0xff,0xfc,0xff,0xfd,
0x3f,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xf5,0xff,
0xff,0xff,0xff,0xfe,0xff,0xff,0x7e,0xbd,0x3f,0xff,0x2b,0xfe,0x2f,0xf5,0xa3,0xfc,
0x5b,0xfe,0x61,0x9f,0x7f,0xef,0xff,0xff,0xa7,0xfb,0xff,0xff,0xfa,0xfe,0xff,0x33,
0xf1,0xff,0xbf,0xff,0xff,0xff,0xfa,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xf1,0xc0,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x30,0x24,0x04,
0x00,0x01,0x00,0x80,0x40,0x00,0x08,0x00,0x00,0x00,0x02,0x01,0x01,0x00,0x02,0x00,
0x00,0x00,0x00,0x00,0x01,0x3d,0xf0,0x2f,0xff,0xff,0xff,0xfe,0xfd,0xbd,0xff,0xfd,
0xff,0xff,0xff,0xff,0xff,0xfb,0xff,0xff,0x7f,0xf6,0xef,0xbf,0xf7,0xff,0x73,0xeb,
0xf1,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0xf9,0xff,0xfd,0xfe,0xff,0xff,
0xff,0xff,0xff,0xff,0xd9,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xf0,0xbf,0x7f,0xff,0xff,
0xff,0x7f,0xff,0xff,0xde,0xff,0xff,0xef,0xdd,0xde,0x77,0xf2,0xfb,0xed,0xe7,0xf1,
0x73,0xfd,0xfd,0xdf,0xff,0x7d,0xbe,0xdf,0xff,0xfb,0xff,0xef,0xff,0xef,0xff,0xff,
0xff,0xff,0xff,0xd0,0xf0,0xbf,0xff,0xff,0xff,0xfe,0xf8,0x30,0x20,0x02,0x00,0x22,
0x40,0xc0,0x00,0x00,0x00,0x08,0x00,0x02,0x41,0x02,0x12,0x00,0x21,0x87,0x81,0x00,
0x00,0x80,0x04,0x0b,0x28,0x01,0xb0,0x00,0x82,0x00,0x40,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0xc1,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xfd,0xff,
0xf7,0xff,0xfe,0x7f,0xed,0x79,0xff,0xde,0xeb,0x7f,0x74,0xf7,0xf7,0xe1,0xf9,0xff,
0xf6,0x5f,0x7f,0xff,0xff,0xff,0xd7,0xdb,0xef,0xff,0xbb,0xff,0xff,0xff,0xcc,0xff,
0xff,0xff,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xf0,0x0f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xfd,0x3d,0xcd,0x49,0x7f,0x6f,
0x2b,0xba,0x5c,0xd2,0xda,0xf6,0xf3,0x3e,0xf7,0xff,0xbd,0xf1,0xfa,0xdf,0xfe,0xf7,
0xcc,0xf6,0xbb,0xa5,0xb3,0xad,0xbf,0x6f,0x7d,0x6f,0x6b,0xdb,0xdf,0xbd,0xff,0xfe,
0xb0,0x5f,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,0xfb,0xdb,0x57,0xf6,0xfe,0x9f,0xd5,
0xb7,0xff,0xaf,0xe5,0x3f,0xff,0xff,0x6f,0xff,0xdb,0xf1,0xfd,0xbf,0xff,0x6f,0x69,
0x6c,0xdf,0xda,0xdf,0xcb,0xff,0xf6,0xff,0x76,0xfd,0xfd,0xbf,0xff,0xff,0xff,0xd0,
0x3f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xfd,0xbd,0x08,0x03,0x89,0x4f,0x5a,
0x0f,0xf0,0xff,0xf8,0xbf,0xff,0xff,0xff,0xff,0xf1,0x5a,0xff,0xff,0xff,0xff,0xf3,
0xfa,0xa0,0xf0,0xf2,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xff,
0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xfc,0xfd,0x00,0x6b,0xff,0xff,0x5a,0x0f,
0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0x5a,0xff,0xff,0xff,0xff,0xb3,0xf5,
0x50,0xf0,0xf0,0xff,0xff,0xff,0xd7,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x7f,0xff,
0xff,0xff,0xfe,0xff,0xff,0xff,0xfd,0xbc,0xff,0xe4,0xe7,0x71,0xff,0xf9,0xc4,0xf4,
0x7f,0x7f,0xcf,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xfb,0xf7,0x73,0xbf,0x14,
0xff,0xe6,0xff,0xff,0xe1,0x7d,0xff,0xff,0xe7,0xff,0xff,0xff,0xf0,0x3f,0xff,0xff,
0xff,0xfe,0xf5,0xff,0xff,0xfe,0xd2,0xfa,0xff,0xc4,0xf4,0x5c,0xbf,0xfa,0xff,0xff,
0xec,0x7e,0xbf,0xff,0xff,0xff,0xf1,0xff,0xff,0xef,0xff,0xff,0x6b,0xdb,0xff,0xdf,
0xf9,0xfb,0xbf,0xff,0xf1,0xff,0xbf,0xff,0xff,0xff,0xfb,0xf0,0xbf,0xff,0xff,0xff,
0xfe,0xf3,0xc0,0x00,0x02,0x00,0x00,0x00,0x00,0x82,0x00,0x00,0x00,0x00,0x80,0x00,
0x00,0x00,0x00,0x40,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x20,0x00,0x00,0x00,0x00,
0x01,0x00,0x01,0x00,0x00,0x80,0x02,0x00,0x01,0x3c,0xf0,0x5f,0xff,0xff,0xff,0xfe,
0xfd,0xbf,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0x7f,0xff,0xdf,0xff,0xef,0xff,
0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xf7,0xff,0xfb,0xff,0xfd,0xff,
0xff,0xff,0xff,0xff,0xff,0xfd,0xff,0xff,0xc3,0xf0,0xaf,0xff,0xff,0xff,0xfe,0xf0,
0xff,0xdf,0xff,0xff,0xf7,0x23,0xff,0xff,0xfd,0xff,0xef,0xff,0xfe,0x7f,0x7d,0xf7,
0xfe,0xff,0x7f,0x71,0xff,0xfb,0x7f,0xff,0xff,0xff,0x6e,0xfd,0xf7,0xfd,0xff,0xbf,
0xff,0xbf,0xf9,0xfd,0xff,0xdf,0xef,0xf0,0xf0,0xaf,0xff,0xff,0xff,0xfe,0xf8,0x30,
0x40,0x01,0x00,0x83,0x00,0x00,0x00,0x0c,0x06,0x08,0x04,0x26,0x26,0x00,0x00,0x06,
0x03,0x00,0x01,0x00,0x00,0x00,0x00,0x04,0x00,0x70,0x08,0x80,0x00,0x20,0x01,0x20,
0x00,0x02,0x00,0x30,0x00,0x00,0xc1,0xf0,0x5f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,
0xff,0xff,0x7b,0x3f,0xf7,0xff,0xd7,0xfe,0xfe,0xfb,0xfe,0x3b,0xfe,0xbd,0xff,0x2f,
0xff,0x71,0xff,0xfb,0x7f,0xe7,0xff,0xf9,0xef,0xff,0xd7,0xfa,0xff,0xb7,0xbb,0xfe,
0xff,0xff,0x74,0xff,0xf7,0xff,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xf0,0x8f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xb5,
0xbd,0x6f,0x7c,0xeb,0x7f,0xfb,0xdb,0xd3,0x4b,0xee,0xd6,0xf6,0xb7,0xfd,0xac,0xa1,
0xfb,0xdf,0xfe,0xf7,0xf4,0x96,0xbd,0xb4,0xc5,0xa5,0xaf,0x6f,0x69,0x4f,0x7f,0xba,
0xdb,0xff,0xff,0xff,0xf0,0x3f,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,0xff,0xdb,0xff,
0xf6,0xff,0xf6,0xff,0xbd,0xbf,0xa5,0xbf,0xff,0x7d,0x7f,0xef,0xff,0xfb,0xf1,0xfd,
0xbf,0xff,0x6f,0xff,0x6b,0x7a,0xdb,0xff,0xdb,0xdf,0xf6,0xfe,0xb6,0xfd,0xfd,0xbf,
0xfe,0xf7,0xff,0xd0,0xef,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xf4,0x2f,0xff,
0xfc,0x43,0x6b,0xff,0xff,0xff,0x0d,0xff,0xfc,0x33,0x3f,0xf0,0x5f,0xf1,0xff,0xff,
0xff,0xff,0xf9,0xde,0xf0,0x4c,0xfe,0x77,0xaf,0xff,0xff,0xef,0xff,0xf0,0xff,0xdb,
0xff,0x5f,0xf0,0xef,0xff,0xff,0xff,0xfe,0xff,0xfe,0xf7,0xff,0xf0,0x2f,0xff,0xfd,
0x43,0x7f,0xff,0xff,0xf1,0x0f,0xff,0xfc,0x33,0x3f,0xff,0xaf,0xf1,0xff,0xff,0xff,
0xff,0xf6,0xd7,0xff,0xbc,0xfd,0xbd,0xff,0xff,0xff,0xff,0xff,0xf0,0xff,0xff,0xff,
0xff,0xf0,0xef,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xfc,0xff,0xff,0xfb,0xf1,
0xbf,0xff,0xf9,0xfd,0xcf,0xf2,0x70,0xff,0x1f,0x9f,0xf3,0xf1,0xff,0xff,0xff,0xff,
0xfc,0xf7,0xff,0x13,0x9f,0xfc,0xff,0xff,0x84,0xf7,0xff,0xff,0x47,0xff,0xff,0xff,
0xf0,0xbf,0xff,0xff,0xff,0xfe,0xf5,0xff,0xff,0xff,0xf1,0xfc,0xff,0xfe,0xfe,0x79,
0x3f,0xff,0x1d,0x46,0xcf,0xff,0xcf,0xfc,0x7b,0xff,0xf1,0xff,0xff,0xff,0xff,0xed,
0xf3,0xab,0xff,0xcb,0xff,0xf8,0xff,0xfc,0xf5,0xff,0xbf,0xff,0xff,0xff,0xfa,0xf0,
0x8f,0xff,0xff,0xff,0xfe,0xf3,0xc2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,
0x00,0x00,0x20,0x00,0x20,0x00,0x00,0x04,0x08,0x01,0x00,0x00,0x00,0x00,0x00,0x20,
0x0c,0x00,0x00,0x04,0x01,0x00,0x01,0x00,0x00,0x80,0x00,0x00,0x01,0x3c,0xf0,0x7f,
0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xff,0xfd,0xfe,0xff,0xff,0xff,0xff,0xfe,0xff,
0xdf,0xff,0xff,0xf7,0xff,0xff,0xff,0xef,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xeb,
0xff,0xdf,0xff,0xff,0xfb,0xf7,0x7f,0xff,0xfe,0xff,0xff,0xbf,0xdb,0xf0,0xff,0xff,
0xff,0xff,0xfe,0xf0,0xff,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0x7f,0xf7,0xff,
0xbf,0xbf,0xcf,0xff,0xff,0xff,0x3e,0xf1,0x7f,0xff,0xff,0xef,0xff,0xff,0xff,0xfe,
0xff,0xfd,0xff,0xbf,0xbd,0xfe,0xff,0xfb,0xf7,0xdf,0xfb,0xd0,0xf0,0x9f,0xff,0xff,
0xff,0xfe,0xf8,0x30,0x20,0x00,0x40,0x01,0x80,0xc0,0x30,0x00,0x00,0x20,0x00,0x10,
0x50,0x88,0x20,0x00,0x00,0x13,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,
0x00,0x00,0x01,0x80,0x08,0x00,0x00,0xa0,0x00,0x10,0xc1,0xf0,0xef,0xff,0xff,0xff,
0xfe,0xfd,0xef,0x7f,0xff,0xff,0xbf,0xff,0xf7,0xff,0xef,0xfb,0xfd,0x77,0xef,0xbf,
0xf7,0x7f,0xff,0xff,0xbf,0xd1,0x7f,0xff,0xff,0xf7,0xff,0xff,0xff,0xff,0xaf,0xff,
0xdf,0xf7,0xfb,0xff,0xfd,0xff,0xfc,0xff,0xfd,0xff,0xf0,0xff,0xff,0xff,0xff,0xfe,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x5f,0xff,0xff,0xff,0xfe,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,
0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0x3f,0xff,0xff,0xff,0xfe,0xdd,0xff,
0xff,0xff,0xa5,0xfd,0x6f,0x7d,0x6d,0x7f,0x52,0xdf,0x5a,0x4b,0xee,0xb6,0xee,0xf2,
0xbb,0xac,0xa1,0x5b,0x4d,0xd6,0xf7,0xfe,0xb2,0xbd,0x35,0xb5,0xb5,0xdd,0x6f,0x7f,
0xe9,0x5f,0x52,0xdf,0xbd,0xff,0xff,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,
0xff,0xdb,0xfe,0xf6,0xff,0xf6,0xff,0xfd,0xbf,0xfd,0xb5,0xbf,0xf9,0x7f,0x6f,0xff,
0xdb,0xf1,0xfd,0xbf,0xff,0x6f,0xff,0x69,0x7f,0xdb,0xff,0xd3,0xff,0xf6,0xfe,0xf2,
0xff,0xad,0xbf,0xff,0xff,0xff,0xd0,0xdf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf5,
0x30,0x0f,0xff,0xff,0xfd,0x6b,0xca,0xff,0xf0,0x0f,0xd6,0xbf,0xcf,0x3f,0xff,0xff,
0xf1,0xff,0xff,0xff,0xca,0xfe,0xbf,0xff,0xf0,0x05,0xaf,0x0f,0xff,0xfc,0xf0,0xcf,
0xf0,0xff,0xff,0xff,0xff,0xf0,0xef,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf5,0x30,
0x0f,0xff,0xff,0xfc,0x3f,0xca,0xff,0x0f,0x0f,0xd6,0xbf,0xff,0xff,0xf5,0x5f,0xf1,
0xff,0x8b,0xff,0xc3,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0xff,0xfc,0xf0,0xcf,0xf0,
0xff,0xff,0xff,0xff,0xf0,0x3f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xcf,0xff,
0xff,0xbf,0x9f,0x3f,0xfe,0xfc,0xff,0x4f,0xff,0xff,0xff,0xff,0xff,0xf7,0xf1,0xff,
0xdf,0xfe,0x7e,0x3f,0x9f,0xf4,0xfc,0x7f,0xfc,0xff,0xff,0x3f,0xff,0x3f,0xfe,0x3f,
0xff,0xff,0xff,0xf0,0x4f,0xff,0xff,0xff,0xfe,0xf5,0xff,0xff,0xfb,0xff,0xfe,0xff,
0xff,0xff,0xff,0xbf,0xfb,0xff,0xf8,0xed,0xff,0x8f,0xff,0xbb,0xff,0xb1,0xf3,0xef,
0x8f,0xf7,0xff,0xff,0xdb,0xff,0xff,0xff,0xef,0xbf,0xfd,0x79,0xbf,0xbf,0xff,0xff,
0xff,0xfb,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xf3,0xc0,0x00,0x00,0x00,0x04,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x04,0x08,0x08,0x01,0x01,0x00,0x90,
0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x00,0x08,0x00,0x04,0x00,0x00,0x01,
0x3c,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0x9f,0xff,0xaf,0xdf,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,
0xbf,0xef,0xff,0xff,0xff,0xed,0xff,0xff,0xff,0xef,0xff,0xbf,0xff,0xff,0xff,0xc3,
0xf0,0x3f,0xff,0xff,0xff,0xfe,0xf0,0xff,0xfd,0xff,0xff,0xff,0xfb,0xff,0xbb,0xff,
0xff,0xff,0x7f,0xf6,0xff,0x7f,0xfb,0xfd,0xed,0xff,0xf1,0xff,0xfe,0x7f,0xff,0xff,
0xff,0x5f,0xff,0xf7,0xff,0x7e,0xff,0xfd,0xff,0xef,0xff,0xff,0xff,0xef,0xf0,0xf0,
0x8f,0xff,0xff,0xff,0xfe,0xf8,0x30,0x80,0x00,0x04,0x00,0x00,0x40,0x02,0x00,0x03,
0x00,0x05,0x04,0x20,0x00,0x00,0x01,0xd0,0x00,0x81,0x00,0x20,0x04,0x04,0x00,0x00,
0x81,0x04,0x08,0x80,0x10,0x00,0xc0,0x00,0x00,0x00,0x20,0x00,0x08,0xc1,0xf0,0x6f,
0xff,0xff,0xff,0xfe,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xf3,0xfd,0xff,0xed,0xfc,
0xff,0xff,0x9f,0xfb,0xfd,0xff,0xff,0xff,0xf1,0xff,0xff,0x7f,0xfb,0x3e,0xff,0x9f,
0xff,0xff,0xff,0xff,0xfd,0xf9,0xff,0xff,0xff,0xfd,0xff,0xff,0xff,0xf0,0x6f,0xff,
0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xcf,0xff,0xff,
0xff,0xfe,0xff,0xff,0xff,0xfd,0xbd,0xff,0xef,0x7c,0xeb,0x7f,0xfb,0xdb,0xfa,0xdc,
0xee,0xf7,0xf6,0xd7,0xf5,0x2d,0xa1,0xbb,0xdd,0xee,0xf7,0x54,0xf7,0xfb,0x2c,0xb5,
0xb4,0xbd,0x6b,0x6f,0xef,0x6f,0xbb,0xdf,0xff,0xff,0xff,0xf0,0x1f,0xff,0xff,0xff,
0xfe,0xbf,0xff,0xff,0xff,0xfb,0xff,0xf6,0xff,0xf6,0xff,0xfd,0xbf,0xff,0xbf,0xef,
0x6f,0xff,0x6f,0xfa,0xdb,0xf1,0xc5,0xbd,0xf5,0x6f,0xff,0x6f,0xca,0xdb,0xff,0xdb,
0xfb,0xf6,0x97,0xf6,0xff,0xfd,0xbf,0xfe,0xf7,0xff,0xd0,0x9f,0xff,0xff,0xff,0xfe,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x8b,0x7f,0xff,0xff,0xe7,0x63,0xff,0xff,
0xff,0xfc,0x77,0xdf,0xf1,0xdb,0xff,0xd6,0xa8,0x3f,0xff,0xff,0x08,0x2f,0xf0,0xff,
0xc3,0xff,0xeb,0xff,0xff,0xff,0xff,0xff,0x5f,0xf0,0xef,0xff,0xff,0xff,0xfe,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x8b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xfc,0xff,0xcf,0xf1,0xdb,0xff,0xd6,0xa8,0x3f,0xff,0xff,0x08,0x2f,0xf0,0xff,0xc3,
0xff,0xeb,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x5f,0xff,0xff,0xff,0xfe,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xf5,0xbf,0xff,0xca,0xff,0x9f,0xff,0xfa,0xb9,0xe7,
0x9f,0xf3,0x81,0xff,0xff,0xfc,0x73,0xd7,0xff,0xff,0x77,0xff,0xfd,0xff,0xfc,0xff,
0xff,0xff,0xff,0xcf,0xff,0xff,0xff,0xf0,0x1f,0xff,0xff,0xff,0xfe,0xf5,0xff,0xff,
0xff,0xf7,0xde,0xff,0xfe,0x7e,0xff,0xbf,0xff,0xbf,0xf1,0xb3,0xff,0xff,0xe3,0xfb,
0xff,0xe1,0x1f,0x7f,0xff,0xf8,0x78,0xff,0xfb,0x1e,0xff,0xf7,0xfe,0xe7,0xff,0xff,
0xff,0xbf,0xff,0xff,0xff,0xfa,0xf0,0x4f,0xff,0xff,0xff,0xfe,0xf3,0xc0,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x04,0x00,
0x01,0x80,0x40,0x40,0x20,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
0x80,0x00,0x00,0x01,0x3c,0xf0,0xaf,0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xfb,0xff,
0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xf7,0xf1,
0xfd,0xff,0xff,0xff,0xdf,0xff,0xef,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,
0xff,0xff,0xff,0xdb,0xf0,0x8f,0xff,0xff,0xff,0xfe,0xf0,0xff,0xdf,0xff,0xff,0x7f,
0xff,0xff,0xff,0xbe,0xd7,0xff,0xed,0xbd,0x7e,0xbf,0xfe,0xf6,0x7f,0xbf,0x71,0xff,
0xff,0xda,0xff,0xf9,0xff,0xbf,0x7f,0xfe,0xff,0x6f,0x7f,0xff,0xff,0xff,0xff,0xff,
0x7f,0xff,0xd0,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xf8,0x30,0x42,0x00,0x00,0x00,0x00,
0x80,0xc1,0x00,0x00,0x90,0x00,0xc4,0x00,0x00,0x12,0x20,0x43,0x22,0x81,0x84,0x00,
0x00,0x14,0x00,0x01,0x00,0x08,0x80,0x00,0x02,0x00,0x02,0x00,0x04,0x02,0x00,0x00,
0x10,0xc1,0xf0,0x1f,0xff,0xff,0xff,0xfe,0xff,0xff,0xfd,0xff,0xff,0xdd,0xfe,0xff,
0xb6,0x76,0xe5,0xbc,0xf9,0xf7,0xaf,0x5f,0xbf,0xfc,0xdf,0xcf,0xf1,0xff,0xef,0x79,
0xff,0xbd,0xff,0xef,0xff,0xff,0xf7,0x6f,0x5f,0xff,0xff,0xfd,0xef,0xef,0xbf,0xff,
0xff,0xf0,0x9f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xf0,0xff,0xff,0xff,0xff,0xfe,0xdb,0xff,0xff,0xfd,0x2d,0xff,0x69,0x2a,0xef,0x77,
0xbb,0xdd,0x5a,0xdf,0xf6,0xf6,0xd6,0xf7,0x7d,0xbd,0xd1,0xb2,0x4a,0xd6,0xb2,0xbe,
0x97,0xf5,0xbd,0xb3,0xad,0xff,0xef,0x7f,0x69,0x6b,0xfb,0xdf,0xff,0xff,0xff,0xf0,
0x2f,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,0xff,0xdb,0xff,0xf6,0xfe,0x9f,0xd4,0xbf,
0xed,0xaf,0xff,0x6b,0x6f,0xf7,0xff,0xdd,0xdb,0x31,0xfd,0xbf,0xff,0x6f,0x7f,0xff,
0xff,0xdb,0xff,0xcb,0xdf,0xf6,0xff,0xf6,0xff,0xfd,0xbf,0xfe,0xf7,0xff,0xd0,0x8f,
0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xfd,0x1f,0xff,0x46,0x2f,0x9f,0xff,0xff,0xff,
0xa5,0xff,0xff,0xff,0xdf,0xb7,0xff,0xff,0xf1,0xff,0xff,0xff,0xf7,0xe9,0x6a,0xbf,
0xff,0xff,0xfd,0xff,0xff,0xfd,0x55,0x57,0xff,0xff,0xff,0xff,0xaf,0xf0,0x4f,0xff,
0xff,0xff,0xfe,0xfe,0xdf,0xff,0xfd,0x1f,0xff,0x46,0x2f,0x9f,0xff,0xff,0xff,0xa5,
0xff,0xff,0xff,0xc0,0x37,0xff,0xff,0xf1,0x99,0x8e,0xdc,0x7f,0xe9,0x6a,0xbf,0xff,
0xf0,0x0f,0xff,0xff,0xfd,0x55,0x57,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,
0xff,0xfe,0xff,0xff,0xff,0xff,0x07,0xff,0xc0,0xbe,0xff,0xff,0xcf,0xef,0x9f,0xff,
0xff,0xfb,0xff,0xe7,0xff,0xff,0xa1,0xe3,0xce,0x3c,0x58,0x3f,0xf3,0xff,0xfd,0xef,
0xf9,0xff,0xff,0xf7,0xf1,0x7f,0xff,0xcb,0xff,0xff,0xff,0xf0,0x2f,0xff,0xff,0xff,
0xfe,0xf5,0x7f,0xff,0xf0,0xff,0xfe,0xff,0xc4,0x75,0xe7,0xb9,0xff,0xff,0xff,0xef,
0xff,0xc7,0x37,0x3b,0xff,0xf0,0x13,0x9e,0x0f,0xf4,0xff,0xfe,0xfb,0xff,0xff,0xf9,
0xfc,0xff,0xff,0xff,0xff,0xbf,0xff,0xff,0xff,0xfa,0xf0,0xef,0xff,0xff,0xff,0xfe,
0xf3,0xc0,0x01,0x00,0x00,0x02,0x00,0x02,0x22,0x00,0x00,0xc0,0x40,0x00,0x40,0x00,
0x04,0x08,0x04,0x0a,0x01,0x01,0x10,0x20,0x20,0x00,0x00,0x04,0x08,0x08,0x04,0x00,
0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x3c,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xfd,
0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0x7f,0xff,0x7f,0xff,0xcf,0x9d,0xff,
0xff,0xf7,0xfd,0xf1,0xff,0xff,0xff,0xee,0xbf,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdb,0xf0,0x6f,0xff,0xff,0xff,0xfe,0xf0,0xff,
0xff,0xff,0xf7,0xf7,0xff,0xff,0xfe,0xbf,0xf7,0xff,0xff,0x5b,0xff,0xbf,0xf7,0xff,
0xfd,0x7f,0x71,0xfd,0xff,0xed,0xf7,0xfe,0xef,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
0xff,0xff,0xef,0xff,0x7f,0xff,0xd0,0xf0,0xff,0xff,0xff,0xff,0xfe,0xf8,0x30,0x11,
0x00,0x48,0x60,0x40,0x82,0x60,0x24,0x60,0x00,0xcc,0x00,0x80,0x04,0x01,0x00,0x00,
0x14,0x01,0x0c,0x04,0x00,0x30,0x00,0x00,0x00,0x08,0x08,0x00,0x01,0x00,0xc2,0x00,
0x00,0x02,0x00,0x80,0x00,0xc1,0xf0,0x5f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,
0xf7,0x7b,0xff,0xf3,0xeb,0xbf,0xff,0xf7,0xff,0xff,0xff,0xe7,0x5d,0x3f,0xff,0xf6,
0xd1,0xfd,0xff,0xeb,0xf7,0x3d,0xff,0xff,0xff,0x5f,0xff,0x7f,0x7f,0xf3,0xff,0xff,
0xef,0xfd,0xbf,0xff,0xff,0xf0,0x5f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf5,0xb5,0xdf,
0x6f,0x7d,0x69,0x7f,0xfb,0xdf,0x52,0x5f,0xf6,0xf7,0xfe,0xf6,0xf3,0xbd,0xb1,0xda,
0xcd,0xfe,0xf6,0xee,0xd2,0xbd,0xa5,0xaf,0xbd,0xff,0x6f,0x7c,0xeb,0x2b,0xfa,0xda,
0xff,0xfe,0xdf,0xf0,0x4f,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,0xff,0xdb,0xff,0xf6,
0xff,0xf6,0xff,0xbd,0xbf,0xcd,0xbf,0xeb,0x6f,0xf7,0x6f,0xdf,0xdb,0x51,0xfd,0xbd,
0xff,0x6f,0xff,0x6f,0xfb,0x5b,0xff,0xdb,0xff,0xf6,0xfe,0xf6,0xfd,0xfd,0xbf,0xfe,
0xf7,0xff,0xd0,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xfa,0x50,0xff,0xff,0xff,
0xf0,0x6f,0xff,0xff,0xf0,0x96,0xff,0xff,0xc6,0x2b,0xff,0xff,0xf1,0xfc,0xff,0xff,
0xf7,0xdb,0xc3,0xff,0x00,0xff,0xff,0xff,0xff,0xff,0xc1,0x4f,0xc3,0xff,0xff,0xff,
0xaf,0xf0,0x9f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf5,0xa0,0xff,0xff,0xff,0xf0,
0x6f,0xff,0xff,0xf0,0x96,0xff,0xff,0xc6,0x2b,0xff,0xff,0xf1,0x5a,0xff,0xff,0xff,
0xf3,0xc3,0xff,0x00,0xff,0xff,0xff,0xff,0xff,0xc1,0x4f,0xc3,0xff,0xff,0xff,0xff,
0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xfc,0xff,0xff,0x9f,0xf0,0x7f,
0xff,0xf9,0xfc,0x4f,0xf3,0xff,0x27,0xeb,0xff,0xfc,0x81,0xfc,0x7f,0xfe,0x7b,0xff,
0xf7,0xff,0x12,0x7f,0xff,0xff,0xff,0xff,0x18,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,
0x7f,0xff,0xff,0xff,0xfe,0xf5,0xff,0xff,0xff,0xdf,0xfe,0xff,0xfc,0x7e,0x7f,0xbf,
0xff,0xff,0xaf,0xef,0xff,0xdf,0xdf,0xfb,0xff,0xf1,0xc3,0xfe,0x6f,0xf1,0xcf,0x3f,
0xfb,0xff,0xff,0xcf,0xfe,0xff,0xff,0xfe,0x7f,0xbf,0xff,0xff,0xbf,0xfa,0xf0,0xdf,
0xff,0xff,0xff,0xfe,0xf3,0xc0,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x00,
0x20,0x00,0x01,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x02,0x00,0x00,0x80,0x00,0x02,0x80,0x00,0x02,0x3c,0xf0,0x2f,0xff,
0xff,0xff,0xfe,0xfd,0xbf,0xff,0xfb,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xf5,0xf1,0xff,0x7f,0xff,0xff,0xff,0xff,0xef,0xff,
0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xdb,0xf0,0x2f,0xff,0xff,
0xff,0xfe,0xf0,0xff,0xff,0xff,0xfb,0xff,0xbf,0xff,0xff,0xff,0xff,0xf7,0xbf,0xfb,
0xff,0xff,0xff,0xdf,0xf7,0xff,0xf1,0xf7,0xbf,0xfb,0xff,0xff,0xff,0x7f,0xde,0xff,
0xff,0xff,0xff,0xff,0xff,0xed,0xf7,0xff,0xff,0x7f,0xd0,0xf0,0x3f,0xff,0xff,0xff,
0xfe,0xf8,0x30,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0xe0,0x00,0x00,0x80,
0x20,0x01,0x01,0x92,0x00,0x01,0x01,0x00,0xe0,0x1c,0x60,0x20,0x30,0x08,0x08,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xc1,0xf0,0x6f,0xff,0xff,0xff,0xfe,
0xff,0xff,0xff,0xff,0xff,0xdb,0xfe,0xff,0xff,0xdf,0xff,0xfc,0x7f,0xfb,0xbf,0xff,
0xff,0xff,0xff,0xff,0xf1,0xf6,0xff,0xf7,0x7e,0x3f,0xff,0x7f,0xff,0xff,0xff,0xf7,
0xff,0xff,0xff,0xed,0xff,0xdf,0xff,0xb7,0xff,0xf0,0x3f,0xff,0xff,0xff,0xfe,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,
0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xbf,0xff,0xdf,
0x57,0xef,0xf1,0xfd,0xfe,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0xfb,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,
0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfb,0xff,0xdf,0xff,
0xff,0xf1,0xfd,0xff,0x7f,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xfe,0xff,0xff,0xff,0xff,0xf0,0x9f,0xff,0xff,0xff,0xfe,0xf7,0xfd,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0xff,0xff,0xff,0xff,0xff,
0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xf0,0x6f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,
0xff,0xff,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xfb,0xff,0xff,0xff,0xfe,0xff,0xff,0xfb,0x6f,0xff,0xfe,0xbf,0xff,0xf1,0xff,
0xf7,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfd,
0xff,0xff,0xff,0xf0,0xef,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xfb,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0x57,0xff,0xfd,0xbf,0xff,0xf1,0xff,0xef,
0xfe,0xff,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,
0xde,0xff,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf7,0xdb,0xff,0xdb,0xfd,
0xf6,0xff,0xf6,0xff,0x3c,0xbc,0xbc,0xbf,0xdf,0x6f,0xe7,0x2f,0xf1,0x3c,0xbf,0xfd,
0xbf,0xdf,0x6f,0xff,0x6f,0xf7,0xdb,0xff,0xdb,0xfd,0xf6,0xff,0xf6,0xff,0xff,0xff,
0x02,0x01,0xdf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff };

View File

@@ -0,0 +1,245 @@
/* 8530 Serial Communications Controller Register definitions */
#define FLAG 0x7e
/* Write Register 0 */
#define R0 0 /* Register selects */
#define R1 1
#define R2 2
#define R3 3
#define R4 4
#define R5 5
#define R6 6
#define R7 7
#define R8 8
#define R9 9
#define R10 10
#define R11 11
#define R12 12
#define R13 13
#define R14 14
#define R15 15
#define NULLCODE 0 /* Null Code */
#define POINT_HIGH 0x8 /* Select upper half of registers */
#define RES_EXT_INT 0x10 /* Reset Ext. Status Interrupts */
#define SEND_ABORT 0x18 /* HDLC Abort */
#define RES_RxINT_FC 0x20 /* Reset RxINT on First Character */
#define RES_Tx_P 0x28 /* Reset TxINT Pending */
#define ERR_RES 0x30 /* Error Reset */
#define RES_H_IUS 0x38 /* Reset highest IUS */
#define RES_Rx_CRC 0x40 /* Reset Rx CRC Checker */
#define RES_Tx_CRC 0x80 /* Reset Tx CRC Checker */
#define RES_EOM_L 0xC0 /* Reset EOM latch */
/* Write Register 1 */
#define EXT_INT_ENAB 0x1 /* Ext Int Enable */
#define TxINT_ENAB 0x2 /* Tx Int Enable */
#define PAR_SPEC 0x4 /* Parity is special condition */
#define RxINT_DISAB 0 /* Rx Int Disable */
#define RxINT_FCERR 0x8 /* Rx Int on First Character Only or Error */
#define INT_ALL_Rx 0x10 /* Int on all Rx Characters or error */
#define INT_ERR_Rx 0x18 /* Int on error only */
#define WT_RDY_RT 0x20 /* Wait/Ready on R/T */
#define WT_FN_RDYFN 0x40 /* Wait/FN/Ready FN */
#define WT_RDY_ENAB 0x80 /* Wait/Ready Enable */
/* Write Register #2 (Interrupt Vector) */
/* Write Register 3 */
#define RxENABLE 0x1 /* Rx Enable */
#define SYNC_L_INH 0x2 /* Sync Character Load Inhibit */
#define ADD_SM 0x4 /* Address Search Mode (SDLC) */
#define RxCRC_ENAB 0x8 /* Rx CRC Enable */
#define ENT_HM 0x10 /* Enter Hunt Mode */
#define AUTO_ENAB 0x20 /* Auto Enables */
#define Rx5 0x0 /* Rx 5 Bits/Character */
#define Rx7 0x40 /* Rx 7 Bits/Character */
#define Rx6 0x80 /* Rx 6 Bits/Character */
#define Rx8 0xc0 /* Rx 8 Bits/Character */
/* Write Register 4 */
#define PAR_ENA 0x1 /* Parity Enable */
#define PAR_EVEN 0x2 /* Parity Even/Odd* */
#define SYNC_ENAB 0 /* Sync Modes Enable */
#define SB1 0x4 /* 1 stop bit/char */
#define SB15 0x8 /* 1.5 stop bits/char */
#define SB2 0xc /* 2 stop bits/char */
#define MONSYNC 0 /* 8 Bit Sync character */
#define BISYNC 0x10 /* 16 bit sync character */
#define SDLC 0x20 /* SDLC Mode (01111110 Sync Flag) */
#define EXTSYNC 0x30 /* External Sync Mode */
#define X1CLK 0x0 /* x1 clock mode */
#define X16CLK 0x40 /* x16 clock mode */
#define X32CLK 0x80 /* x32 clock mode */
#define X64CLK 0xC0 /* x64 clock mode */
/* Write Register 5 */
#define TxCRC_ENAB 0x1 /* Tx CRC Enable */
#define RTS 0x2 /* RTS */
#define SDLC_CRC 0x4 /* SDLC/CRC-16 */
#define TxENAB 0x8 /* Tx Enable */
#define SND_BRK 0x10 /* Send Break */
#define Tx5 0x0 /* Tx 5 bits (or less)/character */
#define Tx7 0x20 /* Tx 7 bits/character */
#define Tx6 0x40 /* Tx 6 bits/character */
#define Tx8 0x60 /* Tx 8 bits/character */
#define DTR 0x80 /* DTR */
/* Write Register 6 (Sync bits 0-7/SDLC Address Field) */
/* Write Register 7 (Sync bits 8-15/SDLC 01111110) */
/* Write Register 8 (transmit buffer) */
/* Write Register 9 (Master interrupt control) */
#define VIS 1 /* Vector Includes Status */
#define NV 2 /* No Vector */
#define DLC 4 /* Disable Lower Chain */
#define MIE 8 /* Master Interrupt Enable */
#define STATHI 0x10 /* Status high */
#define NORESET 0 /* No reset on write to R9 */
#define CHRB 0x40 /* Reset channel B */
#define CHRA 0x80 /* Reset channel A */
#define FHWRES 0xc0 /* Force hardware reset */
/* Write Register 10 (misc control bits) */
#define BIT6 1 /* 6 bit/8bit sync */
#define LOOPMODE 2 /* SDLC Loop mode */
#define ABUNDER 4 /* Abort/flag on SDLC xmit underrun */
#define MARKIDLE 8 /* Mark/flag on idle */
#define GAOP 0x10 /* Go active on poll */
#define NRZ 0 /* NRZ mode */
#define NRZI 0x20 /* NRZI mode */
#define FM1 0x40 /* FM1 (transition = 1) */
#define FM0 0x60 /* FM0 (transition = 0) */
#define CRCPS 0x80 /* CRC Preset I/O */
/* Write Register 11 (Clock Mode control) */
#define TRxCXT 0 /* TRxC = Xtal output */
#define TRxCTC 1 /* TRxC = Transmit clock */
#define TRxCBR 2 /* TRxC = BR Generator Output */
#define TRxCDP 3 /* TRxC = DPLL output */
#define TRxCOI 4 /* TRxC O/I */
#define TCRTxCP 0 /* Transmit clock = RTxC pin */
#define TCTRxCP 8 /* Transmit clock = TRxC pin */
#define TCBR 0x10 /* Transmit clock = BR Generator output */
#define TCDPLL 0x18 /* Transmit clock = DPLL output */
#define RCRTxCP 0 /* Receive clock = RTxC pin */
#define RCTRxCP 0x20 /* Receive clock = TRxC pin */
#define RCBR 0x40 /* Receive clock = BR Generator output */
#define RCDPLL 0x60 /* Receive clock = DPLL output */
#define RTxCX 0x80 /* RTxC Xtal/No Xtal */
/* Write Register 12 (lower byte of baud rate generator time constant) */
/* Write Register 13 (upper byte of baud rate generator time constant) */
/* Write Register 14 (Misc control bits) */
#define BRENABL 1 /* Baud rate generator enable */
#define BRSRC 2 /* Baud rate generator source */
#define DTRREQ 4 /* DTR/Request function */
#define AUTOECHO 8 /* Auto Echo */
#define LOOPBAK 0x10 /* Local loopback */
#define SEARCH 0x20 /* Enter search mode */
#define RMC 0x40 /* Reset missing clock */
#define DISDPLL 0x60 /* Disable DPLL */
#define SSBR 0x80 /* Set DPLL source = BR generator */
#define SSRTxC 0xa0 /* Set DPLL source = RTxC */
#define SFMM 0xc0 /* Set FM mode */
#define SNRZI 0xe0 /* Set NRZI mode */
/* Write Register 15 (external/status interrupt control) */
#define ZCIE 2 /* Zero count IE */
#define DCDIE 8 /* DCD IE */
#define SYNCIE 0x10 /* Sync/hunt IE */
#define CTSIE 0x20 /* CTS IE */
#define TxUIE 0x40 /* Tx Underrun/EOM IE */
#define BRKIE 0x80 /* Break/Abort IE */
/* Read Register 0 */
#define Rx_CH_AV 0x1 /* Rx Character Available */
#define ZCOUNT 0x2 /* Zero count */
#define Tx_BUF_EMP 0x4 /* Tx Buffer empty */
#define DCD 0x8 /* DCD */
#define SYNC_HUNT 0x10 /* Sync/hunt */
#define CTS 0x20 /* CTS */
#define TxEOM 0x40 /* Tx underrun */
#define BRK_ABRT 0x80 /* Break/Abort */
/* Read Register 1 */
#define ALL_SNT 0x1 /* All sent */
/* Residue Data for 8 Rx bits/char programmed */
#define RES3 0x8 /* 0/3 */
#define RES4 0x4 /* 0/4 */
#define RES5 0xc /* 0/5 */
#define RES6 0x2 /* 0/6 */
#define RES7 0xa /* 0/7 */
#define RES8 0x6 /* 0/8 */
#define RES18 0xe /* 1/8 */
#define RES28 0x0 /* 2/8 */
/* Special Rx Condition Interrupts */
#define PAR_ERR 0x10 /* Parity error */
#define Rx_OVR 0x20 /* Rx Overrun Error */
#define CRC_ERR 0x40 /* CRC/Framing Error */
#define END_FR 0x80 /* End of Frame (SDLC) */
/* Read Register 2 (channel b only) - Interrupt vector */
/* Read Register 3 (interrupt pending register) ch a only */
#define CHBEXT 0x1 /* Channel B Ext/Stat IP */
#define CHBTxIP 0x2 /* Channel B Tx IP */
#define CHBRxIP 0x4 /* Channel B Rx IP */
#define CHAEXT 0x8 /* Channel A Ext/Stat IP */
#define CHATxIP 0x10 /* Channel A Tx IP */
#define CHARxIP 0x20 /* Channel A Rx IP */
/* Read Register 8 (receive data register) */
/* Read Register 10 (misc status bits) */
#define ONLOOP 2 /* On loop */
#define LOOPSEND 0x10 /* Loop sending */
#define CLK2MIS 0x40 /* Two clocks missing */
#define CLK1MIS 0x80 /* One clock missing */
/* Read Register 12 (lower byte of baud rate generator constant) */
/* Read Register 13 (upper byte of baud rate generator constant) */
/* Read Register 15 (value of WR 15) */
/* Z85C30/Z85230 Enhanced SCC register definitions */
/* Write Register 7' (SDLC/HDLC Programmable Enhancements) */
#define AUTOTXF 0x01 /* Auto Tx Flag */
#define AUTOEOM 0x02 /* Auto EOM Latch Reset */
#define AUTORTS 0x04 /* Auto RTS */
#define TXDNRZI 0x08 /* TxD Pulled High in SDLC NRZI mode */
#define RXFIFOH 0x08 /* Z85230: Int on RX FIFO half full */
#define FASTDTR 0x10 /* Fast DTR/REQ Mode */
#define CRCCBCR 0x20 /* CRC Check Bytes Completely Received */
#define TXFIFOE 0x20 /* Z85230: Int on TX FIFO completely empty */
#define EXTRDEN 0x40 /* Extended Read Enabled */
/* Write Register 15 (external/status interrupt control) */
#define SHDLCE 1 /* SDLC/HDLC Enhancements Enable */
#define FIFOE 4 /* FIFO Enable */
/* Read Register 6 (frame status FIFO) */
#define BCLSB 0xff /* LSB of 14 bits count */
/* Read Register 7 (frame status FIFO) */
#define BCMSB 0x3f /* MSB of 14 bits count */
#define FDA 0x40 /* FIFO Data Available Status */
#define FOS 0x80 /* FIFO Overflow Status */