Commit 8db60bcf authored by Adrian Bunk's avatar Adrian Bunk Committed by David S. Miller

[WAN]: Remove broken and unmaintained Sangoma drivers.

The in-kernel Sangoma drivers are both not compiling and marked as BROKEN
since at least kernel 2.6.0.

Sangoma offers out-of-tree drivers, and David Mandelstam told me Sangoma
does no longer maintain the in-kernel drivers and prefers to provide them
as a separate installation package.

This patch therefore removes these drivers.
Signed-off-by: default avatarAdrian Bunk <bunk@stusta.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7ad4d2f6
......@@ -3058,13 +3058,6 @@ M: khali@linux-fr.org
L: lm-sensors@lm-sensors.org
S: Odd Fixes
WAN ROUTER & SANGOMA WANPIPE DRIVERS & API (X.25, FRAME RELAY, PPP, CISCO HDLC)
P: Nenad Corbic
M: ncorbic@sangoma.com
M: dm@sangoma.com
W: http://www.sangoma.com
S: Supported
WATCHDOG DEVICE DRIVERS
P: Wim Van Sebroeck
M: wim@iguana.be
......
......@@ -410,103 +410,6 @@ config WAN_ROUTER_DRIVERS
If unsure, say N.
config VENDOR_SANGOMA
tristate "Sangoma WANPIPE(tm) multiprotocol cards"
depends on WAN_ROUTER_DRIVERS && WAN_ROUTER && (PCI || ISA) && BROKEN
---help---
Driver for S514-PCI/ISA Synchronous Data Link Adapters (SDLA).
WANPIPE from Sangoma Technologies Inc. <http://www.sangoma.com/>
is a family of intelligent multiprotocol WAN adapters with data
transfer rates up to 4Mbps. Cards support:
- X.25, Frame Relay, PPP, Cisco HDLC protocols.
- API for protocols like HDLC (LAPB), HDLC Streaming, X.25,
Frame Relay and BiSync.
- Ethernet Bridging over Frame Relay protocol.
- MULTILINK PPP
- Async PPP (Modem Dialup)
The next questions will ask you about the protocols you want
the driver to support.
If you have one or more of these cards, say M to this option;
and read <file:Documentation/networking/wan-router.txt>.
To compile this driver as a module, choose M here: the
module will be called wanpipe.
config WANPIPE_CHDLC
bool "WANPIPE Cisco HDLC support"
depends on VENDOR_SANGOMA
---help---
Connect a WANPIPE card to a leased line using the Cisco HDLC.
- Supports Dual Port Cisco HDLC on the S514-PCI/S508-ISA cards
which allows user to build applications using the HDLC streaming API.
- CHDLC Streaming MULTILINK PPP that can bind multiple WANPIPE T1
cards into a single logical channel.
Say Y and the Cisco HDLC support, HDLC streaming API and
MULTILINK PPP will be included in the driver.
config WANPIPE_FR
bool "WANPIPE Frame Relay support"
depends on VENDOR_SANGOMA
help
Connect a WANPIPE card to a Frame Relay network, or use Frame Relay
API to develop custom applications.
Contains the Ethernet Bridging over Frame Relay feature, where
a WANPIPE frame relay link can be directly connected to the Linux
kernel bridge. The Frame Relay option is supported on S514-PCI
and S508-ISA cards.
Say Y and the Frame Relay support will be included in the driver.
config WANPIPE_X25
bool "WANPIPE X.25 support"
depends on VENDOR_SANGOMA
help
Connect a WANPIPE card to an X.25 network.
Includes the X.25 API support for custom applications over the
X.25 protocol. The X.25 option is supported on S514-PCI and
S508-ISA cards.
Say Y and the X.25 support will be included in the driver.
config WANPIPE_PPP
bool "WANPIPE PPP support"
depends on VENDOR_SANGOMA
help
Connect a WANPIPE card to a leased line using Point-to-Point
Protocol (PPP).
The PPP option is supported on S514-PCI/S508-ISA cards.
Say Y and the PPP support will be included in the driver.
config WANPIPE_MULTPPP
bool "WANPIPE Multi-Port PPP support"
depends on VENDOR_SANGOMA
help
Connect a WANPIPE card to a leased line using Point-to-Point
Protocol (PPP).
Uses in-kernel SyncPPP protocol over the Sangoma HDLC Streaming
adapter. In this case each Sangoma adapter port can support an
independent PPP connection. For example, a single Quad-Port PCI
adapter can support up to four independent PPP links. The PPP
option is supported on S514-PCI/S508-ISA cards.
Say Y and the Multi-Port PPP support will be included in the driver.
config CYCLADES_SYNC
tristate "Cyclom 2X(tm) cards (EXPERIMENTAL)"
depends on WAN_ROUTER_DRIVERS && (PCI || ISA)
......
......@@ -5,14 +5,6 @@
# 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)
......@@ -43,11 +35,6 @@ 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
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
/*****************************************************************************
* sdla_chdlc.c WANPIPE(tm) Multiprotocol WAN Link Driver. Cisco HDLC module.
*
* Authors: Nenad Corbic <ncorbic@sangoma.com>
* Gideon Hack
*
* Copyright: (c) 1995-1999 Sangoma Technologies Inc.
*
* 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.
* ============================================================================
* Sep 30, 1999 Nenad Corbic Fixed dynamic IP and route setup.
* Sep 23, 1999 Nenad Corbic Added SMP support, fixed tracing
* Sep 13, 1999 Nenad Corbic Split up Port 0 and 1 into separate devices.
* Jun 02, 1999 Gideon Hack Added support for the S514 adapter.
* Oct 30, 1998 Jaspreet Singh Added Support for CHDLC API (HDLC STREAMING).
* Oct 28, 1998 Jaspreet Singh Added Support for Dual Port CHDLC.
* Aug 07, 1998 David Fong Initial version.
*****************************************************************************/
#include <linux/module.h>
#include <linux/kernel.h> /* printk(), and other useful stuff */
#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/wanrouter.h> /* WAN router definitions */
#include <linux/wanpipe.h> /* WANPIPE common user API definitions */
#include <linux/if_arp.h> /* ARPHRD_* defines */
#include <linux/jiffies.h> /* time_after() macro */
#include <linux/inetdevice.h>
#include <asm/uaccess.h>
#include <linux/in.h> /* sockaddr_in */
#include <linux/inet.h>
#include <linux/if.h>
#include <asm/byteorder.h> /* htons(), etc. */
#include <linux/sdlapci.h>
#include <asm/io.h>
#include <linux/sdla_chdlc.h> /* CHDLC firmware API definitions */
/****** Defines & Macros ****************************************************/
/* reasons for enabling the timer interrupt on the adapter */
#define TMR_INT_ENABLED_UDP 0x0001
#define TMR_INT_ENABLED_UPDATE 0x0002
#define CHDLC_DFLT_DATA_LEN 1500 /* default MTU */
#define CHDLC_HDR_LEN 1
#define IFF_POINTTOPOINT 0x10
#define WANPIPE 0x00
#define API 0x01
#define CHDLC_API 0x01
#define PORT(x) (x == 0 ? "PRIMARY" : "SECONDARY" )
/******Data Structures*****************************************************/
/* This structure is placed in the private data area of the device structure.
* The card structure used to occupy the private area but now the following
* structure will incorporate the card structure along with CHDLC specific data
*/
typedef struct chdlc_private_area
{
struct net_device *slave;
sdla_t *card;
int TracingEnabled; /* For enabling Tracing */
unsigned long curr_trace_addr; /* Used for Tracing */
unsigned long start_trace_addr;
unsigned long end_trace_addr;
unsigned long base_addr_trace_buffer;
unsigned long end_addr_trace_buffer;
unsigned short number_trace_elements;
unsigned available_buffer_space;
unsigned long router_start_time;
unsigned char route_status;
unsigned char route_removed;
unsigned long tick_counter; /* For 5s timeout counter */
unsigned long router_up_time;
u32 IP_address; /* IP addressing */
u32 IP_netmask;
unsigned char mc; /* Mulitcast support on/off */
unsigned short udp_pkt_lgth; /* udp packet processing */
char udp_pkt_src;
char udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT];
unsigned short timer_int_enabled;
char update_comms_stats; /* updating comms stats */
//FIXME: add driver stats as per frame relay!
} chdlc_private_area_t;
/* Route Status options */
#define NO_ROUTE 0x00
#define ADD_ROUTE 0x01
#define ROUTE_ADDED 0x02
#define REMOVE_ROUTE 0x03
/****** Function Prototypes *************************************************/
/* WAN link driver entry points. These are called by the WAN router module. */
static int wpft1_exec (struct sdla *card, void *u_cmd, void *u_data);
static int chdlc_read_version (sdla_t* card, char* str);
static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb);
/****** Public Functions ****************************************************/
/*============================================================================
* Cisco HDLC protocol initialization routine.
*
* This routine is called by the main WANPIPE module during setup. At this
* point adapter is completely initialized and firmware is running.
* o read firmware version (to make sure it's alive)
* o configure adapter
* o initialize protocol-specific fields of the adapter data space.
*
* Return: 0 o.k.
* < 0 failure.
*/
int wpft1_init (sdla_t* card, wandev_conf_t* conf)
{
unsigned char port_num;
int err;
union
{
char str[80];
} u;
volatile CHDLC_MAILBOX_STRUCT* mb;
CHDLC_MAILBOX_STRUCT* mb1;
unsigned long timeout;
/* Verify configuration ID */
if (conf->config_id != WANCONFIG_CHDLC) {
printk(KERN_INFO "%s: invalid configuration ID %u!\n",
card->devname, conf->config_id);
return -EINVAL;
}
/* Use primary port */
card->u.c.comm_port = 0;
/* Initialize protocol-specific fields */
if(card->hw.type != SDLA_S514){
card->mbox = (void *) card->hw.dpmbase;
}else{
card->mbox = (void *) card->hw.dpmbase + PRI_BASE_ADDR_MB_STRUCT;
}
mb = mb1 = card->mbox;
if (!card->configured){
/* The board will place an 'I' in the return code to indicate that it is
ready to accept commands. We expect this to be completed in less
than 1 second. */
timeout = jiffies;
while (mb->return_code != 'I') /* Wait 1s for board to initialize */
if (time_after(jiffies, timeout + 1*HZ)) break;
if (mb->return_code != 'I') {
printk(KERN_INFO
"%s: Initialization not completed by adapter\n",
card->devname);
printk(KERN_INFO "Please contact Sangoma representative.\n");
return -EIO;
}
}
/* Read firmware version. Note that when adapter initializes, it
* clears the mailbox, so it may appear that the first command was
* executed successfully when in fact it was merely erased. To work
* around this, we execute the first command twice.
*/
if (chdlc_read_version(card, u.str))
return -EIO;
printk(KERN_INFO "%s: Running FT1 Configuration firmware v%s\n",
card->devname, u.str);
card->isr = NULL;
card->poll = NULL;
card->exec = &wpft1_exec;
card->wandev.update = NULL;
card->wandev.new_if = NULL;
card->wandev.del_if = NULL;
card->wandev.state = WAN_DUALPORT;
card->wandev.udp_port = conf->udp_port;
card->wandev.new_if_cnt = 0;
/* This is for the ports link state */
card->u.c.state = WAN_DISCONNECTED;
/* reset the number of times the 'update()' proc has been called */
card->u.c.update_call_count = 0;
card->wandev.ttl = 0x7F;
card->wandev.interface = 0;
card->wandev.clocking = 0;
port_num = card->u.c.comm_port;
/* Setup Port Bps */
card->wandev.bps = 0;
card->wandev.mtu = MIN_LGTH_CHDLC_DATA_CFG;
/* Set up the interrupt status area */
/* Read the CHDLC Configuration and obtain:
* Ptr to shared memory infor struct
* Use this pointer to calculate the value of card->u.c.flags !
*/
mb1->buffer_length = 0;
mb1->command = READ_CHDLC_CONFIGURATION;
err = sdla_exec(mb1) ? mb1->return_code : CMD_TIMEOUT;
if(err != COMMAND_OK) {
chdlc_error(card, err, mb1);
return -EIO;
}
if(card->hw.type == SDLA_S514){
card->u.c.flags = (void *)(card->hw.dpmbase +
(((CHDLC_CONFIGURATION_STRUCT *)mb1->data)->
ptr_shared_mem_info_struct));
}else{
card->u.c.flags = (void *)(card->hw.dpmbase +
(((CHDLC_CONFIGURATION_STRUCT *)mb1->data)->
ptr_shared_mem_info_struct % SDLA_WINDOWSIZE));
}
card->wandev.state = WAN_FT1_READY;
printk(KERN_INFO "%s: FT1 Config Ready !\n",card->devname);
return 0;
}
static int wpft1_exec(sdla_t *card, void *u_cmd, void *u_data)
{
CHDLC_MAILBOX_STRUCT* mbox = card->mbox;
int len;
if (copy_from_user((void*)&mbox->command, u_cmd, sizeof(ft1_exec_cmd_t))){
return -EFAULT;
}
len = mbox->buffer_length;
if (len) {
if( copy_from_user((void*)&mbox->data, u_data, len)){
return -EFAULT;
}
}
/* execute command */
if (!sdla_exec(mbox)){
return -EIO;
}
/* return result */
if( copy_to_user(u_cmd, (void*)&mbox->command, sizeof(ft1_exec_cmd_t))){
return -EFAULT;
}
len = mbox->buffer_length;
if (len && u_data && copy_to_user(u_data, (void*)&mbox->data, len)){
return -EFAULT;
}
return 0;
}
/*============================================================================
* Read firmware code version.
* Put code version as ASCII string in str.
*/
static int chdlc_read_version (sdla_t* card, char* str)
{
CHDLC_MAILBOX_STRUCT* mb = card->mbox;
int len;
char err;
mb->buffer_length = 0;
mb->command = READ_CHDLC_CODE_VERSION;
err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
if(err != COMMAND_OK) {
chdlc_error(card,err,mb);
}
else if (str) { /* is not null */
len = mb->buffer_length;
memcpy(str, mb->data, len);
str[len] = '\0';
}
return (err);
}
/*============================================================================
* Firmware error handler.
* This routine is called whenever firmware command returns non-zero
* return code.
*
* Return zero if previous command has to be cancelled.
*/
static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb)
{
unsigned cmd = mb->command;
switch (err) {
case CMD_TIMEOUT:
printk(KERN_ERR "%s: command 0x%02X timed out!\n",
card->devname, cmd);
break;
case S514_BOTH_PORTS_SAME_CLK_MODE:
if(cmd == SET_CHDLC_CONFIGURATION) {
printk(KERN_INFO
"%s: Configure both ports for the same clock source\n",
card->devname);
break;
}
default:
printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n",
card->devname, cmd, err);
}
return 0;
}
MODULE_LICENSE("GPL");
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
/*****************************************************************************
* sdladrv.c SDLA Support Module. Main module.
*
* This module is a library of common hardware-specific functions
* used by all Sangoma drivers.
*
* Author: Gideon Hack
*
* Copyright: (c) 1995-2000 Sangoma Technologies Inc.
*
* 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.
* ============================================================================
* Mar 20, 2001 Nenad Corbic Added the auto_pci_cfg filed, to support
* the PCISLOT #0.
* Apr 04, 2000 Nenad Corbic Fixed the auto memory detection code.
* The memory test at address 0xC8000.
* Mar 09, 2000 Nenad Corbic Added Gideon's Bug Fix: clear pci
* interrupt flags on initial load.
* Jun 02, 1999 Gideon Hack Added support for the S514 adapter.
* Updates for Linux 2.2.X kernels.
* Sep 17, 1998 Jaspreet Singh Updates for linux 2.2.X kernels
* Dec 20, 1996 Gene Kozin Version 3.0.0. Complete overhaul.
* Jul 12, 1996 Gene Kozin Changes for Linux 2.0 compatibility.
* Jun 12, 1996 Gene Kozin Added support for S503 card.
* Apr 30, 1996 Gene Kozin SDLA hardware interrupt is acknowledged before
* calling protocolspecific ISR.
* Register I/O ports with Linux kernel.
* Miscellaneous bug fixes.
* Dec 20, 1995 Gene Kozin Fixed a bug in interrupt routine.
* Oct 14, 1995 Gene Kozin Initial version.
*****************************************************************************/
/*****************************************************************************
* Notes:
* ------
* 1. This code is ment to be system-independent (as much as possible). To
* achive this, various macros are used to hide system-specific interfaces.
* To compile this code, one of the following constants must be defined:
*
* Platform Define
* -------- ------
* Linux _LINUX_
* SCO Unix _SCO_UNIX_
*
* 2. Supported adapter types:
*
* S502A
* ES502A (S502E)
* S503
* S507
* S508 (S509)
*
* 3. S502A Notes:
*
* There is no separate DPM window enable/disable control in S502A. It
* opens immediately after a window number it written to the HMCR
* register. To close the window, HMCR has to be written a value
* ????1111b (e.g. 0x0F or 0xFF).
*
* S502A DPM window cannot be located at offset E000 (e.g. 0xAE000).
*
* There should be a delay of ??? before reading back S502A status
* register.
*
* 4. S502E Notes:
*
* S502E has a h/w bug: although default IRQ line state is HIGH, enabling
* interrupts by setting bit 1 of the control register (BASE) to '1'
* causes it to go LOW! Therefore, disabling interrupts by setting that
* bit to '0' causes low-to-high transition on IRQ line (ghosty
* interrupt). The same occurs when disabling CPU by resetting bit 0 of
* CPU control register (BASE+3) - see the next note.
*
* S502E CPU and DPM control is limited:
*
* o CPU cannot be stopped independently. Resetting bit 0 of the CPUi
* control register (BASE+3) shuts the board down entirely, including
* DPM;
*
* o DPM access cannot be controlled dynamically. Ones CPU is started,
* bit 1 of the control register (BASE) is used to enable/disable IRQ,
* so that access to shared memory cannot be disabled while CPU is
* running.
****************************************************************************/
#define _LINUX_
#if defined(_LINUX_) /****** Linux *******************************/
#include <linux/config.h>
#include <linux/kernel.h> /* printk(), and other useful stuff */
#include <linux/stddef.h> /* offsetof(), etc. */
#include <linux/errno.h> /* return codes */
#include <linux/string.h> /* inline memset(), etc. */
#include <linux/module.h> /* support for loadable modules */
#include <linux/jiffies.h> /* for jiffies, HZ, etc. */
#include <linux/sdladrv.h> /* API definitions */
#include <linux/sdlasfm.h> /* SDLA firmware module definitions */
#include <linux/sdlapci.h> /* SDLA PCI hardware definitions */
#include <linux/pci.h> /* PCI defines and function prototypes */
#include <asm/io.h> /* for inb(), outb(), etc. */
#define _INB(port) (inb(port))
#define _OUTB(port, byte) (outb((byte),(port)))
#define SYSTEM_TICK jiffies
#include <linux/init.h>
#elif defined(_SCO_UNIX_) /****** SCO Unix ****************************/
#if !defined(INKERNEL)
#error This code MUST be compiled in kernel mode!
#endif
#include <sys/sdladrv.h> /* API definitions */
#include <sys/sdlasfm.h> /* SDLA firmware module definitions */
#include <sys/inline.h> /* for inb(), outb(), etc. */
#define _INB(port) (inb(port))
#define _OUTB(port, byte) (outb((port),(byte)))
#define SYSTEM_TICK lbolt
#else
#error Unknown system type!
#endif
#define MOD_VERSION 3
#define MOD_RELEASE 0
#define SDLA_IODELAY 100 /* I/O Rd/Wr delay, 10 works for 486DX2-66 */
#define EXEC_DELAY 20 /* shared memory access delay, mks */
#define EXEC_TIMEOUT (HZ*2) /* command timeout, in ticks */
/* I/O port address range */
#define S502A_IORANGE 3
#define S502E_IORANGE 4
#define S503_IORANGE 3
#define S507_IORANGE 4
#define S508_IORANGE 4
/* Maximum amount of memory */
#define S502_MAXMEM 0x10000L
#define S503_MAXMEM 0x10000L
#define S507_MAXMEM 0x40000L
#define S508_MAXMEM 0x40000L
/* Minimum amount of memory */
#define S502_MINMEM 0x8000L
#define S503_MINMEM 0x8000L
#define S507_MINMEM 0x20000L
#define S508_MINMEM 0x20000L
#define NO_PORT -1
/****** Function Prototypes *************************************************/
/* Hardware-specific functions */
static int sdla_detect (sdlahw_t* hw);
static int sdla_autodpm (sdlahw_t* hw);
static int sdla_setdpm (sdlahw_t* hw);
static int sdla_load (sdlahw_t* hw, sfm_t* sfm, unsigned len);
static int sdla_init (sdlahw_t* hw);
static unsigned long sdla_memtest (sdlahw_t* hw);
static int sdla_bootcfg (sdlahw_t* hw, sfm_info_t* sfminfo);
static unsigned char make_config_byte (sdlahw_t* hw);
static int sdla_start (sdlahw_t* hw, unsigned addr);
static int init_s502a (sdlahw_t* hw);
static int init_s502e (sdlahw_t* hw);
static int init_s503 (sdlahw_t* hw);
static int init_s507 (sdlahw_t* hw);
static int init_s508 (sdlahw_t* hw);
static int detect_s502a (int port);
static int detect_s502e (int port);
static int detect_s503 (int port);
static int detect_s507 (int port);
static int detect_s508 (int port);
static int detect_s514 (sdlahw_t* hw);
static int find_s514_adapter(sdlahw_t* hw, char find_first_S514_card);
/* Miscellaneous functions */
static void peek_by_4 (unsigned long src, void* buf, unsigned len);
static void poke_by_4 (unsigned long dest, void* buf, unsigned len);
static int calibrate_delay (int mks);
static int get_option_index (unsigned* optlist, unsigned optval);
static unsigned check_memregion (void* ptr, unsigned len);
static unsigned test_memregion (void* ptr, unsigned len);
static unsigned short checksum (unsigned char* buf, unsigned len);
static int init_pci_slot(sdlahw_t *);
static int pci_probe(sdlahw_t *hw);
/****** Global Data **********************************************************
* Note: All data must be explicitly initialized!!!
*/
static struct pci_device_id sdladrv_pci_tbl[] = {
{ V3_VENDOR_ID, V3_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(pci, sdladrv_pci_tbl);
MODULE_LICENSE("GPL");
/* private data */
static char modname[] = "sdladrv";
static char fullname[] = "SDLA Support Module";
static char copyright[] = "(c) 1995-1999 Sangoma Technologies Inc.";
static unsigned exec_idle;
/* Hardware configuration options.
* These are arrays of configuration options used by verification routines.
* The first element of each array is its size (i.e. number of options).
*/
static unsigned s502_port_options[] =
{ 4, 0x250, 0x300, 0x350, 0x360 }
;
static unsigned s503_port_options[] =
{ 8, 0x250, 0x254, 0x300, 0x304, 0x350, 0x354, 0x360, 0x364 }
;
static unsigned s508_port_options[] =
{ 8, 0x250, 0x270, 0x280, 0x300, 0x350, 0x360, 0x380, 0x390 }
;
static unsigned s502a_irq_options[] = { 0 };
static unsigned s502e_irq_options[] = { 4, 2, 3, 5, 7 };
static unsigned s503_irq_options[] = { 5, 2, 3, 4, 5, 7 };
static unsigned s508_irq_options[] = { 8, 3, 4, 5, 7, 10, 11, 12, 15 };
static unsigned s502a_dpmbase_options[] =
{
28,
0xA0000, 0xA2000, 0xA4000, 0xA6000, 0xA8000, 0xAA000, 0xAC000,
0xC0000, 0xC2000, 0xC4000, 0xC6000, 0xC8000, 0xCA000, 0xCC000,
0xD0000, 0xD2000, 0xD4000, 0xD6000, 0xD8000, 0xDA000, 0xDC000,
0xE0000, 0xE2000, 0xE4000, 0xE6000, 0xE8000, 0xEA000, 0xEC000,
};
static unsigned s507_dpmbase_options[] =
{
32,
0xA0000, 0xA2000, 0xA4000, 0xA6000, 0xA8000, 0xAA000, 0xAC000, 0xAE000,
0xB0000, 0xB2000, 0xB4000, 0xB6000, 0xB8000, 0xBA000, 0xBC000, 0xBE000,
0xC0000, 0xC2000, 0xC4000, 0xC6000, 0xC8000, 0xCA000, 0xCC000, 0xCE000,
0xE0000, 0xE2000, 0xE4000, 0xE6000, 0xE8000, 0xEA000, 0xEC000, 0xEE000,
};
static unsigned s508_dpmbase_options[] = /* incl. S502E and S503 */
{
32,
0xA0000, 0xA2000, 0xA4000, 0xA6000, 0xA8000, 0xAA000, 0xAC000, 0xAE000,
0xC0000, 0xC2000, 0xC4000, 0xC6000, 0xC8000, 0xCA000, 0xCC000, 0xCE000,
0xD0000, 0xD2000, 0xD4000, 0xD6000, 0xD8000, 0xDA000, 0xDC000, 0xDE000,
0xE0000, 0xE2000, 0xE4000, 0xE6000, 0xE8000, 0xEA000, 0xEC000, 0xEE000,
};
/*
static unsigned s502_dpmsize_options[] = { 2, 0x2000, 0x10000 };
static unsigned s507_dpmsize_options[] = { 2, 0x2000, 0x4000 };
static unsigned s508_dpmsize_options[] = { 1, 0x2000 };
*/
static unsigned s502a_pclk_options[] = { 2, 3600, 7200 };
static unsigned s502e_pclk_options[] = { 5, 3600, 5000, 7200, 8000, 10000 };
static unsigned s503_pclk_options[] = { 3, 7200, 8000, 10000 };
static unsigned s507_pclk_options[] = { 1, 12288 };
static unsigned s508_pclk_options[] = { 1, 16000 };
/* Host memory control register masks */
static unsigned char s502a_hmcr[] =
{
0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, /* A0000 - AC000 */
0x20, 0x22, 0x24, 0x26, 0x28, 0x2A, 0x2C, /* C0000 - CC000 */
0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, /* D0000 - DC000 */
0x30, 0x32, 0x34, 0x36, 0x38, 0x3A, 0x3C, /* E0000 - EC000 */
};
static unsigned char s502e_hmcr[] =
{
0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E, /* A0000 - AE000 */
0x20, 0x22, 0x24, 0x26, 0x28, 0x2A, 0x2C, 0x2E, /* C0000 - CE000 */
0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, /* D0000 - DE000 */
0x30, 0x32, 0x34, 0x36, 0x38, 0x3A, 0x3C, 0x3E, /* E0000 - EE000 */
};
static unsigned char s507_hmcr[] =
{
0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, /* A0000 - AE000 */
0x40, 0x42, 0x44, 0x46, 0x48, 0x4A, 0x4C, 0x4E, /* B0000 - BE000 */
0x80, 0x82, 0x84, 0x86, 0x88, 0x8A, 0x8C, 0x8E, /* C0000 - CE000 */
0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE, /* E0000 - EE000 */
};
static unsigned char s508_hmcr[] =
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* A0000 - AE000 */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* C0000 - CE000 */
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* D0000 - DE000 */
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, /* E0000 - EE000 */
};
static unsigned char s507_irqmask[] =
{
0x00, 0x20, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0xE0
};
static int pci_slot_ar[MAX_S514_CARDS];
/******* Kernel Loadable Module Entry Points ********************************/
/*============================================================================
* Module 'insert' entry point.
* o print announcement
* o initialize static data
* o calibrate SDLA shared memory access delay.
*
* Return: 0 Ok
* < 0 error.
* Context: process
*/
static int __init sdladrv_init(void)
{
int i=0;
printk(KERN_INFO "%s v%u.%u %s\n",
fullname, MOD_VERSION, MOD_RELEASE, copyright);
exec_idle = calibrate_delay(EXEC_DELAY);
#ifdef WANDEBUG
printk(KERN_DEBUG "%s: exec_idle = %d\n", modname, exec_idle);
#endif
/* Initialize the PCI Card array, which
* will store flags, used to mark
* card initialization state */
for (i=0; i<MAX_S514_CARDS; i++)
pci_slot_ar[i] = 0xFF;
return 0;
}
/*============================================================================
* Module 'remove' entry point.
* o release all remaining system resources
*/
static void __exit sdladrv_cleanup(void)
{
}
module_init(sdladrv_init);
module_exit(sdladrv_cleanup);
/******* Kernel APIs ********************************************************/
/*============================================================================
* Set up adapter.
* o detect adapter type
* o verify hardware configuration options
* o check for hardware conflicts
* o set up adapter shared memory
* o test adapter memory
* o load firmware
* Return: 0 ok.
* < 0 error
*/
EXPORT_SYMBOL(sdla_setup);
int sdla_setup (sdlahw_t* hw, void* sfm, unsigned len)
{
unsigned* irq_opt = NULL; /* IRQ options */
unsigned* dpmbase_opt = NULL; /* DPM window base options */
unsigned* pclk_opt = NULL; /* CPU clock rate options */
int err=0;
if (sdla_detect(hw)) {
if(hw->type != SDLA_S514)
printk(KERN_INFO "%s: no SDLA card found at port 0x%X\n",
modname, hw->port);
return -EINVAL;
}
if(hw->type != SDLA_S514) {
printk(KERN_INFO "%s: found S%04u card at port 0x%X.\n",
modname, hw->type, hw->port);
hw->dpmsize = SDLA_WINDOWSIZE;
switch (hw->type) {
case SDLA_S502A:
hw->io_range = S502A_IORANGE;
irq_opt = s502a_irq_options;
dpmbase_opt = s502a_dpmbase_options;
pclk_opt = s502a_pclk_options;
break;
case SDLA_S502E:
hw->io_range = S502E_IORANGE;
irq_opt = s502e_irq_options;
dpmbase_opt = s508_dpmbase_options;
pclk_opt = s502e_pclk_options;
break;
case SDLA_S503:
hw->io_range = S503_IORANGE;
irq_opt = s503_irq_options;
dpmbase_opt = s508_dpmbase_options;
pclk_opt = s503_pclk_options;
break;
case SDLA_S507:
hw->io_range = S507_IORANGE;
irq_opt = s508_irq_options;
dpmbase_opt = s507_dpmbase_options;
pclk_opt = s507_pclk_options;
break;
case SDLA_S508:
hw->io_range = S508_IORANGE;
irq_opt = s508_irq_options;
dpmbase_opt = s508_dpmbase_options;
pclk_opt = s508_pclk_options;
break;
}
/* Verify IRQ configuration options */
if (!get_option_index(irq_opt, hw->irq)) {
printk(KERN_INFO "%s: IRQ %d is invalid!\n",
modname, hw->irq);
return -EINVAL;
}
/* Verify CPU clock rate configuration options */
if (hw->pclk == 0)
hw->pclk = pclk_opt[1]; /* use default */
else if (!get_option_index(pclk_opt, hw->pclk)) {
printk(KERN_INFO "%s: CPU clock %u is invalid!\n",
modname, hw->pclk);
return -EINVAL;
}
printk(KERN_INFO "%s: assuming CPU clock rate of %u kHz.\n",
modname, hw->pclk);
/* Setup adapter dual-port memory window and test memory */
if (hw->dpmbase == 0) {
err = sdla_autodpm(hw);
if (err) {
printk(KERN_INFO
"%s: can't find available memory region!\n",
modname);
return err;
}
}
else if (!get_option_index(dpmbase_opt,
virt_to_phys(hw->dpmbase))) {
printk(KERN_INFO
"%s: memory address 0x%lX is invalid!\n",
modname, virt_to_phys(hw->dpmbase));
return -EINVAL;
}
else if (sdla_setdpm(hw)) {
printk(KERN_INFO
"%s: 8K memory region at 0x%lX is not available!\n",
modname, virt_to_phys(hw->dpmbase));
return -EINVAL;
}
printk(KERN_INFO
"%s: dual-port memory window is set at 0x%lX.\n",
modname, virt_to_phys(hw->dpmbase));
/* If we find memory in 0xE**** Memory region,
* warn the user to disable the SHADOW RAM.
* Since memory corruption can occur if SHADOW is
* enabled. This can causes random crashes ! */
if (virt_to_phys(hw->dpmbase) >= 0xE0000){
printk(KERN_WARNING "\n%s: !!!!!!!! WARNING !!!!!!!!\n",modname);
printk(KERN_WARNING "%s: WANPIPE is using 0x%lX memory region !!!\n",
modname, virt_to_phys(hw->dpmbase));
printk(KERN_WARNING " Please disable the SHADOW RAM, otherwise\n");
printk(KERN_WARNING " your system might crash randomly from time to time !\n");
printk(KERN_WARNING "%s: !!!!!!!! WARNING !!!!!!!!\n\n",modname);
}
}
else {
hw->memory = test_memregion((void*)hw->dpmbase,
MAX_SIZEOF_S514_MEMORY);
if(hw->memory < (256 * 1024)) {
printk(KERN_INFO
"%s: error in testing S514 memory (0x%lX)\n",
modname, hw->memory);
sdla_down(hw);
return -EINVAL;
}
}
printk(KERN_INFO "%s: found %luK bytes of on-board memory\n",
modname, hw->memory / 1024);
/* Load firmware. If loader fails then shut down adapter */
err = sdla_load(hw, sfm, len);
if (err) sdla_down(hw); /* shutdown adapter */
return err;
}
/*============================================================================
* Shut down SDLA: disable shared memory access and interrupts, stop CPU, etc.
*/
EXPORT_SYMBOL(sdla_down);
int sdla_down (sdlahw_t* hw)
{
unsigned port = hw->port;
int i;
unsigned char CPU_no;
u32 int_config, int_status;
if(!port && (hw->type != SDLA_S514))
return -EFAULT;
switch (hw->type) {
case SDLA_S502A:
_OUTB(port, 0x08); /* halt CPU */
_OUTB(port, 0x08);
_OUTB(port, 0x08);
hw->regs[0] = 0x08;
_OUTB(port + 1, 0xFF); /* close memory window */
hw->regs[1] = 0xFF;
break;
case SDLA_S502E:
_OUTB(port + 3, 0); /* stop CPU */
_OUTB(port, 0); /* reset board */
for (i = 0; i < S502E_IORANGE; ++i)
hw->regs[i] = 0
;
break;
case SDLA_S503:
case SDLA_S507:
case SDLA_S508:
_OUTB(port, 0); /* reset board logic */
hw->regs[0] = 0;
break;
case SDLA_S514:
/* halt the adapter */
*(char *)hw->vector = S514_CPU_HALT;
CPU_no = hw->S514_cpu_no[0];
/* disable the PCI IRQ and disable memory access */
pci_read_config_dword(hw->pci_dev, PCI_INT_CONFIG, &int_config);
int_config &= (CPU_no == S514_CPU_A) ? ~PCI_DISABLE_IRQ_CPU_A : ~PCI_DISABLE_IRQ_CPU_B;
pci_write_config_dword(hw->pci_dev, PCI_INT_CONFIG, int_config);
read_S514_int_stat(hw, &int_status);
S514_intack(hw, int_status);
if(CPU_no == S514_CPU_A)
pci_write_config_dword(hw->pci_dev, PCI_MAP0_DWORD,
PCI_CPU_A_MEM_DISABLE);
else
pci_write_config_dword(hw->pci_dev, PCI_MAP1_DWORD,
PCI_CPU_B_MEM_DISABLE);
/* free up the allocated virtual memory */
iounmap((void *)hw->dpmbase);
iounmap((void *)hw->vector);
break;
default:
return -EINVAL;
}
return 0;
}
/*============================================================================
* Map shared memory window into SDLA address space.
*/
EXPORT_SYMBOL(sdla_mapmem);
int sdla_mapmem (sdlahw_t* hw, unsigned long addr)
{
unsigned port = hw->port;
register int tmp;
switch (hw->type) {
case SDLA_S502A:
case SDLA_S502E:
if (addr < S502_MAXMEM) { /* verify parameter */
tmp = addr >> 13; /* convert to register mask */
_OUTB(port + 2, tmp);
hw->regs[2] = tmp;
}
else return -EINVAL;
break;
case SDLA_S503:
if (addr < S503_MAXMEM) { /* verify parameter */
tmp = (hw->regs[0] & 0x8F) | ((addr >> 9) & 0x70);
_OUTB(port, tmp);
hw->regs[0] = tmp;
}
else return -EINVAL;
break;
case SDLA_S507:
if (addr < S507_MAXMEM) {
if (!(_INB(port) & 0x02))
return -EIO;
tmp = addr >> 13; /* convert to register mask */
_OUTB(port + 2, tmp);
hw->regs[2] = tmp;
}
else return -EINVAL;
break;
case SDLA_S508:
if (addr < S508_MAXMEM) {
tmp = addr >> 13; /* convert to register mask */
_OUTB(port + 2, tmp);
hw->regs[2] = tmp;
}
else return -EINVAL;
break;
case SDLA_S514:
return 0;
default:
return -EINVAL;
}
hw->vector = addr & 0xFFFFE000L;
return 0;
}
/*============================================================================
* Enable interrupt generation.
*/
static int sdla_inten (sdlahw_t* hw)
{
unsigned port = hw->port;
int tmp, i;
switch (hw->type) {
case SDLA_S502E:
/* Note thar interrupt control operations on S502E are allowed
* only if CPU is enabled (bit 0 of status register is set).
*/
if (_INB(port) & 0x01) {
_OUTB(port, 0x02); /* bit1 = 1, bit2 = 0 */
_OUTB(port, 0x06); /* bit1 = 1, bit2 = 1 */
hw->regs[0] = 0x06;
}
else return -EIO;
break;
case SDLA_S503:
tmp = hw->regs[0] | 0x04;
_OUTB(port, tmp);
hw->regs[0] = tmp; /* update mirror */
for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
if (!(_INB(port) & 0x02)) /* verify */
return -EIO;
break;
case SDLA_S508:
tmp = hw->regs[0] | 0x10;
_OUTB(port, tmp);
hw->regs[0] = tmp; /* update mirror */
for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
if (!(_INB(port + 1) & 0x10)) /* verify */
return -EIO;
break;
case SDLA_S502A:
case SDLA_S507:
break;
case SDLA_S514:
break;
default:
return -EINVAL;
}
return 0;
}
/*============================================================================
* Disable interrupt generation.
*/
#if 0
int sdla_intde (sdlahw_t* hw)
{
unsigned port = hw->port;
int tmp, i;
switch (hw->type) {
case SDLA_S502E:
/* Notes:
* 1) interrupt control operations are allowed only if CPU is
* enabled (bit 0 of status register is set).
* 2) disabling interrupts using bit 1 of control register
* causes IRQ line go high, therefore we are going to use
* 0x04 instead: lower it to inhibit interrupts to PC.
*/
if (_INB(port) & 0x01) {
_OUTB(port, hw->regs[0] & ~0x04);
hw->regs[0] &= ~0x04;
}
else return -EIO;
break;
case SDLA_S503:
tmp = hw->regs[0] & ~0x04;
_OUTB(port, tmp);
hw->regs[0] = tmp; /* update mirror */
for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
if (_INB(port) & 0x02) /* verify */
return -EIO;
break;
case SDLA_S508:
tmp = hw->regs[0] & ~0x10;
_OUTB(port, tmp);
hw->regs[0] = tmp; /* update mirror */
for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
if (_INB(port) & 0x10) /* verify */
return -EIO;
break;
case SDLA_S502A:
case SDLA_S507:
break;
default:
return -EINVAL;
}
return 0;
}
#endif /* 0 */
/*============================================================================
* Acknowledge SDLA hardware interrupt.
*/
static int sdla_intack (sdlahw_t* hw)
{
unsigned port = hw->port;
int tmp;
switch (hw->type) {
case SDLA_S502E:
/* To acknoledge hardware interrupt we have to toggle bit 3 of
* control register: \_/
* Note that interrupt control operations on S502E are allowed
* only if CPU is enabled (bit 1 of status register is set).
*/
if (_INB(port) & 0x01) {
tmp = hw->regs[0] & ~0x04;
_OUTB(port, tmp);
tmp |= 0x04;
_OUTB(port, tmp);
hw->regs[0] = tmp;
}
else return -EIO;
break;
case SDLA_S503:
if (_INB(port) & 0x04) {
tmp = hw->regs[0] & ~0x08;
_OUTB(port, tmp);
tmp |= 0x08;
_OUTB(port, tmp);
hw->regs[0] = tmp;
}
break;
case SDLA_S502A:
case SDLA_S507:
case SDLA_S508:
break;
default:
return -EINVAL;
}
return 0;
}
/*============================================================================
* Acknowledge S514 hardware interrupt.
*/
EXPORT_SYMBOL(S514_intack);
void S514_intack (sdlahw_t* hw, u32 int_status)
{
pci_write_config_dword(hw->pci_dev, PCI_INT_STATUS, int_status);
}
/*============================================================================
* Read the S514 hardware interrupt status.
*/
EXPORT_SYMBOL(read_S514_int_stat);
void read_S514_int_stat (sdlahw_t* hw, u32* int_status)
{
pci_read_config_dword(hw->pci_dev, PCI_INT_STATUS, int_status);
}
/*============================================================================
* Generate an interrupt to adapter's CPU.
*/
#if 0
int sdla_intr (sdlahw_t* hw)
{
unsigned port = hw->port;
switch (hw->type) {
case SDLA_S502A:
if (!(_INB(port) & 0x40)) {
_OUTB(port, 0x10); /* issue NMI to CPU */
hw->regs[0] = 0x10;
}
else return -EIO;
break;
case SDLA_S507:
if ((_INB(port) & 0x06) == 0x06) {
_OUTB(port + 3, 0);
}
else return -EIO;
break;
case SDLA_S508:
if (_INB(port + 1) & 0x02) {
_OUTB(port, 0x08);
}
else return -EIO;
break;
case SDLA_S502E:
case SDLA_S503:
default:
return -EINVAL;
}
return 0;
}
#endif /* 0 */
/*============================================================================
* Execute Adapter Command.
* o Set exec flag.
* o Busy-wait until flag is reset.
* o Return number of loops made, or 0 if command timed out.
*/
EXPORT_SYMBOL(sdla_exec);
int sdla_exec (void* opflag)
{
volatile unsigned char* flag = opflag;
unsigned long tstop;
int nloops;
if(readb(flag) != 0x00) {
printk(KERN_INFO
"WANPIPE: opp flag set on entry to sdla_exec\n");
return 0;
}
writeb(0x01, flag);
tstop = SYSTEM_TICK + EXEC_TIMEOUT;
for (nloops = 1; (readb(flag) == 0x01); ++ nloops) {
unsigned delay = exec_idle;
while (-- delay); /* delay */
if (SYSTEM_TICK > tstop) return 0; /* time is up! */
}
return nloops;
}
/*============================================================================
* Read absolute adapter memory.
* Transfer data from adapter's memory to data buffer.
*
* Note:
* Care should be taken when crossing dual-port memory window boundary.
* This function is not atomic, so caller must disable interrupt if
* interrupt routines are accessing adapter shared memory.
*/
EXPORT_SYMBOL(sdla_peek);
int sdla_peek (sdlahw_t* hw, unsigned long addr, void* buf, unsigned len)
{
if (addr + len > hw->memory) /* verify arguments */
return -EINVAL;
if(hw->type == SDLA_S514) { /* copy data for the S514 adapter */
peek_by_4 ((unsigned long)hw->dpmbase + addr, buf, len);
return 0;
}
else { /* copy data for the S508 adapter */
unsigned long oldvec = hw->vector;
unsigned winsize = hw->dpmsize;
unsigned curpos, curlen; /* current offset and block size */
unsigned long curvec; /* current DPM window vector */
int err = 0;
while (len && !err) {
curpos = addr % winsize; /* current window offset */
curvec = addr - curpos; /* current window vector */
curlen = (len > (winsize - curpos)) ?
(winsize - curpos) : len;
/* Relocate window and copy block of data */
err = sdla_mapmem(hw, curvec);
peek_by_4 ((unsigned long)hw->dpmbase + curpos, buf,
curlen);
addr += curlen;
buf = (char*)buf + curlen;
len -= curlen;
}
/* Restore DPM window position */
sdla_mapmem(hw, oldvec);
return err;
}
}
/*============================================================================
* Read data from adapter's memory to a data buffer in 4-byte chunks.
* Note that we ensure that the SDLA memory address is on a 4-byte boundary
* before we begin moving the data in 4-byte chunks.
*/
static void peek_by_4 (unsigned long src, void* buf, unsigned len)
{
/* byte copy data until we get to a 4-byte boundary */
while (len && (src & 0x03)) {
*(char *)buf ++ = readb(src ++);
len --;
}
/* copy data in 4-byte chunks */
while (len >= 4) {
*(unsigned long *)buf = readl(src);
buf += 4;
src += 4;
len -= 4;
}
/* byte copy any remaining data */
while (len) {
*(char *)buf ++ = readb(src ++);
len --;
}
}
/*============================================================================
* Write Absolute Adapter Memory.
* Transfer data from data buffer to adapter's memory.
*
* Note:
* Care should be taken when crossing dual-port memory window boundary.
* This function is not atomic, so caller must disable interrupt if
* interrupt routines are accessing adapter shared memory.
*/
EXPORT_SYMBOL(sdla_poke);
int sdla_poke (sdlahw_t* hw, unsigned long addr, void* buf, unsigned len)
{
if (addr + len > hw->memory) /* verify arguments */
return -EINVAL;
if(hw->type == SDLA_S514) { /* copy data for the S514 adapter */
poke_by_4 ((unsigned long)hw->dpmbase + addr, buf, len);
return 0;
}
else { /* copy data for the S508 adapter */
unsigned long oldvec = hw->vector;
unsigned winsize = hw->dpmsize;
unsigned curpos, curlen; /* current offset and block size */
unsigned long curvec; /* current DPM window vector */
int err = 0;
while (len && !err) {
curpos = addr % winsize; /* current window offset */
curvec = addr - curpos; /* current window vector */
curlen = (len > (winsize - curpos)) ?
(winsize - curpos) : len;
/* Relocate window and copy block of data */
sdla_mapmem(hw, curvec);
poke_by_4 ((unsigned long)hw->dpmbase + curpos, buf,
curlen);
addr += curlen;
buf = (char*)buf + curlen;
len -= curlen;
}
/* Restore DPM window position */
sdla_mapmem(hw, oldvec);
return err;
}
}
/*============================================================================
* Write from a data buffer to adapter's memory in 4-byte chunks.
* Note that we ensure that the SDLA memory address is on a 4-byte boundary
* before we begin moving the data in 4-byte chunks.
*/
static void poke_by_4 (unsigned long dest, void* buf, unsigned len)
{
/* byte copy data until we get to a 4-byte boundary */
while (len && (dest & 0x03)) {
writeb (*(char *)buf ++, dest ++);
len --;
}
/* copy data in 4-byte chunks */
while (len >= 4) {
writel (*(unsigned long *)buf, dest);
dest += 4;
buf += 4;
len -= 4;
}
/* byte copy any remaining data */
while (len) {
writeb (*(char *)buf ++ , dest ++);
len --;
}
}
#ifdef DONT_COMPIPLE_THIS
#endif /* DONT_COMPIPLE_THIS */
/****** Hardware-Specific Functions *****************************************/
/*============================================================================
* Detect adapter type.
* o if adapter type is specified then call detection routine for that adapter
* type. Otherwise call detection routines for every adapter types until
* adapter is detected.
*
* Notes:
* 1) Detection tests are destructive! Adapter will be left in shutdown state
* after the test.
*/
static int sdla_detect (sdlahw_t* hw)
{
unsigned port = hw->port;
int err = 0;
if (!port && (hw->type != SDLA_S514))
return -EFAULT;
switch (hw->type) {
case SDLA_S502A:
if (!detect_s502a(port)) err = -ENODEV;
break;
case SDLA_S502E:
if (!detect_s502e(port)) err = -ENODEV;
break;
case SDLA_S503:
if (!detect_s503(port)) err = -ENODEV;
break;
case SDLA_S507:
if (!detect_s507(port)) err = -ENODEV;
break;
case SDLA_S508:
if (!detect_s508(port)) err = -ENODEV;
break;
case SDLA_S514:
if (!detect_s514(hw)) err = -ENODEV;
break;
default:
if (detect_s502a(port))
hw->type = SDLA_S502A;
else if (detect_s502e(port))
hw->type = SDLA_S502E;
else if (detect_s503(port))
hw->type = SDLA_S503;
else if (detect_s507(port))
hw->type = SDLA_S507;
else if (detect_s508(port))
hw->type = SDLA_S508;
else err = -ENODEV;
}
return err;
}
/*============================================================================
* Autoselect memory region.
* o try all available DMP address options from the top down until success.
*/
static int sdla_autodpm (sdlahw_t* hw)
{
int i, err = -EINVAL;
unsigned* opt;
switch (hw->type) {
case SDLA_S502A:
opt = s502a_dpmbase_options;
break;
case SDLA_S502E:
case SDLA_S503:
case SDLA_S508:
opt = s508_dpmbase_options;
break;
case SDLA_S507:
opt = s507_dpmbase_options;
break;
default:
return -EINVAL;
}
/* Start testing from 8th position, address
* 0xC8000 from the 508 address table.
* We don't want to test A**** addresses, since
* they are usually used for Video */
for (i = 8; i <= opt[0] && err; i++) {
hw->dpmbase = phys_to_virt(opt[i]);
err = sdla_setdpm(hw);
}
return err;
}
/*============================================================================
* Set up adapter dual-port memory window.
* o shut down adapter
* o make sure that no physical memory exists in this region, i.e entire
* region reads 0xFF and is not writable when adapter is shut down.
* o initialize adapter hardware
* o make sure that region is usable with SDLA card, i.e. we can write to it
* when adapter is configured.
*/
static int sdla_setdpm (sdlahw_t* hw)
{
int err;
/* Shut down card and verify memory region */
sdla_down(hw);
if (check_memregion(hw->dpmbase, hw->dpmsize))
return -EINVAL;
/* Initialize adapter and test on-board memory segment by segment.
* If memory size appears to be less than shared memory window size,
* assume that memory region is unusable.
*/
err = sdla_init(hw);
if (err) return err;
if (sdla_memtest(hw) < hw->dpmsize) { /* less than window size */
sdla_down(hw);
return -EIO;
}
sdla_mapmem(hw, 0L); /* set window vector at bottom */
return 0;
}
/*============================================================================
* Load adapter from the memory image of the SDLA firmware module.
* o verify firmware integrity and compatibility
* o start adapter up
*/
static int sdla_load (sdlahw_t* hw, sfm_t* sfm, unsigned len)
{
int i;
/* Verify firmware signature */
if (strcmp(sfm->signature, SFM_SIGNATURE)) {
printk(KERN_INFO "%s: not SDLA firmware!\n",
modname);
return -EINVAL;
}
/* Verify firmware module format version */
if (sfm->version != SFM_VERSION) {
printk(KERN_INFO
"%s: firmware format %u rejected! Expecting %u.\n",
modname, sfm->version, SFM_VERSION);
return -EINVAL;
}
/* Verify firmware module length and checksum */
if ((len - offsetof(sfm_t, image) != sfm->info.codesize) ||
(checksum((void*)&sfm->info,
sizeof(sfm_info_t) + sfm->info.codesize) != sfm->checksum)) {
printk(KERN_INFO "%s: firmware corrupted!\n", modname);
return -EINVAL;
}
/* Announce */
printk(KERN_INFO "%s: loading %s (ID=%u)...\n", modname,
(sfm->descr[0] != '\0') ? sfm->descr : "unknown firmware",
sfm->info.codeid);
if(hw->type == SDLA_S514)
printk(KERN_INFO "%s: loading S514 adapter, CPU %c\n",
modname, hw->S514_cpu_no[0]);
/* Scan through the list of compatible adapters and make sure our
* adapter type is listed.
*/
for (i = 0;
(i < SFM_MAX_SDLA) && (sfm->info.adapter[i] != hw->type);
++i);
if (i == SFM_MAX_SDLA) {
printk(KERN_INFO "%s: firmware is not compatible with S%u!\n",
modname, hw->type);
return -EINVAL;
}
/* Make sure there is enough on-board memory */
if (hw->memory < sfm->info.memsize) {
printk(KERN_INFO
"%s: firmware needs %lu bytes of on-board memory!\n",
modname, sfm->info.memsize);
return -EINVAL;
}
/* Move code onto adapter */
if (sdla_poke(hw, sfm->info.codeoffs, sfm->image, sfm->info.codesize)) {
printk(KERN_INFO "%s: failed to load code segment!\n",
modname);
return -EIO;
}
/* Prepare boot-time configuration data and kick-off CPU */
sdla_bootcfg(hw, &sfm->info);
if (sdla_start(hw, sfm->info.startoffs)) {
printk(KERN_INFO "%s: Damn... Adapter won't start!\n",
modname);
return -EIO;
}
/* position DPM window over the mailbox and enable interrupts */
if (sdla_mapmem(hw, sfm->info.winoffs) || sdla_inten(hw)) {
printk(KERN_INFO "%s: adapter hardware failure!\n",
modname);
return -EIO;
}
hw->fwid = sfm->info.codeid; /* set firmware ID */
return 0;
}
/*============================================================================
* Initialize SDLA hardware: setup memory window, IRQ, etc.
*/
static int sdla_init (sdlahw_t* hw)
{
int i;
for (i = 0; i < SDLA_MAXIORANGE; ++i)
hw->regs[i] = 0;
switch (hw->type) {
case SDLA_S502A: return init_s502a(hw);
case SDLA_S502E: return init_s502e(hw);
case SDLA_S503: return init_s503(hw);
case SDLA_S507: return init_s507(hw);
case SDLA_S508: return init_s508(hw);
}
return -EINVAL;
}
/*============================================================================
* Test adapter on-board memory.
* o slide DPM window from the bottom up and test adapter memory segment by
* segment.
* Return adapter memory size.
*/
static unsigned long sdla_memtest (sdlahw_t* hw)
{
unsigned long memsize;
unsigned winsize;
for (memsize = 0, winsize = hw->dpmsize;
!sdla_mapmem(hw, memsize) &&
(test_memregion(hw->dpmbase, winsize) == winsize)
;
memsize += winsize)
;
hw->memory = memsize;
return memsize;
}
/*============================================================================
* Prepare boot-time firmware configuration data.
* o position DPM window
* o initialize configuration data area
*/
static int sdla_bootcfg (sdlahw_t* hw, sfm_info_t* sfminfo)
{
unsigned char* data;
if (!sfminfo->datasize) return 0; /* nothing to do */
if (sdla_mapmem(hw, sfminfo->dataoffs) != 0)
return -EIO;
if(hw->type == SDLA_S514)
data = (void*)(hw->dpmbase + sfminfo->dataoffs);
else
data = (void*)((u8 *)hw->dpmbase +
(sfminfo->dataoffs - hw->vector));
memset_io (data, 0, sfminfo->datasize);
writeb (make_config_byte(hw), &data[0x00]);
switch (sfminfo->codeid) {
case SFID_X25_502:
case SFID_X25_508:
writeb (3, &data[0x01]); /* T1 timer */
writeb (10, &data[0x03]); /* N2 */
writeb (7, &data[0x06]); /* HDLC window size */
writeb (1, &data[0x0B]); /* DTE */
writeb (2, &data[0x0C]); /* X.25 packet window size */
writew (128, &data[0x0D]); /* default X.25 data size */
writew (128, &data[0x0F]); /* maximum X.25 data size */
break;
}
return 0;
}
/*============================================================================
* Prepare configuration byte identifying adapter type and CPU clock rate.
*/
static unsigned char make_config_byte (sdlahw_t* hw)
{
unsigned char byte = 0;
switch (hw->pclk) {
case 5000: byte = 0x01; break;
case 7200: byte = 0x02; break;
case 8000: byte = 0x03; break;
case 10000: byte = 0x04; break;
case 16000: byte = 0x05; break;
}
switch (hw->type) {
case SDLA_S502E: byte |= 0x80; break;
case SDLA_S503: byte |= 0x40; break;
}
return byte;
}
/*============================================================================
* Start adapter's CPU.
* o calculate a pointer to adapter's cold boot entry point
* o position DPM window
* o place boot instruction (jp addr) at cold boot entry point
* o start CPU
*/
static int sdla_start (sdlahw_t* hw, unsigned addr)
{
unsigned port = hw->port;
unsigned char *bootp;
int err, tmp, i;
if (!port && (hw->type != SDLA_S514)) return -EFAULT;
switch (hw->type) {
case SDLA_S502A:
bootp = hw->dpmbase;
bootp += 0x66;
break;
case SDLA_S502E:
case SDLA_S503:
case SDLA_S507:
case SDLA_S508:
case SDLA_S514:
bootp = hw->dpmbase;
break;
default:
return -EINVAL;
}
err = sdla_mapmem(hw, 0);
if (err) return err;
writeb (0xC3, bootp); /* Z80: 'jp' opcode */
bootp ++;
writew (addr, bootp);
switch (hw->type) {
case SDLA_S502A:
_OUTB(port, 0x10); /* issue NMI to CPU */
hw->regs[0] = 0x10;
break;
case SDLA_S502E:
_OUTB(port + 3, 0x01); /* start CPU */
hw->regs[3] = 0x01;
for (i = 0; i < SDLA_IODELAY; ++i);
if (_INB(port) & 0x01) { /* verify */
/*
* Enabling CPU changes functionality of the
* control register, so we have to reset its
* mirror.
*/
_OUTB(port, 0); /* disable interrupts */
hw->regs[0] = 0;
}
else return -EIO;
break;
case SDLA_S503:
tmp = hw->regs[0] | 0x09; /* set bits 0 and 3 */
_OUTB(port, tmp);
hw->regs[0] = tmp; /* update mirror */
for (i = 0; i < SDLA_IODELAY; ++i);
if (!(_INB(port) & 0x01)) /* verify */
return -EIO;
break;
case SDLA_S507:
tmp = hw->regs[0] | 0x02;
_OUTB(port, tmp);
hw->regs[0] = tmp; /* update mirror */
for (i = 0; i < SDLA_IODELAY; ++i);
if (!(_INB(port) & 0x04)) /* verify */
return -EIO;
break;
case SDLA_S508:
tmp = hw->regs[0] | 0x02;
_OUTB(port, tmp);
hw->regs[0] = tmp; /* update mirror */
for (i = 0; i < SDLA_IODELAY; ++i);
if (!(_INB(port + 1) & 0x02)) /* verify */
return -EIO;
break;
case SDLA_S514:
writeb (S514_CPU_START, hw->vector);
break;
default:
return -EINVAL;
}
return 0;
}
/*============================================================================
* Initialize S502A adapter.
*/
static int init_s502a (sdlahw_t* hw)
{
unsigned port = hw->port;
int tmp, i;
if (!detect_s502a(port))
return -ENODEV;
hw->regs[0] = 0x08;
hw->regs[1] = 0xFF;
/* Verify configuration options */
i = get_option_index(s502a_dpmbase_options, virt_to_phys(hw->dpmbase));
if (i == 0)
return -EINVAL;
tmp = s502a_hmcr[i - 1];
switch (hw->dpmsize) {
case 0x2000:
tmp |= 0x01;
break;
case 0x10000L:
break;
default:
return -EINVAL;
}
/* Setup dual-port memory window (this also enables memory access) */
_OUTB(port + 1, tmp);
hw->regs[1] = tmp;
hw->regs[0] = 0x08;
return 0;
}
/*============================================================================
* Initialize S502E adapter.
*/
static int init_s502e (sdlahw_t* hw)
{
unsigned port = hw->port;
int tmp, i;
if (!detect_s502e(port))
return -ENODEV;
/* Verify configuration options */
i = get_option_index(s508_dpmbase_options, virt_to_phys(hw->dpmbase));
if (i == 0)
return -EINVAL;
tmp = s502e_hmcr[i - 1];
switch (hw->dpmsize) {
case 0x2000:
tmp |= 0x01;
break;
case 0x10000L:
break;
default:
return -EINVAL;
}
/* Setup dual-port memory window */
_OUTB(port + 1, tmp);
hw->regs[1] = tmp;
/* Enable memory access */
_OUTB(port, 0x02);
hw->regs[0] = 0x02;
for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
return (_INB(port) & 0x02) ? 0 : -EIO;
}
/*============================================================================
* Initialize S503 adapter.
* ---------------------------------------------------------------------------
*/
static int init_s503 (sdlahw_t* hw)
{
unsigned port = hw->port;
int tmp, i;
if (!detect_s503(port))
return -ENODEV;
/* Verify configuration options */
i = get_option_index(s508_dpmbase_options, virt_to_phys(hw->dpmbase));
if (i == 0)
return -EINVAL;
tmp = s502e_hmcr[i - 1];
switch (hw->dpmsize) {
case 0x2000:
tmp |= 0x01;
break;
case 0x10000L:
break;
default:
return -EINVAL;
}
/* Setup dual-port memory window */
_OUTB(port + 1, tmp);
hw->regs[1] = tmp;
/* Enable memory access */
_OUTB(port, 0x02);
hw->regs[0] = 0x02; /* update mirror */
return 0;
}
/*============================================================================
* Initialize S507 adapter.
*/
static int init_s507 (sdlahw_t* hw)
{
unsigned port = hw->port;
int tmp, i;
if (!detect_s507(port))
return -ENODEV;
/* Verify configuration options */
i = get_option_index(s507_dpmbase_options, virt_to_phys(hw->dpmbase));
if (i == 0)
return -EINVAL;
tmp = s507_hmcr[i - 1];
switch (hw->dpmsize) {
case 0x2000:
tmp |= 0x01;
break;
case 0x10000L:
break;
default:
return -EINVAL;
}
/* Enable adapter's logic */
_OUTB(port, 0x01);
hw->regs[0] = 0x01;
for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
if (!(_INB(port) & 0x20))
return -EIO;
/* Setup dual-port memory window */
_OUTB(port + 1, tmp);
hw->regs[1] = tmp;
/* Enable memory access */
tmp = hw->regs[0] | 0x04;
if (hw->irq) {
i = get_option_index(s508_irq_options, hw->irq);
if (i) tmp |= s507_irqmask[i - 1];
}
_OUTB(port, tmp);
hw->regs[0] = tmp; /* update mirror */
for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
return (_INB(port) & 0x08) ? 0 : -EIO;
}
/*============================================================================
* Initialize S508 adapter.
*/
static int init_s508 (sdlahw_t* hw)
{
unsigned port = hw->port;
int tmp, i;
if (!detect_s508(port))
return -ENODEV;
/* Verify configuration options */
i = get_option_index(s508_dpmbase_options, virt_to_phys(hw->dpmbase));
if (i == 0)
return -EINVAL;
/* Setup memory configuration */
tmp = s508_hmcr[i - 1];
_OUTB(port + 1, tmp);
hw->regs[1] = tmp;
/* Enable memory access */
_OUTB(port, 0x04);
hw->regs[0] = 0x04; /* update mirror */
for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
return (_INB(port + 1) & 0x04) ? 0 : -EIO;
}
/*============================================================================
* Detect S502A adapter.
* Following tests are used to detect S502A adapter:
* 1. All registers other than status (BASE) should read 0xFF
* 2. After writing 00001000b to control register, status register should
* read 01000000b.
* 3. After writing 0 to control register, status register should still
* read 01000000b.
* 4. After writing 00000100b to control register, status register should
* read 01000100b.
* Return 1 if detected o.k. or 0 if failed.
* Note: This test is destructive! Adapter will be left in shutdown
* state after the test.
*/
static int detect_s502a (int port)
{
int i, j;
if (!get_option_index(s502_port_options, port))
return 0;
for (j = 1; j < SDLA_MAXIORANGE; ++j) {
if (_INB(port + j) != 0xFF)
return 0;
for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
}
_OUTB(port, 0x08); /* halt CPU */
_OUTB(port, 0x08);
_OUTB(port, 0x08);
for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
if (_INB(port) != 0x40)
return 0;
_OUTB(port, 0x00);
for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
if (_INB(port) != 0x40)
return 0;
_OUTB(port, 0x04);
for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
if (_INB(port) != 0x44)
return 0;
/* Reset adapter */
_OUTB(port, 0x08);
_OUTB(port, 0x08);
_OUTB(port, 0x08);
_OUTB(port + 1, 0xFF);
return 1;
}
/*============================================================================
* Detect S502E adapter.
* Following tests are used to verify adapter presence:
* 1. All registers other than status (BASE) should read 0xFF.
* 2. After writing 0 to CPU control register (BASE+3), status register
* (BASE) should read 11111000b.
* 3. After writing 00000100b to port BASE (set bit 2), status register
* (BASE) should read 11111100b.
* Return 1 if detected o.k. or 0 if failed.
* Note: This test is destructive! Adapter will be left in shutdown
* state after the test.
*/
static int detect_s502e (int port)
{
int i, j;
if (!get_option_index(s502_port_options, port))
return 0;
for (j = 1; j < SDLA_MAXIORANGE; ++j) {
if (_INB(port + j) != 0xFF)
return 0;
for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
}
_OUTB(port + 3, 0); /* CPU control reg. */
for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
if (_INB(port) != 0xF8) /* read status */
return 0;
_OUTB(port, 0x04); /* set bit 2 */
for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
if (_INB(port) != 0xFC) /* verify */
return 0;
/* Reset adapter */
_OUTB(port, 0);
return 1;
}
/*============================================================================
* Detect s503 adapter.
* Following tests are used to verify adapter presence:
* 1. All registers other than status (BASE) should read 0xFF.
* 2. After writing 0 to control register (BASE), status register (BASE)
* should read 11110000b.
* 3. After writing 00000100b (set bit 2) to control register (BASE),
* status register should read 11110010b.
* Return 1 if detected o.k. or 0 if failed.
* Note: This test is destructive! Adapter will be left in shutdown
* state after the test.
*/
static int detect_s503 (int port)
{
int i, j;
if (!get_option_index(s503_port_options, port))
return 0;
for (j = 1; j < SDLA_MAXIORANGE; ++j) {
if (_INB(port + j) != 0xFF)
return 0;
for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
}
_OUTB(port, 0); /* reset control reg.*/
for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
if (_INB(port) != 0xF0) /* read status */
return 0;
_OUTB(port, 0x04); /* set bit 2 */
for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
if (_INB(port) != 0xF2) /* verify */
return 0;
/* Reset adapter */
_OUTB(port, 0);
return 1;
}
/*============================================================================
* Detect s507 adapter.
* Following tests are used to detect s507 adapter:
* 1. All ports should read the same value.
* 2. After writing 0x00 to control register, status register should read
* ?011000?b.
* 3. After writing 0x01 to control register, status register should read
* ?011001?b.
* Return 1 if detected o.k. or 0 if failed.
* Note: This test is destructive! Adapter will be left in shutdown
* state after the test.
*/
static int detect_s507 (int port)
{
int tmp, i, j;
if (!get_option_index(s508_port_options, port))
return 0;
tmp = _INB(port);
for (j = 1; j < S507_IORANGE; ++j) {
if (_INB(port + j) != tmp)
return 0;
for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
}
_OUTB(port, 0x00);
for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
if ((_INB(port) & 0x7E) != 0x30)
return 0;
_OUTB(port, 0x01);
for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
if ((_INB(port) & 0x7E) != 0x32)
return 0;
/* Reset adapter */
_OUTB(port, 0x00);
return 1;
}
/*============================================================================
* Detect s508 adapter.
* Following tests are used to detect s508 adapter:
* 1. After writing 0x00 to control register, status register should read
* ??000000b.
* 2. After writing 0x10 to control register, status register should read
* ??010000b
* Return 1 if detected o.k. or 0 if failed.
* Note: This test is destructive! Adapter will be left in shutdown
* state after the test.
*/
static int detect_s508 (int port)
{
int i;
if (!get_option_index(s508_port_options, port))
return 0;
_OUTB(port, 0x00);
for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
if ((_INB(port + 1) & 0x3F) != 0x00)
return 0;
_OUTB(port, 0x10);
for (i = 0; i < SDLA_IODELAY; ++i); /* delay */
if ((_INB(port + 1) & 0x3F) != 0x10)
return 0;
/* Reset adapter */
_OUTB(port, 0x00);
return 1;
}
/*============================================================================
* Detect s514 PCI adapter.
* Return 1 if detected o.k. or 0 if failed.
* Note: This test is destructive! Adapter will be left in shutdown
* state after the test.
*/
static int detect_s514 (sdlahw_t* hw)
{
unsigned char CPU_no, slot_no, auto_slot_cfg;
int number_S514_cards = 0;
u32 S514_mem_base_addr = 0;
u32 ut_u32;
struct pci_dev *pci_dev;
#ifndef CONFIG_PCI
printk(KERN_INFO "%s: Linux not compiled for PCI usage!\n", modname);
return 0;
#endif
/*
The 'setup()' procedure in 'sdlamain.c' passes the CPU number and the
slot number defined in 'router.conf' via the 'port' definition.
*/
CPU_no = hw->S514_cpu_no[0];
slot_no = hw->S514_slot_no;
auto_slot_cfg = hw->auto_pci_cfg;
if (auto_slot_cfg){
printk(KERN_INFO "%s: srch... S514 card, CPU %c, Slot=Auto\n",
modname, CPU_no);
}else{
printk(KERN_INFO "%s: srch... S514 card, CPU %c, Slot #%d\n",
modname, CPU_no, slot_no);
}
/* check to see that CPU A or B has been selected in 'router.conf' */
switch(CPU_no) {
case S514_CPU_A:
case S514_CPU_B:
break;
default:
printk(KERN_INFO "%s: S514 CPU definition invalid.\n",
modname);
printk(KERN_INFO "Must be 'A' or 'B'\n");
return 0;
}
number_S514_cards = find_s514_adapter(hw, 0);
if(!number_S514_cards)
return 0;
/* we are using a single S514 adapter with a slot of 0 so re-read the */
/* location of this adapter */
if((number_S514_cards == 1) && auto_slot_cfg) {
number_S514_cards = find_s514_adapter(hw, 1);
if(!number_S514_cards) {
printk(KERN_INFO "%s: Error finding PCI card\n",
modname);
return 0;
}
}
pci_dev = hw->pci_dev;
/* read the physical memory base address */
S514_mem_base_addr = (CPU_no == S514_CPU_A) ?
(pci_dev->resource[1].start) :
(pci_dev->resource[2].start);
printk(KERN_INFO "%s: S514 PCI memory at 0x%X\n",
modname, S514_mem_base_addr);
if(!S514_mem_base_addr) {
if(CPU_no == S514_CPU_B)
printk(KERN_INFO "%s: CPU #B not present on the card\n", modname);
else
printk(KERN_INFO "%s: No PCI memory allocated to card\n", modname);
return 0;
}
/* enable the PCI memory */
pci_read_config_dword(pci_dev,
(CPU_no == S514_CPU_A) ? PCI_MAP0_DWORD : PCI_MAP1_DWORD,
&ut_u32);
pci_write_config_dword(pci_dev,
(CPU_no == S514_CPU_A) ? PCI_MAP0_DWORD : PCI_MAP1_DWORD,
(ut_u32 | PCI_MEMORY_ENABLE));
/* check the IRQ allocated and enable IRQ usage */
if(!(hw->irq = pci_dev->irq)) {
printk(KERN_INFO "%s: IRQ not allocated to S514 adapter\n",
modname);
return 0;
}
/* BUG FIX : Mar 6 2000
* On a initial loading of the card, we must check
* and clear PCI interrupt bits, due to a reset
* problem on some other boards. i.e. An interrupt
* might be pending, even after system bootup,
* in which case, when starting wanrouter the machine
* would crash.
*/
if (init_pci_slot(hw))
return 0;
pci_read_config_dword(pci_dev, PCI_INT_CONFIG, &ut_u32);
ut_u32 |= (CPU_no == S514_CPU_A) ?
PCI_ENABLE_IRQ_CPU_A : PCI_ENABLE_IRQ_CPU_B;
pci_write_config_dword(pci_dev, PCI_INT_CONFIG, ut_u32);
printk(KERN_INFO "%s: IRQ %d allocated to the S514 card\n",
modname, hw->irq);
/* map the physical PCI memory to virtual memory */
hw->dpmbase = ioremap((unsigned long)S514_mem_base_addr,
(unsigned long)MAX_SIZEOF_S514_MEMORY);
/* map the physical control register memory to virtual memory */
hw->vector = (unsigned long)ioremap(
(unsigned long)(S514_mem_base_addr + S514_CTRL_REG_BYTE),
(unsigned long)16);
if(!hw->dpmbase || !hw->vector) {
printk(KERN_INFO "%s: PCI virtual memory allocation failed\n",
modname);
return 0;
}
/* halt the adapter */
writeb (S514_CPU_HALT, hw->vector);
return 1;
}
/*============================================================================
* Find the S514 PCI adapter in the PCI bus.
* Return the number of S514 adapters found (0 if no adapter found).
*/
static int find_s514_adapter(sdlahw_t* hw, char find_first_S514_card)
{
unsigned char slot_no;
int number_S514_cards = 0;
char S514_found_in_slot = 0;
u16 PCI_subsys_vendor;
struct pci_dev *pci_dev = NULL;
slot_no = hw->S514_slot_no;
while ((pci_dev = pci_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_dev))
!= NULL) {
pci_read_config_word(pci_dev, PCI_SUBSYS_VENDOR_WORD,
&PCI_subsys_vendor);
if(PCI_subsys_vendor != SANGOMA_SUBSYS_VENDOR)
continue;
hw->pci_dev = pci_dev;
if(find_first_S514_card)
return(1);
number_S514_cards ++;
printk(KERN_INFO
"%s: S514 card found, slot #%d (devfn 0x%X)\n",
modname, ((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK),
pci_dev->devfn);
if (hw->auto_pci_cfg){
hw->S514_slot_no = ((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK);
slot_no = hw->S514_slot_no;
}else if (((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK) == slot_no){
S514_found_in_slot = 1;
break;
}
}
/* if no S514 adapter has been found, then exit */
if (!number_S514_cards) {
printk(KERN_INFO "%s: Error, no S514 adapters found\n", modname);
return 0;
}
/* if more than one S514 card has been found, then the user must have */ /* defined a slot number so that the correct adapter is used */
else if ((number_S514_cards > 1) && hw->auto_pci_cfg) {
printk(KERN_INFO "%s: Error, PCI Slot autodetect Failed! \n"
"%s: More than one S514 adapter found.\n"
"%s: Disable the Autodetect feature and supply\n"
"%s: the PCISLOT numbers for each card.\n",
modname,modname,modname,modname);
return 0;
}
/* if the user has specified a slot number and the S514 adapter has */
/* not been found in that slot, then exit */
else if (!hw->auto_pci_cfg && !S514_found_in_slot) {
printk(KERN_INFO
"%s: Error, S514 card not found in specified slot #%d\n",
modname, slot_no);
return 0;
}
return (number_S514_cards);
}
/******* Miscellaneous ******************************************************/
/*============================================================================
* Calibrate SDLA memory access delay.
* Count number of idle loops made within 1 second and then calculate the
* number of loops that should be made to achive desired delay.
*/
static int calibrate_delay (int mks)
{
unsigned int delay;
unsigned long stop;
for (delay = 0, stop = SYSTEM_TICK + HZ; SYSTEM_TICK < stop; ++delay);
return (delay/(1000000L/mks) + 1);
}
/*============================================================================
* Get option's index into the options list.
* Return option's index (1 .. N) or zero if option is invalid.
*/
static int get_option_index (unsigned* optlist, unsigned optval)
{
int i;
for (i = 1; i <= optlist[0]; ++i)
if ( optlist[i] == optval)
return i;
return 0;
}
/*============================================================================
* Check memory region to see if it's available.
* Return: 0 ok.
*/
static unsigned check_memregion (void* ptr, unsigned len)
{
volatile unsigned char* p = ptr;
for (; len && (readb (p) == 0xFF); --len, ++p) {
writeb (0, p); /* attempt to write 0 */
if (readb(p) != 0xFF) { /* still has to read 0xFF */
writeb (0xFF, p);/* restore original value */
break; /* not good */
}
}
return len;
}
/*============================================================================
* Test memory region.
* Return: size of the region that passed the test.
* Note: Region size must be multiple of 2 !
*/
static unsigned test_memregion (void* ptr, unsigned len)
{
volatile unsigned short* w_ptr;
unsigned len_w = len >> 1; /* region len in words */
unsigned i;
for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr)
writew (0xAA55, w_ptr);
for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr)
if (readw (w_ptr) != 0xAA55) {
len_w = i;
break;
}
for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr)
writew (0x55AA, w_ptr);
for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr)
if (readw(w_ptr) != 0x55AA) {
len_w = i;
break;
}
for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr)
writew (0, w_ptr);
return len_w << 1;
}
/*============================================================================
* Calculate 16-bit CRC using CCITT polynomial.
*/
static unsigned short checksum (unsigned char* buf, unsigned len)
{
unsigned short crc = 0;
unsigned mask, flag;
for (; len; --len, ++buf) {
for (mask = 0x80; mask; mask >>= 1) {
flag = (crc & 0x8000);
crc <<= 1;
crc |= ((*buf & mask) ? 1 : 0);
if (flag) crc ^= 0x1021;
}
}
return crc;
}
static int init_pci_slot(sdlahw_t *hw)
{
u32 int_status;
int volatile found=0;
int i=0;
/* Check if this is a very first load for a specific
* pci card. If it is, clear the interrput bits, and
* set the flag indicating that this card was initialized.
*/
for (i=0; (i<MAX_S514_CARDS) && !found; i++){
if (pci_slot_ar[i] == hw->S514_slot_no){
found=1;
break;
}
if (pci_slot_ar[i] == 0xFF){
break;
}
}
if (!found){
read_S514_int_stat(hw,&int_status);
S514_intack(hw,int_status);
if (i == MAX_S514_CARDS){
printk(KERN_INFO "%s: Critical Error !!!\n",modname);
printk(KERN_INFO
"%s: Number of Sangoma PCI cards exceeded maximum limit.\n",
modname);
printk(KERN_INFO "Please contact Sangoma Technologies\n");
return 1;
}
pci_slot_ar[i] = hw->S514_slot_no;
}
return 0;
}
static int pci_probe(sdlahw_t *hw)
{
unsigned char slot_no;
int number_S514_cards = 0;
u16 PCI_subsys_vendor;
u16 PCI_card_type;
struct pci_dev *pci_dev = NULL;
struct pci_bus *bus = NULL;
slot_no = 0;
while ((pci_dev = pci_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_dev))
!= NULL) {
pci_read_config_word(pci_dev, PCI_SUBSYS_VENDOR_WORD,
&PCI_subsys_vendor);
if(PCI_subsys_vendor != SANGOMA_SUBSYS_VENDOR)
continue;
pci_read_config_word(pci_dev, PCI_CARD_TYPE,
&PCI_card_type);
bus = pci_dev->bus;
/* A dual cpu card can support up to 4 physical connections,
* where a single cpu card can support up to 2 physical
* connections. The FT1 card can only support a single
* connection, however we cannot distinguish between a Single
* CPU card and an FT1 card. */
if (PCI_card_type == S514_DUAL_CPU){
number_S514_cards += 4;
printk(KERN_INFO
"wanpipe: S514-PCI card found, cpu(s) 2, bus #%d, slot #%d, irq #%d\n",
bus->number,((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK),
pci_dev->irq);
}else{
number_S514_cards += 2;
printk(KERN_INFO
"wanpipe: S514-PCI card found, cpu(s) 1, bus #%d, slot #%d, irq #%d\n",
bus->number,((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK),
pci_dev->irq);
}
}
return number_S514_cards;
}
EXPORT_SYMBOL(wanpipe_hw_probe);
unsigned wanpipe_hw_probe(void)
{
sdlahw_t hw;
unsigned* opt = s508_port_options;
unsigned cardno=0;
int i;
memset(&hw, 0, sizeof(hw));
for (i = 1; i <= opt[0]; i++) {
if (detect_s508(opt[i])){
/* S508 card can support up to two physical links */
cardno+=2;
printk(KERN_INFO "wanpipe: S508-ISA card found, port 0x%x\n",opt[i]);
}
}
#ifdef CONFIG_PCI
hw.S514_slot_no = 0;
cardno += pci_probe(&hw);
#else
printk(KERN_INFO "wanpipe: Warning, Kernel not compiled for PCI support!\n");
printk(KERN_INFO "wanpipe: PCI Hardware Probe Failed!\n");
#endif
return cardno;
}
/****** End *****************************************************************/
/****************************************************************************
* sdlamain.c WANPIPE(tm) Multiprotocol WAN Link Driver. Main module.
*
* Author: Nenad Corbic <ncorbic@sangoma.com>
* Gideon Hack
*
* Copyright: (c) 1995-2000 Sangoma Technologies Inc.
*
* 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.
* ============================================================================
* Dec 22, 2000 Nenad Corbic Updated for 2.4.X kernels.
* Removed the polling routine.
* Nov 13, 2000 Nenad Corbic Added hw probing on module load and dynamic
* device allocation.
* Nov 7, 2000 Nenad Corbic Fixed the Multi-Port PPP for kernels
* 2.2.16 and above.
* Aug 2, 2000 Nenad Corbic Block the Multi-Port PPP from running on
* kernels 2.2.16 or greater. The SyncPPP
* has changed.
* Jul 25, 2000 Nenad Corbic Updated the Piggiback support for MultPPPP.
* Jul 13, 2000 Nenad Corbic Added Multi-PPP support.
* Feb 02, 2000 Nenad Corbic Fixed up piggyback probing and selection.
* Sep 23, 1999 Nenad Corbic Added support for SMP
* Sep 13, 1999 Nenad Corbic Each port is treated as a separate device.
* Jun 02, 1999 Gideon Hack Added support for the S514 adapter.
* Updates for Linux 2.2.X kernels.
* Sep 17, 1998 Jaspreet Singh Updated for 2.1.121+ kernel
* Nov 28, 1997 Jaspreet Singh Changed DRV_RELEASE to 1
* Nov 10, 1997 Jaspreet Singh Changed sti() to restore_flags();
* Nov 06, 1997 Jaspreet Singh Changed DRV_VERSION to 4 and DRV_RELEASE to 0
* Oct 20, 1997 Jaspreet Singh Modified sdla_isr routine so that card->in_isr
* assignments are taken out and placed in the
* sdla_ppp.c, sdla_fr.c and sdla_x25.c isr
* routines. Took out 'wandev->tx_int_enabled' and
* replaced it with 'wandev->enable_tx_int'.
* May 29, 1997 Jaspreet Singh Flow Control Problem
* added "wandev->tx_int_enabled=1" line in the
* init module. This line initializes the flag for
* preventing Interrupt disabled with device set to
* busy
* Jan 15, 1997 Gene Kozin Version 3.1.0
* o added UDP management stuff
* Jan 02, 1997 Gene Kozin 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/init.h>
#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/wanpipe.h> /* WANPIPE common user API definitions */
#include <linux/rcupdate.h>
#include <linux/in.h>
#include <asm/io.h> /* phys_to_virt() */
#include <linux/pci.h>
#include <linux/sdlapci.h>
#include <linux/if_wanpipe_common.h>
#include <asm/uaccess.h> /* kernel <-> user copy */
#include <linux/inetdevice.h>
#include <linux/ip.h>
#include <net/route.h>
#define KMEM_SAFETYZONE 8
#ifndef CONFIG_WANPIPE_FR
#define wpf_init(a,b) (-EPROTONOSUPPORT)
#endif
#ifndef CONFIG_WANPIPE_CHDLC
#define wpc_init(a,b) (-EPROTONOSUPPORT)
#endif
#ifndef CONFIG_WANPIPE_X25
#define wpx_init(a,b) (-EPROTONOSUPPORT)
#endif
#ifndef CONFIG_WANPIPE_PPP
#define wpp_init(a,b) (-EPROTONOSUPPORT)
#endif
#ifndef CONFIG_WANPIPE_MULTPPP
#define wsppp_init(a,b) (-EPROTONOSUPPORT)
#endif
/***********FOR DEBUGGING PURPOSES*********************************************
static void * dbg_kmalloc(unsigned int size, int prio, int line) {
int i = 0;
void * v = kmalloc(size+sizeof(unsigned int)+2*KMEM_SAFETYZONE*8,prio);
char * c1 = v;
c1 += sizeof(unsigned int);
*((unsigned int *)v) = size;
for (i = 0; i < KMEM_SAFETYZONE; i++) {
c1[0] = 'D'; c1[1] = 'E'; c1[2] = 'A'; c1[3] = 'D';
c1[4] = 'B'; c1[5] = 'E'; c1[6] = 'E'; c1[7] = 'F';
c1 += 8;
}
c1 += size;
for (i = 0; i < KMEM_SAFETYZONE; i++) {
c1[0] = 'M'; c1[1] = 'U'; c1[2] = 'N'; c1[3] = 'G';
c1[4] = 'W'; c1[5] = 'A'; c1[6] = 'L'; c1[7] = 'L';
c1 += 8;
}
v = ((char *)v) + sizeof(unsigned int) + KMEM_SAFETYZONE*8;
printk(KERN_INFO "line %d kmalloc(%d,%d) = %p\n",line,size,prio,v);
return v;
}
static void dbg_kfree(void * v, int line) {
unsigned int * sp = (unsigned int *)(((char *)v) - (sizeof(unsigned int) + KMEM_SAFETYZONE*8));
unsigned int size = *sp;
char * c1 = ((char *)v) - KMEM_SAFETYZONE*8;
int i = 0;
for (i = 0; i < KMEM_SAFETYZONE; i++) {
if ( c1[0] != 'D' || c1[1] != 'E' || c1[2] != 'A' || c1[3] != 'D'
|| c1[4] != 'B' || c1[5] != 'E' || c1[6] != 'E' || c1[7] != 'F') {
printk(KERN_INFO "kmalloced block at %p has been corrupted (underrun)!\n",v);
printk(KERN_INFO " %4x: %2x %2x %2x %2x %2x %2x %2x %2x\n", i*8,
c1[0],c1[1],c1[2],c1[3],c1[4],c1[5],c1[6],c1[7] );
}
c1 += 8;
}
c1 += size;
for (i = 0; i < KMEM_SAFETYZONE; i++) {
if ( c1[0] != 'M' || c1[1] != 'U' || c1[2] != 'N' || c1[3] != 'G'
|| c1[4] != 'W' || c1[5] != 'A' || c1[6] != 'L' || c1[7] != 'L'
) {
printk(KERN_INFO "kmalloced block at %p has been corrupted (overrun):\n",v);
printk(KERN_INFO " %4x: %2x %2x %2x %2x %2x %2x %2x %2x\n", i*8,
c1[0],c1[1],c1[2],c1[3],c1[4],c1[5],c1[6],c1[7] );
}
c1 += 8;
}
printk(KERN_INFO "line %d kfree(%p)\n",line,v);
v = ((char *)v) - (sizeof(unsigned int) + KMEM_SAFETYZONE*8);
kfree(v);
}
#define kmalloc(x,y) dbg_kmalloc(x,y,__LINE__)
#define kfree(x) dbg_kfree(x,__LINE__)
******************************************************************************/
/****** Defines & Macros ****************************************************/
#ifdef _DEBUG_
#define STATIC
#else
#define STATIC static
#endif
#define DRV_VERSION 5 /* version number */
#define DRV_RELEASE 0 /* release (minor version) number */
#define MAX_CARDS 16 /* max number of adapters */
#ifndef CONFIG_WANPIPE_CARDS /* configurable option */
#define CONFIG_WANPIPE_CARDS 1
#endif
#define CMD_OK 0 /* normal firmware return code */
#define CMD_TIMEOUT 0xFF /* firmware command timed out */
#define MAX_CMD_RETRY 10 /* max number of firmware retries */
/****** Function Prototypes *************************************************/
extern void disable_irq(unsigned int);
extern void enable_irq(unsigned int);
/* WAN link driver entry points */
static int setup(struct wan_device* wandev, wandev_conf_t* conf);
static int shutdown(struct wan_device* wandev);
static int ioctl(struct wan_device* wandev, unsigned cmd, unsigned long arg);
/* IOCTL handlers */
static int ioctl_dump (sdla_t* card, sdla_dump_t* u_dump);
static int ioctl_exec (sdla_t* card, sdla_exec_t* u_exec, int);
/* Miscellaneous functions */
STATIC irqreturn_t sdla_isr (int irq, void* dev_id, struct pt_regs *regs);
static void release_hw (sdla_t *card);
static int check_s508_conflicts (sdla_t* card,wandev_conf_t* conf, int*);
static int check_s514_conflicts (sdla_t* card,wandev_conf_t* conf, int*);
/****** Global Data **********************************************************
* Note: All data must be explicitly initialized!!!
*/
/* private data */
static char drvname[] = "wanpipe";
static char fullname[] = "WANPIPE(tm) Multiprotocol Driver";
static char copyright[] = "(c) 1995-2000 Sangoma Technologies Inc.";
static int ncards;
static sdla_t* card_array; /* adapter data space */
/* Wanpipe's own workqueue, used for all API's.
* All protocol specific tasks will be inserted
* into the "wanpipe_wq" workqueue.
* The kernel workqueue mechanism will execute
* all pending tasks in the "wanpipe_wq" workqueue.
*/
struct workqueue_struct *wanpipe_wq;
DECLARE_WORK(wanpipe_work, NULL, NULL);
static int wanpipe_bh_critical;
/******* 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 SDLA shared memory access delay.
*
* Return: 0 Ok
* < 0 error.
* Context: process
*/
static int __init wanpipe_init(void)
{
int cnt, err = 0;
printk(KERN_INFO "%s v%u.%u %s\n",
fullname, DRV_VERSION, DRV_RELEASE, copyright);
wanpipe_wq = create_workqueue("wanpipe_wq");
if (!wanpipe_wq)
return -ENOMEM;
/* Probe for wanpipe cards and return the number found */
printk(KERN_INFO "wanpipe: Probing for WANPIPE hardware.\n");
ncards = wanpipe_hw_probe();
if (ncards){
printk(KERN_INFO "wanpipe: Allocating maximum %i devices: wanpipe%i - wanpipe%i.\n",ncards,1,ncards);
}else{
printk(KERN_INFO "wanpipe: No S514/S508 cards found, unloading modules!\n");
destroy_workqueue(wanpipe_wq);
return -ENODEV;
}
/* Verify number of cards and allocate adapter data space */
card_array = kmalloc(sizeof(sdla_t) * ncards, GFP_KERNEL);
if (card_array == NULL) {
destroy_workqueue(wanpipe_wq);
return -ENOMEM;
}
memset(card_array, 0, sizeof(sdla_t) * ncards);
/* Register adapters with WAN router */
for (cnt = 0; cnt < ncards; ++ cnt) {
sdla_t* card = &card_array[cnt];
struct wan_device* wandev = &card->wandev;
card->next = NULL;
sprintf(card->devname, "%s%d", drvname, cnt + 1);
wandev->magic = ROUTER_MAGIC;
wandev->name = card->devname;
wandev->private = card;
wandev->enable_tx_int = 0;
wandev->setup = &setup;
wandev->shutdown = &shutdown;
wandev->ioctl = &ioctl;
err = register_wan_device(wandev);
if (err) {
printk(KERN_INFO
"%s: %s registration failed with error %d!\n",
drvname, card->devname, err);
break;
}
}
if (cnt){
ncards = cnt; /* adjust actual number of cards */
}else {
kfree(card_array);
destroy_workqueue(wanpipe_wq);
printk(KERN_INFO "IN Init Module: NO Cards registered\n");
err = -ENODEV;
}
return err;
}
/*============================================================================
* Module 'remove' entry point.
* o unregister all adapters from the WAN router
* o release all remaining system resources
*/
static void __exit wanpipe_cleanup(void)
{
int i;
if (!ncards)
return;
for (i = 0; i < ncards; ++i) {
sdla_t* card = &card_array[i];
unregister_wan_device(card->devname);
}
destroy_workqueue(wanpipe_wq);
kfree(card_array);
printk(KERN_INFO "\nwanpipe: WANPIPE Modules Unloaded.\n");
}
module_init(wanpipe_init);
module_exit(wanpipe_cleanup);
/******* WAN Device Driver Entry Points *************************************/
/*============================================================================
* Setup/configure WAN link driver.
* o check adapter state
* o make sure firmware is present in configuration
* o make sure I/O port and IRQ are specified
* o make sure I/O region is available
* o allocate interrupt vector
* o setup SDLA hardware
* o call appropriate routine to perform protocol-specific initialization
* o mark I/O region as used
* o if this is the first active card, then schedule background task
*
* This function is called when router handles ROUTER_SETUP IOCTL. The
* configuration structure is in kernel memory (including extended data, if
* any).
*/
static int setup(struct wan_device* wandev, wandev_conf_t* conf)
{
sdla_t* card;
int err = 0;
int irq=0;
/* Sanity checks */
if ((wandev == NULL) || (wandev->private == NULL) || (conf == NULL)){
printk(KERN_INFO
"%s: Failed Sdlamain Setup wandev %u, card %u, conf %u !\n",
wandev->name,
(unsigned int)wandev,(unsigned int)wandev->private,
(unsigned int)conf);
return -EFAULT;
}
printk(KERN_INFO "%s: Starting WAN Setup\n", wandev->name);
card = wandev->private;
if (wandev->state != WAN_UNCONFIGURED){
printk(KERN_INFO "%s: failed sdlamain setup, busy!\n",
wandev->name);
return -EBUSY; /* already configured */
}
printk(KERN_INFO "\nProcessing WAN device %s...\n", wandev->name);
/* Initialize the counters for each wandev
* Used for counting number of times new_if and
* del_if get called.
*/
wandev->del_if_cnt = 0;
wandev->new_if_cnt = 0;
wandev->config_id = conf->config_id;
if (!conf->data_size || (conf->data == NULL)) {
printk(KERN_INFO
"%s: firmware not found in configuration data!\n",
wandev->name);
return -EINVAL;
}
/* Check for resource conflicts and setup the
* card for piggibacking if necessary */
if(!conf->S514_CPU_no[0]) {
if ((err=check_s508_conflicts(card,conf,&irq)) != 0){
return err;
}
}else {
if ((err=check_s514_conflicts(card,conf,&irq)) != 0){
return err;
}
}
/* If the current card has already been configured
* or it's a piggyback card, do not try to allocate
* resources.
*/
if (!card->wandev.piggyback && !card->configured){
/* Configure hardware, load firmware, etc. */
memset(&card->hw, 0, sizeof(sdlahw_t));
/* for an S514 adapter, pass the CPU number and the slot number read */
/* from 'router.conf' to the 'sdla_setup()' function via the 'port' */
/* parameter */
if (conf->S514_CPU_no[0]){
card->hw.S514_cpu_no[0] = conf->S514_CPU_no[0];
card->hw.S514_slot_no = conf->PCI_slot_no;
card->hw.auto_pci_cfg = conf->auto_pci_cfg;
if (card->hw.auto_pci_cfg == WANOPT_YES){
printk(KERN_INFO "%s: Setting CPU to %c and Slot to Auto\n",
card->devname, card->hw.S514_cpu_no[0]);
}else{
printk(KERN_INFO "%s: Setting CPU to %c and Slot to %i\n",
card->devname, card->hw.S514_cpu_no[0], card->hw.S514_slot_no);
}
}else{
/* 508 Card io port and irq initialization */
card->hw.port = conf->ioport;
card->hw.irq = (conf->irq == 9) ? 2 : conf->irq;
}
/* Compute the virtual address of the card in kernel space */
if(conf->maddr){
card->hw.dpmbase = phys_to_virt(conf->maddr);
}else{
card->hw.dpmbase = (void *)conf->maddr;
}
card->hw.dpmsize = SDLA_WINDOWSIZE;
/* set the adapter type if using an S514 adapter */
card->hw.type = (conf->S514_CPU_no[0]) ? SDLA_S514 : conf->hw_opt[0];
card->hw.pclk = conf->hw_opt[1];
err = sdla_setup(&card->hw, conf->data, conf->data_size);
if (err){
printk(KERN_INFO "%s: Hardware setup Failed %i\n",
card->devname,err);
return err;
}
if(card->hw.type != SDLA_S514)
irq = (conf->irq == 2) ? 9 : conf->irq; /* IRQ2 -> IRQ9 */
else
irq = card->hw.irq;
/* request an interrupt vector - note that interrupts may be shared */
/* when using the S514 PCI adapter */
if(request_irq(irq, sdla_isr,
(card->hw.type == SDLA_S514) ? SA_SHIRQ : 0,
wandev->name, card)){
printk(KERN_INFO "%s: Can't reserve IRQ %d!\n", wandev->name, irq);
return -EINVAL;
}
}else{
printk(KERN_INFO "%s: Card Configured %lu or Piggybacking %i!\n",
wandev->name,card->configured,card->wandev.piggyback);
}
if (!card->configured){
/* Initialize the Spin lock */
printk(KERN_INFO "%s: Initializing for SMP\n",wandev->name);
/* Piggyback spin lock has already been initialized,
* in check_s514/s508_conflicts() */
if (!card->wandev.piggyback){
spin_lock_init(&card->wandev.lock);
}
/* Intialize WAN device data space */
wandev->irq = irq;
wandev->dma = 0;
if(card->hw.type != SDLA_S514){
wandev->ioport = card->hw.port;
}else{
wandev->S514_cpu_no[0] = card->hw.S514_cpu_no[0];
wandev->S514_slot_no = card->hw.S514_slot_no;
}
wandev->maddr = (unsigned long)card->hw.dpmbase;
wandev->msize = card->hw.dpmsize;
wandev->hw_opt[0] = card->hw.type;
wandev->hw_opt[1] = card->hw.pclk;
wandev->hw_opt[2] = card->hw.memory;
wandev->hw_opt[3] = card->hw.fwid;
}
/* Protocol-specific initialization */
switch (card->hw.fwid) {
case SFID_X25_502:
case SFID_X25_508:
printk(KERN_INFO "%s: Starting X.25 Protocol Init.\n",
card->devname);
err = wpx_init(card, conf);
break;
case SFID_FR502:
case SFID_FR508:
printk(KERN_INFO "%s: Starting Frame Relay Protocol Init.\n",
card->devname);
err = wpf_init(card, conf);
break;
case SFID_PPP502:
case SFID_PPP508:
printk(KERN_INFO "%s: Starting PPP Protocol Init.\n",
card->devname);
err = wpp_init(card, conf);
break;
case SFID_CHDLC508:
case SFID_CHDLC514:
if (conf->ft1){
printk(KERN_INFO "%s: Starting FT1 CSU/DSU Config Driver.\n",
card->devname);
err = wpft1_init(card, conf);
break;
}else if (conf->config_id == WANCONFIG_MPPP){
printk(KERN_INFO "%s: Starting Multi-Port PPP Protocol Init.\n",
card->devname);
err = wsppp_init(card,conf);
break;
}else{
printk(KERN_INFO "%s: Starting CHDLC Protocol Init.\n",
card->devname);
err = wpc_init(card, conf);
break;
}
default:
printk(KERN_INFO "%s: Error, Firmware is not supported %X %X!\n",
wandev->name,card->hw.fwid,SFID_CHDLC508);
err = -EPROTONOSUPPORT;
}
if (err != 0){
if (err == -EPROTONOSUPPORT){
printk(KERN_INFO
"%s: Error, Protocol selected has not been compiled!\n",
card->devname);
printk(KERN_INFO
"%s: Re-configure the kernel and re-build the modules!\n",
card->devname);
}
release_hw(card);
wandev->state = WAN_UNCONFIGURED;
return err;
}
/* Reserve I/O region and schedule background task */
if(card->hw.type != SDLA_S514 && !card->wandev.piggyback)
if (!request_region(card->hw.port, card->hw.io_range,
wandev->name)) {
printk(KERN_WARNING "port 0x%04x busy\n", card->hw.port);
release_hw(card);
wandev->state = WAN_UNCONFIGURED;
return -EBUSY;
}
/* Only use the polling routine for the X25 protocol */
card->wandev.critical=0;
return 0;
}
/*==================================================================
* configure_s508_card
*
* For a S508 adapter, check for a possible configuration error in that
* we are loading an adapter in the same IO port as a previously loaded S508
* card.
*/
static int check_s508_conflicts (sdla_t* card,wandev_conf_t* conf, int *irq)
{
unsigned long smp_flags;
int i;
if (conf->ioport <= 0) {
printk(KERN_INFO
"%s: can't configure without I/O port address!\n",
card->wandev.name);
return -EINVAL;
}
if (conf->irq <= 0) {
printk(KERN_INFO "%s: can't configure without IRQ!\n",
card->wandev.name);
return -EINVAL;
}
if (test_bit(0,&card->configured))
return 0;
/* Check for already loaded card with the same IO port and IRQ
* If found, copy its hardware configuration and use its
* resources (i.e. piggybacking)
*/
for (i = 0; i < ncards; i++) {
sdla_t *nxt_card = &card_array[i];
/* Skip the current card ptr */
if (nxt_card == card)
continue;
/* Find a card that is already configured with the
* same IO Port */
if ((nxt_card->hw.type == SDLA_S508) &&
(nxt_card->hw.port == conf->ioport) &&
(nxt_card->next == NULL)){
/* We found a card the card that has same configuration
* as us. This means, that we must setup this card in
* piggibacking mode. However, only CHDLC and MPPP protocol
* support this setup */
if ((conf->config_id == WANCONFIG_CHDLC ||
conf->config_id == WANCONFIG_MPPP) &&
(nxt_card->wandev.config_id == WANCONFIG_CHDLC ||
nxt_card->wandev.config_id == WANCONFIG_MPPP)){
*irq = nxt_card->hw.irq;
memcpy(&card->hw, &nxt_card->hw, sizeof(sdlahw_t));
/* The master could already be running, we must
* set this as a critical area */
lock_adapter_irq(&nxt_card->wandev.lock, &smp_flags);
nxt_card->next = card;
card->next = nxt_card;
card->wandev.piggyback = WANOPT_YES;
/* We must initialise the piggiback spin lock here
* since isr will try to lock card->next if it
* exists */
spin_lock_init(&card->wandev.lock);
unlock_adapter_irq(&nxt_card->wandev.lock, &smp_flags);
break;
}else{
/* Trying to run piggibacking with a wrong protocol */
printk(KERN_INFO "%s: ERROR: Resource busy, ioport: 0x%x\n"
"%s: This protocol doesn't support\n"
"%s: multi-port operation!\n",
card->devname,nxt_card->hw.port,
card->devname,card->devname);
return -EEXIST;
}
}
}
/* Make sure I/O port region is available only if we are the
* master device. If we are running in piggybacking mode,
* we will use the resources of the master card. */
if (!card->wandev.piggyback) {
struct resource *rr =
request_region(conf->ioport, SDLA_MAXIORANGE, "sdlamain");
release_region(conf->ioport, SDLA_MAXIORANGE);
if (!rr) {
printk(KERN_INFO
"%s: I/O region 0x%X - 0x%X is in use!\n",
card->wandev.name, conf->ioport,
conf->ioport + SDLA_MAXIORANGE - 1);
return -EINVAL;
}
}
return 0;
}
/*==================================================================
* configure_s514_card
*
* For a S514 adapter, check for a possible configuration error in that
* we are loading an adapter in the same slot as a previously loaded S514
* card.
*/
static int check_s514_conflicts(sdla_t* card,wandev_conf_t* conf, int *irq)
{
unsigned long smp_flags;
int i;
if (test_bit(0,&card->configured))
return 0;
/* Check for already loaded card with the same IO port and IRQ
* If found, copy its hardware configuration and use its
* resources (i.e. piggybacking)
*/
for (i = 0; i < ncards; i ++) {
sdla_t* nxt_card = &card_array[i];
if(nxt_card == card)
continue;
if((nxt_card->hw.type == SDLA_S514) &&
(nxt_card->hw.S514_slot_no == conf->PCI_slot_no) &&
(nxt_card->hw.S514_cpu_no[0] == conf->S514_CPU_no[0])&&
(nxt_card->next == NULL)){
if ((conf->config_id == WANCONFIG_CHDLC ||
conf->config_id == WANCONFIG_MPPP) &&
(nxt_card->wandev.config_id == WANCONFIG_CHDLC ||
nxt_card->wandev.config_id == WANCONFIG_MPPP)){
*irq = nxt_card->hw.irq;
memcpy(&card->hw, &nxt_card->hw, sizeof(sdlahw_t));
/* The master could already be running, we must
* set this as a critical area */
lock_adapter_irq(&nxt_card->wandev.lock,&smp_flags);
nxt_card->next = card;
card->next = nxt_card;
card->wandev.piggyback = WANOPT_YES;
/* We must initialise the piggiback spin lock here
* since isr will try to lock card->next if it
* exists */
spin_lock_init(&card->wandev.lock);
unlock_adapter_irq(&nxt_card->wandev.lock,&smp_flags);
}else{
/* Trying to run piggibacking with a wrong protocol */
printk(KERN_INFO "%s: ERROR: Resource busy: CPU %c PCISLOT %i\n"
"%s: This protocol doesn't support\n"
"%s: multi-port operation!\n",
card->devname,
conf->S514_CPU_no[0],conf->PCI_slot_no,
card->devname,card->devname);
return -EEXIST;
}
}
}
return 0;
}
/*============================================================================
* 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 shutdown(struct wan_device* wandev)
{
sdla_t *card;
int err=0;
/* sanity checks */
if ((wandev == NULL) || (wandev->private == NULL)){
return -EFAULT;
}
if (wandev->state == WAN_UNCONFIGURED){
return 0;
}
card = wandev->private;
if (card->tty_opt){
if (card->tty_open){
printk(KERN_INFO
"%s: Shutdown Failed: TTY is still open\n",
card->devname);
return -EBUSY;
}
}
wandev->state = WAN_UNCONFIGURED;
set_bit(PERI_CRIT,(void*)&wandev->critical);
/* In case of piggibacking, make sure that
* we never try to shutdown both devices at the same
* time, because they depend on one another */
if (card->disable_comm){
card->disable_comm(card);
}
/* Release Resources */
release_hw(card);
/* only free the allocated I/O range if not an S514 adapter */
if (wandev->hw_opt[0] != SDLA_S514 && !card->configured){
release_region(card->hw.port, card->hw.io_range);
}
if (!card->configured){
memset(&card->hw, 0, sizeof(sdlahw_t));
if (card->next){
memset(&card->next->hw, 0, sizeof(sdlahw_t));
}
}
clear_bit(PERI_CRIT,(void*)&wandev->critical);
return err;
}
static void release_hw (sdla_t *card)
{
sdla_t *nxt_card;
/* Check if next device exists */
if (card->next){
nxt_card = card->next;
/* If next device is down then release resources */
if (nxt_card->wandev.state == WAN_UNCONFIGURED){
if (card->wandev.piggyback){
/* If this device is piggyback then use
* information of the master device
*/
printk(KERN_INFO "%s: Piggyback shutting down\n",card->devname);
sdla_down(&card->next->hw);
free_irq(card->wandev.irq, card->next);
card->configured = 0;
card->next->configured = 0;
card->wandev.piggyback = 0;
}else{
/* Master device shutting down */
printk(KERN_INFO "%s: Master shutting down\n",card->devname);
sdla_down(&card->hw);
free_irq(card->wandev.irq, card);
card->configured = 0;
card->next->configured = 0;
}
}else{
printk(KERN_INFO "%s: Device still running %i\n",
nxt_card->devname,nxt_card->wandev.state);
card->configured = 1;
}
}else{
printk(KERN_INFO "%s: Master shutting down\n",card->devname);
sdla_down(&card->hw);
free_irq(card->wandev.irq, card);
card->configured = 0;
}
return;
}
/*============================================================================
* Driver I/O control.
* o verify arguments
* o perform requested action
*
* This function is called when router handles one of the reserved user
* IOCTLs. Note that 'arg' stil points to user address space.
*/
static int ioctl(struct wan_device* wandev, unsigned cmd, unsigned long arg)
{
sdla_t* card;
int err;
/* sanity checks */
if ((wandev == NULL) || (wandev->private == NULL))
return -EFAULT;
if (wandev->state == WAN_UNCONFIGURED)
return -ENODEV;
card = wandev->private;
if(card->hw.type != SDLA_S514){
disable_irq(card->hw.irq);
}
if (test_bit(SEND_CRIT, (void*)&wandev->critical)) {
return -EAGAIN;
}
switch (cmd) {
case WANPIPE_DUMP:
err = ioctl_dump(wandev->private, (void*)arg);
break;
case WANPIPE_EXEC:
err = ioctl_exec(wandev->private, (void*)arg, cmd);
break;
default:
err = -EINVAL;
}
return err;
}
/****** Driver IOCTL Handlers ***********************************************/
/*============================================================================
* Dump adapter memory to user buffer.
* o verify request structure
* o copy request structure to kernel data space
* o verify length/offset
* o verify user buffer
* o copy adapter memory image to user buffer
*
* Note: when dumping memory, this routine switches curent dual-port memory
* vector, so care must be taken to avoid racing conditions.
*/
static int ioctl_dump (sdla_t* card, sdla_dump_t* u_dump)
{
sdla_dump_t dump;
unsigned winsize;
unsigned long oldvec; /* DPM window vector */
unsigned long smp_flags;
int err = 0;
if(copy_from_user((void*)&dump, (void*)u_dump, sizeof(sdla_dump_t)))
return -EFAULT;
if ((dump.magic != WANPIPE_MAGIC) ||
(dump.offset + dump.length > card->hw.memory))
return -EINVAL;
winsize = card->hw.dpmsize;
if(card->hw.type != SDLA_S514) {
lock_adapter_irq(&card->wandev.lock, &smp_flags);
oldvec = card->hw.vector;
while (dump.length) {
/* current offset */
unsigned pos = dump.offset % winsize;
/* current vector */
unsigned long vec = dump.offset - pos;
unsigned len = (dump.length > (winsize - pos)) ?
(winsize - pos) : dump.length;
/* relocate window */
if (sdla_mapmem(&card->hw, vec) != 0) {
err = -EIO;
break;
}
if(copy_to_user((void *)dump.ptr,
(u8 *)card->hw.dpmbase + pos, len)){
unlock_adapter_irq(&card->wandev.lock, &smp_flags);
return -EFAULT;
}
dump.length -= len;
dump.offset += len;
dump.ptr = (char*)dump.ptr + len;
}
sdla_mapmem(&card->hw, oldvec);/* restore DPM window position */
unlock_adapter_irq(&card->wandev.lock, &smp_flags);
}else {
if(copy_to_user((void *)dump.ptr,
(u8 *)card->hw.dpmbase + dump.offset, dump.length)){
return -EFAULT;
}
}
return err;
}
/*============================================================================
* Execute adapter firmware command.
* o verify request structure
* o copy request structure to kernel data space
* o call protocol-specific 'exec' function
*/
static int ioctl_exec (sdla_t* card, sdla_exec_t* u_exec, int cmd)
{
sdla_exec_t exec;
int err=0;
if (card->exec == NULL && cmd == WANPIPE_EXEC){
return -ENODEV;
}
if(copy_from_user((void*)&exec, (void*)u_exec, sizeof(sdla_exec_t)))
return -EFAULT;
if ((exec.magic != WANPIPE_MAGIC) || (exec.cmd == NULL))
return -EINVAL;
switch (cmd) {
case WANPIPE_EXEC:
err = card->exec(card, exec.cmd, exec.data);
break;
}
return err;
}
/******* Miscellaneous ******************************************************/
/*============================================================================
* SDLA Interrupt Service Routine.
* o acknowledge SDLA hardware interrupt.
* o call protocol-specific interrupt service routine, if any.
*/
STATIC irqreturn_t sdla_isr (int irq, void* dev_id, struct pt_regs *regs)
{
#define card ((sdla_t*)dev_id)
if(card->hw.type == SDLA_S514) { /* handle interrrupt on S514 */
u32 int_status;
unsigned char CPU_no = card->hw.S514_cpu_no[0];
unsigned char card_found_for_IRQ;
u8 IRQ_count = 0;
for(;;) {
read_S514_int_stat(&card->hw, &int_status);
/* check if the interrupt is for this device */
if(!((unsigned char)int_status &
(IRQ_CPU_A | IRQ_CPU_B)))
return IRQ_HANDLED;
/* if the IRQ is for both CPUs on the same adapter, */
/* then alter the interrupt status so as to handle */
/* one CPU at a time */
if(((unsigned char)int_status & (IRQ_CPU_A | IRQ_CPU_B))
== (IRQ_CPU_A | IRQ_CPU_B)) {
int_status &= (CPU_no == S514_CPU_A) ?
~IRQ_CPU_B : ~IRQ_CPU_A;
}
card_found_for_IRQ = 0;
/* check to see that the CPU number for this device */
/* corresponds to the interrupt status read */
switch (CPU_no) {
case S514_CPU_A:
if((unsigned char)int_status &
IRQ_CPU_A)
card_found_for_IRQ = 1;
break;
case S514_CPU_B:
if((unsigned char)int_status &
IRQ_CPU_B)
card_found_for_IRQ = 1;
break;
}
/* exit if the interrupt is for another CPU on the */
/* same IRQ */
if(!card_found_for_IRQ)
return IRQ_HANDLED;
if (!card ||
(card->wandev.state == WAN_UNCONFIGURED && !card->configured)){
printk(KERN_INFO
"Received IRQ %d for CPU #%c\n",
irq, CPU_no);
printk(KERN_INFO
"IRQ for unconfigured adapter\n");
S514_intack(&card->hw, int_status);
return IRQ_HANDLED;
}
if (card->in_isr) {
printk(KERN_INFO
"%s: interrupt re-entrancy on IRQ %d\n",
card->devname, card->wandev.irq);
S514_intack(&card->hw, int_status);
return IRQ_HANDLED;
}
spin_lock(&card->wandev.lock);
if (card->next){
spin_lock(&card->next->wandev.lock);
}
S514_intack(&card->hw, int_status);
if (card->isr)
card->isr(card);
if (card->next){
spin_unlock(&card->next->wandev.lock);
}
spin_unlock(&card->wandev.lock);
/* handle a maximum of two interrupts (one for each */
/* CPU on the adapter) before returning */
if((++ IRQ_count) == 2)
return IRQ_HANDLED;
}
}
else { /* handle interrupt on S508 adapter */
if (!card || ((card->wandev.state == WAN_UNCONFIGURED) && !card->configured))
return IRQ_HANDLED;
if (card->in_isr) {
printk(KERN_INFO
"%s: interrupt re-entrancy on IRQ %d!\n",
card->devname, card->wandev.irq);
return IRQ_HANDLED;
}
spin_lock(&card->wandev.lock);
if (card->next){
spin_lock(&card->next->wandev.lock);
}
sdla_intack(&card->hw);
if (card->isr)
card->isr(card);
if (card->next){
spin_unlock(&card->next->wandev.lock);
}
spin_unlock(&card->wandev.lock);
}
return IRQ_HANDLED;
#undef card
}
/*============================================================================
* This routine is called by the protocol-specific modules when network
* interface is being open. The only reason we need this, is because we
* have to call MOD_INC_USE_COUNT, but cannot include 'module.h' where it's
* defined more than once into the same kernel module.
*/
void wanpipe_open (sdla_t* card)
{
++card->open_cnt;
}
/*============================================================================
* This routine is called by the protocol-specific modules when network
* interface is being closed. The only reason we need this, is because we
* have to call MOD_DEC_USE_COUNT, but cannot include 'module.h' where it's
* defined more than once into the same kernel module.
*/
void wanpipe_close (sdla_t* card)
{
--card->open_cnt;
}
/*============================================================================
* Set WAN device state.
*/
void wanpipe_set_state (sdla_t* card, int state)
{
if (card->wandev.state != state) {
switch (state) {
case WAN_CONNECTED:
printk (KERN_INFO "%s: link connected!\n",
card->devname);
break;
case WAN_CONNECTING:
printk (KERN_INFO "%s: link connecting...\n",
card->devname);
break;
case WAN_DISCONNECTED:
printk (KERN_INFO "%s: link disconnected!\n",
card->devname);
break;
}
card->wandev.state = state;
}
card->state_tick = jiffies;
}
sdla_t * wanpipe_find_card (char *name)
{
int cnt;
for (cnt = 0; cnt < ncards; ++ cnt) {
sdla_t* card = &card_array[cnt];
if (!strcmp(card->devname,name))
return card;
}
return NULL;
}
sdla_t * wanpipe_find_card_num (int num)
{
if (num < 1 || num > ncards)
return NULL;
num--;
return &card_array[num];
}
/*
* @work_pointer: work_struct to be done;
* should already have PREPARE_WORK() or
* INIT_WORK() done on it by caller;
*/
void wanpipe_queue_work (struct work_struct *work_pointer)
{
if (test_and_set_bit(1, (void*)&wanpipe_bh_critical))
printk(KERN_INFO "CRITICAL IN QUEUING WORK\n");
queue_work(wanpipe_wq, work_pointer);
clear_bit(1,(void*)&wanpipe_bh_critical);
}
void wakeup_sk_bh(struct net_device *dev)
{
wanpipe_common_t *chan = dev->priv;
if (test_bit(0,&chan->common_critical))
return;
if (chan->sk && chan->tx_timer){
chan->tx_timer->expires=jiffies+1;
add_timer(chan->tx_timer);
}
}
int change_dev_flags(struct net_device *dev, unsigned flags)
{
struct ifreq if_info;
mm_segment_t fs = get_fs();
int err;
memset(&if_info, 0, sizeof(if_info));
strcpy(if_info.ifr_name, dev->name);
if_info.ifr_flags = flags;
set_fs(get_ds()); /* get user space block */
err = devinet_ioctl(SIOCSIFFLAGS, &if_info);
set_fs(fs);
return err;
}
unsigned long get_ip_address(struct net_device *dev, int option)
{
struct in_ifaddr *ifaddr;
struct in_device *in_dev;
unsigned long addr = 0;
rcu_read_lock();
if ((in_dev = __in_dev_get_rcu(dev)) == NULL){
goto out;
}
if ((ifaddr = in_dev->ifa_list)== NULL ){
goto out;
}
switch (option){
case WAN_LOCAL_IP:
addr = ifaddr->ifa_local;
break;
case WAN_POINTOPOINT_IP:
addr = ifaddr->ifa_address;
break;
case WAN_NETMASK_IP:
addr = ifaddr->ifa_mask;
break;
case WAN_BROADCAST_IP:
addr = ifaddr->ifa_broadcast;
break;
default:
break;
}
out:
rcu_read_unlock();
return addr;
}
void add_gateway(sdla_t *card, struct net_device *dev)
{
mm_segment_t oldfs;
struct rtentry route;
int res;
memset((char*)&route,0,sizeof(struct rtentry));
((struct sockaddr_in *)
&(route.rt_dst))->sin_addr.s_addr = 0;
((struct sockaddr_in *)
&(route.rt_dst))->sin_family = AF_INET;
((struct sockaddr_in *)
&(route.rt_genmask))->sin_addr.s_addr = 0;
((struct sockaddr_in *)
&(route.rt_genmask)) ->sin_family = AF_INET;
route.rt_flags = 0;
route.rt_dev = dev->name;
oldfs = get_fs();
set_fs(get_ds());
res = ip_rt_ioctl(SIOCADDRT,&route);
set_fs(oldfs);
if (res == 0){
printk(KERN_INFO "%s: Gateway added for %s\n",
card->devname,dev->name);
}
return;
}
MODULE_LICENSE("GPL");
/****** End *********************************************************/
/*****************************************************************************
* wanpipe_multppp.c Multi-Port PPP driver module.
*
* Authors: Nenad Corbic <ncorbic@sangoma.com>
*
* Copyright: (c) 1995-2001 Sangoma Technologies Inc.
*
* 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.
* ============================================================================
* Dec 15 2000 Updated for 2.4.X kernel
* Nov 15 2000 Fixed the SyncPPP support for kernels 2.2.16 and higher.
* The pppstruct has changed.
* Jul 13 2000 Using the kernel Syncppp module on top of RAW Wanpipe CHDLC
* module.
*****************************************************************************/
#include <linux/module.h>
#include <linux/kernel.h> /* printk(), and other useful stuff */
#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/wanrouter.h> /* WAN router definitions */
#include <linux/wanpipe.h> /* WANPIPE common user API definitions */
#include <linux/if_arp.h> /* ARPHRD_* defines */
#include <linux/jiffies.h> /* time_after() macro */
#include <linux/in.h> /* sockaddr_in */
#include <linux/inet.h>
#include <linux/if.h>
#include <asm/byteorder.h> /* htons(), etc. */
#include <linux/sdlapci.h>
#include <asm/io.h>
#include <linux/sdla_chdlc.h> /* CHDLC firmware API definitions */
#include <linux/sdla_asy.h> /* CHDLC (async) API definitions */
#include <linux/if_wanpipe_common.h> /* Socket Driver common area */
#include <linux/if_wanpipe.h>
#include <linux/inetdevice.h>
#include <asm/uaccess.h>
#include <net/syncppp.h>
/****** Defines & Macros ****************************************************/
#ifdef _DEBUG_
#define STATIC
#else
#define STATIC static
#endif
/* reasons for enabling the timer interrupt on the adapter */
#define TMR_INT_ENABLED_UDP 0x01
#define TMR_INT_ENABLED_UPDATE 0x02
#define TMR_INT_ENABLED_CONFIG 0x04
#define CHDLC_DFLT_DATA_LEN 1500 /* default MTU */
#define CHDLC_HDR_LEN 1
#define IFF_POINTTOPOINT 0x10
#define CHDLC_API 0x01
#define PORT(x) (x == 0 ? "PRIMARY" : "SECONDARY" )
#define MAX_BH_BUFF 10
#define CRC_LENGTH 2
#define PPP_HEADER_LEN 4
/******Data Structures*****************************************************/
/* This structure is placed in the private data area of the device structure.
* The card structure used to occupy the private area but now the following
* structure will incorporate the card structure along with CHDLC specific data
*/
typedef struct chdlc_private_area
{
void *if_ptr; /* General Pointer used by SPPP */
wanpipe_common_t common;
sdla_t *card;
int TracingEnabled; /* For enabling Tracing */
unsigned long curr_trace_addr; /* Used for Tracing */
unsigned long start_trace_addr;
unsigned long end_trace_addr;
unsigned long base_addr_trace_buffer;
unsigned long end_addr_trace_buffer;
unsigned short number_trace_elements;
unsigned available_buffer_space;
unsigned long router_start_time;
unsigned char route_status;
unsigned char route_removed;
unsigned long tick_counter; /* For 5s timeout counter */
unsigned long router_up_time;
u32 IP_address; /* IP addressing */
u32 IP_netmask;
unsigned char mc; /* Mulitcast support on/off */
unsigned short udp_pkt_lgth; /* udp packet processing */
char udp_pkt_src;
char udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT];
unsigned short timer_int_enabled;
char update_comms_stats; /* updating comms stats */
//FIXME: add driver stats as per frame relay!
} chdlc_private_area_t;
/* Route Status options */
#define NO_ROUTE 0x00
#define ADD_ROUTE 0x01
#define ROUTE_ADDED 0x02
#define REMOVE_ROUTE 0x03
/* variable for keeping track of enabling/disabling FT1 monitor status */
static int rCount = 0;
/* variable for tracking how many interfaces to open for WANPIPE on the
two ports */
extern void disable_irq(unsigned int);
extern void enable_irq(unsigned int);
/****** Function Prototypes *************************************************/
/* WAN link driver entry points. These are called by the WAN router module. */
static int update(struct wan_device* wandev);
static int new_if(struct wan_device* wandev, struct net_device* dev,
wanif_conf_t* conf);
static int del_if(struct wan_device* wandev, struct net_device* dev);
/* Network device interface */
static int if_init(struct net_device* dev);
static int if_open(struct net_device* dev);
static int if_close(struct net_device* dev);
static int if_send(struct sk_buff* skb, struct net_device* dev);
static struct net_device_stats* if_stats(struct net_device* dev);
static void if_tx_timeout(struct net_device *dev);
/* CHDLC Firmware interface functions */
static int chdlc_configure (sdla_t* card, void* data);
static int chdlc_comm_enable (sdla_t* card);
static int chdlc_comm_disable (sdla_t* card);
static int chdlc_read_version (sdla_t* card, char* str);
static int chdlc_set_intr_mode (sdla_t* card, unsigned mode);
static int chdlc_send (sdla_t* card, void* data, unsigned len);
static int chdlc_read_comm_err_stats (sdla_t* card);
static int chdlc_read_op_stats (sdla_t* card);
static int config_chdlc (sdla_t *card);
/* Miscellaneous CHDLC Functions */
static int set_chdlc_config (sdla_t* card);
static void init_chdlc_tx_rx_buff(sdla_t* card, struct net_device *dev);
static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb);
static int process_chdlc_exception(sdla_t *card);
static int process_global_exception(sdla_t *card);
static int update_comms_stats(sdla_t* card,
chdlc_private_area_t* chdlc_priv_area);
static void port_set_state (sdla_t *card, int);
/* Interrupt handlers */
static void wsppp_isr (sdla_t* card);
static void rx_intr (sdla_t* card);
static void timer_intr(sdla_t *);
/* Miscellaneous functions */
static int reply_udp( unsigned char *data, unsigned int mbox_len );
static int intr_test( sdla_t* card);
static int udp_pkt_type( struct sk_buff *skb , sdla_t* card);
static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card,
struct sk_buff *skb, struct net_device* dev,
chdlc_private_area_t* chdlc_priv_area);
static int process_udp_mgmt_pkt(sdla_t* card, struct net_device* dev,
chdlc_private_area_t* chdlc_priv_area);
static unsigned short calc_checksum (char *, int);
static void s508_lock (sdla_t *card, unsigned long *smp_flags);
static void s508_unlock (sdla_t *card, unsigned long *smp_flags);
static void send_ppp_term_request(struct net_device *dev);
static int Intr_test_counter;
/****** Public Functions ****************************************************/
/*============================================================================
* Cisco HDLC protocol initialization routine.
*
* This routine is called by the main WANPIPE module during setup. At this
* point adapter is completely initialized and firmware is running.
* o read firmware version (to make sure it's alive)
* o configure adapter
* o initialize protocol-specific fields of the adapter data space.
*
* Return: 0 o.k.
* < 0 failure.
*/
int wsppp_init (sdla_t* card, wandev_conf_t* conf)
{
unsigned char port_num;
int err;
unsigned long max_permitted_baud = 0;
SHARED_MEMORY_INFO_STRUCT *flags;
union
{
char str[80];
} u;
volatile CHDLC_MAILBOX_STRUCT* mb;
CHDLC_MAILBOX_STRUCT* mb1;
unsigned long timeout;
/* Verify configuration ID */
if (conf->config_id != WANCONFIG_MPPP) {
printk(KERN_INFO "%s: invalid configuration ID %u!\n",
card->devname, conf->config_id);
return -EINVAL;
}
/* Find out which Port to use */
if ((conf->comm_port == WANOPT_PRI) || (conf->comm_port == WANOPT_SEC)){
if (card->next){
if (conf->comm_port != card->next->u.c.comm_port){
card->u.c.comm_port = conf->comm_port;
}else{
printk(KERN_ERR "%s: ERROR - %s port used!\n",
card->wandev.name, PORT(conf->comm_port));
return -EINVAL;
}
}else{
card->u.c.comm_port = conf->comm_port;
}
}else{
printk(KERN_ERR "%s: ERROR - Invalid Port Selected!\n",
card->wandev.name);
return -EINVAL;
}
/* Initialize protocol-specific fields */
if(card->hw.type != SDLA_S514){
if (card->u.c.comm_port == WANOPT_PRI){
card->mbox = (void *) card->hw.dpmbase;
}else{
card->mbox = (void *) card->hw.dpmbase +
SEC_BASE_ADDR_MB_STRUCT - PRI_BASE_ADDR_MB_STRUCT;
}
}else{
/* for a S514 adapter, set a pointer to the actual mailbox in the */
/* allocated virtual memory area */
if (card->u.c.comm_port == WANOPT_PRI){
card->mbox = (void *) card->hw.dpmbase + PRI_BASE_ADDR_MB_STRUCT;
}else{
card->mbox = (void *) card->hw.dpmbase + SEC_BASE_ADDR_MB_STRUCT;
}
}
mb = mb1 = card->mbox;
if (!card->configured){
/* The board will place an 'I' in the return code to indicate that it is
ready to accept commands. We expect this to be completed in less
than 1 second. */
timeout = jiffies + 1 * HZ;
while (mb->return_code != 'I') /* Wait 1s for board to initialize */
if (time_after(jiffies, timeout)) break;
if (mb->return_code != 'I') {
printk(KERN_INFO
"%s: Initialization not completed by adapter\n",
card->devname);
printk(KERN_INFO "Please contact Sangoma representative.\n");
return -EIO;
}
}
/* Read firmware version. Note that when adapter initializes, it
* clears the mailbox, so it may appear that the first command was
* executed successfully when in fact it was merely erased. To work
* around this, we execute the first command twice.
*/
if (chdlc_read_version(card, u.str))
return -EIO;
printk(KERN_INFO "%s: Running Raw CHDLC firmware v%s\n"
"%s: for Multi-Port PPP protocol.\n",
card->devname,u.str,card->devname);
card->isr = &wsppp_isr;
card->poll = NULL;
card->exec = NULL;
card->wandev.update = &update;
card->wandev.new_if = &new_if;
card->wandev.del_if = &del_if;
card->wandev.udp_port = conf->udp_port;
card->wandev.new_if_cnt = 0;
/* reset the number of times the 'update()' proc has been called */
card->u.c.update_call_count = 0;
card->wandev.ttl = conf->ttl;
card->wandev.interface = conf->interface;
if ((card->u.c.comm_port == WANOPT_SEC && conf->interface == WANOPT_V35)&&
card->hw.type != SDLA_S514){
printk(KERN_INFO "%s: ERROR - V35 Interface not supported on S508 %s port \n",
card->devname, PORT(card->u.c.comm_port));
return -EIO;
}
card->wandev.clocking = conf->clocking;
port_num = card->u.c.comm_port;
/* Setup Port Bps */
if(card->wandev.clocking) {
if((port_num == WANOPT_PRI) || card->u.c.receive_only) {
/* For Primary Port 0 */
max_permitted_baud =
(card->hw.type == SDLA_S514) ?
PRI_MAX_BAUD_RATE_S514 :
PRI_MAX_BAUD_RATE_S508;
}
else if(port_num == WANOPT_SEC) {
/* For Secondary Port 1 */
max_permitted_baud =
(card->hw.type == SDLA_S514) ?
SEC_MAX_BAUD_RATE_S514 :
SEC_MAX_BAUD_RATE_S508;
}
if(conf->bps > max_permitted_baud) {
conf->bps = max_permitted_baud;
printk(KERN_INFO "%s: Baud too high!\n",
card->wandev.name);
printk(KERN_INFO "%s: Baud rate set to %lu bps\n",
card->wandev.name, max_permitted_baud);
}
card->wandev.bps = conf->bps;
}else{
card->wandev.bps = 0;
}
/* Setup the Port MTU */
if((port_num == WANOPT_PRI) || card->u.c.receive_only) {
/* For Primary Port 0 */
card->wandev.mtu =
(conf->mtu >= MIN_LGTH_CHDLC_DATA_CFG) ?
min_t(unsigned int, conf->mtu, PRI_MAX_NO_DATA_BYTES_IN_FRAME) :
CHDLC_DFLT_DATA_LEN;
} else if(port_num == WANOPT_SEC) {
/* For Secondary Port 1 */
card->wandev.mtu =
(conf->mtu >= MIN_LGTH_CHDLC_DATA_CFG) ?
min_t(unsigned int, conf->mtu, SEC_MAX_NO_DATA_BYTES_IN_FRAME) :
CHDLC_DFLT_DATA_LEN;
}
/* Add on a PPP Header */
card->wandev.mtu += PPP_HEADER_LEN;
/* Set up the interrupt status area */
/* Read the CHDLC Configuration and obtain:
* Ptr to shared memory infor struct
* Use this pointer to calculate the value of card->u.c.flags !
*/
mb1->buffer_length = 0;
mb1->command = READ_CHDLC_CONFIGURATION;
err = sdla_exec(mb1) ? mb1->return_code : CMD_TIMEOUT;
if(err != COMMAND_OK) {
clear_bit(1, (void*)&card->wandev.critical);
if(card->hw.type != SDLA_S514)
enable_irq(card->hw.irq);
chdlc_error(card, err, mb1);
return -EIO;
}
if(card->hw.type == SDLA_S514){
card->u.c.flags = (void *)(card->hw.dpmbase +
(((CHDLC_CONFIGURATION_STRUCT *)mb1->data)->
ptr_shared_mem_info_struct));
}else{
card->u.c.flags = (void *)(card->hw.dpmbase +
(((CHDLC_CONFIGURATION_STRUCT *)mb1->data)->
ptr_shared_mem_info_struct % SDLA_WINDOWSIZE));
}
flags = card->u.c.flags;
/* This is for the ports link state */
card->wandev.state = WAN_DUALPORT;
card->u.c.state = WAN_DISCONNECTED;
if (!card->wandev.piggyback){
err = intr_test(card);
if(err || (Intr_test_counter < MAX_INTR_TEST_COUNTER)) {
printk(KERN_ERR "%s: Interrupt test failed (%i)\n",
card->devname, Intr_test_counter);
printk(KERN_ERR "%s: Please choose another interrupt\n",
card->devname);
return -EIO;
}
printk(KERN_INFO "%s: Interrupt test passed (%i)\n",
card->devname, Intr_test_counter);
}
if (chdlc_set_intr_mode(card, APP_INT_ON_TIMER)){
printk (KERN_INFO "%s: Failed to set interrupt triggers!\n",
card->devname);
return -EIO;
}
/* Mask the Timer interrupt */
flags->interrupt_info_struct.interrupt_permission &=
~APP_INT_ON_TIMER;
printk(KERN_INFO "\n");
return 0;
}
/******* WAN Device Driver Entry Points *************************************/
/*============================================================================
* Update device status & statistics
* This procedure is called when updating the PROC file system and returns
* various communications statistics. These statistics are accumulated from 3
* different locations:
* 1) The 'if_stats' recorded for the device.
* 2) Communication error statistics on the adapter.
* 3) CHDLC operational statistics on the adapter.
* The board level statistics are read during a timer interrupt. Note that we
* read the error and operational statistics during consecitive timer ticks so
* as to minimize the time that we are inside the interrupt handler.
*
*/
static int update(struct wan_device* wandev)
{
sdla_t* card = wandev->private;
struct net_device* dev;
volatile chdlc_private_area_t* chdlc_priv_area;
SHARED_MEMORY_INFO_STRUCT *flags;
unsigned long timeout;
/* sanity checks */
if((wandev == NULL) || (wandev->private == NULL))
return -EFAULT;
if(wandev->state == WAN_UNCONFIGURED)
return -ENODEV;
/* more sanity checks */
if(!card->u.c.flags)
return -ENODEV;
if((dev=card->wandev.dev) == NULL)
return -ENODEV;
if((chdlc_priv_area=dev->priv) == NULL)
return -ENODEV;
flags = card->u.c.flags;
if(chdlc_priv_area->update_comms_stats){
return -EAGAIN;
}
/* we will need 2 timer interrupts to complete the */
/* reading of the statistics */
chdlc_priv_area->update_comms_stats = 2;
flags->interrupt_info_struct.interrupt_permission |= APP_INT_ON_TIMER;
chdlc_priv_area->timer_int_enabled = TMR_INT_ENABLED_UPDATE;
/* wait a maximum of 1 second for the statistics to be updated */
timeout = jiffies + 1 * HZ;
for(;;) {
if(chdlc_priv_area->update_comms_stats == 0)
break;
if (time_after(jiffies, timeout)){
chdlc_priv_area->update_comms_stats = 0;
chdlc_priv_area->timer_int_enabled &=
~TMR_INT_ENABLED_UPDATE;
return -EAGAIN;
}
}
return 0;
}
/*============================================================================
* Create new logical channel.
* This routine is called by the router when ROUTER_IFNEW IOCTL is being
* handled.
* o parse media- and hardware-specific configuration
* o make sure that a new channel can be created
* o allocate resources, if necessary
* o prepare network device structure for registaration.
*
* Return: 0 o.k.
* < 0 failure (channel will not be created)
*/
static int new_if(struct wan_device* wandev, struct net_device* pdev,
wanif_conf_t* conf)
{
struct ppp_device *pppdev = (struct ppp_device *)pdev;
struct net_device *dev = NULL;
struct sppp *sp;
sdla_t* card = wandev->private;
chdlc_private_area_t* chdlc_priv_area;
if ((conf->name[0] == '\0') || (strlen(conf->name) > WAN_IFNAME_SZ)) {
printk(KERN_INFO "%s: invalid interface name!\n",
card->devname);
return -EINVAL;
}
/* allocate and initialize private data */
chdlc_priv_area = kmalloc(sizeof(chdlc_private_area_t), GFP_KERNEL);
if(chdlc_priv_area == NULL)
return -ENOMEM;
memset(chdlc_priv_area, 0, sizeof(chdlc_private_area_t));
chdlc_priv_area->card = card;
/* initialize data */
strcpy(card->u.c.if_name, conf->name);
if(card->wandev.new_if_cnt > 0) {
kfree(chdlc_priv_area);
return -EEXIST;
}
card->wandev.new_if_cnt++;
chdlc_priv_area->TracingEnabled = 0;
//We don't need this any more
chdlc_priv_area->route_status = NO_ROUTE;
chdlc_priv_area->route_removed = 0;
printk(KERN_INFO "%s: Firmware running in HDLC STREAMING Mode\n",
wandev->name);
/* Setup wanpipe as a router (WANPIPE) or as an API */
if( strcmp(conf->usedby, "WANPIPE") == 0) {
printk(KERN_INFO "%s: Driver running in WANPIPE mode!\n",
wandev->name);
card->u.c.usedby = WANPIPE;
} else {
printk(KERN_INFO
"%s: API Mode is not supported for SyncPPP!\n",
wandev->name);
kfree(chdlc_priv_area);
return -EINVAL;
}
/* Get Multicast Information */
chdlc_priv_area->mc = conf->mc;
chdlc_priv_area->if_ptr = pppdev;
/* prepare network device data space for registration */
strcpy(dev->name,card->u.c.if_name);
/* Attach PPP protocol layer to pppdev
* The sppp_attach() will initilize the dev structure
* and setup ppp layer protocols.
* All we have to do is to bind in:
* if_open(), if_close(), if_send() and get_stats() functions.
*/
sppp_attach(pppdev);
dev = pppdev->dev;
sp = &pppdev->sppp;
/* Enable PPP Debugging */
// FIXME Fix this up somehow
//sp->pp_flags |= PP_DEBUG;
sp->pp_flags &= ~PP_CISCO;
dev->init = &if_init;
dev->priv = chdlc_priv_area;
return 0;
}
/*============================================================================
* Delete logical channel.
*/
static int del_if(struct wan_device* wandev, struct net_device* dev)
{
chdlc_private_area_t *chdlc_priv_area = dev->priv;
sdla_t *card = chdlc_priv_area->card;
unsigned long smp_lock;
/* Detach the PPP layer */
printk(KERN_INFO "%s: Detaching SyncPPP Module from %s\n",
wandev->name,dev->name);
lock_adapter_irq(&wandev->lock,&smp_lock);
sppp_detach(dev);
chdlc_priv_area->if_ptr=NULL;
chdlc_set_intr_mode(card, 0);
if (card->u.c.comm_enabled)
chdlc_comm_disable(card);
unlock_adapter_irq(&wandev->lock,&smp_lock);
port_set_state(card, WAN_DISCONNECTED);
return 0;
}
/****** Network Device Interface ********************************************/
/*============================================================================
* Initialize Linux network interface.
*
* This routine is called only once for each interface, during Linux network
* interface registration. Returning anything but zero will fail interface
* registration.
*/
static int if_init(struct net_device* dev)
{
chdlc_private_area_t* chdlc_priv_area = dev->priv;
sdla_t* card = chdlc_priv_area->card;
struct wan_device* wandev = &card->wandev;
/* NOTE: Most of the dev initialization was
* done in sppp_attach(), called by new_if()
* function. All we have to do here is
* to link four major routines below.
*/
/* Initialize device driver entry points */
dev->open = &if_open;
dev->stop = &if_close;
dev->hard_start_xmit = &if_send;
dev->get_stats = &if_stats;
dev->tx_timeout = &if_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
/* Initialize hardware parameters */
dev->irq = wandev->irq;
dev->dma = wandev->dma;
dev->base_addr = wandev->ioport;
dev->mem_start = wandev->maddr;
dev->mem_end = wandev->maddr + wandev->msize - 1;
/* Set transmit buffer queue length
* If we over fill this queue the packets will
* be droped by the kernel.
* sppp_attach() sets this to 10, but
* 100 will give us more room at low speeds.
*/
dev->tx_queue_len = 100;
return 0;
}
/*============================================================================
* Handle transmit timeout event from netif watchdog
*/
static void if_tx_timeout(struct net_device *dev)
{
chdlc_private_area_t* chan = dev->priv;
sdla_t *card = chan->card;
/* If our device stays busy for at least 5 seconds then we will
* kick start the device by making dev->tbusy = 0. We expect
* that our device never stays busy more than 5 seconds. So this
* is only used as a last resort.
*/
++card->wandev.stats.collisions;
printk (KERN_INFO "%s: Transmit timed out on %s\n", card->devname,dev->name);
netif_wake_queue (dev);
}
/*============================================================================
* Open network interface.
* o enable communications and interrupts.
* o prevent module from unloading by incrementing use count
*
* Return 0 if O.k. or errno.
*/
static int if_open(struct net_device* dev)
{
chdlc_private_area_t* chdlc_priv_area = dev->priv;
sdla_t* card = chdlc_priv_area->card;
struct timeval tv;
SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
/* Only one open per interface is allowed */
if (netif_running(dev))
return -EBUSY;
/* Start PPP Layer */
if (sppp_open(dev)){
return -EIO;
}
do_gettimeofday(&tv);
chdlc_priv_area->router_start_time = tv.tv_sec;
netif_start_queue(dev);
wanpipe_open(card);
chdlc_priv_area->timer_int_enabled |= TMR_INT_ENABLED_CONFIG;
flags->interrupt_info_struct.interrupt_permission |= APP_INT_ON_TIMER;
return 0;
}
/*============================================================================
* Close network interface.
* o if this is the last close, then disable communications and interrupts.
* o reset flags.
*/
static int if_close(struct net_device* dev)
{
chdlc_private_area_t* chdlc_priv_area = dev->priv;
sdla_t* card = chdlc_priv_area->card;
/* Stop the PPP Layer */
sppp_close(dev);
netif_stop_queue(dev);
wanpipe_close(card);
return 0;
}
/*============================================================================
* Send a packet on a network interface.
* o set tbusy flag (marks start of the transmission) to block a timer-based
* transmit from overlapping.
* o check link state. If link is not up, then drop the packet.
* o execute adapter send command.
* o free socket buffer
*
* Return: 0 complete (socket buffer must be freed)
* non-0 packet may be re-transmitted (tbusy must be set)
*
* Notes:
* 1. This routine is called either by the protocol stack or by the "net
* bottom half" (with interrupts enabled).
* 2. Setting tbusy flag will inhibit further transmit requests from the
* protocol stack and can be used for flow control with protocol layer.
*/
static int if_send(struct sk_buff* skb, struct net_device* dev)
{
chdlc_private_area_t *chdlc_priv_area = dev->priv;
sdla_t *card = chdlc_priv_area->card;
SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
INTERRUPT_INFORMATION_STRUCT *chdlc_int = &flags->interrupt_info_struct;
int udp_type = 0;
unsigned long smp_flags;
int err=0;
netif_stop_queue(dev);
if (skb == NULL){
/* If we get here, some higher layer thinks we've missed an
* tx-done interrupt.
*/
printk(KERN_INFO "%s: Received NULL skb buffer! interface %s got kicked!\n",
card->devname, dev->name);
netif_wake_queue(dev);
return 0;
}
if (ntohs(skb->protocol) != htons(PVC_PROT)){
/* check the udp packet type */
udp_type = udp_pkt_type(skb, card);
if (udp_type == UDP_CPIPE_TYPE){
if(store_udp_mgmt_pkt(UDP_PKT_FRM_STACK, card, skb, dev,
chdlc_priv_area)){
chdlc_int->interrupt_permission |=
APP_INT_ON_TIMER;
}
netif_start_queue(dev);
return 0;
}
}
/* Lock the 508 Card: SMP is supported */
if(card->hw.type != SDLA_S514){
s508_lock(card,&smp_flags);
}
if (test_and_set_bit(SEND_CRIT, (void*)&card->wandev.critical)){
printk(KERN_INFO "%s: Critical in if_send: %lx\n",
card->wandev.name,card->wandev.critical);
++card->wandev.stats.tx_dropped;
netif_start_queue(dev);
goto if_send_crit_exit;
}
if (card->wandev.state != WAN_CONNECTED){
++card->wandev.stats.tx_dropped;
netif_start_queue(dev);
goto if_send_crit_exit;
}
if (chdlc_send(card, skb->data, skb->len)){
netif_stop_queue(dev);
}else{
++card->wandev.stats.tx_packets;
card->wandev.stats.tx_bytes += skb->len;
dev->trans_start = jiffies;
netif_start_queue(dev);
}
if_send_crit_exit:
if (!(err=netif_queue_stopped(dev))){
dev_kfree_skb_any(skb);
}else{
chdlc_priv_area->tick_counter = jiffies;
chdlc_int->interrupt_permission |= APP_INT_ON_TX_FRAME;
}
clear_bit(SEND_CRIT, (void*)&card->wandev.critical);
if(card->hw.type != SDLA_S514){
s508_unlock(card,&smp_flags);
}
return err;
}
/*============================================================================
* Reply to UDP Management system.
* Return length of reply.
*/
static int reply_udp( unsigned char *data, unsigned int mbox_len )
{
unsigned short len, udp_length, temp, ip_length;
unsigned long ip_temp;
int even_bound = 0;
chdlc_udp_pkt_t *c_udp_pkt = (chdlc_udp_pkt_t *)data;
/* Set length of packet */
len = sizeof(ip_pkt_t)+
sizeof(udp_pkt_t)+
sizeof(wp_mgmt_t)+
sizeof(cblock_t)+
sizeof(trace_info_t)+
mbox_len;
/* fill in UDP reply */
c_udp_pkt->wp_mgmt.request_reply = UDPMGMT_REPLY;
/* fill in UDP length */
udp_length = sizeof(udp_pkt_t)+
sizeof(wp_mgmt_t)+
sizeof(cblock_t)+
sizeof(trace_info_t)+
mbox_len;
/* put it on an even boundary */
if ( udp_length & 0x0001 ) {
udp_length += 1;
len += 1;
even_bound = 1;
}
temp = (udp_length<<8)|(udp_length>>8);
c_udp_pkt->udp_pkt.udp_length = temp;
/* swap UDP ports */
temp = c_udp_pkt->udp_pkt.udp_src_port;
c_udp_pkt->udp_pkt.udp_src_port =
c_udp_pkt->udp_pkt.udp_dst_port;
c_udp_pkt->udp_pkt.udp_dst_port = temp;
/* add UDP pseudo header */
temp = 0x1100;
*((unsigned short *)(c_udp_pkt->data+mbox_len+even_bound)) = temp;
temp = (udp_length<<8)|(udp_length>>8);
*((unsigned short *)(c_udp_pkt->data+mbox_len+even_bound+2)) = temp;
/* calculate UDP checksum */
c_udp_pkt->udp_pkt.udp_checksum = 0;
c_udp_pkt->udp_pkt.udp_checksum = calc_checksum(&data[UDP_OFFSET],udp_length+UDP_OFFSET);
/* fill in IP length */
ip_length = len;
temp = (ip_length<<8)|(ip_length>>8);
c_udp_pkt->ip_pkt.total_length = temp;
/* swap IP addresses */
ip_temp = c_udp_pkt->ip_pkt.ip_src_address;
c_udp_pkt->ip_pkt.ip_src_address = c_udp_pkt->ip_pkt.ip_dst_address;
c_udp_pkt->ip_pkt.ip_dst_address = ip_temp;
/* fill in IP checksum */
c_udp_pkt->ip_pkt.hdr_checksum = 0;
c_udp_pkt->ip_pkt.hdr_checksum = calc_checksum(data,sizeof(ip_pkt_t));
return len;
} /* reply_udp */
unsigned short calc_checksum (char *data, int len)
{
unsigned short temp;
unsigned long sum=0;
int i;
for( i = 0; i <len; i+=2 ) {
memcpy(&temp,&data[i],2);
sum += (unsigned long)temp;
}
while (sum >> 16 ) {
sum = (sum & 0xffffUL) + (sum >> 16);
}
temp = (unsigned short)sum;
temp = ~temp;
if( temp == 0 )
temp = 0xffff;
return temp;
}
/*============================================================================
* Get ethernet-style interface statistics.
* Return a pointer to struct enet_statistics.
*/
static struct net_device_stats* if_stats(struct net_device* dev)
{
sdla_t *my_card;
chdlc_private_area_t* chdlc_priv_area;
/* Shutdown bug fix. In del_if() we kill
* dev->priv pointer. This function, gets
* called after del_if(), thus check
* if pointer has been deleted */
if ((chdlc_priv_area=dev->priv) == NULL)
return NULL;
my_card = chdlc_priv_area->card;
return &my_card->wandev.stats;
}
/****** Cisco HDLC Firmware Interface Functions *******************************/
/*============================================================================
* Read firmware code version.
* Put code version as ASCII string in str.
*/
static int chdlc_read_version (sdla_t* card, char* str)
{
CHDLC_MAILBOX_STRUCT* mb = card->mbox;
int len;
char err;
mb->buffer_length = 0;
mb->command = READ_CHDLC_CODE_VERSION;
err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
if(err != COMMAND_OK) {
chdlc_error(card,err,mb);
}
else if (str) { /* is not null */
len = mb->buffer_length;
memcpy(str, mb->data, len);
str[len] = '\0';
}
return (err);
}
/*-----------------------------------------------------------------------------
* Configure CHDLC firmware.
*/
static int chdlc_configure (sdla_t* card, void* data)
{
int err;
CHDLC_MAILBOX_STRUCT *mailbox = card->mbox;
int data_length = sizeof(CHDLC_CONFIGURATION_STRUCT);
mailbox->buffer_length = data_length;
memcpy(mailbox->data, data, data_length);
mailbox->command = SET_CHDLC_CONFIGURATION;
err = sdla_exec(mailbox) ? mailbox->return_code : CMD_TIMEOUT;
if (err != COMMAND_OK) chdlc_error (card, err, mailbox);
return err;
}
/*============================================================================
* Set interrupt mode -- HDLC Version.
*/
static int chdlc_set_intr_mode (sdla_t* card, unsigned mode)
{
CHDLC_MAILBOX_STRUCT* mb = card->mbox;
CHDLC_INT_TRIGGERS_STRUCT* int_data =
(CHDLC_INT_TRIGGERS_STRUCT *)mb->data;
int err;
int_data->CHDLC_interrupt_triggers = mode;
int_data->IRQ = card->hw.irq;
int_data->interrupt_timer = 1;
mb->buffer_length = sizeof(CHDLC_INT_TRIGGERS_STRUCT);
mb->command = SET_CHDLC_INTERRUPT_TRIGGERS;
err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
if (err != COMMAND_OK)
chdlc_error (card, err, mb);
return err;
}
/*============================================================================
* Enable communications.
*/
static int chdlc_comm_enable (sdla_t* card)
{
int err;
CHDLC_MAILBOX_STRUCT* mb = card->mbox;
mb->buffer_length = 0;
mb->command = ENABLE_CHDLC_COMMUNICATIONS;
err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
if (err != COMMAND_OK)
chdlc_error(card, err, mb);
else
card->u.c.comm_enabled=1;
return err;
}
/*============================================================================
* Disable communications and Drop the Modem lines (DCD and RTS).
*/
static int chdlc_comm_disable (sdla_t* card)
{
int err;
CHDLC_MAILBOX_STRUCT* mb = card->mbox;
mb->buffer_length = 0;
mb->command = DISABLE_CHDLC_COMMUNICATIONS;
err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
if (err != COMMAND_OK)
chdlc_error(card,err,mb);
return err;
}
/*============================================================================
* Read communication error statistics.
*/
static int chdlc_read_comm_err_stats (sdla_t* card)
{
int err;
CHDLC_MAILBOX_STRUCT* mb = card->mbox;
mb->buffer_length = 0;
mb->command = READ_COMMS_ERROR_STATS;
err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
if (err != COMMAND_OK)
chdlc_error(card,err,mb);
return err;
}
/*============================================================================
* Read CHDLC operational statistics.
*/
static int chdlc_read_op_stats (sdla_t* card)
{
int err;
CHDLC_MAILBOX_STRUCT* mb = card->mbox;
mb->buffer_length = 0;
mb->command = READ_CHDLC_OPERATIONAL_STATS;
err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
if (err != COMMAND_OK)
chdlc_error(card,err,mb);
return err;
}
/*============================================================================
* Update communications error and general packet statistics.
*/
static int update_comms_stats(sdla_t* card,
chdlc_private_area_t* chdlc_priv_area)
{
CHDLC_MAILBOX_STRUCT* mb = card->mbox;
COMMS_ERROR_STATS_STRUCT* err_stats;
CHDLC_OPERATIONAL_STATS_STRUCT *op_stats;
/* on the first timer interrupt, read the comms error statistics */
if(chdlc_priv_area->update_comms_stats == 2) {
if(chdlc_read_comm_err_stats(card))
return 1;
err_stats = (COMMS_ERROR_STATS_STRUCT *)mb->data;
card->wandev.stats.rx_over_errors =
err_stats->Rx_overrun_err_count;
card->wandev.stats.rx_crc_errors =
err_stats->CRC_err_count;
card->wandev.stats.rx_frame_errors =
err_stats->Rx_abort_count;
card->wandev.stats.rx_fifo_errors =
err_stats->Rx_dis_pri_bfrs_full_count;
card->wandev.stats.rx_missed_errors =
card->wandev.stats.rx_fifo_errors;
card->wandev.stats.tx_aborted_errors =
err_stats->sec_Tx_abort_count;
}
/* on the second timer interrupt, read the operational statistics */
else {
if(chdlc_read_op_stats(card))
return 1;
op_stats = (CHDLC_OPERATIONAL_STATS_STRUCT *)mb->data;
card->wandev.stats.rx_length_errors =
(op_stats->Rx_Data_discard_short_count +
op_stats->Rx_Data_discard_long_count);
}
return 0;
}
/*============================================================================
* Send packet.
* Return: 0 - o.k.
* 1 - no transmit buffers available
*/
static int chdlc_send (sdla_t* card, void* data, unsigned len)
{
CHDLC_DATA_TX_STATUS_EL_STRUCT *txbuf = card->u.c.txbuf;
if (txbuf->opp_flag)
return 1;
sdla_poke(&card->hw, txbuf->ptr_data_bfr, data, len);
txbuf->frame_length = len;
txbuf->opp_flag = 1; /* start transmission */
/* Update transmit buffer control fields */
card->u.c.txbuf = ++txbuf;
if ((void*)txbuf > card->u.c.txbuf_last)
card->u.c.txbuf = card->u.c.txbuf_base;
return 0;
}
/****** Firmware Error Handler **********************************************/
/*============================================================================
* Firmware error handler.
* This routine is called whenever firmware command returns non-zero
* return code.
*
* Return zero if previous command has to be cancelled.
*/
static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb)
{
unsigned cmd = mb->command;
switch (err) {
case CMD_TIMEOUT:
printk(KERN_ERR "%s: command 0x%02X timed out!\n",
card->devname, cmd);
break;
case S514_BOTH_PORTS_SAME_CLK_MODE:
if(cmd == SET_CHDLC_CONFIGURATION) {
printk(KERN_INFO
"%s: Configure both ports for the same clock source\n",
card->devname);
break;
}
default:
printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n",
card->devname, cmd, err);
}
return 0;
}
/****** Interrupt Handlers **************************************************/
/*============================================================================
* Cisco HDLC interrupt service routine.
*/
STATIC void wsppp_isr (sdla_t* card)
{
struct net_device* dev;
SHARED_MEMORY_INFO_STRUCT* flags = NULL;
int i;
sdla_t *my_card;
/* Check for which port the interrupt has been generated
* Since Secondary Port is piggybacking on the Primary
* the check must be done here.
*/
flags = card->u.c.flags;
if (!flags->interrupt_info_struct.interrupt_type){
/* Check for a second port (piggybacking) */
if((my_card = card->next)){
flags = my_card->u.c.flags;
if (flags->interrupt_info_struct.interrupt_type){
card = my_card;
card->isr(card);
return;
}
}
}
dev = card->wandev.dev;
card->in_isr = 1;
flags = card->u.c.flags;
/* If we get an interrupt with no network device, stop the interrupts
* and issue an error */
if ((!dev || !dev->priv) && flags->interrupt_info_struct.interrupt_type !=
COMMAND_COMPLETE_APP_INT_PEND){
goto isr_done;
}
/* if critical due to peripheral operations
* ie. update() or getstats() then reset the interrupt and
* wait for the board to retrigger.
*/
if(test_bit(PERI_CRIT, (void*)&card->wandev.critical)) {
flags->interrupt_info_struct.
interrupt_type = 0;
goto isr_done;
}
/* On a 508 Card, if critical due to if_send
* Major Error !!!
*/
if(card->hw.type != SDLA_S514) {
if(test_bit(0, (void*)&card->wandev.critical)) {
printk(KERN_INFO "%s: Critical while in ISR: %lx\n",
card->devname, card->wandev.critical);
goto isr_done;
}
}
switch(flags->interrupt_info_struct.interrupt_type) {
case RX_APP_INT_PEND: /* 0x01: receive interrupt */
rx_intr(card);
break;
case TX_APP_INT_PEND: /* 0x02: transmit interrupt */
flags->interrupt_info_struct.interrupt_permission &=
~APP_INT_ON_TX_FRAME;
netif_wake_queue(dev);
break;
case COMMAND_COMPLETE_APP_INT_PEND:/* 0x04: cmd cplt */
++ Intr_test_counter;
break;
case CHDLC_EXCEP_COND_APP_INT_PEND: /* 0x20 */
process_chdlc_exception(card);
break;
case GLOBAL_EXCEP_COND_APP_INT_PEND:
process_global_exception(card);
break;
case TIMER_APP_INT_PEND:
timer_intr(card);
break;
default:
printk(KERN_INFO "%s: spurious interrupt 0x%02X!\n",
card->devname,
flags->interrupt_info_struct.interrupt_type);
printk(KERN_INFO "Code name: ");
for(i = 0; i < 4; i ++)
printk(KERN_INFO "%c",
flags->global_info_struct.codename[i]);
printk(KERN_INFO "\nCode version: ");
for(i = 0; i < 4; i ++)
printk(KERN_INFO "%c",
flags->global_info_struct.codeversion[i]);
printk(KERN_INFO "\n");
break;
}
isr_done:
card->in_isr = 0;
flags->interrupt_info_struct.interrupt_type = 0;
}
/*============================================================================
* Receive interrupt handler.
*/
static void rx_intr (sdla_t* card)
{
struct net_device *dev;
chdlc_private_area_t *chdlc_priv_area;
SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
CHDLC_DATA_RX_STATUS_EL_STRUCT *rxbuf = card->u.c.rxmb;
struct sk_buff *skb;
unsigned len;
unsigned addr = rxbuf->ptr_data_bfr;
void *buf;
int i,udp_type;
if (rxbuf->opp_flag != 0x01) {
printk(KERN_INFO
"%s: corrupted Rx buffer @ 0x%X, flag = 0x%02X!\n",
card->devname, (unsigned)rxbuf, rxbuf->opp_flag);
printk(KERN_INFO "Code name: ");
for(i = 0; i < 4; i ++)
printk(KERN_INFO "%c",
flags->global_info_struct.codename[i]);
printk(KERN_INFO "\nCode version: ");
for(i = 0; i < 4; i ++)
printk(KERN_INFO "%c",
flags->global_info_struct.codeversion[i]);
printk(KERN_INFO "\n");
/* Bug Fix: Mar 6 2000
* If we get a corrupted mailbox, it measn that driver
* is out of sync with the firmware. There is no recovery.
* If we don't turn off all interrupts for this card
* the machine will crash.
*/
printk(KERN_INFO "%s: Critical router failure ...!!!\n", card->devname);
printk(KERN_INFO "Please contact Sangoma Technologies !\n");
chdlc_set_intr_mode(card,0);
return;
}
dev = card->wandev.dev;
if (!dev){
goto rx_exit;
}
if (!netif_running(dev)){
goto rx_exit;
}
chdlc_priv_area = dev->priv;
if (rxbuf->error_flag){
goto rx_exit;
}
/* Take off two CRC bytes */
if (rxbuf->frame_length < 7 || rxbuf->frame_length > 1506 ){
goto rx_exit;
}
len = rxbuf->frame_length - CRC_LENGTH;
/* Allocate socket buffer */
skb = dev_alloc_skb(len);
if (skb == NULL) {
if (net_ratelimit()){
printk(KERN_INFO "%s: no socket buffers available!\n",
card->devname);
}
++card->wandev.stats.rx_dropped;
goto rx_exit;
}
/* Copy data to the socket buffer */
if((addr + len) > card->u.c.rx_top + 1) {
unsigned tmp = card->u.c.rx_top - addr + 1;
buf = skb_put(skb, tmp);
sdla_peek(&card->hw, addr, buf, tmp);
addr = card->u.c.rx_base;
len -= tmp;
}
buf = skb_put(skb, len);
sdla_peek(&card->hw, addr, buf, len);
skb->protocol = htons(ETH_P_WAN_PPP);
card->wandev.stats.rx_packets ++;
card->wandev.stats.rx_bytes += skb->len;
udp_type = udp_pkt_type( skb, card );
if(udp_type == UDP_CPIPE_TYPE) {
if(store_udp_mgmt_pkt(UDP_PKT_FRM_NETWORK,
card, skb, dev, chdlc_priv_area)) {
flags->interrupt_info_struct.
interrupt_permission |=
APP_INT_ON_TIMER;
}
}else{
/* Pass it up the protocol stack */
skb->dev = dev;
skb->mac.raw = skb->data;
netif_rx(skb);
dev->last_rx = jiffies;
}
rx_exit:
/* Release buffer element and calculate a pointer to the next one */
rxbuf->opp_flag = 0x00;
card->u.c.rxmb = ++ rxbuf;
if((void*)rxbuf > card->u.c.rxbuf_last){
card->u.c.rxmb = card->u.c.rxbuf_base;
}
}
/*============================================================================
* Timer interrupt handler.
* The timer interrupt is used for two purposes:
* 1) Processing udp calls from 'cpipemon'.
* 2) Reading board-level statistics for updating the proc file system.
*/
void timer_intr(sdla_t *card)
{
struct net_device* dev;
chdlc_private_area_t* chdlc_priv_area = NULL;
SHARED_MEMORY_INFO_STRUCT* flags = NULL;
dev = card->wandev.dev;
chdlc_priv_area = dev->priv;
if (chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_CONFIG) {
if (!config_chdlc(card)){
chdlc_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_CONFIG;
}
}
/* process a udp call if pending */
if(chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_UDP) {
process_udp_mgmt_pkt(card, dev,
chdlc_priv_area);
chdlc_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_UDP;
}
/* read the communications statistics if required */
if(chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_UPDATE) {
update_comms_stats(card, chdlc_priv_area);
if(!(-- chdlc_priv_area->update_comms_stats)) {
chdlc_priv_area->timer_int_enabled &=
~TMR_INT_ENABLED_UPDATE;
}
}
/* only disable the timer interrupt if there are no udp or statistic */
/* updates pending */
if(!chdlc_priv_area->timer_int_enabled) {
flags = card->u.c.flags;
flags->interrupt_info_struct.interrupt_permission &=
~APP_INT_ON_TIMER;
}
}
/*------------------------------------------------------------------------------
Miscellaneous Functions
- set_chdlc_config() used to set configuration options on the board
------------------------------------------------------------------------------*/
static int set_chdlc_config(sdla_t* card)
{
CHDLC_CONFIGURATION_STRUCT cfg;
memset(&cfg, 0, sizeof(CHDLC_CONFIGURATION_STRUCT));
if(card->wandev.clocking)
cfg.baud_rate = card->wandev.bps;
cfg.line_config_options = (card->wandev.interface == WANOPT_RS232) ?
INTERFACE_LEVEL_RS232 : INTERFACE_LEVEL_V35;
cfg.modem_config_options = 0;
//API OPTIONS
cfg.CHDLC_API_options = DISCARD_RX_ERROR_FRAMES;
cfg.modem_status_timer = 100;
cfg.CHDLC_protocol_options = HDLC_STREAMING_MODE;
cfg.percent_data_buffer_for_Tx = 50;
cfg.CHDLC_statistics_options = (CHDLC_TX_DATA_BYTE_COUNT_STAT |
CHDLC_RX_DATA_BYTE_COUNT_STAT);
cfg.max_CHDLC_data_field_length = card->wandev.mtu;
cfg.transmit_keepalive_timer = 0;
cfg.receive_keepalive_timer = 0;
cfg.keepalive_error_tolerance = 0;
cfg.SLARP_request_timer = 0;
cfg.IP_address = 0;
cfg.IP_netmask = 0;
return chdlc_configure(card, &cfg);
}
/*============================================================================
* Process global exception condition
*/
static int process_global_exception(sdla_t *card)
{
CHDLC_MAILBOX_STRUCT* mbox = card->mbox;
int err;
mbox->buffer_length = 0;
mbox->command = READ_GLOBAL_EXCEPTION_CONDITION;
err = sdla_exec(mbox) ? mbox->return_code : CMD_TIMEOUT;
if(err != CMD_TIMEOUT ){
switch(mbox->return_code) {
case EXCEP_MODEM_STATUS_CHANGE:
printk(KERN_INFO "%s: Modem status change\n",
card->devname);
switch(mbox->data[0] & (DCD_HIGH | CTS_HIGH)) {
case (DCD_HIGH):
printk(KERN_INFO "%s: DCD high, CTS low\n",card->devname);
break;
case (CTS_HIGH):
printk(KERN_INFO "%s: DCD low, CTS high\n",card->devname);
break;
case ((DCD_HIGH | CTS_HIGH)):
printk(KERN_INFO "%s: DCD high, CTS high\n",card->devname);
break;
default:
printk(KERN_INFO "%s: DCD low, CTS low\n",card->devname);
break;
}
if (!(mbox->data[0] & DCD_HIGH) || !(mbox->data[0] & DCD_HIGH)){
//printk(KERN_INFO "Sending TERM Request Manually !\n");
send_ppp_term_request(card->wandev.dev);
}
break;
case EXCEP_TRC_DISABLED:
printk(KERN_INFO "%s: Line trace disabled\n",
card->devname);
break;
case EXCEP_IRQ_TIMEOUT:
printk(KERN_INFO "%s: IRQ timeout occurred\n",
card->devname);
break;
default:
printk(KERN_INFO "%s: Global exception %x\n",
card->devname, mbox->return_code);
break;
}
}
return 0;
}
/*============================================================================
* Process chdlc exception condition
*/
static int process_chdlc_exception(sdla_t *card)
{
CHDLC_MAILBOX_STRUCT* mb = card->mbox;
int err;
mb->buffer_length = 0;
mb->command = READ_CHDLC_EXCEPTION_CONDITION;
err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
if(err != CMD_TIMEOUT) {
switch (err) {
case EXCEP_LINK_ACTIVE:
port_set_state(card, WAN_CONNECTED);
break;
case EXCEP_LINK_INACTIVE_MODEM:
port_set_state(card, WAN_DISCONNECTED);
break;
case EXCEP_LOOPBACK_CONDITION:
printk(KERN_INFO "%s: Loopback Condition Detected.\n",
card->devname);
break;
case NO_CHDLC_EXCEP_COND_TO_REPORT:
printk(KERN_INFO "%s: No exceptions reported.\n",
card->devname);
break;
default:
printk(KERN_INFO "%s: Exception Condition %x!\n",
card->devname,err);
break;
}
}
return 0;
}
/*=============================================================================
* Store a UDP management packet for later processing.
*/
static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card,
struct sk_buff *skb, struct net_device* dev,
chdlc_private_area_t* chdlc_priv_area )
{
int udp_pkt_stored = 0;
if(!chdlc_priv_area->udp_pkt_lgth &&
(skb->len <= MAX_LGTH_UDP_MGNT_PKT)) {
chdlc_priv_area->udp_pkt_lgth = skb->len;
chdlc_priv_area->udp_pkt_src = udp_pkt_src;
memcpy(chdlc_priv_area->udp_pkt_data, skb->data, skb->len);
chdlc_priv_area->timer_int_enabled = TMR_INT_ENABLED_UDP;
udp_pkt_stored = 1;
}
if(udp_pkt_src == UDP_PKT_FRM_STACK)
dev_kfree_skb_any(skb);
else
dev_kfree_skb_any(skb);
return(udp_pkt_stored);
}
/*=============================================================================
* Process UDP management packet.
*/
static int process_udp_mgmt_pkt(sdla_t* card, struct net_device* dev,
chdlc_private_area_t* chdlc_priv_area )
{
unsigned char *buf;
unsigned int frames, len;
struct sk_buff *new_skb;
unsigned short buffer_length, real_len;
unsigned long data_ptr;
unsigned data_length;
int udp_mgmt_req_valid = 1;
CHDLC_MAILBOX_STRUCT *mb = card->mbox;
SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
chdlc_udp_pkt_t *chdlc_udp_pkt;
struct timeval tv;
int err;
char ut_char;
chdlc_udp_pkt = (chdlc_udp_pkt_t *) chdlc_priv_area->udp_pkt_data;
if(chdlc_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK) {
switch(chdlc_udp_pkt->cblock.command) {
case READ_GLOBAL_STATISTICS:
case READ_MODEM_STATUS:
case READ_CHDLC_LINK_STATUS:
case CPIPE_ROUTER_UP_TIME:
case READ_COMMS_ERROR_STATS:
case READ_CHDLC_OPERATIONAL_STATS:
/* These two commands are executed for
* each request */
case READ_CHDLC_CONFIGURATION:
case READ_CHDLC_CODE_VERSION:
udp_mgmt_req_valid = 1;
break;
default:
udp_mgmt_req_valid = 0;
break;
}
}
if(!udp_mgmt_req_valid) {
/* set length to 0 */
chdlc_udp_pkt->cblock.buffer_length = 0;
/* set return code */
chdlc_udp_pkt->cblock.return_code = 0xCD;
if (net_ratelimit()){
printk(KERN_INFO
"%s: Warning, Illegal UDP command attempted from network: %x\n",
card->devname,chdlc_udp_pkt->cblock.command);
}
} else {
unsigned long trace_status_cfg_addr = 0;
TRACE_STATUS_EL_CFG_STRUCT trace_cfg_struct;
TRACE_STATUS_ELEMENT_STRUCT trace_element_struct;
switch(chdlc_udp_pkt->cblock.command) {
case CPIPE_ENABLE_TRACING:
if (!chdlc_priv_area->TracingEnabled) {
/* OPERATE_DATALINE_MONITOR */
mb->buffer_length = sizeof(LINE_TRACE_CONFIG_STRUCT);
mb->command = SET_TRACE_CONFIGURATION;
((LINE_TRACE_CONFIG_STRUCT *)mb->data)->
trace_config = TRACE_ACTIVE;
/* Trace delay mode is not used because it slows
down transfer and results in a standoff situation
when there is a lot of data */
/* Configure the Trace based on user inputs */
((LINE_TRACE_CONFIG_STRUCT *)mb->data)->trace_config |=
chdlc_udp_pkt->data[0];
((LINE_TRACE_CONFIG_STRUCT *)mb->data)->
trace_deactivation_timer = 4000;
err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
if (err != COMMAND_OK) {
chdlc_error(card,err,mb);
card->TracingEnabled = 0;
chdlc_udp_pkt->cblock.return_code = err;
mb->buffer_length = 0;
break;
}
/* Get the base address of the trace element list */
mb->buffer_length = 0;
mb->command = READ_TRACE_CONFIGURATION;
err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
if (err != COMMAND_OK) {
chdlc_error(card,err,mb);
chdlc_priv_area->TracingEnabled = 0;
chdlc_udp_pkt->cblock.return_code = err;
mb->buffer_length = 0;
break;
}
trace_status_cfg_addr =((LINE_TRACE_CONFIG_STRUCT *)
mb->data) -> ptr_trace_stat_el_cfg_struct;
sdla_peek(&card->hw, trace_status_cfg_addr,
&trace_cfg_struct, sizeof(trace_cfg_struct));
chdlc_priv_area->start_trace_addr = trace_cfg_struct.
base_addr_trace_status_elements;
chdlc_priv_area->number_trace_elements =
trace_cfg_struct.number_trace_status_elements;
chdlc_priv_area->end_trace_addr = (unsigned long)
((TRACE_STATUS_ELEMENT_STRUCT *)
chdlc_priv_area->start_trace_addr +
(chdlc_priv_area->number_trace_elements - 1));
chdlc_priv_area->base_addr_trace_buffer =
trace_cfg_struct.base_addr_trace_buffer;
chdlc_priv_area->end_addr_trace_buffer =
trace_cfg_struct.end_addr_trace_buffer;
chdlc_priv_area->curr_trace_addr =
trace_cfg_struct.next_trace_element_to_use;
chdlc_priv_area->available_buffer_space = 2000 -
sizeof(ip_pkt_t) -
sizeof(udp_pkt_t) -
sizeof(wp_mgmt_t) -
sizeof(cblock_t) -
sizeof(trace_info_t);
}
chdlc_udp_pkt->cblock.return_code = COMMAND_OK;
mb->buffer_length = 0;
chdlc_priv_area->TracingEnabled = 1;
break;
case CPIPE_DISABLE_TRACING:
if (chdlc_priv_area->TracingEnabled) {
/* OPERATE_DATALINE_MONITOR */
mb->buffer_length = sizeof(LINE_TRACE_CONFIG_STRUCT);
mb->command = SET_TRACE_CONFIGURATION;
((LINE_TRACE_CONFIG_STRUCT *)mb->data)->
trace_config = TRACE_INACTIVE;
err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
}
chdlc_priv_area->TracingEnabled = 0;
chdlc_udp_pkt->cblock.return_code = COMMAND_OK;
mb->buffer_length = 0;
break;
case CPIPE_GET_TRACE_INFO:
if (!chdlc_priv_area->TracingEnabled) {
chdlc_udp_pkt->cblock.return_code = 1;
mb->buffer_length = 0;
break;
}
chdlc_udp_pkt->trace_info.ismoredata = 0x00;
buffer_length = 0; /* offset of packet already occupied */
for (frames=0; frames < chdlc_priv_area->number_trace_elements; frames++){
trace_pkt_t *trace_pkt = (trace_pkt_t *)
&chdlc_udp_pkt->data[buffer_length];
sdla_peek(&card->hw, chdlc_priv_area->curr_trace_addr,
(unsigned char *)&trace_element_struct,
sizeof(TRACE_STATUS_ELEMENT_STRUCT));
if (trace_element_struct.opp_flag == 0x00) {
break;
}
/* get pointer to real data */
data_ptr = trace_element_struct.ptr_data_bfr;
/* See if there is actual data on the trace buffer */
if (data_ptr){
data_length = trace_element_struct.trace_length;
}else{
data_length = 0;
chdlc_udp_pkt->trace_info.ismoredata = 0x01;
}
if( (chdlc_priv_area->available_buffer_space - buffer_length)
< ( sizeof(trace_pkt_t) + data_length) ) {
/* indicate there are more frames on board & exit */
chdlc_udp_pkt->trace_info.ismoredata = 0x01;
break;
}
trace_pkt->status = trace_element_struct.trace_type;
trace_pkt->time_stamp =
trace_element_struct.trace_time_stamp;
trace_pkt->real_length =
trace_element_struct.trace_length;
/* see if we can fit the frame into the user buffer */
real_len = trace_pkt->real_length;
if (data_ptr == 0) {
trace_pkt->data_avail = 0x00;
} else {
unsigned tmp = 0;
/* get the data from circular buffer
must check for end of buffer */
trace_pkt->data_avail = 0x01;
if ((data_ptr + real_len) >
chdlc_priv_area->end_addr_trace_buffer + 1){
tmp = chdlc_priv_area->end_addr_trace_buffer - data_ptr + 1;
sdla_peek(&card->hw, data_ptr,
trace_pkt->data,tmp);
data_ptr = chdlc_priv_area->base_addr_trace_buffer;
}
sdla_peek(&card->hw, data_ptr,
&trace_pkt->data[tmp], real_len - tmp);
}
/* zero the opp flag to show we got the frame */
ut_char = 0x00;
sdla_poke(&card->hw, chdlc_priv_area->curr_trace_addr, &ut_char, 1);
/* now move onto the next frame */
chdlc_priv_area->curr_trace_addr += sizeof(TRACE_STATUS_ELEMENT_STRUCT);
/* check if we went over the last address */
if ( chdlc_priv_area->curr_trace_addr > chdlc_priv_area->end_trace_addr ) {
chdlc_priv_area->curr_trace_addr = chdlc_priv_area->start_trace_addr;
}
if(trace_pkt->data_avail == 0x01) {
buffer_length += real_len - 1;
}
/* for the header */
buffer_length += sizeof(trace_pkt_t);
} /* For Loop */
if (frames == chdlc_priv_area->number_trace_elements){
chdlc_udp_pkt->trace_info.ismoredata = 0x01;
}
chdlc_udp_pkt->trace_info.num_frames = frames;
mb->buffer_length = buffer_length;
chdlc_udp_pkt->cblock.buffer_length = buffer_length;
chdlc_udp_pkt->cblock.return_code = COMMAND_OK;
break;
case CPIPE_FT1_READ_STATUS:
((unsigned char *)chdlc_udp_pkt->data )[0] =
flags->FT1_info_struct.parallel_port_A_input;
((unsigned char *)chdlc_udp_pkt->data )[1] =
flags->FT1_info_struct.parallel_port_B_input;
chdlc_udp_pkt->cblock.return_code = COMMAND_OK;
mb->buffer_length = 2;
break;
case CPIPE_ROUTER_UP_TIME:
do_gettimeofday( &tv );
chdlc_priv_area->router_up_time = tv.tv_sec -
chdlc_priv_area->router_start_time;
*(unsigned long *)&chdlc_udp_pkt->data =
chdlc_priv_area->router_up_time;
mb->buffer_length = sizeof(unsigned long);
break;
case FT1_MONITOR_STATUS_CTRL:
/* Enable FT1 MONITOR STATUS */
if ((chdlc_udp_pkt->data[0] & ENABLE_READ_FT1_STATUS) ||
(chdlc_udp_pkt->data[0] & ENABLE_READ_FT1_OP_STATS)) {
if( rCount++ != 0 ) {
chdlc_udp_pkt->cblock.
return_code = COMMAND_OK;
mb->buffer_length = 1;
break;
}
}
/* Disable FT1 MONITOR STATUS */
if( chdlc_udp_pkt->data[0] == 0) {
if( --rCount != 0) {
chdlc_udp_pkt->cblock.
return_code = COMMAND_OK;
mb->buffer_length = 1;
break;
}
}
default:
/* it's a board command */
mb->command = chdlc_udp_pkt->cblock.command;
mb->buffer_length = chdlc_udp_pkt->cblock.buffer_length;
if (mb->buffer_length) {
memcpy(&mb->data, (unsigned char *) chdlc_udp_pkt->
data, mb->buffer_length);
}
/* run the command on the board */
err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
if (err != COMMAND_OK) {
break;
}
/* copy the result back to our buffer */
memcpy(&chdlc_udp_pkt->cblock, mb, sizeof(cblock_t));
if (mb->buffer_length) {
memcpy(&chdlc_udp_pkt->data, &mb->data,
mb->buffer_length);
}
} /* end of switch */
} /* end of else */
/* Fill UDP TTL */
chdlc_udp_pkt->ip_pkt.ttl = card->wandev.ttl;
len = reply_udp(chdlc_priv_area->udp_pkt_data, mb->buffer_length);
if(chdlc_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK) {
if(!chdlc_send(card, chdlc_priv_area->udp_pkt_data, len)) {
++ card->wandev.stats.tx_packets;
card->wandev.stats.tx_bytes += len;
}
} else {
/* Pass it up the stack
Allocate socket buffer */
if ((new_skb = dev_alloc_skb(len)) != NULL) {
/* copy data into new_skb */
buf = skb_put(new_skb, len);
memcpy(buf, chdlc_priv_area->udp_pkt_data, len);
/* Decapsulate pkt and pass it up the protocol stack */
new_skb->protocol = htons(ETH_P_IP);
new_skb->dev = dev;
new_skb->mac.raw = new_skb->data;
netif_rx(new_skb);
dev->last_rx = jiffies;
} else {
printk(KERN_INFO "%s: no socket buffers available!\n",
card->devname);
}
}
chdlc_priv_area->udp_pkt_lgth = 0;
return 0;
}
/*============================================================================
* Initialize Receive and Transmit Buffers.
*/
static void init_chdlc_tx_rx_buff(sdla_t* card, struct net_device *dev)
{
CHDLC_MAILBOX_STRUCT* mb = card->mbox;
CHDLC_TX_STATUS_EL_CFG_STRUCT *tx_config;
CHDLC_RX_STATUS_EL_CFG_STRUCT *rx_config;
char err;
mb->buffer_length = 0;
mb->command = READ_CHDLC_CONFIGURATION;
err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
if(err != COMMAND_OK) {
chdlc_error(card,err,mb);
return;
}
if(card->hw.type == SDLA_S514) {
tx_config = (CHDLC_TX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase +
(((CHDLC_CONFIGURATION_STRUCT *)mb->data)->
ptr_CHDLC_Tx_stat_el_cfg_struct));
rx_config = (CHDLC_RX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase +
(((CHDLC_CONFIGURATION_STRUCT *)mb->data)->
ptr_CHDLC_Rx_stat_el_cfg_struct));
/* Setup Head and Tails for buffers */
card->u.c.txbuf_base = (void *)(card->hw.dpmbase +
tx_config->base_addr_Tx_status_elements);
card->u.c.txbuf_last =
(CHDLC_DATA_TX_STATUS_EL_STRUCT *)
card->u.c.txbuf_base +
(tx_config->number_Tx_status_elements - 1);
card->u.c.rxbuf_base = (void *)(card->hw.dpmbase +
rx_config->base_addr_Rx_status_elements);
card->u.c.rxbuf_last =
(CHDLC_DATA_RX_STATUS_EL_STRUCT *)
card->u.c.rxbuf_base +
(rx_config->number_Rx_status_elements - 1);
/* Set up next pointer to be used */
card->u.c.txbuf = (void *)(card->hw.dpmbase +
tx_config->next_Tx_status_element_to_use);
card->u.c.rxmb = (void *)(card->hw.dpmbase +
rx_config->next_Rx_status_element_to_use);
}
else {
tx_config = (CHDLC_TX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase +
(((CHDLC_CONFIGURATION_STRUCT *)mb->data)->
ptr_CHDLC_Tx_stat_el_cfg_struct % SDLA_WINDOWSIZE));
rx_config = (CHDLC_RX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase +
(((CHDLC_CONFIGURATION_STRUCT *)mb->data)->
ptr_CHDLC_Rx_stat_el_cfg_struct % SDLA_WINDOWSIZE));
/* Setup Head and Tails for buffers */
card->u.c.txbuf_base = (void *)(card->hw.dpmbase +
(tx_config->base_addr_Tx_status_elements % SDLA_WINDOWSIZE));
card->u.c.txbuf_last =
(CHDLC_DATA_TX_STATUS_EL_STRUCT *)card->u.c.txbuf_base
+ (tx_config->number_Tx_status_elements - 1);
card->u.c.rxbuf_base = (void *)(card->hw.dpmbase +
(rx_config->base_addr_Rx_status_elements % SDLA_WINDOWSIZE));
card->u.c.rxbuf_last =
(CHDLC_DATA_RX_STATUS_EL_STRUCT *)card->u.c.rxbuf_base
+ (rx_config->number_Rx_status_elements - 1);
/* Set up next pointer to be used */
card->u.c.txbuf = (void *)(card->hw.dpmbase +
(tx_config->next_Tx_status_element_to_use % SDLA_WINDOWSIZE));
card->u.c.rxmb = (void *)(card->hw.dpmbase +
(rx_config->next_Rx_status_element_to_use % SDLA_WINDOWSIZE));
}
/* Setup Actual Buffer Start and end addresses */
card->u.c.rx_base = rx_config->base_addr_Rx_buffer;
card->u.c.rx_top = rx_config->end_addr_Rx_buffer;
}
/*=============================================================================
* Perform Interrupt Test by running READ_CHDLC_CODE_VERSION command MAX_INTR
* _TEST_COUNTER times.
*/
static int intr_test( sdla_t* card)
{
CHDLC_MAILBOX_STRUCT* mb = card->mbox;
int err,i;
Intr_test_counter = 0;
/* The critical flag is unset because during initialization (if_open)
* we want the interrupts to be enabled so that when the wpc_isr is
* called it does not exit due to critical flag set.
*/
err = chdlc_set_intr_mode(card, APP_INT_ON_COMMAND_COMPLETE);
if (err == CMD_OK) {
for (i = 0; i < MAX_INTR_TEST_COUNTER; i ++) {
mb->buffer_length = 0;
mb->command = READ_CHDLC_CODE_VERSION;
err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
}
}
else {
return err;
}
err = chdlc_set_intr_mode(card, 0);
if (err != CMD_OK)
return err;
return 0;
}
/*==============================================================================
* Determine what type of UDP call it is. CPIPEAB ?
*/
static int udp_pkt_type(struct sk_buff *skb, sdla_t* card)
{
chdlc_udp_pkt_t *chdlc_udp_pkt = (chdlc_udp_pkt_t *)skb->data;
if (!strncmp(chdlc_udp_pkt->wp_mgmt.signature,UDPMGMT_SIGNATURE,8) &&
(chdlc_udp_pkt->udp_pkt.udp_dst_port == ntohs(card->wandev.udp_port)) &&
(chdlc_udp_pkt->ip_pkt.protocol == UDPMGMT_UDP_PROTOCOL) &&
(chdlc_udp_pkt->wp_mgmt.request_reply == UDPMGMT_REQUEST)) {
return UDP_CPIPE_TYPE;
}
else return UDP_INVALID_TYPE;
}
/*============================================================================
* Set PORT state.
*/
static void port_set_state (sdla_t *card, int state)
{
struct net_device *dev = card->wandev.dev;
chdlc_private_area_t *chdlc_priv_area = dev->priv;
if (card->u.c.state != state)
{
switch (state)
{
case WAN_CONNECTED:
printk (KERN_INFO "%s: HDLC link connected!\n",
card->devname);
break;
case WAN_CONNECTING:
printk (KERN_INFO "%s: HDLC link connecting...\n",
card->devname);
break;
case WAN_DISCONNECTED:
printk (KERN_INFO "%s: HDLC link disconnected!\n",
card->devname);
break;
}
card->wandev.state = card->u.c.state = state;
chdlc_priv_area->common.state = state;
}
}
void s508_lock (sdla_t *card, unsigned long *smp_flags)
{
spin_lock_irqsave(&card->wandev.lock, *smp_flags);
if (card->next){
/* It is ok to use spin_lock here, since we
* already turned off interrupts */
spin_lock(&card->next->wandev.lock);
}
}
void s508_unlock (sdla_t *card, unsigned long *smp_flags)
{
if (card->next){
spin_unlock(&card->next->wandev.lock);
}
spin_unlock_irqrestore(&card->wandev.lock, *smp_flags);
}
/*===========================================================================
* config_chdlc
*
* Configure the chdlc protocol and enable communications.
*
* The if_open() function binds this function to the poll routine.
* Therefore, this function will run every time the chdlc interface
* is brought up. We cannot run this function from the if_open
* because if_open does not have access to the remote IP address.
*
* If the communications are not enabled, proceed to configure
* the card and enable communications.
*
* If the communications are enabled, it means that the interface
* was shutdown by ether the user or driver. In this case, we
* have to check that the IP addresses have not changed. If
* the IP addresses have changed, we have to reconfigure the firmware
* and update the changed IP addresses. Otherwise, just exit.
*
*/
static int config_chdlc (sdla_t *card)
{
struct net_device *dev = card->wandev.dev;
SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
if (card->u.c.comm_enabled){
chdlc_comm_disable(card);
port_set_state(card, WAN_DISCONNECTED);
}
if (set_chdlc_config(card)) {
printk(KERN_INFO "%s: CHDLC Configuration Failed!\n",
card->devname);
return 0;
}
init_chdlc_tx_rx_buff(card, dev);
/* Set interrupt mode and mask */
if (chdlc_set_intr_mode(card, APP_INT_ON_RX_FRAME |
APP_INT_ON_GLOBAL_EXCEP_COND |
APP_INT_ON_TX_FRAME |
APP_INT_ON_CHDLC_EXCEP_COND | APP_INT_ON_TIMER)){
printk (KERN_INFO "%s: Failed to set interrupt triggers!\n",
card->devname);
return 0;
}
/* Mask the Transmit and Timer interrupt */
flags->interrupt_info_struct.interrupt_permission &=
~(APP_INT_ON_TX_FRAME | APP_INT_ON_TIMER);
if (chdlc_comm_enable(card) != 0) {
printk(KERN_INFO "%s: Failed to enable chdlc communications!\n",
card->devname);
flags->interrupt_info_struct.interrupt_permission = 0;
card->u.c.comm_enabled=0;
chdlc_set_intr_mode(card,0);
return 0;
}
/* Initialize Rx/Tx buffer control fields */
port_set_state(card, WAN_CONNECTING);
return 0;
}
static void send_ppp_term_request(struct net_device *dev)
{
struct sk_buff *new_skb;
unsigned char *buf;
if ((new_skb = dev_alloc_skb(8)) != NULL) {
/* copy data into new_skb */
buf = skb_put(new_skb, 8);
sprintf(buf,"%c%c%c%c%c%c%c%c", 0xFF,0x03,0xC0,0x21,0x05,0x98,0x00,0x07);
/* Decapsulate pkt and pass it up the protocol stack */
new_skb->protocol = htons(ETH_P_WAN_PPP);
new_skb->dev = dev;
new_skb->mac.raw = new_skb->data;
netif_rx(new_skb);
dev->last_rx = jiffies;
}
}
MODULE_LICENSE("GPL");
/****** End ****************************************************************/
/*****************************************************************************
* sdla_asy.h Header file for the Sangoma S508/S514 asynchronous code API
*
* Author: Gideon Hack
*
* Copyright: (c) 2000 Sangoma Technologies Inc.
*
* 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.
* ============================================================================
*
* Jan 28, 2000 Gideon Hack Initial Version
*
*****************************************************************************/
#ifndef _WANPIPE_ASYNC_H
#define _WANPIPE_ASYNC_H
/* ----------------------------------------------------------------------------
* Interface commands
* --------------------------------------------------------------------------*/
#define SET_ASY_CONFIGURATION 0xE2 /* set the asychronous operational configuration */
#define READ_ASY_CONFIGURATION 0xE3 /* read the current asychronous operational configuration */
#define ENABLE_ASY_COMMUNICATIONS 0xE4 /* enable asychronous communications */
#define DISABLE_ASY_COMMUNICATIONS 0xE5 /* disable asychronous communications */
#define READ_ASY_OPERATIONAL_STATS 0xE7 /* retrieve the asychronous operational statistics */
#define FLUSH_ASY_OPERATIONAL_STATS 0xE8 /* flush the asychronous operational statistics */
#define TRANSMIT_ASY_BREAK_SIGNAL 0xEC /* transmit an asychronous break signal */
/* ----------------------------------------------------------------------------
* Return codes from interface commands
* --------------------------------------------------------------------------*/
#define COMMAND_INVALID_FOR_PORT 0x50 /* the command is invalid for the selected port */
#define DISABLE_ASY_COMMS_BEFORE_CFG 0xE1 /* communications must be disabled before setting the configuration */
#define ASY_COMMS_ENABLED 0xE1 /* communications are currently enabled */
#define ASY_COMMS_DISABLED 0xE1 /* communications are currently disabled */
#define ASY_CFG_BEFORE_COMMS_ENABLED 0xE2 /* perform a SET_ASY_CONFIGURATION before enabling comms */
#define LGTH_ASY_CFG_DATA_INVALID 0xE2 /* the length of the passed configuration data is invalid */
#define INVALID_ASY_CFG_DATA 0xE3 /* the passed configuration data is invalid */
#define ASY_BREAK_SIGNAL_BUSY 0xEC /* a break signal is being transmitted */
/* ----------------------------------------------------------------------------
* Constants for the SET_ASY_CONFIGURATION/READ_ASY_CONFIGURATION command
* --------------------------------------------------------------------------*/
/* the asynchronous configuration structure */
typedef struct {
unsigned long baud_rate PACKED; /* the baud rate */
unsigned short line_config_options PACKED; /* line configuration options */
unsigned short modem_config_options PACKED; /* modem configuration options */
unsigned short asy_API_options PACKED; /* asynchronous API options */
unsigned short asy_protocol_options PACKED; /* asynchronous protocol options */
unsigned short Tx_bits_per_char PACKED; /* number of bits per tx character */
unsigned short Rx_bits_per_char PACKED; /* number of bits per received character */
unsigned short stop_bits PACKED; /* number of stop bits per character */
unsigned short parity PACKED; /* parity definition */
unsigned short break_timer PACKED; /* the break signal timer */
unsigned short asy_Rx_inter_char_timer PACKED; /* the receive inter-character timer */
unsigned short asy_Rx_complete_length PACKED; /* the receive 'buffer complete' length */
unsigned short XON_char PACKED; /* the XON character */
unsigned short XOFF_char PACKED; /* the XOFF character */
unsigned short asy_statistics_options PACKED; /* async operational stat options */
unsigned long ptr_shared_mem_info_struct PACKED;/* ptr to the shared memory area information structure */
unsigned long ptr_asy_Tx_stat_el_cfg_struct PACKED;/* ptr to the transmit status element configuration structure */
unsigned long ptr_asy_Rx_stat_el_cfg_struct PACKED;/* ptr to the receive status element configuration structure */
} ASY_CONFIGURATION_STRUCT;
/* permitted minimum and maximum values for setting the asynchronous configuration */
#define MIN_ASY_BAUD_RATE 50 /* maximum baud rate */
#define MAX_ASY_BAUD_RATE 250000 /* minimum baud rate */
#define MIN_ASY_BITS_PER_CHAR 5 /* minimum number of bits per character */
#define MAX_ASY_BITS_PER_CHAR 8 /* maximum number of bits per character */
#define MIN_BREAK_TMR_VAL 0 /* minimum break signal timer */
#define MAX_BREAK_TMR_VAL 5000 /* maximum break signal timer */
#define MIN_ASY_RX_INTER_CHAR_TMR 0 /* minimum receive inter-character timer */
#define MAX_ASY_RX_INTER_CHAR_TMR 30000 /* maximum receive inter-character timer */
#define MIN_ASY_RX_CPLT_LENGTH 0 /* minimum receive 'length complete' value */
#define MAX_ASY_RX_CPLT_LENGTH 2000 /* maximum receive 'length complete' value */
/* bit settings for the 'asy_API_options' */
#define ASY_RX_DATA_TRANSPARENT 0x0001 /* do not strip parity and unused bits from received characters */
/* bit settings for the 'asy_protocol_options' */
#define ASY_RTS_HS_FOR_RX 0x0001 /* RTS handshaking is used for reception control */
#define ASY_XON_XOFF_HS_FOR_RX 0x0002 /* XON/XOFF handshaking is used for reception control */
#define ASY_XON_XOFF_HS_FOR_TX 0x0004 /* XON/XOFF handshaking is used for transmission control */
#define ASY_DCD_HS_FOR_TX 0x0008 /* DCD handshaking is used for transmission control */
#define ASY_CTS_HS_FOR_TX 0x0020 /* CTS handshaking is used for transmission control */
/* bit settings for the 'stop_bits' definition */
#define ONE_STOP_BIT 1 /* representation for 1 stop bit */
#define TWO_STOP_BITS 2 /* representation for 2 stop bits */
#define ONE_AND_A_HALF_STOP_BITS 3 /* representation for 1.5 stop bits */
/* bit settings for the 'parity' definition */
#define NO_PARITY 0 /* representation for no parity */
#define ODD_PARITY 1 /* representation for odd parity */
#define EVEN_PARITY 2 /* representation for even parity */
/* ----------------------------------------------------------------------------
* Constants for the READ_COMMS_ERROR_STATS command (asynchronous mode)
* --------------------------------------------------------------------------*/
/* the communications error statistics structure */
typedef struct {
unsigned short Rx_overrun_err_count PACKED; /* receiver overrun error count */
unsigned short Rx_parity_err_count PACKED; /* parity errors received count */
unsigned short Rx_framing_err_count PACKED; /* framing errors received count */
unsigned short comms_err_stat_reserved_1 PACKED;/* reserved for later use */
unsigned short comms_err_stat_reserved_2 PACKED;/* reserved for later use */
unsigned short comms_err_stat_reserved_3 PACKED;/* reserved for later use */
unsigned short comms_err_stat_reserved_4 PACKED;/* reserved for later use */
unsigned short comms_err_stat_reserved_5 PACKED;/* reserved for later use */
unsigned short DCD_state_change_count PACKED; /* DCD state change count */
unsigned short CTS_state_change_count PACKED; /* CTS state change count */
} ASY_COMMS_ERROR_STATS_STRUCT;
/* ----------------------------------------------------------------------------
* Constants for the READ_ASY_OPERATIONAL_STATS command
* --------------------------------------------------------------------------*/
/* the asynchronous operational statistics structure */
typedef struct {
/* Data transmission statistics */
unsigned long Data_blocks_Tx_count PACKED;/* number of blocks transmitted */
unsigned long Data_bytes_Tx_count PACKED;/* number of bytes transmitted */
unsigned long Data_Tx_throughput PACKED;/* transmit throughput */
unsigned long no_ms_for_Data_Tx_thruput_comp PACKED;/* millisecond time used for the Tx throughput computation */
unsigned long Tx_Data_discard_lgth_err_count PACKED;/* number of Data blocks discarded (length error) */
unsigned long reserved_Data_frm_Tx_stat1 PACKED;/* reserved for later use */
unsigned long reserved_Data_frm_Tx_stat2 PACKED;/* reserved for later use */
unsigned long reserved_Data_frm_Tx_stat3 PACKED;/* reserved for later use */
/* Data reception statistics */
unsigned long Data_blocks_Rx_count PACKED;/* number of blocks received */
unsigned long Data_bytes_Rx_count PACKED;/* number of bytes received */
unsigned long Data_Rx_throughput PACKED;/* receive throughput */
unsigned long no_ms_for_Data_Rx_thruput_comp PACKED;/* millisecond time used for the Rx throughput computation */
unsigned long Rx_Data_bytes_discard_count PACKED;/* received Data bytes discarded */
unsigned long reserved_Data_frm_Rx_stat1 PACKED;/* reserved for later use */
/* handshaking protocol statistics */
unsigned short XON_chars_Tx_count PACKED; /* number of XON characters transmitted */
unsigned short XOFF_chars_Tx_count PACKED; /* number of XOFF characters transmitted */
unsigned short XON_chars_Rx_count PACKED; /* number of XON characters received */
unsigned short XOFF_chars_Rx_count PACKED; /* number of XOFF characters received */
unsigned short Tx_halt_modem_low_count PACKED; /* number of times Tx halted (modem line low) */
unsigned short Rx_halt_RTS_low_count PACKED; /* number of times Rx halted by setting RTS low */
unsigned long reserved_handshaking_stat1 PACKED;/* reserved for later use */
/* break statistics */
unsigned short break_Tx_count PACKED; /* number of break sequences transmitted */
unsigned short break_Rx_count PACKED; /* number of break sequences received */
unsigned long reserved_break_stat1 PACKED;/* reserved for later use */
/* miscellaneous statistics */
unsigned long reserved_misc_stat1 PACKED; /* reserved for later use */
unsigned long reserved_misc_stat2 PACKED; /* reserved for later use */
} ASY_OPERATIONAL_STATS_STRUCT;
/* ----------------------------------------------------------------------------
* Constants for Data transmission
* --------------------------------------------------------------------------*/
/* the Data block transmit status element configuration structure */
typedef struct {
unsigned short number_Tx_status_elements PACKED; /* number of transmit status elements */
unsigned long base_addr_Tx_status_elements PACKED; /* base address of the transmit element list */
unsigned long next_Tx_status_element_to_use PACKED; /* pointer to the next transmit element to be used */
} ASY_TX_STATUS_EL_CFG_STRUCT;
/* the Data block transmit status element structure */
typedef struct {
unsigned char opp_flag PACKED; /* opp flag */
unsigned short data_length PACKED; /* length of the block to be transmitted */
unsigned char reserved_1 PACKED; /* reserved for internal use */
unsigned long reserved_2 PACKED; /* reserved for internal use */
unsigned long reserved_3 PACKED; /* reserved for internal use */
unsigned long ptr_data_bfr PACKED; /* pointer to the data area */
} ASY_DATA_TX_STATUS_EL_STRUCT;
/* ----------------------------------------------------------------------------
* Constants for Data reception
* --------------------------------------------------------------------------*/
/* the Data block receive status element configuration structure */
typedef struct {
unsigned short number_Rx_status_elements PACKED;/* number of receive status elements */
unsigned long base_addr_Rx_status_elements PACKED;/* base address of the receive element list */
unsigned long next_Rx_status_element_to_use PACKED;/* pointer to the next receive element to be used */
unsigned long base_addr_Rx_buffer PACKED;/* base address of the receive data buffer */
unsigned long end_addr_Rx_buffer PACKED;/* end address of the receive data buffer */
} ASY_RX_STATUS_EL_CFG_STRUCT;
/* the Data block receive status element structure */
typedef struct {
unsigned char opp_flag PACKED; /* opp flag */
unsigned short data_length PACKED; /* length of the received data block */
unsigned char reserved_1 PACKED; /* reserved for internal use */
unsigned short time_stamp PACKED; /* receive time stamp (HDLC_STREAMING_MODE) */
unsigned short data_buffered PACKED; /* the number of data bytes still buffered */
unsigned long reserved_2 PACKED; /* reserved for internal use */
unsigned long ptr_data_bfr PACKED; /* pointer to the data area */
} ASY_DATA_RX_STATUS_EL_STRUCT;
#endif
/*************************************************************************
sdla_chdlc.h Sangoma Cisco HDLC firmware API definitions
Author: Gideon Hack
Nenad Corbic <ncorbic@sangoma.com>
Copyright: (c) 1995-2000 Sangoma Technologies Inc.
This program is free software; you can redistribute it and/or
modify it under the term 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.
===========================================================================
Oct 04, 1999 Nenad Corbic Updated API support
Jun 02, 1999 Gideon Hack Changes for S514 usage.
Oct 28, 1998 Jaspreet Singh Made changes for Dual Port CHDLC.
Jun 11, 1998 David Fong Initial version.
===========================================================================
Organization
- Compatibility notes
- Constants defining the shared memory control block (mailbox)
- Interface commands
- Return code from interface commands
- Constants for the commands (structures for casting data)
- UDP Management constants and structures
*************************************************************************/
#ifndef _SDLA_CHDLC_H
# define _SDLC_CHDLC_H
/*------------------------------------------------------------------------
Notes:
All structres defined in this file are byte-aligned.
Compiler Platform
------------------------
GNU C Linux
------------------------------------------------------------------------*/
#ifndef PACKED
#define PACKED __attribute__((packed))
#endif /* PACKED */
/* ----------------------------------------------------------------------------
* Constants defining the shared memory control block (mailbox)
* --------------------------------------------------------------------------*/
#define PRI_BASE_ADDR_MB_STRUCT 0xE000 /* the base address of the mailbox structure on the adapter */
#define SEC_BASE_ADDR_MB_STRUCT 0xE800 /* the base address of the mailbox structure on the adapter */
#define SIZEOF_MB_DATA_BFR 2032 /* the size of the actual mailbox data area */
#define NUMBER_MB_RESERVED_BYTES 0x0B /* the number of reserved bytes in the mailbox header area */
#define MIN_LGTH_CHDLC_DATA_CFG 300 /* min length of the CHDLC data field (for configuration purposes) */
#define PRI_MAX_NO_DATA_BYTES_IN_FRAME 15354 /* PRIMARY - max length of the CHDLC data field */
typedef struct {
unsigned char opp_flag PACKED; /* the opp flag */
unsigned char command PACKED; /* the user command */
unsigned short buffer_length PACKED; /* the data length */
unsigned char return_code PACKED; /* the return code */
unsigned char MB_reserved[NUMBER_MB_RESERVED_BYTES] PACKED; /* reserved for later */
unsigned char data[SIZEOF_MB_DATA_BFR] PACKED; /* the data area */
} CHDLC_MAILBOX_STRUCT;
typedef struct {
pid_t pid_num PACKED;
CHDLC_MAILBOX_STRUCT cmdarea PACKED;
} CMDBLOCK_STRUCT;
/* ----------------------------------------------------------------------------
* Interface commands
* --------------------------------------------------------------------------*/
/* global interface commands */
#define READ_GLOBAL_EXCEPTION_CONDITION 0x01
#define SET_GLOBAL_CONFIGURATION 0x02
#define READ_GLOBAL_CONFIGURATION 0x03
#define READ_GLOBAL_STATISTICS 0x04
#define FLUSH_GLOBAL_STATISTICS 0x05
#define SET_MODEM_STATUS 0x06 /* set status of DTR or RTS */
#define READ_MODEM_STATUS 0x07 /* read status of CTS and DCD */
#define READ_COMMS_ERROR_STATS 0x08
#define FLUSH_COMMS_ERROR_STATS 0x09
#define SET_TRACE_CONFIGURATION 0x0A /* set the line trace config */
#define READ_TRACE_CONFIGURATION 0x0B /* read the line trace config */
#define READ_TRACE_STATISTICS 0x0C /* read the trace statistics */
#define FLUSH_TRACE_STATISTICS 0x0D /* flush the trace statistics */
#define FT1_MONITOR_STATUS_CTRL 0x1C /* set the status of the S508/FT1 monitoring */
#define SET_FT1_CONFIGURATION 0x18 /* set the FT1 configuration */
#define READ_FT1_CONFIGURATION 0x19 /* read the FT1 configuration */
#define TRANSMIT_ASYNC_DATA_TO_FT1 0x1A /* output asynchronous data to the FT1 */
#define RECEIVE_ASYNC_DATA_FROM_FT1 0x1B /* receive asynchronous data from the FT1 */
#define FT1_MONITOR_STATUS_CTRL 0x1C /* set the status of the FT1 monitoring */
#define READ_FT1_OPERATIONAL_STATS 0x1D /* read the S508/FT1 operational statistics */
#define SET_FT1_MODE 0x1E /* set the operational mode of the S508/FT1 module */
/* CHDLC-level interface commands */
#define READ_CHDLC_CODE_VERSION 0x20
#define READ_CHDLC_EXCEPTION_CONDITION 0x21 /* read exception condition from the adapter */
#define SET_CHDLC_CONFIGURATION 0x22
#define READ_CHDLC_CONFIGURATION 0x23
#define ENABLE_CHDLC_COMMUNICATIONS 0x24
#define DISABLE_CHDLC_COMMUNICATIONS 0x25
#define READ_CHDLC_LINK_STATUS 0x26
#define READ_CHDLC_OPERATIONAL_STATS 0x27
#define FLUSH_CHDLC_OPERATIONAL_STATS 0x28
#define SET_CHDLC_INTERRUPT_TRIGGERS 0x30 /* set application interrupt triggers */
#define READ_CHDLC_INTERRUPT_TRIGGERS 0x31 /* read application interrupt trigger configuration */
/* Special UDP drivers management commands */
#define CPIPE_ENABLE_TRACING 0x50
#define CPIPE_DISABLE_TRACING 0x51
#define CPIPE_GET_TRACE_INFO 0x52
#define CPIPE_GET_IBA_DATA 0x53
#define CPIPE_FT1_READ_STATUS 0x54
#define CPIPE_DRIVER_STAT_IFSEND 0x55
#define CPIPE_DRIVER_STAT_INTR 0x56
#define CPIPE_DRIVER_STAT_GEN 0x57
#define CPIPE_FLUSH_DRIVER_STATS 0x58
#define CPIPE_ROUTER_UP_TIME 0x59
/* Driver specific commands for API */
#define CHDLC_READ_TRACE_DATA 0xE4 /* read trace data */
#define TRACE_ALL 0x00
#define TRACE_PROT 0x01
#define TRACE_DATA 0x02
#define DISCARD_RX_ERROR_FRAMES 0x0001
/* ----------------------------------------------------------------------------
* Return codes from interface commands
* --------------------------------------------------------------------------*/
#define COMMAND_OK 0x00
/* return codes from global interface commands */
#define NO_GLOBAL_EXCEP_COND_TO_REPORT 0x01 /* there is no CHDLC exception condition to report */
#define LGTH_GLOBAL_CFG_DATA_INVALID 0x01 /* the length of the passed global configuration data is invalid */
#define LGTH_TRACE_CFG_DATA_INVALID 0x01 /* the length of the passed trace configuration data is invalid */
#define IRQ_TIMEOUT_VALUE_INVALID 0x02 /* an invalid application IRQ timeout value was selected */
#define TRACE_CONFIG_INVALID 0x02 /* the passed line trace configuration is invalid */
#define ADAPTER_OPERATING_FREQ_INVALID 0x03 /* an invalid adapter operating frequency was selected */
#define TRC_DEAC_TMR_INVALID 0x03 /* the trace deactivation timer is invalid */
#define S508_FT1_ADPTR_NOT_PRESENT 0x0C /* the S508/FT1 adapter is not present */
#define INVALID_FT1_STATUS_SELECTION 0x0D /* the S508/FT1 status selection is invalid */
#define FT1_OP_STATS_NOT_ENABLED 0x0D /* the FT1 operational statistics have not been enabled */
#define FT1_OP_STATS_NOT_AVAILABLE 0x0E /* the FT1 operational statistics are not currently available */
#define S508_FT1_MODE_SELECTION_BUSY 0x0E /* the S508/FT1 adapter is busy selecting the operational mode */
/* return codes from command READ_GLOBAL_EXCEPTION_CONDITION */
#define EXCEP_MODEM_STATUS_CHANGE 0x10 /* a modem status change occurred */
#define EXCEP_TRC_DISABLED 0x11 /* the trace has been disabled */
#define EXCEP_IRQ_TIMEOUT 0x12 /* IRQ timeout */
/* return codes from CHDLC-level interface commands */
#define NO_CHDLC_EXCEP_COND_TO_REPORT 0x21 /* there is no CHDLC exception condition to report */
#define CHDLC_COMMS_DISABLED 0x21 /* communications are not currently enabled */
#define CHDLC_COMMS_ENABLED 0x21 /* communications are currently enabled */
#define DISABLE_CHDLC_COMMS_BEFORE_CFG 0x21 /* CHDLC communications must be disabled before setting the configuration */
#define ENABLE_CHDLC_COMMS_BEFORE_CONN 0x21 /* communications must be enabled before using the CHDLC_CONNECT conmmand */
#define CHDLC_CFG_BEFORE_COMMS_ENABLED 0x22 /* perform a SET_CHDLC_CONFIGURATION before enabling comms */
#define LGTH_CHDLC_CFG_DATA_INVALID 0x22 /* the length of the passed CHDLC configuration data is invalid */
#define LGTH_INT_TRIGGERS_DATA_INVALID 0x22 /* the length of the passed interrupt trigger data is invalid */
#define INVALID_IRQ_SELECTED 0x23 /* in invalid IRQ was selected in the SET_CHDLC_INTERRUPT_TRIGGERS */
#define INVALID_CHDLC_CFG_DATA 0x23 /* the passed CHDLC configuration data is invalid */
#define IRQ_TMR_VALUE_INVALID 0x24 /* an invalid application IRQ timer value was selected */
#define LARGER_PERCENT_TX_BFR_REQUIRED 0x24 /* a larger Tx buffer percentage is required */
#define LARGER_PERCENT_RX_BFR_REQUIRED 0x25 /* a larger Rx buffer percentage is required */
#define S514_BOTH_PORTS_SAME_CLK_MODE 0x26 /* S514 - both ports must have same clock mode */
#define INVALID_CMND_HDLC_STREAM_MODE 0x4E /* the CHDLC interface command is invalid for HDLC streaming mode */
#define INVALID_CHDLC_COMMAND 0x4F /* the defined CHDLC interface command is invalid */
/* return codes from command READ_CHDLC_EXCEPTION_CONDITION */
#define EXCEP_LINK_ACTIVE 0x30 /* the CHDLC link has become active */
#define EXCEP_LINK_INACTIVE_MODEM 0x31 /* the CHDLC link has become inactive (modem status) */
#define EXCEP_LINK_INACTIVE_KPALV 0x32 /* the CHDLC link has become inactive (keepalive status) */
#define EXCEP_IP_ADDRESS_DISCOVERED 0x33 /* the IP address has been discovered */
#define EXCEP_LOOPBACK_CONDITION 0x34 /* a loopback condition has occurred */
/* return code from command CHDLC_SEND_WAIT and CHDLC_SEND_NO_WAIT */
#define LINK_DISCONNECTED 0x21
#define NO_TX_BFRS_AVAIL 0x24
/* ----------------------------------------------------------------------------
* Constants for the SET_GLOBAL_CONFIGURATION/READ_GLOBAL_CONFIGURATION commands
* --------------------------------------------------------------------------*/
/* the global configuration structure */
typedef struct {
unsigned short adapter_config_options PACKED; /* adapter config options */
unsigned short app_IRQ_timeout PACKED; /* application IRQ timeout */
unsigned long adapter_operating_frequency PACKED; /* adapter operating frequency */
} GLOBAL_CONFIGURATION_STRUCT;
/* settings for the 'app_IRQ_timeout' */
#define MAX_APP_IRQ_TIMEOUT_VALUE 5000 /* the maximum permitted IRQ timeout */
/* ----------------------------------------------------------------------------
* Constants for the READ_GLOBAL_STATISTICS command
* --------------------------------------------------------------------------*/
/* the global statistics structure */
typedef struct {
unsigned short app_IRQ_timeout_count PACKED;
} GLOBAL_STATS_STRUCT;
/* ----------------------------------------------------------------------------
* Constants for the READ_COMMS_ERROR_STATS command
* --------------------------------------------------------------------------*/
/* the communications error statistics structure */
typedef struct {
unsigned short Rx_overrun_err_count PACKED;
unsigned short CRC_err_count PACKED; /* receiver CRC error count */
unsigned short Rx_abort_count PACKED; /* abort frames recvd count */
unsigned short Rx_dis_pri_bfrs_full_count PACKED;/* receiver disabled */
unsigned short comms_err_stat_reserved_1 PACKED;/* reserved for later */
unsigned short sec_Tx_abort_msd_Tx_int_count PACKED; /* secondary - abort frames transmitted count (missed Tx interrupt) */
unsigned short missed_Tx_und_int_count PACKED; /* missed tx underrun interrupt count */
unsigned short sec_Tx_abort_count PACKED; /*secondary-abort frames tx count */
unsigned short DCD_state_change_count PACKED; /* DCD state change */
unsigned short CTS_state_change_count PACKED; /* CTS state change */
} COMMS_ERROR_STATS_STRUCT;
/* ----------------------------------------------------------------------------
* Constants used for line tracing
* --------------------------------------------------------------------------*/
/* the trace configuration structure (SET_TRACE_CONFIGURATION/READ_TRACE_CONFIGURATION commands) */
typedef struct {
unsigned char trace_config PACKED; /* trace configuration */
unsigned short trace_deactivation_timer PACKED; /* trace deactivation timer */
unsigned long ptr_trace_stat_el_cfg_struct PACKED; /* a pointer to the line trace element configuration structure */
} LINE_TRACE_CONFIG_STRUCT;
/* 'trace_config' bit settings */
#define TRACE_INACTIVE 0x00 /* trace is inactive */
#define TRACE_ACTIVE 0x01 /* trace is active */
#define TRACE_DELAY_MODE 0x04 /* operate the trace in delay mode */
#define TRACE_DATA_FRAMES 0x08 /* trace Data frames */
#define TRACE_SLARP_FRAMES 0x10 /* trace SLARP frames */
#define TRACE_CDP_FRAMES 0x20 /* trace CDP frames */
/* the line trace status element configuration structure */
typedef struct {
unsigned short number_trace_status_elements PACKED; /* number of line trace elements */
unsigned long base_addr_trace_status_elements PACKED; /* base address of the trace element list */
unsigned long next_trace_element_to_use PACKED; /* pointer to the next trace element to be used */
unsigned long base_addr_trace_buffer PACKED; /* base address of the trace data buffer */
unsigned long end_addr_trace_buffer PACKED; /* end address of the trace data buffer */
} TRACE_STATUS_EL_CFG_STRUCT;
/* the line trace status element structure */
typedef struct {
unsigned char opp_flag PACKED; /* opp flag */
unsigned short trace_length PACKED; /* trace length */
unsigned char trace_type PACKED; /* trace type */
unsigned short trace_time_stamp PACKED; /* time stamp */
unsigned short trace_reserved_1 PACKED; /* reserved for later use */
unsigned long trace_reserved_2 PACKED; /* reserved for later use */
unsigned long ptr_data_bfr PACKED; /* ptr to the trace data buffer */
} TRACE_STATUS_ELEMENT_STRUCT;
/* "trace_type" bit settings */
#define TRACE_INCOMING 0x00
#define TRACE_OUTGOINGING 0x01
#define TRACE_INCOMING_ABORTED 0x10
#define TRACE_INCOMING_CRC_ERROR 0x20
#define TRACE_INCOMING_OVERRUN_ERROR 0x40
/* the line trace statistics structure */
typedef struct {
unsigned long frames_traced_count PACKED; /* number of frames traced */
unsigned long trc_frms_not_recorded_count PACKED; /* number of trace frames discarded */
} LINE_TRACE_STATS_STRUCT;
/* ----------------------------------------------------------------------------
* Constants for the FT1_MONITOR_STATUS_CTRL command
* --------------------------------------------------------------------------*/
#define DISABLE_FT1_STATUS_STATISTICS 0x00 /* disable the FT1 status and statistics monitoring */
#define ENABLE_READ_FT1_STATUS 0x01 /* read the FT1 operational status */
#define ENABLE_READ_FT1_OP_STATS 0x02 /* read the FT1 operational statistics */
#define FLUSH_FT1_OP_STATS 0x04 /* flush the FT1 operational statistics */
/* ----------------------------------------------------------------------------
* Constants for the SET_CHDLC_CONFIGURATION command
* --------------------------------------------------------------------------*/
/* the CHDLC configuration structure */
typedef struct {
unsigned long baud_rate PACKED; /* the baud rate */
unsigned short line_config_options PACKED; /* line configuration options */
unsigned short modem_config_options PACKED; /* modem configration options */
unsigned short modem_status_timer PACKED; /* timer for monitoring modem status changes */
unsigned short CHDLC_API_options PACKED; /* CHDLC API options */
unsigned short CHDLC_protocol_options PACKED; /* CHDLC protocol options */
unsigned short percent_data_buffer_for_Tx PACKED; /* percentage data buffering used for Tx */
unsigned short CHDLC_statistics_options PACKED; /* CHDLC operational statistics options */
unsigned short max_CHDLC_data_field_length PACKED; /* the maximum length of the CHDLC Data field */
unsigned short transmit_keepalive_timer PACKED; /* the transmit keepalive timer */
unsigned short receive_keepalive_timer PACKED; /* the receive keepalive timer */
unsigned short keepalive_error_tolerance PACKED; /* the receive keepalive error tolerance */
unsigned short SLARP_request_timer PACKED; /* the SLARP request timer */
unsigned long IP_address PACKED; /* the IP address */
unsigned long IP_netmask PACKED; /* the IP netmask */
unsigned long ptr_shared_mem_info_struct PACKED; /* a pointer to the shared memory area information structure */
unsigned long ptr_CHDLC_Tx_stat_el_cfg_struct PACKED; /* a pointer to the transmit status element configuration structure */
unsigned long ptr_CHDLC_Rx_stat_el_cfg_struct PACKED; /* a pointer to the receive status element configuration structure */
} CHDLC_CONFIGURATION_STRUCT;
/* settings for the 'line_config_options' */
#define INTERFACE_LEVEL_V35 0x0000 /* V.35 interface level */
#define INTERFACE_LEVEL_RS232 0x0001 /* RS-232 interface level */
/* settings for the 'modem_config_options' */
#define DONT_RAISE_DTR_RTS_ON_EN_COMMS 0x0001
/* don't automatically raise DTR and RTS when performing an
ENABLE_CHDLC_COMMUNICATIONS command */
#define DONT_REPORT_CHG_IN_MODEM_STAT 0x0002
/* don't report changes in modem status to the application */
/* bit settings for the 'CHDLC_protocol_options' byte */
#define IGNORE_DCD_FOR_LINK_STAT 0x0001
/* ignore DCD in determining the CHDLC link status */
#define IGNORE_CTS_FOR_LINK_STAT 0x0002
/* ignore CTS in determining the CHDLC link status */
#define IGNORE_KPALV_FOR_LINK_STAT 0x0004
/* ignore keepalive frames in determining the CHDLC link status */
#define SINGLE_TX_BUFFER 0x4000
/* configure a single transmit buffer */
#define HDLC_STREAMING_MODE 0x8000
/* settings for the 'CHDLC_statistics_options' */
#define CHDLC_TX_DATA_BYTE_COUNT_STAT 0x0001
/* record the number of Data bytes transmitted */
#define CHDLC_RX_DATA_BYTE_COUNT_STAT 0x0002
/* record the number of Data bytes received */
#define CHDLC_TX_THROUGHPUT_STAT 0x0004
/* compute the Data frame transmit throughput */
#define CHDLC_RX_THROUGHPUT_STAT 0x0008
/* compute the Data frame receive throughput */
/* permitted minimum and maximum values for setting the CHDLC configuration */
#define PRI_MAX_BAUD_RATE_S508 2666666 /* PRIMARY - maximum baud rate (S508) */
#define SEC_MAX_BAUD_RATE_S508 258064 /* SECONDARY - maximum baud rate (S508) */
#define PRI_MAX_BAUD_RATE_S514 2750000 /* PRIMARY - maximum baud rate (S508) */
#define SEC_MAX_BAUD_RATE_S514 515625 /* SECONDARY - maximum baud rate (S508) */
#define MIN_MODEM_TIMER 0 /* minimum modem status timer */
#define MAX_MODEM_TIMER 5000 /* maximum modem status timer */
#define SEC_MAX_NO_DATA_BYTES_IN_FRAME 2048 /* SECONDARY - max length of the CHDLC data field */
#define MIN_Tx_KPALV_TIMER 0 /* minimum transmit keepalive timer */
#define MAX_Tx_KPALV_TIMER 60000 /* maximum transmit keepalive timer */
#define DEFAULT_Tx_KPALV_TIMER 10000 /* default transmit keepalive timer */
#define MIN_Rx_KPALV_TIMER 10 /* minimum receive keepalive timer */
#define MAX_Rx_KPALV_TIMER 60000 /* maximum receive keepalive timer */
#define DEFAULT_Rx_KPALV_TIMER 10000 /* default receive keepalive timer */
#define MIN_KPALV_ERR_TOL 1 /* min kpalv error tolerance count */
#define MAX_KPALV_ERR_TOL 20 /* max kpalv error tolerance count */
#define DEFAULT_KPALV_ERR_TOL 3 /* default value */
#define MIN_SLARP_REQ_TIMER 0 /* min transmit SLARP Request timer */
#define MAX_SLARP_REQ_TIMER 60000 /* max transmit SLARP Request timer */
#define DEFAULT_SLARP_REQ_TIMER 0 /* default value -- no SLARP */
/* ----------------------------------------------------------------------------
* Constants for the READ_CHDLC_LINK_STATUS command
* --------------------------------------------------------------------------*/
/* the CHDLC status structure */
typedef struct {
unsigned char CHDLC_link_status PACKED; /* CHDLC link status */
unsigned char no_Data_frms_for_app PACKED; /* number of Data frames available for the application */
unsigned char receiver_status PACKED; /* enabled/disabled */
unsigned char SLARP_state PACKED; /* internal SLARP state */
} CHDLC_LINK_STATUS_STRUCT;
/* settings for the 'CHDLC_link_status' variable */
#define CHDLC_LINK_INACTIVE 0x00 /* the CHDLC link is inactive */
#define CHDLC_LINK_ACTIVE 0x01 /* the CHDLC link is active */
/* ----------------------------------------------------------------------------
* Constants for the READ_CHDLC_OPERATIONAL_STATS command
* --------------------------------------------------------------------------*/
/* the CHDLC operational statistics structure */
typedef struct {
/* Data frame transmission statistics */
unsigned long Data_frames_Tx_count PACKED; /* # of frames transmitted */
unsigned long Data_bytes_Tx_count PACKED; /* # of bytes transmitted */
unsigned long Data_Tx_throughput PACKED; /* transmit throughput */
unsigned long no_ms_for_Data_Tx_thruput_comp PACKED; /* millisecond time used for the Tx throughput computation */
unsigned long Tx_Data_discard_lgth_err_count PACKED; /* number of Data frames discarded (length error) */
unsigned long reserved_Data_frm_Tx_stat1 PACKED; /* reserved for later */
unsigned long reserved_Data_frm_Tx_stat2 PACKED; /* reserved for later */
unsigned long reserved_Data_frm_Tx_stat3 PACKED; /* reserved for later */
/* Data frame reception statistics */
unsigned long Data_frames_Rx_count PACKED; /* number of frames received */
unsigned long Data_bytes_Rx_count PACKED; /* number of bytes received */
unsigned long Data_Rx_throughput PACKED; /* receive throughput */
unsigned long no_ms_for_Data_Rx_thruput_comp PACKED; /* millisecond time used for the Rx throughput computation */
unsigned long Rx_Data_discard_short_count PACKED; /* received Data frames discarded (too short) */
unsigned long Rx_Data_discard_long_count PACKED; /* received Data frames discarded (too long) */
unsigned long Rx_Data_discard_inactive_count PACKED; /* received Data frames discarded (link inactive) */
unsigned long reserved_Data_frm_Rx_stat1 PACKED; /* reserved for later */
/* SLARP frame transmission/reception statistics */
unsigned long CHDLC_SLARP_REQ_Tx_count PACKED; /* number of SLARP Request frames transmitted */
unsigned long CHDLC_SLARP_REQ_Rx_count PACKED; /* number of SLARP Request frames received */
unsigned long CHDLC_SLARP_REPLY_Tx_count PACKED; /* number of SLARP Reply frames transmitted */
unsigned long CHDLC_SLARP_REPLY_Rx_count PACKED; /* number of SLARP Reply frames received */
unsigned long CHDLC_SLARP_KPALV_Tx_count PACKED; /* number of SLARP keepalive frames transmitted */
unsigned long CHDLC_SLARP_KPALV_Rx_count PACKED; /* number of SLARP keepalive frames received */
unsigned long reserved_SLARP_stat1 PACKED; /* reserved for later */
unsigned long reserved_SLARP_stat2 PACKED; /* reserved for later */
/* CDP frame transmission/reception statistics */
unsigned long CHDLC_CDP_Tx_count PACKED; /* number of CDP frames transmitted */
unsigned long CHDLC_CDP_Rx_count PACKED; /* number of CDP frames received */
unsigned long reserved_CDP_stat1 PACKED; /* reserved for later */
unsigned long reserved_CDP_stat2 PACKED; /* reserved for later */
unsigned long reserved_CDP_stat3 PACKED; /* reserved for later */
unsigned long reserved_CDP_stat4 PACKED; /* reserved for later */
unsigned long reserved_CDP_stat5 PACKED; /* reserved for later */
unsigned long reserved_CDP_stat6 PACKED; /* reserved for later */
/* Incoming frames with a format error statistics */
unsigned short Rx_frm_incomp_CHDLC_hdr_count PACKED; /* frames received of with incomplete Cisco HDLC header */
unsigned short Rx_frms_too_long_count PACKED; /* frames received of excessive length count */
unsigned short Rx_invalid_CHDLC_addr_count PACKED; /* frames received with an invalid CHDLC address count */
unsigned short Rx_invalid_CHDLC_ctrl_count PACKED; /* frames received with an invalid CHDLC control field count */
unsigned short Rx_invalid_CHDLC_type_count PACKED; /* frames received of an invalid CHDLC frame type count */
unsigned short Rx_SLARP_invalid_code_count PACKED; /* SLARP frame received with an invalid packet code */
unsigned short Rx_SLARP_Reply_bad_IP_addr PACKED; /* SLARP Reply received - bad IP address */
unsigned short Rx_SLARP_Reply_bad_netmask PACKED; /* SLARP Reply received - bad netmask */
unsigned long reserved_frm_format_err1 PACKED; /* reserved for later */
unsigned long reserved_frm_format_err2 PACKED; /* reserved for later */
unsigned long reserved_frm_format_err3 PACKED; /* reserved for later */
unsigned long reserved_frm_format_err4 PACKED; /* reserved for later */
/* CHDLC timeout/retry statistics */
unsigned short SLARP_Rx_keepalive_TO_count PACKED; /* timeout count for incoming SLARP frames */
unsigned short SLARP_Request_TO_count PACKED; /* timeout count for SLARP Request frames */
unsigned long To_retry_reserved_stat1 PACKED; /* reserved for later */
unsigned long To_retry_reserved_stat2 PACKED; /* reserved for later */
unsigned long To_retry_reserved_stat3 PACKED; /* reserved for later */
/* CHDLC link active/inactive and loopback statistics */
unsigned short link_active_count PACKED; /* number of times that the link went active */
unsigned short link_inactive_modem_count PACKED; /* number of times that the link went inactive (modem failure) */
unsigned short link_inactive_keepalive_count PACKED; /* number of times that the link went inactive (keepalive failure) */
unsigned short link_looped_count PACKED; /* link looped count */
unsigned long link_status_reserved_stat1 PACKED; /* reserved for later use */
unsigned long link_status_reserved_stat2 PACKED; /* reserved for later use */
/* miscellaneous statistics */
unsigned long reserved_misc_stat1 PACKED; /* reserved for later */
unsigned long reserved_misc_stat2 PACKED; /* reserved for later */
unsigned long reserved_misc_stat3 PACKED; /* reserved for later */
unsigned long reserved_misc_stat4 PACKED; /* reserved for later */
} CHDLC_OPERATIONAL_STATS_STRUCT;
/* ----------------------------------------------------------------------------
* Constants for using application interrupts
* --------------------------------------------------------------------------*/
/* the structure used for the SET_CHDLC_INTERRUPT_TRIGGERS/READ_CHDLC_INTERRUPT_TRIGGERS command */
typedef struct {
unsigned char CHDLC_interrupt_triggers PACKED; /* CHDLC interrupt trigger configuration */
unsigned char IRQ PACKED; /* IRQ to be used */
unsigned short interrupt_timer PACKED; /* interrupt timer */
unsigned short misc_interrupt_bits PACKED; /* miscellaneous bits */
} CHDLC_INT_TRIGGERS_STRUCT;
/* 'CHDLC_interrupt_triggers' bit settings */
#define APP_INT_ON_RX_FRAME 0x01 /* interrupt on Data frame reception */
#define APP_INT_ON_TX_FRAME 0x02 /* interrupt when an Data frame may be transmitted */
#define APP_INT_ON_COMMAND_COMPLETE 0x04 /* interrupt when an interface command is complete */
#define APP_INT_ON_TIMER 0x08 /* interrupt on a defined millisecond timeout */
#define APP_INT_ON_GLOBAL_EXCEP_COND 0x10 /* interrupt on a global exception condition */
#define APP_INT_ON_CHDLC_EXCEP_COND 0x20 /* interrupt on an CHDLC exception condition */
#define APP_INT_ON_TRACE_DATA_AVAIL 0x80 /* interrupt when trace data is available */
/* interrupt types indicated at 'interrupt_type' byte of the INTERRUPT_INFORMATION_STRUCT */
#define NO_APP_INTS_PEND 0x00 /* no interrups are pending */
#define RX_APP_INT_PEND 0x01 /* a receive interrupt is pending */
#define TX_APP_INT_PEND 0x02 /* a transmit interrupt is pending */
#define COMMAND_COMPLETE_APP_INT_PEND 0x04 /* a 'command complete' interrupt is pending */
#define TIMER_APP_INT_PEND 0x08 /* a timer interrupt is pending */
#define GLOBAL_EXCEP_COND_APP_INT_PEND 0x10 /* a global exception condition interrupt is pending */
#define CHDLC_EXCEP_COND_APP_INT_PEND 0x20 /* an CHDLC exception condition interrupt is pending */
#define TRACE_DATA_AVAIL_APP_INT_PEND 0x80 /* a trace data available interrupt is pending */
/* modem status changes */
#define DCD_HIGH 0x08
#define CTS_HIGH 0x20
/* ----------------------------------------------------------------------------
* Constants for Data frame transmission
* --------------------------------------------------------------------------*/
/* the Data frame transmit status element configuration structure */
typedef struct {
unsigned short number_Tx_status_elements PACKED; /* number of transmit status elements */
unsigned long base_addr_Tx_status_elements PACKED; /* base address of the transmit element list */
unsigned long next_Tx_status_element_to_use PACKED; /* pointer to the next transmit element to be used */
} CHDLC_TX_STATUS_EL_CFG_STRUCT;
/* the Data frame transmit status element structure */
typedef struct {
unsigned char opp_flag PACKED; /* opp flag */
unsigned short frame_length PACKED; /* length of the frame to be transmitted */
unsigned char reserved_1 PACKED; /* reserved for internal use */
unsigned long reserved_2 PACKED; /* reserved for internal use */
unsigned long reserved_3 PACKED; /* reserved for internal use */
unsigned long ptr_data_bfr PACKED; /* pointer to the data area */
} CHDLC_DATA_TX_STATUS_EL_STRUCT;
/* ----------------------------------------------------------------------------
* Constants for Data frame reception
* --------------------------------------------------------------------------*/
/* the Data frame receive status element configuration structure */
typedef struct {
unsigned short number_Rx_status_elements PACKED; /* number of receive status elements */
unsigned long base_addr_Rx_status_elements PACKED; /* base address of the receive element list */
unsigned long next_Rx_status_element_to_use PACKED; /* pointer to the next receive element to be used */
unsigned long base_addr_Rx_buffer PACKED; /* base address of the receive data buffer */
unsigned long end_addr_Rx_buffer PACKED; /* end address of the receive data buffer */
} CHDLC_RX_STATUS_EL_CFG_STRUCT;
/* the Data frame receive status element structure */
typedef struct {
unsigned char opp_flag PACKED; /* opp flag */
unsigned short frame_length PACKED; /* length of the received frame */
unsigned char error_flag PACKED; /* frame errors (HDLC_STREAMING_MODE)*/
unsigned short time_stamp PACKED; /* receive time stamp (HDLC_STREAMING_MODE) */
unsigned long reserved_1 PACKED; /* reserved for internal use */
unsigned short reserved_2 PACKED; /* reserved for internal use */
unsigned long ptr_data_bfr PACKED; /* pointer to the data area */
} CHDLC_DATA_RX_STATUS_EL_STRUCT;
/* ----------------------------------------------------------------------------
* Constants defining the shared memory information area
* --------------------------------------------------------------------------*/
/* the global information structure */
typedef struct {
unsigned char global_status PACKED; /* global status */
unsigned char modem_status PACKED; /* current modem status */
unsigned char global_excep_conditions PACKED; /* global exception conditions */
unsigned char glob_info_reserved[5] PACKED; /* reserved */
unsigned char codename[4] PACKED; /* Firmware name */
unsigned char codeversion[4] PACKED; /* Firmware version */
} GLOBAL_INFORMATION_STRUCT;
/* the CHDLC information structure */
typedef struct {
unsigned char CHDLC_status PACKED; /* CHDLC status */
unsigned char CHDLC_excep_conditions PACKED; /* CHDLC exception conditions */
unsigned char CHDLC_info_reserved[14] PACKED; /* reserved */
} CHDLC_INFORMATION_STRUCT;
/* the interrupt information structure */
typedef struct {
unsigned char interrupt_type PACKED; /* type of interrupt triggered */
unsigned char interrupt_permission PACKED; /* interrupt permission mask */
unsigned char int_info_reserved[14] PACKED; /* reserved */
} INTERRUPT_INFORMATION_STRUCT;
/* the S508/FT1 information structure */
typedef struct {
unsigned char parallel_port_A_input PACKED; /* input - parallel port A */
unsigned char parallel_port_B_input PACKED; /* input - parallel port B */
unsigned char FT1_info_reserved[14] PACKED; /* reserved */
} FT1_INFORMATION_STRUCT;
/* the shared memory area information structure */
typedef struct {
GLOBAL_INFORMATION_STRUCT global_info_struct PACKED; /* the global information structure */
CHDLC_INFORMATION_STRUCT CHDLC_info_struct PACKED; /* the CHDLC information structure */
INTERRUPT_INFORMATION_STRUCT interrupt_info_struct PACKED; /* the interrupt information structure */
FT1_INFORMATION_STRUCT FT1_info_struct PACKED; /* the S508/FT1 information structure */
} SHARED_MEMORY_INFO_STRUCT;
/* ----------------------------------------------------------------------------
* UDP Management constants and structures
* --------------------------------------------------------------------------*/
/* The embedded control block for UDP mgmt
This is essentially a mailbox structure, without the large data field */
typedef struct {
unsigned char opp_flag PACKED; /* the opp flag */
unsigned char command PACKED; /* the user command */
unsigned short buffer_length PACKED; /* the data length */
unsigned char return_code PACKED; /* the return code */
unsigned char MB_reserved[NUMBER_MB_RESERVED_BYTES] PACKED; /* reserved for later */
} cblock_t;
/* UDP management packet layout (data area of ip packet) */
/*
typedef struct {
unsigned char signature[8] PACKED;
unsigned char request_reply PACKED;
unsigned char id PACKED;
unsigned char reserved[6] PACKED;
cblock_t cblock PACKED;
unsigned char num_frames PACKED;
unsigned char ismoredata PACKED;
unsigned char data[SIZEOF_MB_DATA_BFR] PACKED;
} udp_management_packet_t;
*/
typedef struct {
unsigned char num_frames PACKED;
unsigned char ismoredata PACKED;
} trace_info_t;
typedef struct {
ip_pkt_t ip_pkt PACKED;
udp_pkt_t udp_pkt PACKED;
wp_mgmt_t wp_mgmt PACKED;
cblock_t cblock PACKED;
trace_info_t trace_info PACKED;
unsigned char data[SIZEOF_MB_DATA_BFR] PACKED;
} chdlc_udp_pkt_t;
typedef struct ft1_exec_cmd{
unsigned char command PACKED; /* the user command */
unsigned short buffer_length PACKED; /* the data length */
unsigned char return_code PACKED; /* the return code */
unsigned char MB_reserved[NUMBER_MB_RESERVED_BYTES] PACKED;
} ft1_exec_cmd_t;
typedef struct {
unsigned char opp_flag PACKED;
ft1_exec_cmd_t cmd PACKED;
unsigned char data[SIZEOF_MB_DATA_BFR] PACKED;
} ft1_exec_t;
#define UDPMGMT_SIGNATURE "CTPIPEAB"
/* UDP/IP packet (for UDP management) layout */
/*
typedef struct {
unsigned char reserved[2] PACKED;
unsigned short ip_length PACKED;
unsigned char reserved2[4] PACKED;
unsigned char ip_ttl PACKED;
unsigned char ip_protocol PACKED;
unsigned short ip_checksum PACKED;
unsigned long ip_src_address PACKED;
unsigned long ip_dst_address PACKED;
unsigned short udp_src_port PACKED;
unsigned short udp_dst_port PACKED;
unsigned short udp_length PACKED;
unsigned short udp_checksum PACKED;
udp_management_packet_t um_packet PACKED;
} ip_packet_t;
*/
/* valid ip_protocol for UDP management */
#define UDPMGMT_UDP_PROTOCOL 0x11
typedef struct {
unsigned char status PACKED;
unsigned char data_avail PACKED;
unsigned short real_length PACKED;
unsigned short time_stamp PACKED;
unsigned char data[1] PACKED;
} trace_pkt_t;
typedef struct {
unsigned char error_flag PACKED;
unsigned short time_stamp PACKED;
unsigned char reserved[13] PACKED;
} api_rx_hdr_t;
typedef struct {
api_rx_hdr_t api_rx_hdr PACKED;
void * data PACKED;
} api_rx_element_t;
typedef struct {
unsigned char attr PACKED;
unsigned char reserved[15] PACKED;
} api_tx_hdr_t;
typedef struct {
api_tx_hdr_t api_tx_hdr PACKED;
void * data PACKED;
} api_tx_element_t;
/* ----------------------------------------------------------------------------
* Constants for the SET_FT1_CONFIGURATION/READ_FT1_CONFIGURATION command
* --------------------------------------------------------------------------*/
/* the FT1 configuration structure */
typedef struct {
unsigned short framing_mode;
unsigned short encoding_mode;
unsigned short line_build_out;
unsigned short channel_base;
unsigned short baud_rate_kbps; /* the baud rate (in kbps) */
unsigned short clock_mode;
} ft1_config_t;
/* settings for the 'framing_mode' */
#define ESF_FRAMING 0x00 /* ESF framing */
#define D4_FRAMING 0x01 /* D4 framing */
/* settings for the 'encoding_mode' */
#define B8ZS_ENCODING 0x00 /* B8ZS encoding */
#define AMI_ENCODING 0x01 /* AMI encoding */
/* settings for the 'line_build_out' */
#define LN_BLD_CSU_0dB_DSX1_0_to_133 0x00 /* set build out to CSU (0db) or DSX-1 (0-133ft) */
#define LN_BLD_DSX1_133_to_266 0x01 /* set build out DSX-1 (133-266ft) */
#define LN_BLD_DSX1_266_to_399 0x02 /* set build out DSX-1 (266-399ft) */
#define LN_BLD_DSX1_399_to_533 0x03 /* set build out DSX-1 (399-533ft) */
#define LN_BLD_DSX1_533_to_655 0x04 /* set build out DSX-1 (533-655ft) */
#define LN_BLD_CSU_NEG_7dB 0x05 /* set build out to CSU (-7.5db) */
#define LN_BLD_CSU_NEG_15dB 0x06 /* set build out to CSU (-15db) */
#define LN_BLD_CSU_NEG_22dB 0x07 /* set build out to CSU (-22.5db) */
/* settings for the 'channel_base' */
#define MIN_CHANNEL_BASE_VALUE 1 /* the minimum permitted channel base value */
#define MAX_CHANNEL_BASE_VALUE 24 /* the maximum permitted channel base value */
/* settings for the 'baud_rate_kbps' */
#define MIN_BAUD_RATE_KBPS 0 /* the minimum permitted baud rate (kbps) */
#define MAX_BAUD_RATE_KBPS 1536 /* the maximum permitted baud rate (kbps) */
#define BAUD_RATE_FT1_AUTO_CONFIG 0xFFFF /* the baud rate used to trigger an automatic FT1 configuration */
/* settings for the 'clock_mode' */
#define CLOCK_MODE_NORMAL 0x00 /* clock mode set to normal (slave) */
#define CLOCK_MODE_MASTER 0x01 /* clock mode set to master */
#define BAUD_RATE_FT1_AUTO_CONFIG 0xFFFF
#define AUTO_FT1_CONFIG_NOT_COMPLETE 0x08
#define AUTO_FT1_CFG_FAIL_OP_MODE 0x0C
#define AUTO_FT1_CFG_FAIL_INVALID_LINE 0x0D
#ifdef _MSC_
# pragma pack()
#endif
#endif /* _SDLA_CHDLC_H */
/*****************************************************************************
* sdla_ppp.h Sangoma PPP firmware API definitions.
*
* Author: Nenad Corbic <ncorbic@sangoma.com>
*
* Copyright: (c) 1995-1997 Sangoma Technologies Inc.
*
* 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.
* ============================================================================
* Feb 24, 2000 Nenad Corbic v2.1.2
* Jan 06, 1997 Gene Kozin v2.0
* Apr 11, 1996 Gene Kozin Initial version.
*****************************************************************************/
#ifndef _SDLA_PPP_H
#define _SDLA_PPP_H
/*----------------------------------------------------------------------------
* Notes:
* ------
* 1. All structures defined in this file are byte-alined.
*
* Compiler Platform
* -------- --------
* GNU C Linux
*/
#ifndef PACKED
# define PACKED __attribute__((packed))
#endif /* PACKED */
/* Adapter memory layout and important constants */
#define PPP508_MB_VECT 0xE000 /* mailbox window vector */
#define PPP508_MB_OFFS 0 /* mailbox offset */
#define PPP508_FLG_OFFS 0x1000 /* status flags offset */
#define PPP508_BUF_OFFS 0x1100 /* buffer info block offset */
#define PPP514_MB_OFFS 0xE000 /* mailbox offset */
#define PPP514_FLG_OFFS 0xF000 /* status flags offset */
#define PPP514_BUF_OFFS 0xF100 /* buffer info block offset */
#define PPP_MAX_DATA 1008 /* command block data buffer length */
/****** Data Structures *****************************************************/
/*----------------------------------------------------------------------------
* PPP Command Block.
*/
typedef struct ppp_cmd{
unsigned char command PACKED; /* command code */
unsigned short length PACKED; /* length of data buffer */
unsigned char result PACKED; /* return code */
unsigned char rsrv[11] PACKED; /* reserved for future use */
} ppp_cmd_t;
typedef struct cblock{
unsigned char opp_flag PACKED;
unsigned char command PACKED; /* command code */
unsigned short length PACKED; /* length of data buffer */
unsigned char result PACKED; /* return code */
unsigned char rsrv[11] PACKED; /* reserved for future use */
} cblock_t;
typedef struct ppp_udp_pkt{
ip_pkt_t ip_pkt PACKED;
udp_pkt_t udp_pkt PACKED;
wp_mgmt_t wp_mgmt PACKED;
cblock_t cblock PACKED;
unsigned char data[MAX_LGTH_UDP_MGNT_PKT] PACKED;
} ppp_udp_pkt_t;
typedef struct {
unsigned char status PACKED;
unsigned char data_avail PACKED;
unsigned short real_length PACKED;
unsigned short time_stamp PACKED;
unsigned char data[1] PACKED;
} trace_pkt_t;
typedef struct {
unsigned char opp_flag PACKED;
unsigned char trace_type PACKED;
unsigned short trace_length PACKED;
unsigned short trace_data_ptr PACKED;
unsigned short trace_time_stamp PACKED;
} trace_element_t;
/* 'command' field defines */
#define PPP_READ_CODE_VERSION 0x10 /* configuration commands */
#define PPP_SET_CONFIG 0x05
#define PPP_READ_CONFIG 0x06
#define PPP_SET_INTR_FLAGS 0x20
#define PPP_READ_INTR_FLAGS 0x21
#define PPP_SET_INBOUND_AUTH 0x30
#define PPP_SET_OUTBOUND_AUTH 0x31
#define PPP_GET_CONNECTION_INFO 0x32
#define PPP_COMM_ENABLE 0x03 /* operational commands */
#define PPP_COMM_DISABLE 0x04
#define PPP_SEND_SIGN_FRAME 0x23
#define PPP_READ_SIGN_RESPONSE 0x24
#define PPP_DATALINE_MONITOR 0x33
#define PPP_READ_STATISTICS 0x07 /* statistics commands */
#define PPP_FLUSH_STATISTICS 0x08
#define PPP_READ_ERROR_STATS 0x09
#define PPP_FLUSH_ERROR_STATS 0x0A
#define PPP_READ_PACKET_STATS 0x12
#define PPP_FLUSH_PACKET_STATS 0x13
#define PPP_READ_LCP_STATS 0x14
#define PPP_FLUSH_LCP_STATS 0x15
#define PPP_READ_LPBK_STATS 0x16
#define PPP_FLUSH_LPBK_STATS 0x17
#define PPP_READ_IPCP_STATS 0x18
#define PPP_FLUSH_IPCP_STATS 0x19
#define PPP_READ_IPXCP_STATS 0x1A
#define PPP_FLUSH_IPXCP_STATS 0x1B
#define PPP_READ_PAP_STATS 0x1C
#define PPP_FLUSH_PAP_STATS 0x1D
#define PPP_READ_CHAP_STATS 0x1E
#define PPP_FLUSH_CHAP_STATS 0x1F
/* 'result' field defines */
#define PPPRES_OK 0x00 /* command executed successfully */
#define PPPRES_INVALID_STATE 0x09 /* invalid command in this context */
/*----------------------------------------------------------------------------
* PPP Mailbox.
* This structure is located at offset PPP???_MB_OFFS into PPP???_MB_VECT
*/
typedef struct ppp_mbox
{
unsigned char flag PACKED; /* 00h: command execution flag */
ppp_cmd_t cmd PACKED; /* 01h: command block */
unsigned char data[1] PACKED; /* 10h: variable length data buffer */
} ppp_mbox_t;
/*----------------------------------------------------------------------------
* PPP Status Flags.
* This structure is located at offset PPP???_FLG_OFFS into
* PPP???_MB_VECT.
*/
typedef struct ppp_flags
{
unsigned char iflag PACKED; /* 00: interrupt flag */
unsigned char imask PACKED; /* 01: interrupt mask */
unsigned char resrv PACKED;
unsigned char mstatus PACKED; /* 03: modem status */
unsigned char lcp_state PACKED; /* 04: LCP state */
unsigned char ppp_phase PACKED; /* 05: PPP phase */
unsigned char ip_state PACKED; /* 06: IPCP state */
unsigned char ipx_state PACKED; /* 07: IPXCP state */
unsigned char pap_state PACKED; /* 08: PAP state */
unsigned char chap_state PACKED; /* 09: CHAP state */
unsigned short disc_cause PACKED; /* 0A: disconnection cause */
} ppp_flags_t;
/* 'iflag' defines */
#define PPP_INTR_RXRDY 0x01 /* Rx ready */
#define PPP_INTR_TXRDY 0x02 /* Tx ready */
#define PPP_INTR_MODEM 0x04 /* modem status change (DCD, CTS) */
#define PPP_INTR_CMD 0x08 /* interface command completed */
#define PPP_INTR_DISC 0x10 /* data link disconnected */
#define PPP_INTR_OPEN 0x20 /* data link open */
#define PPP_INTR_DROP_DTR 0x40 /* DTR drop timeout expired */
#define PPP_INTR_TIMER 0x80 /* timer interrupt */
/* 'mstatus' defines */
#define PPP_MDM_DCD 0x08 /* mdm_status: DCD */
#define PPP_MDM_CTS 0x20 /* mdm_status: CTS */
/* 'disc_cause' defines */
#define PPP_LOCAL_TERMINATION 0x0001 /* Local Request by PPP termination phase */
#define PPP_DCD_CTS_DROP 0x0002 /* DCD and/or CTS dropped. Link down */
#define PPP_REMOTE_TERMINATION 0x0800 /* Remote Request by PPP termination phase */
/* 'misc_config_bits' defines */
#define DONT_RE_TX_ABORTED_I_FRAMES 0x01
#define TX_FRM_BYTE_COUNT_STATS 0x02
#define RX_FRM_BYTE_COUNT_STATS 0x04
#define TIME_STAMP_IN_RX_FRAMES 0x08
#define NON_STD_ADPTR_FREQ 0x10
#define INTERFACE_LEVEL_RS232 0x20
#define AUTO_LINK_RECOVERY 0x100
#define DONT_TERMINATE_LNK_MAX_CONFIG 0x200
/* 'authentication options' defines */
#define NO_AUTHENTICATION 0x00
#define INBOUND_AUTH 0x80
#define PAP_AUTH 0x01
#define CHAP_AUTH 0x02
/* 'ip options' defines */
#define L_AND_R_IP_NO_ASSIG 0x00
#define L_IP_LOCAL_ASSIG 0x01
#define L_IP_REMOTE_ASSIG 0x02
#define R_IP_LOCAL_ASSIG 0x04
#define R_IP_REMOTE_ASSIG 0x08
#define ENABLE_IP 0x80
/* 'ipx options' defines */
#define ROUTING_PROT_DEFAULT 0x20
#define ENABLE_IPX 0x80
#define DISABLE_IPX 0x00
/*----------------------------------------------------------------------------
* PPP Buffer Info.
* This structure is located at offset PPP508_BUF_OFFS into
* PPP508_MB_VECT.
*/
typedef struct ppp508_buf_info
{
unsigned short txb_num PACKED; /* 00: number of transmit buffers */
unsigned long txb_ptr PACKED; /* 02: pointer to the buffer ctl. */
unsigned long txb_nxt PACKED;
unsigned char rsrv1[22] PACKED;
unsigned short rxb_num PACKED; /* 20: number of receive buffers */
unsigned long rxb_ptr PACKED; /* 22: pointer to the buffer ctl. */
unsigned long rxb1_ptr PACKED; /* 26: pointer to the first buf.ctl. */
unsigned long rxb_base PACKED; /* 2A: pointer to the buffer base */
unsigned char rsrv2[2] PACKED;
unsigned long rxb_end PACKED; /* 30: pointer to the buffer end */
} ppp508_buf_info_t;
/*----------------------------------------------------------------------------
* Transmit/Receive Buffer Control Block.
*/
typedef struct ppp_buf_ctl
{
unsigned char flag PACKED; /* 00: 'buffer ready' flag */
unsigned short length PACKED; /* 01: length of data */
unsigned char reserved1[1] PACKED; /* 03: */
unsigned char proto PACKED; /* 04: protocol */
unsigned short timestamp PACKED; /* 05: time stamp (Rx only) */
unsigned char reserved2[5] PACKED; /* 07: */
union
{
unsigned short o_p[2]; /* 1C: buffer offset & page (S502) */
unsigned long ptr; /* 1C: buffer pointer (S508) */
} buf PACKED;
} ppp_buf_ctl_t;
/*----------------------------------------------------------------------------
* S508 Adapter Configuration Block (passed to the PPP_SET_CONFIG command).
*/
typedef struct ppp508_conf
{
unsigned long line_speed PACKED; /* 00: baud rate, bps */
unsigned short txbuf_percent PACKED; /* 04: % of Tx buffer */
unsigned short conf_flags PACKED; /* 06: configuration bits */
unsigned short mtu_local PACKED; /* 08: local MTU */
unsigned short mtu_remote PACKED; /* 0A: remote MTU */
unsigned short restart_tmr PACKED; /* 0C: restart timer */
unsigned short auth_rsrt_tmr PACKED; /* 0E: authentication timer */
unsigned short auth_wait_tmr PACKED; /* 10: authentication timer */
unsigned short mdm_fail_tmr PACKED; /* 12: modem failure timer */
unsigned short dtr_drop_tmr PACKED; /* 14: DTR drop timer */
unsigned short connect_tmout PACKED; /* 16: connection timeout */
unsigned short conf_retry PACKED; /* 18: max. retry */
unsigned short term_retry PACKED; /* 1A: max. retry */
unsigned short fail_retry PACKED; /* 1C: max. retry */
unsigned short auth_retry PACKED; /* 1E: max. retry */
unsigned char auth_options PACKED; /* 20: authentication opt. */
unsigned char ip_options PACKED; /* 21: IP options */
unsigned long ip_local PACKED; /* 22: local IP address */
unsigned long ip_remote PACKED; /* 26: remote IP address */
unsigned char ipx_options PACKED; /* 2A: IPX options */
unsigned char ipx_netno[4] PACKED; /* 2B: IPX net number */
unsigned char ipx_local[6] PACKED; /* 2F: local IPX node number*/
unsigned char ipx_remote[6] PACKED; /* 35: remote IPX node num.*/
unsigned char ipx_router[48] PACKED; /* 3B: IPX router name*/
unsigned long alt_cpu_clock PACKED; /* 6B: */
} ppp508_conf_t;
/*----------------------------------------------------------------------------
* S508 Adapter Read Connection Information Block
* Returned by the PPP_GET_CONNECTION_INFO command
*/
typedef struct ppp508_connect_info
{
unsigned short mru PACKED; /* 00-01 Remote Max Rec' Unit */
unsigned char ip_options PACKED; /* 02: Negotiated ip options */
unsigned long ip_local PACKED; /* 03-06: local IP address */
unsigned long ip_remote PACKED; /* 07-0A: remote IP address */
unsigned char ipx_options PACKED; /* 0B: Negotiated ipx options */
unsigned char ipx_netno[4] PACKED; /* 0C-0F: IPX net number */
unsigned char ipx_local[6] PACKED; /* 10-1F: local IPX node # */
unsigned char ipx_remote[6] PACKED; /* 16-1B: remote IPX node # */
unsigned char ipx_router[48] PACKED; /* 1C-4B: IPX router name */
unsigned char auth_status PACKED; /* 4C: Authentication Status */
unsigned char inbd_auth_peerID[1] PACKED; /* 4D: variable length inbound authenticated peer ID */
} ppp508_connect_info_t;
/* 'line_speed' field */
#define PPP_BITRATE_1200 0x01
#define PPP_BITRATE_2400 0x02
#define PPP_BITRATE_4800 0x03
#define PPP_BITRATE_9600 0x04
#define PPP_BITRATE_19200 0x05
#define PPP_BITRATE_38400 0x06
#define PPP_BITRATE_45000 0x07
#define PPP_BITRATE_56000 0x08
#define PPP_BITRATE_64000 0x09
#define PPP_BITRATE_74000 0x0A
#define PPP_BITRATE_112000 0x0B
#define PPP_BITRATE_128000 0x0C
#define PPP_BITRATE_156000 0x0D
/* Defines for the 'conf_flags' field */
#define PPP_IGNORE_TX_ABORT 0x01 /* don't re-transmit aborted frames */
#define PPP_ENABLE_TX_STATS 0x02 /* enable Tx statistics */
#define PPP_ENABLE_RX_STATS 0x04 /* enable Rx statistics */
#define PPP_ENABLE_TIMESTAMP 0x08 /* enable timestamp */
/* 'ip_options' defines */
#define PPP_LOCAL_IP_LOCAL 0x01
#define PPP_LOCAL_IP_REMOTE 0x02
#define PPP_REMOTE_IP_LOCAL 0x04
#define PPP_REMOTE_IP_REMOTE 0x08
/* 'ipx_options' defines */
#define PPP_REMOTE_IPX_NETNO 0x01
#define PPP_REMOTE_IPX_LOCAL 0x02
#define PPP_REMOTE_IPX_REMOTE 0x04
#define PPP_IPX_ROUTE_RIP_SAP 0x08
#define PPP_IPX_ROUTE_NLSP 0x10
#define PPP_IPX_ROUTE_DEFAULT 0x20
#define PPP_IPX_CONF_COMPLETE 0x40
#define PPP_IPX_ENABLE 0x80
/*----------------------------------------------------------------------------
* S508 Adapter Configuration Block (returned by the PPP_READ_CONFIG command).
*/
typedef struct ppp508_get_conf
{
unsigned long bps PACKED; /* 00: baud rate, bps */
ppp508_conf_t conf PACKED; /* 04: requested config. */
unsigned short txb_num PACKED; /* 6F: number of Tx buffers */
unsigned short rxb_num PACKED; /* 71: number of Rx buffers */
} ppp508_get_conf_t;
/*----------------------------------------------------------------------------
* S508 Operational Statistics (returned by the PPP_READ_STATISTIC command).
*/
typedef struct ppp508_stats
{
unsigned short reserved1 PACKED; /* 00: */
unsigned short rx_bad_len PACKED; /* 02: */
unsigned short reserved2 PACKED; /* 04: */
unsigned long tx_frames PACKED; /* 06: */
unsigned long tx_bytes PACKED; /* 0A: */
unsigned long rx_frames PACKED; /* 0E: */
unsigned long rx_bytes PACKED; /* 12: */
} ppp508_stats_t;
/*----------------------------------------------------------------------------
* Adapter Error Statistics (returned by the PPP_READ_ERROR_STATS command).
*/
typedef struct ppp_err_stats
{
unsigned char rx_overrun PACKED; /* 00: Rx overrun errors */
unsigned char rx_bad_crc PACKED; /* 01: Rx CRC errors */
unsigned char rx_abort PACKED; /* 02: Rx aborted frames */
unsigned char rx_lost PACKED; /* 03: Rx frames lost */
unsigned char tx_abort PACKED; /* 04: Tx aborted frames */
unsigned char tx_underrun PACKED; /* 05: Tx underrun errors */
unsigned char tx_missed_intr PACKED; /* 06: Tx underruns missed */
unsigned char reserved PACKED; /* 07: Tx underruns missed */
unsigned char dcd_trans PACKED; /* 08: DCD transitions */
unsigned char cts_trans PACKED; /* 09: CTS transitions */
} ppp_err_stats_t;
/*----------------------------------------------------------------------------
* Packet Statistics (returned by the PPP_READ_PACKET_STATS command).
*/
typedef struct ppp_pkt_stats
{
unsigned short rx_bad_header PACKED; /* 00: */
unsigned short rx_prot_unknwn PACKED; /* 02: */
unsigned short rx_too_large PACKED; /* 04: */
unsigned short rx_lcp PACKED; /* 06: */
unsigned short tx_lcp PACKED; /* 08: */
unsigned short rx_ipcp PACKED; /* 0A: */
unsigned short tx_ipcp PACKED; /* 0C: */
unsigned short rx_ipxcp PACKED; /* 0E: */
unsigned short tx_ipxcp PACKED; /* 10: */
unsigned short rx_pap PACKED; /* 12: */
unsigned short tx_pap PACKED; /* 14: */
unsigned short rx_chap PACKED; /* 16: */
unsigned short tx_chap PACKED; /* 18: */
unsigned short rx_lqr PACKED; /* 1A: */
unsigned short tx_lqr PACKED; /* 1C: */
unsigned short rx_ip PACKED; /* 1E: */
unsigned short tx_ip PACKED; /* 20: */
unsigned short rx_ipx PACKED; /* 22: */
unsigned short tx_ipx PACKED; /* 24: */
} ppp_pkt_stats_t;
/*----------------------------------------------------------------------------
* LCP Statistics (returned by the PPP_READ_LCP_STATS command).
*/
typedef struct ppp_lcp_stats
{
unsigned short rx_unknown PACKED; /* 00: unknown LCP type */
unsigned short rx_conf_rqst PACKED; /* 02: Configure-Request */
unsigned short rx_conf_ack PACKED; /* 04: Configure-Ack */
unsigned short rx_conf_nak PACKED; /* 06: Configure-Nak */
unsigned short rx_conf_rej PACKED; /* 08: Configure-Reject */
unsigned short rx_term_rqst PACKED; /* 0A: Terminate-Request */
unsigned short rx_term_ack PACKED; /* 0C: Terminate-Ack */
unsigned short rx_code_rej PACKED; /* 0E: Code-Reject */
unsigned short rx_proto_rej PACKED; /* 10: Protocol-Reject */
unsigned short rx_echo_rqst PACKED; /* 12: Echo-Request */
unsigned short rx_echo_reply PACKED; /* 14: Echo-Reply */
unsigned short rx_disc_rqst PACKED; /* 16: Discard-Request */
unsigned short tx_conf_rqst PACKED; /* 18: Configure-Request */
unsigned short tx_conf_ack PACKED; /* 1A: Configure-Ack */
unsigned short tx_conf_nak PACKED; /* 1C: Configure-Nak */
unsigned short tx_conf_rej PACKED; /* 1E: Configure-Reject */
unsigned short tx_term_rqst PACKED; /* 20: Terminate-Request */
unsigned short tx_term_ack PACKED; /* 22: Terminate-Ack */
unsigned short tx_code_rej PACKED; /* 24: Code-Reject */
unsigned short tx_proto_rej PACKED; /* 26: Protocol-Reject */
unsigned short tx_echo_rqst PACKED; /* 28: Echo-Request */
unsigned short tx_echo_reply PACKED; /* 2A: Echo-Reply */
unsigned short tx_disc_rqst PACKED; /* 2E: Discard-Request */
unsigned short rx_too_large PACKED; /* 30: packets too large */
unsigned short rx_ack_inval PACKED; /* 32: invalid Conf-Ack */
unsigned short rx_rej_inval PACKED; /* 34: invalid Conf-Reject */
unsigned short rx_rej_badid PACKED; /* 36: Conf-Reject w/bad ID */
} ppp_lcp_stats_t;
/*----------------------------------------------------------------------------
* Loopback Error Statistics (returned by the PPP_READ_LPBK_STATS command).
*/
typedef struct ppp_lpbk_stats
{
unsigned short conf_magic PACKED; /* 00: */
unsigned short loc_echo_rqst PACKED; /* 02: */
unsigned short rem_echo_rqst PACKED; /* 04: */
unsigned short loc_echo_reply PACKED; /* 06: */
unsigned short rem_echo_reply PACKED; /* 08: */
unsigned short loc_disc_rqst PACKED; /* 0A: */
unsigned short rem_disc_rqst PACKED; /* 0C: */
unsigned short echo_tx_collsn PACKED; /* 0E: */
unsigned short echo_rx_collsn PACKED; /* 10: */
} ppp_lpbk_stats_t;
/*----------------------------------------------------------------------------
* Protocol Statistics (returned by the PPP_READ_IPCP_STATS and
* PPP_READ_IPXCP_STATS commands).
*/
typedef struct ppp_prot_stats
{
unsigned short rx_unknown PACKED; /* 00: unknown type */
unsigned short rx_conf_rqst PACKED; /* 02: Configure-Request */
unsigned short rx_conf_ack PACKED; /* 04: Configure-Ack */
unsigned short rx_conf_nak PACKED; /* 06: Configure-Nak */
unsigned short rx_conf_rej PACKED; /* 08: Configure-Reject */
unsigned short rx_term_rqst PACKED; /* 0A: Terminate-Request */
unsigned short rx_term_ack PACKED; /* 0C: Terminate-Ack */
unsigned short rx_code_rej PACKED; /* 0E: Code-Reject */
unsigned short reserved PACKED; /* 10: */
unsigned short tx_conf_rqst PACKED; /* 12: Configure-Request */
unsigned short tx_conf_ack PACKED; /* 14: Configure-Ack */
unsigned short tx_conf_nak PACKED; /* 16: Configure-Nak */
unsigned short tx_conf_rej PACKED; /* 18: Configure-Reject */
unsigned short tx_term_rqst PACKED; /* 1A: Terminate-Request */
unsigned short tx_term_ack PACKED; /* 1C: Terminate-Ack */
unsigned short tx_code_rej PACKED; /* 1E: Code-Reject */
unsigned short rx_too_large PACKED; /* 20: packets too large */
unsigned short rx_ack_inval PACKED; /* 22: invalid Conf-Ack */
unsigned short rx_rej_inval PACKED; /* 24: invalid Conf-Reject */
unsigned short rx_rej_badid PACKED; /* 26: Conf-Reject w/bad ID */
} ppp_prot_stats_t;
/*----------------------------------------------------------------------------
* PAP Statistics (returned by the PPP_READ_PAP_STATS command).
*/
typedef struct ppp_pap_stats
{
unsigned short rx_unknown PACKED; /* 00: unknown type */
unsigned short rx_auth_rqst PACKED; /* 02: Authenticate-Request */
unsigned short rx_auth_ack PACKED; /* 04: Authenticate-Ack */
unsigned short rx_auth_nak PACKED; /* 06: Authenticate-Nak */
unsigned short reserved PACKED; /* 08: */
unsigned short tx_auth_rqst PACKED; /* 0A: Authenticate-Request */
unsigned short tx_auth_ack PACKED; /* 0C: Authenticate-Ack */
unsigned short tx_auth_nak PACKED; /* 0E: Authenticate-Nak */
unsigned short rx_too_large PACKED; /* 10: packets too large */
unsigned short rx_bad_peerid PACKED; /* 12: invalid peer ID */
unsigned short rx_bad_passwd PACKED; /* 14: invalid password */
} ppp_pap_stats_t;
/*----------------------------------------------------------------------------
* CHAP Statistics (returned by the PPP_READ_CHAP_STATS command).
*/
typedef struct ppp_chap_stats
{
unsigned short rx_unknown PACKED; /* 00: unknown type */
unsigned short rx_challenge PACKED; /* 02: Authenticate-Request */
unsigned short rx_response PACKED; /* 04: Authenticate-Ack */
unsigned short rx_success PACKED; /* 06: Authenticate-Nak */
unsigned short rx_failure PACKED; /* 08: Authenticate-Nak */
unsigned short reserved PACKED; /* 0A: */
unsigned short tx_challenge PACKED; /* 0C: Authenticate-Request */
unsigned short tx_response PACKED; /* 0E: Authenticate-Ack */
unsigned short tx_success PACKED; /* 10: Authenticate-Nak */
unsigned short tx_failure PACKED; /* 12: Authenticate-Nak */
unsigned short rx_too_large PACKED; /* 14: packets too large */
unsigned short rx_bad_peerid PACKED; /* 16: invalid peer ID */
unsigned short rx_bad_passwd PACKED; /* 18: invalid password */
unsigned short rx_bad_md5 PACKED; /* 1A: invalid MD5 format */
unsigned short rx_bad_resp PACKED; /* 1C: invalid response */
} ppp_chap_stats_t;
/*----------------------------------------------------------------------------
* Connection Information (returned by the PPP_GET_CONNECTION_INFO command).
*/
typedef struct ppp_conn_info
{
unsigned short remote_mru PACKED; /* 00: */
unsigned char ip_options PACKED; /* 02: */
unsigned char ip_local[4] PACKED; /* 03: */
unsigned char ip_remote[4] PACKED; /* 07: */
unsigned char ipx_options PACKED; /* 0B: */
unsigned char ipx_network[4] PACKED; /* 0C: */
unsigned char ipx_local[6] PACKED; /* 10: */
unsigned char ipx_remote[6] PACKED; /* 16: */
unsigned char ipx_router[48] PACKED; /* 1C: */
unsigned char auth_status PACKED; /* 4C: */
unsigned char peer_id[0] PACKED; /* 4D: */
} ppp_conn_info_t;
/* Data structure for SET_TRIGGER_INTR command
*/
typedef struct ppp_intr_info{
unsigned char i_enable PACKED; /* 0 Interrupt enable bits */
unsigned char irq PACKED; /* 1 Irq number */
unsigned short timer_len PACKED; /* 2 Timer delay */
} ppp_intr_info_t;
#define FT1_MONITOR_STATUS_CTRL 0x80
#define SET_FT1_MODE 0x81
/* Special UDP drivers management commands */
#define PPIPE_ENABLE_TRACING 0x20
#define PPIPE_DISABLE_TRACING 0x21
#define PPIPE_GET_TRACE_INFO 0x22
#define PPIPE_GET_IBA_DATA 0x23
#define PPIPE_KILL_BOARD 0x24
#define PPIPE_FT1_READ_STATUS 0x25
#define PPIPE_DRIVER_STAT_IFSEND 0x26
#define PPIPE_DRIVER_STAT_INTR 0x27
#define PPIPE_DRIVER_STAT_GEN 0x28
#define PPIPE_FLUSH_DRIVER_STATS 0x29
#define PPIPE_ROUTER_UP_TIME 0x30
#define DISABLE_TRACING 0x00
#define TRACE_SIGNALLING_FRAMES 0x01
#define TRACE_DATA_FRAMES 0x02
#ifdef _MSC_
# pragma pack()
#endif
#endif /* _SDLA_PPP_H */
/*****************************************************************************
* sdla_x25.h Sangoma X.25 firmware API definitions.
*
* Author: Nenad Corbic <ncorbic@sangoma.com>
*
* Copyright: (c) 1995-2000 Sangoma Technologies Inc.
*
* 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.
* ============================================================================
* Feb 28, 2000 Nenad Corbic Updated for socket based x25api
* Dec 13, 1996 Gene Kozin Initial version
*****************************************************************************/
#ifndef _SDLA_X25_H
#define _SDLA_X25_H
/*----------------------------------------------------------------------------
* Notes:
* ------
* 1. All structures defined in this file are byte-alined.
* Compiler Platform
* -------- --------
* GNU C Linux
*
*/
#ifndef PACKED
# define PACKED __attribute__((packed))
#endif /* PACKED */
/****** CONSTANTS DEFINITIONS ***********************************************/
#define X25_MAX_CHAN 255 /* max number of open X.25 circuits */
#define X25_MAX_DATA 1024 /* max length of X.25 data buffer */
/*
* X.25 shared memory layout.
*/
#define X25_MBOX_OFFS 0x16B0 /* general mailbox block */
#define X25_RXMBOX_OFFS 0x1AD0 /* receive mailbox */
#define X25_STATUS_OFFS 0x1EF0 /* X.25 status structure */
#define X25_MB_VECTOR 0xE000 /* S514 mailbox window vecotr */
#define X25_MISC_HDLC_BITS 0x1F00 /*X.25 miscallaneous HDLC bits */
/* code levels */
#define HDLC_LEVEL 0x01
#define X25_LEVEL 0x02
#define X25_AND_HDLC_LEVEL 0x03
#define DO_HDLC_LEVEL_ERROR_CHECKING 0x04
/****** DATA STRUCTURES *****************************************************/
/*----------------------------------------------------------------------------
* X.25 Command Block.
*/
typedef struct X25Cmd
{
unsigned char command PACKED; /* command code */
unsigned short length PACKED; /* transfer data length */
unsigned char result PACKED; /* return code */
unsigned char pf PACKED; /* P/F bit */
unsigned short lcn PACKED; /* logical channel */
unsigned char qdm PACKED; /* Q/D/M bits */
unsigned char cause PACKED; /* cause field */
unsigned char diagn PACKED; /* diagnostics */
unsigned char pktType PACKED; /* packet type */
unsigned char resrv[4] PACKED; /* reserved */
} TX25Cmd;
/*
* Defines for the 'command' field.
*/
/*----- General commands --------------*/
#define X25_SET_GLOBAL_VARS 0x0B /* set global variables */
#define X25_READ_MODEM_STATUS 0x0C /* read modem status */
#define X25_READ_CODE_VERSION 0x15 /* read firmware version number */
#define X25_TRACE_CONFIGURE 0x14 /* configure trace facility */
#define X25_READ_TRACE_DATA 0x16 /* read trace data */
#define X25_SET_INTERRUPT_MODE 0x17 /* set interrupt generation mode */
#define X25_READ_INTERRUPT_MODE 0x18 /* read interrupt generation mode */
/*----- HDLC-level commands -----------*/
#define X25_HDLC_LINK_CONFIGURE 0x01 /* configure HDLC link level */
#define X25_HDLC_LINK_OPEN 0x02 /* open HDLC link */
#define X25_HDLC_LINK_CLOSE 0x03 /* close HDLC link */
#define X25_HDLC_LINK_SETUP 0x04 /* set up HDLC link */
#define X25_HDLC_LINK_DISC 0x05 /* disconnect DHLC link */
#define X25_HDLC_LINK_STATUS 0x06 /* read DHLC link status */
#define X25_HDLC_READ_STATS 0x07 /* read operational statistics */
#define X25_HDLC_FLUSH_STATS 0x08 /* flush operational statistics */
#define X25_HDLC_READ_COMM_ERR 0x09 /* read error statistics */
#define X25_HDLC_FLUSH_COMM_ERR 0x0A /* flush error statistics */
#define X25_HDLC_FLUSH_BUFFERS 0x0D /* flush HDLC-level data buffers */
#define X25_HDLC_SPRVS_CNT_STAT 0x0F /* read surervisory count status */
#define X25_HDLC_SEND_UI_FRAME 0x10 /* send unnumbered information frame */
#define X25_HDLC_WRITE 0x11 /* send HDLC information frame */
#define X25_HDLC_READ 0x21 /* read HDLC information frame */
#define X25_HDLC_READ_CONFIG 0x12 /* read HDLC configuration */
#define X25_HDLC_SET_CONFIG 0x13 /* set HDLC configuration */
#define SET_PROTOCOL_LEVEL 0x1F /* set protocol level */
/*----- X.25-level commands -----------*/
#define X25_READ 0x22 /* read X.25 packet */
#define X25_WRITE 0x23 /* send X.25 packet */
#define X25_PLACE_CALL 0x30 /* place a call on SVC */
#define X25_ACCEPT_CALL 0x31 /* accept incomming call */
#define X25_CLEAR_CALL 0x32 /* clear call */
#define X25_CLEAR_CONFRM 0x33 /* send clear confirmation packet */
#define X25_RESET 0x34 /* send reset request packet */
#define X25_RESET_CONFRM 0x35 /* send reset confirmation packet */
#define X25_RESTART 0x36 /* send restart request packet */
#define X25_RESTART_CONFRM 0x37 /* send restart confirmation packet */
#define X25_INTERRUPT 0x38 /* send interrupt request packet */
#define X25_INTERRUPT_CONFRM 0x39 /* send interrupt confirmation pkt */
#define X25_REGISTRATION_RQST 0x3A /* send registration request packet */
#define X25_REGISTRATION_CONFRM 0x3B /* send registration confirmation */
#define X25_IS_DATA_AVAILABLE 0x40 /* querry receive queue */
#define X25_INCOMMING_CALL_CTL 0x41 /* select incomming call options */
#define X25_CONFIGURE_PVC 0x42 /* configure PVC */
#define X25_GET_ACTIVE_CHANNELS 0x43 /* get a list of active circuits */
#define X25_READ_CHANNEL_CONFIG 0x44 /* read virt. circuit configuration */
#define X25_FLUSH_DATA_BUFFERS 0x45 /* flush X.25-level data buffers */
#define X25_READ_HISTORY_TABLE 0x46 /* read asynchronous event log */
#define X25_HISTORY_TABLE_CTL 0x47 /* control asynchronous event log */
#define X25_GET_TX_D_BIT_STATUS 0x48 /* is packet with D-bit acknowleged */
#define X25_READ_STATISTICS 0x49 /* read X.25-level statistics */
#define X25_FLUSH_STATISTICS 0x4A /* flush X.25-level statistics */
#define X25_READ_CONFIGURATION 0x50 /* read HDLC & X.25 configuration */
#define X25_SET_CONFIGURATION 0x51 /* set HDLC & X.25 configuration */
/*
* Defines for the 'result' field.
*/
/*----- General results ---------------*/
#define X25RES_OK 0x00
#define X25RES_ERROR 0x01
#define X25RES_LINK_NOT_IN_ABM 0x02 /* link is not in ABM mode */
#define X25RES_LINK_CLOSED 0x03
#define X25RES_INVAL_LENGTH 0x04
#define X25RES_INVAL_CMD 0x05
#define X25RES_UNNUMBERED_FRAME 0x06 /* unnunbered frame received */
#define X25RES_FRM_REJECT_MODE 0x07 /* link is in Frame Reject mode */
#define X25RES_MODEM_FAILURE 0x08 /* DCD and/or CTS dropped */
#define X25RES_N2_RETRY_LIMIT 0x09 /* N2 retry limit has been exceeded */
#define X25RES_INVAL_LCN 0x30 /* invalid logical channel number */
#define X25RES_INVAL_STATE 0x31 /* channel is not in data xfer mode */
#define X25RES_INVAL_DATA_LEN 0x32 /* invalid data length */
#define X25RES_NOT_READY 0x33 /* no data available / buffers full */
#define X25RES_NETWORK_DOWN 0x34
#define X25RES_CHANNEL_IN_USE 0x35 /* there is data queued on this LCN */
#define X25RES_REGST_NOT_SUPPRT 0x36 /* registration not supported */
#define X25RES_INVAL_FORMAT 0x37 /* invalid packet format */
#define X25RES_D_BIT_NOT_SUPPRT 0x38 /* D-bit pragmatics not supported */
#define X25RES_FACIL_NOT_SUPPRT 0x39 /* Call facility not supported */
#define X25RES_INVAL_CALL_ARG 0x3A /* errorneous call arguments */
#define X25RES_INVAL_CALL_DATA 0x3B /* errorneous call user data */
#define X25RES_ASYNC_PACKET 0x40 /* asynchronous packet received */
#define X25RES_PROTO_VIOLATION 0x41 /* protocol violation occurred */
#define X25RES_PKT_TIMEOUT 0x42 /* X.25 packet time out */
#define X25RES_PKT_RETRY_LIMIT 0x43 /* X.25 packet retry limit exceeded */
/*----- Command-dependent results -----*/
#define X25RES_LINK_DISC 0x00 /* HDLC_LINK_STATUS */
#define X25RES_LINK_IN_ABM 0x01 /* HDLC_LINK_STATUS */
#define X25RES_NO_DATA 0x01 /* HDLC_READ/READ_TRACE_DATA*/
#define X25RES_TRACE_INACTIVE 0x02 /* READ_TRACE_DATA */
#define X25RES_LINK_IS_OPEN 0x01 /* HDLC_LINK_OPEN */
#define X25RES_LINK_IS_DISC 0x02 /* HDLC_LINK_DISC */
#define X25RES_LINK_IS_CLOSED 0x03 /* HDLC_LINK_CLOSE */
#define X25RES_INVAL_PARAM 0x31 /* INCOMMING_CALL_CTL */
#define X25RES_INVAL_CONFIG 0x35 /* REGISTR_RQST/CONFRM */
/*
* Defines for the 'qdm_bits' field.
*/
#define X25CMD_Q_BIT_MASK 0x04
#define X25CMD_D_BIT_MASK 0x02
#define X25CMD_M_BIT_MASK 0x01
/*
* Defines for the 'pkt_type' field.
*/
/*----- Asynchronous events ------*/
#define ASE_CLEAR_RQST 0x02
#define ASE_RESET_RQST 0x04
#define ASE_RESTART_RQST 0x08
#define ASE_INTERRUPT 0x10
#define ASE_DTE_REGISTR_RQST 0x20
#define ASE_CALL_RQST 0x30
#define ASE_CALL_ACCEPTED 0x31
#define ASE_CLEAR_CONFRM 0x32
#define ASE_RESET_CONFRM 0x33
#define ASE_RESTART_CONFRM 0x34
#define ASE_INTERRUPT_CONFRM 0x35
#define ASE_DCE_REGISTR_CONFRM 0x36
#define ASE_DIAGNOSTIC 0x37
#define ASE_CALL_AUTO_CLEAR 0x38
#define AUTO_RESPONSE_FLAG 0x80
/*----- Time-Out events ----------*/
#define TOE_RESTART_RQST 0x03
#define TOE_CALL_RQST 0x05
#define TOE_CLEAR_RQST 0x08
#define TOE_RESET_RQST 0x0A
/*----- Protocol Violation events */
#define PVE_CLEAR_RQST 0x32
#define PVE_RESET_RQST 0x33
#define PVE_RESTART_RQST 0x34
#define PVE_DIAGNOSTIC 0x37
#define INTR_ON_RX_FRAME 0x01
#define INTR_ON_TX_FRAME 0x02
#define INTR_ON_MODEM_STATUS_CHANGE 0x04
#define INTR_ON_COMMAND_COMPLETE 0x08
#define INTR_ON_X25_ASY_TRANSACTION 0x10
#define INTR_ON_TIMER 0x40
#define DIRECT_RX_INTR_USAGE 0x80
#define NO_INTR_PENDING 0x00
#define RX_INTR_PENDING 0x01
#define TX_INTR_PENDING 0x02
#define MODEM_INTR_PENDING 0x04
#define COMMAND_COMPLETE_INTR_PENDING 0x08
#define X25_ASY_TRANS_INTR_PENDING 0x10
#define TIMER_INTR_PENDING 0x40
/*----------------------------------------------------------------------------
* X.25 Mailbox.
* This structure is located at offsets X25_MBOX_OFFS and X25_RXMBOX_OFFS
* into shared memory window.
*/
typedef struct X25Mbox
{
unsigned char opflag PACKED; /* 00h: execution flag */
TX25Cmd cmd PACKED; /* 01h: command block */
unsigned char data[1] PACKED; /* 10h: data buffer */
} TX25Mbox;
/*----------------------------------------------------------------------------
* X.25 Time Stamp Structure.
*/
typedef struct X25TimeStamp
{
unsigned char month PACKED;
unsigned char date PACKED;
unsigned char sec PACKED;
unsigned char min PACKED;
unsigned char hour PACKED;
} TX25TimeStamp;
/*----------------------------------------------------------------------------
* X.25 Status Block.
* This structure is located at offset X25_STATUS_OFF into shared memory
* window.
*/
typedef struct X25Status
{
unsigned short pvc_map PACKED; /* 00h: PVC map */
unsigned short icc_map PACKED; /* 02h: Incomming Chan. map */
unsigned short twc_map PACKED; /* 04h: Two-way Cnan. map */
unsigned short ogc_map PACKED; /* 06h: Outgoing Chan. map */
TX25TimeStamp tstamp PACKED; /* 08h: timestamp (BCD) */
unsigned char iflags PACKED; /* 0Dh: interrupt flags */
unsigned char imask PACKED; /* 0Eh: interrupt mask */
unsigned char resrv PACKED; /* 0Eh: */
unsigned char gflags PACKED; /* 10h: misc. HDLC/X25 flags */
unsigned char cflags[X25_MAX_CHAN] PACKED; /* channel status bytes */
} TX25Status;
/*
* Bitmasks for the 'iflags' field.
*/
#define X25_RX_INTR 0x01 /* receive interrupt */
#define X25_TX_INTR 0x02 /* transmit interrupt */
#define X25_MODEM_INTR 0x04 /* modem status interrupt (CTS/DCD) */
#define X25_EVENT_INTR 0x10 /* asyncronous event encountered */
#define X25_CMD_INTR 0x08 /* interface command complete */
/*
* Bitmasks for the 'gflags' field.
*/
#define X25_HDLC_ABM 0x01 /* HDLC is in ABM mode */
#define X25_RX_READY 0x02 /* X.25 data available */
#define X25_TRACE_READY 0x08 /* trace data available */
#define X25_EVENT_IND 0x20 /* asynchronous event indicator */
#define X25_TX_READY 0x40 /* space is available in Tx buf.*/
/*
* Bitmasks for the 'cflags' field.
*/
#define X25_XFER_MODE 0x80 /* channel is in data transfer mode */
#define X25_TXWIN_OPEN 0x40 /* transmit window open */
#define X25_RXBUF_MASK 0x3F /* number of data buffers available */
/*****************************************************************************
* Following definitions structurize contents of the TX25Mbox.data field for
* different X.25 interface commands.
****************************************************************************/
/* ---------------------------------------------------------------------------
* X25_SET_GLOBAL_VARS Command.
*/
typedef struct X25GlobalVars
{
unsigned char resrv PACKED; /* 00h: reserved */
unsigned char dtrCtl PACKED; /* 01h: DTR control code */
unsigned char resErr PACKED; /* 01h: '1' - reset modem error */
} TX25GlobalVars;
/*
* Defines for the 'dtrCtl' field.
*/
#define X25_RAISE_DTR 0x01
#define X25_DROP_DTR 0x02
/* ---------------------------------------------------------------------------
* X25_READ_MODEM_STATUS Command.
*/
typedef struct X25ModemStatus
{
unsigned char status PACKED; /* 00h: modem status */
} TX25ModemStatus;
/*
* Defines for the 'status' field.
*/
#define X25_CTS_MASK 0x20
#define X25_DCD_MASK 0x08
/* ---------------------------------------------------------------------------
* X25_HDLC_LINK_STATUS Command.
*/
typedef struct X25LinkStatus
{
unsigned char txQueued PACKED; /* 00h: queued Tx I-frames*/
unsigned char rxQueued PACKED; /* 01h: queued Rx I-frames*/
unsigned char station PACKED; /* 02h: DTE/DCE config. */
unsigned char reserved PACKED; /* 03h: reserved */
unsigned char sfTally PACKED; /* 04h: supervisory frame tally */
} TX25LinkStatus;
/*
* Defines for the 'station' field.
*/
#define X25_STATION_DTE 0x01 /* station configured as DTE */
#define X25_STATION_DCE 0x02 /* station configured as DCE */
/* ---------------------------------------------------------------------------
* X25_HDLC_READ_STATS Command.
*/
typedef struct HdlcStats
{ /* a number of ... */
unsigned short rxIFrames PACKED; /* 00h: ready Rx I-frames */
unsigned short rxNoseq PACKED; /* 02h: frms out-of-sequence */
unsigned short rxNodata PACKED; /* 04h: I-frms without data */
unsigned short rxDiscarded PACKED; /* 06h: discarded frames */
unsigned short rxTooLong PACKED; /* 08h: frames too long */
unsigned short rxBadAddr PACKED; /* 0Ah: frms with inval.addr*/
unsigned short txAcked PACKED; /* 0Ch: acknowledged I-frms */
unsigned short txRetransm PACKED; /* 0Eh: re-transmit. I-frms */
unsigned short t1Timeout PACKED; /* 10h: T1 timeouts */
unsigned short rxSABM PACKED; /* 12h: received SABM frames */
unsigned short rxDISC PACKED; /* 14h: received DISC frames */
unsigned short rxDM PACKED; /* 16h: received DM frames */
unsigned short rxFRMR PACKED; /* 18h: FRMR frames received */
unsigned short txSABM PACKED; /* 1Ah: transm. SABM frames*/
unsigned short txDISC PACKED; /* 1Ch: transm. DISC frames*/
unsigned short txDM PACKED; /* 1Eh: transm. DM frames */
unsigned short txFRMR PACKED; /* 20h: transm. FRMR frames*/
} THdlcStats;
/* ---------------------------------------------------------------------------
* X25_HDLC_READ_COMM_ERR Command.
*/
typedef struct HdlcCommErr
{ /* a number of ... */
unsigned char rxOverrun PACKED; /* 00h: Rx overrun errors */
unsigned char rxBadCrc PACKED; /* 01h: Rx CRC errors */
unsigned char rxAborted PACKED; /* 02h: Rx aborted frames */
unsigned char rxDropped PACKED; /* 03h: frames lost */
unsigned char txAborted PACKED; /* 04h: Tx aborted frames */
unsigned char txUnderrun PACKED; /* 05h: Tx underrun errors */
unsigned char txMissIntr PACKED; /* 06h: missed underrun ints */
unsigned char reserved PACKED; /* 07h: reserved */
unsigned char droppedDCD PACKED; /* 08h: times DCD dropped */
unsigned char droppedCTS PACKED; /* 09h: times CTS dropped */
} THdlcCommErr;
/* ---------------------------------------------------------------------------
* X25_SET_CONFIGURATION & X25_READ_CONFIGURATION Commands.
*/
typedef struct X25Config
{
unsigned char baudRate PACKED; /* 00h: */
unsigned char t1 PACKED; /* 01h: */
unsigned char t2 PACKED; /* 02h: */
unsigned char n2 PACKED; /* 03h: */
unsigned short hdlcMTU PACKED; /* 04h: */
unsigned char hdlcWindow PACKED; /* 06h: */
unsigned char t4 PACKED; /* 07h: */
unsigned char autoModem PACKED; /* 08h: */
unsigned char autoHdlc PACKED; /* 09h: */
unsigned char hdlcOptions PACKED; /* 0Ah: */
unsigned char station PACKED; /* 0Bh: */
unsigned char pktWindow PACKED; /* 0Ch: */
unsigned short defPktSize PACKED; /* 0Dh: */
unsigned short pktMTU PACKED; /* 0Fh: */
unsigned short loPVC PACKED; /* 11h: */
unsigned short hiPVC PACKED; /* 13h: */
unsigned short loIncommingSVC PACKED; /* 15h: */
unsigned short hiIncommingSVC PACKED; /* 17h: */
unsigned short loTwoWaySVC PACKED; /* 19h: */
unsigned short hiTwoWaySVC PACKED; /* 1Bh: */
unsigned short loOutgoingSVC PACKED; /* 1Dh: */
unsigned short hiOutgoingSVC PACKED; /* 1Fh: */
unsigned short options PACKED; /* 21h: */
unsigned char responseOpt PACKED; /* 23h: */
unsigned short facil1 PACKED; /* 24h: */
unsigned short facil2 PACKED; /* 26h: */
unsigned short ccittFacil PACKED; /* 28h: */
unsigned short otherFacil PACKED; /* 2Ah: */
unsigned short ccittCompat PACKED; /* 2Ch: */
unsigned char t10t20 PACKED; /* 2Eh: */
unsigned char t11t21 PACKED; /* 2Fh: */
unsigned char t12t22 PACKED; /* 30h: */
unsigned char t13t23 PACKED; /* 31h: */
unsigned char t16t26 PACKED; /* 32H: */
unsigned char t28 PACKED; /* 33h: */
unsigned char r10r20 PACKED; /* 34h: */
unsigned char r12r22 PACKED; /* 35h: */
unsigned char r13r23 PACKED; /* 36h: */
} TX25Config;
/* ---------------------------------------------------------------------------
* X25_READ_CHANNEL_CONFIG Command.
*/
typedef struct X25ChanAlloc /*----- Channel allocation -*/
{
unsigned short loPVC PACKED; /* 00h: lowest PVC number */
unsigned short hiPVC PACKED; /* 02h: highest PVC number */
unsigned short loIncommingSVC PACKED; /* 04h: lowest incoming SVC */
unsigned short hiIncommingSVC PACKED; /* 06h: highest incoming SVC */
unsigned short loTwoWaySVC PACKED; /* 08h: lowest two-way SVC */
unsigned short hiTwoWaySVC PACKED; /* 0Ah: highest two-way SVC */
unsigned short loOutgoingSVC PACKED; /* 0Ch: lowest outgoing SVC */
unsigned short hiOutgoingSVC PACKED; /* 0Eh: highest outgoing SVC */
} TX25ChanAlloc;
typedef struct X25ChanCfg /*------ Channel configuration -----*/
{
unsigned char type PACKED; /* 00h: channel type */
unsigned char txConf PACKED; /* 01h: Tx packet and window sizes */
unsigned char rxConf PACKED; /* 01h: Rx packet and window sizes */
} TX25ChanCfg;
/*
* Defines for the 'type' field.
*/
#define X25_PVC 0x01 /* PVC */
#define X25_SVC_IN 0x03 /* Incoming SVC */
#define X25_SVC_TWOWAY 0x07 /* Two-way SVC */
#define X25_SVC_OUT 0x0B /* Outgoing SVC */
/*----------------------------------------------------------------------------
* X25_READ_STATISTICS Command.
*/
typedef struct X25Stats
{ /* number of packets Tx/Rx'ed */
unsigned short txRestartRqst PACKED; /* 00h: Restart Request */
unsigned short rxRestartRqst PACKED; /* 02h: Restart Request */
unsigned short txRestartConf PACKED; /* 04h: Restart Confirmation */
unsigned short rxRestartConf PACKED; /* 06h: Restart Confirmation */
unsigned short txResetRqst PACKED; /* 08h: Reset Request */
unsigned short rxResetRqst PACKED; /* 0Ah: Reset Request */
unsigned short txResetConf PACKED; /* 0Ch: Reset Confirmation */
unsigned short rxResetConf PACKED; /* 0Eh: Reset Confirmation */
unsigned short txCallRequest PACKED; /* 10h: Call Request */
unsigned short rxCallRequest PACKED; /* 12h: Call Request */
unsigned short txCallAccept PACKED; /* 14h: Call Accept */
unsigned short rxCallAccept PACKED; /* 16h: Call Accept */
unsigned short txClearRqst PACKED; /* 18h: Clear Request */
unsigned short rxClearRqst PACKED; /* 1Ah: Clear Request */
unsigned short txClearConf PACKED; /* 1Ch: Clear Confirmation */
unsigned short rxClearConf PACKED; /* 1Eh: Clear Confirmation */
unsigned short txDiagnostic PACKED; /* 20h: Diagnostic */
unsigned short rxDiagnostic PACKED; /* 22h: Diagnostic */
unsigned short txRegRqst PACKED; /* 24h: Registration Request */
unsigned short rxRegRqst PACKED; /* 26h: Registration Request */
unsigned short txRegConf PACKED; /* 28h: Registration Confirm.*/
unsigned short rxRegConf PACKED; /* 2Ah: Registration Confirm.*/
unsigned short txInterrupt PACKED; /* 2Ch: Interrupt */
unsigned short rxInterrupt PACKED; /* 2Eh: Interrupt */
unsigned short txIntrConf PACKED; /* 30h: Interrupt Confirm. */
unsigned short rxIntrConf PACKED; /* 32h: Interrupt Confirm. */
unsigned short txData PACKED; /* 34h: Data */
unsigned short rxData PACKED; /* 36h: Data */
unsigned short txRR PACKED; /* 38h: RR */
unsigned short rxRR PACKED; /* 3Ah: RR */
unsigned short txRNR PACKED; /* 3Ch: RNR */
unsigned short rxRNR PACKED; /* 3Eh: RNR */
} TX25Stats;
/*----------------------------------------------------------------------------
* X25_READ_HISTORY_TABLE Command.
*/
typedef struct X25EventLog
{
unsigned char type PACKED; /* 00h: transaction type */
unsigned short lcn PACKED; /* 01h: logical channel num */
unsigned char packet PACKED; /* 03h: async packet type */
unsigned char cause PACKED; /* 04h: X.25 cause field */
unsigned char diag PACKED; /* 05h: X.25 diag field */
TX25TimeStamp ts PACKED; /* 06h: time stamp */
} TX25EventLog;
/*
* Defines for the 'type' field.
*/
#define X25LOG_INCOMMING 0x00
#define X25LOG_APPLICATION 0x01
#define X25LOG_AUTOMATIC 0x02
#define X25LOG_ERROR 0x04
#define X25LOG_TIMEOUT 0x08
#define X25LOG_RECOVERY 0x10
/*
* Defines for the 'packet' field.
*/
#define X25LOG_CALL_RQST 0x0B
#define X25LOG_CALL_ACCEPTED 0x0F
#define X25LOG_CLEAR_RQST 0x13
#define X25LOG_CLEAR_CONFRM 0x17
#define X25LOG_RESET_RQST 0x1B
#define X25LOG_RESET_CONFRM 0x1F
#define X25LOG_RESTART_RQST 0xFB
#define X25LOG_RESTART_COMFRM 0xFF
#define X25LOG_DIAGNOSTIC 0xF1
#define X25LOG_DTE_REG_RQST 0xF3
#define X25LOG_DTE_REG_COMFRM 0xF7
/* ---------------------------------------------------------------------------
* X25_TRACE_CONFIGURE Command.
*/
typedef struct X25TraceCfg
{
unsigned char flags PACKED; /* 00h: trace configuration flags */
unsigned char timeout PACKED; /* 01h: timeout for trace delay mode*/
} TX25TraceCfg;
/*
* Defines for the 'flags' field.
*/
#define X25_TRC_ENABLE 0x01 /* bit0: '1' - trace enabled */
#define X25_TRC_TIMESTAMP 0x02 /* bit1: '1' - time stamping enabled*/
#define X25_TRC_DELAY 0x04 /* bit2: '1' - trace delay enabled */
#define X25_TRC_DATA 0x08 /* bit3: '1' - trace data packets */
#define X25_TRC_SUPERVISORY 0x10 /* bit4: '1' - trace suprvisory pkts*/
#define X25_TRC_ASYNCHRONOUS 0x20 /* bit5: '1' - trace asynch. packets*/
#define X25_TRC_HDLC 0x40 /* bit6: '1' - trace all packets */
#define X25_TRC_READ 0x80 /* bit7: '1' - get current config. */
/* ---------------------------------------------------------------------------
* X25_READ_TRACE_DATA Command.
*/
typedef struct X25Trace /*----- Trace data structure -------*/
{
unsigned short length PACKED; /* 00h: trace data length */
unsigned char type PACKED; /* 02h: trace type */
unsigned char lost_cnt PACKED; /* 03h: N of traces lost */
TX25TimeStamp tstamp PACKED; /* 04h: mon/date/sec/min/hour */
unsigned short millisec PACKED; /* 09h: ms time stamp */
unsigned char data[0] PACKED; /* 0Bh: traced frame */
} TX25Trace;
/*
* Defines for the 'type' field.
*/
#define X25_TRC_TYPE_MASK 0x0F /* bits 0..3: trace type */
#define X25_TRC_TYPE_RX_FRAME 0x00 /* received frame trace */
#define X25_TRC_TYPE_TX_FRAME 0x01 /* transmitted frame */
#define X25_TRC_TYPE_ERR_FRAME 0x02 /* error frame */
#define X25_TRC_ERROR_MASK 0xF0 /* bits 4..7: error code */
#define X25_TRCERR_RX_ABORT 0x10 /* receive abort error */
#define X25_TRCERR_RX_BADCRC 0x20 /* receive CRC error */
#define X25_TRCERR_RX_OVERRUN 0x30 /* receiver overrun error */
#define X25_TRCERR_RX_TOO_LONG 0x40 /* excessive frame length error */
#define X25_TRCERR_TX_ABORT 0x70 /* aborted frame transmittion error */
#define X25_TRCERR_TX_UNDERRUN 0x80 /* transmit underrun error */
/*****************************************************************************
* Following definitions describe HDLC frame and X.25 packet formats.
****************************************************************************/
typedef struct HDLCFrame /*----- DHLC Frame Format ----------*/
{
unsigned char addr PACKED; /* address field */
unsigned char cntl PACKED; /* control field */
unsigned char data[0] PACKED;
} THDLCFrame;
typedef struct X25Pkt /*----- X.25 Paket Format ----------*/
{
unsigned char lcn_hi PACKED; /* 4 MSB of Logical Channel Number */
unsigned char lcn_lo PACKED; /* 8 LSB of Logical Channel Number */
unsigned char type PACKED;
unsigned char data[0] PACKED;
} TX25Pkt;
/*
* Defines for the 'lcn_hi' field.
*/
#define X25_Q_BIT_MASK 0x80 /* Data Qualifier Bit mask */
#define X25_D_BIT_MASK 0x40 /* Delivery Confirmation Bit mask */
#define X25_M_BITS_MASK 0x30 /* Modulo Bits mask */
#define X25_LCN_MSB_MASK 0x0F /* LCN most significant bits mask */
/*
* Defines for the 'type' field.
*/
#define X25PKT_DATA 0x01 /* Data packet mask */
#define X25PKT_SUPERVISORY 0x02 /* Supervisory packet mask */
#define X25PKT_CALL_RQST 0x0B /* Call Request/Incoming */
#define X25PKT_CALL_ACCEPTED 0x0F /* Call Accepted/Connected */
#define X25PKT_CLEAR_RQST 0x13 /* Clear Request/Indication */
#define X25PKT_CLEAR_CONFRM 0x17 /* Clear Confirmation */
#define X25PKT_RESET_RQST 0x1B /* Reset Request/Indication */
#define X25PKT_RESET_CONFRM 0x1F /* Reset Confirmation */
#define X25PKT_RESTART_RQST 0xFB /* Restart Request/Indication */
#define X25PKT_RESTART_CONFRM 0xFF /* Restart Confirmation */
#define X25PKT_INTERRUPT 0x23 /* Interrupt */
#define X25PKT_INTERRUPT_CONFRM 0x27 /* Interrupt Confirmation */
#define X25PKT_DIAGNOSTIC 0xF1 /* Diagnostic */
#define X25PKT_REGISTR_RQST 0xF3 /* Registration Request */
#define X25PKT_REGISTR_CONFRM 0xF7 /* Registration Confirmation */
#define X25PKT_RR_MASKED 0x01 /* Receive Ready packet after masking */
#define X25PKT_RNR_MASKED 0x05 /* Receive Not Ready after masking */
typedef struct {
TX25Cmd cmd PACKED;
char data[X25_MAX_DATA] PACKED;
} mbox_cmd_t;
typedef struct {
unsigned char qdm PACKED; /* Q/D/M bits */
unsigned char cause PACKED; /* cause field */
unsigned char diagn PACKED; /* diagnostics */
unsigned char pktType PACKED;
unsigned short length PACKED;
unsigned char result PACKED;
unsigned short lcn PACKED;
char reserved[7] PACKED;
}x25api_hdr_t;
typedef struct {
x25api_hdr_t hdr PACKED;
char data[X25_MAX_DATA] PACKED;
}x25api_t;
/*
* XPIPEMON Definitions
*/
/* valid ip_protocol for UDP management */
#define UDPMGMT_UDP_PROTOCOL 0x11
#define UDPMGMT_XPIPE_SIGNATURE "XLINK8ND"
#define UDPMGMT_DRVRSTATS_SIGNATURE "DRVSTATS"
/* values for request/reply byte */
#define UDPMGMT_REQUEST 0x01
#define UDPMGMT_REPLY 0x02
#define UDP_OFFSET 12
typedef struct {
unsigned char opp_flag PACKED; /* the opp flag */
unsigned char command PACKED; /* command code */
unsigned short length PACKED; /* transfer data length */
unsigned char result PACKED; /* return code */
unsigned char pf PACKED; /* P/F bit */
unsigned short lcn PACKED; /* logical channel */
unsigned char qdm PACKED; /* Q/D/M bits */
unsigned char cause PACKED; /* cause field */
unsigned char diagn PACKED; /* diagnostics */
unsigned char pktType PACKED; /* packet type */
unsigned char resrv[4] PACKED; /* reserved */
} cblock_t;
typedef struct {
ip_pkt_t ip_pkt PACKED;
udp_pkt_t udp_pkt PACKED;
wp_mgmt_t wp_mgmt PACKED;
cblock_t cblock PACKED;
unsigned char data[4080] PACKED;
} x25_udp_pkt_t;
typedef struct read_hdlc_stat {
unsigned short inf_frames_rx_ok PACKED;
unsigned short inf_frames_rx_out_of_seq PACKED;
unsigned short inf_frames_rx_no_data PACKED;
unsigned short inf_frames_rx_dropped PACKED;
unsigned short inf_frames_rx_data_too_long PACKED;
unsigned short inf_frames_rx_invalid_addr PACKED;
unsigned short inf_frames_tx_ok PACKED;
unsigned short inf_frames_tx_retransmit PACKED;
unsigned short T1_timeouts PACKED;
unsigned short SABM_frames_rx PACKED;
unsigned short DISC_frames_rx PACKED;
unsigned short DM_frames_rx PACKED;
unsigned short FRMR_frames_rx PACKED;
unsigned short SABM_frames_tx PACKED;
unsigned short DISC_frames_tx PACKED;
unsigned short DM_frames_tx PACKED;
unsigned short FRMR_frames_tx PACKED;
} read_hdlc_stat_t;
typedef struct read_comms_err_stats{
unsigned char overrun_err_rx PACKED;
unsigned char CRC_err PACKED;
unsigned char abort_frames_rx PACKED;
unsigned char frames_dropped_buf_full PACKED;
unsigned char abort_frames_tx PACKED;
unsigned char transmit_underruns PACKED;
unsigned char missed_tx_underruns_intr PACKED;
unsigned char reserved PACKED;
unsigned char DCD_drop PACKED;
unsigned char CTS_drop PACKED;
} read_comms_err_stats_t;
typedef struct trace_data {
unsigned short length PACKED;
unsigned char type PACKED;
unsigned char trace_dropped PACKED;
unsigned char reserved[5] PACKED;
unsigned short timestamp PACKED;
unsigned char data PACKED;
} trace_data_t;
enum {UDP_XPIPE_TYPE};
#define XPIPE_ENABLE_TRACING 0x14
#define XPIPE_DISABLE_TRACING 0x14
#define XPIPE_GET_TRACE_INFO 0x16
#define XPIPE_FT1_READ_STATUS 0x74
#define XPIPE_DRIVER_STAT_IFSEND 0x75
#define XPIPE_DRIVER_STAT_INTR 0x76
#define XPIPE_DRIVER_STAT_GEN 0x77
#define XPIPE_FLUSH_DRIVER_STATS 0x78
#define XPIPE_ROUTER_UP_TIME 0x79
#define XPIPE_SET_FT1_MODE 0x81
#define XPIPE_FT1_STATUS_CTRL 0x80
/* error messages */
#define NO_BUFFS_OR_CLOSED_WIN 0x33
#define DATA_LENGTH_TOO_BIG 0x32
#define NO_DATA_AVAILABLE 0x33
#define Z80_TIMEOUT_ERROR 0x0a
#define NO_BUFFS 0x08
/* Trace options */
#define TRACE_DEFAULT 0x03
#define TRACE_SUPERVISOR_FRMS 0x10
#define TRACE_ASYNC_FRMS 0x20
#define TRACE_ALL_HDLC_FRMS 0x40
#define TRACE_DATA_FRMS 0x08
#endif /* _SDLA_X25_H */
/*****************************************************************************
* sdladrv.h SDLA Support Module. Kernel API Definitions.
*
* Author: Gideon Hack
*
* Copyright: (c) 1995-2000 Sangoma Technologies Inc.
*
* 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.
* ============================================================================
* Jun 02, 1999 Gideon Hack Added support for the S514 PCI adapter.
* Dec 11, 1996 Gene Kozin Complete overhaul.
* Oct 17, 1996 Gene Kozin Minor bug fixes.
* Jun 12, 1996 Gene Kozin Added support for S503 card.
* Dec 06, 1995 Gene Kozin Initial version.
*****************************************************************************/
#ifndef _SDLADRV_H
#define _SDLADRV_H
#define SDLA_MAXIORANGE 4 /* maximum I/O port range */
#define SDLA_WINDOWSIZE 0x2000 /* default dual-port memory window size */
/****** Data Structures *****************************************************/
/*----------------------------------------------------------------------------
* Adapter hardware configuration. Pointer to this structure is passed to all
* APIs.
*/
typedef struct sdlahw
{
unsigned type; /* adapter type */
unsigned fwid; /* firmware ID */
unsigned port; /* adapter I/O port base */
int irq; /* interrupt request level */
char S514_cpu_no[1]; /* PCI CPU Number */
unsigned char S514_slot_no; /* PCI Slot Number */
char auto_pci_cfg; /* Autodetect PCI Slot */
struct pci_dev *pci_dev; /* PCI device */
void * dpmbase; /* dual-port memory base */
unsigned dpmsize; /* dual-port memory size */
unsigned pclk; /* CPU clock rate, kHz */
unsigned long memory; /* memory size */
unsigned long vector; /* local offset of the DPM window */
unsigned io_range; /* I/O port range */
unsigned char regs[SDLA_MAXIORANGE]; /* was written to registers */
unsigned reserved[5];
} sdlahw_t;
/****** Function Prototypes *************************************************/
extern int sdla_setup (sdlahw_t* hw, void* sfm, unsigned len);
extern int sdla_down (sdlahw_t* hw);
extern void S514_intack (sdlahw_t* hw, u32 int_status);
extern void read_S514_int_stat (sdlahw_t* hw, u32* int_status);
extern int sdla_mapmem (sdlahw_t* hw, unsigned long addr);
extern int sdla_peek (sdlahw_t* hw, unsigned long addr, void* buf,
unsigned len);
extern int sdla_poke (sdlahw_t* hw, unsigned long addr, void* buf,
unsigned len);
extern int sdla_exec (void* opflag);
extern unsigned wanpipe_hw_probe(void);
#endif /* _SDLADRV_H */
/*****************************************************************************
* sdlapci.h WANPIPE(tm) Multiprotocol WAN Link Driver.
* Definitions for the SDLA PCI adapter.
*
* Author: Gideon Hack <ghack@sangoma.com>
*
* Copyright: (c) 1999-2000 Sangoma Technologies Inc.
*
* 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.
* ============================================================================
* Jun 02, 1999 Gideon Hack Initial version.
*****************************************************************************/
#ifndef _SDLAPCI_H
#define _SDLAPCI_H
/****** Defines *************************************************************/
/* Definitions for identifying and finding S514 PCI adapters */
#define V3_VENDOR_ID 0x11B0 /* V3 vendor ID number */
#define V3_DEVICE_ID 0x0002 /* V3 device ID number */
#define SANGOMA_SUBSYS_VENDOR 0x4753 /* ID for Sangoma */
#define PCI_DEV_SLOT_MASK 0x1F /* mask for slot numbering */
#define PCI_IRQ_NOT_ALLOCATED 0xFF /* interrupt line for no IRQ */
/* Local PCI register offsets */
#define PCI_VENDOR_ID_WORD 0x00 /* vendor ID */
#define PCI_IO_BASE_DWORD 0x10 /* IO base */
#define PCI_MEM_BASE0_DWORD 0x14 /* memory base - apperture 0 */
#define PCI_MEM_BASE1_DWORD 0x18 /* memory base - apperture 1 */
#define PCI_SUBSYS_VENDOR_WORD 0x2C /* subsystem vendor ID */
#define PCI_INT_LINE_BYTE 0x3C /* interrupt line */
#define PCI_INT_PIN_BYTE 0x3D /* interrupt pin */
#define PCI_MAP0_DWORD 0x40 /* PCI to local bus address 0 */
#define PCI_MAP1_DWORD 0x44 /* PCI to local bus address 1 */
#define PCI_INT_STATUS 0x48 /* interrupt status */
#define PCI_INT_CONFIG 0x4C /* interrupt configuration */
/* Local PCI register usage */
#define PCI_MEMORY_ENABLE 0x00000003 /* enable PCI memory */
#define PCI_CPU_A_MEM_DISABLE 0x00000002 /* disable CPU A memory */
#define PCI_CPU_B_MEM_DISABLE 0x00100002 /* disable CPU B memory */
#define PCI_ENABLE_IRQ_CPU_A 0x005A0004 /* enable IRQ for CPU A */
#define PCI_ENABLE_IRQ_CPU_B 0x005A0008 /* enable IRQ for CPU B */
#define PCI_DISABLE_IRQ_CPU_A 0x00000004 /* disable IRQ for CPU A */
#define PCI_DISABLE_IRQ_CPU_B 0x00000008 /* disable IRQ for CPU B */
/* Setting for the Interrupt Status register */
#define IRQ_CPU_A 0x04 /* IRQ for CPU A */
#define IRQ_CPU_B 0x08 /* IRQ for CPU B */
/* The maximum size of the S514 memory */
#define MAX_SIZEOF_S514_MEMORY (256 * 1024)
/* S514 control register offsets within the memory address space */
#define S514_CTRL_REG_BYTE 0x80000
/* S514 adapter control bytes */
#define S514_CPU_HALT 0x00
#define S514_CPU_START 0x01
/* The maximum number of S514 adapters supported */
#define MAX_S514_CARDS 20
#define PCI_CARD_TYPE 0x2E
#define S514_DUAL_CPU 0x12
#define S514_SINGLE_CPU 0x11
#endif /* _SDLAPCI_H */
/*****************************************************************************
* sdlasfm.h WANPIPE(tm) Multiprotocol WAN Link Driver.
* Definitions for the SDLA Firmware Module (SFM).
*
* Author: Gideon Hack
*
* Copyright: (c) 1995-1999 Sangoma Technologies Inc.
*
* 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.
* ============================================================================
* Jun 02, 1999 Gideon Hack Added support for the S514 adapter.
* Dec 11, 1996 Gene Kozin Cosmetic changes
* Apr 16, 1996 Gene Kozin Changed adapter & firmware IDs. Version 2
* Dec 15, 1995 Gene Kozin Structures chaned
* Nov 09, 1995 Gene Kozin Initial version.
*****************************************************************************/
#ifndef _SDLASFM_H
#define _SDLASFM_H
/****** Defines *************************************************************/
#define SFM_VERSION 2
#define SFM_SIGNATURE "SFM - Sangoma SDLA Firmware Module"
/* min/max */
#define SFM_IMAGE_SIZE 0x8000 /* max size of SDLA code image file */
#define SFM_DESCR_LEN 256 /* max length of description string */
#define SFM_MAX_SDLA 16 /* max number of compatible adapters */
/* Adapter types */
#define SDLA_S502A 5020
#define SDLA_S502E 5021
#define SDLA_S503 5030
#define SDLA_S508 5080
#define SDLA_S507 5070
#define SDLA_S509 5090
#define SDLA_S514 5140
/* S514 PCI adapter CPU numbers */
#define S514_CPU_A 'A'
#define S514_CPU_B 'B'
/* Firmware identification numbers:
* 0 .. 999 Test & Diagnostics
* 1000 .. 1999 Streaming HDLC
* 2000 .. 2999 Bisync
* 3000 .. 3999 SDLC
* 4000 .. 4999 HDLC
* 5000 .. 5999 X.25
* 6000 .. 6999 Frame Relay
* 7000 .. 7999 PPP
* 8000 .. 8999 Cisco HDLC
*/
#define SFID_CALIB502 200
#define SFID_STRM502 1200
#define SFID_STRM508 1800
#define SFID_BSC502 2200
#define SFID_SDLC502 3200
#define SFID_HDLC502 4200
#define SFID_HDLC508 4800
#define SFID_X25_502 5200
#define SFID_X25_508 5800
#define SFID_FR502 6200
#define SFID_FR508 6800
#define SFID_PPP502 7200
#define SFID_PPP508 7800
#define SFID_PPP514 7140
#define SFID_CHDLC508 8800
#define SFID_CHDLC514 8140
/****** Data Types **********************************************************/
typedef struct sfm_info /* firmware module information */
{
unsigned short codeid; /* firmware ID */
unsigned short version; /* firmaware version number */
unsigned short adapter[SFM_MAX_SDLA]; /* compatible adapter types */
unsigned long memsize; /* minimum memory size */
unsigned short reserved[2]; /* reserved */
unsigned short startoffs; /* entry point offset */
unsigned short winoffs; /* dual-port memory window offset */
unsigned short codeoffs; /* code load offset */
unsigned short codesize; /* code size */
unsigned short dataoffs; /* configuration data load offset */
unsigned short datasize; /* configuration data size */
} sfm_info_t;
typedef struct sfm /* SDLA firmware file structire */
{
char signature[80]; /* SFM file signature */
unsigned short version; /* file format version */
unsigned short checksum; /* info + image */
unsigned short reserved[6]; /* reserved */
char descr[SFM_DESCR_LEN]; /* description string */
sfm_info_t info; /* firmware module info */
unsigned char image[1]; /* code image (variable size) */
} sfm_t;
#endif /* _SDLASFM_H */
/*****************************************************************************
* wanpipe.h WANPIPE(tm) Multiprotocol WAN Link Driver.
* User-level API definitions.
*
* Author: Nenad Corbic <ncorbic@sangoma.com>
* Gideon Hack
*
* Copyright: (c) 1995-2000 Sangoma Technologies Inc.
*
* 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.
* ============================================================================
* Nov 3, 2000 Nenad Corbic Added config_id to sdla_t structure.
* Used to determine the protocol running.
* Jul 13, 2000 Nenad Corbic Added SyncPPP Support
* Feb 24, 2000 Nenad Corbic Added support for x25api driver
* Oct 04, 1999 Nenad Corbic New CHDLC and FRAME RELAY code, SMP support
* Jun 02, 1999 Gideon Hack Added 'update_call_count' for Cisco HDLC
* support
* Jun 26, 1998 David Fong Added 'ip_mode' in sdla_t.u.p for dynamic IP
* routing mode configuration
* Jun 12, 1998 David Fong Added Cisco HDLC union member in sdla_t
* Dec 08, 1997 Jaspreet Singh Added 'authenticator' in union of 'sdla_t'
* Nov 26, 1997 Jaspreet Singh Added 'load_sharing' structure. Also added
* 'devs_struct','dev_to_devtint_next' to 'sdla_t'
* Nov 24, 1997 Jaspreet Singh Added 'irq_dis_if_send_count',
* 'irq_dis_poll_count' to 'sdla_t'.
* Nov 06, 1997 Jaspreet Singh Added a define called 'INTR_TEST_MODE'
* Oct 20, 1997 Jaspreet Singh Added 'buff_intr_mode_unbusy' and
* 'dlci_intr_mode_unbusy' to 'sdla_t'
* Oct 18, 1997 Jaspreet Singh Added structure to maintain global driver
* statistics.
* Jan 15, 1997 Gene Kozin Version 3.1.0
* o added UDP management stuff
* Jan 02, 1997 Gene Kozin Version 3.0.0
*****************************************************************************/
#ifndef _WANPIPE_H
#define _WANPIPE_H
#include <linux/wanrouter.h>
/* Defines */
#ifndef PACKED
#define PACKED __attribute__((packed))
#endif
#define WANPIPE_MAGIC 0x414C4453L /* signature: 'SDLA' reversed */
/* IOCTL numbers (up to 16) */
#define WANPIPE_DUMP (ROUTER_USER+0) /* dump adapter's memory */
#define WANPIPE_EXEC (ROUTER_USER+1) /* execute firmware command */
#define TRACE_ALL 0x00
#define TRACE_PROT 0x01
#define TRACE_DATA 0x02
/* values for request/reply byte */
#define UDPMGMT_REQUEST 0x01
#define UDPMGMT_REPLY 0x02
#define UDP_OFFSET 12
#define MAX_CMD_BUFF 10
#define MAX_X25_LCN 255 /* Maximum number of x25 channels */
#define MAX_LCN_NUM 4095 /* Maximum lcn number */
#define MAX_FT1_RETRY 100
#ifndef AF_WANPIPE
#define AF_WANPIPE 25
#ifndef PF_WANPIPE
#define PF_WANPIPE AF_WANPIPE
#endif
#endif
#define TX_TIMEOUT 5*HZ
/* General Critical Flags */
#define SEND_CRIT 0x00
#define PERI_CRIT 0x01
/* Chdlc and PPP polling critical flag */
#define POLL_CRIT 0x03
/* Frame Relay Tx IRQ send critical flag */
#define SEND_TXIRQ_CRIT 0x02
/* Frame Relay ARP critical flag */
#define ARP_CRIT 0x03
/* Bit maps for dynamic interface configuration
* DYN_OPT_ON : turns this option on/off
* DEV_DOWN : device was shutdown by the driver not
* by user
*/
#define DYN_OPT_ON 0x00
#define DEV_DOWN 0x01
/*
* Data structures for IOCTL calls.
*/
typedef struct sdla_dump /* WANPIPE_DUMP */
{
unsigned long magic; /* for verification */
unsigned long offset; /* absolute adapter memory address */
unsigned long length; /* block length */
void* ptr; /* -> buffer */
} sdla_dump_t;
typedef struct sdla_exec /* WANPIPE_EXEC */
{
unsigned long magic; /* for verification */
void* cmd; /* -> command structure */
void* data; /* -> data buffer */
} sdla_exec_t;
/* UDP management stuff */
typedef struct wum_header
{
unsigned char signature[8]; /* 00h: signature */
unsigned char type; /* 08h: request/reply */
unsigned char command; /* 09h: commnand */
unsigned char reserved[6]; /* 0Ah: reserved */
} wum_header_t;
/*************************************************************************
Data Structure for global statistics
*************************************************************************/
typedef struct global_stats
{
unsigned long isr_entry;
unsigned long isr_already_critical;
unsigned long isr_rx;
unsigned long isr_tx;
unsigned long isr_intr_test;
unsigned long isr_spurious;
unsigned long isr_enable_tx_int;
unsigned long rx_intr_corrupt_rx_bfr;
unsigned long rx_intr_on_orphaned_DLCI;
unsigned long rx_intr_dev_not_started;
unsigned long tx_intr_dev_not_started;
unsigned long poll_entry;
unsigned long poll_already_critical;
unsigned long poll_processed;
unsigned long poll_tbusy_bad_status;
unsigned long poll_host_disable_irq;
unsigned long poll_host_enable_irq;
} global_stats_t;
typedef struct{
unsigned short udp_src_port PACKED;
unsigned short udp_dst_port PACKED;
unsigned short udp_length PACKED;
unsigned short udp_checksum PACKED;
} udp_pkt_t;
typedef struct {
unsigned char ver_inet_hdr_length PACKED;
unsigned char service_type PACKED;
unsigned short total_length PACKED;
unsigned short identifier PACKED;
unsigned short flags_frag_offset PACKED;
unsigned char ttl PACKED;
unsigned char protocol PACKED;
unsigned short hdr_checksum PACKED;
unsigned long ip_src_address PACKED;
unsigned long ip_dst_address PACKED;
} ip_pkt_t;
typedef struct {
unsigned char signature[8] PACKED;
unsigned char request_reply PACKED;
unsigned char id PACKED;
unsigned char reserved[6] PACKED;
} wp_mgmt_t;
/*************************************************************************
Data Structure for if_send statistics
*************************************************************************/
typedef struct if_send_stat{
unsigned long if_send_entry;
unsigned long if_send_skb_null;
unsigned long if_send_broadcast;
unsigned long if_send_multicast;
unsigned long if_send_critical_ISR;
unsigned long if_send_critical_non_ISR;
unsigned long if_send_tbusy;
unsigned long if_send_tbusy_timeout;
unsigned long if_send_PIPE_request;
unsigned long if_send_wan_disconnected;
unsigned long if_send_dlci_disconnected;
unsigned long if_send_no_bfrs;
unsigned long if_send_adptr_bfrs_full;
unsigned long if_send_bfr_passed_to_adptr;
unsigned long if_send_protocol_error;
unsigned long if_send_bfr_not_passed_to_adptr;
unsigned long if_send_tx_int_enabled;
unsigned long if_send_consec_send_fail;
} if_send_stat_t;
typedef struct rx_intr_stat{
unsigned long rx_intr_no_socket;
unsigned long rx_intr_dev_not_started;
unsigned long rx_intr_PIPE_request;
unsigned long rx_intr_bfr_not_passed_to_stack;
unsigned long rx_intr_bfr_passed_to_stack;
} rx_intr_stat_t;
typedef struct pipe_mgmt_stat{
unsigned long UDP_PIPE_mgmt_kmalloc_err;
unsigned long UDP_PIPE_mgmt_direction_err;
unsigned long UDP_PIPE_mgmt_adptr_type_err;
unsigned long UDP_PIPE_mgmt_adptr_cmnd_OK;
unsigned long UDP_PIPE_mgmt_adptr_cmnd_timeout;
unsigned long UDP_PIPE_mgmt_adptr_send_passed;
unsigned long UDP_PIPE_mgmt_adptr_send_failed;
unsigned long UDP_PIPE_mgmt_not_passed_to_stack;
unsigned long UDP_PIPE_mgmt_passed_to_stack;
unsigned long UDP_PIPE_mgmt_no_socket;
unsigned long UDP_PIPE_mgmt_passed_to_adptr;
} pipe_mgmt_stat_t;
typedef struct {
struct sk_buff *skb;
} bh_data_t, cmd_data_t;
#define MAX_LGTH_UDP_MGNT_PKT 2000
/* This is used for interrupt testing */
#define INTR_TEST_MODE 0x02
#define WUM_SIGNATURE_L 0x50495046
#define WUM_SIGNATURE_H 0x444E3845
#define WUM_KILL 0x50
#define WUM_EXEC 0x51
#define WANPIPE 0x00
#define API 0x01
#define BRIDGE 0x02
#define BRIDGE_NODE 0x03
#ifdef __KERNEL__
/****** Kernel Interface ****************************************************/
#include <linux/sdladrv.h> /* SDLA support module API definitions */
#include <linux/sdlasfm.h> /* SDLA firmware module definitions */
#include <linux/workqueue.h>
#include <linux/serial.h>
#include <linux/serialP.h>
#include <linux/serial_reg.h>
#include <asm/serial.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <linux/tty_flip.h>
/****** Data Structures *****************************************************/
/* Adapter Data Space.
* This structure is needed because we handle multiple cards, otherwise
* static data would do it.
*/
typedef struct sdla
{
char devname[WAN_DRVNAME_SZ+1]; /* card name */
sdlahw_t hw; /* hardware configuration */
struct wan_device wandev; /* WAN device data space */
unsigned open_cnt; /* number of open interfaces */
unsigned long state_tick; /* link state timestamp */
unsigned intr_mode; /* Type of Interrupt Mode */
char in_isr; /* interrupt-in-service flag */
char buff_int_mode_unbusy; /* flag for carrying out dev_tint */
char dlci_int_mode_unbusy; /* flag for carrying out dev_tint */
long configured; /* flag for previous configurations */
unsigned short irq_dis_if_send_count; /* Disabling irqs in if_send*/
unsigned short irq_dis_poll_count; /* Disabling irqs in poll routine*/
unsigned short force_enable_irq;
char TracingEnabled; /* flag for enabling trace */
global_stats_t statistics; /* global statistics */
void* mbox; /* -> mailbox */
void* rxmb; /* -> receive mailbox */
void* flags; /* -> adapter status flags */
void (*isr)(struct sdla* card); /* interrupt service routine */
void (*poll)(struct sdla* card); /* polling routine */
int (*exec)(struct sdla* card, void* u_cmd, void* u_data);
/* Used by the listen() system call */
/* Wanpipe Socket Interface */
int (*func) (struct sk_buff *, struct sock *);
struct sock *sk;
/* Shutdown function */
void (*disable_comm) (struct sdla *card);
/* Secondary Port Device: Piggibacking */
struct sdla *next;
/* TTY driver variables */
unsigned char tty_opt;
struct tty_struct *tty;
unsigned int tty_minor;
unsigned int tty_open;
unsigned char *tty_buf;
unsigned char *tty_rx;
struct work_struct tty_work;
union
{
struct
{ /****** X.25 specific data **********/
u32 lo_pvc;
u32 hi_pvc;
u32 lo_svc;
u32 hi_svc;
struct net_device *svc_to_dev_map[MAX_X25_LCN];
struct net_device *pvc_to_dev_map[MAX_X25_LCN];
struct net_device *tx_dev;
struct net_device *cmd_dev;
u32 no_dev;
volatile u8 *hdlc_buf_status;
u32 tx_interrupts_pending;
u16 timer_int_enabled;
struct net_device *poll_device;
atomic_t command_busy;
u16 udp_pkt_lgth;
u32 udp_type;
u8 udp_pkt_src;
u32 udp_lcn;
struct net_device *udp_dev;
s8 udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT];
u8 LAPB_hdlc; /* Option to turn off X25 and run only LAPB */
u8 logging; /* Option to log call messages */
u8 oob_on_modem; /* Option to send modem status to the api */
u16 num_of_ch; /* Number of channels configured by the user */
struct work_struct x25_poll_work;
struct timer_list x25_timer;
} x;
struct
{ /****** frame relay specific data ***/
void* rxmb_base; /* -> first Rx buffer */
void* rxmb_last; /* -> last Rx buffer */
unsigned rx_base; /* S508 receive buffer base */
unsigned rx_top; /* S508 receive buffer end */
unsigned short node_dlci[100];
unsigned short dlci_num;
struct net_device *dlci_to_dev_map[991 + 1];
unsigned tx_interrupts_pending;
unsigned short timer_int_enabled;
unsigned short udp_pkt_lgth;
int udp_type;
char udp_pkt_src;
unsigned udp_dlci;
char udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT];
void* trc_el_base; /* first trace element */
void* trc_el_last; /* last trace element */
void *curr_trc_el; /* current trace element */
unsigned short trc_bfr_space; /* trace buffer space */
unsigned char update_comms_stats;
struct net_device *arp_dev;
spinlock_t if_send_lock;
} f;
struct /****** PPP-specific data ***********/
{
char if_name[WAN_IFNAME_SZ+1]; /* interface name */
void* txbuf; /* -> current Tx buffer */
void* txbuf_base; /* -> first Tx buffer */
void* txbuf_last; /* -> last Tx buffer */
void* rxbuf_base; /* -> first Rx buffer */
void* rxbuf_last; /* -> last Rx buffer */
unsigned rx_base; /* S508 receive buffer base */
unsigned rx_top; /* S508 receive buffer end */
char ip_mode; /* STATIC/HOST/PEER IP Mode */
char authenticator; /* Authenticator for PAP/CHAP */
unsigned char comm_enabled; /* Is comm enabled or not */
unsigned char peer_route; /* Process Peer Route */
unsigned long *txbuf_next; /* Next Tx buffer to use */
unsigned long *rxbuf_next; /* Next Rx buffer to use */
} p;
struct /* Cisco HDLC-specific data */
{
char if_name[WAN_IFNAME_SZ+1]; /* interface name */
unsigned char comm_port;/* Communication Port O or 1 */
unsigned char usedby; /* Used by WANPIPE or API */
void* rxmb; /* Receive mail box */
void* flags; /* flags */
void* tx_status; /* Tx status element */
void* rx_status; /* Rx status element */
void* txbuf; /* -> current Tx buffer */
void* txbuf_base; /* -> first Tx buffer */
void* txbuf_last; /* -> last Tx buffer */
void* rxbuf_base; /* -> first Rx buffer */
void* rxbuf_last; /* -> last Rx buffer */
unsigned rx_base; /* S508 receive buffer base */
unsigned rx_top; /* S508 receive buffer end */
unsigned char receive_only; /* high speed receivers */
unsigned short protocol_options;
unsigned short kpalv_tx; /* Tx kpalv timer */
unsigned short kpalv_rx; /* Rx kpalv timer */
unsigned short kpalv_err; /* Error tolerance */
unsigned short slarp_timer; /* SLARP req timer */
unsigned state; /* state of the link */
unsigned char api_status;
unsigned char update_call_count;
unsigned short api_options; /* for async config */
unsigned char async_mode;
unsigned short tx_bits_per_char;
unsigned short rx_bits_per_char;
unsigned short stop_bits;
unsigned short parity;
unsigned short break_timer;
unsigned short inter_char_timer;
unsigned short rx_complete_length;
unsigned short xon_char;
unsigned short xoff_char;
unsigned char comm_enabled; /* Is comm enabled or not */
unsigned char backup;
} c;
struct
{
void* tx_status; /* Tx status element */
void* rx_status; /* Rx status element */
void* trace_status; /* Trace status element */
void* txbuf; /* -> current Tx buffer */
void* txbuf_base; /* -> first Tx buffer */
void* txbuf_last; /* -> last Tx buffer */
void* rxbuf_base; /* -> first Rx buffer */
void* rxbuf_last; /* -> last Rx buffer */
void* tracebuf; /* -> current Trace buffer */
void* tracebuf_base; /* -> current Trace buffer */
void* tracebuf_last; /* -> current Trace buffer */
unsigned rx_base; /* receive buffer base */
unsigned rx_end; /* receive buffer end */
unsigned trace_base; /* trace buffer base */
unsigned trace_end; /* trace buffer end */
} h;
} u;
} sdla_t;
/****** Public Functions ****************************************************/
void wanpipe_open (sdla_t* card); /* wpmain.c */
void wanpipe_close (sdla_t* card); /* wpmain.c */
void wanpipe_set_state (sdla_t* card, int state); /* wpmain.c */
int wpx_init (sdla_t* card, wandev_conf_t* conf); /* wpx.c */
int wpf_init (sdla_t* card, wandev_conf_t* conf); /* wpf.c */
int wpp_init (sdla_t* card, wandev_conf_t* conf); /* wpp.c */
int wpc_init (sdla_t* card, wandev_conf_t* conf); /* Cisco HDLC */
int bsc_init (sdla_t* card, wandev_conf_t* conf); /* BSC streaming */
int hdlc_init(sdla_t* card, wandev_conf_t* conf); /* HDLC support */
int wpft1_init (sdla_t* card, wandev_conf_t* conf); /* FT1 Config support */
int wsppp_init (sdla_t* card, wandev_conf_t* conf); /* Sync PPP on top of RAW CHDLC */
extern sdla_t * wanpipe_find_card(char *);
extern sdla_t * wanpipe_find_card_num (int);
extern void wanpipe_queue_work (struct work_struct *);
extern void wanpipe_mark_bh (void);
extern void wakeup_sk_bh(struct net_device *dev);
extern int change_dev_flags(struct net_device *dev, unsigned flags);
extern unsigned long get_ip_address(struct net_device *dev, int option);
extern void add_gateway(sdla_t *card, struct net_device *dev);
#endif /* __KERNEL__ */
#endif /* _WANPIPE_H */
......@@ -55,12 +55,10 @@
#include <asm/uaccess.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/wanpipe.h>
#include <linux/if_wanpipe.h>
#include <linux/pkt_sched.h>
#include <linux/tcp_states.h>
#include <linux/if_wanpipe_common.h>
#include <linux/sdla_x25.h>
#ifdef CONFIG_INET
#include <net/inet_common.h>
......
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