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
File diff suppressed because it is too large Load Diff
+86
View File
@@ -0,0 +1,86 @@
#
# Makefile for the Linux network (wan) device drivers.
#
# 3 Aug 2000, Christoph Hellwig <hch@infradead.org>
# Rewritten to use lists instead of if-statements.
#
wanpipe-y := sdlamain.o sdla_ft1.o
wanpipe-$(CONFIG_WANPIPE_X25) += sdla_x25.o
wanpipe-$(CONFIG_WANPIPE_FR) += sdla_fr.o
wanpipe-$(CONFIG_WANPIPE_CHDLC) += sdla_chdlc.o
wanpipe-$(CONFIG_WANPIPE_PPP) += sdla_ppp.o
wanpipe-$(CONFIG_WANPIPE_MULTPPP) += wanpipe_multppp.o
wanpipe-objs := $(wanpipe-y)
cyclomx-y := cycx_main.o
cyclomx-$(CONFIG_CYCLOMX_X25) += cycx_x25.o
cyclomx-objs := $(cyclomx-y)
hdlc-y := hdlc_generic.o
hdlc-$(CONFIG_HDLC_RAW) += hdlc_raw.o
hdlc-$(CONFIG_HDLC_RAW_ETH) += hdlc_raw_eth.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
hdlc-objs := $(hdlc-y)
pc300-y := pc300_drv.o
pc300-$(CONFIG_PC300_MLPPP) += pc300_tty.o
pc300-objs := $(pc300-y)
obj-$(CONFIG_HOSTESS_SV11) += z85230.o syncppp.o hostess_sv11.o
obj-$(CONFIG_SEALEVEL_4021) += z85230.o syncppp.o sealevel.o
obj-$(CONFIG_COSA) += syncppp.o cosa.o
obj-$(CONFIG_FARSYNC) += syncppp.o farsync.o
obj-$(CONFIG_DSCC4) += dscc4.o
obj-$(CONFIG_LANMEDIA) += syncppp.o
obj-$(CONFIG_SYNCLINK_SYNCPPP) += syncppp.o
obj-$(CONFIG_X25_ASY) += x25_asy.o
obj-$(CONFIG_LANMEDIA) += lmc/
obj-$(CONFIG_DLCI) += dlci.o
obj-$(CONFIG_SDLA) += sdla.o
ifeq ($(CONFIG_WANPIPE_MULTPPP),y)
obj-$(CONFIG_VENDOR_SANGOMA) += sdladrv.o wanpipe.o syncppp.o
else
obj-$(CONFIG_VENDOR_SANGOMA) += sdladrv.o wanpipe.o
endif
obj-$(CONFIG_CYCLADES_SYNC) += cycx_drv.o cyclomx.o
obj-$(CONFIG_LAPBETHER) += lapbether.o
obj-$(CONFIG_SBNI) += sbni.o
obj-$(CONFIG_PC300) += pc300.o
obj-$(CONFIG_HDLC) += hdlc.o
ifeq ($(CONFIG_HDLC_PPP),y)
obj-$(CONFIG_HDLC) += syncppp.o
endif
obj-$(CONFIG_N2) += n2.o
obj-$(CONFIG_C101) += c101.o
obj-$(CONFIG_WANXL) += wanxl.o
obj-$(CONFIG_PCI200SYN) += pci200syn.o
clean-files := wanxlfw.inc
$(obj)/wanxl.o: $(obj)/wanxlfw.inc
ifeq ($(CONFIG_WANXL_BUILD_FIRMWARE),y)
ifeq ($(ARCH),m68k)
AS68K = $(AS)
LD68K = $(LD)
else
AS68K = as68k
LD68K = ld68k
endif
quiet_cmd_build_wanxlfw = BLD FW $@
cmd_build_wanxlfw = \
$(CPP) -Wp,-MD,$(depfile) -I$(srctree)/include $< | $(AS68K) -m68360 -o $(obj)/wanxlfw.o; \
$(LD68K) --oformat binary -Ttext 0x1000 $(obj)/wanxlfw.o -o $(obj)/wanxlfw.bin; \
hexdump -ve '"\n" 16/1 "0x%02X,"' $(obj)/wanxlfw.bin | sed 's/0x ,//g;1s/^/static u8 firmware[]={/;$$s/,$$/\n};\n/' >$(obj)/wanxlfw.inc; \
rm -f $(obj)/wanxlfw.bin $(obj)/wanxlfw.o
$(obj)/wanxlfw.inc: $(src)/wanxlfw.S
$(call if_changed_dep,build_wanxlfw)
targets += wanxlfw.inc
endif
+446
View File
@@ -0,0 +1,446 @@
/*
* Moxa C101 synchronous serial card driver for Linux
*
* Copyright (C) 2000-2003 Krzysztof Halasa <khc@pm.waw.pl>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License
* as published by the Free Software Foundation.
*
* For information see http://hq.pm.waw.pl/hdlc/
*
* Sources of information:
* Hitachi HD64570 SCA User's Manual
* Moxa C101 User's Manual
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/moduleparam.h>
#include <linux/netdevice.h>
#include <linux/hdlc.h>
#include <linux/delay.h>
#include <asm/io.h>
#include "hd64570.h"
static const char* version = "Moxa C101 driver version: 1.15";
static const char* devname = "C101";
#undef DEBUG_PKT
#define DEBUG_RINGS
#define C101_PAGE 0x1D00
#define C101_DTR 0x1E00
#define C101_SCA 0x1F00
#define C101_WINDOW_SIZE 0x2000
#define C101_MAPPED_RAM_SIZE 0x4000
#define RAM_SIZE (256 * 1024)
#define TX_RING_BUFFERS 10
#define RX_RING_BUFFERS ((RAM_SIZE - C101_WINDOW_SIZE) / \
(sizeof(pkt_desc) + HDLC_MAX_MRU) - TX_RING_BUFFERS)
#define CLOCK_BASE 9830400 /* 9.8304 MHz */
#define PAGE0_ALWAYS_MAPPED
static char *hw; /* pointer to hw=xxx command line string */
typedef struct card_s {
struct net_device *dev;
spinlock_t lock; /* TX lock */
u8 __iomem *win0base; /* ISA window base address */
u32 phy_winbase; /* ISA physical base address */
sync_serial_settings settings;
int rxpart; /* partial frame received, next frame invalid*/
unsigned short encoding;
unsigned short parity;
u16 rx_ring_buffers; /* number of buffers in a ring */
u16 tx_ring_buffers;
u16 buff_offset; /* offset of first buffer of first channel */
u16 rxin; /* rx ring buffer 'in' pointer */
u16 txin; /* tx ring buffer 'in' and 'last' pointers */
u16 txlast;
u8 rxs, txs, tmc; /* SCA registers */
u8 irq; /* IRQ (3-15) */
u8 page;
struct card_s *next_card;
}card_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_out(value, reg, card) writeb(value, (card)->win0base + C101_SCA + (reg))
#define sca_inw(reg, card) readw((card)->win0base + C101_SCA + (reg))
/* EDA address register must be set in EDAL, EDAH order - 8 bit ISA bus */
#define sca_outw(value, reg, card) do { \
writeb(value & 0xFF, (card)->win0base + C101_SCA + (reg)); \
writeb((value >> 8 ) & 0xFF, (card)->win0base + C101_SCA + (reg+1));\
} while(0)
#define port_to_card(port) (port)
#define log_node(port) (0)
#define phy_node(port) (0)
#define winsize(card) (C101_WINDOW_SIZE)
#define win0base(card) ((card)->win0base)
#define winbase(card) ((card)->win0base + 0x2000)
#define get_port(card, port) (card)
static void sca_msci_intr(port_t *port);
static inline u8 sca_get_page(card_t *card)
{
return card->page;
}
static inline void openwin(card_t *card, u8 page)
{
card->page = page;
writeb(page, card->win0base + C101_PAGE);
}
#include "hd6457x.c"
static void sca_msci_intr(port_t *port)
{
struct net_device *dev = port_to_dev(port);
card_t* card = port_to_card(port);
u8 stat = sca_in(MSCI1_OFFSET + ST1, card); /* read MSCI ST1 status */
/* Reset MSCI TX underrun status bit */
sca_out(stat & ST1_UDRN, MSCI0_OFFSET + ST1, card);
if (stat & ST1_UDRN) {
struct net_device_stats *stats = hdlc_stats(dev);
stats->tx_errors++; /* TX Underrun error detected */
stats->tx_fifo_errors++;
}
/* Reset MSCI CDCD status bit - uses ch#2 DCD input */
sca_out(stat & ST1_CDCD, MSCI1_OFFSET + ST1, card);
if (stat & ST1_CDCD)
hdlc_set_carrier(!(sca_in(MSCI1_OFFSET + ST3, card) & ST3_DCD),
dev);
}
static void c101_set_iface(port_t *port)
{
u8 rxs = port->rxs & CLK_BRG_MASK;
u8 txs = port->txs & CLK_BRG_MASK;
switch(port->settings.clock_type) {
case CLOCK_INT:
rxs |= CLK_BRG_RX; /* TX clock */
txs |= CLK_RXCLK_TX; /* BRG output */
break;
case CLOCK_TXINT:
rxs |= CLK_LINE_RX; /* RXC input */
txs |= CLK_BRG_TX; /* BRG output */
break;
case CLOCK_TXFROMRX:
rxs |= CLK_LINE_RX; /* RXC input */
txs |= CLK_RXCLK_TX; /* RX clock */
break;
default: /* EXTernal clock */
rxs |= CLK_LINE_RX; /* RXC input */
txs |= CLK_LINE_TX; /* TXC input */
}
port->rxs = rxs;
port->txs = txs;
sca_out(rxs, MSCI1_OFFSET + RXS, port);
sca_out(txs, MSCI1_OFFSET + TXS, port);
sca_set_port(port);
}
static int c101_open(struct net_device *dev)
{
port_t *port = dev_to_port(dev);
int result;
result = hdlc_open(dev);
if (result)
return result;
writeb(1, port->win0base + C101_DTR);
sca_out(0, MSCI1_OFFSET + CTL, port); /* RTS uses ch#2 output */
sca_open(dev);
/* DCD is connected to port 2 !@#$%^& - disable MSCI0 CDCD interrupt */
sca_out(IE1_UDRN, MSCI0_OFFSET + IE1, port);
sca_out(IE0_TXINT, MSCI0_OFFSET + IE0, port);
hdlc_set_carrier(!(sca_in(MSCI1_OFFSET + ST3, port) & ST3_DCD), dev);
printk(KERN_DEBUG "0x%X\n", sca_in(MSCI1_OFFSET + ST3, port));
/* enable MSCI1 CDCD interrupt */
sca_out(IE1_CDCD, MSCI1_OFFSET + IE1, port);
sca_out(IE0_RXINTA, MSCI1_OFFSET + IE0, port);
sca_out(0x48, IER0, port); /* TXINT #0 and RXINT #1 */
c101_set_iface(port);
return 0;
}
static int c101_close(struct net_device *dev)
{
port_t *port = dev_to_port(dev);
sca_close(dev);
writeb(0, port->win0base + C101_DTR);
sca_out(CTL_NORTS, MSCI1_OFFSET + CTL, port);
hdlc_close(dev);
return 0;
}
static int c101_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
const size_t size = sizeof(sync_serial_settings);
sync_serial_settings new_line;
sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync;
port_t *port = dev_to_port(dev);
#ifdef DEBUG_RINGS
if (cmd == SIOCDEVPRIVATE) {
sca_dump_rings(dev);
printk(KERN_DEBUG "MSCI1: ST: %02x %02x %02x %02x\n",
sca_in(MSCI1_OFFSET + ST0, port),
sca_in(MSCI1_OFFSET + ST1, port),
sca_in(MSCI1_OFFSET + ST2, port),
sca_in(MSCI1_OFFSET + ST3, port));
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 (ifr->ifr_settings.size < size) {
ifr->ifr_settings.size = size; /* data size wanted */
return -ENOBUFS;
}
if (copy_to_user(line, &port->settings, size))
return -EFAULT;
return 0;
case IF_IFACE_SYNC_SERIAL:
if(!capable(CAP_NET_ADMIN))
return -EPERM;
if (copy_from_user(&new_line, line, size))
return -EFAULT;
if (new_line.clock_type != CLOCK_EXT &&
new_line.clock_type != CLOCK_TXFROMRX &&
new_line.clock_type != CLOCK_INT &&
new_line.clock_type != CLOCK_TXINT)
return -EINVAL; /* No such clock setting */
if (new_line.loopback != 0 && new_line.loopback != 1)
return -EINVAL;
memcpy(&port->settings, &new_line, size); /* Update settings */
c101_set_iface(port);
return 0;
default:
return hdlc_ioctl(dev, ifr, cmd);
}
}
static void c101_destroy_card(card_t *card)
{
readb(card->win0base + C101_PAGE); /* Resets SCA? */
if (card->irq)
free_irq(card->irq, card);
if (card->win0base) {
iounmap(card->win0base);
release_mem_region(card->phy_winbase, C101_MAPPED_RAM_SIZE);
}
free_netdev(card->dev);
kfree(card);
}
static int __init c101_run(unsigned long irq, unsigned long winbase)
{
struct net_device *dev;
hdlc_device *hdlc;
card_t *card;
int result;
if (irq<3 || irq>15 || irq == 6) /* FIXME */ {
printk(KERN_ERR "c101: invalid IRQ value\n");
return -ENODEV;
}
if (winbase < 0xC0000 || winbase > 0xDFFFF || (winbase & 0x3FFF) !=0) {
printk(KERN_ERR "c101: invalid RAM value\n");
return -ENODEV;
}
card = kmalloc(sizeof(card_t), GFP_KERNEL);
if (card == NULL) {
printk(KERN_ERR "c101: unable to allocate memory\n");
return -ENOBUFS;
}
memset(card, 0, sizeof(card_t));
card->dev = alloc_hdlcdev(card);
if (!card->dev) {
printk(KERN_ERR "c101: unable to allocate memory\n");
kfree(card);
return -ENOBUFS;
}
if (request_irq(irq, sca_intr, 0, devname, card)) {
printk(KERN_ERR "c101: could not allocate IRQ\n");
c101_destroy_card(card);
return(-EBUSY);
}
card->irq = irq;
if (!request_mem_region(winbase, C101_MAPPED_RAM_SIZE, devname)) {
printk(KERN_ERR "c101: could not request RAM window\n");
c101_destroy_card(card);
return(-EBUSY);
}
card->phy_winbase = winbase;
card->win0base = ioremap(winbase, C101_MAPPED_RAM_SIZE);
if (!card->win0base) {
printk(KERN_ERR "c101: could not map I/O address\n");
c101_destroy_card(card);
return -EBUSY;
}
card->tx_ring_buffers = TX_RING_BUFFERS;
card->rx_ring_buffers = RX_RING_BUFFERS;
card->buff_offset = C101_WINDOW_SIZE; /* Bytes 1D00-1FFF reserved */
readb(card->win0base + C101_PAGE); /* Resets SCA? */
udelay(100);
writeb(0, card->win0base + C101_PAGE);
writeb(0, card->win0base + C101_DTR); /* Power-up for RAM? */
sca_init(card, 0);
dev = port_to_dev(card);
hdlc = dev_to_hdlc(dev);
spin_lock_init(&card->lock);
SET_MODULE_OWNER(dev);
dev->irq = irq;
dev->mem_start = winbase;
dev->mem_end = winbase + C101_MAPPED_RAM_SIZE - 1;
dev->tx_queue_len = 50;
dev->do_ioctl = c101_ioctl;
dev->open = c101_open;
dev->stop = c101_close;
hdlc->attach = sca_attach;
hdlc->xmit = sca_xmit;
card->settings.clock_type = CLOCK_EXT;
result = register_hdlc_device(dev);
if (result) {
printk(KERN_WARNING "c101: unable to register hdlc device\n");
c101_destroy_card(card);
return result;
}
sca_init_sync_port(card); /* Set up C101 memory */
hdlc_set_carrier(!(sca_in(MSCI1_OFFSET + ST3, card) & ST3_DCD), dev);
printk(KERN_INFO "%s: Moxa C101 on IRQ%u,"
" using %u TX + %u RX packets rings\n",
dev->name, card->irq,
card->tx_ring_buffers, card->rx_ring_buffers);
*new_card = card;
new_card = &card->next_card;
return 0;
}
static int __init c101_init(void)
{
if (hw == NULL) {
#ifdef MODULE
printk(KERN_INFO "c101: no card initialized\n");
#endif
return -ENOSYS; /* no parameters specified, abort */
}
printk(KERN_INFO "%s\n", version);
do {
unsigned long irq, ram;
irq = simple_strtoul(hw, &hw, 0);
if (*hw++ != ',')
break;
ram = simple_strtoul(hw, &hw, 0);
if (*hw == ':' || *hw == '\x0')
c101_run(irq, ram);
if (*hw == '\x0')
return first_card ? 0 : -ENOSYS;
}while(*hw++ == ':');
printk(KERN_ERR "c101: invalid hardware parameters\n");
return first_card ? 0 : -ENOSYS;
}
static void __exit c101_cleanup(void)
{
card_t *card = first_card;
while (card) {
card_t *ptr = card;
card = card->next_card;
unregister_hdlc_device(port_to_dev(ptr));
c101_destroy_card(ptr);
}
}
module_init(c101_init);
module_exit(c101_cleanup);
MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
MODULE_DESCRIPTION("Moxa C101 serial port driver");
MODULE_LICENSE("GPL v2");
module_param(hw, charp, 0444); /* hw=irq,ram:irq,... */
File diff suppressed because it is too large Load Diff
+117
View File
@@ -0,0 +1,117 @@
/* $Id: cosa.h,v 1.6 1999/01/06 14:02:44 kas Exp $ */
/*
* Copyright (C) 1995-1997 Jan "Yenya" Kasprzak <kas@fi.muni.cz>
*
* 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.
*/
#ifndef COSA_H__
#define COSA_H__
#include <linux/ioctl.h>
#ifdef __KERNEL__
/* status register - output bits */
#define SR_RX_DMA_ENA 0x04 /* receiver DMA enable bit */
#define SR_TX_DMA_ENA 0x08 /* transmitter DMA enable bit */
#define SR_RST 0x10 /* SRP reset */
#define SR_USR_INT_ENA 0x20 /* user interrupt enable bit */
#define SR_TX_INT_ENA 0x40 /* transmitter interrupt enable bit */
#define SR_RX_INT_ENA 0x80 /* receiver interrupt enable bit */
/* status register - input bits */
#define SR_USR_RQ 0x20 /* user interrupt request pending */
#define SR_TX_RDY 0x40 /* transmitter empty (ready) */
#define SR_RX_RDY 0x80 /* receiver data ready */
#define SR_UP_REQUEST 0x02 /* request from SRP to transfer data
up to PC */
#define SR_DOWN_REQUEST 0x01 /* SRP is able to transfer data down
from PC to SRP */
#define SR_END_OF_TRANSFER 0x03 /* SRP signalize end of
transfer (up or down) */
#define SR_CMD_FROM_SRP_MASK 0x03 /* mask to get SRP command */
/* bits in driver status byte definitions : */
#define SR_RDY_RCV 0x01 /* ready to receive packet */
#define SR_RDY_SND 0x02 /* ready to send packet */
#define SR_CMD_PND 0x04 /* command pending */ /* not currently used */
/* ???? */
#define SR_PKT_UP 0x01 /* transfer of packet up in progress */
#define SR_PKT_DOWN 0x02 /* transfer of packet down in progress */
#endif /* __KERNEL__ */
#define SR_LOAD_ADDR 0x4400 /* SRP microcode load address */
#define SR_START_ADDR 0x4400 /* SRP microcode start address */
#define COSA_LOAD_ADDR 0x400 /* SRP microcode load address */
#define COSA_MAX_FIRMWARE_SIZE 0x10000
/* ioctls */
struct cosa_download {
int addr, len;
char __user *code;
};
/* Reset the device */
#define COSAIORSET _IO('C',0xf0)
/* Start microcode at given address */
#define COSAIOSTRT _IOW('C',0xf1, int)
/* Read the block from the device memory */
#define COSAIORMEM _IOWR('C',0xf2, struct cosa_download *)
/* actually the struct cosa_download itself; this is to keep
* the ioctl number same as in 2.4 in order to keep the user-space
* utils compatible. */
/* Write the block to the device memory (i.e. download the microcode) */
#define COSAIODOWNLD _IOW('C',0xf2, struct cosa_download *)
/* actually the struct cosa_download itself; this is to keep
* the ioctl number same as in 2.4 in order to keep the user-space
* utils compatible. */
/* Read the device type (one of "srp", "cosa", and "cosa8" for now) */
#define COSAIORTYPE _IOR('C',0xf3, char *)
/* Read the device identification string */
#define COSAIORIDSTR _IOR('C',0xf4, char *)
/* Maximum length of the identification string. */
#define COSA_MAX_ID_STRING 128
/* Increment/decrement the module usage count :-) */
/* #define COSAIOMINC _IO('C',0xf5) */
/* #define COSAIOMDEC _IO('C',0xf6) */
/* Get the total number of cards installed */
#define COSAIONRCARDS _IO('C',0xf7)
/* Get the number of channels on this card */
#define COSAIONRCHANS _IO('C',0xf8)
/* Set the driver for the bus-master operations */
#define COSAIOBMSET _IOW('C', 0xf9, unsigned short)
#define COSA_BM_OFF 0 /* Bus-mastering off - use ISA DMA (default) */
#define COSA_BM_ON 1 /* Bus-mastering on - faster but untested */
/* Gets the busmaster status */
#define COSAIOBMGET _IO('C', 0xfa)
#endif /* !COSA_H__ */
File diff suppressed because it is too large Load Diff
+351
View File
@@ -0,0 +1,351 @@
/*
* cycx_main.c Cyclades Cyclom 2X WAN Link Driver. Main module.
*
* Author: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*
* Copyright: (c) 1998-2003 Arnaldo Carvalho de Melo
*
* Based on sdlamain.c by Gene Kozin <genek@compuserve.com> &
* Jaspreet Singh <jaspreet@sangoma.com>
*
* 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.
* ============================================================================
* Please look at the bitkeeper changelog (or any other scm tool that ends up
* importing bitkeeper changelog or that replaces bitkeeper in the future as
* main tool for linux development).
*
* 2001/05/09 acme Fix MODULE_DESC for debug, .bss nitpicks,
* some cleanups
* 2000/07/13 acme remove useless #ifdef MODULE and crap
* #if KERNEL_VERSION > blah
* 2000/07/06 acme __exit at cyclomx_cleanup
* 2000/04/02 acme dprintk and cycx_debug
* module_init/module_exit
* 2000/01/21 acme rename cyclomx_open to cyclomx_mod_inc_use_count
* and cyclomx_close to cyclomx_mod_dec_use_count
* 2000/01/08 acme cleanup
* 1999/11/06 acme cycx_down back to life (it needs to be
* called to iounmap the dpmbase)
* 1999/08/09 acme removed references to enable_tx_int
* use spinlocks instead of cli/sti in
* cyclomx_set_state
* 1999/05/19 acme works directly linked into the kernel
* init_waitqueue_head for 2.3.* kernel
* 1999/05/18 acme major cleanup (polling not needed), etc
* 1998/08/28 acme minor cleanup (ioctls for firmware deleted)
* queue_task activated
* 1998/08/08 acme Initial version.
*/
#include <linux/config.h> /* OS configuration options */
#include <linux/stddef.h> /* offsetof(), etc. */
#include <linux/errno.h> /* return codes */
#include <linux/string.h> /* inline memset(), etc. */
#include <linux/slab.h> /* kmalloc(), kfree() */
#include <linux/kernel.h> /* printk(), and other useful stuff */
#include <linux/module.h> /* support for loadable modules */
#include <linux/ioport.h> /* request_region(), release_region() */
#include <linux/wanrouter.h> /* WAN router definitions */
#include <linux/cyclomx.h> /* cyclomx common user API definitions */
#include <linux/init.h> /* __init (when not using as a module) */
unsigned int cycx_debug;
MODULE_AUTHOR("Arnaldo Carvalho de Melo");
MODULE_DESCRIPTION("Cyclom 2X Sync Card Driver.");
MODULE_LICENSE("GPL");
module_param(cycx_debug, int, 0);
MODULE_PARM_DESC(cycx_debug, "cyclomx debug level");
/* Defines & Macros */
#define CYCX_DRV_VERSION 0 /* version number */
#define CYCX_DRV_RELEASE 11 /* release (minor version) number */
#define CYCX_MAX_CARDS 1 /* max number of adapters */
#define CONFIG_CYCX_CARDS 1
/* Function Prototypes */
/* WAN link driver entry points */
static int cycx_wan_setup(struct wan_device *wandev, wandev_conf_t *conf);
static int cycx_wan_shutdown(struct wan_device *wandev);
/* Miscellaneous functions */
static irqreturn_t cycx_isr(int irq, void *dev_id, struct pt_regs *regs);
/* Global Data
* Note: All data must be explicitly initialized!!!
*/
/* private data */
static char cycx_drvname[] = "cyclomx";
static char cycx_fullname[] = "CYCLOM 2X(tm) Sync Card Driver";
static char cycx_copyright[] = "(c) 1998-2003 Arnaldo Carvalho de Melo "
"<acme@conectiva.com.br>";
static int cycx_ncards = CONFIG_CYCX_CARDS;
static struct cycx_device *cycx_card_array; /* adapter data space */
/* Kernel Loadable Module Entry Points */
/*
* Module 'insert' entry point.
* o print announcement
* o allocate adapter data space
* o initialize static data
* o register all cards with WAN router
* o calibrate Cyclom 2X shared memory access delay.
*
* Return: 0 Ok
* < 0 error.
* Context: process
*/
int __init cycx_init(void)
{
int cnt, err = -ENOMEM;
printk(KERN_INFO "%s v%u.%u %s\n",
cycx_fullname, CYCX_DRV_VERSION, CYCX_DRV_RELEASE,
cycx_copyright);
/* Verify number of cards and allocate adapter data space */
cycx_ncards = min_t(int, cycx_ncards, CYCX_MAX_CARDS);
cycx_ncards = max_t(int, cycx_ncards, 1);
cycx_card_array = kmalloc(sizeof(struct cycx_device) * cycx_ncards,
GFP_KERNEL);
if (!cycx_card_array)
goto out;
memset(cycx_card_array, 0, sizeof(struct cycx_device) * cycx_ncards);
/* Register adapters with WAN router */
for (cnt = 0; cnt < cycx_ncards; ++cnt) {
struct cycx_device *card = &cycx_card_array[cnt];
struct wan_device *wandev = &card->wandev;
sprintf(card->devname, "%s%d", cycx_drvname, cnt + 1);
wandev->magic = ROUTER_MAGIC;
wandev->name = card->devname;
wandev->private = card;
wandev->setup = cycx_wan_setup;
wandev->shutdown = cycx_wan_shutdown;
err = register_wan_device(wandev);
if (err) {
printk(KERN_ERR "%s: %s registration failed with "
"error %d!\n",
cycx_drvname, card->devname, err);
break;
}
}
err = -ENODEV;
if (!cnt) {
kfree(cycx_card_array);
goto out;
}
err = 0;
cycx_ncards = cnt; /* adjust actual number of cards */
out: return err;
}
/*
* Module 'remove' entry point.
* o unregister all adapters from the WAN router
* o release all remaining system resources
*/
static void __exit cycx_exit(void)
{
int i = 0;
for (; i < cycx_ncards; ++i) {
struct cycx_device *card = &cycx_card_array[i];
unregister_wan_device(card->devname);
}
kfree(cycx_card_array);
}
/* WAN Device Driver Entry Points */
/*
* Setup/configure WAN link driver.
* o check adapter state
* o make sure firmware is present in configuration
* o allocate interrupt vector
* o setup Cyclom 2X hardware
* o call appropriate routine to perform protocol-specific initialization
*
* This function is called when router handles ROUTER_SETUP IOCTL. The
* configuration structure is in kernel memory (including extended data, if
* any).
*/
static int cycx_wan_setup(struct wan_device *wandev, wandev_conf_t *conf)
{
int rc = -EFAULT;
struct cycx_device *card;
int irq;
/* Sanity checks */
if (!wandev || !wandev->private || !conf)
goto out;
card = wandev->private;
rc = -EBUSY;
if (wandev->state != WAN_UNCONFIGURED)
goto out;
rc = -EINVAL;
if (!conf->data_size || !conf->data) {
printk(KERN_ERR "%s: firmware not found in configuration "
"data!\n", wandev->name);
goto out;
}
if (conf->irq <= 0) {
printk(KERN_ERR "%s: can't configure without IRQ!\n",
wandev->name);
goto out;
}
/* Allocate IRQ */
irq = conf->irq == 2 ? 9 : conf->irq; /* IRQ2 -> IRQ9 */
if (request_irq(irq, cycx_isr, 0, wandev->name, card)) {
printk(KERN_ERR "%s: can't reserve IRQ %d!\n",
wandev->name, irq);
goto out;
}
/* Configure hardware, load firmware, etc. */
memset(&card->hw, 0, sizeof(card->hw));
card->hw.irq = irq;
card->hw.dpmsize = CYCX_WINDOWSIZE;
card->hw.fwid = CFID_X25_2X;
spin_lock_init(&card->lock);
init_waitqueue_head(&card->wait_stats);
rc = cycx_setup(&card->hw, conf->data, conf->data_size, conf->maddr);
if (rc)
goto out_irq;
/* Initialize WAN device data space */
wandev->irq = irq;
wandev->dma = wandev->ioport = 0;
wandev->maddr = (unsigned long)card->hw.dpmbase;
wandev->msize = card->hw.dpmsize;
wandev->hw_opt[2] = 0;
wandev->hw_opt[3] = card->hw.fwid;
/* Protocol-specific initialization */
switch (card->hw.fwid) {
#ifdef CONFIG_CYCLOMX_X25
case CFID_X25_2X:
rc = cycx_x25_wan_init(card, conf);
break;
#endif
default:
printk(KERN_ERR "%s: this firmware is not supported!\n",
wandev->name);
rc = -EINVAL;
}
if (rc) {
cycx_down(&card->hw);
goto out_irq;
}
rc = 0;
out:
return rc;
out_irq:
free_irq(irq, card);
goto out;
}
/*
* Shut down WAN link driver.
* o shut down adapter hardware
* o release system resources.
*
* This function is called by the router when device is being unregistered or
* when it handles ROUTER_DOWN IOCTL.
*/
static int cycx_wan_shutdown(struct wan_device *wandev)
{
int ret = -EFAULT;
struct cycx_device *card;
/* sanity checks */
if (!wandev || !wandev->private)
goto out;
ret = 0;
if (wandev->state == WAN_UNCONFIGURED)
goto out;
card = wandev->private;
wandev->state = WAN_UNCONFIGURED;
cycx_down(&card->hw);
printk(KERN_INFO "%s: irq %d being freed!\n", wandev->name,
wandev->irq);
free_irq(wandev->irq, card);
out: return ret;
}
/* Miscellaneous */
/*
* Cyclom 2X Interrupt Service Routine.
* o acknowledge Cyclom 2X hardware interrupt.
* o call protocol-specific interrupt service routine, if any.
*/
static irqreturn_t cycx_isr(int irq, void *dev_id, struct pt_regs *regs)
{
struct cycx_device *card = (struct cycx_device *)dev_id;
if (!card || card->wandev.state == WAN_UNCONFIGURED)
goto out;
if (card->in_isr) {
printk(KERN_WARNING "%s: interrupt re-entrancy on IRQ %d!\n",
card->devname, card->wandev.irq);
goto out;
}
if (card->isr)
card->isr(card);
return IRQ_HANDLED;
out:
return IRQ_NONE;
}
/* Set WAN device state. */
void cycx_set_state(struct cycx_device *card, int state)
{
unsigned long flags;
char *string_state = NULL;
spin_lock_irqsave(&card->lock, flags);
if (card->wandev.state != state) {
switch (state) {
case WAN_CONNECTED:
string_state = "connected!";
break;
case WAN_DISCONNECTED:
string_state = "disconnected!";
break;
}
printk(KERN_INFO "%s: link %s\n", card->devname, string_state);
card->wandev.state = state;
}
card->state_tick = jiffies;
spin_unlock_irqrestore(&card->lock, flags);
}
module_init(cycx_init);
module_exit(cycx_exit);
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+357
View File
@@ -0,0 +1,357 @@
/*
* FarSync X21 driver for Linux
*
* Actually sync driver for X.21, V.35 and V.24 on FarSync T-series cards
*
* Copyright (C) 2001 FarSite Communications Ltd.
* www.farsite.co.uk
*
* 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.
*
* Author: R.J.Dunlop <bob.dunlop@farsite.co.uk>
*
* For the most part this file only contains structures and information
* that is visible to applications outside the driver. Shared memory
* layout etc is internal to the driver and described within farsync.c.
* Overlap exists in that the values used for some fields within the
* ioctl interface extend into the cards firmware interface so values in
* this file may not be changed arbitrarily.
*/
/* What's in a name
*
* The project name for this driver is Oscar. The driver is intended to be
* used with the FarSite T-Series cards (T2P & T4P) running in the high
* speed frame shifter mode. This is sometimes referred to as X.21 mode
* which is a complete misnomer as the card continues to support V.24 and
* V.35 as well as X.21.
*
* 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
* 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_NDEV_NAME "sync" /* For net interface */
#define FST_DEV_NAME "farsync" /* For misc interfaces */
/* User version number
*
* This version number is incremented with each official release of the
* package and is a simplified number for normal user reference.
* Individual files are tracked by the version control system and may
* have individual versions (or IDs) that move much faster than the
* the release version as individual updates are tracked.
*/
#define FST_USER_VERSION "1.04"
/* Ioctl call command values
*
* The first three private ioctls are used by the sync-PPP module,
* allowing a little room for expansion we start our numbering at 10.
*/
#define FSTWRITE (SIOCDEVPRIVATE+10)
#define FSTCPURESET (SIOCDEVPRIVATE+11)
#define FSTCPURELEASE (SIOCDEVPRIVATE+12)
#define FSTGETCONF (SIOCDEVPRIVATE+13)
#define FSTSETCONF (SIOCDEVPRIVATE+14)
/* FSTWRITE
*
* Used to write a block of data (firmware etc) before the card is running
*/
struct fstioc_write {
unsigned int size;
unsigned int offset;
unsigned char data[0];
};
/* FSTCPURESET and FSTCPURELEASE
*
* These take no additional data.
* FSTCPURESET forces the cards CPU into a reset state and holds it there.
* FSTCPURELEASE releases the CPU from this reset state allowing it to run,
* the reset vector should be setup before this ioctl is run.
*/
/* FSTGETCONF and FSTSETCONF
*
* Get and set a card/ports configuration.
* In order to allow selective setting of items and for the kernel to
* indicate a partial status response the first field "valid" is a bitmask
* indicating which other fields in the structure are valid.
* Many of the field names in this structure match those used in the
* firmware shared memory configuration interface and come originally from
* the NT header file Smc.h
*
* When used with FSTGETCONF this structure should be zeroed before use.
* This is to allow for possible future expansion when some of the fields
* might be used to indicate a different (expanded) structure.
*/
struct fstioc_info {
unsigned int valid; /* Bits of structure that are valid */
unsigned int nports; /* Number of serial ports */
unsigned int type; /* Type index of card */
unsigned int state; /* State of card */
unsigned int index; /* Index of port ioctl was issued on */
unsigned int smcFirmwareVersion;
unsigned long kernelVersion; /* What Kernel version we are working with */
unsigned short lineInterface; /* Physical interface type */
unsigned char proto; /* Line protocol */
unsigned char internalClock; /* 1 => internal clock, 0 => external */
unsigned int lineSpeed; /* Speed in bps */
unsigned int v24IpSts; /* V.24 control input status */
unsigned int v24OpSts; /* V.24 control output status */
unsigned short clockStatus; /* lsb: 0=> present, 1=> absent */
unsigned short cableStatus; /* lsb: 0=> present, 1=> absent */
unsigned short cardMode; /* lsb: LED id mode */
unsigned short debug; /* Debug flags */
unsigned char transparentMode; /* Not used always 0 */
unsigned char invertClock; /* Invert clock feature for syncing */
unsigned char startingSlot; /* Time slot to use for start of tx */
unsigned char clockSource; /* External or internal */
unsigned char framing; /* E1, T1 or J1 */
unsigned char structure; /* unframed, double, crc4, f4, f12, */
/* f24 f72 */
unsigned char interface; /* rj48c or bnc */
unsigned char coding; /* hdb3 b8zs */
unsigned char lineBuildOut; /* 0, -7.5, -15, -22 */
unsigned char equalizer; /* short or lon haul settings */
unsigned char loopMode; /* various loopbacks */
unsigned char range; /* cable lengths */
unsigned char txBufferMode; /* tx elastic buffer depth */
unsigned char rxBufferMode; /* rx elastic buffer depth */
unsigned char losThreshold; /* Attenuation on LOS signal */
unsigned char idleCode; /* Value to send as idle timeslot */
unsigned int receiveBufferDelay; /* delay thro rx buffer timeslots */
unsigned int framingErrorCount; /* framing errors */
unsigned int codeViolationCount; /* code violations */
unsigned int crcErrorCount; /* CRC errors */
int lineAttenuation; /* in dB*/
unsigned short lossOfSignal;
unsigned short receiveRemoteAlarm;
unsigned short alarmIndicationSignal;
};
/* "valid" bitmask */
#define FSTVAL_NONE 0x00000000 /* Nothing valid (firmware not running).
* Slight misnomer. In fact nports,
* type, state and index will be set
* based on hardware detected.
*/
#define FSTVAL_OMODEM 0x0000001F /* First 5 bits correspond to the
* output status bits defined for
* v24OpSts
*/
#define FSTVAL_SPEED 0x00000020 /* internalClock, lineSpeed, clockStatus
*/
#define FSTVAL_CABLE 0x00000040 /* lineInterface, cableStatus */
#define FSTVAL_IMODEM 0x00000080 /* v24IpSts */
#define FSTVAL_CARD 0x00000100 /* nports, type, state, index,
* smcFirmwareVersion
*/
#define FSTVAL_PROTO 0x00000200 /* proto */
#define FSTVAL_MODE 0x00000400 /* cardMode */
#define FSTVAL_PHASE 0x00000800 /* Clock phase */
#define FSTVAL_TE1 0x00001000 /* T1E1 Configuration */
#define FSTVAL_DEBUG 0x80000000 /* debug */
#define FSTVAL_ALL 0x00001FFF /* Note: does not include DEBUG flag */
/* "type" */
#define FST_TYPE_NONE 0 /* Probably should never happen */
#define FST_TYPE_T2P 1 /* T2P X21 2 port card */
#define FST_TYPE_T4P 2 /* T4P X21 4 port card */
#define FST_TYPE_T1U 3 /* T1U X21 1 port card */
#define FST_TYPE_T2U 4 /* T2U X21 2 port card */
#define FST_TYPE_T4U 5 /* T4U X21 4 port card */
#define FST_TYPE_TE1 6 /* T1E1 X21 1 port card */
/* "family" */
#define FST_FAMILY_TXP 0 /* T2P or T4P */
#define FST_FAMILY_TXU 1 /* T1U or T2U or T4U */
/* "state" */
#define FST_UNINIT 0 /* Raw uninitialised state following
* system startup */
#define FST_RESET 1 /* Processor held in reset state */
#define FST_DOWNLOAD 2 /* Card being downloaded */
#define FST_STARTING 3 /* Released following download */
#define FST_RUNNING 4 /* Processor running */
#define FST_BADVERSION 5 /* Bad shared memory version detected */
#define FST_HALTED 6 /* Processor flagged a halt */
#define FST_IFAILED 7 /* Firmware issued initialisation failed
* interrupt
*/
/* "lineInterface" */
#define V24 1
#define X21 2
#define V35 3
#define X21D 4
#define T1 5
#define E1 6
#define J1 7
/* "proto" */
#define FST_HDLC 1 /* Cisco compatible HDLC */
#define FST_PPP 2 /* Sync PPP */
#define FST_MONITOR 3 /* Monitor only (raw packet reception) */
#define FST_RAW 4 /* Two way raw packets */
#define FST_GEN_HDLC 5 /* Using "Generic HDLC" module */
/* "internalClock" */
#define INTCLK 1
#define EXTCLK 0
/* "v24IpSts" bitmask */
#define IPSTS_CTS 0x00000001 /* Clear To Send (Indicate for X.21) */
#define IPSTS_INDICATE IPSTS_CTS
#define IPSTS_DSR 0x00000002 /* Data Set Ready (T2P Port A) */
#define IPSTS_DCD 0x00000004 /* Data Carrier Detect */
#define IPSTS_RI 0x00000008 /* Ring Indicator (T2P Port A) */
#define IPSTS_TMI 0x00000010 /* Test Mode Indicator (Not Supported)*/
/* "v24OpSts" bitmask */
#define OPSTS_RTS 0x00000001 /* Request To Send (Control for X.21) */
#define OPSTS_CONTROL OPSTS_RTS
#define OPSTS_DTR 0x00000002 /* Data Terminal Ready */
#define OPSTS_DSRS 0x00000004 /* Data Signalling Rate Select (Not
* Supported) */
#define OPSTS_SS 0x00000008 /* Select Standby (Not Supported) */
#define OPSTS_LL 0x00000010 /* Maintenance Test (Not Supported) */
/* "cardMode" bitmask */
#define CARD_MODE_IDENTIFY 0x0001
/*
* Constants for T1/E1 configuration
*/
/*
* Clock source
*/
#define CLOCKING_SLAVE 0
#define CLOCKING_MASTER 1
/*
* Framing
*/
#define FRAMING_E1 0
#define FRAMING_J1 1
#define FRAMING_T1 2
/*
* Structure
*/
#define STRUCTURE_UNFRAMED 0
#define STRUCTURE_E1_DOUBLE 1
#define STRUCTURE_E1_CRC4 2
#define STRUCTURE_E1_CRC4M 3
#define STRUCTURE_T1_4 4
#define STRUCTURE_T1_12 5
#define STRUCTURE_T1_24 6
#define STRUCTURE_T1_72 7
/*
* Interface
*/
#define INTERFACE_RJ48C 0
#define INTERFACE_BNC 1
/*
* Coding
*/
#define CODING_HDB3 0
#define CODING_NRZ 1
#define CODING_CMI 2
#define CODING_CMI_HDB3 3
#define CODING_CMI_B8ZS 4
#define CODING_AMI 5
#define CODING_AMI_ZCS 6
#define CODING_B8ZS 7
/*
* Line Build Out
*/
#define LBO_0dB 0
#define LBO_7dB5 1
#define LBO_15dB 2
#define LBO_22dB5 3
/*
* Range for long haul t1 > 655ft
*/
#define RANGE_0_133_FT 0
#define RANGE_0_40_M RANGE_0_133_FT
#define RANGE_133_266_FT 1
#define RANGE_40_81_M RANGE_133_266_FT
#define RANGE_266_399_FT 2
#define RANGE_81_122_M RANGE_266_399_FT
#define RANGE_399_533_FT 3
#define RANGE_122_162_M RANGE_399_533_FT
#define RANGE_533_655_FT 4
#define RANGE_162_200_M RANGE_533_655_FT
/*
* Receive Equaliser
*/
#define EQUALIZER_SHORT 0
#define EQUALIZER_LONG 1
/*
* Loop modes
*/
#define LOOP_NONE 0
#define LOOP_LOCAL 1
#define LOOP_PAYLOAD_EXC_TS0 2
#define LOOP_PAYLOAD_INC_TS0 3
#define LOOP_REMOTE 4
/*
* Buffer modes
*/
#define BUFFER_2_FRAME 0
#define BUFFER_1_FRAME 1
#define BUFFER_96_BIT 2
#define BUFFER_NONE 3
/* Debug support
*
* These should only be enabled for development kernels, production code
* should define FST_DEBUG=0 in order to exclude the code.
* Setting FST_DEBUG=1 will include all the debug code but in a disabled
* state, use the FSTSETCONF ioctl to enable specific debug actions, or
* FST_DEBUG can be set to prime the debug selection.
*/
#define FST_DEBUG 0x0000
#if FST_DEBUG
extern int fst_debug_mask; /* Bit mask of actions to debug, bits
* listed below. Note: Bit 0 is used
* to trigger the inclusion of this
* code, without enabling any actions.
*/
#define DBG_INIT 0x0002 /* Card detection and initialisation */
#define DBG_OPEN 0x0004 /* Open and close sequences */
#define DBG_PCI 0x0008 /* PCI config operations */
#define DBG_IOCTL 0x0010 /* Ioctls and other config */
#define DBG_INTR 0x0020 /* Interrupt routines (be careful) */
#define DBG_TX 0x0040 /* Packet transmission */
#define DBG_RX 0x0080 /* Packet reception */
#define DBG_CMD 0x0100 /* Port command issuing */
#define DBG_ASS 0xFFFF /* Assert like statements. Code that
* should never be reached, if you see
* one of these then I've been an ass
*/
#endif /* FST_DEBUG */
+241
View File
@@ -0,0 +1,241 @@
#ifndef __HD64570_H
#define __HD64570_H
/* SCA HD64570 register definitions - all addresses for mode 0 (8086 MPU)
and 1 (64180 MPU). For modes 2 and 3, XOR the address with 0x01.
Source: HD64570 SCA User's Manual
*/
/* SCA Control Registers */
#define LPR 0x00 /* Low Power */
/* Wait controller registers */
#define PABR0 0x02 /* Physical Address Boundary 0 */
#define PABR1 0x03 /* Physical Address Boundary 1 */
#define WCRL 0x04 /* Wait Control L */
#define WCRM 0x05 /* Wait Control M */
#define WCRH 0x06 /* Wait Control H */
#define PCR 0x08 /* DMA Priority Control */
#define DMER 0x09 /* DMA Master Enable */
/* Interrupt registers */
#define ISR0 0x10 /* Interrupt Status 0 */
#define ISR1 0x11 /* Interrupt Status 1 */
#define ISR2 0x12 /* Interrupt Status 2 */
#define IER0 0x14 /* Interrupt Enable 0 */
#define IER1 0x15 /* Interrupt Enable 1 */
#define IER2 0x16 /* Interrupt Enable 2 */
#define ITCR 0x18 /* Interrupt Control */
#define IVR 0x1A /* Interrupt Vector */
#define IMVR 0x1C /* Interrupt Modified Vector */
/* MSCI channel (port) 0 registers - offset 0x20
MSCI channel (port) 1 registers - offset 0x40 */
#define MSCI0_OFFSET 0x20
#define MSCI1_OFFSET 0x40
#define TRBL 0x00 /* TX/RX buffer L */
#define TRBH 0x01 /* TX/RX buffer H */
#define ST0 0x02 /* Status 0 */
#define ST1 0x03 /* Status 1 */
#define ST2 0x04 /* Status 2 */
#define ST3 0x05 /* Status 3 */
#define FST 0x06 /* Frame Status */
#define IE0 0x08 /* Interrupt Enable 0 */
#define IE1 0x09 /* Interrupt Enable 1 */
#define IE2 0x0A /* Interrupt Enable 2 */
#define FIE 0x0B /* Frame Interrupt Enable */
#define CMD 0x0C /* Command */
#define MD0 0x0E /* Mode 0 */
#define MD1 0x0F /* Mode 1 */
#define MD2 0x10 /* Mode 2 */
#define CTL 0x11 /* Control */
#define SA0 0x12 /* Sync/Address 0 */
#define SA1 0x13 /* Sync/Address 1 */
#define IDL 0x14 /* Idle Pattern */
#define TMC 0x15 /* Time Constant */
#define RXS 0x16 /* RX Clock Source */
#define TXS 0x17 /* TX Clock Source */
#define TRC0 0x18 /* TX Ready Control 0 */
#define TRC1 0x19 /* TX Ready Control 1 */
#define RRC 0x1A /* RX Ready Control */
#define CST0 0x1C /* Current Status 0 */
#define CST1 0x1D /* Current Status 1 */
/* Timer channel 0 (port 0 RX) registers - offset 0x60
Timer channel 1 (port 0 TX) registers - offset 0x68
Timer channel 2 (port 1 RX) registers - offset 0x70
Timer channel 3 (port 1 TX) registers - offset 0x78
*/
#define TIMER0RX_OFFSET 0x60
#define TIMER0TX_OFFSET 0x68
#define TIMER1RX_OFFSET 0x70
#define TIMER1TX_OFFSET 0x78
#define TCNTL 0x00 /* Up-counter L */
#define TCNTH 0x01 /* Up-counter H */
#define TCONRL 0x02 /* Constant L */
#define TCONRH 0x03 /* Constant H */
#define TCSR 0x04 /* Control/Status */
#define TEPR 0x05 /* Expand Prescale */
/* DMA channel 0 (port 0 RX) registers - offset 0x80
DMA channel 1 (port 0 TX) registers - offset 0xA0
DMA channel 2 (port 1 RX) registers - offset 0xC0
DMA channel 3 (port 1 TX) registers - offset 0xE0
*/
#define DMAC0RX_OFFSET 0x80
#define DMAC0TX_OFFSET 0xA0
#define DMAC1RX_OFFSET 0xC0
#define DMAC1TX_OFFSET 0xE0
#define BARL 0x00 /* Buffer Address L (chained block) */
#define BARH 0x01 /* Buffer Address H (chained block) */
#define BARB 0x02 /* Buffer Address B (chained block) */
#define DARL 0x00 /* RX Destination Addr L (single block) */
#define DARH 0x01 /* RX Destination Addr H (single block) */
#define DARB 0x02 /* RX Destination Addr B (single block) */
#define SARL 0x04 /* TX Source Address L (single block) */
#define SARH 0x05 /* TX Source Address H (single block) */
#define SARB 0x06 /* TX Source Address B (single block) */
#define CPB 0x06 /* Chain Pointer Base (chained block) */
#define CDAL 0x08 /* Current Descriptor Addr L (chained block) */
#define CDAH 0x09 /* Current Descriptor Addr H (chained block) */
#define EDAL 0x0A /* Error Descriptor Addr L (chained block) */
#define EDAH 0x0B /* Error Descriptor Addr H (chained block) */
#define BFLL 0x0C /* RX Receive Buffer Length L (chained block)*/
#define BFLH 0x0D /* RX Receive Buffer Length H (chained block)*/
#define BCRL 0x0E /* Byte Count L */
#define BCRH 0x0F /* Byte Count H */
#define DSR 0x10 /* DMA Status */
#define DSR_RX(node) (DSR + (node ? DMAC1RX_OFFSET : DMAC0RX_OFFSET))
#define DSR_TX(node) (DSR + (node ? DMAC1TX_OFFSET : DMAC0TX_OFFSET))
#define DMR 0x11 /* DMA Mode */
#define DMR_RX(node) (DMR + (node ? DMAC1RX_OFFSET : DMAC0RX_OFFSET))
#define DMR_TX(node) (DMR + (node ? DMAC1TX_OFFSET : DMAC0TX_OFFSET))
#define FCT 0x13 /* Frame End Interrupt Counter */
#define FCT_RX(node) (FCT + (node ? DMAC1RX_OFFSET : DMAC0RX_OFFSET))
#define FCT_TX(node) (FCT + (node ? DMAC1TX_OFFSET : DMAC0TX_OFFSET))
#define DIR 0x14 /* DMA Interrupt Enable */
#define DIR_RX(node) (DIR + (node ? DMAC1RX_OFFSET : DMAC0RX_OFFSET))
#define DIR_TX(node) (DIR + (node ? DMAC1TX_OFFSET : DMAC0TX_OFFSET))
#define DCR 0x15 /* DMA Command */
#define DCR_RX(node) (DCR + (node ? DMAC1RX_OFFSET : DMAC0RX_OFFSET))
#define DCR_TX(node) (DCR + (node ? DMAC1TX_OFFSET : DMAC0TX_OFFSET))
/* Descriptor Structure */
typedef struct {
u16 cp; /* Chain Pointer */
u32 bp; /* Buffer Pointer (24 bits) */
u16 len; /* Data Length */
u8 stat; /* Status */
u8 unused; /* pads to 2-byte boundary */
}__attribute__ ((packed)) pkt_desc;
/* Packet Descriptor Status bits */
#define ST_TX_EOM 0x80 /* End of frame */
#define ST_TX_EOT 0x01 /* End of transmition */
#define ST_RX_EOM 0x80 /* End of frame */
#define ST_RX_SHORT 0x40 /* Short frame */
#define ST_RX_ABORT 0x20 /* Abort */
#define ST_RX_RESBIT 0x10 /* Residual bit */
#define ST_RX_OVERRUN 0x08 /* Overrun */
#define ST_RX_CRC 0x04 /* CRC */
#define ST_ERROR_MASK 0x7C
#define DIR_EOTE 0x80 /* Transfer completed */
#define DIR_EOME 0x40 /* Frame Transfer Completed (chained-block) */
#define DIR_BOFE 0x20 /* Buffer Overflow/Underflow (chained-block)*/
#define DIR_COFE 0x10 /* Counter Overflow (chained-block) */
#define DSR_EOT 0x80 /* Transfer completed */
#define DSR_EOM 0x40 /* Frame Transfer Completed (chained-block) */
#define DSR_BOF 0x20 /* Buffer Overflow/Underflow (chained-block)*/
#define DSR_COF 0x10 /* Counter Overflow (chained-block) */
#define DSR_DE 0x02 /* DMA Enable */
#define DSR_DWE 0x01 /* DMA Write Disable */
/* DMA Master Enable Register (DMER) bits */
#define DMER_DME 0x80 /* DMA Master Enable */
#define CMD_RESET 0x21 /* Reset Channel */
#define CMD_TX_ENABLE 0x02 /* Start transmitter */
#define CMD_RX_ENABLE 0x12 /* Start receiver */
#define MD0_HDLC 0x80 /* Bit-sync HDLC mode */
#define MD0_CRC_ENA 0x04 /* Enable CRC code calculation */
#define MD0_CRC_CCITT 0x02 /* CCITT CRC instead of CRC-16 */
#define MD0_CRC_PR1 0x01 /* Initial all-ones instead of all-zeros */
#define MD0_CRC_NONE 0x00
#define MD0_CRC_16_0 0x04
#define MD0_CRC_16 0x05
#define MD0_CRC_ITU_0 0x06
#define MD0_CRC_ITU 0x07
#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 CTL_NORTS 0x01
#define CTL_IDLE 0x10 /* Transmit an idle pattern */
#define CTL_UDRNC 0x20 /* Idle after CRC or FCS+flag transmition */
#define ST0_TXRDY 0x02 /* TX ready */
#define ST0_RXRDY 0x01 /* RX ready */
#define ST1_UDRN 0x80 /* MSCI TX underrun */
#define ST1_CDCD 0x04 /* DCD level changed */
#define ST3_CTS 0x08 /* modem input - /CTS */
#define ST3_DCD 0x04 /* modem input - /DCD */
#define IE0_TXINT 0x80 /* TX INT MSCI interrupt enable */
#define IE0_RXINTA 0x40 /* RX INT A MSCI interrupt enable */
#define IE1_UDRN 0x80 /* TX underrun MSCI interrupt enable */
#define IE1_CDCD 0x04 /* DCD level changed */
#define DCR_ABORT 0x01 /* Software abort command */
#define DCR_CLEAR_EOF 0x02 /* Clear EOF interrupt */
/* TX and RX Clock Source - RXS and TXS */
#define CLK_BRG_MASK 0x0F
#define CLK_LINE_RX 0x00 /* TX/RX clock line input */
#define CLK_LINE_TX 0x00 /* TX/RX line input */
#define CLK_BRG_RX 0x40 /* internal baud rate generator */
#define CLK_BRG_TX 0x40 /* internal baud rate generator */
#define CLK_RXCLK_TX 0x60 /* TX clock from RX clock */
#endif
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+330
View File
@@ -0,0 +1,330 @@
/*
* Generic HDLC support routines for Linux
* Cisco HDLC support
*
* Copyright (C) 2000 - 2003 Krzysztof Halasa <khc@pm.waw.pl>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License
* as published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/poll.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>
#undef DEBUG_HARD_HEADER
#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 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(struct net_device *dev, 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",
dev->name);
return;
}
skb_reserve(skb, 4);
cisco_hard_header(skb, dev, 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;
/* we will need do_div here if 1000 % HZ != 0 */
data->time = htonl((jiffies - INITIAL_JIFFIES) * (1000 / HZ));
skb_put(skb, sizeof(cisco_packet));
skb->priority = TC_PRIO_CONTROL;
skb->dev = dev;
skb->nh.raw = skb->data;
dev_queue_xmit(skb);
}
static unsigned short cisco_type_trans(struct sk_buff *skb,
struct net_device *dev)
{
hdlc_header *data = (hdlc_header*)skb->data;
if (skb->len < sizeof(hdlc_header))
return __constant_htons(ETH_P_HDLC);
if (data->address != CISCO_MULTICAST &&
data->address != CISCO_UNICAST)
return __constant_htons(ETH_P_HDLC);
switch(data->protocol) {
case __constant_htons(ETH_P_IP):
case __constant_htons(ETH_P_IPX):
case __constant_htons(ETH_P_IPV6):
skb_pull(skb, sizeof(hdlc_header));
return data->protocol;
default:
return __constant_htons(ETH_P_HDLC);
}
}
static int cisco_rx(struct sk_buff *skb)
{
struct net_device *dev = skb->dev;
hdlc_device *hdlc = dev_to_hdlc(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;
switch(ntohs(data->protocol)) {
case CISCO_SYS_INFO:
/* Packet is not needed, drop it. */
dev_kfree_skb_any(skb);
return NET_RX_SUCCESS;
case CISCO_KEEPALIVE:
if (skb->len != sizeof(hdlc_header) + CISCO_PACKET_LEN &&
skb->len != sizeof(hdlc_header) + CISCO_BIG_PACKET_LEN) {
printk(KERN_INFO "%s: Invalid length of Cisco "
"control packet (%d bytes)\n",
dev->name, skb->len);
goto rx_error;
}
cisco_data = (cisco_packet*)(skb->data + sizeof(hdlc_header));
switch(ntohl (cisco_data->type)) {
case CISCO_ADDR_REQ: /* Stolen from syncppp.c :-) */
in_dev = dev->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(dev->name,
(*ifap)->ifa_label) == 0) {
addr = (*ifap)->ifa_local;
mask = (*ifap)->ifa_mask;
break;
}
ifap = &(*ifap)->ifa_next;
}
cisco_keepalive_send(dev, CISCO_ADDR_REPLY,
addr, mask);
}
dev_kfree_skb_any(skb);
return NET_RX_SUCCESS;
case CISCO_ADDR_REPLY:
printk(KERN_INFO "%s: Unexpected Cisco IP address "
"reply\n", dev->name);
goto rx_error;
case CISCO_KEEPALIVE_REQ:
hdlc->state.cisco.rxseq = ntohl(cisco_data->par1);
if (hdlc->state.cisco.request_sent &&
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",
dev->name, days, hrs,
min, sec);
netif_carrier_on(dev);
hdlc->state.cisco.up = 1;
}
}
dev_kfree_skb_any(skb);
return NET_RX_SUCCESS;
} /* switch(keepalive type) */
} /* switch(protocol) */
printk(KERN_INFO "%s: Unsupported protocol %x\n", dev->name,
data->protocol);
dev_kfree_skb_any(skb);
return NET_RX_DROP;
rx_error:
hdlc->stats.rx_errors++; /* Mark error */
dev_kfree_skb_any(skb);
return NET_RX_DROP;
}
static void cisco_timer(unsigned long arg)
{
struct net_device *dev = (struct net_device *)arg;
hdlc_device *hdlc = dev_to_hdlc(dev);
if (hdlc->state.cisco.up &&
time_after(jiffies, hdlc->state.cisco.last_poll +
hdlc->state.cisco.settings.timeout * HZ)) {
hdlc->state.cisco.up = 0;
printk(KERN_INFO "%s: Link down\n", dev->name);
netif_carrier_off(dev);
}
cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ,
++hdlc->state.cisco.txseq,
hdlc->state.cisco.rxseq);
hdlc->state.cisco.request_sent = 1;
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 void cisco_start(struct net_device *dev)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
hdlc->state.cisco.up = 0;
hdlc->state.cisco.request_sent = 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)dev;
add_timer(&hdlc->state.cisco.timer);
}
static void cisco_stop(struct net_device *dev)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
del_timer_sync(&hdlc->state.cisco.timer);
if (netif_carrier_ok(dev))
netif_carrier_off(dev);
hdlc->state.cisco.up = 0;
hdlc->state.cisco.request_sent = 0;
}
int hdlc_cisco_ioctl(struct net_device *dev, struct ifreq *ifr)
{
cisco_proto __user *cisco_s = ifr->ifr_settings.ifs_ifsu.cisco;
const size_t size = sizeof(cisco_proto);
cisco_proto new_settings;
hdlc_device *hdlc = dev_to_hdlc(dev);
int result;
switch (ifr->ifr_settings.type) {
case IF_GET_PROTO:
ifr->ifr_settings.type = IF_PROTO_CISCO;
if (ifr->ifr_settings.size < size) {
ifr->ifr_settings.size = size; /* data size wanted */
return -ENOBUFS;
}
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(&new_settings, cisco_s, size))
return -EFAULT;
if (new_settings.interval < 1 ||
new_settings.timeout < 2)
return -EINVAL;
result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT);
if (result)
return result;
hdlc_proto_detach(hdlc);
memcpy(&hdlc->state.cisco.settings, &new_settings, size);
memset(&hdlc->proto, 0, sizeof(hdlc->proto));
hdlc->proto.start = cisco_start;
hdlc->proto.stop = cisco_stop;
hdlc->proto.netif_rx = cisco_rx;
hdlc->proto.type_trans = cisco_type_trans;
hdlc->proto.id = IF_PROTO_CISCO;
dev->hard_start_xmit = hdlc->xmit;
dev->hard_header = cisco_hard_header;
dev->hard_header_cache = NULL;
dev->type = ARPHRD_CISCO;
dev->flags = IFF_POINTOPOINT | IFF_NOARP;
dev->addr_len = 0;
return 0;
}
return -EINVAL;
}
File diff suppressed because it is too large Load Diff
+343
View File
@@ -0,0 +1,343 @@
/*
* Generic HDLC support routines for Linux
*
* Copyright (C) 1999 - 2003 Krzysztof Halasa <khc@pm.waw.pl>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License
* as published by the Free Software Foundation.
*
* Currently supported:
* * raw IP-in-HDLC
* * Cisco HDLC
* * Frame Relay with ANSI or CCITT LMI (both user and network side)
* * PPP
* * X.25
*
* Use sethdlc utility to set line parameters, protocol and PVCs
*
* How does it work:
* - proto.open(), close(), start(), stop() calls are serialized.
* The order is: open, [ start, stop ... ] close ...
* - proto.start() and stop() are called with spin_lock_irq held.
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/poll.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>
static const char* version = "HDLC support module revision 1.17";
#undef DEBUG_LINK
static int hdlc_change_mtu(struct net_device *dev, int new_mtu)
{
if ((new_mtu < 68) || (new_mtu > HDLC_MAX_MTU))
return -EINVAL;
dev->mtu = new_mtu;
return 0;
}
static struct net_device_stats *hdlc_get_stats(struct net_device *dev)
{
return hdlc_stats(dev);
}
static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *p)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
if (hdlc->proto.netif_rx)
return hdlc->proto.netif_rx(skb);
hdlc->stats.rx_dropped++; /* Shouldn't happen */
dev_kfree_skb(skb);
return NET_RX_DROP;
}
static void __hdlc_set_carrier_on(struct net_device *dev)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
if (hdlc->proto.start)
return hdlc->proto.start(dev);
#ifdef DEBUG_LINK
if (netif_carrier_ok(dev))
printk(KERN_ERR "hdlc_set_carrier_on(): already on\n");
#endif
netif_carrier_on(dev);
}
static void __hdlc_set_carrier_off(struct net_device *dev)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
if (hdlc->proto.stop)
return hdlc->proto.stop(dev);
#ifdef DEBUG_LINK
if (!netif_carrier_ok(dev))
printk(KERN_ERR "hdlc_set_carrier_off(): already off\n");
#endif
netif_carrier_off(dev);
}
void hdlc_set_carrier(int on, struct net_device *dev)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
unsigned long flags;
on = on ? 1 : 0;
#ifdef DEBUG_LINK
printk(KERN_DEBUG "hdlc_set_carrier %i\n", on);
#endif
spin_lock_irqsave(&hdlc->state_lock, flags);
if (hdlc->carrier == on)
goto carrier_exit; /* no change in DCD line level */
#ifdef DEBUG_LINK
printk(KERN_INFO "%s: carrier %s\n", dev->name, on ? "ON" : "off");
#endif
hdlc->carrier = on;
if (!hdlc->open)
goto carrier_exit;
if (hdlc->carrier)
__hdlc_set_carrier_on(dev);
else
__hdlc_set_carrier_off(dev);
carrier_exit:
spin_unlock_irqrestore(&hdlc->state_lock, flags);
}
/* Must be called by hardware driver when HDLC device is being opened */
int hdlc_open(struct net_device *dev)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
#ifdef DEBUG_LINK
printk(KERN_DEBUG "hdlc_open() carrier %i open %i\n",
hdlc->carrier, hdlc->open);
#endif
if (hdlc->proto.id == -1)
return -ENOSYS; /* no protocol attached */
if (hdlc->proto.open) {
int result = hdlc->proto.open(dev);
if (result)
return result;
}
spin_lock_irq(&hdlc->state_lock);
if (hdlc->carrier)
__hdlc_set_carrier_on(dev);
hdlc->open = 1;
spin_unlock_irq(&hdlc->state_lock);
return 0;
}
/* Must be called by hardware driver when HDLC device is being closed */
void hdlc_close(struct net_device *dev)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
#ifdef DEBUG_LINK
printk(KERN_DEBUG "hdlc_close() carrier %i open %i\n",
hdlc->carrier, hdlc->open);
#endif
spin_lock_irq(&hdlc->state_lock);
hdlc->open = 0;
if (hdlc->carrier)
__hdlc_set_carrier_off(dev);
spin_unlock_irq(&hdlc->state_lock);
if (hdlc->proto.close)
hdlc->proto.close(dev);
}
#ifndef CONFIG_HDLC_RAW
#define hdlc_raw_ioctl(dev, ifr) -ENOSYS
#endif
#ifndef CONFIG_HDLC_RAW_ETH
#define hdlc_raw_eth_ioctl(dev, ifr) -ENOSYS
#endif
#ifndef CONFIG_HDLC_PPP
#define hdlc_ppp_ioctl(dev, ifr) -ENOSYS
#endif
#ifndef CONFIG_HDLC_CISCO
#define hdlc_cisco_ioctl(dev, ifr) -ENOSYS
#endif
#ifndef CONFIG_HDLC_FR
#define hdlc_fr_ioctl(dev, ifr) -ENOSYS
#endif
#ifndef CONFIG_HDLC_X25
#define hdlc_x25_ioctl(dev, ifr) -ENOSYS
#endif
int hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
unsigned int proto;
if (cmd != SIOCWANDEV)
return -EINVAL;
switch(ifr->ifr_settings.type) {
case IF_PROTO_HDLC:
case IF_PROTO_HDLC_ETH:
case IF_PROTO_PPP:
case IF_PROTO_CISCO:
case IF_PROTO_FR:
case IF_PROTO_X25:
proto = ifr->ifr_settings.type;
break;
default:
proto = hdlc->proto.id;
}
switch(proto) {
case IF_PROTO_HDLC: return hdlc_raw_ioctl(dev, ifr);
case IF_PROTO_HDLC_ETH: return hdlc_raw_eth_ioctl(dev, ifr);
case IF_PROTO_PPP: return hdlc_ppp_ioctl(dev, ifr);
case IF_PROTO_CISCO: return hdlc_cisco_ioctl(dev, ifr);
case IF_PROTO_FR: return hdlc_fr_ioctl(dev, ifr);
case IF_PROTO_X25: return hdlc_x25_ioctl(dev, ifr);
default: return -EINVAL;
}
}
static void hdlc_setup(struct net_device *dev)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
dev->get_stats = hdlc_get_stats;
dev->change_mtu = hdlc_change_mtu;
dev->mtu = HDLC_MAX_MTU;
dev->type = ARPHRD_RAWHDLC;
dev->hard_header_len = 16;
dev->flags = IFF_POINTOPOINT | IFF_NOARP;
hdlc->proto.id = -1;
hdlc->proto.detach = NULL;
hdlc->carrier = 1;
hdlc->open = 0;
spin_lock_init(&hdlc->state_lock);
}
struct net_device *alloc_hdlcdev(void *priv)
{
struct net_device *dev;
dev = alloc_netdev(sizeof(hdlc_device), "hdlc%d", hdlc_setup);
if (dev)
dev_to_hdlc(dev)->priv = priv;
return dev;
}
int register_hdlc_device(struct net_device *dev)
{
int result = dev_alloc_name(dev, "hdlc%d");
if (result < 0)
return result;
result = register_netdev(dev);
if (result != 0)
return -EIO;
if (netif_carrier_ok(dev))
netif_carrier_off(dev); /* no carrier until DCD goes up */
return 0;
}
void unregister_hdlc_device(struct net_device *dev)
{
rtnl_lock();
hdlc_proto_detach(dev_to_hdlc(dev));
unregister_netdevice(dev);
rtnl_unlock();
}
MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
MODULE_DESCRIPTION("HDLC support module");
MODULE_LICENSE("GPL v2");
EXPORT_SYMBOL(hdlc_open);
EXPORT_SYMBOL(hdlc_close);
EXPORT_SYMBOL(hdlc_set_carrier);
EXPORT_SYMBOL(hdlc_ioctl);
EXPORT_SYMBOL(alloc_hdlcdev);
EXPORT_SYMBOL(register_hdlc_device);
EXPORT_SYMBOL(unregister_hdlc_device);
static struct packet_type hdlc_packet_type = {
.type = __constant_htons(ETH_P_HDLC),
.func = hdlc_rcv,
};
static int __init hdlc_module_init(void)
{
printk(KERN_INFO "%s\n", version);
dev_add_pack(&hdlc_packet_type);
return 0;
}
static void __exit hdlc_module_exit(void)
{
dev_remove_pack(&hdlc_packet_type);
}
module_init(hdlc_module_init);
module_exit(hdlc_module_exit);
+115
View File
@@ -0,0 +1,115 @@
/*
* Generic HDLC support routines for Linux
* Point-to-point protocol support
*
* Copyright (C) 1999 - 2003 Krzysztof Halasa <khc@pm.waw.pl>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License
* as published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/poll.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>
static int ppp_open(struct net_device *dev)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
void *old_ioctl;
int result;
dev->priv = &hdlc->state.ppp.syncppp_ptr;
hdlc->state.ppp.syncppp_ptr = &hdlc->state.ppp.pppdev;
hdlc->state.ppp.pppdev.dev = dev;
old_ioctl = dev->do_ioctl;
hdlc->state.ppp.old_change_mtu = dev->change_mtu;
sppp_attach(&hdlc->state.ppp.pppdev);
/* sppp_attach nukes them. We don't need syncppp's ioctl */
dev->do_ioctl = old_ioctl;
hdlc->state.ppp.pppdev.sppp.pp_flags &= ~PP_CISCO;
dev->type = ARPHRD_PPP;
result = sppp_open(dev);
if (result) {
sppp_detach(dev);
return result;
}
return 0;
}
static void ppp_close(struct net_device *dev)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
sppp_close(dev);
sppp_detach(dev);
dev->rebuild_header = NULL;
dev->change_mtu = hdlc->state.ppp.old_change_mtu;
dev->mtu = HDLC_MAX_MTU;
dev->hard_header_len = 16;
}
static unsigned short ppp_type_trans(struct sk_buff *skb,
struct net_device *dev)
{
return __constant_htons(ETH_P_WAN_PPP);
}
int hdlc_ppp_ioctl(struct net_device *dev, struct ifreq *ifr)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
int result;
switch (ifr->ifr_settings.type) {
case IF_GET_PROTO:
ifr->ifr_settings.type = IF_PROTO_PPP;
return 0; /* return protocol only, no settable parameters */
case IF_PROTO_PPP:
if(!capable(CAP_NET_ADMIN))
return -EPERM;
if(dev->flags & IFF_UP)
return -EBUSY;
/* no settable parameters */
result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT);
if (result)
return result;
hdlc_proto_detach(hdlc);
memset(&hdlc->proto, 0, sizeof(hdlc->proto));
hdlc->proto.open = ppp_open;
hdlc->proto.close = ppp_close;
hdlc->proto.type_trans = ppp_type_trans;
hdlc->proto.id = IF_PROTO_PPP;
dev->hard_start_xmit = hdlc->xmit;
dev->hard_header = NULL;
dev->type = ARPHRD_PPP;
dev->addr_len = 0;
return 0;
}
return -EINVAL;
}
+90
View File
@@ -0,0 +1,90 @@
/*
* Generic HDLC support routines for Linux
* HDLC support
*
* Copyright (C) 1999 - 2003 Krzysztof Halasa <khc@pm.waw.pl>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License
* as published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/poll.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>
static unsigned short raw_type_trans(struct sk_buff *skb,
struct net_device *dev)
{
return __constant_htons(ETH_P_IP);
}
int hdlc_raw_ioctl(struct net_device *dev, struct ifreq *ifr)
{
raw_hdlc_proto __user *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc;
const size_t size = sizeof(raw_hdlc_proto);
raw_hdlc_proto new_settings;
hdlc_device *hdlc = dev_to_hdlc(dev);
int result;
switch (ifr->ifr_settings.type) {
case IF_GET_PROTO:
ifr->ifr_settings.type = IF_PROTO_HDLC;
if (ifr->ifr_settings.size < size) {
ifr->ifr_settings.size = size; /* data size wanted */
return -ENOBUFS;
}
if (copy_to_user(raw_s, &hdlc->state.raw_hdlc.settings, size))
return -EFAULT;
return 0;
case IF_PROTO_HDLC:
if (!capable(CAP_NET_ADMIN))
return -EPERM;
if (dev->flags & IFF_UP)
return -EBUSY;
if (copy_from_user(&new_settings, raw_s, size))
return -EFAULT;
if (new_settings.encoding == ENCODING_DEFAULT)
new_settings.encoding = ENCODING_NRZ;
if (new_settings.parity == PARITY_DEFAULT)
new_settings.parity = PARITY_CRC16_PR1_CCITT;
result = hdlc->attach(dev, new_settings.encoding,
new_settings.parity);
if (result)
return result;
hdlc_proto_detach(hdlc);
memcpy(&hdlc->state.raw_hdlc.settings, &new_settings, size);
memset(&hdlc->proto, 0, sizeof(hdlc->proto));
hdlc->proto.type_trans = raw_type_trans;
hdlc->proto.id = IF_PROTO_HDLC;
dev->hard_start_xmit = hdlc->xmit;
dev->hard_header = NULL;
dev->type = ARPHRD_RAWHDLC;
dev->flags = IFF_POINTOPOINT | IFF_NOARP;
dev->addr_len = 0;
return 0;
}
return -EINVAL;
}

Some files were not shown because too many files have changed in this diff Show More