Commit 796297ff authored by Linus Torvalds's avatar Linus Torvalds

Merge http://gkernel.bkbits.net/net-drivers-2.5

into penguin.transmeta.com:/home/penguin/torvalds/repositories/kernel/linux
parents 58c1bd4c 5b17799f
Generic HDLC layer for Linux kernel 2.4/2.5
Krzysztof Halasa <khc@pm.waw.pl>
May, 2001
Generic HDLC layer currently supports:
- Frame Relay (ANSI, CCITT and no LMI), with ARP support (no InARP),
- raw HDLC (IPv4 only),
- Cisco HDLC,
- PPP (uses syncppp.c),
- X.25 (uses X.25 routines).
There are hardware drivers for the following cards:
- C101 by Moxa Technologies Co., Ltd.
- RISCom/N2 by SDL Communications Inc.
- and others, some not in the official kernel.
Make sure the hdlc.o and the hardware driver are loaded. It should
create a number of "hdlc" (hdlc0 etc) network devices, one for each
WAN port. You'll need the "sethdlc" utility, get it from:
http://hq.pm.waw.pl/hdlc/
Compile sethdlc.c utility:
gcc -O2 -Wall -o sethdlc sethdlc.c
Make sure you're using a correct version of sethdlc for your kernel.
Use sethdlc to set physical interface, clock rate, HDLC mode used,
and add any required PVCs if using Frame Relay.
Usually you want something like:
sethdlc hdlc0 clock int rate 128000
sethdlc hdlc0 cisco interval 10 timeout 25
or
sethdlc hdlc0 rs232 clock ext
sethdlc fr lmi ansi
sethdlc create 99
In Frame Relay mode, ifconfig master hdlc device up (without assigning
any IP address to it) before using pvc devices.
Setting interface:
* v35 | rs232 | x21 | t1 | e1 - sets physical interface for a given port
if the card has software-selectable interfaces
loopback - activate hardware loopback (for testing only)
* clock ext - external clock (uses DTE RX and TX clock)
* clock int - internal clock (provides clock signal on DCE clock output)
* clock txint - TX internal, RX external (provides TX clock on DCE output)
* clock txfromrx - TX clock derived from RX clock (TX clock on DCE output)
* rate - sets clock rate in bps (not required for external clock or
for txfromrx)
Setting protocol:
* hdlc - sets raw HDLC (IP-only) mode
nrz / nrzi / fm-mark / fm-space / manchester - sets transmission code
no-parity / crc16 / crc16-pr0 (CRC16 with preset zeros) / crc32-itu
crc16-itu (CRC16 with ITU-T polynomial) / crc16-itu-pr0 - sets parity
* cisco - sets Cisco HDLC mode (IP, IPv6 and IPX supported)
interval - time in seconds between keepalive packets
timeout - time in seconds after last received keepalive packet before
we assume the link is down
* ppp - sets synchronous PPP mode
* x25 - sets X.25 mode
* fr - Frame Relay mode
lmi ansi / ccitt / none - LMI (link management) type
dce - Frame Relay DCE (network) side LMI instead of default DTE (user).
It has nothing to do with clocks!
t391 - link integrity verification polling timer (in seconds) - user
t392 - polling verification timer (in seconds) - network
n391 - full status polling counter - user
n392 - error threshold - both user and network
n393 - monitored events count - both user and network
* create | delete n - FR only - adds / deletes PVC interface with DLCI #n.
Board-specific issues
---------------------
n2.o and c101.o need parameters to work (note double quotes):
insmod n2 hw='"io,irq,ram,ports[:io,irq,...]"'
example:
insmod n2 hw='"0x300,10,0xD0000,01"'
or
insmod c101 hw='"irq,ram[:irq,...]"
example:
insmod c101 hw='"9,0xdc000"'
If built into the kernel, these drivers need kernel (command line) parameters:
n2=io,irq,ram,ports:...
or
c101=irq,ram:...
If you have a problem with N2 or C101 card, you can issue the "private"
command to see port's packet descriptor rings:
sethdlc hdlc0 private
The hardware driver have to be build with CONFIG_HDLC_DEBUG_RINGS.
Attaching this info to bug reports would be helpful. Anyway, let me know
if you have problems using this.
For patches and other info look at http://hq.pm.waw.pl/hdlc/
Brief Notes on C-Media 8738/8338 Driver
=======================================
Takashi Iwai <tiwai@suse.de>
Front/Rear Multi-channel Playback
---------------------------------
CM8x38 chip can use ADC as the second DAC so that two different stereo
channels can be used for front/rear playbacks. Since there are two
DACs, both streams are handled independently unlike the 4/6ch multi-
channel playbacks in the section below.
As default, ALSA driver assigns the first PCM device (i.e. hw:0,0 for
card#0) for front and 4/6ch playbacks, while the second PCM device
(hw:0,1) is assigned to the second DAC for rear playback.
There are slight difference between two DACs.
- The first DAC supports U8 and S16LE formats, while the second DAC
supports only S16LE.
- The second DAC supports only two channel stereo.
Please note that the CM8x38 DAC doesn't support continuous playback
rate but only fixed rates: 5512, 8000, 11025, 16000, 22050, 32000,
44100 and 48000 Hz.
The rear output can be heard only when "Four Channel Mode" switch is
disabled. Otherwise no signal will be routed to the rear speakers.
As default it's turned on.
*** WARNING ***
When "Four Channel Mode" switch is off, the output from rear speakers
will be FULL VOLUME regardless of Master and PCM volumes.
This might damage your audio equipment. Please disconnect speakers
before your turn off this switch.
*** WARNING ***
[ Well.. I once got the output with correct volume (i.e. same with the
front one) and was so excited. It was even with "Four Channel" bit
on and "double DAC" mode. Actually I could hear separate 4 channels
from front and rear speakers! But.. after reboot, all was gone.
It's a very pity that I didn't save the register dump at that
time.. Maybe there is an unknown register to achieve this... ]
If your card has an extra output jack for the rear output, the rear
playback should be routed there as default. If not, there is a
control switch in the driver "Line-In As Rear", which you can change
via alsamixer or somewhat else. When this switch is on, line-in jack
is used as rear output.
There are two more controls regarding to the rear output.
The "Exchange DAC" switch is used to exchange front and rear playback
routes, i.e. the 2nd DAC is output from front output.
4/6 Multi-Channel Playback
--------------------------
The recent CM8738 chips support for the 4/6 multi-channel playback
function. This is useful especially for AC3 decoding.
When the multi-channel is supported, the driver name has a suffix
"-MC" such like "CMI8738-MC6". You can check this name from
/proc/asound/cards.
When the 4/6-ch output is enabled, the front DAC accepts up to 6 (or
4) channels. This is different from the dual DACs described in the
previous section. While the dual DAC supports two different rates or
formats, the 4/6-ch playback supports only the same condition for all
channels.
For using 4/6 channel playback, you need to specify the PCM channels
as you like and set the format S16LE. For example, for playback with
4 channels,
snd_pcm_hw_params_set_access(pcm, hw, SND_PCM_ACCESS_RW_INTERLEAVED);
// or mmap if you like
snd_pcm_hw_params_set_format(pcm, hw, SND_PCM_FORMAT_S16_LE);
snd_pcm_hw_params_set_channels(pcm, hw, 4);
and use the interleaved 4 channel data.
There is a control switch, "Line-In As Bass". As you can imagine from
its name, the line-in jack is used for the bass (5th and 6th channels)
output.
Digital I/O
-----------
The CM8x38 provides the excellent SPDIF capability with very chip
price (yes, that's the reason I bought the card :)
The SPDIF playback and capture are done via the third PCM device
(hw:0,2). Usually this is assigned to the PCM device "spdif".
The available rates are 44100 and 48000 Hz.
For playback with aplay, you can run like below:
% aplay -Dhw:0,2 foo.wav
or
% aplay -Dspdif foo.wav
So far, only S16LE format is supported. Still no 24bit. Sorry, not
enough info for this.
The playback and capture over SPDIF use normal DAC and ADC,
respectively, so you cannot playback both analog and digital streams
simultaneously.
To enable SPDIF output, you need to turn on "IEC958 Output Switch"
control via mixer or alsactl. Then you'll see the red light on from
the card so you know that's working obviously :)
The SPDIF input is always enabled, so you can hear SPDIF input data
from line-out with "IEC958 In Monitor" switch at any time (see
below).
You can play via SPDIF even with the first device (hw:0,0),
but SPDIF is enabled only when the proper format (S16LE), sample rate
(441100 or 48000) and channels (2) are used. Otherwise it's turned
off. (Also don't forget to turn on "IEC958 Output Switch", too.)
Additionally there are relevant control switches:
"IEC958 Mix Analog" - Mix analog PCM playback and FM-OPL/3 streams and
output through SPDIF. This switch appears only on old chip
models (CM8738 033 and 037).
Note: without this control you can output PCM to SPDIF.
This is "mixing" of streams, so e.g. it's not for AC3 output
(see the next section).
"IEC958 In Select" - Select SPDIF input, the internal CD-in (false)
and the external input (true). This switch appears only on
the chip models 039 or later.
"IEC958 Loop" - SPDIF input data is loop back into SPDIF
output (aka bypass)
"IEC958 Copyright" - Set the copyright bit.
"IEC958 5V" - Select 0.5V (coax) or 5V (optical) interface.
On some cards this doesn't work and you need to change the
configuration with hardware dip-switch.
"IEC958 In Monitor" - SPDIF input is routed to DAC.
"IEC958 In Phase Inverse" - Set SPDIF input format as inverse.
[FIXME: this doesn't work on all chips..]
"IEC958 In Valid" - Set input validity flag detection.
Note: When "PCM Playback Switch" is on, you'll hear the digital output
stream through analog line-out.
The AC3 (RAW DIGITAL) OUTPUT
----------------------------
The driver supports raw digital (typically AC3) i/o over SPDIF. This
can be toggled via IEC958 playback control, but usually you need to
access it via alsa-lib. See alsa-lib documents for more details.
On the raw digital mode, the "PCM Playback Switch" is automatically
turned off so that non-audio data is heard from the analog line-out.
Similarly the following switches are off: "IEC958 Mix Analog" and
"IEC958 Loop". The switches are resumed after closing the SPDIF PCM
device automatically to the previous state.
ANALOG MIXER INTERFACE
----------------------
The mixer interface on CM8x38 is similar to SB16.
There are Master, PCM, Synth, CD, Line, Mic and PC Speaker playback
volumes. Synth, CD, Line and Mic have playback and capture switches,
too, as well as SB16.
In addition to the standard SB mixer, CM8x38 provides more functions.
- PCM playback switch
- PCM capture switch (to capture the data sent to DAC)
- Mic Boost switch
- Mic capture volume
- Aux playback volume/switch and capture switch
- 3D control switch
MIDI CONTROLLER
---------------
The MPU401-UART interface is enabled as default only for the first
(CMIPCI) card. You need to set module option "snd_midi_port" properly
for the 2nd (CMIPCI) card.
There is _no_ hardware wavetable function on this chip (except for
OPL3 synth below).
What's said as MIDI synth on Windows is a software synthesizer
emulation. On Linux use TiMidity or other softsynth program for
playing MIDI music.
FM OPL/3 Synth
--------------
The FM OPL/3 is also enabled as default only for the first card.
Set "snd_fm_port" module option for more cards.
The output quality of FM OPL/3 is, however, very weird.
I don't know why..
Joystick and Modem
------------------
The joystick and modem should be available by enabling the control
switch "Joystick" and "Modem" respectively. But I myself have never
tested them yet.
Debugging Information
---------------------
The registers are shown in /proc/asound/cardX/cmipci. If you have any
problem (especially unexpected behavior of mixer), please attach the
output of this proc file together with the bug report.
This diff is collapsed.
This diff is collapsed.
...@@ -41,14 +41,15 @@ CONFIG_FARSYNC ...@@ -41,14 +41,15 @@ CONFIG_FARSYNC
This driver supports the FarSync T-Series X.21 (and V.35/V.24) cards This driver supports the FarSync T-Series X.21 (and V.35/V.24) cards
from FarSite Communications Ltd. from FarSite Communications Ltd.
Synchronous communication is supported on all ports at speeds up to Synchronous communication is supported on all ports at speeds up to
8Mb/s (128K on V.24) using synchronous PPP or Cisco HDLC. 8Mb/s (128K on V.24) using synchronous PPP, Cisco HDLC, raw HDLC,
Frame Relay or X.25/LAPB.
If you want to compile this driver as a module ( = code which can be If you want to compile this driver as a module ( = code which can be
inserted in and removed from the running kernel whenever you want) inserted in and removed from the running kernel whenever you want)
say M here and read <file:Documentation/modules.txt>. say M here and read <file:Documentation/modules.txt>.
The module will be called farsync.o and if you want the module to be The module will be called farsync.o and if you want the module to be
automatically loaded when the interface is referenced then you automatically loaded when the interface is referenced then you
should add "alias syncX farsync" to /etc/modules.conf for each should add "alias hdlcX farsync" to /etc/modules.conf for each
interface, where X is 0, 1, 2, ... interface, where X is 0, 1, 2, ...
CONFIG_DLCI CONFIG_DLCI
......
...@@ -39,9 +39,6 @@ if [ "$CONFIG_WAN" = "y" ]; then ...@@ -39,9 +39,6 @@ if [ "$CONFIG_WAN" = "y" ]; then
dep_tristate ' Etinc PCISYNC serial board support (EXPERIMENTAL)' CONFIG_DSCC4 m dep_tristate ' Etinc PCISYNC serial board support (EXPERIMENTAL)' CONFIG_DSCC4 m
# FarSite Communications' cards
tristate ' FarSync T-Series X.21 (and V.35/V.24) cards' CONFIG_FARSYNC
# #
# Lan Media's board. Currently 1000, 1200, 5200, 5245 # Lan Media's board. Currently 1000, 1200, 5200, 5245
...@@ -55,8 +52,13 @@ if [ "$CONFIG_WAN" = "y" ]; then ...@@ -55,8 +52,13 @@ if [ "$CONFIG_WAN" = "y" ]; then
tristate ' SyncLink HDLC/SYNCPPP support' CONFIG_SYNCLINK_SYNCPPP tristate ' SyncLink HDLC/SYNCPPP support' CONFIG_SYNCLINK_SYNCPPP
tristate ' Generic HDLC driver' CONFIG_HDLC # Generic HDLC
tristate ' Generic HDLC layer' CONFIG_HDLC
if [ "$CONFIG_HDLC" != "n" ]; then if [ "$CONFIG_HDLC" != "n" ]; then
bool ' Raw HDLC support' CONFIG_HDLC_RAW
bool ' Cisco HDLC support' CONFIG_HDLC_CISCO
bool ' Frame Relay support' CONFIG_HDLC_FR
bool ' Synchronous Point-to-Point Protocol (PPP) support' CONFIG_HDLC_PPP bool ' Synchronous Point-to-Point Protocol (PPP) support' CONFIG_HDLC_PPP
if [ "$CONFIG_LAPB" = "m" -a "$CONFIG_HDLC" = "m" -o "$CONFIG_LAPB" = "y" ]; then if [ "$CONFIG_LAPB" = "m" -a "$CONFIG_HDLC" = "m" -o "$CONFIG_LAPB" = "y" ]; then
bool ' X.25 protocol support' CONFIG_HDLC_X25 bool ' X.25 protocol support' CONFIG_HDLC_X25
...@@ -65,6 +67,11 @@ if [ "$CONFIG_WAN" = "y" ]; then ...@@ -65,6 +67,11 @@ if [ "$CONFIG_WAN" = "y" ]; then
fi fi
dep_tristate ' SDL RISCom/N2 support' CONFIG_N2 $CONFIG_HDLC dep_tristate ' SDL RISCom/N2 support' CONFIG_N2 $CONFIG_HDLC
dep_tristate ' Moxa C101 support' CONFIG_C101 $CONFIG_HDLC dep_tristate ' Moxa C101 support' CONFIG_C101 $CONFIG_HDLC
dep_tristate ' FarSync T-Series support' CONFIG_FARSYNC $CONFIG_HDLC
bool ' Debug received/transmitted packets' CONFIG_HDLC_DEBUG_PKT
bool ' Debug hard_header routines' CONFIG_HDLC_DEBUG_HARD_HEADER
bool ' Debug FECN/BECN conditions' CONFIG_HDLC_DEBUG_ECN
bool ' Debug RX/TX packet rings' CONFIG_HDLC_DEBUG_RINGS
fi fi
tristate ' Frame relay DLCI support' CONFIG_DLCI tristate ' Frame relay DLCI support' CONFIG_DLCI
......
...@@ -9,7 +9,7 @@ SUB_DIRS := ...@@ -9,7 +9,7 @@ SUB_DIRS :=
O_TARGET := wan.o O_TARGET := wan.o
export-objs = z85230.o syncppp.o comx.o sdladrv.o cycx_drv.o hdlc.o export-objs = z85230.o syncppp.o comx.o sdladrv.o cycx_drv.o hdlc_generic.o
list-multi = wanpipe.o cyclomx.o list-multi = wanpipe.o cyclomx.o
wanpipe-objs = sdlamain.o sdla_ft1.o $(wanpipe-y) wanpipe-objs = sdlamain.o sdla_ft1.o $(wanpipe-y)
...@@ -22,6 +22,11 @@ wanpipe-$(CONFIG_WANPIPE_MULTPPP) += wanpipe_multppp.o ...@@ -22,6 +22,11 @@ wanpipe-$(CONFIG_WANPIPE_MULTPPP) += wanpipe_multppp.o
cyclomx-objs = cycx_main.o $(cyclomx-y) cyclomx-objs = cycx_main.o $(cyclomx-y)
cyclomx-$(CONFIG_CYCLOMX_X25) += cycx_x25.o cyclomx-$(CONFIG_CYCLOMX_X25) += cycx_x25.o
hdlc-$(CONFIG_HDLC_RAW) += hdlc_raw.o
hdlc-$(CONFIG_HDLC_CISCO) += hdlc_cisco.o
hdlc-$(CONFIG_HDLC_FR) += hdlc_fr.o
hdlc-$(CONFIG_HDLC_PPP) += hdlc_ppp.o
hdlc-$(CONFIG_HDLC_X25) += hdlc_x25.o
obj-$(CONFIG_HOSTESS_SV11) += z85230.o syncppp.o hostess_sv11.o obj-$(CONFIG_HOSTESS_SV11) += z85230.o syncppp.o hostess_sv11.o
obj-$(CONFIG_SEALEVEL_4021) += z85230.o syncppp.o sealevel.o obj-$(CONFIG_SEALEVEL_4021) += z85230.o syncppp.o sealevel.o
...@@ -56,12 +61,17 @@ obj-$(CONFIG_CYCLADES_SYNC) += cycx_drv.o cyclomx.o ...@@ -56,12 +61,17 @@ obj-$(CONFIG_CYCLADES_SYNC) += cycx_drv.o cyclomx.o
obj-$(CONFIG_LAPBETHER) += lapbether.o obj-$(CONFIG_LAPBETHER) += lapbether.o
obj-$(CONFIG_SBNI) += sbni.o obj-$(CONFIG_SBNI) += sbni.o
obj-$(CONFIG_HDLC) += hdlc.o obj-$(CONFIG_HDLC) += hdlc.o
obj-$(CONFIG_HDLC_PPP) += syncppp.o ifeq ($(CONFIG_HDLC_PPP),y)
obj-$(CONFIG_HDLC) += syncppp.o
endif
obj-$(CONFIG_N2) += n2.o obj-$(CONFIG_N2) += n2.o
obj-$(CONFIG_C101) += c101.o obj-$(CONFIG_C101) += c101.o
include $(TOPDIR)/Rules.make include $(TOPDIR)/Rules.make
hdlc.o: hdlc_generic.o $(hdlc-y)
$(LD) -r -o $@ hdlc_generic.o $(hdlc-y)
wanpipe.o: $(wanpipe-objs) wanpipe.o: $(wanpipe-objs)
$(LD) -r -o $@ $(wanpipe-objs) $(LD) -r -o $@ $(wanpipe-objs)
......
/* /*
* Moxa C101 synchronous serial card driver for Linux * Moxa C101 synchronous serial card driver for Linux
* *
* Copyright (C) 2000 Krzysztof Halasa <khc@pm.waw.pl> * Copyright (C) 2000-2001 Krzysztof Halasa <khc@pm.waw.pl>
* *
* This program is free software; you can redistribute it and/or modify it * 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 * under the terms of the GNU General Public License as published by
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
* Moxa C101 User's Manual * Moxa C101 User's Manual
*/ */
#include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -29,10 +30,8 @@ ...@@ -29,10 +30,8 @@
#include "hd64570.h" #include "hd64570.h"
#define DEBUG_RINGS
/* #define DEBUG_PKT */
static const char* version = "Moxa C101 driver revision: 1.02 for Linux 2.4"; static const char* version = "Moxa C101 driver version: 1.09";
static const char* devname = "C101"; static const char* devname = "C101";
#define C101_PAGE 0x1D00 #define C101_PAGE 0x1D00
...@@ -51,12 +50,12 @@ static char *hw; /* pointer to hw=xxx command line string */ ...@@ -51,12 +50,12 @@ static char *hw; /* pointer to hw=xxx command line string */
typedef struct card_s { typedef struct card_s {
hdlc_device hdlc; /* HDLC device struct - must be first */ hdlc_device hdlc; /* HDLC device struct - must be first */
spinlock_t lock; /* TX lock */ spinlock_t lock; /* TX lock */
int clkmode; /* clock mode */
int clkrate; /* clock speed */
int line; /* loopback only */
u8 *win0base; /* ISA window base address */ u8 *win0base; /* ISA window base address */
u32 phy_winbase; /* ISA physical base address */ u32 phy_winbase; /* ISA physical base address */
u16 buff_offset; /* offset of first buffer of first channel */ u16 buff_offset; /* offset of first buffer of first channel */
sync_serial_settings settings;
unsigned short encoding;
unsigned short parity;
u8 rxs, txs, tmc; /* SCA registers */ u8 rxs, txs, tmc; /* SCA registers */
u8 irq; /* IRQ (3-15) */ u8 irq; /* IRQ (3-15) */
u8 ring_buffers; /* number of buffers in a ring */ u8 ring_buffers; /* number of buffers in a ring */
...@@ -72,6 +71,9 @@ typedef struct card_s { ...@@ -72,6 +71,9 @@ typedef struct card_s {
typedef card_t port_t; typedef card_t port_t;
static card_t *first_card;
static card_t **new_card = &first_card;
#define sca_in(reg, card) readb((card)->win0base + C101_SCA + (reg)) #define sca_in(reg, card) readb((card)->win0base + C101_SCA + (reg))
#define sca_out(value, reg, card) writeb(value, (card)->win0base + C101_SCA + (reg)) #define sca_out(value, reg, card) writeb(value, (card)->win0base + C101_SCA + (reg))
...@@ -105,13 +107,13 @@ static inline void openwin(card_t *card, u8 page) ...@@ -105,13 +107,13 @@ static inline void openwin(card_t *card, u8 page)
#include "hd6457x.c" #include "hd6457x.c"
static int c101_set_clock(port_t *port, int value) static int c101_set_iface(port_t *port)
{ {
u8 msci = get_msci(port); u8 msci = get_msci(port);
u8 rxs = port->rxs & CLK_BRG_MASK; u8 rxs = port->rxs & CLK_BRG_MASK;
u8 txs = port->txs & CLK_BRG_MASK; u8 txs = port->txs & CLK_BRG_MASK;
switch(value) { switch(port->settings.clock_type) {
case CLOCK_EXT: case CLOCK_EXT:
rxs |= CLK_LINE_RX; /* RXC input */ rxs |= CLK_LINE_RX; /* RXC input */
txs |= CLK_LINE_TX; /* TXC input */ txs |= CLK_LINE_TX; /* TXC input */
...@@ -140,76 +142,76 @@ static int c101_set_clock(port_t *port, int value) ...@@ -140,76 +142,76 @@ static int c101_set_clock(port_t *port, int value)
port->txs = txs; port->txs = txs;
sca_out(rxs, msci + RXS, port); sca_out(rxs, msci + RXS, port);
sca_out(txs, msci + TXS, port); sca_out(txs, msci + TXS, port);
port->clkmode = value; sca_set_port(port);
return 0; return 0;
} }
static int c101_open(hdlc_device *hdlc) static int c101_open(struct net_device *dev)
{ {
hdlc_device *hdlc = dev_to_hdlc(dev);
port_t *port = hdlc_to_port(hdlc); port_t *port = hdlc_to_port(hdlc);
int result = hdlc_open(hdlc);
if (result)
return result;
MOD_INC_USE_COUNT; MOD_INC_USE_COUNT;
writeb(1, port->win0base + C101_DTR); writeb(1, port->win0base + C101_DTR);
sca_out(0, MSCI1_OFFSET + CTL, port); /* RTS uses ch#2 output */ sca_out(0, MSCI1_OFFSET + CTL, port); /* RTS uses ch#2 output */
sca_open(hdlc); sca_open(hdlc);
c101_set_clock(port, port->clkmode); return c101_set_iface(port);
return 0;
} }
static void c101_close(hdlc_device *hdlc) static int c101_close(struct net_device *dev)
{ {
hdlc_device *hdlc = dev_to_hdlc(dev);
port_t *port = hdlc_to_port(hdlc); port_t *port = hdlc_to_port(hdlc);
sca_close(hdlc); sca_close(hdlc);
writeb(0, port->win0base + C101_DTR); writeb(0, port->win0base + C101_DTR);
sca_out(CTL_NORTS, MSCI1_OFFSET + CTL, port); sca_out(CTL_NORTS, MSCI1_OFFSET + CTL, port);
hdlc_close(hdlc);
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
return 0;
} }
static int c101_ioctl(hdlc_device *hdlc, struct ifreq *ifr, int cmd) static int c101_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{ {
int value = ifr->ifr_ifru.ifru_ivalue; union line_settings *line = &ifr->ifr_settings->ifs_line;
int result = 0; const size_t size = sizeof(sync_serial_settings);
hdlc_device *hdlc = dev_to_hdlc(dev);
port_t *port = hdlc_to_port(hdlc); port_t *port = hdlc_to_port(hdlc);
#ifdef CONFIG_HDLC_DEBUG_RINGS
if (cmd == SIOCDEVPRIVATE) {
sca_dump_rings(hdlc);
return 0;
}
#endif
if (cmd != SIOCWANDEV)
return hdlc_ioctl(dev, ifr, cmd);
switch(ifr->ifr_settings->type) {
case IF_GET_IFACE:
ifr->ifr_settings->type = IF_IFACE_SYNC_SERIAL;
if (copy_to_user(&line->sync, &port->settings, size))
return -EFAULT;
return 0;
case IF_IFACE_SYNC_SERIAL:
if(!capable(CAP_NET_ADMIN)) if(!capable(CAP_NET_ADMIN))
return -EPERM; return -EPERM;
switch(cmd) { if (copy_from_user(&port->settings, &line->sync, size))
case HDLCSCLOCK: return -EFAULT;
result = c101_set_clock(port, value); /* FIXME - put sanity checks here */
case HDLCGCLOCK: return c101_set_iface(port);
value = port->clkmode;
break;
case HDLCSCLOCKRATE:
port->clkrate = value;
sca_set_clock(port);
case HDLCGCLOCKRATE:
value = port->clkrate;
break;
case HDLCSLINE:
result = sca_set_loopback(port, value);
case HDLCGLINE:
value = port->line;
break;
#ifdef DEBUG_RINGS
case HDLCRUN:
sca_dump_rings(hdlc);
return 0;
#endif /* DEBUG_RINGS */
default: default:
return -EINVAL; return hdlc_ioctl(dev, ifr, cmd);
} }
ifr->ifr_ifru.ifru_ivalue = value;
return result;
} }
...@@ -231,6 +233,7 @@ static void c101_destroy_card(card_t *card) ...@@ -231,6 +233,7 @@ static void c101_destroy_card(card_t *card)
static int c101_run(unsigned long irq, unsigned long winbase) static int c101_run(unsigned long irq, unsigned long winbase)
{ {
struct net_device *dev;
card_t *card; card_t *card;
int result; int result;
...@@ -284,15 +287,19 @@ static int c101_run(unsigned long irq, unsigned long winbase) ...@@ -284,15 +287,19 @@ static int c101_run(unsigned long irq, unsigned long winbase)
sca_init(card, 0); sca_init(card, 0);
dev = hdlc_to_dev(&card->hdlc);
spin_lock_init(&card->lock); spin_lock_init(&card->lock);
hdlc_to_dev(&card->hdlc)->irq = irq; dev->irq = irq;
hdlc_to_dev(&card->hdlc)->mem_start = winbase; dev->mem_start = winbase;
hdlc_to_dev(&card->hdlc)->mem_end = winbase + C101_MAPPED_RAM_SIZE - 1; dev->mem_end = winbase + C101_MAPPED_RAM_SIZE - 1;
hdlc_to_dev(&card->hdlc)->tx_queue_len = 50; dev->tx_queue_len = 50;
card->hdlc.ioctl = c101_ioctl; dev->do_ioctl = c101_ioctl;
card->hdlc.open = c101_open; dev->open = c101_open;
card->hdlc.close = c101_close; dev->stop = c101_close;
card->hdlc.attach = sca_attach;
card->hdlc.xmit = sca_xmit; card->hdlc.xmit = sca_xmit;
card->settings.clock_type = CLOCK_EXT;
result = register_hdlc_device(&card->hdlc); result = register_hdlc_device(&card->hdlc);
if (result) { if (result) {
...@@ -319,7 +326,7 @@ static int __init c101_init(void) ...@@ -319,7 +326,7 @@ static int __init c101_init(void)
return -ENOSYS; /* no parameters specified, abort */ return -ENOSYS; /* no parameters specified, abort */
} }
printk(KERN_INFO "%s\n", version); printk(KERN_INFO "%s (SCA-%s)\n", version, sca_version);
do { do {
unsigned long irq, ram; unsigned long irq, ram;
......
This diff is collapsed.
This diff is collapsed.
...@@ -32,13 +32,8 @@ ...@@ -32,13 +32,8 @@
* A short common prefix is useful for routines within the driver to avoid * A short common prefix is useful for routines within the driver to avoid
* conflict with other similar drivers and I chosen to use "fst_" for this * conflict with other similar drivers and I chosen to use "fst_" for this
* purpose (FarSite T-series). * purpose (FarSite T-series).
*
* Finally the device driver needs a short network interface name. Since
* "hdlc" is already in use I've chosen the even less informative "sync"
* for the present.
*/ */
#define FST_NAME "fst" /* In debug/info etc */ #define FST_NAME "fst" /* In debug/info etc */
#define FST_NDEV_NAME "sync" /* For net interface */
#define FST_DEV_NAME "farsync" /* For misc interfaces */ #define FST_DEV_NAME "farsync" /* For misc interfaces */
......
...@@ -152,7 +152,7 @@ typedef struct { ...@@ -152,7 +152,7 @@ typedef struct {
u32 bp; /* Buffer Pointer (24 bits) */ u32 bp; /* Buffer Pointer (24 bits) */
u16 len; /* Data Length */ u16 len; /* Data Length */
u8 stat; /* Status */ u8 stat; /* Status */
u8 unused2; u8 unused; /* pads to 2-byte boundary */
}__attribute__ ((packed)) pkt_desc; }__attribute__ ((packed)) pkt_desc;
...@@ -202,7 +202,11 @@ typedef struct { ...@@ -202,7 +202,11 @@ typedef struct {
#define MD0_CRC_ITU_0 0x06 #define MD0_CRC_ITU_0 0x06
#define MD0_CRC_ITU 0x07 #define MD0_CRC_ITU 0x07
#define MD2_NRZI 0x20 /* NRZI mode */ #define MD2_NRZ 0x00
#define MD2_NRZI 0x20
#define MD2_MANCHESTER 0x80
#define MD2_FM_MARK 0xA0
#define MD2_FM_SPACE 0xC0
#define MD2_LOOPBACK 0x03 /* Local data Loopback */ #define MD2_LOOPBACK 0x03 /* Local data Loopback */
#define CTL_NORTS 0x01 #define CTL_NORTS 0x01
......
This diff is collapsed.
/*
* Generic HDLC support routines for Linux
* Cisco HDLC support
*
* Copyright (C) 2000 - 2001 Krzysztof Halasa <khc@pm.waw.pl>
*
* 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.
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/if_arp.h>
#include <linux/init.h>
#include <linux/skbuff.h>
#include <linux/pkt_sched.h>
#include <linux/inetdevice.h>
#include <linux/lapb.h>
#include <linux/rtnetlink.h>
#include <linux/hdlc.h>
#define CISCO_MULTICAST 0x8F /* Cisco multicast address */
#define CISCO_UNICAST 0x0F /* Cisco unicast address */
#define CISCO_KEEPALIVE 0x8035 /* Cisco keepalive protocol */
#define CISCO_SYS_INFO 0x2000 /* Cisco interface/system info */
#define CISCO_ADDR_REQ 0 /* Cisco address request */
#define CISCO_ADDR_REPLY 1 /* Cisco address reply */
#define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */
static int cisco_hard_header(struct sk_buff *skb, struct net_device *dev,
u16 type, void *daddr, void *saddr,
unsigned int len)
{
hdlc_header *data;
#ifdef CONFIG_HDLC_DEBUG_HARD_HEADER
printk(KERN_DEBUG "%s: cisco_hard_header called\n", dev->name);
#endif
skb_push(skb, sizeof(hdlc_header));
data = (hdlc_header*)skb->data;
if (type == CISCO_KEEPALIVE)
data->address = CISCO_MULTICAST;
else
data->address = CISCO_UNICAST;
data->control = 0;
data->protocol = htons(type);
return sizeof(hdlc_header);
}
static void cisco_keepalive_send(hdlc_device *hdlc, u32 type,
u32 par1, u32 par2)
{
struct sk_buff *skb;
cisco_packet *data;
skb = dev_alloc_skb(sizeof(hdlc_header) + sizeof(cisco_packet));
if (!skb) {
printk(KERN_WARNING
"%s: Memory squeeze on cisco_keepalive_send()\n",
hdlc_to_name(hdlc));
return;
}
skb_reserve(skb, 4);
cisco_hard_header(skb, hdlc_to_dev(hdlc), CISCO_KEEPALIVE,
NULL, NULL, 0);
data = (cisco_packet*)skb->tail;
data->type = htonl(type);
data->par1 = htonl(par1);
data->par2 = htonl(par2);
data->rel = 0xFFFF;
data->time = htonl(jiffies * 1000 / HZ);
skb_put(skb, sizeof(cisco_packet));
skb->priority = TC_PRIO_CONTROL;
skb->dev = hdlc_to_dev(hdlc);
dev_queue_xmit(skb);
}
static void cisco_rx(struct sk_buff *skb)
{
hdlc_device *hdlc = dev_to_hdlc(skb->dev);
hdlc_header *data = (hdlc_header*)skb->data;
cisco_packet *cisco_data;
struct in_device *in_dev;
u32 addr, mask;
if (skb->len < sizeof(hdlc_header))
goto rx_error;
if (data->address != CISCO_MULTICAST &&
data->address != CISCO_UNICAST)
goto rx_error;
skb_pull(skb, sizeof(hdlc_header));
switch(ntohs(data->protocol)) {
case ETH_P_IP:
case ETH_P_IPX:
case ETH_P_IPV6:
skb->protocol = data->protocol;
skb->dev = hdlc_to_dev(hdlc);
netif_rx(skb);
return;
case CISCO_SYS_INFO:
/* Packet is not needed, drop it. */
dev_kfree_skb_any(skb);
return;
case CISCO_KEEPALIVE:
if (skb->len != CISCO_PACKET_LEN &&
skb->len != CISCO_BIG_PACKET_LEN) {
printk(KERN_INFO "%s: Invalid length of Cisco "
"control packet (%d bytes)\n",
hdlc_to_name(hdlc), skb->len);
goto rx_error;
}
cisco_data = (cisco_packet*)skb->data;
switch(ntohl (cisco_data->type)) {
case CISCO_ADDR_REQ: /* Stolen from syncppp.c :-) */
in_dev = hdlc_to_dev(hdlc)->ip_ptr;
addr = 0;
mask = ~0; /* is the mask correct? */
if (in_dev != NULL) {
struct in_ifaddr **ifap = &in_dev->ifa_list;
while (*ifap != NULL) {
if (strcmp(hdlc_to_name(hdlc),
(*ifap)->ifa_label) == 0) {
addr = (*ifap)->ifa_local;
mask = (*ifap)->ifa_mask;
break;
}
ifap = &(*ifap)->ifa_next;
}
cisco_keepalive_send(hdlc, CISCO_ADDR_REPLY,
addr, mask);
}
dev_kfree_skb_any(skb);
return;
case CISCO_ADDR_REPLY:
printk(KERN_INFO "%s: Unexpected Cisco IP address "
"reply\n", hdlc_to_name(hdlc));
goto rx_error;
case CISCO_KEEPALIVE_REQ:
hdlc->state.cisco.rxseq = ntohl(cisco_data->par1);
if (ntohl(cisco_data->par2) == hdlc->state.cisco.txseq) {
hdlc->state.cisco.last_poll = jiffies;
if (!hdlc->state.cisco.up) {
u32 sec, min, hrs, days;
sec = ntohl(cisco_data->time) / 1000;
min = sec / 60; sec -= min * 60;
hrs = min / 60; min -= hrs * 60;
days = hrs / 24; hrs -= days * 24;
printk(KERN_INFO "%s: Link up (peer "
"uptime %ud%uh%um%us)\n",
hdlc_to_name(hdlc), days, hrs,
min, sec);
}
hdlc->state.cisco.up = 1;
}
dev_kfree_skb_any(skb);
return;
} /* switch(keepalive type) */
} /* switch(protocol) */
printk(KERN_INFO "%s: Unsupported protocol %x\n", hdlc_to_name(hdlc),
data->protocol);
dev_kfree_skb_any(skb);
return;
rx_error:
hdlc->stats.rx_errors++; /* Mark error */
dev_kfree_skb_any(skb);
}
static void cisco_timer(unsigned long arg)
{
hdlc_device *hdlc = (hdlc_device*)arg;
if (hdlc->state.cisco.up &&
jiffies - hdlc->state.cisco.last_poll >=
hdlc->state.cisco.settings.timeout * HZ) {
hdlc->state.cisco.up = 0;
printk(KERN_INFO "%s: Link down\n", hdlc_to_name(hdlc));
}
cisco_keepalive_send(hdlc, CISCO_KEEPALIVE_REQ,
++hdlc->state.cisco.txseq,
hdlc->state.cisco.rxseq);
hdlc->state.cisco.timer.expires = jiffies +
hdlc->state.cisco.settings.interval * HZ;
hdlc->state.cisco.timer.function = cisco_timer;
hdlc->state.cisco.timer.data = arg;
add_timer(&hdlc->state.cisco.timer);
}
static int cisco_open(hdlc_device *hdlc)
{
hdlc->state.cisco.last_poll = 0;
hdlc->state.cisco.up = 0;
hdlc->state.cisco.txseq = hdlc->state.cisco.rxseq = 0;
init_timer(&hdlc->state.cisco.timer);
hdlc->state.cisco.timer.expires = jiffies + HZ; /*First poll after 1s*/
hdlc->state.cisco.timer.function = cisco_timer;
hdlc->state.cisco.timer.data = (unsigned long)hdlc;
add_timer(&hdlc->state.cisco.timer);
return 0;
}
static void cisco_close(hdlc_device *hdlc)
{
del_timer_sync(&hdlc->state.cisco.timer);
}
int hdlc_cisco_ioctl(hdlc_device *hdlc, struct ifreq *ifr)
{
cisco_proto *cisco_s = &ifr->ifr_settings->ifs_hdlc.cisco;
const size_t size = sizeof(cisco_proto);
struct net_device *dev = hdlc_to_dev(hdlc);
int result;
switch (ifr->ifr_settings->type) {
case IF_GET_PROTO:
ifr->ifr_settings->type = IF_PROTO_CISCO;
if (copy_to_user(cisco_s, &hdlc->state.cisco.settings, size))
return -EFAULT;
return 0;
case IF_PROTO_CISCO:
if(!capable(CAP_NET_ADMIN))
return -EPERM;
if(dev->flags & IFF_UP)
return -EBUSY;
if (copy_from_user(&hdlc->state.cisco.settings, cisco_s, size))
return -EFAULT;
/* FIXME - put sanity checks here */
hdlc_detach(hdlc);
result=hdlc->attach(hdlc, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT);
if (result) {
hdlc->proto = -1;
return result;
}
hdlc->open = cisco_open;
hdlc->stop = cisco_close;
hdlc->netif_rx = cisco_rx;
hdlc->proto = IF_PROTO_CISCO;
dev->hard_start_xmit = hdlc->xmit;
dev->hard_header = cisco_hard_header;
dev->type = ARPHRD_CISCO;
dev->addr_len = 0;
return 0;
}
return -EINVAL;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -2117,11 +2117,13 @@ EXPORT_SYMBOL(pci_announce_device_to_drivers); ...@@ -2117,11 +2117,13 @@ EXPORT_SYMBOL(pci_announce_device_to_drivers);
EXPORT_SYMBOL(pci_add_new_bus); EXPORT_SYMBOL(pci_add_new_bus);
EXPORT_SYMBOL(pci_do_scan_bus); EXPORT_SYMBOL(pci_do_scan_bus);
EXPORT_SYMBOL(pci_scan_slot); EXPORT_SYMBOL(pci_scan_slot);
#ifdef CONFIG_PROC_FS
EXPORT_SYMBOL(pci_proc_attach_device); EXPORT_SYMBOL(pci_proc_attach_device);
EXPORT_SYMBOL(pci_proc_detach_device); EXPORT_SYMBOL(pci_proc_detach_device);
EXPORT_SYMBOL(pci_proc_attach_bus); EXPORT_SYMBOL(pci_proc_attach_bus);
EXPORT_SYMBOL(pci_proc_detach_bus); EXPORT_SYMBOL(pci_proc_detach_bus);
#endif #endif
#endif
EXPORT_SYMBOL(pci_set_power_state); EXPORT_SYMBOL(pci_set_power_state);
EXPORT_SYMBOL(pci_save_state); EXPORT_SYMBOL(pci_save_state);
......
This diff is collapsed.
#ifndef __HDLC_IOCTL_H__
#define __HDLC_IOCTL_H__
typedef struct {
unsigned int clock_rate; /* bits per second */
unsigned int clock_type; /* internal, external, TX-internal etc. */
unsigned short loopback;
} sync_serial_settings; /* V.35, V.24, X.21 */
typedef struct {
unsigned int clock_rate; /* bits per second */
unsigned int clock_type; /* internal, external, TX-internal etc. */
unsigned short loopback;
unsigned int slot_map;
} te1_settings; /* T1, E1 */
typedef struct {
unsigned short encoding;
unsigned short parity;
} raw_hdlc_proto;
typedef struct {
unsigned int t391;
unsigned int t392;
unsigned int n391;
unsigned int n392;
unsigned int n393;
unsigned short lmi;
unsigned short dce; /* 1 for DCE (network side) operation */
} fr_proto;
typedef struct {
unsigned int dlci;
} fr_proto_pvc; /* for creating/deleting FR PVCs */
typedef struct {
unsigned int interval;
unsigned int timeout;
} cisco_proto;
/* PPP doesn't need any info now - supply length = 0 to ioctl */
union hdlc_settings {
raw_hdlc_proto raw_hdlc;
cisco_proto cisco;
fr_proto fr;
fr_proto_pvc fr_pvc;
};
union line_settings {
sync_serial_settings sync;
te1_settings te1;
};
#endif /* __HDLC_IOCTL_H__ */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment