Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
d52531b8
Commit
d52531b8
authored
Jan 19, 2004
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
This removes the old Eicon ISDN driver.
The config entries etc were already removed earlier.
parent
f69c2d56
Changes
38
Show whitespace changes
Inline
Side-by-side
Showing
38 changed files
with
0 additions
and
14577 deletions
+0
-14577
drivers/isdn/eicon/Divas_mod.c
drivers/isdn/eicon/Divas_mod.c
+0
-134
drivers/isdn/eicon/Kconfig
drivers/isdn/eicon/Kconfig
+0
-53
drivers/isdn/eicon/Makefile
drivers/isdn/eicon/Makefile
+0
-19
drivers/isdn/eicon/adapter.h
drivers/isdn/eicon/adapter.h
+0
-247
drivers/isdn/eicon/bri.c
drivers/isdn/eicon/bri.c
+0
-697
drivers/isdn/eicon/common.c
drivers/isdn/eicon/common.c
+0
-867
drivers/isdn/eicon/constant.h
drivers/isdn/eicon/constant.h
+0
-161
drivers/isdn/eicon/divalog.h
drivers/isdn/eicon/divalog.h
+0
-38
drivers/isdn/eicon/divas.h
drivers/isdn/eicon/divas.h
+0
-214
drivers/isdn/eicon/dsp_defs.h
drivers/isdn/eicon/dsp_defs.h
+0
-286
drivers/isdn/eicon/dspdids.h
drivers/isdn/eicon/dspdids.h
+0
-67
drivers/isdn/eicon/eicon.h
drivers/isdn/eicon/eicon.h
+0
-386
drivers/isdn/eicon/eicon_dsp.h
drivers/isdn/eicon/eicon_dsp.h
+0
-285
drivers/isdn/eicon/eicon_idi.c
drivers/isdn/eicon/eicon_idi.c
+0
-3197
drivers/isdn/eicon/eicon_idi.h
drivers/isdn/eicon/eicon_idi.h
+0
-119
drivers/isdn/eicon/eicon_io.c
drivers/isdn/eicon/eicon_io.c
+0
-749
drivers/isdn/eicon/eicon_isa.c
drivers/isdn/eicon/eicon_isa.c
+0
-454
drivers/isdn/eicon/eicon_isa.h
drivers/isdn/eicon/eicon_isa.h
+0
-121
drivers/isdn/eicon/eicon_mod.c
drivers/isdn/eicon/eicon_mod.c
+0
-1642
drivers/isdn/eicon/eicon_pci.c
drivers/isdn/eicon/eicon_pci.c
+0
-109
drivers/isdn/eicon/eicon_pci.h
drivers/isdn/eicon/eicon_pci.h
+0
-34
drivers/isdn/eicon/fourbri.c
drivers/isdn/eicon/fourbri.c
+0
-560
drivers/isdn/eicon/fpga.c
drivers/isdn/eicon/fpga.c
+0
-141
drivers/isdn/eicon/idi.c
drivers/isdn/eicon/idi.c
+0
-854
drivers/isdn/eicon/idi.h
drivers/isdn/eicon/idi.h
+0
-129
drivers/isdn/eicon/kprintf.c
drivers/isdn/eicon/kprintf.c
+0
-52
drivers/isdn/eicon/lincfg.c
drivers/isdn/eicon/lincfg.c
+0
-257
drivers/isdn/eicon/linchr.c
drivers/isdn/eicon/linchr.c
+0
-198
drivers/isdn/eicon/linio.c
drivers/isdn/eicon/linio.c
+0
-729
drivers/isdn/eicon/linsys.c
drivers/isdn/eicon/linsys.c
+0
-136
drivers/isdn/eicon/log.c
drivers/isdn/eicon/log.c
+0
-160
drivers/isdn/eicon/pc.h
drivers/isdn/eicon/pc.h
+0
-292
drivers/isdn/eicon/pc_maint.h
drivers/isdn/eicon/pc_maint.h
+0
-148
drivers/isdn/eicon/pr_pc.h
drivers/isdn/eicon/pr_pc.h
+0
-70
drivers/isdn/eicon/pri.c
drivers/isdn/eicon/pri.c
+0
-517
drivers/isdn/eicon/sys.h
drivers/isdn/eicon/sys.h
+0
-95
drivers/isdn/eicon/uxio.h
drivers/isdn/eicon/uxio.h
+0
-196
drivers/isdn/eicon/xlog.c
drivers/isdn/eicon/xlog.c
+0
-164
No files found.
drivers/isdn/eicon/Divas_mod.c
deleted
100644 → 0
View file @
f69c2d56
/*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/fs.h>
#undef N_DATA
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include "adapter.h"
#include "uxio.h"
MODULE_DESCRIPTION
(
"ISDN4Linux: Driver for Eicon Diva Server cards"
);
MODULE_AUTHOR
(
"Armin Schindler"
);
MODULE_LICENSE
(
"GPL"
);
void
DivasInitDpc
(
void
);
#ifdef MODULE
#include "idi.h"
void
DIVA_DIDD_Write
(
DESCRIPTOR
*
,
int
);
EXPORT_SYMBOL_NOVERS
(
DIVA_DIDD_Read
);
EXPORT_SYMBOL_NOVERS
(
DIVA_DIDD_Write
);
EXPORT_SYMBOL_NOVERS
(
DivasPrintf
);
#endif
int
DivasCardsDiscover
(
void
);
static
int
__init
divas_init
(
void
)
{
printk
(
KERN_DEBUG
"DIVA Server Driver - initialising
\n
"
);
printk
(
KERN_DEBUG
"DIVA Server Driver - Version 2.0.16
\n
"
);
#if !defined(CONFIG_PCI)
printk
(
KERN_WARNING
"CONFIG_PCI is not defined!
\n
"
);
return
-
ENODEV
;
#endif
DivasInitDpc
();
if
(
DivasCardsDiscover
()
<
0
)
{
printk
(
KERN_WARNING
"Divas: Not loaded
\n
"
);
return
-
ENODEV
;
}
return
0
;
}
static
void
__exit
divas_exit
(
void
)
{
card_t
*
pCard
;
word
wCardIndex
;
extern
int
Divas_major
;
printk
(
KERN_DEBUG
"DIVA Server Driver - unloading
\n
"
);
pCard
=
DivasCards
;
for
(
wCardIndex
=
0
;
wCardIndex
<
MAX_CARDS
;
wCardIndex
++
)
{
if
((
pCard
->
hw
)
&&
(
pCard
->
hw
->
in_use
))
{
(
*
pCard
->
card_reset
)(
pCard
);
UxIsrRemove
(
pCard
->
hw
,
pCard
);
UxCardHandleFree
(
pCard
->
hw
);
if
(
pCard
->
e_tbl
!=
NULL
)
{
kfree
(
pCard
->
e_tbl
);
}
if
(
pCard
->
hw
->
card_type
==
DIA_CARD_TYPE_DIVA_SERVER_B
)
{
release_region
(
pCard
->
hw
->
io_base
,
0x20
);
release_region
(
pCard
->
hw
->
reset_base
,
0x80
);
}
// If this is a 4BRI ...
if
(
pCard
->
hw
->
card_type
==
DIA_CARD_TYPE_DIVA_SERVER_Q
)
{
// Skip over the next 3 virtual adapters
wCardIndex
+=
3
;
// But free their handles
pCard
++
;
UxCardHandleFree
(
pCard
->
hw
);
if
(
pCard
->
e_tbl
!=
NULL
)
{
kfree
(
pCard
->
e_tbl
);
}
pCard
++
;
UxCardHandleFree
(
pCard
->
hw
);
if
(
pCard
->
e_tbl
!=
NULL
)
{
kfree
(
pCard
->
e_tbl
);
}
pCard
++
;
UxCardHandleFree
(
pCard
->
hw
);
if
(
pCard
->
e_tbl
!=
NULL
)
{
kfree
(
pCard
->
e_tbl
);
}
}
}
pCard
++
;
}
unregister_chrdev
(
Divas_major
,
"Divas"
);
}
module_init
(
divas_init
);
module_exit
(
divas_exit
);
drivers/isdn/eicon/Kconfig
deleted
100644 → 0
View file @
f69c2d56
#
# Config.in for Eicon active ISDN support
#
config ISDN_DRV_EICON
bool "Eicon active card support"
help
Say Y here if you have an Eicon active ISDN card. In order to use
this card, additional firmware is necessary, which has to be loaded
into the card using the eiconctrl utility which is part of the
latest isdn4k-utils package. Please read the file
<file:Documentation/isdn/README.eicon> for more information.
choice
prompt "Eicon active card support"
optional
depends on ISDN_DRV_EICON && ISDN && m
config ISDN_DRV_EICON_DIVAS
tristate "Eicon driver"
depends on PCI
help
Enable this option if you want the eicon driver as standalone
version with no interface to the ISDN4Linux isdn module. If you
say Y here, the eicon module only supports the Diva Server PCI
cards and will provide its own IDI interface. You should say N
here.
config ISDN_DRV_EICON_OLD
tristate "Legacy driver"
help
Say Y here to use your Eicon active ISDN card with ISDN4Linux
isdn module.
config ISDN_DRV_EICON_PCI
bool "Eicon PCI DIVA Server BRI/PRI/4BRI support"
depends on ISDN_DRV_EICON_OLD && PCI
help
Say Y here if you have an Eicon Diva Server (BRI/PRI/4BRI) ISDN
card. Please read <file:Documentation/isdn/README.eicon> for more
information.
config ISDN_DRV_EICON_ISA
bool "Eicon S,SX,SCOM,Quadro,S2M support"
depends on ISDN_DRV_EICON_OLD
help
Say Y here if you have an old-type Eicon active ISDN card. In order
to use this card, additional firmware is necessary, which has to be
loaded into the card using the eiconctrl utility which is part of
the latest isdn4k-utils package. Please read the file
<file:Documentation/isdn/README.eicon> for more information.
endchoice
drivers/isdn/eicon/Makefile
deleted
100644 → 0
View file @
f69c2d56
# Makefile for the eicon ISDN device driver
# Each configuration option enables a list of files.
obj-$(CONFIG_ISDN_DRV_EICON_OLD)
+=
eicon.o
obj-$(CONFIG_ISDN_DRV_EICON_DIVAS)
+=
divas.o
# Multipart objects.
eicon-y
:=
eicon_mod.o eicon_isa.o eicon_pci.o
\
eicon_idi.o eicon_io.o
eicon-$(CONFIG_ISDN_DRV_EICON_PCI)
+=
common.o idi.o bri.o pri.o log.o
\
xlog.o kprintf.o fpga.o fourbri.o lincfg.o
\
linchr.o linsys.o linio.o
divas-y
:=
common.o idi.o bri.o pri.o log.o xlog.o
\
kprintf.o fpga.o fourbri.o lincfg.o
\
linchr.o linsys.o linio.o Divas_mod.o
drivers/isdn/eicon/adapter.h
deleted
100644 → 0
View file @
f69c2d56
/*
* Main internal include file for Diva Server driver
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.7
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#if !defined(ADAPTER_H)
#define ADAPTER_H
#include "sys.h"
#include "idi.h"
#include "divas.h"
#undef ID_MASK
#include "pc.h"
#define XMOREC 0x1f
#define XMOREF 0x20
#define XBUSY 0x40
#define RMORE 0x80
/* structure for all information we have to keep on a per */
/* adapater basis */
typedef
struct
adapter_s
ADAPTER
;
struct
adapter_s
{
void
*
io
;
byte
IdTable
[
256
];
byte
ReadyInt
;
byte
(
*
ram_in
)(
ADAPTER
*
a
,
void
*
adr
);
word
(
*
ram_inw
)(
ADAPTER
*
a
,
void
*
adr
);
void
(
*
ram_in_buffer
)(
ADAPTER
*
a
,
void
*
adr
,
void
*
P
,
word
length
);
void
(
*
ram_look_ahead
)(
ADAPTER
*
a
,
PBUFFER
*
RBuffer
,
ENTITY
*
e
);
void
(
*
ram_out
)(
ADAPTER
*
a
,
void
*
adr
,
byte
data
);
void
(
*
ram_outw
)(
ADAPTER
*
a
,
void
*
adr
,
word
data
);
void
(
*
ram_out_buffer
)(
ADAPTER
*
a
,
void
*
adr
,
void
*
P
,
word
length
);
void
(
*
ram_inc
)(
ADAPTER
*
a
,
void
*
adr
);
};
typedef
struct
card
card_t
;
typedef
int
card_load_fn_t
(
card_t
*
card
,
dia_load_t
*
load
);
typedef
int
card_config_fn_t
(
card_t
*
card
,
dia_config_t
*
config
);
typedef
int
card_start_fn_t
(
card_t
*
card
,
byte
*
channels
);
typedef
int
card_reset_fn_t
(
card_t
*
card
);
typedef
int
card_mem_get_fn_t
(
card_t
*
card
,
mem_block_t
*
mem_block
);
#define MAX_PENTITIES 256
/* Number of entities primary adapter */
#define MAX_ENTITIES 16
/* Number of entities standard adapter */
typedef
struct
e_info_s
E_INFO
;
struct
e_info_s
{
ENTITY
*
e
;
/* entity pointer */
byte
next
;
/* chaining index */
word
assign_ref
;
/* assign reference */
};
/* DIVA card info (details hidden from user) */
typedef
struct
ux_diva_card_s
ux_diva_card_t
;
/* card info */
struct
card
{
ADAPTER
a
;
/* per-adapter information */
dia_card_t
cfg
;
/* card configuration */
int
state
;
/* State of the adapter */
dword
serial_no
;
/* serial number */
int
test_int_pend
;
/* set for interrupt testing */
ux_diva_card_t
*
hw
;
/* O/S-specific handle */
card_reset_fn_t
*
card_reset
;
/* call this to reset card */
card_load_fn_t
*
card_load
;
/* call this to load card */
card_config_fn_t
*
card_config
;
/* call this to config card */
card_start_fn_t
*
card_start
;
/* call this to start card */
card_mem_get_fn_t
*
card_mem_get
;
/* call this to get card memory */
E_INFO
*
e_tbl
;
/* table of ENTITY pointers */
byte
e_head
;
/* list of active ENTITIES */
byte
e_tail
;
/* list of active ENTITIES */
int
e_count
;
/* # of active ENTITIES */
int
e_max
;
/* total # of ENTITIES */
byte
assign
;
/* assign queue entry */
PBUFFER
RBuffer
;
/* Copy of receive lookahead buffer */
int
log_types
;
/* bit-mask of active logs */
word
xlog_offset
;
/* offset to XLOG buffer on card */
void
(
*
out
)(
ADAPTER
*
a
);
byte
(
*
dpc
)(
ADAPTER
*
a
);
byte
(
*
test_int
)(
ADAPTER
*
a
);
void
(
*
clear_int
)(
ADAPTER
*
a
);
void
(
*
reset_int
)(
card_t
*
c
);
int
is_live
;
int
(
*
card_isr
)(
card_t
*
card
);
int
int_pend
;
/* interrupt pending */
long
interrupt_reentered
;
long
dpc_reentered
;
int
set_xlog_request
;
}
;
/* card information */
#define MAX_CARDS 20
/* max number of cards on a system */
extern
card_t
DivasCards
[];
extern
int
DivasCardNext
;
extern
dia_config_t
DivasCardConfigs
[];
extern
byte
DivasFlavourConfig
[];
/*------------------------------------------------------------------*/
/* public functions of IDI common code */
/*------------------------------------------------------------------*/
void
DivasOut
(
ADAPTER
*
a
);
byte
DivasDpc
(
ADAPTER
*
a
);
byte
DivasTestInt
(
ADAPTER
*
a
);
void
DivasClearInt
(
ADAPTER
*
a
);
/*------------------------------------------------------------------*/
/* public functions of configuration platform-specific code */
/*------------------------------------------------------------------*/
int
DivasConfigGet
(
dia_card_t
*
card
);
/*------------------------------------------------------------------*/
/* public functions of LOG related code */
/*------------------------------------------------------------------*/
void
DivasXlogReq
(
int
card_num
);
int
DivasXlogRetrieve
(
card_t
*
card
);
void
DivasLog
(
dia_log_t
*
log
);
void
DivasLogIdi
(
card_t
*
card
,
ENTITY
*
e
,
int
request
);
/*------------------------------------------------------------------*/
/* public functions to initialise cards for each type supported */
/*------------------------------------------------------------------*/
int
DivasPriInit
(
card_t
*
card
,
dia_card_t
*
cfg
);
int
DivasBriInit
(
card_t
*
card
,
dia_card_t
*
cfg
);
int
Divas4BriInit
(
card_t
*
card
,
dia_card_t
*
cfg
);
void
DivasBriPatch
(
card_t
*
card
);
/*------------------------------------------------------------------*/
/* public functions of log common code */
/*------------------------------------------------------------------*/
extern
char
*
DivasLogFifoRead
(
void
);
extern
void
DivasLogFifoWrite
(
char
*
entry
,
int
length
);
extern
int
DivasLogFifoEmpty
(
void
);
extern
int
DivasLogFifoFull
(
void
);
extern
void
DivasLogAdd
(
void
*
buffer
,
int
length
);
/*------------------------------------------------------------------*/
/* public functions of misc. platform-specific code */
/*------------------------------------------------------------------*/
int
DivasDpcSchedule
(
void
);
void
DivasDoDpc
(
unsigned
long
);
int
DivasScheduleRequestDpc
(
void
);
/* table of IDI request functions */
extern
IDI_CALL
DivasIdiRequest
[];
/*
* initialisation entry point
*/
int
DivasInit
(
void
);
/*
* Get information on the number and type of cards present
*/
extern
int
DivasCardsDiscover
(
void
);
/*
* initialise a new card
*/
int
DivasCardNew
(
dia_card_t
*
card
);
/*
* configure specified card
*/
int
DivasCardConfig
(
dia_config_t
*
config
);
/*
* load specified binary code onto card
*/
int
DivasCardLoad
(
dia_load_t
*
load
);
/*
* start specified card running
*/
int
DivasCardStart
(
int
card_id
);
/*
* ISR for card
* Returns 0 if specified card was interrupting
*/
int
DivasIsr
(
void
*
arg
);
/*
* Get number of active cards
*/
int
DivasGetNum
(
void
);
/*
* Get list of active cards
*/
int
DivasGetList
(
dia_card_list_t
*
card_list
);
/* definitions common to several card types */
#define DIVAS_SHARED_OFFSET (0x1000)
#endif
/* ADAPTER_H */
drivers/isdn/eicon/bri.c
deleted
100644 → 0
View file @
f69c2d56
/*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.8
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include "eicon.h"
#include "sys.h"
#include "idi.h"
#include "divas.h"
#include "pc.h"
#include "pr_pc.h"
#include "dsp_defs.h"
#include "adapter.h"
#include "uxio.h"
#define PCI_BADDR0 0x10
#define PCI_BADDR1 0x14
#define PCI_BADDR2 0x18
#define DIVAS_SIGNATURE 0x4447
/* offset to start of MAINT area (used by xlog) */
#define DIVAS_MAINT_OFFSET 0xff00
/* value for BRI card */
#define PROTCAP_TELINDUS 0x1
#define PROTCAP_V90D 0x8
word
GetProtFeatureValue
(
char
*
sw_id
);
byte
io_in
(
ADAPTER
*
a
,
void
*
adr
);
word
io_inw
(
ADAPTER
*
a
,
void
*
adr
);
void
io_in_buffer
(
ADAPTER
*
a
,
void
*
adr
,
void
*
P
,
word
length
);
void
io_look_ahead
(
ADAPTER
*
a
,
PBUFFER
*
RBuffer
,
ENTITY
*
e
);
void
io_out
(
ADAPTER
*
a
,
void
*
adr
,
byte
data
);
void
io_outw
(
ADAPTER
*
a
,
void
*
adr
,
word
data
);
void
io_out_buffer
(
ADAPTER
*
a
,
void
*
adr
,
void
*
P
,
word
length
);
void
io_inc
(
ADAPTER
*
a
,
void
*
adr
);
static
int
diva_server_bri_test_int
(
card_t
*
card
);
static
int
bri_ISR
(
card_t
*
card
);
#define PLX_IOBASE 0
#define DIVAS_IOBASE 1
#define REG_DATA 0x00
#define REG_ADDRLO 0x04
#define REG_ADDRHI 0x0C
#define REG_IOCTRL 0x10
#define M_PCI_RESET 0x10
byte
UxCardPortIoIn
(
ux_diva_card_t
*
card
,
byte
*
base
,
int
offset
);
word
UxCardPortIoInW
(
ux_diva_card_t
*
card
,
byte
*
base
,
int
offset
);
void
UxCardPortIoOut
(
ux_diva_card_t
*
card
,
byte
*
base
,
int
offset
,
byte
);
void
UxCardPortIoOutW
(
ux_diva_card_t
*
card
,
byte
*
base
,
int
offset
,
word
);
int
DivasBRIInitPCI
(
card_t
*
card
,
dia_card_t
*
cfg
);
static
int
diva_server_bri_reset
(
card_t
*
card
)
{
byte
*
DivasIOBase
;
word
i
;
dword
dwWait
;
UxCardLog
(
0
);
DPRINTF
((
"divas: resetting BRI adapter"
));
DivasIOBase
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_IOBASE
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_IOCTRL
,
0
);
for
(
i
=
0
;
i
<
50000
;
i
++
)
;
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_ADDRHI
,
0
);
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_ADDRLO
,
0
);
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_DATA
,
0
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_ADDRHI
,
0xFF
);
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_ADDRLO
,
0x0000
);
for
(
i
=
0
;
i
<
0x8000
;
i
++
)
{
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_DATA
,
0
);
}
for
(
dwWait
=
0
;
dwWait
<
0x00FFFFFF
;
dwWait
++
)
;
UxCardMemDetach
(
card
->
hw
,
DivasIOBase
);
return
0
;
}
static
void
diva_server_bri_reset_int
(
card_t
*
card
)
{
byte
*
DivasIOBase
=
NULL
;
DivasIOBase
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_IOBASE
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_IOCTRL
,
0x08
);
UxCardMemDetach
(
card
->
hw
,
DivasIOBase
);
return
;
}
static
int
diva_server_bri_start
(
card_t
*
card
,
byte
*
channels
)
{
byte
*
DivasIOBase
,
*
PLXIOBase
;
word
wSig
=
0
;
word
i
;
dword
dwSerialNum
;
byte
bPLX9060
=
FALSE
;
DPRINTF
((
"divas: starting Diva Server BRI card"
));
card
->
is_live
=
FALSE
;
DivasIOBase
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_IOBASE
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_ADDRHI
,
0xFF
);
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_ADDRLO
,
0x1E
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_DATA
,
0
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_DATA
,
0
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_IOCTRL
,
0x08
);
/* wait for signature to indicate card has started */
for
(
i
=
0
;
i
<
300
;
i
++
)
{
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_ADDRHI
,
0xFF
);
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_ADDRLO
,
0x1E
);
wSig
=
UxCardPortIoInW
(
card
->
hw
,
DivasIOBase
,
REG_DATA
);
if
(
wSig
==
DIVAS_SIGNATURE
)
{
DPRINTF
((
"divas: card started after %d ms"
,
i
*
10
));
break
;
}
UxPause
(
10
);
}
if
(
wSig
!=
DIVAS_SIGNATURE
)
{
DPRINTF
((
"divas: card failed to start (Sig=0x%x)"
,
wSig
));
UxCardMemDetach
(
card
->
hw
,
DivasIOBase
);
return
-
1
;
}
card
->
is_live
=
TRUE
;
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_ADDRHI
,
0xFF
);
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_ADDRLO
,
0x3F6
);
*
channels
=
UxCardPortIoInW
(
card
->
hw
,
DivasIOBase
,
REG_DATA
);
UxCardMemDetach
(
card
->
hw
,
DivasIOBase
);
PLXIOBase
=
UxCardMemAttach
(
card
->
hw
,
PLX_IOBASE
);
bPLX9060
=
UxCardPortIoInW
(
card
->
hw
,
PLXIOBase
,
0x6C
)
|
UxCardPortIoInW
(
card
->
hw
,
PLXIOBase
,
0x6E
);
if
(
bPLX9060
)
{
dwSerialNum
=
(
UxCardPortIoInW
(
card
->
hw
,
PLXIOBase
,
0x1E
)
<<
16
)
|
(
UxCardPortIoInW
(
card
->
hw
,
PLXIOBase
,
0x22
));
DPRINTF
((
"divas: PLX9060 in use. Serial number 0x%04X"
,
dwSerialNum
));
}
else
{
dwSerialNum
=
(
UxCardPortIoInW
(
card
->
hw
,
PLXIOBase
,
0x22
)
<<
16
)
|
(
UxCardPortIoInW
(
card
->
hw
,
PLXIOBase
,
0x26
));
DPRINTF
((
"divas: PLX9050 in use. Serial number 0x%04X"
,
dwSerialNum
));
}
UxCardMemDetach
(
card
->
hw
,
PLXIOBase
);
card
->
serial_no
=
dwSerialNum
;
diva_server_bri_test_int
(
card
);
return
0
;
}
static
int
diva_server_bri_load
(
card_t
*
card
,
dia_load_t
*
load
)
{
byte
*
DivasIOBase
;
dword
r3000_base
;
dword
dwAddr
,
dwLength
,
i
;
word
wTest
,
aWord
;
DPRINTF
((
"divas: loading Diva Server BRI card"
));
switch
(
load
->
code_type
)
{
case
DIA_CPU_CODE
:
DPRINTF
((
"divas: loading RISC %s"
,
&
load
->
code
[
0x80
]));
card
->
hw
->
features
=
GetProtFeatureValue
((
char
*
)
&
load
->
code
[
0x80
]);
DPRINTF
((
"divas: features 0x%x"
,
card
->
hw
->
features
));
if
(
card
->
hw
->
features
==
0xFFFF
)
{
DPRINTF
((
"divas: invalid feature string failed load
\n
"
));
return
-
1
;
}
r3000_base
=
0
;
break
;
case
DIA_DSP_CODE
:
DPRINTF
((
"divas: DSP code
\"
%s
\"
"
,
load
->
code
));
if
((
card
->
hw
->
features
)
&&
(
!
(
card
->
hw
->
features
&
PROTCAP_TELINDUS
)))
{
DPRINTF
((
"divas: only Telindus style binaries supported"
));
return
-
1
;
}
if
((
card
->
hw
->
features
)
&&
(
card
->
hw
->
features
&
PROTCAP_V90D
))
{
DPRINTF
((
"divas: V.90 DSP binary"
));
r3000_base
=
(
0xBF790000
+
(((
sizeof
(
dword
)
+
(
sizeof
(
t_dsp_download_desc
)
*
DSP_MAX_DOWNLOAD_COUNT
))
+
3
)
&
0xFFFFFFFC
));
}
else
{
DPRINTF
((
"divas: non-V.90 DSP binary"
));
r3000_base
=
(
0xBF7A0000
+
(((
sizeof
(
dword
)
+
(
sizeof
(
t_dsp_download_desc
)
*
DSP_MAX_DOWNLOAD_COUNT
))
+
3
)
&
0xFFFFFFFC
));
}
DPRINTF
((
"divas: loading at 0x%x"
,
r3000_base
));
break
;
case
DIA_TABLE_CODE
:
DPRINTF
((
"divas: TABLE code"
));
if
((
card
->
hw
->
features
)
&&
(
card
->
hw
->
features
&
PROTCAP_V90D
))
{
r3000_base
=
0xBF790000
+
sizeof
(
dword
);
}
else
{
r3000_base
=
0xBF7A0000
+
sizeof
(
dword
);
}
break
;
case
DIA_DLOAD_CNT
:
DPRINTF
((
"divas: COUNT code"
));
if
((
card
->
hw
->
features
)
&&
(
card
->
hw
->
features
&
PROTCAP_V90D
))
{
r3000_base
=
0xBF790000
;
}
else
{
r3000_base
=
0xBF7A0000
;
}
break
;
default:
DPRINTF
((
"divas: unknown code type %d"
,
load
->
code_type
));
return
-
1
;
break
;
}
DPRINTF
((
"divas: Writing %d bytes to adapter, address 0x%x"
,
load
->
length
,
r3000_base
));
DivasIOBase
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_IOBASE
);
DPRINTF
((
"divas: Attached to 0x%04X"
,
DivasIOBase
));
dwLength
=
load
->
length
;
for
(
i
=
0
;
i
<
dwLength
;
i
++
)
{
dwAddr
=
r3000_base
+
i
;
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_ADDRHI
,
dwAddr
>>
16
);
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_ADDRLO
,
dwAddr
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_DATA
,
load
->
code
[
i
]);
}
DPRINTF
((
"divas: Verifying"
));
for
(
i
=
0
;
i
<
dwLength
;
i
++
)
{
dwAddr
=
r3000_base
+
i
;
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_ADDRHI
,
dwAddr
>>
16
);
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_ADDRLO
,
dwAddr
);
wTest
=
UxCardPortIoIn
(
card
->
hw
,
DivasIOBase
,
REG_DATA
);
aWord
=
load
->
code
[
i
];
if
(
wTest
!=
aWord
)
{
DPRINTF
((
"divas: load verify failed on byte %d"
,
i
));
DPRINTF
((
"divas: RAM 0x%x File 0x%x"
,
wTest
,
aWord
));
UxCardMemDetach
(
card
->
hw
,
DivasIOBase
);
return
-
1
;
}
}
DPRINTF
((
"divas: Loaded and verified. Detaching from adapter"
));
UxCardMemDetach
(
card
->
hw
,
DivasIOBase
);
UxCardLog
(
0
);
return
0
;
}
static
int
diva_server_bri_config
(
card_t
*
card
,
dia_config_t
*
config
)
{
byte
*
DivasIOBase
,
i
;
DPRINTF
((
"divas: configuring Diva Server BRI card"
));
DivasIOBase
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_IOBASE
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_ADDRHI
,
0xFF
);
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_ADDRLO
,
8
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_DATA
,
config
->
tei
);
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_ADDRLO
,
9
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_DATA
,
config
->
nt2
);
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_ADDRLO
,
10
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_DATA
,
config
->
sig_flags
);
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_ADDRLO
,
11
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_DATA
,
config
->
watchdog
);
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_ADDRLO
,
12
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_DATA
,
config
->
permanent
);
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_ADDRLO
,
13
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_DATA
,
0
);
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_ADDRLO
,
14
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_DATA
,
config
->
stable_l2
);
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_ADDRLO
,
15
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_DATA
,
config
->
no_order_check
);
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_ADDRLO
,
16
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_DATA
,
0
);
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_ADDRLO
,
17
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_DATA
,
0
);
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_ADDRLO
,
18
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_DATA
,
config
->
low_channel
);
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_ADDRLO
,
19
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_DATA
,
config
->
prot_version
);
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_ADDRLO
,
20
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_DATA
,
config
->
crc4
);
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_ADDRLO
,
21
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_DATA
,
0
);
if
((
card
->
hw
->
features
)
&&
(
card
->
hw
->
features
&
PROTCAP_V90D
))
{
DPRINTF
((
"divas: Signifying V.90"
));
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_ADDRLO
,
22
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_DATA
,
4
);
}
else
{
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_ADDRLO
,
22
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_DATA
,
0
);
}
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_ADDRLO
,
23
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_DATA
,
card
->
serial_no
&
0xFF
);
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_ADDRLO
,
24
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_DATA
,
(
card
->
serial_no
>>
8
)
&
0xFF
);
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_ADDRLO
,
25
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_DATA
,
(
card
->
serial_no
>>
16
)
&
0xFF
);
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_ADDRLO
,
26
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_DATA
,
21
);
for
(
i
=
0
;
i
<
32
;
i
++
)
{
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_ADDRLO
,
32
+
i
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_DATA
,
config
->
terminal
[
0
].
oad
[
i
]);
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_ADDRLO
,
64
+
i
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_DATA
,
config
->
terminal
[
0
].
osa
[
i
]);
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_ADDRLO
,
96
+
i
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_DATA
,
config
->
terminal
[
0
].
spid
[
i
]);
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_ADDRLO
,
128
+
i
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_DATA
,
config
->
terminal
[
1
].
oad
[
i
]);
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_ADDRLO
,
160
+
i
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_DATA
,
config
->
terminal
[
1
].
osa
[
i
]);
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_ADDRLO
,
192
+
i
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_DATA
,
config
->
terminal
[
1
].
spid
[
i
]);
}
UxCardMemDetach
(
card
->
hw
,
DivasIOBase
);
return
0
;
}
void
DivasBriPatch
(
card_t
*
card
)
{
dword
PLXIOBase
=
0
;
dword
DivasIOBase
=
0
;
PLXIOBase
=
card
->
cfg
.
reset_base
;
DivasIOBase
=
card
->
cfg
.
io_base
;
if
(
card
->
hw
==
NULL
)
{
DPRINTF
((
"Divas: BRI PATCH (PLX chip) card->hw is null"
));
return
;
}
if
(
PLXIOBase
==
0
)
{
DPRINTF
((
"Divas: BRI (PLX chip) cannot be patched. The BRI adapter may"
));
DPRINTF
((
"Divas: not function properly. If you do encounter problems,"
));
DPRINTF
((
"Divas: ensure that your machine is using the latest BIOS."
));
return
;
}
DPRINTF
((
"Divas: PLX I/O Base 0x%x"
,
PLXIOBase
));
DPRINTF
((
"Divas: Divas I/O Base 0x%x"
,
DivasIOBase
));
if
(
PLXIOBase
&
0x80
)
{
dword
dwSize
,
dwSerialNum
,
dwCmd
;
boolean_t
bPLX9060
;
word
wSerHi
,
wSerLo
;
DPRINTF
((
"Divas: Patch required"
));
dwCmd
=
0
;
UxPciConfigWrite
(
card
->
hw
,
4
,
PCI_COMMAND
,
&
dwCmd
);
PLXIOBase
&=
~
0x80
;
UxPciConfigWrite
(
card
->
hw
,
4
,
PCI_BADDR1
,
&
PLXIOBase
);
dwSize
=
0xFFFFFFFF
;
UxPciConfigWrite
(
card
->
hw
,
4
,
PCI_BADDR1
,
&
dwSize
);
UxPciConfigRead
(
card
->
hw
,
4
,
PCI_BADDR1
,
&
dwSize
);
dwSize
=
(
~
(
dwSize
&
~
7
))
+
1
;
DivasIOBase
=
PLXIOBase
+
dwSize
;
card
->
cfg
.
reset_base
=
PLXIOBase
;
card
->
cfg
.
io_base
=
DivasIOBase
;
UxPciConfigWrite
(
card
->
hw
,
4
,
PCI_BADDR1
,
&
card
->
cfg
.
reset_base
);
UxPciConfigWrite
(
card
->
hw
,
4
,
PCI_BADDR2
,
&
card
->
cfg
.
io_base
);
dwCmd
=
5
;
UxPciConfigWrite
(
card
->
hw
,
4
,
PCI_COMMAND
,
&
dwCmd
);
bPLX9060
=
UxCardPortIoInW
(
card
->
hw
,
(
void
*
)
card
->
cfg
.
reset_base
,
0x6C
)
|
UxCardPortIoInW
(
card
->
hw
,
(
void
*
)
card
->
cfg
.
reset_base
,
0x6E
);
if
(
bPLX9060
)
{
wSerHi
=
UxCardPortIoInW
(
card
->
hw
,
(
void
*
)
card
->
cfg
.
reset_base
,
0x1E
);
wSerLo
=
UxCardPortIoInW
(
card
->
hw
,
(
void
*
)
card
->
cfg
.
reset_base
,
0x22
);
dwSerialNum
=
(
wSerHi
<<
16
)
|
wSerLo
;
UxCardLog
(
0
);
}
else
{
wSerHi
=
UxCardPortIoInW
(
card
->
hw
,
(
void
*
)
card
->
cfg
.
reset_base
,
0x22
);
wSerLo
=
UxCardPortIoInW
(
card
->
hw
,
(
void
*
)
card
->
cfg
.
reset_base
,
0x26
);
dwSerialNum
=
(
wSerHi
<<
16
)
|
wSerLo
;
UxCardLog
(
0
);
}
}
else
{
word
wSerHi
,
wSerLo
;
boolean_t
bPLX9060
;
dword
dwSerialNum
;
DPRINTF
((
"divas: No patch required"
));
bPLX9060
=
UxCardPortIoInW
(
card
->
hw
,
(
void
*
)
card
->
cfg
.
reset_base
,
0x6C
)
|
UxCardPortIoInW
(
card
->
hw
,
(
void
*
)
card
->
cfg
.
reset_base
,
0x6E
);
if
(
bPLX9060
)
{
wSerHi
=
UxCardPortIoInW
(
card
->
hw
,
(
void
*
)
card
->
cfg
.
reset_base
,
0x1E
);
wSerLo
=
UxCardPortIoInW
(
card
->
hw
,
(
void
*
)
card
->
cfg
.
reset_base
,
0x22
);
dwSerialNum
=
(
wSerHi
<<
16
)
|
wSerLo
;
}
else
{
wSerHi
=
UxCardPortIoInW
(
card
->
hw
,
(
void
*
)
card
->
cfg
.
reset_base
,
0x22
);
wSerLo
=
UxCardPortIoInW
(
card
->
hw
,
(
void
*
)
card
->
cfg
.
reset_base
,
0x26
);
dwSerialNum
=
(
wSerHi
<<
16
)
|
wSerLo
;
}
}
DPRINTF
((
"Divas: After patching:"
));
DPRINTF
((
"Divas: PLX I/O Base 0x%x"
,
PLXIOBase
));
DPRINTF
((
"Divas: Divas I/O Base 0x%x"
,
DivasIOBase
));
}
#define TEST_INT_DIVAS_BRI 0x12
static
int
diva_server_bri_test_int
(
card_t
*
card
)
{
boolean_t
bPLX9060
=
FALSE
;
byte
*
PLXIOBase
=
NULL
,
*
DivasIOBase
=
NULL
;
DPRINTF
((
"divas: test interrupt for Diva Server BRI card"
));
PLXIOBase
=
UxCardMemAttach
(
card
->
hw
,
PLX_IOBASE
);
bPLX9060
=
UxCardPortIoInW
(
card
->
hw
,
PLXIOBase
,
0x6C
)
||
UxCardPortIoInW
(
card
->
hw
,
PLXIOBase
,
0x6E
);
if
(
bPLX9060
)
{
/* PLX9060 */
UxCardPortIoOut
(
card
->
hw
,
PLXIOBase
,
0x69
,
0x09
);
}
else
{
/* PLX9050 */
UxCardPortIoOut
(
card
->
hw
,
PLXIOBase
,
0x4C
,
0x41
);
}
card
->
test_int_pend
=
TEST_INT_DIVAS_BRI
;
UxCardMemDetach
(
card
->
hw
,
PLXIOBase
);
DivasIOBase
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_IOBASE
);
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_IOCTRL
,
0x89
);
UxCardMemDetach
(
card
->
hw
,
DivasIOBase
);
return
0
;
}
static
int
diva_server_bri_mem_get
(
card_t
*
card
,
mem_block_t
*
mem_block
)
{
dword
user_addr
=
mem_block
->
addr
;
word
length
=
0
;
dword
addr
;
word
i
;
byte
*
DivasIOBase
;
DPRINTF
((
"divas: Retrieving memory from 0x%x"
,
user_addr
));
DivasIOBase
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_IOBASE
);
addr
=
user_addr
;
for
(
i
=
0
;
i
<
(
16
*
8
);
i
++
)
{
addr
=
user_addr
+
i
;
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
REG_ADDRHI
,
addr
>>
16
);
UxCardPortIoOutW
(
card
->
hw
,
DivasIOBase
,
REG_ADDRLO
,
(
word
)
addr
);
mem_block
->
data
[
i
]
=
UxCardPortIoIn
(
card
->
hw
,
DivasIOBase
,
REG_DATA
);
length
++
;
}
UxCardMemDetach
(
card
->
hw
,
DivasIOBase
);
return
length
;
}
int
DivasBriInit
(
card_t
*
card
,
dia_card_t
*
cfg
)
{
DPRINTF
((
"divas: initialise Diva Server BRI card"
));
if
(
DivasBRIInitPCI
(
card
,
cfg
)
==
-
1
)
{
return
-
1
;
}
card
->
card_reset
=
diva_server_bri_reset
;
card
->
card_start
=
diva_server_bri_start
;
card
->
card_load
=
diva_server_bri_load
;
card
->
card_config
=
diva_server_bri_config
;
card
->
reset_int
=
diva_server_bri_reset_int
;
card
->
card_mem_get
=
diva_server_bri_mem_get
;
card
->
xlog_offset
=
DIVAS_MAINT_OFFSET
;
card
->
out
=
DivasOut
;
card
->
test_int
=
DivasTestInt
;
card
->
dpc
=
DivasDpc
;
card
->
clear_int
=
DivasClearInt
;
card
->
card_isr
=
bri_ISR
;
card
->
a
.
ram_out
=
io_out
;
card
->
a
.
ram_outw
=
io_outw
;
card
->
a
.
ram_out_buffer
=
io_out_buffer
;
card
->
a
.
ram_inc
=
io_inc
;
card
->
a
.
ram_in
=
io_in
;
card
->
a
.
ram_inw
=
io_inw
;
card
->
a
.
ram_in_buffer
=
io_in_buffer
;
card
->
a
.
ram_look_ahead
=
io_look_ahead
;
return
0
;
}
word
GetProtFeatureValue
(
char
*
sw_id
)
{
word
features
=
0
;
while
((
*
sw_id
)
&&
(
sw_id
[
0
]
!=
'['
))
sw_id
++
;
if
(
sw_id
==
NULL
)
{
DPRINTF
((
"divas: no feature string present"
));
features
=
-
1
;
}
else
{
byte
i
,
shifter
;
sw_id
+=
3
;
for
(
i
=
0
,
shifter
=
12
;
i
<
4
;
i
++
,
shifter
-=
4
)
{
if
((
sw_id
[
i
]
>=
'0'
)
&&
(
sw_id
[
i
]
<=
'9'
))
{
features
|=
(
sw_id
[
i
]
-
'0'
)
<<
shifter
;
}
else
if
((
sw_id
[
i
]
>=
'a'
)
&&
(
sw_id
[
i
]
<=
'f'
))
{
features
|=
(
sw_id
[
i
]
-
'a'
+
10
)
<<
shifter
;
}
else
if
((
sw_id
[
i
]
>=
'A'
)
&&
(
sw_id
[
i
]
<=
'F'
))
{
features
|=
(
sw_id
[
i
]
-
'A'
+
10
)
<<
shifter
;
}
else
{
DPRINTF
((
"divas: invalid feature string"
));
return
-
1
;
}
}
}
return
features
;
}
int
bri_ISR
(
card_t
*
card
)
{
int
served
=
0
;
byte
*
DivasIOBase
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_IOBASE
);
if
(
UxCardPortIoIn
(
card
->
hw
,
DivasIOBase
,
M_PCI_RESET
)
&
0x01
)
{
served
=
1
;
card
->
int_pend
+=
1
;
DivasDpcSchedule
();
/* ISR DPC */
UxCardPortIoOut
(
card
->
hw
,
DivasIOBase
,
M_PCI_RESET
,
0x08
);
}
UxCardMemDetach
(
card
->
hw
,
DivasIOBase
);
return
(
served
!=
0
);
}
drivers/isdn/eicon/common.c
deleted
100644 → 0
View file @
f69c2d56
/*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.15
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include "eicon.h"
#include "sys.h"
#include "idi.h"
#include "constant.h"
#include "divas.h"
#include "pc.h"
#include "pr_pc.h"
#include "uxio.h"
#define DIVAS_LOAD_CMD 0x02
#define DIVAS_START_CMD 0x03
#define DIVAS_IRQ_RESET 0xC18
#define DIVAS_IRQ_RESET_VAL 0xFE
#define TEST_INT_DIVAS 0x11
#define TEST_INT_DIVAS_BRI 0x12
#define TEST_INT_DIVAS_Q 0x13
#define DIVAS_RESET 0x81
#define DIVAS_LED1 0x04
#define DIVAS_LED2 0x08
#define DIVAS_LED3 0x20
#define DIVAS_LED4 0x40
#define DIVAS_SIGNATURE 0x4447
#define MP_PROTOCOL_ADDR 0xA0011000
#define PLX_IOBASE 0
#define DIVAS_IOBASE 1
typedef
struct
{
dword
cmd
;
dword
addr
;
dword
len
;
dword
err
;
dword
live
;
dword
reserved
[(
0x1020
>>
2
)
-
6
];
dword
signature
;
byte
data
[
1
];
}
diva_server_boot_t
;
int
DivasCardNext
;
card_t
DivasCards
[
MAX_CARDS
];
dia_config_t
*
DivasConfig
(
card_t
*
,
dia_config_t
*
);
static
DESCRIPTOR
DIDD_Table
[
32
];
void
DIVA_DIDD_Read
(
DESCRIPTOR
*
table
,
int
tablelength
)
{
memset
(
table
,
0
,
tablelength
);
if
(
tablelength
>
sizeof
(
DIDD_Table
))
tablelength
=
sizeof
(
DIDD_Table
);
if
(
tablelength
%
sizeof
(
DESCRIPTOR
))
{
tablelength
/=
sizeof
(
DESCRIPTOR
);
tablelength
*=
sizeof
(
DESCRIPTOR
);
}
if
(
tablelength
>
0
)
memcpy
((
void
*
)
table
,
(
void
*
)
DIDD_Table
,
tablelength
);
return
;
}
void
DIVA_DIDD_Write
(
DESCRIPTOR
*
table
,
int
tablelength
)
{
if
(
tablelength
>
sizeof
(
DIDD_Table
))
tablelength
=
sizeof
(
DIDD_Table
);
memcpy
((
void
*
)
DIDD_Table
,
(
void
*
)
table
,
tablelength
);
return
;
}
static
void
init_idi_tab
(
void
)
{
DESCRIPTOR
d
[
32
];
memset
(
d
,
0
,
sizeof
(
d
));
d
[
0
].
type
=
IDI_DIMAINT
;
/* identify the DIMAINT entry */
d
[
0
].
channels
=
0
;
/* zero channels associated with dimaint*/
d
[
0
].
features
=
0
;
/* no features associated with dimaint */
d
[
0
].
request
=
(
IDI_CALL
)
DivasPrintf
;
DIVA_DIDD_Write
(
d
,
sizeof
(
d
));
return
;
}
/*
* I/O routines for memory mapped cards
*/
byte
mem_in
(
ADAPTER
*
a
,
void
*
adr
)
{
card_t
*
card
=
a
->
io
;
unsigned
char
*
b
,
*
m
;
byte
value
;
m
=
b
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_SHARED_MEMORY
);
m
+=
(
unsigned
int
)
adr
;
value
=
UxCardMemIn
(
card
->
hw
,
m
);
UxCardMemDetach
(
card
->
hw
,
b
);
return
value
;
}
word
mem_inw
(
ADAPTER
*
a
,
void
*
adr
)
{
card_t
*
card
=
a
->
io
;
unsigned
char
*
b
,
*
m
;
word
value
;
m
=
b
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_SHARED_MEMORY
);
m
+=
(
unsigned
int
)
adr
;
value
=
UxCardMemInW
(
card
->
hw
,
m
);
UxCardMemDetach
(
card
->
hw
,
b
);
return
value
;
}
void
mem_in_buffer
(
ADAPTER
*
a
,
void
*
adr
,
void
*
P
,
word
length
)
{
card_t
*
card
=
a
->
io
;
unsigned
char
*
b
,
*
m
;
m
=
b
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_SHARED_MEMORY
);
m
+=
(
unsigned
int
)
adr
;
UxCardMemInBuffer
(
card
->
hw
,
m
,
P
,
length
);
UxCardMemDetach
(
card
->
hw
,
b
);
return
;
}
void
mem_look_ahead
(
ADAPTER
*
a
,
PBUFFER
*
RBuffer
,
ENTITY
*
e
)
{
card_t
*
card
=
a
->
io
;
unsigned
char
*
b
,
*
m
;
m
=
b
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_SHARED_MEMORY
);
m
+=
(
dword
)
&
RBuffer
->
length
;
card
->
RBuffer
.
length
=
UxCardMemInW
(
card
->
hw
,
m
);
m
=
b
;
m
+=
(
dword
)
&
RBuffer
->
P
;
UxCardMemInBuffer
(
card
->
hw
,
m
,
card
->
RBuffer
.
P
,
card
->
RBuffer
.
length
);
e
->
RBuffer
=
(
DBUFFER
*
)
&
card
->
RBuffer
;
UxCardMemDetach
(
card
->
hw
,
b
);
return
;
}
void
mem_out
(
ADAPTER
*
a
,
void
*
adr
,
byte
data
)
{
card_t
*
card
=
a
->
io
;
unsigned
char
*
b
,
*
m
;
m
=
b
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_SHARED_MEMORY
);
m
+=
(
unsigned
int
)
adr
;
UxCardMemOut
(
card
->
hw
,
m
,
data
);
UxCardMemDetach
(
card
->
hw
,
b
);
return
;
}
void
mem_outw
(
ADAPTER
*
a
,
void
*
adr
,
word
data
)
{
card_t
*
card
=
a
->
io
;
unsigned
char
*
b
,
*
m
;
m
=
b
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_SHARED_MEMORY
);
m
+=
(
unsigned
int
)
adr
;
UxCardMemOutW
(
card
->
hw
,
m
,
data
);
UxCardMemDetach
(
card
->
hw
,
b
);
return
;
}
void
mem_out_buffer
(
ADAPTER
*
a
,
void
*
adr
,
void
*
P
,
word
length
)
{
card_t
*
card
=
a
->
io
;
unsigned
char
*
b
,
*
m
;
m
=
b
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_SHARED_MEMORY
);
m
+=
(
unsigned
int
)
adr
;
UxCardMemOutBuffer
(
card
->
hw
,
m
,
P
,
length
);
UxCardMemDetach
(
card
->
hw
,
b
);
return
;
}
void
mem_inc
(
ADAPTER
*
a
,
void
*
adr
)
{
word
value
;
card_t
*
card
=
a
->
io
;
unsigned
char
*
b
,
*
m
;
m
=
b
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_SHARED_MEMORY
);
m
+=
(
unsigned
int
)
adr
;
value
=
UxCardMemInW
(
card
->
hw
,
m
);
value
++
;
UxCardMemOutW
(
card
->
hw
,
m
,
value
);
UxCardMemDetach
(
card
->
hw
,
b
);
return
;
}
/*
* I/O routines for I/O mapped cards
*/
byte
io_in
(
ADAPTER
*
a
,
void
*
adr
)
{
card_t
*
card
=
a
->
io
;
byte
value
;
byte
*
DivasIOBase
=
NULL
;
DivasIOBase
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_IOBASE
);
value
=
UxCardIoIn
(
card
->
hw
,
DivasIOBase
,
adr
);
UxCardMemDetach
(
card
->
hw
,
DivasIOBase
);
return
value
;
}
word
io_inw
(
ADAPTER
*
a
,
void
*
adr
)
{
card_t
*
card
=
a
->
io
;
word
value
;
byte
*
DivasIOBase
=
NULL
;
DivasIOBase
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_IOBASE
);
value
=
UxCardIoInW
(
card
->
hw
,
DivasIOBase
,
adr
);
UxCardMemDetach
(
card
->
hw
,
DivasIOBase
);
return
value
;
}
void
io_in_buffer
(
ADAPTER
*
a
,
void
*
adr
,
void
*
P
,
word
length
)
{
card_t
*
card
=
a
->
io
;
byte
*
DivasIOBase
=
NULL
;
DivasIOBase
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_IOBASE
);
UxCardIoInBuffer
(
card
->
hw
,
DivasIOBase
,
adr
,
P
,
length
);
UxCardMemDetach
(
card
->
hw
,
DivasIOBase
);
return
;
}
void
io_look_ahead
(
ADAPTER
*
a
,
PBUFFER
*
RBuffer
,
ENTITY
*
e
)
{
card_t
*
card
=
a
->
io
;
byte
*
DivasIOBase
=
NULL
;
DivasIOBase
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_IOBASE
);
card
->
RBuffer
.
length
=
UxCardIoInW
(
card
->
hw
,
DivasIOBase
,
(
byte
*
)
RBuffer
);
UxCardIoInBuffer
(
card
->
hw
,
DivasIOBase
,
&
RBuffer
->
P
,
card
->
RBuffer
.
P
,
card
->
RBuffer
.
length
);
UxCardMemDetach
(
card
->
hw
,
DivasIOBase
);
e
->
RBuffer
=
(
DBUFFER
*
)
&
card
->
RBuffer
;
return
;
}
void
io_out
(
ADAPTER
*
a
,
void
*
adr
,
byte
data
)
{
card_t
*
card
=
a
->
io
;
byte
*
DivasIOBase
=
NULL
;
DivasIOBase
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_IOBASE
);
UxCardIoOut
(
card
->
hw
,
DivasIOBase
,
adr
,
data
);
UxCardMemDetach
(
card
->
hw
,
DivasIOBase
);
return
;
}
void
io_outw
(
ADAPTER
*
a
,
void
*
adr
,
word
data
)
{
card_t
*
card
=
a
->
io
;
byte
*
DivasIOBase
=
NULL
;
DivasIOBase
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_IOBASE
);
UxCardIoOutW
(
card
->
hw
,
DivasIOBase
,
adr
,
data
);
UxCardMemDetach
(
card
->
hw
,
DivasIOBase
);
return
;
}
void
io_out_buffer
(
ADAPTER
*
a
,
void
*
adr
,
void
*
P
,
word
length
)
{
card_t
*
card
=
a
->
io
;
byte
*
DivasIOBase
=
NULL
;
DivasIOBase
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_IOBASE
);
UxCardIoOutBuffer
(
card
->
hw
,
DivasIOBase
,
adr
,
P
,
length
);
UxCardMemDetach
(
card
->
hw
,
DivasIOBase
);
return
;
}
void
io_inc
(
ADAPTER
*
a
,
void
*
adr
)
{
word
value
;
card_t
*
card
=
a
->
io
;
byte
*
DivasIOBase
;
DivasIOBase
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_IOBASE
);
value
=
UxCardIoInW
(
card
->
hw
,
DivasIOBase
,
adr
);
value
++
;
UxCardIoOutW
(
card
->
hw
,
DivasIOBase
,
adr
,
value
);
UxCardMemDetach
(
card
->
hw
,
DivasIOBase
);
return
;
}
static
void
test_int
(
card_t
*
card
)
{
byte
*
shared
,
*
DivasIOBase
;
switch
(
card
->
test_int_pend
)
{
case
TEST_INT_DIVAS
:
DPRINTF
((
"divas: test interrupt pending"
));
shared
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_SHARED_MEMORY
);
if
(
UxCardMemIn
(
card
->
hw
,
&
shared
[
0x3FE
]))
{
UxCardMemOut
(
card
->
hw
,
&
(((
struct
pr_ram
*
)
shared
)
->
RcOutput
),
0
);
UxCardMemDetach
(
card
->
hw
,
shared
);
(
*
card
->
reset_int
)(
card
);
shared
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_SHARED_MEMORY
);
UxCardMemOut
(
card
->
hw
,
&
shared
[
0x3FE
],
0
);
DPRINTF
((
"divas: test interrupt cleared"
));
}
UxCardMemDetach
(
card
->
hw
,
shared
);
card
->
test_int_pend
=
0
;
break
;
case
TEST_INT_DIVAS_BRI
:
DPRINTF
((
"divas: BRI test interrupt pending"
));
(
*
card
->
reset_int
)(
card
);
DivasIOBase
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_IOBASE
);
UxCardIoOutW
(
card
->
hw
,
DivasIOBase
,
(
void
*
)
0x3FE
,
0
);
UxCardMemDetach
(
card
->
hw
,
DivasIOBase
);
DPRINTF
((
"divas: test interrupt cleared"
));
card
->
test_int_pend
=
0
;
break
;
case
TEST_INT_DIVAS_Q
:
DPRINTF
((
"divas: 4BRI test interrupt pending"
));
(
*
card
->
reset_int
)(
card
);
card
->
test_int_pend
=
0
;
break
;
default:
DPRINTF
((
"divas: unknown test interrupt pending"
));
return
;
}
return
;
}
void
card_isr
(
void
*
dev_id
)
{
card_t
*
card
=
(
card_t
*
)
dev_id
;
ADAPTER
*
a
=
&
card
->
a
;
int
ipl
;
if
(
card
->
test_int_pend
)
{
ipl
=
UxCardLock
(
card
->
hw
);
card
->
int_pend
=
0
;
test_int
(
card
);
UxCardUnlock
(
card
->
hw
,
ipl
);
return
;
}
if
(
card
->
card_isr
)
{
(
*
(
card
->
card_isr
))(
card
);
}
else
{
ipl
=
UxCardLock
(
card
->
hw
);
if
((
card
->
test_int
)(
a
))
{
(
card
->
reset_int
)(
card
);
}
UxCardUnlock
(
card
->
hw
,
ipl
);
}
}
int
DivasCardNew
(
dia_card_t
*
card_info
)
{
card_t
*
card
;
static
boolean_t
first_call
=
TRUE
;
boolean_t
NeedISRandReset
=
FALSE
;
DPRINTF
((
"divas: new card "
));
if
(
first_call
)
{
first_call
=
FALSE
;
init_idi_tab
();
}
DivasConfigGet
(
card_info
);
if
(
DivasCardNext
==
DIM
(
DivasCards
))
{
KDPRINTF
((
KERN_WARNING
"Divas: no space available for new card"
));
return
-
1
;
}
card
=
&
DivasCards
[
DivasCardNext
];
card
->
state
=
DIA_UNKNOWN
;
card
->
cfg
=
*
card_info
;
card
->
a
.
io
=
card
;
if
(
UxCardHandleGet
(
&
card
->
hw
,
card_info
))
{
KDPRINTF
((
KERN_WARNING
"Divas: cannot get OS specific handle for card"
));
return
-
1
;
}
if
(
card_info
->
card_type
==
DIA_CARD_TYPE_DIVA_SERVER_B
)
{
DivasBriPatch
(
card
);
card_info
->
io_base
=
card
->
cfg
.
io_base
;
}
switch
(
card_info
->
card_type
)
{
case
DIA_CARD_TYPE_DIVA_SERVER
:
if
(
DivasPriInit
(
card
,
card_info
))
{
return
-
1
;
}
NeedISRandReset
=
TRUE
;
break
;
case
DIA_CARD_TYPE_DIVA_SERVER_B
:
if
(
DivasBriInit
(
card
,
card_info
))
{
return
-
1
;
}
NeedISRandReset
=
TRUE
;
break
;
case
DIA_CARD_TYPE_DIVA_SERVER_Q
:
if
(
Divas4BriInit
(
card
,
card_info
))
{
return
-
1
;
}
if
(
card_info
->
name
[
6
]
==
'0'
)
{
NeedISRandReset
=
TRUE
;
}
else
// Need to set paramater for ISR anyway
{
card
->
hw
->
user_isr_arg
=
card
;
card
->
hw
->
user_isr
=
card_isr
;
}
break
;
default:
KDPRINTF
((
KERN_WARNING
"Divas: unsupported card type (%d)"
,
card_info
->
card_type
));
return
-
1
;
}
if
(
NeedISRandReset
)
{
if
(
UxIsrInstall
(
card
->
hw
,
card_isr
,
card
))
{
KDPRINTF
((
KERN_WARNING
"Divas: Install ISR failed (IRQ %d)"
,
card
->
cfg
.
irq
));
UxCardHandleFree
(
card
->
hw
);
return
-
1
;
}
if
(
card_info
->
card_type
!=
DIA_CARD_TYPE_DIVA_SERVER_Q
)
{
if
((
*
card
->
card_reset
)(
card
))
{
KDPRINTF
((
KERN_WARNING
"Divas: Adapter reset failed"
));
return
-
1
;
}
card
->
state
=
DIA_RESET
;
}
NeedISRandReset
=
FALSE
;
}
DivasCardNext
++
;
return
0
;
}
void
*
get_card
(
int
card_id
)
{
int
i
;
for
(
i
=
0
;
i
<
DivasCardNext
;
i
++
)
{
if
(
DivasCards
[
i
].
cfg
.
card_id
==
card_id
)
{
return
(
&
DivasCards
[
i
]);
}
}
DPRINTF
((
"divas: get_card() : no such card id (%d)"
,
card_id
));
return
NULL
;
}
int
DivasCardConfig
(
dia_config_t
*
config
)
{
card_t
*
card
;
int
status
;
DPRINTF
((
"divas: configuring card"
));
card
=
get_card
(
config
->
card_id
);
if
(
!
card
)
{
return
-
1
;
}
config
=
DivasConfig
(
card
,
config
);
status
=
(
*
card
->
card_config
)(
card
,
config
);
if
(
!
status
)
{
card
->
state
=
DIA_CONFIGURED
;
}
return
status
;
}
int
DivasCardLoad
(
dia_load_t
*
load
)
{
card_t
*
card
;
int
status
;
card
=
get_card
(
load
->
card_id
);
if
(
!
card
)
{
return
-
1
;
}
if
(
card
->
state
==
DIA_RUNNING
)
{
(
*
card
->
card_reset
)(
card
);
}
status
=
(
*
card
->
card_load
)(
card
,
load
);
if
(
!
status
)
{
card
->
state
=
DIA_LOADED
;
}
return
status
;
}
static
int
idi_register
(
card_t
*
card
,
byte
channels
)
{
DESCRIPTOR
d
[
32
];
int
length
,
num_entities
;
DPRINTF
((
"divas: registering card with IDI"
));
num_entities
=
(
channels
>
2
)
?
MAX_PENTITIES
:
MAX_ENTITIES
;
card
->
e_tbl
=
UxAlloc
(
sizeof
(
E_INFO
)
*
num_entities
);
if
(
!
card
->
e_tbl
)
{
KDPRINTF
((
KERN_WARNING
"Divas: IDI register failed - no memory available"
));
return
-
1
;
}
memset
(
card
->
e_tbl
,
0
,
sizeof
(
E_INFO
)
*
num_entities
);
card
->
e_max
=
num_entities
;
DIVA_DIDD_Read
(
d
,
sizeof
(
d
));
for
(
length
=
0
;
length
<
DIM
(
d
);
length
++
)
if
(
d
[
length
].
type
==
0
)
break
;
if
(
length
>=
DIM
(
d
))
{
KDPRINTF
((
KERN_WARNING
"Divas: IDI register failed - table full"
));
return
-
1
;
}
switch
(
card
->
cfg
.
card_type
)
{
case
DIA_CARD_TYPE_DIVA_SERVER
:
d
[
length
].
type
=
IDI_ADAPTER_PR
;
/* d[length].serial = card->serial_no; */
break
;
case
DIA_CARD_TYPE_DIVA_SERVER_B
:
d
[
length
].
type
=
IDI_ADAPTER_MAESTRA
;
/* d[length].serial = card->serial_no; */
break
;
// 4BRI is treated as 4 BRI adapters
case
DIA_CARD_TYPE_DIVA_SERVER_Q
:
d
[
length
].
type
=
IDI_ADAPTER_MAESTRA
;
/* d[length].serial = card->cfg.serial; */
}
d
[
length
].
features
=
0
;
d
[
length
].
features
|=
DI_FAX3
|
DI_MODEM
|
DI_POST
|
DI_V110
|
DI_V120
;
if
(
card
->
hw
->
features
&
PROTCAP_MANIF
)
{
d
[
length
].
features
|=
DI_MANAGE
;
}
if
(
card
->
hw
->
features
&
PROTCAP_V_42
)
{
d
[
length
].
features
|=
DI_V_42
;
}
if
(
card
->
hw
->
features
&
PROTCAP_EXTD_FAX
)
{
d
[
length
].
features
|=
DI_EXTD_FAX
;
}
d
[
length
].
channels
=
channels
;
d
[
length
].
request
=
DivasIdiRequest
[
card
-
DivasCards
];
length
++
;
DIVA_DIDD_Write
(
d
,
sizeof
(
d
));
return
0
;
}
int
DivasCardStart
(
int
card_id
)
{
card_t
*
card
;
byte
channels
;
int
status
;
DPRINTF
((
"divas: starting card"
));
card
=
get_card
(
card_id
);
if
(
!
card
)
{
return
-
1
;
}
status
=
(
*
card
->
card_start
)(
card
,
&
channels
);
if
(
status
)
{
return
status
;
}
/* 4BRI == 4 x BRI so call idi_register 4 times each with 2 channels */
if
(
card
->
cfg
.
card_type
==
DIA_CARD_TYPE_DIVA_SERVER_Q
)
{
int
i
;
card_t
*
FourBRISlave
;
for
(
i
=
3
;
i
>=
0
;
i
--
)
{
FourBRISlave
=
get_card
(
card_id
-
i
);
/* 0, 1, 2, 3 */
if
(
FourBRISlave
)
{
idi_register
(
FourBRISlave
,
2
);
FourBRISlave
->
state
=
DIA_RUNNING
;
}
}
card
->
serial_no
=
card
->
cfg
.
serial
;
DPRINTF
((
"divas: card id %d (4BRI), serial no. 0x%x ready with %d channels"
,
card_id
-
3
,
card
->
serial_no
,
(
int
)
channels
));
}
else
{
status
=
idi_register
(
card
,
channels
);
if
(
!
status
)
{
card
->
state
=
DIA_RUNNING
;
DPRINTF
((
"divas: card id %d, serial no. 0x%x ready with %d channels"
,
card_id
,
card
->
serial_no
,
(
int
)
channels
));
}
}
return
status
;
}
int
DivasGetMem
(
mem_block_t
*
mem_block
)
{
card_t
*
card
;
word
card_id
=
mem_block
->
card_id
;
card
=
get_card
(
card_id
);
if
(
!
card
)
{
return
0
;
}
return
(
*
card
->
card_mem_get
)(
card
,
mem_block
);
}
/*
* Deleyed Procedure Call for handling interrupts from card
*/
void
DivaDoCardDpc
(
card_t
*
card
)
{
ADAPTER
*
a
;
a
=
&
card
->
a
;
if
(
UxInterlockedIncrement
(
card
->
hw
,
&
card
->
dpc_reentered
)
>
1
)
{
return
;
}
do
{
if
((
*
(
card
->
test_int
))(
a
))
{
(
*
(
card
->
dpc
))(
a
);
(
*
(
card
->
clear_int
))(
a
);
}
(
*
(
card
->
out
))(
a
);
}
while
(
UxInterlockedDecrement
(
card
->
hw
,
&
card
->
dpc_reentered
));
}
void
DivasDoDpc
(
unsigned
long
dummy
)
{
card_t
*
card
=
DivasCards
;
int
i
=
DivasCardNext
;
while
(
i
--
)
{
if
(
card
->
state
==
DIA_RUNNING
)
DivaDoCardDpc
(
card
);
card
++
;
}
}
/*
* DivasGetNum
* Returns the number of active adapters
*/
int
DivasGetNum
(
void
)
{
return
(
DivasCardNext
);
}
/*
* DivasGetList
* Returns a list of active adapters
*/
int
DivasGetList
(
dia_card_list_t
*
card_list
)
{
int
i
;
memset
(
card_list
,
0
,
sizeof
(
dia_card_list_t
));
for
(
i
=
0
;
i
<
DivasCardNext
;
i
++
)
{
card_list
->
card_type
=
DivasCards
[
i
].
cfg
.
card_type
;
card_list
->
card_slot
=
DivasCards
[
i
].
cfg
.
slot
;
card_list
->
state
=
DivasCards
[
i
].
state
;
card_list
++
;
}
return
0
;
}
/*
* control logging for specified card
*/
void
DivasLog
(
dia_log_t
*
log
)
{
card_t
*
card
;
card
=
get_card
(
log
->
card_id
);
if
(
!
card
)
{
return
;
}
card
->
log_types
=
log
->
log_types
;
return
;
}
drivers/isdn/eicon/constant.h
deleted
100644 → 0
View file @
f69c2d56
/*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.0
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
/*------------------------------------------------------------------*/
/* Q.931 information elements maximum length */
/* excluding the identifier, including the length field */
/*------------------------------------------------------------------*/
#define MAX_LEN_BC 13
#define MAX_LEN_LLC 19
/* ctr3 */
#define MAX_LEN_HLC 6
/* ctr3 */
#define MAX_LEN_UUI 200
/* Hicom USBS req */
#define MAX_LEN_NUM 24
#define MAX_LEN_DSP 83
/* ctr3 */
#define MAX_LEN_NI 4
#define MAX_LEN_PI 5
#define MAX_LEN_SIN 3
#define MAX_LEN_CST 4
#define MAX_LEN_SIG 2
#define MAX_LEN_SPID 32
#define MAX_LEN_EID 3
#define MAX_LEN_CHI 35
/* ctr3 */
#define MAX_LEN_CAU 33
#define MAX_LEN_FTY 130
#define MAX_LEN_KEY 83
/* ctr3 */
#define MAX_LEN_RSI 4
#define MAX_LEN_CAI 11
#define MAX_NUM_SPID 4
#define MAX_LEN_USERID 9
#define MAX_LEN_APPLID 5
#define MAX_LEN_NTTCIF 15
/*------------------------------------------------------------------*/
/* decision return values */
/*------------------------------------------------------------------*/
#define YES 1
#define NO 0
/*-------------------------------------------------------------------*/
/* w element coding */
/*-------------------------------------------------------------------*/
#define NTTCIF 0x01
#define BC 0x04
#define CAU 0x08
#define CAD 0x0c
#define CAI 0x10
#define CST 0x14
#define CHI 0x18
#define LLI 0x19
#define CHA 0x1a
#define FTY 0x1c
#define PI 0x1e
#define NFAC 0x20
#define TC 0x24
#define ATT_EID 0x26
#define NI 0x27
#define DSP 0x28
#define DT 0x29
#define KEY 0x2c
#define KP 0x2c
#define UID 0x2d
#define SIG 0x34
#define FI 0x39
#define SPID 0x3a
#define EID 0x3b
#define DSPF 0x3c
#define ECAD 0x4c
#define OAD 0x6c
#define OSA 0x6d
#define DAD 0x70
#define CPN 0x70
#define DSA 0x71
#define RDX 0x73
#define RAD 0x74
#define RDN 0x74
#define RSI 0x79
#define SCR 0x7A
/* internal unscreened CPN */
#define MIE 0x7a
/* internal management info element */
#define LLC 0x7c
#define HLC 0x7d
#define UUI 0x7e
#define ESC 0x7f
#define SHIFT 0x90
#define MORE 0xa0
#define CL 0xb0
/* information elements used on the spid interface */
#define SPID_CMD 0xc0
#define SPID_LINK 0x10
#define SPID_DN 0x70
#define SPID_BC 0x04
#define SPID_SWITCH 0x11
/*------------------------------------------------------------------*/
/* global configuration parameters, defined in exec.c */
/* these parameters are configured with program loading */
/*------------------------------------------------------------------*/
#define PROT_1TR6 0
#define PROT_ETSI 1
#define PROT_FRANC 2
#define PROT_BELG 3
#define PROT_SWED 4
#define PROT_NI 5
#define PROT_5ESS 6
#define PROT_JAPAN 7
#define PROT_ATEL 8
#define PROT_US 9
#define PROT_ITALY 10
#define PROT_TWAN 11
#define PROT_AUSTRAL 12
#define INIT_PROT_1TR6 0x80|PROT_1TR6
#define INIT_PROT_ETSI 0x80|PROT_ETSI
#define INIT_PROT_FRANC 0x80|PROT_FRANC
#define INIT_PROT_BELG 0x80|PROT_BELG
#define INIT_PROT_SWED 0x80|PROT_SWED
#define INIT_PROT_NI 0x80|PROT_NI
#define INIT_PROT_5ESS 0x80|PROT_5ESS
#define INIT_PROT_JAPAN 0x80|PROT_JAPAN
#define INIT_PROT_ATEL 0x80|PROT_ATEL
#define INIT_PROT_ITALY 0x80|PROT_ITALY
#define INIT_PROT_TWAN 0x80|PROT_TWAN
#define INIT_PROT_AUSTRAL 0x80|PROT_AUSTRAL
/* -----------------------------------------------------------**
** The PROTOCOL_FEATURE_STRING in feature.h (included **
** in prstart.sx and astart.sx) defines capabilities and **
** features of the actual protocol code. It's used as a bit **
** mask. **
** The following Bits are defined: **
** -----------------------------------------------------------*/
#define PROTCAP_TELINDUS 0x0001
/* Telindus Variant of protocol code */
#define PROTCAP_MANIF 0x0002
/* Management interface implemented */
#define PROTCAP_V_42 0x0004
/* V42 implemented */
#define PROTCAP_V90D 0x0008
/* V.90D (implies up to 384k DSP code) */
#define PROTCAP_EXTD_FAX 0x0010
/* Extended FAX (ECM, 2D, T6, Polling) */
#define PROTCAP_FREE4 0x0020
/* not used */
#define PROTCAP_FREE5 0x0040
/* not used */
#define PROTCAP_FREE6 0x0080
/* not used */
#define PROTCAP_FREE7 0x0100
/* not used */
#define PROTCAP_FREE8 0x0200
/* not used */
#define PROTCAP_FREE9 0x0400
/* not used */
#define PROTCAP_FREE10 0x0800
/* not used */
#define PROTCAP_FREE11 0x1000
/* not used */
#define PROTCAP_FREE12 0x2000
/* not used */
#define PROTCAP_FREE13 0x4000
/* not used */
#define PROTCAP_EXTENSION 0x8000
/* used for future extentions */
drivers/isdn/eicon/divalog.h
deleted
100644 → 0
View file @
f69c2d56
/*
* Include file for defining the kernel logger messages
* These definitions are shared between the klog driver and the
* klogd daemon process
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.0
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#if !defined(_KLOGMSG_H)
#define _KLOGMSG_H
/* define a type for a log entry */
#define KLOG_TEXT_MSG (0)
#define KLOG_XLOG_MSG (1)
#define KLOG_XTXT_MSG (2)
#define KLOG_IDI_REQ (4)
#define KLOG_IDI_CALLBACK (5)
#define KLOG_CAPI_MSG (6)
typedef
struct
{
unsigned
long
time_stamp
;
/* in ms since last system boot */
int
card
;
/* card number (-1 for all) */
unsigned
int
type
;
/* type of log message (0 is text) */
unsigned
int
length
;
/* message length (non-text messages only) */
unsigned
short
code
;
/* message code (non-text messages only) */
char
buffer
[
110
];
/* text/data to log */
}
klog_t
;
void
DivasLogAdd
(
void
*
buffer
,
int
length
);
#endif
/* of _KLOGMSG_H */
drivers/isdn/eicon/divas.h
deleted
100644 → 0
View file @
f69c2d56
/*
* External Diva Server driver include file
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.5
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#if !defined(DIVAS_H)
#define DIVAS_H
#include "sys.h"
/* IOCTL commands */
#define DIA_IOCTL_INIT (0)
#define DIA_IOCTL_LOAD (1)
#define DIA_IOCTL_CONFIG (2)
#define DIA_IOCTL_START (3)
#define DIA_IOCTL_GET_NUM (4)
#define DIA_IOCTL_GET_LIST (5)
#define DIA_IOCTL_LOG (6)
#define DIA_IOCTL_DETECT (7)
#define DIA_IOCTL_SPACE (8)
#define DIA_IOCTL_GET_MEM (9)
#define DIA_IOCTL_FLAVOUR (10)
#define DIA_IOCTL_XLOG_REQ (11)
/* Error codes */
#define XLOG_ERR_CARD_NUM (13)
#define XLOG_ERR_DONE (14)
#define XLOG_ERR_CMD (15)
#define XLOG_ERR_TIMEOUT (16)
#define XLOG_ERR_CARD_STATE (17)
#define XLOG_ERR_UNKNOWN (18)
#define XLOG_OK (0)
/* Adapter states */
#define DIA_UNKNOWN (0)
#define DIA_RESET (1)
#define DIA_LOADED (2)
#define DIA_CONFIGURED (3)
#define DIA_RUNNING (4)
/* Stucture for getting card specific information from active cad driver */
typedef
struct
{
int
card_type
;
int
card_slot
;
int
state
;
}
dia_card_list_t
;
/* use following to select which logging to have active */
#define DIVAS_LOG_DEBUG (1 << 0)
#define DIVAS_LOG_XLOG (1 << 1)
#define DIVAS_LOG_IDI (1 << 2)
#define DIVAS_LOG_CAPI (1 << 3)
/* stucture for DIA_IOCTL_LOG to get information from adapter */
typedef
struct
{
int
card_id
;
int
log_types
;
/* bit mask of log types: use DIVAS_LOG_XXX */
}
dia_log_t
;
/* list of cards supported by this driver */
#define DIA_CARD_TYPE_DIVA_SERVER (0)
/* Diva Server PRI */
#define DIA_CARD_TYPE_DIVA_SERVER_B (1)
/* Diva Server BRI */
#define DIA_CARD_TYPE_DIVA_SERVER_Q (2)
/* Diva Server 4-BRI */
/* bus types */
#define DIA_BUS_TYPE_ISA (0)
#define DIA_BUS_TYPE_ISA_PNP (1)
#define DIA_BUS_TYPE_PCI (2)
#define DIA_BUS_TYPE_MCA (3)
/* types of memory used (index for memory array below) */
#define DIVAS_RAM_MEMORY 0
#define DIVAS_REG_MEMORY 1
#define DIVAS_CFG_MEMORY 2
#define DIVAS_SHARED_MEMORY 3
#define DIVAS_CTL_MEMORY 4
/*
* card config information
* passed as parameter to DIA_IOCTL_INIT ioctl to initialise new card
*/
typedef
struct
{
int
card_id
;
/* unique id assigned to this card */
int
card_type
;
/* use DIA_CARD_TYPE_xxx above */
int
bus_type
;
/* use DIA_BUS_TYPE_xxx above */
struct
pci_dev
*
pdev
;
int
slot
;
/* slot number in bus */
unsigned
char
irq
;
/* IRQ number */
int
reset_base
;
/* Reset register for I/O mapped cards */
int
io_base
;
/* I/O base for I/O mapped cards */
void
*
memory
[
5
];
/* memory base addresses for memory mapped cards */
char
name
[
9
];
/* name of adapter */
int
serial
;
/* serial number */
unsigned
char
int_priority
;
/* Interrupt priority */
}
dia_card_t
;
/*
* protocol configuration information
* passed as parameter to DIA_IOCTL_CONFIG ioctl to configure card
*/
typedef
struct
{
int
card_id
;
/* to identify particular card */
unsigned
char
tei
;
unsigned
char
nt2
;
unsigned
char
watchdog
;
unsigned
char
permanent
;
unsigned
char
x_interface
;
unsigned
char
stable_l2
;
unsigned
char
no_order_check
;
unsigned
char
handset_type
;
unsigned
char
sig_flags
;
unsigned
char
low_channel
;
unsigned
char
prot_version
;
unsigned
char
crc4
;
struct
{
unsigned
char
oad
[
32
];
unsigned
char
osa
[
32
];
unsigned
char
spid
[
32
];
}
terminal
[
2
];
}
dia_config_t
;
/*
* code configuration
* passed as parameter to DIA_IOCTL_LOAD ioctl
* one of these ioctl per code file to load
*/
typedef
struct
{
int
card_id
;
/* card to load */
enum
{
DIA_CPU_CODE
,
/* CPU code */
DIA_DSP_CODE
,
/* DSP code */
DIA_CONT_CODE
,
/* continuation of code */
DIA_TABLE_CODE
,
/* code table */
DIA_DLOAD_CNT
,
/* number of downloads*/
DIA_FPGA_CODE
}
code_type
;
/* code for CPU or DSP ? */
int
length
;
/* length of code */
unsigned
char
*
code
;
/* pointer (in user-space) to code */
}
dia_load_t
;
/*
* start configuration
* passed as parameter to DIA_IOCTL_START ioctl
*/
typedef
struct
{
int
card_id
;
/* card to start */
}
dia_start_t
;
/* used for retrieving memory from the card */
typedef
struct
{
word
card_id
;
dword
addr
;
byte
data
[
16
*
8
];
}
mem_block_t
;
/* DIVA Server specific addresses */
#define DIVAS_CPU_START_ADDR (0x0)
#define ORG_MAX_PROTOCOL_CODE_SIZE 0x000A0000
#define ORG_MAX_DSP_CODE_SIZE (0x000F0000 - ORG_MAX_PROTOCOL_CODE_SIZE)
#define ORG_DSP_CODE_BASE (0xBF7F0000 - ORG_MAX_DSP_CODE_SIZE)
#define DIVAS_DSP_START_ADDR (0xBF7A0000)
#define DIVAS_SHARED_OFFSET (0x1000)
#define MP_DSP_CODE_BASE 0xa03a0000
#define MQ_PROTCODE_OFFSET 0x100000
#define MQ_SM_OFFSET 0X0f0000
#define V90D_MAX_PROTOCOL_CODE_SIZE 0x00090000
#define V90D_MAX_DSP_CODE_SIZE (0x000F0000 - V90D_MAX_PROTOCOL_CODE_SIZE)
#define V90D_DSP_CODE_BASE (0xBF7F0000 - V90D_MAX_DSP_CODE_SIZE)
#define MQ_ORG_MAX_PROTOCOL_CODE_SIZE 0x000a0000
/* max 640K Protocol-Code */
#define MQ_ORG_MAX_DSP_CODE_SIZE 0x00050000
/* max 320K DSP-Code */
#define MQ_ORG_DSP_CODE_BASE (MQ_MAX_DSP_DOWNLOAD_ADDR \
- MQ_ORG_MAX_DSP_CODE_SIZE)
#define MQ_V90D_MAX_PROTOCOL_CODE_SIZE 0x00090000
/* max 576K Protocol-Code */
#define MQ_V90D_MAX_DSP_CODE_SIZE 0x00060000
/* max 384K DSP-Code if V.90D included */
#define MQ_MAX_DSP_DOWNLOAD_ADDR 0xa03f0000
#define MQ_V90D_DSP_CODE_BASE (MQ_MAX_DSP_DOWNLOAD_ADDR \
- MQ_V90D_MAX_DSP_CODE_SIZE)
#define ALIGNMENT_MASK_MAESTRA 0xfffffffc
#endif
/* DIVAS_H */
drivers/isdn/eicon/dsp_defs.h
deleted
100644 → 0
View file @
f69c2d56
/*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.0
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#ifndef DSP_DEFS_H_
#define DSP_DEFS_H_
#ifndef DSPDIDS_H_
#include "dspdids.h"
#endif
#ifdef __cplusplus
extern
"C"
{
#endif
/*---------------------------------------------------------------------------*/
#ifndef NULL
#define NULL 0
#endif
#ifndef TRUE
#define TRUE (0 == 0)
#endif
#ifndef FALSE
#define FALSE (0 != 0)
#endif
/*---------------------------------------------------------------------------*/
#define DSP_MEMORY_TYPE_EXTERNAL_DM 0
#define DSP_MEMORY_TYPE_EXTERNAL_PM 1
#define DSP_MEMORY_TYPE_INTERNAL_DM 2
#define DSP_MEMORY_TYPE_INTERNAL_PM 3
#define DSP_DOWNLOAD_FLAG_BOOTABLE 0x0001
#define DSP_DOWNLOAD_FLAG_2181 0x0002
#define DSP_DOWNLOAD_FLAG_TIMECRITICAL 0x0004
#define DSP_DOWNLOAD_FLAG_COMPAND 0x0008
#define DSP_MEMORY_BLOCK_COUNT 16
#define DSP_SEGMENT_PM_FLAG 0x0001
#define DSP_SEGMENT_SHARED_FLAG 0x0002
#define DSP_SEGMENT_EXTERNAL_DM DSP_MEMORY_TYPE_EXTERNAL_DM
#define DSP_SEGMENT_EXTERNAL_PM DSP_MEMORY_TYPE_EXTERNAL_PM
#define DSP_SEGMENT_INTERNAL_DM DSP_MEMORY_TYPE_INTERNAL_DM
#define DSP_SEGMENT_INTERNAL_PM DSP_MEMORY_TYPE_INTERNAL_PM
#define DSP_SEGMENT_FIRST_RELOCATABLE 4
#define DSP_DATA_BLOCK_PM_FLAG 0x0001
#define DSP_DATA_BLOCK_DWORD_FLAG 0x0002
#define DSP_DATA_BLOCK_RESOLVE_FLAG 0x0004
#define DSP_RELOC_NONE 0x00
#define DSP_RELOC_SEGMENT_MASK 0x3f
#define DSP_RELOC_TYPE_MASK 0xc0
#define DSP_RELOC_TYPE_0 0x00
/* relocation of address in DM word / high part of PM word */
#define DSP_RELOC_TYPE_1 0x40
/* relocation of address in low part of PM data word */
#define DSP_RELOC_TYPE_2 0x80
/* relocation of address in standard command */
#define DSP_RELOC_TYPE_3 0xc0
/* relocation of address in call/jump on flag in */
#define DSP_COMBIFILE_FORMAT_IDENTIFICATION_SIZE 48
#define DSP_COMBIFILE_FORMAT_VERSION_BCD 0x0100
#define DSP_FILE_FORMAT_IDENTIFICATION_SIZE 48
#define DSP_FILE_FORMAT_VERSION_BCD 0x0100
typedef
struct
tag_dsp_combifile_header
{
char
format_identification
[
DSP_COMBIFILE_FORMAT_IDENTIFICATION_SIZE
];
word
format_version_bcd
;
word
header_size
;
word
combifile_description_size
;
word
directory_entries
;
word
directory_size
;
word
download_count
;
word
usage_mask_size
;
}
t_dsp_combifile_header
;
typedef
struct
tag_dsp_combifile_directory_entry
{
word
card_type_number
;
word
file_set_number
;
}
t_dsp_combifile_directory_entry
;
typedef
struct
tag_dsp_file_header
{
char
format_identification
[
DSP_FILE_FORMAT_IDENTIFICATION_SIZE
];
word
format_version_bcd
;
word
download_id
;
word
download_flags
;
word
required_processing_power
;
word
interface_channel_count
;
word
header_size
;
word
download_description_size
;
word
memory_block_table_size
;
word
memory_block_count
;
word
segment_table_size
;
word
segment_count
;
word
symbol_table_size
;
word
symbol_count
;
word
total_data_size_dm
;
word
data_block_count_dm
;
word
total_data_size_pm
;
word
data_block_count_pm
;
}
t_dsp_file_header
;
typedef
struct
tag_dsp_memory_block_desc
{
word
alias_memory_block
;
word
memory_type
;
word
address
;
word
size
;
/* DSP words */
}
t_dsp_memory_block_desc
;
typedef
struct
tag_dsp_segment_desc
{
word
memory_block
;
word
attributes
;
word
base
;
word
size
;
word
alignment
;
/* ==0 -> no other legal start address than base */
}
t_dsp_segment_desc
;
typedef
struct
tag_dsp_symbol_desc
{
word
symbol_id
;
word
segment
;
word
offset
;
word
size
;
/* DSP words */
}
t_dsp_symbol_desc
;
typedef
struct
tag_dsp_data_block_header
{
word
attributes
;
word
segment
;
word
offset
;
word
size
;
/* DSP words */
}
t_dsp_data_block_header
;
typedef
struct
tag_dsp_download_desc
/* be sure to keep native alignment for MAESTRA's */
{
word
download_id
;
word
download_flags
;
word
required_processing_power
;
word
interface_channel_count
;
word
excess_header_size
;
word
memory_block_count
;
word
segment_count
;
word
symbol_count
;
word
data_block_count_dm
;
word
data_block_count_pm
;
byte
*
p_excess_header_data
;
char
*
p_download_description
;
t_dsp_memory_block_desc
*
p_memory_block_table
;
t_dsp_segment_desc
*
p_segment_table
;
t_dsp_symbol_desc
*
p_symbol_table
;
word
*
p_data_blocks_dm
;
word
*
p_data_blocks_pm
;
}
t_dsp_download_desc
;
#define DSP_DOWNLOAD_INDEX_KERNEL 0
#define DSP30TX_DOWNLOAD_INDEX_KERNEL 1
#define DSP30RX_DOWNLOAD_INDEX_KERNEL 2
#define DSP_MAX_DOWNLOAD_COUNT 35
#define DSP_DOWNLOAD_MAX_SEGMENTS 16
#define DSP_UDATA_REQUEST_RECONFIGURE 0
/*
parameters:
<word> reconfigure delay (in 8kHz samples)
<word> reconfigure code
<byte> reconfigure hdlc preamble flags
*/
#define DSP_RECONFIGURE_TX_FLAG 0x8000
#define DSP_RECONFIGURE_SHORT_TRAIN_FLAG 0x4000
#define DSP_RECONFIGURE_ECHO_PROTECT_FLAG 0x2000
#define DSP_RECONFIGURE_HDLC_FLAG 0x1000
#define DSP_RECONFIGURE_SYNC_FLAG 0x0800
#define DSP_RECONFIGURE_PROTOCOL_MASK 0x00ff
#define DSP_RECONFIGURE_IDLE 0
#define DSP_RECONFIGURE_V25 1
#define DSP_RECONFIGURE_V21_CH2 2
#define DSP_RECONFIGURE_V27_2400 3
#define DSP_RECONFIGURE_V27_4800 4
#define DSP_RECONFIGURE_V29_7200 5
#define DSP_RECONFIGURE_V29_9600 6
#define DSP_RECONFIGURE_V33_12000 7
#define DSP_RECONFIGURE_V33_14400 8
#define DSP_RECONFIGURE_V17_7200 9
#define DSP_RECONFIGURE_V17_9600 10
#define DSP_RECONFIGURE_V17_12000 11
#define DSP_RECONFIGURE_V17_14400 12
/*
data indications if transparent framer
<byte> data 0
<byte> data 1
...
data indications if HDLC framer
<byte> data 0
<byte> data 1
...
<byte> CRC 0
<byte> CRC 1
<byte> preamble flags
*/
#define DSP_UDATA_INDICATION_SYNC 0
/*
returns:
<word> time of sync (sampled from counter at 8kHz)
*/
#define DSP_UDATA_INDICATION_DCD_OFF 1
/*
returns:
<word> time of DCD off (sampled from counter at 8kHz)
*/
#define DSP_UDATA_INDICATION_DCD_ON 2
/*
returns:
<word> time of DCD on (sampled from counter at 8kHz)
<byte> connected norm
<word> connected options
<dword> connected speed (bit/s)
*/
#define DSP_UDATA_INDICATION_CTS_OFF 3
/*
returns:
<word> time of CTS off (sampled from counter at 8kHz)
*/
#define DSP_UDATA_INDICATION_CTS_ON 4
/*
returns:
<word> time of CTS on (sampled from counter at 8kHz)
<byte> connected norm
<word> connected options
<dword> connected speed (bit/s)
*/
#define DSP_CONNECTED_NORM_UNSPECIFIED 0
#define DSP_CONNECTED_NORM_V21 1
#define DSP_CONNECTED_NORM_V23 2
#define DSP_CONNECTED_NORM_V22 3
#define DSP_CONNECTED_NORM_V22_BIS 4
#define DSP_CONNECTED_NORM_V32_BIS 5
#define DSP_CONNECTED_NORM_V34 6
#define DSP_CONNECTED_NORM_V8 7
#define DSP_CONNECTED_NORM_BELL_212A 8
#define DSP_CONNECTED_NORM_BELL_103 9
#define DSP_CONNECTED_NORM_V29_LEASED_LINE 10
#define DSP_CONNECTED_NORM_V33_LEASED_LINE 11
#define DSP_CONNECTED_NORM_TFAST 12
#define DSP_CONNECTED_NORM_V21_CH2 13
#define DSP_CONNECTED_NORM_V27_TER 14
#define DSP_CONNECTED_NORM_V29 15
#define DSP_CONNECTED_NORM_V33 16
#define DSP_CONNECTED_NORM_V17 17
#define DSP_CONNECTED_OPTION_TRELLIS 0x0001
/*---------------------------------------------------------------------------*/
#ifdef __cplusplus
}
#endif
#endif
/*---------------------------------------------------------------------------*/
drivers/isdn/eicon/dspdids.h
deleted
100644 → 0
View file @
f69c2d56
/*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.0
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#ifndef DSPDIDS_H_
#define DSPDIDS_H_
/*---------------------------------------------------------------------------*/
#define DSP_DID_INVALID 0
#define DSP_DID_DIVA 1
#define DSP_DID_DIVA_PRO 2
#define DSP_DID_DIVA_PRO_20 3
#define DSP_DID_DIVA_PRO_PCCARD 4
#define DSP_DID_DIVA_SERVER_BRI_1M 5
#define DSP_DID_DIVA_SERVER_BRI_2M 6
#define DSP_DID_DIVA_SERVER_PRI_2M_TX 7
#define DSP_DID_DIVA_SERVER_PRI_2M_RX 8
#define DSP_DID_DIVA_SERVER_PRI_30M 9
#define DSP_DID_TASK_HSCX 100
#define DSP_DID_TASK_HSCX_PRI_2M_TX 101
#define DSP_DID_TASK_HSCX_PRI_2M_RX 102
#define DSP_DID_TASK_V110KRNL 200
#define DSP_DID_OVERLAY_V1100 201
#define DSP_DID_OVERLAY_V1101 202
#define DSP_DID_OVERLAY_V1102 203
#define DSP_DID_OVERLAY_V1103 204
#define DSP_DID_OVERLAY_V1104 205
#define DSP_DID_OVERLAY_V1105 206
#define DSP_DID_OVERLAY_V1106 207
#define DSP_DID_OVERLAY_V1107 208
#define DSP_DID_OVERLAY_V1108 209
#define DSP_DID_OVERLAY_V1109 210
#define DSP_DID_TASK_V110_PRI_2M_TX 220
#define DSP_DID_TASK_V110_PRI_2M_RX 221
#define DSP_DID_TASK_MODEM 300
#define DSP_DID_TASK_FAX05 400
#define DSP_DID_TASK_VOICE 500
#define DSP_DID_TASK_TIKRNL81 600
#define DSP_DID_OVERLAY_DIAL 601
#define DSP_DID_OVERLAY_V22 602
#define DSP_DID_OVERLAY_V32 603
#define DSP_DID_OVERLAY_FSK 604
#define DSP_DID_OVERLAY_FAX 605
#define DSP_DID_OVERLAY_VXX 606
#define DSP_DID_OVERLAY_V8 607
#define DSP_DID_OVERLAY_INFO 608
#define DSP_DID_OVERLAY_V34 609
#define DSP_DID_OVERLAY_DFX 610
#define DSP_DID_PARTIAL_OVERLAY_DIAL 611
#define DSP_DID_PARTIAL_OVERLAY_FSK 612
#define DSP_DID_PARTIAL_OVERLAY_FAX 613
#define DSP_DID_TASK_TIKRNL05 700
/*---------------------------------------------------------------------------*/
#endif
/*---------------------------------------------------------------------------*/
drivers/isdn/eicon/eicon.h
deleted
100644 → 0
View file @
f69c2d56
/* $Id: eicon.h,v 1.1.4.1.2.3 2002/10/01 11:29:13 armin Exp $
*
* ISDN low-level module for Eicon active ISDN-Cards.
*
* Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
* Copyright 1998-2000 by Armin Schindler (mac@melware.de)
* Copyright 1999,2000 Cytronics & Melware (info@melware.de)
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#ifndef eicon_h
#define eicon_h
#include <linux/interrupt.h>
#define EICON_IOCTL_SETMMIO 0
#define EICON_IOCTL_GETMMIO 1
#define EICON_IOCTL_SETIRQ 2
#define EICON_IOCTL_GETIRQ 3
#define EICON_IOCTL_LOADBOOT 4
#define EICON_IOCTL_ADDCARD 5
#define EICON_IOCTL_GETTYPE 6
#define EICON_IOCTL_LOADPCI 7
#define EICON_IOCTL_LOADISA 8
#define EICON_IOCTL_GETVER 9
#define EICON_IOCTL_GETXLOG 10
#define EICON_IOCTL_MANIF 90
#define EICON_IOCTL_FREEIT 97
#define EICON_IOCTL_TEST 98
#define EICON_IOCTL_DEBUGVAR 99
#define EICON_IOCTL_DIA_OFFSET 100
/* Bus types */
#define EICON_BUS_ISA 1
#define EICON_BUS_MCA 2
#define EICON_BUS_PCI 3
/* Constants for describing Card-Type */
#define EICON_CTYPE_S 0
#define EICON_CTYPE_SX 1
#define EICON_CTYPE_SCOM 2
#define EICON_CTYPE_QUADRO 3
#define EICON_CTYPE_S2M 4
#define EICON_CTYPE_MAESTRA 5
#define EICON_CTYPE_MAESTRAQ 6
#define EICON_CTYPE_MAESTRAQ_U 7
#define EICON_CTYPE_MAESTRAP 8
#define EICON_CTYPE_ISABRI 0x10
#define EICON_CTYPE_ISAPRI 0x20
#define EICON_CTYPE_MASK 0x0f
#define EICON_CTYPE_QUADRO_NR(n) (n<<4)
#define MAX_HEADER_LEN 10
#define MAX_STATUS_BUFFER 150
/* Struct for adding new cards */
typedef
struct
eicon_cdef
{
int
membase
;
int
irq
;
char
id
[
10
];
}
eicon_cdef
;
#define EICON_ISA_BOOT_MEMCHK 1
#define EICON_ISA_BOOT_NORMAL 2
/* Struct for downloading protocol via ioctl for ISA cards */
/* same struct for downloading protocol via ioctl for MCA cards */
typedef
struct
{
/* start-up parameters */
unsigned
char
tei
;
unsigned
char
nt2
;
unsigned
char
skip1
;
unsigned
char
WatchDog
;
unsigned
char
Permanent
;
unsigned
char
XInterface
;
unsigned
char
StableL2
;
unsigned
char
NoOrderCheck
;
unsigned
char
HandsetType
;
unsigned
char
skip2
;
unsigned
char
LowChannel
;
unsigned
char
ProtVersion
;
unsigned
char
Crc4
;
unsigned
char
Loopback
;
unsigned
char
oad
[
32
];
unsigned
char
osa
[
32
];
unsigned
char
spid
[
32
];
unsigned
char
boot_opt
;
unsigned
long
bootstrap_len
;
unsigned
long
firmware_len
;
unsigned
char
code
[
1
];
/* Rest (bootstrap- and firmware code) will be allocated */
}
eicon_isa_codebuf
;
/* Data for downloading protocol via ioctl */
typedef
union
{
eicon_isa_codebuf
isa
;
eicon_isa_codebuf
mca
;
}
eicon_codebuf
;
/* Data for Management interface */
typedef
struct
{
int
count
;
int
pos
;
int
length
[
50
];
unsigned
char
data
[
700
];
}
eicon_manifbuf
;
#define TRACE_OK (1)
#ifdef __KERNEL__
/* Kernel includes */
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h>
#include <linux/skbuff.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/major.h>
#include <asm/io.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/ioport.h>
#include <linux/timer.h>
#include <linux/wait.h>
#include <linux/delay.h>
#include <linux/ctype.h>
#include <linux/pci.h>
#include <linux/isdn.h>
#include <linux/isdnif.h>
typedef
struct
{
__u16
length
__attribute__
((
packed
));
/* length of data/parameter field */
__u8
P
[
1
];
/* data/parameter field */
}
eicon_PBUFFER
;
#include "eicon_isa.h"
#include "idi.h"
typedef
struct
{
__u16
NextReq
__attribute__
((
packed
));
/* pointer to next Req Buffer */
__u16
NextRc
__attribute__
((
packed
));
/* pointer to next Rc Buffer */
__u16
NextInd
__attribute__
((
packed
));
/* pointer to next Ind Buffer */
__u8
ReqInput
__attribute__
((
packed
));
/* number of Req Buffers sent */
__u8
ReqOutput
__attribute__
((
packed
));
/* number of Req Buffers returned */
__u8
ReqReserved
__attribute__
((
packed
));
/*number of Req Buffers reserved */
__u8
Int
__attribute__
((
packed
));
/* ISDN-P interrupt */
__u8
XLock
__attribute__
((
packed
));
/* Lock field for arbitration */
__u8
RcOutput
__attribute__
((
packed
));
/* number of Rc buffers received */
__u8
IndOutput
__attribute__
((
packed
));
/* number of Ind buffers received */
__u8
IMask
__attribute__
((
packed
));
/* Interrupt Mask Flag */
__u8
Reserved1
[
2
]
__attribute__
((
packed
));
/* reserved field, do not use */
__u8
ReadyInt
__attribute__
((
packed
));
/* request field for ready int */
__u8
Reserved2
[
12
]
__attribute__
((
packed
));
/* reserved field, do not use */
__u8
InterfaceType
__attribute__
((
packed
));
/* interface type 1=16K */
__u16
Signature
__attribute__
((
packed
));
/* ISDN-P initialized ind */
__u8
B
[
1
];
/* buffer space for Req,Ind and Rc */
}
eicon_pr_ram
;
/* Macro for delay via schedule() */
#define SLEEP(j) { \
set_current_state(TASK_UNINTERRUPTIBLE); \
schedule_timeout(j); \
}
typedef
struct
{
__u8
Req
;
/* pending request */
__u8
Rc
;
/* return code received */
__u8
Ind
;
/* indication received */
__u8
ReqCh
;
/* channel of current Req */
__u8
RcCh
;
/* channel of current Rc */
__u8
IndCh
;
/* channel of current Ind */
__u8
D3Id
;
/* ID used by this entity */
__u8
B2Id
;
/* ID used by this entity */
__u8
GlobalId
;
/* reserved field */
__u8
XNum
;
/* number of X-buffers */
__u8
RNum
;
/* number of R-buffers */
struct
sk_buff_head
X
;
/* X-buffer queue */
struct
sk_buff_head
R
;
/* R-buffer queue */
__u8
RNR
;
/* receive not ready flag */
__u8
complete
;
/* receive complete status */
__u8
busy
;
/* busy flag */
__u16
ref
;
/* saved reference */
}
entity
;
#define FAX_MAX_SCANLINE 256
typedef
struct
{
__u8
PrevObject
;
__u8
NextObject
;
__u8
abLine
[
FAX_MAX_SCANLINE
];
__u8
abFrame
[
FAX_MAX_SCANLINE
];
unsigned
int
LineLen
;
unsigned
int
LineDataLen
;
__u32
LineData
;
unsigned
int
NullBytesPos
;
__u8
NullByteExist
;
int
PageCount
;
__u8
Dle
;
__u8
Eop
;
}
eicon_ch_fax_buf
;
typedef
struct
{
int
No
;
/* Channel Number */
unsigned
short
fsm_state
;
/* Current D-Channel state */
unsigned
short
statectrl
;
/* State controling bits */
unsigned
short
eazmask
;
/* EAZ-Mask for this Channel */
int
queued
;
/* User-Data Bytes in TX queue */
int
pqueued
;
/* User-Data Packets in TX queue */
int
waitq
;
/* User-Data Bytes in wait queue */
int
waitpq
;
/* User-Data Bytes in packet queue */
struct
sk_buff
*
tskb1
;
/* temp skb 1 */
struct
sk_buff
*
tskb2
;
/* temp skb 2 */
unsigned
char
l2prot
;
/* Layer 2 protocol */
unsigned
char
l3prot
;
/* Layer 3 protocol */
#ifdef CONFIG_ISDN_TTY_FAX
T30_s
*
fax
;
/* pointer to fax data in LL */
eicon_ch_fax_buf
fax2
;
/* fax related struct */
#endif
entity
e
;
/* Native Entity */
ENTITY
de
;
/* Divas D Entity */
ENTITY
be
;
/* Divas B Entity */
char
cpn
[
32
];
/* remember cpn */
char
oad
[
32
];
/* remember oad */
char
dsa
[
32
];
/* remember dsa */
char
osa
[
32
];
/* remember osa */
unsigned
char
cause
[
2
];
/* Last Cause */
unsigned
char
si1
;
unsigned
char
si2
;
unsigned
char
plan
;
unsigned
char
screen
;
}
eicon_chan
;
typedef
struct
{
eicon_chan
*
ptr
;
}
eicon_chan_ptr
;
#include "eicon_pci.h"
#define EICON_FLAGS_RUNNING 1
/* Cards driver activated */
#define EICON_FLAGS_PVALID 2
/* Cards port is valid */
#define EICON_FLAGS_IVALID 4
/* Cards irq is valid */
#define EICON_FLAGS_MVALID 8
/* Cards membase is valid */
#define EICON_FLAGS_LOADED 8
/* Firmware loaded */
/* D-Channel states */
#define EICON_STATE_NULL 0
#define EICON_STATE_ICALL 1
#define EICON_STATE_OCALL 2
#define EICON_STATE_IWAIT 3
#define EICON_STATE_OWAIT 4
#define EICON_STATE_IBWAIT 5
#define EICON_STATE_OBWAIT 6
#define EICON_STATE_BWAIT 7
#define EICON_STATE_BHWAIT 8
#define EICON_STATE_BHWAIT2 9
#define EICON_STATE_DHWAIT 10
#define EICON_STATE_DHWAIT2 11
#define EICON_STATE_BSETUP 12
#define EICON_STATE_ACTIVE 13
#define EICON_STATE_ICALLW 14
#define EICON_STATE_LISTEN 15
#define EICON_STATE_WMCONN 16
#define EICON_MAX_QUEUE 2138
typedef
union
{
eicon_isa_card
isa
;
eicon_pci_card
pci
;
eicon_isa_card
mca
;
}
eicon_hwif
;
typedef
struct
{
__u8
ret
;
__u8
id
;
__u8
ch
;
}
eicon_ack
;
typedef
struct
{
__u8
code
;
__u8
id
;
__u8
ch
;
}
eicon_req
;
typedef
struct
{
__u8
ret
;
__u8
id
;
__u8
ch
;
__u8
more
;
}
eicon_indhdr
;
/*
* Per card driver data
*/
typedef
struct
eicon_card
{
eicon_hwif
hwif
;
/* Hardware dependent interface */
DESCRIPTOR
*
d
;
/* IDI Descriptor */
u_char
ptype
;
/* Protocol type (1TR6 or Euro) */
u_char
bus
;
/* Bustype (ISA, MCA, PCI) */
u_char
type
;
/* Cardtype (EICON_CTYPE_...) */
struct
eicon_card
*
qnext
;
/* Pointer to next quadro adapter */
int
Feature
;
/* Protocol Feature Value */
struct
eicon_card
*
next
;
/* Pointer to next device struct */
int
myid
;
/* Driver-Nr. assigned by linklevel */
unsigned
long
flags
;
/* Statusflags */
struct
sk_buff_head
rcvq
;
/* Receive-Message queue */
struct
sk_buff_head
sndq
;
/* Send-Message queue */
struct
sk_buff_head
rackq
;
/* Req-Ack-Message queue */
struct
sk_buff_head
sackq
;
/* Data-Ack-Message queue */
struct
sk_buff_head
statq
;
/* Status-Message queue */
int
statq_entries
;
struct
tasklet_struct
snd_tq
;
/* Task struct for xmit bh */
struct
tasklet_struct
rcv_tq
;
/* Task struct for rcv bh */
struct
tasklet_struct
ack_tq
;
/* Task struct for ack bh */
eicon_chan
*
IdTable
[
256
];
/* Table to find entity */
__u16
ref_in
;
__u16
ref_out
;
int
nchannels
;
/* Number of B-Channels */
int
ReadyInt
;
/* Ready Interrupt */
eicon_chan
*
bch
;
/* B-Channel status/control */
DBUFFER
*
dbuf
;
/* Dbuffer for Diva Server */
BUFFERS
*
sbuf
;
/* Buffer for Diva Server */
char
*
sbufp
;
/* Data Buffer for Diva Server */
isdn_if
interface
;
/* Interface to upper layer */
char
regname
[
35
];
/* Drivers card name */
#ifdef CONFIG_MCA
int
mca_slot
;
/* # of cards MCA slot */
int
mca_io
;
/* MCA cards IO port */
#endif
/* CONFIG_MCA */
}
eicon_card
;
#include "eicon_idi.h"
extern
eicon_card
*
cards
;
extern
char
*
eicon_ctype_name
[];
extern
__inline__
void
eicon_schedule_tx
(
eicon_card
*
card
)
{
tasklet_schedule
(
&
card
->
snd_tq
);
}
extern
__inline__
void
eicon_schedule_rx
(
eicon_card
*
card
)
{
tasklet_schedule
(
&
card
->
rcv_tq
);
}
extern
__inline__
void
eicon_schedule_ack
(
eicon_card
*
card
)
{
tasklet_schedule
(
&
card
->
ack_tq
);
}
extern
int
eicon_addcard
(
int
,
int
,
int
,
char
*
,
int
);
extern
void
eicon_io_transmit
(
eicon_card
*
card
);
extern
irqreturn_t
eicon_irq
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
);
extern
void
eicon_io_rcv_dispatch
(
eicon_card
*
ccard
);
extern
void
eicon_io_ack_dispatch
(
eicon_card
*
ccard
);
#ifdef CONFIG_MCA
extern
int
eicon_mca_find_card
(
int
,
int
,
int
,
char
*
);
extern
int
eicon_mca_probe
(
int
,
int
,
int
,
int
,
char
*
);
extern
int
eicon_info
(
char
*
,
int
,
void
*
);
#endif
/* CONFIG_MCA */
extern
ulong
DebugVar
;
extern
void
eicon_log
(
eicon_card
*
card
,
int
level
,
const
char
*
fmt
,
...);
extern
void
eicon_putstatus
(
eicon_card
*
card
,
char
*
buf
);
extern
spinlock_t
eicon_lock
;
#endif
/* __KERNEL__ */
#endif
/* eicon_h */
drivers/isdn/eicon/eicon_dsp.h
deleted
100644 → 0
View file @
f69c2d56
/* $Id: eicon_dsp.h,v 1.1.4.1.2.2 2002/10/01 11:29:13 armin Exp $
*
* ISDN lowlevel-module for Eicon active cards.
* DSP definitions
*
* Copyright 1999,2000 by Armin Schindler (mac@melware.de)
* Copyright 1999,2000 Cytronics & Melware (info@melware.de)
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#ifndef DSP_H
#define DSP_H
#include "dsp_defs.h"
#define DSP_UDATA_REQUEST_SWITCH_FRAMER 1
/*
parameters:
<byte> transmit framer type
<byte> receive framer type
*/
#define DSP_REQUEST_SWITCH_FRAMER_HDLC 0
#define DSP_REQUEST_SWITCH_FRAMER_TRANSPARENT 1
#define DSP_REQUEST_SWITCH_FRAMER_ASYNC 2
#define DSP_UDATA_REQUEST_CLEARDOWN 2
/*
parameters:
- none -
*/
#define DSP_UDATA_REQUEST_TX_CONFIRMATION_ON 3
/*
parameters:
- none -
*/
#define DSP_UDATA_REQUEST_TX_CONFIRMATION_OFF 4
/*
parameters:
- none -
*/
typedef
struct
eicon_dsp_ind
{
__u16
time
__attribute__
((
packed
));
__u8
norm
__attribute__
((
packed
));
__u16
options
__attribute__
((
packed
));
__u32
speed
__attribute__
((
packed
));
__u16
delay
__attribute__
((
packed
));
__u32
txspeed
__attribute__
((
packed
));
__u32
rxspeed
__attribute__
((
packed
));
}
eicon_dsp_ind
;
#define DSP_CONNECTED_OPTION_V42_TRANS 0x0002
#define DSP_CONNECTED_OPTION_V42_LAPM 0x0004
#define DSP_CONNECTED_OPTION_SHORT_TRAIN 0x0008
#define DSP_CONNECTED_OPTION_TALKER_ECHO_PROTECT 0x0010
#define DSP_UDATA_INDICATION_DISCONNECT 5
/*
returns:
<byte> cause
*/
#define DSP_DISCONNECT_CAUSE_NONE 0x00
#define DSP_DISCONNECT_CAUSE_BUSY_TONE 0x01
#define DSP_DISCONNECT_CAUSE_CONGESTION_TONE 0x02
#define DSP_DISCONNECT_CAUSE_INCOMPATIBILITY 0x03
#define DSP_DISCONNECT_CAUSE_CLEARDOWN 0x04
#define DSP_DISCONNECT_CAUSE_TRAINING_TIMEOUT 0x05
#define DSP_UDATA_INDICATION_TX_CONFIRMATION 6
/*
returns:
<word> confirmation number
*/
#define DSP_UDATA_REQUEST_SEND_DTMF_DIGITS 16
/*
parameters:
<word> tone duration (ms)
<word> gap duration (ms)
<byte> digit 0 tone code
...
<byte> digit n tone code
*/
#define DSP_SEND_DTMF_DIGITS_HEADER_LENGTH 5
#define DSP_DTMF_DIGIT_TONE_LOW_GROUP_697_HZ 0x00
#define DSP_DTMF_DIGIT_TONE_LOW_GROUP_770_HZ 0x01
#define DSP_DTMF_DIGIT_TONE_LOW_GROUP_852_HZ 0x02
#define DSP_DTMF_DIGIT_TONE_LOW_GROUP_941_HZ 0x03
#define DSP_DTMF_DIGIT_TONE_LOW_GROUP_MASK 0x03
#define DSP_DTMF_DIGIT_TONE_HIGH_GROUP_1209_HZ 0x00
#define DSP_DTMF_DIGIT_TONE_HIGH_GROUP_1336_HZ 0x04
#define DSP_DTMF_DIGIT_TONE_HIGH_GROUP_1477_HZ 0x08
#define DSP_DTMF_DIGIT_TONE_HIGH_GROUP_1633_HZ 0x0c
#define DSP_DTMF_DIGIT_TONE_HIGH_GROUP_MASK 0x0c
#define DSP_DTMF_DIGIT_TONE_CODE_0 0x07
#define DSP_DTMF_DIGIT_TONE_CODE_1 0x00
#define DSP_DTMF_DIGIT_TONE_CODE_2 0x04
#define DSP_DTMF_DIGIT_TONE_CODE_3 0x08
#define DSP_DTMF_DIGIT_TONE_CODE_4 0x01
#define DSP_DTMF_DIGIT_TONE_CODE_5 0x05
#define DSP_DTMF_DIGIT_TONE_CODE_6 0x09
#define DSP_DTMF_DIGIT_TONE_CODE_7 0x02
#define DSP_DTMF_DIGIT_TONE_CODE_8 0x06
#define DSP_DTMF_DIGIT_TONE_CODE_9 0x0a
#define DSP_DTMF_DIGIT_TONE_CODE_STAR 0x03
#define DSP_DTMF_DIGIT_TONE_CODE_HASHMARK 0x0b
#define DSP_DTMF_DIGIT_TONE_CODE_A 0x0c
#define DSP_DTMF_DIGIT_TONE_CODE_B 0x0d
#define DSP_DTMF_DIGIT_TONE_CODE_C 0x0e
#define DSP_DTMF_DIGIT_TONE_CODE_D 0x0f
#define DSP_UDATA_INDICATION_DTMF_DIGITS_SENT 16
/*
returns:
- none -
One indication will be sent for every request.
*/
#define DSP_UDATA_REQUEST_ENABLE_DTMF_RECEIVER 17
/*
parameters:
<word> tone duration (ms)
<word> gap duration (ms)
*/
typedef
struct
enable_dtmf_s
{
__u16
tone
;
__u16
gap
;
}
enable_dtmf_s
;
#define DSP_UDATA_REQUEST_DISABLE_DTMF_RECEIVER 18
/*
parameters:
- none -
*/
#define DSP_UDATA_INDICATION_DTMF_DIGITS_RECEIVED 17
/*
returns:
<byte> digit 0 tone code
...
<byte> digit n tone code
*/
#define DSP_DTMF_DIGITS_RECEIVED_HEADER_LENGTH 1
#define DSP_UDATA_INDICATION_MODEM_CALLING_TONE 18
/*
returns:
- none -
*/
#define DSP_UDATA_INDICATION_FAX_CALLING_TONE 19
/*
returns:
- none -
*/
#define DSP_UDATA_INDICATION_ANSWER_TONE 20
/*
returns:
- none -
*/
/* ============= FAX ================ */
#define EICON_FAXID_LEN 20
typedef
struct
eicon_t30_s
{
__u8
code
;
__u8
rate
;
__u8
resolution
;
__u8
format
;
__u8
pages_low
;
__u8
pages_high
;
__u8
atf
;
__u8
control_bits_low
;
__u8
control_bits_high
;
__u8
feature_bits_low
;
__u8
feature_bits_high
;
__u8
universal_5
;
__u8
universal_6
;
__u8
universal_7
;
__u8
station_id_len
;
__u8
head_line_len
;
__u8
station_id
[
EICON_FAXID_LEN
];
/* __u8 head_line[]; */
}
eicon_t30_s
;
/* EDATA transmit messages */
#define EDATA_T30_DIS 0x01
#define EDATA_T30_FTT 0x02
#define EDATA_T30_MCF 0x03
/* EDATA receive messages */
#define EDATA_T30_DCS 0x81
#define EDATA_T30_TRAIN_OK 0x82
#define EDATA_T30_EOP 0x83
#define EDATA_T30_MPS 0x84
#define EDATA_T30_EOM 0x85
#define EDATA_T30_DTC 0x86
#define T30_FORMAT_SFF 0
#define T30_FORMAT_ASCII 1
#define T30_FORMAT_COUNT 2
#define T30_CONTROL_BIT_DISABLE_FINE 0x0001
#define T30_CONTROL_BIT_ENABLE_ECM 0x0002
#define T30_CONTROL_BIT_ECM_64_BYTES 0x0004
#define T30_CONTROL_BIT_ENABLE_2D_CODING 0x0008
#define T30_CONTROL_BIT_ENABLE_T6_CODING 0x0010
#define T30_CONTROL_BIT_ENABLE_UNCOMPR 0x0020
#define T30_CONTROL_BIT_ACCEPT_POLLING 0x0040
#define T30_CONTROL_BIT_REQUEST_POLLING 0x0080
#define T30_CONTROL_BIT_MORE_DOCUMENTS 0x0100
#define T30_CONTROL_BIT_ALL_FEATURES\
(T30_CONTROL_BIT_ENABLE_ECM | T30_CONTROL_BIT_ENABLE_2D_CODING |\
T30_CONTROL_BIT_ENABLE_T6_CODING | T30_CONTROL_BIT_ENABLE_UNCOMPR)
#define T30_FEATURE_BIT_FINE 0x0001
#define T30_FEATURE_BIT_ECM 0x0002
#define T30_FEATURE_BIT_ECM_64_BYTES 0x0004
#define T30_FEATURE_BIT_2D_CODING 0x0008
#define T30_FEATURE_BIT_T6_CODING 0x0010
#define T30_FEATURE_BIT_UNCOMPR_ENABLED 0x0020
#define T30_FEATURE_BIT_POLLING 0x0040
#define FAX_OBJECT_DOCU 1
#define FAX_OBJECT_PAGE 2
#define FAX_OBJECT_LINE 3
#define T4_EOL 0x800
#define T4_EOL_BITSIZE 12
#define T4_EOL_DWORD (T4_EOL << (32 - T4_EOL_BITSIZE))
#define T4_EOL_MASK_DWORD ((__u32) -1 << (32 - T4_EOL_BITSIZE))
#define SFF_LEN_FLD_SIZE 3
#define _DLE_ 0x10
#define _ETX_ 0x03
typedef
struct
eicon_sff_dochead
{
__u32
id
__attribute__
((
packed
));
__u8
version
__attribute__
((
packed
));
__u8
reserved1
__attribute__
((
packed
));
__u16
userinfo
__attribute__
((
packed
));
__u16
pagecount
__attribute__
((
packed
));
__u16
off1pagehead
__attribute__
((
packed
));
__u32
offnpagehead
__attribute__
((
packed
));
__u32
offdocend
__attribute__
((
packed
));
}
eicon_sff_dochead
;
typedef
struct
eicon_sff_pagehead
{
__u8
pageheadid
__attribute__
((
packed
));
__u8
pageheadlen
__attribute__
((
packed
));
__u8
resvert
__attribute__
((
packed
));
__u8
reshoriz
__attribute__
((
packed
));
__u8
coding
__attribute__
((
packed
));
__u8
reserved2
__attribute__
((
packed
));
__u16
linelength
__attribute__
((
packed
));
__u16
pagelength
__attribute__
((
packed
));
__u32
offprevpage
__attribute__
((
packed
));
__u32
offnextpage
__attribute__
((
packed
));
}
eicon_sff_pagehead
;
#endif
/* DSP_H */
drivers/isdn/eicon/eicon_idi.c
deleted
100644 → 0
View file @
f69c2d56
/* $Id: eicon_idi.c,v 1.1.4.1.2.4 2002/10/01 11:29:13 armin Exp $
*
* ISDN lowlevel-module for Eicon active cards.
* IDI interface
*
* Copyright 1998-2000 by Armin Schindler (mac@melware.de)
* Copyright 1999,2000 Cytronics & Melware (info@melware.de)
*
* Thanks to Deutsche Mailbox Saar-Lor-Lux GmbH
* for sponsoring and testing fax
* capabilities with Diva Server cards.
* (dor@deutschemailbox.de)
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include <linux/config.h>
#include "eicon.h"
#include "eicon_idi.h"
#include "eicon_dsp.h"
#include "uxio.h"
#undef EICON_FULL_SERVICE_OKTETT
char
*
eicon_idi_revision
=
"$Revision: 1.1.4.1.2.4 $"
;
eicon_manifbuf
*
manbuf
;
int
eicon_idi_manage_assign
(
eicon_card
*
card
);
int
eicon_idi_manage_remove
(
eicon_card
*
card
);
int
idi_fill_in_T30
(
eicon_chan
*
chan
,
unsigned
char
*
buffer
);
int
idi_assign_req
(
eicon_REQ
*
reqbuf
,
int
signet
,
eicon_chan
*
chan
)
{
int
l
=
0
;
int
tmp
;
tmp
=
0
;
if
(
!
signet
)
{
/* Signal Layer */
reqbuf
->
XBuffer
.
P
[
l
++
]
=
CAI
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
1
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
0
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
KEY
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
3
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
'I'
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
'4'
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
'L'
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
SHIFT
|
6
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
SIN
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
2
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
0
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
0
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
0
;
/* end */
reqbuf
->
Req
=
ASSIGN
;
reqbuf
->
ReqCh
=
0
;
reqbuf
->
ReqId
=
DSIG_ID
;
reqbuf
->
XBuffer
.
length
=
l
;
reqbuf
->
Reference
=
0
;
/* Sig Entity */
}
else
{
/* Network Layer */
reqbuf
->
XBuffer
.
P
[
l
++
]
=
CAI
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
1
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
chan
->
e
.
D3Id
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
LLC
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
2
;
switch
(
chan
->
l2prot
)
{
case
ISDN_PROTO_L2_V11096
:
case
ISDN_PROTO_L2_V11019
:
case
ISDN_PROTO_L2_V11038
:
case
ISDN_PROTO_L2_TRANS
:
reqbuf
->
XBuffer
.
P
[
l
++
]
=
2
;
/* transparent */
break
;
case
ISDN_PROTO_L2_X75I
:
case
ISDN_PROTO_L2_X75UI
:
case
ISDN_PROTO_L2_X75BUI
:
reqbuf
->
XBuffer
.
P
[
l
++
]
=
5
;
/* X.75 */
break
;
case
ISDN_PROTO_L2_MODEM
:
if
(
chan
->
fsm_state
==
EICON_STATE_IWAIT
)
reqbuf
->
XBuffer
.
P
[
l
++
]
=
9
;
/* V.42 incoming */
else
reqbuf
->
XBuffer
.
P
[
l
++
]
=
10
;
/* V.42 */
break
;
case
ISDN_PROTO_L2_HDLC
:
case
ISDN_PROTO_L2_FAX
:
if
(
chan
->
fsm_state
==
EICON_STATE_IWAIT
)
reqbuf
->
XBuffer
.
P
[
l
++
]
=
3
;
/* autoconnect on incoming */
else
reqbuf
->
XBuffer
.
P
[
l
++
]
=
2
;
/* transparent */
break
;
default:
reqbuf
->
XBuffer
.
P
[
l
++
]
=
1
;
}
switch
(
chan
->
l3prot
)
{
case
ISDN_PROTO_L3_FCLASS2
:
#ifdef CONFIG_ISDN_TTY_FAX
reqbuf
->
XBuffer
.
P
[
l
++
]
=
6
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
NLC
;
tmp
=
idi_fill_in_T30
(
chan
,
&
reqbuf
->
XBuffer
.
P
[
l
+
1
]);
reqbuf
->
XBuffer
.
P
[
l
++
]
=
tmp
;
l
+=
tmp
;
break
;
#endif
case
ISDN_PROTO_L3_TRANS
:
default:
reqbuf
->
XBuffer
.
P
[
l
++
]
=
4
;
}
reqbuf
->
XBuffer
.
P
[
l
++
]
=
0
;
/* end */
reqbuf
->
Req
=
ASSIGN
;
reqbuf
->
ReqCh
=
0
;
reqbuf
->
ReqId
=
NL_ID
;
reqbuf
->
XBuffer
.
length
=
l
;
reqbuf
->
Reference
=
1
;
/* Net Entity */
}
return
(
0
);
}
int
idi_put_req
(
eicon_REQ
*
reqbuf
,
int
rq
,
int
signet
,
int
Ch
)
{
reqbuf
->
Req
=
rq
;
reqbuf
->
ReqCh
=
Ch
;
reqbuf
->
ReqId
=
1
;
reqbuf
->
XBuffer
.
length
=
1
;
reqbuf
->
XBuffer
.
P
[
0
]
=
0
;
reqbuf
->
Reference
=
signet
;
return
(
0
);
}
int
idi_put_suspend_req
(
eicon_REQ
*
reqbuf
,
eicon_chan
*
chan
)
{
reqbuf
->
Req
=
SUSPEND
;
reqbuf
->
ReqCh
=
0
;
reqbuf
->
ReqId
=
1
;
reqbuf
->
XBuffer
.
P
[
0
]
=
CAI
;
reqbuf
->
XBuffer
.
P
[
1
]
=
1
;
reqbuf
->
XBuffer
.
P
[
2
]
=
chan
->
No
;
reqbuf
->
XBuffer
.
P
[
3
]
=
0
;
reqbuf
->
XBuffer
.
length
=
4
;
reqbuf
->
Reference
=
0
;
/* Sig Entity */
return
(
0
);
}
int
idi_call_res_req
(
eicon_REQ
*
reqbuf
,
eicon_chan
*
chan
)
{
int
l
=
9
;
reqbuf
->
Req
=
CALL_RES
;
reqbuf
->
ReqCh
=
0
;
reqbuf
->
ReqId
=
1
;
reqbuf
->
XBuffer
.
P
[
0
]
=
CAI
;
reqbuf
->
XBuffer
.
P
[
1
]
=
6
;
reqbuf
->
XBuffer
.
P
[
2
]
=
9
;
reqbuf
->
XBuffer
.
P
[
3
]
=
0
;
reqbuf
->
XBuffer
.
P
[
4
]
=
0
;
reqbuf
->
XBuffer
.
P
[
5
]
=
0
;
reqbuf
->
XBuffer
.
P
[
6
]
=
32
;
reqbuf
->
XBuffer
.
P
[
7
]
=
0
;
switch
(
chan
->
l2prot
)
{
case
ISDN_PROTO_L2_X75I
:
case
ISDN_PROTO_L2_X75UI
:
case
ISDN_PROTO_L2_X75BUI
:
case
ISDN_PROTO_L2_HDLC
:
reqbuf
->
XBuffer
.
P
[
1
]
=
1
;
reqbuf
->
XBuffer
.
P
[
2
]
=
0x05
;
l
=
4
;
break
;
case
ISDN_PROTO_L2_V11096
:
reqbuf
->
XBuffer
.
P
[
2
]
=
0x0d
;
reqbuf
->
XBuffer
.
P
[
3
]
=
5
;
reqbuf
->
XBuffer
.
P
[
4
]
=
0
;
break
;
case
ISDN_PROTO_L2_V11019
:
reqbuf
->
XBuffer
.
P
[
2
]
=
0x0d
;
reqbuf
->
XBuffer
.
P
[
3
]
=
6
;
reqbuf
->
XBuffer
.
P
[
4
]
=
0
;
break
;
case
ISDN_PROTO_L2_V11038
:
reqbuf
->
XBuffer
.
P
[
2
]
=
0x0d
;
reqbuf
->
XBuffer
.
P
[
3
]
=
7
;
reqbuf
->
XBuffer
.
P
[
4
]
=
0
;
break
;
case
ISDN_PROTO_L2_MODEM
:
reqbuf
->
XBuffer
.
P
[
2
]
=
0x11
;
reqbuf
->
XBuffer
.
P
[
3
]
=
7
;
reqbuf
->
XBuffer
.
P
[
4
]
=
0
;
reqbuf
->
XBuffer
.
P
[
5
]
=
0
;
reqbuf
->
XBuffer
.
P
[
6
]
=
128
;
reqbuf
->
XBuffer
.
P
[
7
]
=
0
;
break
;
case
ISDN_PROTO_L2_FAX
:
reqbuf
->
XBuffer
.
P
[
2
]
=
0x10
;
reqbuf
->
XBuffer
.
P
[
3
]
=
0
;
reqbuf
->
XBuffer
.
P
[
4
]
=
0
;
reqbuf
->
XBuffer
.
P
[
5
]
=
0
;
reqbuf
->
XBuffer
.
P
[
6
]
=
128
;
reqbuf
->
XBuffer
.
P
[
7
]
=
0
;
break
;
case
ISDN_PROTO_L2_TRANS
:
switch
(
chan
->
l3prot
)
{
case
ISDN_PROTO_L3_TRANSDSP
:
reqbuf
->
XBuffer
.
P
[
2
]
=
22
;
/* DTMF, audio events on */
}
break
;
}
reqbuf
->
XBuffer
.
P
[
8
]
=
0
;
reqbuf
->
XBuffer
.
length
=
l
;
reqbuf
->
Reference
=
0
;
/* Sig Entity */
eicon_log
(
NULL
,
8
,
"idi_req: Ch%d: Call_Res
\n
"
,
chan
->
No
);
return
(
0
);
}
int
idi_do_req
(
eicon_card
*
card
,
eicon_chan
*
chan
,
int
cmd
,
int
layer
)
{
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb2
;
eicon_REQ
*
reqbuf
;
eicon_chan_ptr
*
chan2
;
skb
=
alloc_skb
(
270
+
sizeof
(
eicon_REQ
),
GFP_ATOMIC
);
skb2
=
alloc_skb
(
sizeof
(
eicon_chan_ptr
),
GFP_ATOMIC
);
if
((
!
skb
)
||
(
!
skb2
))
{
eicon_log
(
card
,
1
,
"idi_err: Ch%d: alloc_skb failed in do_req()
\n
"
,
chan
->
No
);
if
(
skb
)
dev_kfree_skb
(
skb
);
if
(
skb2
)
dev_kfree_skb
(
skb2
);
return
-
ENOMEM
;
}
chan2
=
(
eicon_chan_ptr
*
)
skb_put
(
skb2
,
sizeof
(
eicon_chan_ptr
));
chan2
->
ptr
=
chan
;
reqbuf
=
(
eicon_REQ
*
)
skb_put
(
skb
,
270
+
sizeof
(
eicon_REQ
));
eicon_log
(
card
,
8
,
"idi_req: Ch%d: req %x (%s)
\n
"
,
chan
->
No
,
cmd
,
(
layer
)
?
"Net"
:
"Sig"
);
if
(
layer
)
cmd
|=
0x700
;
switch
(
cmd
)
{
case
ASSIGN
:
case
ASSIGN
|
0x700
:
idi_assign_req
(
reqbuf
,
layer
,
chan
);
break
;
case
REMOVE
:
case
REMOVE
|
0x700
:
idi_put_req
(
reqbuf
,
REMOVE
,
layer
,
0
);
break
;
case
INDICATE_REQ
:
idi_put_req
(
reqbuf
,
INDICATE_REQ
,
0
,
0
);
break
;
case
HANGUP
:
idi_put_req
(
reqbuf
,
HANGUP
,
0
,
0
);
break
;
case
SUSPEND
:
idi_put_suspend_req
(
reqbuf
,
chan
);
break
;
case
RESUME
:
idi_put_req
(
reqbuf
,
RESUME
,
0
,
0
);
break
;
case
REJECT
:
idi_put_req
(
reqbuf
,
REJECT
,
0
,
0
);
break
;
case
CALL_ALERT
:
idi_put_req
(
reqbuf
,
CALL_ALERT
,
0
,
0
);
break
;
case
CALL_RES
:
idi_call_res_req
(
reqbuf
,
chan
);
break
;
case
CALL_HOLD
:
idi_put_req
(
reqbuf
,
CALL_HOLD
,
0
,
0
);
break
;
case
N_CONNECT
|
0x700
:
idi_put_req
(
reqbuf
,
N_CONNECT
,
1
,
0
);
break
;
case
N_CONNECT_ACK
|
0x700
:
idi_put_req
(
reqbuf
,
N_CONNECT_ACK
,
1
,
0
);
break
;
case
N_DISC
|
0x700
:
idi_put_req
(
reqbuf
,
N_DISC
,
1
,
chan
->
e
.
IndCh
);
break
;
case
N_DISC_ACK
|
0x700
:
idi_put_req
(
reqbuf
,
N_DISC_ACK
,
1
,
chan
->
e
.
IndCh
);
break
;
default:
eicon_log
(
card
,
1
,
"idi_req: Ch%d: Unknown request
\n
"
,
chan
->
No
);
dev_kfree_skb
(
skb
);
dev_kfree_skb
(
skb2
);
return
(
-
1
);
}
skb_queue_tail
(
&
chan
->
e
.
X
,
skb
);
skb_queue_tail
(
&
card
->
sndq
,
skb2
);
eicon_schedule_tx
(
card
);
return
(
0
);
}
int
eicon_idi_listen_req
(
eicon_card
*
card
,
eicon_chan
*
chan
)
{
if
((
!
card
)
||
(
!
chan
))
return
1
;
eicon_log
(
card
,
16
,
"idi_req: Ch%d: Listen_Req eazmask=0x%x
\n
"
,
chan
->
No
,
chan
->
eazmask
);
if
(
!
chan
->
e
.
D3Id
)
{
idi_do_req
(
card
,
chan
,
ASSIGN
,
0
);
}
if
(
chan
->
fsm_state
==
EICON_STATE_NULL
)
{
if
(
!
(
chan
->
statectrl
&
HAVE_CONN_REQ
))
{
idi_do_req
(
card
,
chan
,
INDICATE_REQ
,
0
);
chan
->
fsm_state
=
EICON_STATE_LISTEN
;
}
}
return
(
0
);
}
unsigned
char
idi_si2bc
(
int
si1
,
int
si2
,
char
*
bc
,
char
*
hlc
)
{
hlc
[
0
]
=
0
;
switch
(
si1
)
{
case
1
:
bc
[
0
]
=
0x90
;
/* 3,1 kHz audio */
bc
[
1
]
=
0x90
;
/* 64 kbit/s */
bc
[
2
]
=
0xa3
;
/* G.711 A-law */
#ifdef EICON_FULL_SERVICE_OKTETT
if
(
si2
==
1
)
{
bc
[
0
]
=
0x80
;
/* Speech */
hlc
[
0
]
=
0x02
;
/* hlc len */
hlc
[
1
]
=
0x91
;
/* first hic */
hlc
[
2
]
=
0x81
;
/* Telephony */
}
#endif
return
(
3
);
case
2
:
bc
[
0
]
=
0x90
;
/* 3,1 kHz audio */
bc
[
1
]
=
0x90
;
/* 64 kbit/s */
bc
[
2
]
=
0xa3
;
/* G.711 A-law */
#ifdef EICON_FULL_SERVICE_OKTETT
if
(
si2
==
2
)
{
hlc
[
0
]
=
0x02
;
/* hlc len */
hlc
[
1
]
=
0x91
;
/* first hic */
hlc
[
2
]
=
0x84
;
/* Fax Gr.2/3 */
}
#endif
return
(
3
);
case
5
:
case
7
:
default:
bc
[
0
]
=
0x88
;
bc
[
1
]
=
0x90
;
return
(
2
);
}
return
(
0
);
}
int
idi_hangup
(
eicon_card
*
card
,
eicon_chan
*
chan
)
{
if
((
!
card
)
||
(
!
chan
))
return
1
;
if
((
chan
->
fsm_state
==
EICON_STATE_ACTIVE
)
||
(
chan
->
fsm_state
==
EICON_STATE_WMCONN
))
{
if
(
chan
->
e
.
B2Id
)
idi_do_req
(
card
,
chan
,
N_DISC
,
1
);
}
if
(
chan
->
e
.
B2Id
)
idi_do_req
(
card
,
chan
,
REMOVE
,
1
);
if
(
chan
->
fsm_state
!=
EICON_STATE_NULL
)
{
chan
->
statectrl
|=
WAITING_FOR_HANGUP
;
idi_do_req
(
card
,
chan
,
HANGUP
,
0
);
chan
->
fsm_state
=
EICON_STATE_NULL
;
}
eicon_log
(
card
,
8
,
"idi_req: Ch%d: Hangup
\n
"
,
chan
->
No
);
#ifdef CONFIG_ISDN_TTY_FAX
chan
->
fax
=
0
;
#endif
return
(
0
);
}
int
capipmsg
(
eicon_card
*
card
,
eicon_chan
*
chan
,
capi_msg
*
cm
)
{
if
((
cm
->
para
[
0
]
!=
3
)
||
(
cm
->
para
[
1
]
!=
0
))
return
-
1
;
if
(
cm
->
para
[
2
]
<
3
)
return
-
1
;
if
(
cm
->
para
[
4
]
!=
0
)
return
-
1
;
switch
(
cm
->
para
[
3
])
{
case
4
:
/* Suspend */
eicon_log
(
card
,
8
,
"idi_req: Ch%d: Call Suspend
\n
"
,
chan
->
No
);
if
(
cm
->
para
[
5
])
{
idi_do_req
(
card
,
chan
,
SUSPEND
,
0
);
}
else
{
idi_do_req
(
card
,
chan
,
CALL_HOLD
,
0
);
}
break
;
case
5
:
/* Resume */
eicon_log
(
card
,
8
,
"idi_req: Ch%d: Call Resume
\n
"
,
chan
->
No
);
idi_do_req
(
card
,
chan
,
RESUME
,
0
);
break
;
}
return
0
;
}
int
idi_connect_res
(
eicon_card
*
card
,
eicon_chan
*
chan
)
{
if
((
!
card
)
||
(
!
chan
))
return
1
;
chan
->
fsm_state
=
EICON_STATE_IWAIT
;
/* check if old NetID has been removed */
if
(
chan
->
e
.
B2Id
)
{
eicon_log
(
card
,
1
,
"eicon: Ch%d: old net_id %x still exist, removing.
\n
"
,
chan
->
No
,
chan
->
e
.
B2Id
);
idi_do_req
(
card
,
chan
,
REMOVE
,
1
);
}
idi_do_req
(
card
,
chan
,
ASSIGN
,
1
);
idi_do_req
(
card
,
chan
,
CALL_RES
,
0
);
return
(
0
);
}
int
idi_connect_req
(
eicon_card
*
card
,
eicon_chan
*
chan
,
char
*
phone
,
char
*
eazmsn
,
int
si1
,
int
si2
)
{
int
l
=
0
;
int
i
;
unsigned
char
tmp
;
unsigned
char
*
sub
,
*
sp
;
unsigned
char
bc
[
5
];
unsigned
char
hlc
[
5
];
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb2
;
eicon_REQ
*
reqbuf
;
eicon_chan_ptr
*
chan2
;
if
((
!
card
)
||
(
!
chan
))
return
1
;
skb
=
alloc_skb
(
270
+
sizeof
(
eicon_REQ
),
GFP_ATOMIC
);
skb2
=
alloc_skb
(
sizeof
(
eicon_chan_ptr
),
GFP_ATOMIC
);
if
((
!
skb
)
||
(
!
skb2
))
{
eicon_log
(
card
,
1
,
"idi_err: Ch%d: alloc_skb failed in connect_req()
\n
"
,
chan
->
No
);
if
(
skb
)
dev_kfree_skb
(
skb
);
if
(
skb2
)
dev_kfree_skb
(
skb2
);
return
-
ENOMEM
;
}
chan2
=
(
eicon_chan_ptr
*
)
skb_put
(
skb2
,
sizeof
(
eicon_chan_ptr
));
chan2
->
ptr
=
chan
;
reqbuf
=
(
eicon_REQ
*
)
skb_put
(
skb
,
270
+
sizeof
(
eicon_REQ
));
reqbuf
->
Req
=
CALL_REQ
;
reqbuf
->
ReqCh
=
0
;
reqbuf
->
ReqId
=
1
;
sub
=
NULL
;
sp
=
phone
;
while
(
*
sp
)
{
if
(
*
sp
==
'.'
)
{
sub
=
sp
+
1
;
*
sp
=
0
;
}
else
sp
++
;
}
reqbuf
->
XBuffer
.
P
[
l
++
]
=
CPN
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
strlen
(
phone
)
+
1
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
0x81
;
for
(
i
=
0
;
i
<
strlen
(
phone
);
i
++
)
reqbuf
->
XBuffer
.
P
[
l
++
]
=
phone
[
i
]
&
0x7f
;
if
(
sub
)
{
reqbuf
->
XBuffer
.
P
[
l
++
]
=
DSA
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
strlen
(
sub
)
+
2
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
0x80
;
/* NSAP coded */
reqbuf
->
XBuffer
.
P
[
l
++
]
=
0x50
;
/* local IDI format */
while
(
*
sub
)
reqbuf
->
XBuffer
.
P
[
l
++
]
=
*
sub
++
&
0x7f
;
}
sub
=
NULL
;
sp
=
eazmsn
;
while
(
*
sp
)
{
if
(
*
sp
==
'.'
)
{
sub
=
sp
+
1
;
*
sp
=
0
;
}
else
sp
++
;
}
reqbuf
->
XBuffer
.
P
[
l
++
]
=
OAD
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
strlen
(
eazmsn
)
+
2
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
0x01
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
0x80
;
for
(
i
=
0
;
i
<
strlen
(
eazmsn
);
i
++
)
reqbuf
->
XBuffer
.
P
[
l
++
]
=
eazmsn
[
i
]
&
0x7f
;
if
(
sub
)
{
reqbuf
->
XBuffer
.
P
[
l
++
]
=
OSA
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
strlen
(
sub
)
+
2
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
0x80
;
/* NSAP coded */
reqbuf
->
XBuffer
.
P
[
l
++
]
=
0x50
;
/* local IDI format */
while
(
*
sub
)
reqbuf
->
XBuffer
.
P
[
l
++
]
=
*
sub
++
&
0x7f
;
}
if
(
si2
>
2
)
{
reqbuf
->
XBuffer
.
P
[
l
++
]
=
SHIFT
|
6
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
SIN
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
2
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
si1
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
si2
;
}
else
if
((
tmp
=
idi_si2bc
(
si1
,
si2
,
bc
,
hlc
))
>
0
)
{
reqbuf
->
XBuffer
.
P
[
l
++
]
=
BC
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
tmp
;
for
(
i
=
0
;
i
<
tmp
;
i
++
)
reqbuf
->
XBuffer
.
P
[
l
++
]
=
bc
[
i
];
if
((
tmp
=
hlc
[
0
]))
{
reqbuf
->
XBuffer
.
P
[
l
++
]
=
HLC
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
tmp
;
for
(
i
=
1
;
i
<=
tmp
;
i
++
)
reqbuf
->
XBuffer
.
P
[
l
++
]
=
hlc
[
i
];
}
}
reqbuf
->
XBuffer
.
P
[
l
++
]
=
CAI
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
6
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
0x09
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
0
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
0
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
0
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
32
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
0
;
switch
(
chan
->
l2prot
)
{
case
ISDN_PROTO_L2_X75I
:
case
ISDN_PROTO_L2_X75UI
:
case
ISDN_PROTO_L2_X75BUI
:
case
ISDN_PROTO_L2_HDLC
:
reqbuf
->
XBuffer
.
P
[
l
-
6
]
=
5
;
reqbuf
->
XBuffer
.
P
[
l
-
7
]
=
1
;
l
-=
5
;
break
;
case
ISDN_PROTO_L2_V11096
:
reqbuf
->
XBuffer
.
P
[
l
-
7
]
=
3
;
reqbuf
->
XBuffer
.
P
[
l
-
6
]
=
0x0d
;
reqbuf
->
XBuffer
.
P
[
l
-
5
]
=
5
;
reqbuf
->
XBuffer
.
P
[
l
-
4
]
=
0
;
l
-=
3
;
break
;
case
ISDN_PROTO_L2_V11019
:
reqbuf
->
XBuffer
.
P
[
l
-
7
]
=
3
;
reqbuf
->
XBuffer
.
P
[
l
-
6
]
=
0x0d
;
reqbuf
->
XBuffer
.
P
[
l
-
5
]
=
6
;
reqbuf
->
XBuffer
.
P
[
l
-
4
]
=
0
;
l
-=
3
;
break
;
case
ISDN_PROTO_L2_V11038
:
reqbuf
->
XBuffer
.
P
[
l
-
7
]
=
3
;
reqbuf
->
XBuffer
.
P
[
l
-
6
]
=
0x0d
;
reqbuf
->
XBuffer
.
P
[
l
-
5
]
=
7
;
reqbuf
->
XBuffer
.
P
[
l
-
4
]
=
0
;
l
-=
3
;
break
;
case
ISDN_PROTO_L2_MODEM
:
reqbuf
->
XBuffer
.
P
[
l
-
6
]
=
0x11
;
reqbuf
->
XBuffer
.
P
[
l
-
5
]
=
7
;
reqbuf
->
XBuffer
.
P
[
l
-
4
]
=
0
;
reqbuf
->
XBuffer
.
P
[
l
-
3
]
=
0
;
reqbuf
->
XBuffer
.
P
[
l
-
2
]
=
128
;
reqbuf
->
XBuffer
.
P
[
l
-
1
]
=
0
;
break
;
case
ISDN_PROTO_L2_FAX
:
reqbuf
->
XBuffer
.
P
[
l
-
6
]
=
0x10
;
reqbuf
->
XBuffer
.
P
[
l
-
5
]
=
0
;
reqbuf
->
XBuffer
.
P
[
l
-
4
]
=
0
;
reqbuf
->
XBuffer
.
P
[
l
-
3
]
=
0
;
reqbuf
->
XBuffer
.
P
[
l
-
2
]
=
128
;
reqbuf
->
XBuffer
.
P
[
l
-
1
]
=
0
;
break
;
case
ISDN_PROTO_L2_TRANS
:
switch
(
chan
->
l3prot
)
{
case
ISDN_PROTO_L3_TRANSDSP
:
reqbuf
->
XBuffer
.
P
[
l
-
6
]
=
22
;
/* DTMF, audio events on */
}
break
;
}
reqbuf
->
XBuffer
.
P
[
l
++
]
=
0
;
/* end */
reqbuf
->
XBuffer
.
length
=
l
;
reqbuf
->
Reference
=
0
;
/* Sig Entity */
if
(
chan
->
statectrl
&
WAITING_FOR_HANGUP
)
{
/* If the line did not disconnect yet,
we have to delay this command */
eicon_log
(
card
,
32
,
"idi_req: Ch%d: delaying conn_req
\n
"
,
chan
->
No
);
chan
->
statectrl
|=
HAVE_CONN_REQ
;
chan
->
tskb1
=
skb
;
chan
->
tskb2
=
skb2
;
}
else
{
skb_queue_tail
(
&
chan
->
e
.
X
,
skb
);
skb_queue_tail
(
&
card
->
sndq
,
skb2
);
eicon_schedule_tx
(
card
);
}
eicon_log
(
card
,
8
,
"idi_req: Ch%d: Conn_Req %s -> %s
\n
"
,
chan
->
No
,
eazmsn
,
phone
);
return
(
0
);
}
void
idi_IndParse
(
eicon_card
*
ccard
,
eicon_chan
*
chan
,
idi_ind_message
*
message
,
unsigned
char
*
buffer
,
int
len
)
{
int
i
,
j
;
int
pos
=
0
;
int
codeset
=
0
;
int
wlen
=
0
;
int
lock
=
0
;
__u8
w
;
__u16
code
;
isdn_ctrl
cmd
;
memset
(
message
,
0
,
sizeof
(
idi_ind_message
));
if
((
!
len
)
||
(
!
buffer
[
pos
]))
return
;
while
(
pos
<=
len
)
{
w
=
buffer
[
pos
++
];
if
(
!
w
)
return
;
if
(
w
&
0x80
)
{
wlen
=
0
;
}
else
{
wlen
=
buffer
[
pos
++
];
}
if
(
pos
>
len
)
return
;
if
(
lock
&
0x80
)
lock
&=
0x7f
;
else
codeset
=
lock
;
if
((
w
&
0xf0
)
==
SHIFT
)
{
codeset
=
w
;
if
(
!
(
codeset
&
0x08
))
lock
=
codeset
&
7
;
codeset
&=
7
;
lock
|=
0x80
;
}
else
{
if
(
w
==
ESC
&&
wlen
>=
2
)
{
code
=
buffer
[
pos
++
]
|
0x800
;
wlen
--
;
}
else
code
=
w
;
code
|=
(
codeset
<<
8
);
if
(
pos
+
wlen
>
len
)
{
eicon_log
(
ccard
,
1
,
"idi_err: Ch%d: IElen %d of %x exceeds Ind_Length (+%d)
\n
"
,
chan
->
No
,
wlen
,
code
,
(
pos
+
wlen
)
-
len
);
return
;
}
switch
(
code
)
{
case
OAD
:
if
(
wlen
>
sizeof
(
message
->
oad
))
{
pos
+=
wlen
;
break
;
}
j
=
1
;
if
(
wlen
)
{
message
->
plan
=
buffer
[
pos
++
];
if
(
message
->
plan
&
0x80
)
message
->
screen
=
0
;
else
{
message
->
screen
=
buffer
[
pos
++
];
j
=
2
;
}
}
for
(
i
=
0
;
i
<
wlen
-
j
;
i
++
)
message
->
oad
[
i
]
=
buffer
[
pos
++
];
eicon_log
(
ccard
,
2
,
"idi_inf: Ch%d: OAD=(0x%02x,0x%02x) %s
\n
"
,
chan
->
No
,
message
->
plan
,
message
->
screen
,
message
->
oad
);
break
;
case
RDN
:
if
(
wlen
>
sizeof
(
message
->
rdn
))
{
pos
+=
wlen
;
break
;
}
j
=
1
;
if
(
wlen
)
{
if
(
!
(
buffer
[
pos
++
]
&
0x80
))
{
pos
++
;
j
=
2
;
}
}
for
(
i
=
0
;
i
<
wlen
-
j
;
i
++
)
message
->
rdn
[
i
]
=
buffer
[
pos
++
];
eicon_log
(
ccard
,
2
,
"idi_inf: Ch%d: RDN= %s
\n
"
,
chan
->
No
,
message
->
rdn
);
break
;
case
CPN
:
if
(
wlen
>
sizeof
(
message
->
cpn
))
{
pos
+=
wlen
;
break
;
}
for
(
i
=
0
;
i
<
wlen
;
i
++
)
message
->
cpn
[
i
]
=
buffer
[
pos
++
];
eicon_log
(
ccard
,
2
,
"idi_inf: Ch%d: CPN=(0x%02x) %s
\n
"
,
chan
->
No
,
(
__u8
)
message
->
cpn
[
0
],
message
->
cpn
+
1
);
break
;
case
DSA
:
if
(
wlen
>
sizeof
(
message
->
dsa
))
{
pos
+=
wlen
;
break
;
}
pos
+=
2
;
for
(
i
=
0
;
i
<
wlen
-
2
;
i
++
)
message
->
dsa
[
i
]
=
buffer
[
pos
++
];
eicon_log
(
ccard
,
2
,
"idi_inf: Ch%d: DSA=%s
\n
"
,
chan
->
No
,
message
->
dsa
);
break
;
case
OSA
:
if
(
wlen
>
sizeof
(
message
->
osa
))
{
pos
+=
wlen
;
break
;
}
pos
+=
2
;
for
(
i
=
0
;
i
<
wlen
-
2
;
i
++
)
message
->
osa
[
i
]
=
buffer
[
pos
++
];
eicon_log
(
ccard
,
2
,
"idi_inf: Ch%d: OSA=%s
\n
"
,
chan
->
No
,
message
->
osa
);
break
;
case
CAD
:
pos
+=
wlen
;
eicon_log
(
ccard
,
2
,
"idi_inf: Ch%d: Connected Address in ind, len:%x
\n
"
,
chan
->
No
,
wlen
);
break
;
case
BC
:
if
(
wlen
>
sizeof
(
message
->
bc
))
{
pos
+=
wlen
;
break
;
}
for
(
i
=
0
;
i
<
wlen
;
i
++
)
message
->
bc
[
i
]
=
buffer
[
pos
++
];
eicon_log
(
ccard
,
4
,
"idi_inf: Ch%d: BC = 0x%02x 0x%02x 0x%02x
\n
"
,
chan
->
No
,
message
->
bc
[
0
],
message
->
bc
[
1
],
message
->
bc
[
2
]);
break
;
case
0x800
|
BC
:
if
(
wlen
>
sizeof
(
message
->
e_bc
))
{
pos
+=
wlen
;
break
;
}
for
(
i
=
0
;
i
<
wlen
;
i
++
)
message
->
e_bc
[
i
]
=
buffer
[
pos
++
];
eicon_log
(
ccard
,
4
,
"idi_inf: Ch%d: ESC/BC=%d
\n
"
,
chan
->
No
,
message
->
bc
[
0
]);
break
;
case
LLC
:
if
(
wlen
>
sizeof
(
message
->
llc
))
{
pos
+=
wlen
;
break
;
}
for
(
i
=
0
;
i
<
wlen
;
i
++
)
message
->
llc
[
i
]
=
buffer
[
pos
++
];
eicon_log
(
ccard
,
4
,
"idi_inf: Ch%d: LLC=%d %d %d %d ...
\n
"
,
chan
->
No
,
message
->
llc
[
0
],
message
->
llc
[
1
],
message
->
llc
[
2
],
message
->
llc
[
3
]);
break
;
case
HLC
:
if
(
wlen
>
sizeof
(
message
->
hlc
))
{
pos
+=
wlen
;
break
;
}
for
(
i
=
0
;
i
<
wlen
;
i
++
)
message
->
hlc
[
i
]
=
buffer
[
pos
++
];
eicon_log
(
ccard
,
4
,
"idi_inf: Ch%d: HLC=%x %x %x %x %x ...
\n
"
,
chan
->
No
,
message
->
hlc
[
0
],
message
->
hlc
[
1
],
message
->
hlc
[
2
],
message
->
hlc
[
3
],
message
->
hlc
[
4
]);
break
;
case
DSP
:
case
0x600
|
DSP
:
if
(
wlen
>
sizeof
(
message
->
display
))
{
pos
+=
wlen
;
break
;
}
for
(
i
=
0
;
i
<
wlen
;
i
++
)
message
->
display
[
i
]
=
buffer
[
pos
++
];
eicon_log
(
ccard
,
4
,
"idi_inf: Ch%d: Display: %s
\n
"
,
chan
->
No
,
message
->
display
);
break
;
case
0x600
|
KEY
:
if
(
wlen
>
sizeof
(
message
->
keypad
))
{
pos
+=
wlen
;
break
;
}
for
(
i
=
0
;
i
<
wlen
;
i
++
)
message
->
keypad
[
i
]
=
buffer
[
pos
++
];
eicon_log
(
ccard
,
4
,
"idi_inf: Ch%d: Keypad: %s
\n
"
,
chan
->
No
,
message
->
keypad
);
break
;
case
NI
:
case
0x600
|
NI
:
if
(
wlen
)
{
switch
(
buffer
[
pos
]
&
127
)
{
case
0
:
eicon_log
(
ccard
,
4
,
"idi_inf: Ch%d: User suspended.
\n
"
,
chan
->
No
);
break
;
case
1
:
eicon_log
(
ccard
,
4
,
"idi_inf: Ch%d: User resumed.
\n
"
,
chan
->
No
);
break
;
case
2
:
eicon_log
(
ccard
,
4
,
"idi_inf: Ch%d: Bearer service change.
\n
"
,
chan
->
No
);
break
;
default:
eicon_log
(
ccard
,
4
,
"idi_inf: Ch%d: Unknown Notification %x.
\n
"
,
chan
->
No
,
buffer
[
pos
]
&
127
);
}
pos
+=
wlen
;
}
break
;
case
PI
:
case
0x600
|
PI
:
if
(
wlen
>
1
)
{
switch
(
buffer
[
pos
+
1
]
&
127
)
{
case
1
:
eicon_log
(
ccard
,
4
,
"idi_inf: Ch%d: Call is not end-to-end ISDN.
\n
"
,
chan
->
No
);
break
;
case
2
:
eicon_log
(
ccard
,
4
,
"idi_inf: Ch%d: Destination address is non ISDN.
\n
"
,
chan
->
No
);
break
;
case
3
:
eicon_log
(
ccard
,
4
,
"idi_inf: Ch%d: Origination address is non ISDN.
\n
"
,
chan
->
No
);
break
;
case
4
:
eicon_log
(
ccard
,
4
,
"idi_inf: Ch%d: Call has returned to the ISDN.
\n
"
,
chan
->
No
);
break
;
case
5
:
eicon_log
(
ccard
,
4
,
"idi_inf: Ch%d: Interworking has occurred.
\n
"
,
chan
->
No
);
break
;
case
8
:
eicon_log
(
ccard
,
4
,
"idi_inf: Ch%d: In-band information available.
\n
"
,
chan
->
No
);
break
;
default:
eicon_log
(
ccard
,
4
,
"idi_inf: Ch%d: Unknown Progress %x.
\n
"
,
chan
->
No
,
buffer
[
pos
+
1
]
&
127
);
}
}
pos
+=
wlen
;
break
;
case
CAU
:
if
(
wlen
>
sizeof
(
message
->
cau
))
{
pos
+=
wlen
;
break
;
}
for
(
i
=
0
;
i
<
wlen
;
i
++
)
message
->
cau
[
i
]
=
buffer
[
pos
++
];
memcpy
(
&
chan
->
cause
,
&
message
->
cau
,
2
);
eicon_log
(
ccard
,
4
,
"idi_inf: Ch%d: CAU=%d %d
\n
"
,
chan
->
No
,
message
->
cau
[
0
],
message
->
cau
[
1
]);
break
;
case
0x800
|
CAU
:
if
(
wlen
>
sizeof
(
message
->
e_cau
))
{
pos
+=
wlen
;
break
;
}
for
(
i
=
0
;
i
<
wlen
;
i
++
)
message
->
e_cau
[
i
]
=
buffer
[
pos
++
];
eicon_log
(
ccard
,
4
,
"idi_inf: Ch%d: ECAU=%d %d
\n
"
,
chan
->
No
,
message
->
e_cau
[
0
],
message
->
e_cau
[
1
]);
break
;
case
0x800
|
CHI
:
if
(
wlen
>
sizeof
(
message
->
e_chi
))
{
pos
+=
wlen
;
break
;
}
for
(
i
=
0
;
i
<
wlen
;
i
++
)
message
->
e_chi
[
i
]
=
buffer
[
pos
++
];
eicon_log
(
ccard
,
4
,
"idi_inf: Ch%d: ESC/CHI=%d
\n
"
,
chan
->
No
,
message
->
e_cau
[
0
]);
break
;
case
0x800
|
0x7a
:
pos
++
;
message
->
e_mt
=
buffer
[
pos
++
];
eicon_log
(
ccard
,
4
,
"idi_inf: Ch%d: EMT=0x%x
\n
"
,
chan
->
No
,
message
->
e_mt
);
break
;
case
DT
:
if
(
wlen
>
sizeof
(
message
->
dt
))
{
pos
+=
wlen
;
break
;
}
for
(
i
=
0
;
i
<
wlen
;
i
++
)
message
->
dt
[
i
]
=
buffer
[
pos
++
];
eicon_log
(
ccard
,
4
,
"idi_inf: Ch%d: DT: %02d.%02d.%02d %02d:%02d:%02d
\n
"
,
chan
->
No
,
message
->
dt
[
2
],
message
->
dt
[
1
],
message
->
dt
[
0
],
message
->
dt
[
3
],
message
->
dt
[
4
],
message
->
dt
[
5
]);
break
;
case
0x600
|
SIN
:
if
(
wlen
>
sizeof
(
message
->
sin
))
{
pos
+=
wlen
;
break
;
}
for
(
i
=
0
;
i
<
wlen
;
i
++
)
message
->
sin
[
i
]
=
buffer
[
pos
++
];
eicon_log
(
ccard
,
2
,
"idi_inf: Ch%d: SIN=%d %d
\n
"
,
chan
->
No
,
message
->
sin
[
0
],
message
->
sin
[
1
]);
break
;
case
0x600
|
CPS
:
eicon_log
(
ccard
,
2
,
"idi_inf: Ch%d: Called Party Status in ind
\n
"
,
chan
->
No
);
pos
+=
wlen
;
break
;
case
0x600
|
CIF
:
for
(
i
=
0
;
i
<
wlen
;
i
++
)
if
(
buffer
[
pos
+
i
]
!=
'0'
)
break
;
memcpy
(
&
cmd
.
parm
.
num
,
&
buffer
[
pos
+
i
],
wlen
-
i
);
cmd
.
parm
.
num
[
wlen
-
i
]
=
0
;
eicon_log
(
ccard
,
2
,
"idi_inf: Ch%d: CIF=%s
\n
"
,
chan
->
No
,
cmd
.
parm
.
num
);
pos
+=
wlen
;
cmd
.
driver
=
ccard
->
myid
;
cmd
.
command
=
ISDN_STAT_CINF
;
cmd
.
arg
=
chan
->
No
;
ccard
->
interface
.
statcallb
(
&
cmd
);
break
;
case
0x600
|
DATE
:
eicon_log
(
ccard
,
2
,
"idi_inf: Ch%d: Date in ind
\n
"
,
chan
->
No
);
pos
+=
wlen
;
break
;
case
0xa1
:
eicon_log
(
ccard
,
2
,
"idi_inf: Ch%d: Sending Complete in ind.
\n
"
,
chan
->
No
);
pos
+=
wlen
;
break
;
case
0xe08
:
case
0xe7a
:
case
0xe04
:
case
0xe00
:
/* *** TODO *** */
case
CHA
:
/* Charge advice */
case
FTY
:
case
0x600
|
FTY
:
case
CHI
:
case
0x800
:
/* Not yet interested in this */
pos
+=
wlen
;
break
;
case
0x880
:
/* Managment Information Element */
if
(
!
manbuf
)
{
eicon_log
(
ccard
,
1
,
"idi_err: manbuf not allocated
\n
"
);
}
else
{
memcpy
(
&
manbuf
->
data
[
manbuf
->
pos
],
&
buffer
[
pos
],
wlen
);
manbuf
->
length
[
manbuf
->
count
]
=
wlen
;
manbuf
->
count
++
;
manbuf
->
pos
+=
wlen
;
}
pos
+=
wlen
;
break
;
default:
pos
+=
wlen
;
eicon_log
(
ccard
,
6
,
"idi_inf: Ch%d: unknown information element 0x%x in ind, len:%x
\n
"
,
chan
->
No
,
code
,
wlen
);
}
}
}
}
void
idi_bc2si
(
unsigned
char
*
bc
,
unsigned
char
*
hlc
,
unsigned
char
*
sin
,
unsigned
char
*
si1
,
unsigned
char
*
si2
)
{
si1
[
0
]
=
0
;
si2
[
0
]
=
0
;
switch
(
bc
[
0
]
&
0x7f
)
{
case
0x00
:
/* Speech */
si1
[
0
]
=
1
;
#ifdef EICON_FULL_SERVICE_OKTETT
si1
[
0
]
=
sin
[
0
];
si2
[
0
]
=
sin
[
1
];
#endif
break
;
case
0x10
:
/* 3.1 Khz audio */
si1
[
0
]
=
1
;
#ifdef EICON_FULL_SERVICE_OKTETT
si1
[
0
]
=
sin
[
0
];
si2
[
0
]
=
sin
[
1
];
#endif
break
;
case
0x08
:
/* Unrestricted digital information */
si1
[
0
]
=
7
;
si2
[
0
]
=
sin
[
1
];
break
;
case
0x09
:
/* Restricted digital information */
si1
[
0
]
=
2
;
break
;
case
0x11
:
/* Unrestr. digital information with
* tones/announcements ( or 7 kHz audio
*/
si1
[
0
]
=
3
;
break
;
case
0x18
:
/* Video */
si1
[
0
]
=
4
;
break
;
}
switch
(
bc
[
1
]
&
0x7f
)
{
case
0x40
:
/* packed mode */
si1
[
0
]
=
8
;
break
;
case
0x10
:
/* 64 kbit */
case
0x11
:
/* 2*64 kbit */
case
0x13
:
/* 384 kbit */
case
0x15
:
/* 1536 kbit */
case
0x17
:
/* 1920 kbit */
/* moderate = bc[1] & 0x7f; */
break
;
}
}
/********************* FAX stuff ***************************/
#ifdef CONFIG_ISDN_TTY_FAX
int
idi_fill_in_T30
(
eicon_chan
*
chan
,
unsigned
char
*
buffer
)
{
eicon_t30_s
*
t30
=
(
eicon_t30_s
*
)
buffer
;
if
(
!
chan
->
fax
)
{
eicon_log
(
NULL
,
1
,
"idi_T30: fill_in with NULL fax struct, ERROR
\n
"
);
return
0
;
}
memset
(
t30
,
0
,
sizeof
(
eicon_t30_s
));
t30
->
station_id_len
=
EICON_FAXID_LEN
;
memcpy
(
&
t30
->
station_id
[
0
],
&
chan
->
fax
->
id
[
0
],
EICON_FAXID_LEN
);
t30
->
resolution
=
chan
->
fax
->
resolution
;
t30
->
rate
=
chan
->
fax
->
rate
+
1
;
/* eicon rate starts with 1 */
t30
->
format
=
T30_FORMAT_SFF
;
t30
->
pages_low
=
0
;
t30
->
pages_high
=
0
;
t30
->
atf
=
1
;
/* optimised for AT+F command set */
t30
->
code
=
0
;
t30
->
feature_bits_low
=
0
;
t30
->
feature_bits_high
=
0
;
t30
->
control_bits_low
=
0
;
t30
->
control_bits_high
=
0
;
if
(
chan
->
fax
->
nbc
)
{
/* set compression by DCC value */
switch
(
chan
->
fax
->
compression
)
{
case
(
0
):
/* 1-D modified */
break
;
case
(
1
):
/* 2-D modified Read */
t30
->
control_bits_low
|=
T30_CONTROL_BIT_ENABLE_2D_CODING
;
t30
->
feature_bits_low
|=
T30_FEATURE_BIT_2D_CODING
;
break
;
case
(
2
):
/* 2-D uncompressed */
t30
->
control_bits_low
|=
T30_CONTROL_BIT_ENABLE_UNCOMPR
;
t30
->
control_bits_low
|=
T30_CONTROL_BIT_ENABLE_2D_CODING
;
t30
->
feature_bits_low
|=
T30_FEATURE_BIT_UNCOMPR_ENABLED
;
t30
->
feature_bits_low
|=
T30_FEATURE_BIT_2D_CODING
;
break
;
case
(
3
):
/* 2-D modified Read */
t30
->
control_bits_low
|=
T30_CONTROL_BIT_ENABLE_T6_CODING
;
t30
->
control_bits_low
|=
T30_CONTROL_BIT_ENABLE_2D_CODING
;
t30
->
control_bits_low
|=
T30_CONTROL_BIT_ENABLE_UNCOMPR
;
t30
->
feature_bits_low
|=
T30_FEATURE_BIT_UNCOMPR_ENABLED
;
t30
->
feature_bits_low
|=
T30_FEATURE_BIT_T6_CODING
;
t30
->
feature_bits_low
|=
T30_FEATURE_BIT_2D_CODING
;
t30
->
control_bits_low
|=
T30_CONTROL_BIT_ENABLE_ECM
;
t30
->
feature_bits_low
|=
T30_FEATURE_BIT_ECM
;
break
;
}
}
else
{
/* set compression to best */
t30
->
control_bits_low
|=
T30_CONTROL_BIT_ENABLE_T6_CODING
;
t30
->
control_bits_low
|=
T30_CONTROL_BIT_ENABLE_2D_CODING
;
t30
->
control_bits_low
|=
T30_CONTROL_BIT_ENABLE_UNCOMPR
;
t30
->
feature_bits_low
|=
T30_FEATURE_BIT_UNCOMPR_ENABLED
;
t30
->
feature_bits_low
|=
T30_FEATURE_BIT_T6_CODING
;
t30
->
feature_bits_low
|=
T30_FEATURE_BIT_2D_CODING
;
t30
->
control_bits_low
|=
T30_CONTROL_BIT_ENABLE_ECM
;
t30
->
feature_bits_low
|=
T30_FEATURE_BIT_ECM
;
}
switch
(
chan
->
fax
->
ecm
)
{
case
(
0
):
/* disable ECM */
break
;
case
(
1
):
t30
->
control_bits_low
|=
T30_CONTROL_BIT_ENABLE_ECM
;
t30
->
control_bits_low
|=
T30_CONTROL_BIT_ECM_64_BYTES
;
t30
->
feature_bits_low
|=
T30_FEATURE_BIT_ECM
;
t30
->
feature_bits_low
|=
T30_FEATURE_BIT_ECM_64_BYTES
;
break
;
case
(
2
):
t30
->
control_bits_low
|=
T30_CONTROL_BIT_ENABLE_ECM
;
t30
->
feature_bits_low
|=
T30_FEATURE_BIT_ECM
;
break
;
}
if
(
DebugVar
&
128
)
{
char
st
[
40
];
eicon_log
(
NULL
,
128
,
"sT30:code = %x
\n
"
,
t30
->
code
);
eicon_log
(
NULL
,
128
,
"sT30:rate = %x
\n
"
,
t30
->
rate
);
eicon_log
(
NULL
,
128
,
"sT30:res = %x
\n
"
,
t30
->
resolution
);
eicon_log
(
NULL
,
128
,
"sT30:format = %x
\n
"
,
t30
->
format
);
eicon_log
(
NULL
,
128
,
"sT30:pages_low = %x
\n
"
,
t30
->
pages_low
);
eicon_log
(
NULL
,
128
,
"sT30:pages_high = %x
\n
"
,
t30
->
pages_high
);
eicon_log
(
NULL
,
128
,
"sT30:atf = %x
\n
"
,
t30
->
atf
);
eicon_log
(
NULL
,
128
,
"sT30:control_bits_low = %x
\n
"
,
t30
->
control_bits_low
);
eicon_log
(
NULL
,
128
,
"sT30:control_bits_high = %x
\n
"
,
t30
->
control_bits_high
);
eicon_log
(
NULL
,
128
,
"sT30:feature_bits_low = %x
\n
"
,
t30
->
feature_bits_low
);
eicon_log
(
NULL
,
128
,
"sT30:feature_bits_high = %x
\n
"
,
t30
->
feature_bits_high
);
//eicon_log(NULL, 128, "sT30:universal_5 = %x\n", t30->universal_5);
//eicon_log(NULL, 128, "sT30:universal_6 = %x\n", t30->universal_6);
//eicon_log(NULL, 128, "sT30:universal_7 = %x\n", t30->universal_7);
eicon_log
(
NULL
,
128
,
"sT30:station_id_len = %x
\n
"
,
t30
->
station_id_len
);
eicon_log
(
NULL
,
128
,
"sT30:head_line_len = %x
\n
"
,
t30
->
head_line_len
);
strlcpy
(
st
,
t30
->
station_id
,
t30
->
station_id_len
+
1
);
eicon_log
(
NULL
,
128
,
"sT30:station_id = <%s>
\n
"
,
st
);
}
return
(
sizeof
(
eicon_t30_s
));
}
/* send fax struct */
int
idi_send_edata
(
eicon_card
*
card
,
eicon_chan
*
chan
)
{
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb2
;
eicon_REQ
*
reqbuf
;
eicon_chan_ptr
*
chan2
;
if
((
chan
->
fsm_state
==
EICON_STATE_NULL
)
||
(
chan
->
fsm_state
==
EICON_STATE_LISTEN
))
{
eicon_log
(
card
,
1
,
"idi_snd: Ch%d: send edata on state %d !
\n
"
,
chan
->
No
,
chan
->
fsm_state
);
return
-
ENODEV
;
}
eicon_log
(
card
,
128
,
"idi_snd: Ch%d: edata (fax)
\n
"
,
chan
->
No
);
skb
=
alloc_skb
(
sizeof
(
eicon_REQ
)
+
sizeof
(
eicon_t30_s
),
GFP_ATOMIC
);
skb2
=
alloc_skb
(
sizeof
(
eicon_chan_ptr
),
GFP_ATOMIC
);
if
((
!
skb
)
||
(
!
skb2
))
{
eicon_log
(
card
,
1
,
"idi_err: Ch%d: alloc_skb failed in send_edata()
\n
"
,
chan
->
No
);
if
(
skb
)
dev_kfree_skb
(
skb
);
if
(
skb2
)
dev_kfree_skb
(
skb2
);
return
-
ENOMEM
;
}
chan2
=
(
eicon_chan_ptr
*
)
skb_put
(
skb2
,
sizeof
(
eicon_chan_ptr
));
chan2
->
ptr
=
chan
;
reqbuf
=
(
eicon_REQ
*
)
skb_put
(
skb
,
sizeof
(
eicon_t30_s
)
+
sizeof
(
eicon_REQ
));
reqbuf
->
Req
=
N_EDATA
;
reqbuf
->
ReqCh
=
chan
->
e
.
IndCh
;
reqbuf
->
ReqId
=
1
;
reqbuf
->
XBuffer
.
length
=
idi_fill_in_T30
(
chan
,
reqbuf
->
XBuffer
.
P
);
reqbuf
->
Reference
=
1
;
/* Net Entity */
skb_queue_tail
(
&
chan
->
e
.
X
,
skb
);
skb_queue_tail
(
&
card
->
sndq
,
skb2
);
eicon_schedule_tx
(
card
);
return
(
0
);
}
void
idi_parse_edata
(
eicon_card
*
ccard
,
eicon_chan
*
chan
,
unsigned
char
*
buffer
,
int
len
)
{
eicon_t30_s
*
p
=
(
eicon_t30_s
*
)
buffer
;
int
i
;
if
(
DebugVar
&
128
)
{
char
st
[
40
];
eicon_log
(
ccard
,
128
,
"rT30:len %d , size %d
\n
"
,
len
,
sizeof
(
eicon_t30_s
));
eicon_log
(
ccard
,
128
,
"rT30:code = %x
\n
"
,
p
->
code
);
eicon_log
(
ccard
,
128
,
"rT30:rate = %x
\n
"
,
p
->
rate
);
eicon_log
(
ccard
,
128
,
"rT30:res = %x
\n
"
,
p
->
resolution
);
eicon_log
(
ccard
,
128
,
"rT30:format = %x
\n
"
,
p
->
format
);
eicon_log
(
ccard
,
128
,
"rT30:pages_low = %x
\n
"
,
p
->
pages_low
);
eicon_log
(
ccard
,
128
,
"rT30:pages_high = %x
\n
"
,
p
->
pages_high
);
eicon_log
(
ccard
,
128
,
"rT30:atf = %x
\n
"
,
p
->
atf
);
eicon_log
(
ccard
,
128
,
"rT30:control_bits_low = %x
\n
"
,
p
->
control_bits_low
);
eicon_log
(
ccard
,
128
,
"rT30:control_bits_high = %x
\n
"
,
p
->
control_bits_high
);
eicon_log
(
ccard
,
128
,
"rT30:feature_bits_low = %x
\n
"
,
p
->
feature_bits_low
);
eicon_log
(
ccard
,
128
,
"rT30:feature_bits_high = %x
\n
"
,
p
->
feature_bits_high
);
//eicon_log(ccard, 128, "rT30:universal_5 = %x\n", p->universal_5);
//eicon_log(ccard, 128, "rT30:universal_6 = %x\n", p->universal_6);
//eicon_log(ccard, 128, "rT30:universal_7 = %x\n", p->universal_7);
eicon_log
(
ccard
,
128
,
"rT30:station_id_len = %x
\n
"
,
p
->
station_id_len
);
eicon_log
(
ccard
,
128
,
"rT30:head_line_len = %x
\n
"
,
p
->
head_line_len
);
strlcpy
(
st
,
p
->
station_id
,
p
->
station_id_len
+
1
);
eicon_log
(
ccard
,
128
,
"rT30:station_id = <%s>
\n
"
,
st
);
}
if
(
!
chan
->
fax
)
{
eicon_log
(
ccard
,
1
,
"idi_edata: parse to NULL fax struct, ERROR
\n
"
);
return
;
}
chan
->
fax
->
code
=
p
->
code
;
i
=
(
p
->
station_id_len
<
FAXIDLEN
)
?
p
->
station_id_len
:
(
FAXIDLEN
-
1
);
memcpy
(
chan
->
fax
->
r_id
,
p
->
station_id
,
i
);
chan
->
fax
->
r_id
[
i
]
=
0
;
chan
->
fax
->
r_resolution
=
p
->
resolution
;
chan
->
fax
->
r_rate
=
p
->
rate
-
1
;
chan
->
fax
->
r_binary
=
0
;
/* no binary support */
chan
->
fax
->
r_width
=
0
;
chan
->
fax
->
r_length
=
2
;
chan
->
fax
->
r_scantime
=
0
;
chan
->
fax
->
r_compression
=
0
;
chan
->
fax
->
r_ecm
=
0
;
if
(
p
->
feature_bits_low
&
T30_FEATURE_BIT_2D_CODING
)
{
chan
->
fax
->
r_compression
=
1
;
if
(
p
->
feature_bits_low
&
T30_FEATURE_BIT_UNCOMPR_ENABLED
)
{
chan
->
fax
->
r_compression
=
2
;
}
}
if
(
p
->
feature_bits_low
&
T30_FEATURE_BIT_T6_CODING
)
{
chan
->
fax
->
r_compression
=
3
;
}
if
(
p
->
feature_bits_low
&
T30_FEATURE_BIT_ECM
)
{
chan
->
fax
->
r_ecm
=
2
;
if
(
p
->
feature_bits_low
&
T30_FEATURE_BIT_ECM_64_BYTES
)
chan
->
fax
->
r_ecm
=
1
;
}
}
void
idi_fax_send_header
(
eicon_card
*
card
,
eicon_chan
*
chan
,
int
header
)
{
static
__u16
wd2sff
[]
=
{
1728
,
2048
,
2432
,
1216
,
864
};
static
__u16
ln2sff
[
2
][
3
]
=
{
{
1143
,
1401
,
0
}
,
{
2287
,
2802
,
0
}
};
struct
sk_buff
*
skb
;
eicon_sff_dochead
*
doc
;
eicon_sff_pagehead
*
page
;
u_char
*
docp
;
if
(
!
chan
->
fax
)
{
eicon_log
(
card
,
1
,
"idi_fax: send head with NULL fax struct, ERROR
\n
"
);
return
;
}
if
(
header
==
2
)
{
/* DocHeader + PageHeader */
skb
=
alloc_skb
(
sizeof
(
eicon_sff_dochead
)
+
sizeof
(
eicon_sff_pagehead
),
GFP_ATOMIC
);
}
else
{
skb
=
alloc_skb
(
sizeof
(
eicon_sff_pagehead
),
GFP_ATOMIC
);
}
if
(
!
skb
)
{
eicon_log
(
card
,
1
,
"idi_err: Ch%d: alloc_skb failed in fax_send_header()
\n
"
,
chan
->
No
);
return
;
}
if
(
header
==
2
)
{
/* DocHeader + PageHeader */
docp
=
skb_put
(
skb
,
sizeof
(
eicon_sff_dochead
)
+
sizeof
(
eicon_sff_pagehead
));
doc
=
(
eicon_sff_dochead
*
)
docp
;
page
=
(
eicon_sff_pagehead
*
)
(
docp
+
sizeof
(
eicon_sff_dochead
));
memset
(
docp
,
0
,
sizeof
(
eicon_sff_dochead
)
+
sizeof
(
eicon_sff_pagehead
));
doc
->
id
=
0x66666653
;
doc
->
version
=
0x01
;
doc
->
off1pagehead
=
sizeof
(
eicon_sff_dochead
);
}
else
{
page
=
(
eicon_sff_pagehead
*
)
skb_put
(
skb
,
sizeof
(
eicon_sff_pagehead
));
memset
(
page
,
0
,
sizeof
(
eicon_sff_pagehead
));
}
switch
(
header
)
{
case
1
:
/* PageHeaderEnd */
page
->
pageheadid
=
254
;
page
->
pageheadlen
=
0
;
break
;
case
0
:
/* PageHeader */
case
2
:
/* DocHeader + PageHeader */
page
->
pageheadid
=
254
;
page
->
pageheadlen
=
sizeof
(
eicon_sff_pagehead
)
-
2
;
page
->
resvert
=
chan
->
fax
->
resolution
;
page
->
reshoriz
=
0
;
/* always 203 dpi */
page
->
coding
=
0
;
/* always 1D */
page
->
linelength
=
wd2sff
[
chan
->
fax
->
width
];
page
->
pagelength
=
ln2sff
[
chan
->
fax
->
resolution
][
chan
->
fax
->
length
];
eicon_log
(
card
,
128
,
"sSFF-Head: linelength = %d
\n
"
,
page
->
linelength
);
eicon_log
(
card
,
128
,
"sSFF-Head: pagelength = %d
\n
"
,
page
->
pagelength
);
break
;
}
idi_send_data
(
card
,
chan
,
0
,
skb
,
0
,
0
);
}
void
idi_fax_cmd
(
eicon_card
*
card
,
eicon_chan
*
chan
)
{
isdn_ctrl
cmd
;
if
((
!
card
)
||
(
!
chan
))
return
;
if
(
!
chan
->
fax
)
{
eicon_log
(
card
,
1
,
"idi_fax: cmd with NULL fax struct, ERROR
\n
"
);
return
;
}
switch
(
chan
->
fax
->
code
)
{
case
ISDN_TTY_FAX_DT
:
if
(
chan
->
fax
->
phase
==
ISDN_FAX_PHASE_B
)
{
idi_send_edata
(
card
,
chan
);
break
;
}
if
(
chan
->
fax
->
phase
==
ISDN_FAX_PHASE_D
)
{
idi_send_edata
(
card
,
chan
);
break
;
}
break
;
case
ISDN_TTY_FAX_DR
:
if
(
chan
->
fax
->
phase
==
ISDN_FAX_PHASE_B
)
{
idi_send_edata
(
card
,
chan
);
cmd
.
driver
=
card
->
myid
;
cmd
.
command
=
ISDN_STAT_FAXIND
;
cmd
.
arg
=
chan
->
No
;
chan
->
fax
->
r_code
=
ISDN_TTY_FAX_CFR
;
card
->
interface
.
statcallb
(
&
cmd
);
cmd
.
driver
=
card
->
myid
;
cmd
.
command
=
ISDN_STAT_FAXIND
;
cmd
.
arg
=
chan
->
No
;
chan
->
fax
->
r_code
=
ISDN_TTY_FAX_RID
;
card
->
interface
.
statcallb
(
&
cmd
);
/* telling 1-D compression */
chan
->
fax
->
r_compression
=
0
;
cmd
.
driver
=
card
->
myid
;
cmd
.
command
=
ISDN_STAT_FAXIND
;
cmd
.
arg
=
chan
->
No
;
chan
->
fax
->
r_code
=
ISDN_TTY_FAX_DCS
;
card
->
interface
.
statcallb
(
&
cmd
);
chan
->
fax2
.
NextObject
=
FAX_OBJECT_DOCU
;
chan
->
fax2
.
PrevObject
=
FAX_OBJECT_DOCU
;
break
;
}
if
(
chan
->
fax
->
phase
==
ISDN_FAX_PHASE_D
)
{
idi_send_edata
(
card
,
chan
);
break
;
}
break
;
case
ISDN_TTY_FAX_ET
:
switch
(
chan
->
fax
->
fet
)
{
case
0
:
case
1
:
idi_fax_send_header
(
card
,
chan
,
0
);
break
;
case
2
:
idi_fax_send_header
(
card
,
chan
,
1
);
break
;
}
break
;
}
}
void
idi_edata_rcveop
(
eicon_card
*
card
,
eicon_chan
*
chan
)
{
isdn_ctrl
cmd
;
if
(
!
chan
->
fax
)
{
eicon_log
(
card
,
1
,
"idi_edata: rcveop with NULL fax struct, ERROR
\n
"
);
return
;
}
cmd
.
driver
=
card
->
myid
;
cmd
.
command
=
ISDN_STAT_FAXIND
;
cmd
.
arg
=
chan
->
No
;
chan
->
fax
->
r_code
=
ISDN_TTY_FAX_ET
;
card
->
interface
.
statcallb
(
&
cmd
);
}
void
idi_reset_fax_stat
(
eicon_chan
*
chan
)
{
chan
->
fax2
.
LineLen
=
0
;
chan
->
fax2
.
LineData
=
0
;
chan
->
fax2
.
LineDataLen
=
0
;
chan
->
fax2
.
NullByteExist
=
0
;
chan
->
fax2
.
Dle
=
0
;
chan
->
fax2
.
PageCount
=
0
;
chan
->
fax2
.
Eop
=
0
;
}
void
idi_edata_action
(
eicon_card
*
ccard
,
eicon_chan
*
chan
,
char
*
buffer
,
int
len
)
{
isdn_ctrl
cmd
;
if
(
!
chan
->
fax
)
{
eicon_log
(
ccard
,
1
,
"idi_edata: action with NULL fax struct, ERROR
\n
"
);
return
;
}
if
(
chan
->
fax
->
direction
==
ISDN_TTY_FAX_CONN_OUT
)
{
idi_parse_edata
(
ccard
,
chan
,
buffer
,
len
);
if
(
chan
->
fax
->
phase
==
ISDN_FAX_PHASE_A
)
{
idi_reset_fax_stat
(
chan
);
chan
->
fsm_state
=
EICON_STATE_ACTIVE
;
cmd
.
driver
=
ccard
->
myid
;
cmd
.
command
=
ISDN_STAT_BCONN
;
cmd
.
arg
=
chan
->
No
;
strcpy
(
cmd
.
parm
.
num
,
""
);
ccard
->
interface
.
statcallb
(
&
cmd
);
cmd
.
driver
=
ccard
->
myid
;
cmd
.
command
=
ISDN_STAT_FAXIND
;
cmd
.
arg
=
chan
->
No
;
chan
->
fax
->
r_code
=
ISDN_TTY_FAX_FCON
;
ccard
->
interface
.
statcallb
(
&
cmd
);
cmd
.
driver
=
ccard
->
myid
;
cmd
.
command
=
ISDN_STAT_FAXIND
;
cmd
.
arg
=
chan
->
No
;
chan
->
fax
->
r_code
=
ISDN_TTY_FAX_RID
;
ccard
->
interface
.
statcallb
(
&
cmd
);
cmd
.
driver
=
ccard
->
myid
;
cmd
.
command
=
ISDN_STAT_FAXIND
;
cmd
.
arg
=
chan
->
No
;
chan
->
fax
->
r_code
=
ISDN_TTY_FAX_DIS
;
ccard
->
interface
.
statcallb
(
&
cmd
);
if
(
chan
->
fax
->
r_compression
!=
0
)
{
/* telling fake compression in second DIS message */
chan
->
fax
->
r_compression
=
0
;
cmd
.
driver
=
ccard
->
myid
;
cmd
.
command
=
ISDN_STAT_FAXIND
;
cmd
.
arg
=
chan
->
No
;
chan
->
fax
->
r_code
=
ISDN_TTY_FAX_DIS
;
ccard
->
interface
.
statcallb
(
&
cmd
);
}
cmd
.
driver
=
ccard
->
myid
;
cmd
.
command
=
ISDN_STAT_FAXIND
;
cmd
.
arg
=
chan
->
No
;
chan
->
fax
->
r_code
=
ISDN_TTY_FAX_SENT
;
/* OK message */
ccard
->
interface
.
statcallb
(
&
cmd
);
}
else
if
(
chan
->
fax
->
phase
==
ISDN_FAX_PHASE_D
)
{
if
((
chan
->
fax
->
code
==
EDATA_T30_MCF
)
&&
(
chan
->
fax
->
fet
!=
2
))
{
cmd
.
driver
=
ccard
->
myid
;
cmd
.
command
=
ISDN_STAT_FAXIND
;
cmd
.
arg
=
chan
->
No
;
chan
->
fax
->
r_code
=
ISDN_TTY_FAX_PTS
;
ccard
->
interface
.
statcallb
(
&
cmd
);
}
switch
(
chan
->
fax
->
fet
)
{
case
0
:
/* new page */
/* stay in phase D , wait on cmd +FDT */
break
;
case
1
:
/* new document */
/* link-level switch to phase B */
break
;
case
2
:
/* session end */
default:
/* send_edata produces error on some */
/* fax-machines here, so we don't */
/* idi_send_edata(ccard, chan); */
break
;
}
}
}
if
(
chan
->
fax
->
direction
==
ISDN_TTY_FAX_CONN_IN
)
{
idi_parse_edata
(
ccard
,
chan
,
buffer
,
len
);
if
((
chan
->
fax
->
code
==
EDATA_T30_DCS
)
&&
(
chan
->
fax
->
phase
==
ISDN_FAX_PHASE_A
))
{
idi_reset_fax_stat
(
chan
);
cmd
.
driver
=
ccard
->
myid
;
cmd
.
command
=
ISDN_STAT_BCONN
;
cmd
.
arg
=
chan
->
No
;
strcpy
(
cmd
.
parm
.
num
,
""
);
ccard
->
interface
.
statcallb
(
&
cmd
);
cmd
.
driver
=
ccard
->
myid
;
cmd
.
command
=
ISDN_STAT_FAXIND
;
cmd
.
arg
=
chan
->
No
;
chan
->
fax
->
r_code
=
ISDN_TTY_FAX_FCON_I
;
ccard
->
interface
.
statcallb
(
&
cmd
);
}
else
if
((
chan
->
fax
->
code
==
EDATA_T30_TRAIN_OK
)
&&
(
chan
->
fax
->
phase
==
ISDN_FAX_PHASE_A
))
{
cmd
.
driver
=
ccard
->
myid
;
cmd
.
command
=
ISDN_STAT_FAXIND
;
cmd
.
arg
=
chan
->
No
;
chan
->
fax
->
r_code
=
ISDN_TTY_FAX_RID
;
ccard
->
interface
.
statcallb
(
&
cmd
);
cmd
.
driver
=
ccard
->
myid
;
cmd
.
command
=
ISDN_STAT_FAXIND
;
cmd
.
arg
=
chan
->
No
;
chan
->
fax
->
r_code
=
ISDN_TTY_FAX_TRAIN_OK
;
ccard
->
interface
.
statcallb
(
&
cmd
);
}
else
if
((
chan
->
fax
->
code
==
EDATA_T30_TRAIN_OK
)
&&
(
chan
->
fax
->
phase
==
ISDN_FAX_PHASE_B
))
{
cmd
.
driver
=
ccard
->
myid
;
cmd
.
command
=
ISDN_STAT_FAXIND
;
cmd
.
arg
=
chan
->
No
;
chan
->
fax
->
r_code
=
ISDN_TTY_FAX_TRAIN_OK
;
ccard
->
interface
.
statcallb
(
&
cmd
);
}
else
if
(
chan
->
fax
->
phase
==
ISDN_FAX_PHASE_C
)
{
switch
(
chan
->
fax
->
code
)
{
case
EDATA_T30_TRAIN_OK
:
idi_send_edata
(
ccard
,
chan
);
break
;
case
EDATA_T30_MPS
:
chan
->
fax
->
fet
=
0
;
idi_edata_rcveop
(
ccard
,
chan
);
break
;
case
EDATA_T30_EOM
:
chan
->
fax
->
fet
=
1
;
idi_edata_rcveop
(
ccard
,
chan
);
break
;
case
EDATA_T30_EOP
:
chan
->
fax
->
fet
=
2
;
idi_edata_rcveop
(
ccard
,
chan
);
break
;
}
}
}
}
void
fax_put_rcv
(
eicon_card
*
ccard
,
eicon_chan
*
chan
,
u_char
*
Data
,
int
len
)
{
struct
sk_buff
*
skb
;
skb
=
alloc_skb
(
len
+
MAX_HEADER_LEN
,
GFP_ATOMIC
);
if
(
!
skb
)
{
eicon_log
(
ccard
,
1
,
"idi_err: Ch%d: alloc_skb failed in fax_put_rcv()
\n
"
,
chan
->
No
);
return
;
}
skb_reserve
(
skb
,
MAX_HEADER_LEN
);
memcpy
(
skb_put
(
skb
,
len
),
Data
,
len
);
ccard
->
interface
.
rcvcallb_skb
(
ccard
->
myid
,
chan
->
No
,
skb
);
}
void
idi_faxdata_rcv
(
eicon_card
*
ccard
,
eicon_chan
*
chan
,
struct
sk_buff
*
skb
)
{
eicon_OBJBUFFER
InBuf
;
eicon_OBJBUFFER
LineBuf
;
unsigned
int
Length
=
0
;
unsigned
int
aLength
=
0
;
unsigned
int
ObjectSize
=
0
;
unsigned
int
ObjHeadLen
=
0
;
unsigned
int
ObjDataLen
=
0
;
__u8
Recordtype
;
__u8
PageHeaderLen
;
__u8
Event
;
eicon_sff_pagehead
*
ob_page
;
__u16
Cl2Eol
=
0x8000
;
# define EVENT_NONE 0
# define EVENT_NEEDDATA 1
if
(
!
chan
->
fax
)
{
eicon_log
(
ccard
,
1
,
"idi_fax: rcvdata with NULL fax struct, ERROR
\n
"
);
return
;
}
if
(
chan
->
fax
->
direction
==
ISDN_TTY_FAX_CONN_IN
)
{
InBuf
.
Data
=
skb
->
data
;
InBuf
.
Size
=
skb
->
len
;
InBuf
.
Len
=
0
;
InBuf
.
Next
=
InBuf
.
Data
;
LineBuf
.
Data
=
chan
->
fax2
.
abLine
;
LineBuf
.
Size
=
sizeof
(
chan
->
fax2
.
abLine
);
LineBuf
.
Len
=
chan
->
fax2
.
LineLen
;
LineBuf
.
Next
=
LineBuf
.
Data
+
LineBuf
.
Len
;
Event
=
EVENT_NONE
;
while
(
Event
==
EVENT_NONE
)
{
switch
(
chan
->
fax2
.
NextObject
)
{
case
FAX_OBJECT_DOCU
:
Length
=
LineBuf
.
Len
+
(
InBuf
.
Size
-
InBuf
.
Len
);
if
(
Length
<
sizeof
(
eicon_sff_dochead
))
{
Event
=
EVENT_NEEDDATA
;
break
;
}
ObjectSize
=
sizeof
(
eicon_sff_dochead
);
Length
=
ObjectSize
;
if
(
LineBuf
.
Len
<
Length
)
{
Length
-=
LineBuf
.
Len
;
LineBuf
.
Len
=
0
;
LineBuf
.
Next
=
LineBuf
.
Data
;
InBuf
.
Len
+=
Length
;
InBuf
.
Next
+=
Length
;
}
else
{
LineBuf
.
Len
-=
Length
;
LineBuf
.
Next
=
LineBuf
.
Data
+
LineBuf
.
Len
;
memmove
(
LineBuf
.
Data
,
LineBuf
.
Data
+
Length
,
LineBuf
.
Len
);
}
chan
->
fax2
.
PrevObject
=
FAX_OBJECT_DOCU
;
chan
->
fax2
.
NextObject
=
FAX_OBJECT_PAGE
;
break
;
case
FAX_OBJECT_PAGE
:
Length
=
LineBuf
.
Len
+
(
InBuf
.
Size
-
InBuf
.
Len
);
if
(
Length
<
2
)
{
Event
=
EVENT_NEEDDATA
;
break
;
}
if
(
LineBuf
.
Len
==
0
)
{
*
LineBuf
.
Next
++
=
*
InBuf
.
Next
++
;
LineBuf
.
Len
++
;
InBuf
.
Len
++
;
}
if
(
LineBuf
.
Len
==
1
)
{
*
LineBuf
.
Next
++
=
*
InBuf
.
Next
++
;
LineBuf
.
Len
++
;
InBuf
.
Len
++
;
}
PageHeaderLen
=
*
(
LineBuf
.
Data
+
1
);
ObjectSize
=
(
PageHeaderLen
==
0
)
?
2
:
sizeof
(
eicon_sff_pagehead
);
if
(
Length
<
ObjectSize
)
{
Event
=
EVENT_NEEDDATA
;
break
;
}
Length
=
ObjectSize
;
/* extract page dimensions */
if
(
LineBuf
.
Len
<
Length
)
{
aLength
=
Length
-
LineBuf
.
Len
;
memcpy
(
LineBuf
.
Next
,
InBuf
.
Next
,
aLength
);
LineBuf
.
Next
+=
aLength
;
InBuf
.
Next
+=
aLength
;
LineBuf
.
Len
+=
aLength
;
InBuf
.
Len
+=
aLength
;
}
if
(
Length
>
2
)
{
ob_page
=
(
eicon_sff_pagehead
*
)
LineBuf
.
Data
;
switch
(
ob_page
->
linelength
)
{
case
2048
:
chan
->
fax
->
r_width
=
1
;
break
;
case
2432
:
chan
->
fax
->
r_width
=
2
;
break
;
case
1216
:
chan
->
fax
->
r_width
=
3
;
break
;
case
864
:
chan
->
fax
->
r_width
=
4
;
break
;
case
1728
:
default:
chan
->
fax
->
r_width
=
0
;
}
switch
(
ob_page
->
pagelength
)
{
case
1143
:
case
2287
:
chan
->
fax
->
r_length
=
0
;
break
;
case
1401
:
case
2802
:
chan
->
fax
->
r_length
=
1
;
break
;
default:
chan
->
fax
->
r_length
=
2
;
}
eicon_log
(
ccard
,
128
,
"rSFF-Head: linelength = %d
\n
"
,
ob_page
->
linelength
);
eicon_log
(
ccard
,
128
,
"rSFF-Head: pagelength = %d
\n
"
,
ob_page
->
pagelength
);
}
LineBuf
.
Len
-=
Length
;
LineBuf
.
Next
=
LineBuf
.
Data
+
LineBuf
.
Len
;
memmove
(
LineBuf
.
Data
,
LineBuf
.
Data
+
Length
,
LineBuf
.
Len
);
chan
->
fax2
.
PrevObject
=
FAX_OBJECT_PAGE
;
chan
->
fax2
.
NextObject
=
FAX_OBJECT_LINE
;
break
;
case
FAX_OBJECT_LINE
:
Length
=
LineBuf
.
Len
+
(
InBuf
.
Size
-
InBuf
.
Len
);
if
(
Length
<
1
)
{
Event
=
EVENT_NEEDDATA
;
break
;
}
if
(
LineBuf
.
Len
==
0
)
{
*
LineBuf
.
Next
++
=
*
InBuf
.
Next
++
;
LineBuf
.
Len
++
;
InBuf
.
Len
++
;
}
Recordtype
=
*
LineBuf
.
Data
;
if
(
Recordtype
==
0
)
{
/* recordtype pixel row (2 byte length) */
ObjHeadLen
=
3
;
if
(
Length
<
ObjHeadLen
)
{
Event
=
EVENT_NEEDDATA
;
break
;
}
while
(
LineBuf
.
Len
<
ObjHeadLen
)
{
*
LineBuf
.
Next
++
=
*
InBuf
.
Next
++
;
LineBuf
.
Len
++
;
InBuf
.
Len
++
;
}
ObjDataLen
=
*
((
__u16
*
)
(
LineBuf
.
Data
+
1
));
ObjectSize
=
ObjHeadLen
+
ObjDataLen
;
if
(
Length
<
ObjectSize
)
{
Event
=
EVENT_NEEDDATA
;
break
;
}
}
else
if
((
Recordtype
>=
1
)
&&
(
Recordtype
<=
216
))
{
/* recordtype pixel row (1 byte length) */
ObjHeadLen
=
1
;
ObjDataLen
=
Recordtype
;
ObjectSize
=
ObjHeadLen
+
ObjDataLen
;
if
(
Length
<
ObjectSize
)
{
Event
=
EVENT_NEEDDATA
;
break
;
}
}
else
if
((
Recordtype
>=
217
)
&&
(
Recordtype
<=
253
))
{
/* recordtype empty lines */
ObjHeadLen
=
1
;
ObjDataLen
=
0
;
ObjectSize
=
ObjHeadLen
+
ObjDataLen
;
LineBuf
.
Len
--
;
LineBuf
.
Next
=
LineBuf
.
Data
+
LineBuf
.
Len
;
memmove
(
LineBuf
.
Data
,
LineBuf
.
Data
+
1
,
LineBuf
.
Len
);
break
;
}
else
if
(
Recordtype
==
254
)
{
/* recordtype page header */
chan
->
fax2
.
PrevObject
=
FAX_OBJECT_LINE
;
chan
->
fax2
.
NextObject
=
FAX_OBJECT_PAGE
;
break
;
}
else
{
/* recordtype user information */
ObjHeadLen
=
2
;
if
(
Length
<
ObjHeadLen
)
{
Event
=
EVENT_NEEDDATA
;
break
;
}
while
(
LineBuf
.
Len
<
ObjHeadLen
)
{
*
LineBuf
.
Next
++
=
*
InBuf
.
Next
++
;
LineBuf
.
Len
++
;
InBuf
.
Len
++
;
}
ObjDataLen
=
*
(
LineBuf
.
Data
+
1
);
ObjectSize
=
ObjHeadLen
+
ObjDataLen
;
if
(
ObjDataLen
==
0
)
{
/* illegal line coding */
LineBuf
.
Len
-=
ObjHeadLen
;
LineBuf
.
Next
=
LineBuf
.
Data
+
LineBuf
.
Len
;
memmove
(
LineBuf
.
Data
,
LineBuf
.
Data
+
ObjHeadLen
,
LineBuf
.
Len
);
break
;
}
else
{
/* user information */
if
(
Length
<
ObjectSize
)
{
Event
=
EVENT_NEEDDATA
;
break
;
}
Length
=
ObjectSize
;
if
(
LineBuf
.
Len
<
Length
)
{
Length
-=
LineBuf
.
Len
;
LineBuf
.
Len
=
0
;
LineBuf
.
Next
=
LineBuf
.
Data
;
InBuf
.
Len
+=
Length
;
InBuf
.
Next
+=
Length
;
}
else
{
LineBuf
.
Len
-=
Length
;
LineBuf
.
Next
=
LineBuf
.
Data
+
LineBuf
.
Len
;
memmove
(
LineBuf
.
Data
,
LineBuf
.
Data
+
Length
,
LineBuf
.
Len
);
}
}
break
;
}
Length
=
ObjectSize
;
if
(
LineBuf
.
Len
>
ObjHeadLen
)
{
fax_put_rcv
(
ccard
,
chan
,
LineBuf
.
Data
+
ObjHeadLen
,
(
LineBuf
.
Len
-
ObjHeadLen
));
}
Length
-=
LineBuf
.
Len
;
LineBuf
.
Len
=
0
;
LineBuf
.
Next
=
LineBuf
.
Data
;
if
(
Length
>
0
)
{
fax_put_rcv
(
ccard
,
chan
,
InBuf
.
Next
,
Length
);
InBuf
.
Len
+=
Length
;
InBuf
.
Next
+=
Length
;
}
fax_put_rcv
(
ccard
,
chan
,
(
__u8
*
)
&
Cl2Eol
,
sizeof
(
Cl2Eol
));
break
;
}
/* end of switch (chan->fax2.NextObject) */
}
/* end of while (Event==EVENT_NONE) */
if
(
InBuf
.
Len
<
InBuf
.
Size
)
{
Length
=
InBuf
.
Size
-
InBuf
.
Len
;
if
((
LineBuf
.
Len
+
Length
)
>
LineBuf
.
Size
)
{
eicon_log
(
ccard
,
1
,
"idi_fax: Ch%d: %d bytes dropping, small buffer
\n
"
,
chan
->
No
,
Length
);
}
else
{
memcpy
(
LineBuf
.
Next
,
InBuf
.
Next
,
Length
);
LineBuf
.
Len
+=
Length
;
}
}
chan
->
fax2
.
LineLen
=
LineBuf
.
Len
;
}
else
{
/* CONN_OUT */
/* On CONN_OUT we do not need incoming data, drop it */
/* maybe later for polling */
}
# undef EVENT_NONE
# undef EVENT_NEEDDATA
return
;
}
int
idi_fax_send_outbuf
(
eicon_card
*
ccard
,
eicon_chan
*
chan
,
eicon_OBJBUFFER
*
OutBuf
)
{
struct
sk_buff
*
skb
;
skb
=
alloc_skb
(
OutBuf
->
Len
,
GFP_ATOMIC
);
if
(
!
skb
)
{
eicon_log
(
ccard
,
1
,
"idi_err: Ch%d: alloc_skb failed in fax_send_outbuf()
\n
"
,
chan
->
No
);
return
(
-
1
);
}
memcpy
(
skb_put
(
skb
,
OutBuf
->
Len
),
OutBuf
->
Data
,
OutBuf
->
Len
);
OutBuf
->
Len
=
0
;
OutBuf
->
Next
=
OutBuf
->
Data
;
return
(
idi_send_data
(
ccard
,
chan
,
0
,
skb
,
1
,
0
));
}
int
idi_faxdata_send
(
eicon_card
*
ccard
,
eicon_chan
*
chan
,
struct
sk_buff
*
skb
)
{
isdn_ctrl
cmd
;
eicon_OBJBUFFER
InBuf
;
__u8
InData
;
__u8
InMask
;
eicon_OBJBUFFER
OutBuf
;
eicon_OBJBUFFER
LineBuf
;
__u32
LineData
;
unsigned
int
LineDataLen
;
__u8
Byte
;
__u8
Event
;
int
ret
=
1
;
# define EVENT_NONE 0
# define EVENT_EOD 1
# define EVENT_EOL 2
# define EVENT_EOP 3
if
((
!
ccard
)
||
(
!
chan
))
return
-
1
;
if
(
!
chan
->
fax
)
{
eicon_log
(
ccard
,
1
,
"idi_fax: senddata with NULL fax struct, ERROR
\n
"
);
return
-
1
;
}
if
(
chan
->
fax
->
direction
==
ISDN_TTY_FAX_CONN_IN
)
{
/* Simply ignore any data written in data mode when receiving a fax. */
/* This is not completely correct because only XON's should come here. */
dev_kfree_skb
(
skb
);
return
1
;
}
if
(
chan
->
fax
->
phase
!=
ISDN_FAX_PHASE_C
)
{
dev_kfree_skb
(
skb
);
return
1
;
}
if
(
chan
->
queued
+
skb
->
len
>
1200
)
return
0
;
if
(
chan
->
pqueued
>
1
)
return
0
;
InBuf
.
Data
=
skb
->
data
;
InBuf
.
Size
=
skb
->
len
;
InBuf
.
Len
=
0
;
InBuf
.
Next
=
InBuf
.
Data
;
InData
=
0
;
InMask
=
0
;
LineBuf
.
Data
=
chan
->
fax2
.
abLine
;
LineBuf
.
Size
=
sizeof
(
chan
->
fax2
.
abLine
);
LineBuf
.
Len
=
chan
->
fax2
.
LineLen
;
LineBuf
.
Next
=
LineBuf
.
Data
+
LineBuf
.
Len
;
LineData
=
chan
->
fax2
.
LineData
;
LineDataLen
=
chan
->
fax2
.
LineDataLen
;
OutBuf
.
Data
=
chan
->
fax2
.
abFrame
;
OutBuf
.
Size
=
sizeof
(
chan
->
fax2
.
abFrame
);
OutBuf
.
Len
=
0
;
OutBuf
.
Next
=
OutBuf
.
Data
;
Event
=
EVENT_NONE
;
chan
->
fax2
.
Eop
=
0
;
for
(;;)
{
for
(;;)
{
if
(
InMask
==
0
)
{
if
(
InBuf
.
Len
>=
InBuf
.
Size
)
{
Event
=
EVENT_EOD
;
break
;
}
if
((
chan
->
fax2
.
Dle
!=
_DLE_
)
&&
*
InBuf
.
Next
==
_DLE_
)
{
chan
->
fax2
.
Dle
=
_DLE_
;
InBuf
.
Next
++
;
InBuf
.
Len
++
;
if
(
InBuf
.
Len
>=
InBuf
.
Size
)
{
Event
=
EVENT_EOD
;
break
;
}
}
if
(
chan
->
fax2
.
Dle
==
_DLE_
)
{
chan
->
fax2
.
Dle
=
0
;
if
(
*
InBuf
.
Next
==
_ETX_
)
{
Event
=
EVENT_EOP
;
break
;
}
else
if
(
*
InBuf
.
Next
==
_DLE_
)
{
/* do nothing */
}
else
{
eicon_log
(
ccard
,
1
,
"idi_err: Ch%d: unknown DLE escape %02x found
\n
"
,
chan
->
No
,
*
InBuf
.
Next
);
InBuf
.
Next
++
;
InBuf
.
Len
++
;
if
(
InBuf
.
Len
>=
InBuf
.
Size
)
{
Event
=
EVENT_EOD
;
break
;
}
}
}
InBuf
.
Len
++
;
InData
=
*
InBuf
.
Next
++
;
InMask
=
(
chan
->
fax
->
bor
)
?
0x80
:
0x01
;
}
while
(
InMask
)
{
LineData
>>=
1
;
LineDataLen
++
;
if
(
InData
&
InMask
)
LineData
|=
0x80000000
;
if
(
chan
->
fax
->
bor
)
InMask
>>=
1
;
else
InMask
<<=
1
;
if
((
LineDataLen
>=
T4_EOL_BITSIZE
)
&&
((
LineData
&
T4_EOL_MASK_DWORD
)
==
T4_EOL_DWORD
))
{
Event
=
EVENT_EOL
;
if
(
LineDataLen
>
T4_EOL_BITSIZE
)
{
Byte
=
(
__u8
)
((
LineData
&
~
T4_EOL_MASK_DWORD
)
>>
(
32
-
LineDataLen
));
if
(
Byte
==
0
)
{
if
(
!
chan
->
fax2
.
NullByteExist
)
{
chan
->
fax2
.
NullBytesPos
=
LineBuf
.
Len
;
chan
->
fax2
.
NullByteExist
=
1
;
}
}
else
{
chan
->
fax2
.
NullByteExist
=
0
;
}
if
(
LineBuf
.
Len
<
LineBuf
.
Size
)
{
*
LineBuf
.
Next
++
=
Byte
;
LineBuf
.
Len
++
;
}
}
LineDataLen
=
0
;
break
;
}
if
(
LineDataLen
>=
T4_EOL_BITSIZE
+
8
)
{
Byte
=
(
__u8
)
((
LineData
&
~
T4_EOL_MASK_DWORD
)
>>
(
32
-
T4_EOL_BITSIZE
-
8
));
LineData
&=
T4_EOL_MASK_DWORD
;
LineDataLen
=
T4_EOL_BITSIZE
;
if
(
Byte
==
0
)
{
if
(
!
chan
->
fax2
.
NullByteExist
)
{
chan
->
fax2
.
NullBytesPos
=
LineBuf
.
Len
;
chan
->
fax2
.
NullByteExist
=
1
;
}
}
else
{
chan
->
fax2
.
NullByteExist
=
0
;
}
if
(
LineBuf
.
Len
<
LineBuf
.
Size
)
{
*
LineBuf
.
Next
++
=
Byte
;
LineBuf
.
Len
++
;
}
}
}
if
(
Event
!=
EVENT_NONE
)
break
;
}
if
((
Event
!=
EVENT_EOL
)
&&
(
Event
!=
EVENT_EOP
))
break
;
if
((
Event
==
EVENT_EOP
)
&&
(
LineDataLen
>
0
))
{
LineData
>>=
32
-
LineDataLen
;
LineDataLen
=
0
;
while
(
LineData
!=
0
)
{
Byte
=
(
__u8
)
LineData
;
LineData
>>=
8
;
if
(
Byte
==
0
)
{
if
(
!
chan
->
fax2
.
NullByteExist
)
{
chan
->
fax2
.
NullBytesPos
=
LineBuf
.
Len
;
chan
->
fax2
.
NullByteExist
=
1
;
}
}
else
{
chan
->
fax2
.
NullByteExist
=
0
;
}
if
(
LineBuf
.
Len
<
LineBuf
.
Size
)
{
*
LineBuf
.
Next
++
=
Byte
;
LineBuf
.
Len
++
;
}
}
}
if
(
chan
->
fax2
.
NullByteExist
)
{
if
(
chan
->
fax2
.
NullBytesPos
==
0
)
{
LineBuf
.
Len
=
0
;
}
else
{
LineBuf
.
Len
=
chan
->
fax2
.
NullBytesPos
+
1
;
}
}
if
(
LineBuf
.
Len
>
0
)
{
if
(
OutBuf
.
Len
+
LineBuf
.
Len
+
SFF_LEN_FLD_SIZE
>
OutBuf
.
Size
)
{
ret
=
idi_fax_send_outbuf
(
ccard
,
chan
,
&
OutBuf
);
}
if
(
LineBuf
.
Len
<=
216
)
{
*
OutBuf
.
Next
++
=
(
__u8
)
LineBuf
.
Len
;
OutBuf
.
Len
++
;
}
else
{
*
OutBuf
.
Next
++
=
0
;
*
((
__u16
*
)
OutBuf
.
Next
)
++
=
(
__u16
)
LineBuf
.
Len
;
OutBuf
.
Len
+=
3
;
}
memcpy
(
OutBuf
.
Next
,
LineBuf
.
Data
,
LineBuf
.
Len
);
OutBuf
.
Next
+=
LineBuf
.
Len
;
OutBuf
.
Len
+=
LineBuf
.
Len
;
}
LineBuf
.
Len
=
0
;
LineBuf
.
Next
=
LineBuf
.
Data
;
chan
->
fax2
.
NullByteExist
=
0
;
if
(
Event
==
EVENT_EOP
)
break
;
Event
=
EVENT_NONE
;
}
if
(
Event
==
EVENT_EOP
)
{
chan
->
fax2
.
Eop
=
1
;
chan
->
fax2
.
PageCount
++
;
cmd
.
driver
=
ccard
->
myid
;
cmd
.
command
=
ISDN_STAT_FAXIND
;
cmd
.
arg
=
chan
->
No
;
chan
->
fax
->
r_code
=
ISDN_TTY_FAX_EOP
;
ccard
->
interface
.
statcallb
(
&
cmd
);
}
if
(
OutBuf
.
Len
>
0
)
{
ret
=
idi_fax_send_outbuf
(
ccard
,
chan
,
&
OutBuf
);
}
chan
->
fax2
.
LineLen
=
LineBuf
.
Len
;
chan
->
fax2
.
LineData
=
LineData
;
chan
->
fax2
.
LineDataLen
=
LineDataLen
;
# undef EVENT_NONE
# undef EVENT_EOD
# undef EVENT_EOL
# undef EVENT_EOP
if
(
ret
>=
0
)
dev_kfree_skb
(
skb
);
if
(
ret
==
0
)
ret
=
1
;
return
(
ret
);
}
void
idi_fax_hangup
(
eicon_card
*
ccard
,
eicon_chan
*
chan
)
{
isdn_ctrl
cmd
;
if
(
!
chan
->
fax
)
{
eicon_log
(
ccard
,
1
,
"idi_fax: hangup with NULL fax struct, ERROR
\n
"
);
return
;
}
if
((
chan
->
fax
->
direction
==
ISDN_TTY_FAX_CONN_OUT
)
&&
(
chan
->
fax
->
code
==
0
))
{
cmd
.
driver
=
ccard
->
myid
;
cmd
.
command
=
ISDN_STAT_FAXIND
;
cmd
.
arg
=
chan
->
No
;
chan
->
fax
->
r_code
=
ISDN_TTY_FAX_PTS
;
ccard
->
interface
.
statcallb
(
&
cmd
);
}
if
((
chan
->
fax
->
code
>
1
)
&&
(
chan
->
fax
->
code
<
120
))
chan
->
fax
->
code
+=
120
;
eicon_log
(
ccard
,
8
,
"idi_fax: Ch%d: Hangup (code=%d)
\n
"
,
chan
->
No
,
chan
->
fax
->
code
);
chan
->
fax
->
r_code
=
ISDN_TTY_FAX_HNG
;
cmd
.
driver
=
ccard
->
myid
;
cmd
.
command
=
ISDN_STAT_FAXIND
;
cmd
.
arg
=
chan
->
No
;
ccard
->
interface
.
statcallb
(
&
cmd
);
}
#endif
/******** FAX ********/
int
idi_send_udata
(
eicon_card
*
card
,
eicon_chan
*
chan
,
int
UReq
,
u_char
*
buffer
,
int
len
)
{
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb2
;
eicon_REQ
*
reqbuf
;
eicon_chan_ptr
*
chan2
;
if
((
chan
->
fsm_state
==
EICON_STATE_NULL
)
||
(
chan
->
fsm_state
==
EICON_STATE_LISTEN
))
{
eicon_log
(
card
,
1
,
"idi_snd: Ch%d: send udata on state %d !
\n
"
,
chan
->
No
,
chan
->
fsm_state
);
return
-
ENODEV
;
}
eicon_log
(
card
,
8
,
"idi_snd: Ch%d: udata 0x%x: %d %d %d %d
\n
"
,
chan
->
No
,
UReq
,
buffer
[
0
],
buffer
[
1
],
buffer
[
2
],
buffer
[
3
]);
skb
=
alloc_skb
(
sizeof
(
eicon_REQ
)
+
len
+
1
,
GFP_ATOMIC
);
skb2
=
alloc_skb
(
sizeof
(
eicon_chan_ptr
),
GFP_ATOMIC
);
if
((
!
skb
)
||
(
!
skb2
))
{
eicon_log
(
card
,
1
,
"idi_err: Ch%d: alloc_skb failed in send_udata()
\n
"
,
chan
->
No
);
if
(
skb
)
dev_kfree_skb
(
skb
);
if
(
skb2
)
dev_kfree_skb
(
skb2
);
return
-
ENOMEM
;
}
chan2
=
(
eicon_chan_ptr
*
)
skb_put
(
skb2
,
sizeof
(
eicon_chan_ptr
));
chan2
->
ptr
=
chan
;
reqbuf
=
(
eicon_REQ
*
)
skb_put
(
skb
,
1
+
len
+
sizeof
(
eicon_REQ
));
reqbuf
->
Req
=
N_UDATA
;
reqbuf
->
ReqCh
=
chan
->
e
.
IndCh
;
reqbuf
->
ReqId
=
1
;
reqbuf
->
XBuffer
.
length
=
len
+
1
;
reqbuf
->
XBuffer
.
P
[
0
]
=
UReq
;
memcpy
(
&
reqbuf
->
XBuffer
.
P
[
1
],
buffer
,
len
);
reqbuf
->
Reference
=
1
;
/* Net Entity */
skb_queue_tail
(
&
chan
->
e
.
X
,
skb
);
skb_queue_tail
(
&
card
->
sndq
,
skb2
);
eicon_schedule_tx
(
card
);
return
(
0
);
}
void
idi_audio_cmd
(
eicon_card
*
ccard
,
eicon_chan
*
chan
,
int
cmd
,
u_char
*
value
)
{
u_char
buf
[
6
];
struct
enable_dtmf_s
*
dtmf_buf
=
(
struct
enable_dtmf_s
*
)
buf
;
if
((
!
ccard
)
||
(
!
chan
))
return
;
memset
(
buf
,
0
,
6
);
switch
(
cmd
)
{
case
ISDN_AUDIO_SETDD
:
if
(
value
[
0
])
{
dtmf_buf
->
tone
=
(
__u16
)
(
value
[
1
]
*
5
);
dtmf_buf
->
gap
=
(
__u16
)
(
value
[
1
]
*
5
);
idi_send_udata
(
ccard
,
chan
,
DSP_UDATA_REQUEST_ENABLE_DTMF_RECEIVER
,
buf
,
4
);
}
else
{
idi_send_udata
(
ccard
,
chan
,
DSP_UDATA_REQUEST_DISABLE_DTMF_RECEIVER
,
buf
,
0
);
}
break
;
}
}
void
idi_parse_udata
(
eicon_card
*
ccard
,
eicon_chan
*
chan
,
unsigned
char
*
buffer
,
int
len
)
{
isdn_ctrl
cmd
;
eicon_dsp_ind
*
p
=
(
eicon_dsp_ind
*
)
(
&
buffer
[
1
]);
static
char
*
connmsg
[]
=
{
""
,
"V.21"
,
"V.23"
,
"V.22"
,
"V.22bis"
,
"V.32bis"
,
"V.34"
,
"V.8"
,
"Bell 212A"
,
"Bell 103"
,
"V.29 Leased"
,
"V.33 Leased"
,
"V.90"
,
"V.21 CH2"
,
"V.27ter"
,
"V.29"
,
"V.33"
,
"V.17"
,
"V.32"
,
"K56Flex"
,
"X2"
,
"V.18"
,
"V.18LH"
,
"V.18HL"
,
"V.21LH"
,
"V.21HL"
,
"Bell 103LH"
,
"Bell 103HL"
,
"V.23"
,
"V.23"
,
"EDT 110"
,
"Baudot45"
,
"Baudot47"
,
"Baudot50"
,
"DTMF"
};
static
u_char
dtmf_code
[]
=
{
'1'
,
'4'
,
'7'
,
'*'
,
'2'
,
'5'
,
'8'
,
'0'
,
'3'
,
'6'
,
'9'
,
'#'
,
'A'
,
'B'
,
'C'
,
'D'
};
if
((
!
ccard
)
||
(
!
chan
))
return
;
switch
(
buffer
[
0
])
{
case
DSP_UDATA_INDICATION_SYNC
:
eicon_log
(
ccard
,
16
,
"idi_ind: Ch%d: UDATA_SYNC time %d
\n
"
,
chan
->
No
,
p
->
time
);
break
;
case
DSP_UDATA_INDICATION_DCD_OFF
:
eicon_log
(
ccard
,
8
,
"idi_ind: Ch%d: UDATA_DCD_OFF time %d
\n
"
,
chan
->
No
,
p
->
time
);
break
;
case
DSP_UDATA_INDICATION_DCD_ON
:
if
((
chan
->
l2prot
==
ISDN_PROTO_L2_MODEM
)
&&
(
chan
->
fsm_state
==
EICON_STATE_WMCONN
))
{
chan
->
fsm_state
=
EICON_STATE_ACTIVE
;
cmd
.
driver
=
ccard
->
myid
;
cmd
.
command
=
ISDN_STAT_BCONN
;
cmd
.
arg
=
chan
->
No
;
if
(
p
->
norm
>
34
)
{
sprintf
(
cmd
.
parm
.
num
,
"%d/(%d)"
,
p
->
speed
,
p
->
norm
);
}
else
{
sprintf
(
cmd
.
parm
.
num
,
"%d/%s"
,
p
->
speed
,
connmsg
[
p
->
norm
]);
}
ccard
->
interface
.
statcallb
(
&
cmd
);
}
eicon_log
(
ccard
,
8
,
"idi_ind: Ch%d: UDATA_DCD_ON time %d
\n
"
,
chan
->
No
,
p
->
time
);
eicon_log
(
ccard
,
8
,
"idi_ind: Ch%d: %d %d %d %d
\n
"
,
chan
->
No
,
p
->
norm
,
p
->
options
,
p
->
speed
,
p
->
delay
);
break
;
case
DSP_UDATA_INDICATION_CTS_OFF
:
eicon_log
(
ccard
,
8
,
"idi_ind: Ch%d: UDATA_CTS_OFF time %d
\n
"
,
chan
->
No
,
p
->
time
);
break
;
case
DSP_UDATA_INDICATION_CTS_ON
:
eicon_log
(
ccard
,
8
,
"idi_ind: Ch%d: UDATA_CTS_ON time %d
\n
"
,
chan
->
No
,
p
->
time
);
eicon_log
(
ccard
,
8
,
"idi_ind: Ch%d: %d %d %d %d
\n
"
,
chan
->
No
,
p
->
norm
,
p
->
options
,
p
->
speed
,
p
->
delay
);
break
;
case
DSP_UDATA_INDICATION_DISCONNECT
:
eicon_log
(
ccard
,
8
,
"idi_ind: Ch%d: UDATA_DISCONNECT cause %d
\n
"
,
chan
->
No
,
buffer
[
1
]);
break
;
case
DSP_UDATA_INDICATION_DTMF_DIGITS_RECEIVED
:
eicon_log
(
ccard
,
8
,
"idi_ind: Ch%d: UDATA_DTMF_REC '%c'
\n
"
,
chan
->
No
,
dtmf_code
[
buffer
[
1
]]);
cmd
.
driver
=
ccard
->
myid
;
cmd
.
command
=
ISDN_STAT_AUDIO
;
cmd
.
parm
.
num
[
0
]
=
ISDN_AUDIO_DTMF
;
cmd
.
parm
.
num
[
1
]
=
dtmf_code
[
buffer
[
1
]];
cmd
.
arg
=
chan
->
No
;
ccard
->
interface
.
statcallb
(
&
cmd
);
break
;
default:
eicon_log
(
ccard
,
8
,
"idi_ind: Ch%d: UNHANDLED UDATA Indication 0x%02x
\n
"
,
chan
->
No
,
buffer
[
0
]);
}
}
void
eicon_parse_trace
(
eicon_card
*
ccard
,
unsigned
char
*
buffer
,
int
len
)
{
int
i
,
j
,
n
;
int
buflen
=
len
*
3
+
30
;
char
*
p
;
struct
trace_s
{
unsigned
long
time
;
unsigned
short
size
;
unsigned
short
code
;
unsigned
char
data
[
1
];
}
*
q
;
if
(
!
(
p
=
kmalloc
(
buflen
,
GFP_ATOMIC
)))
{
eicon_log
(
ccard
,
1
,
"idi_err: Ch??: could not allocate trace buffer
\n
"
);
return
;
}
memset
(
p
,
0
,
buflen
);
q
=
(
struct
trace_s
*
)
buffer
;
if
(
DebugVar
&
512
)
{
if
((
q
->
code
==
3
)
||
(
q
->
code
==
4
))
{
n
=
(
short
)
*
(
q
->
data
);
if
(
n
)
{
j
=
sprintf
(
p
,
"DTRC:"
);
for
(
i
=
0
;
i
<
n
;
i
++
)
{
j
+=
sprintf
(
p
+
j
,
"%02x "
,
q
->
data
[
i
+
2
]);
}
j
+=
sprintf
(
p
+
j
,
"
\n
"
);
}
}
}
else
{
j
=
sprintf
(
p
,
"XLOG: %lx %04x %04x "
,
q
->
time
,
q
->
size
,
q
->
code
);
for
(
i
=
0
;
i
<
q
->
size
;
i
++
)
{
j
+=
sprintf
(
p
+
j
,
"%02x "
,
q
->
data
[
i
]);
}
j
+=
sprintf
(
p
+
j
,
"
\n
"
);
}
if
(
strlen
(
p
))
eicon_putstatus
(
ccard
,
p
);
kfree
(
p
);
}
void
idi_handle_ind
(
eicon_card
*
ccard
,
struct
sk_buff
*
skb
)
{
int
tmp
;
char
tnum
[
64
];
int
dlev
;
int
free_buff
;
ulong
flags
;
struct
sk_buff
*
skb2
;
eicon_IND
*
ind
=
(
eicon_IND
*
)
skb
->
data
;
eicon_chan
*
chan
;
idi_ind_message
message
;
isdn_ctrl
cmd
;
if
(
!
ccard
)
{
eicon_log
(
ccard
,
1
,
"idi_err: Ch??: null card in handle_ind
\n
"
);
dev_kfree_skb
(
skb
);
return
;
}
if
((
chan
=
ccard
->
IdTable
[
ind
->
IndId
])
==
NULL
)
{
eicon_log
(
ccard
,
1
,
"idi_err: Ch??: null chan in handle_ind
\n
"
);
dev_kfree_skb
(
skb
);
return
;
}
if
((
ind
->
Ind
!=
8
)
&&
(
ind
->
Ind
!=
0xc
))
dlev
=
144
;
else
dlev
=
128
;
eicon_log
(
ccard
,
dlev
,
"idi_hdl: Ch%d: Ind=%x Id=%x Ch=%x MInd=%x MLen=%x Len=%x
\n
"
,
chan
->
No
,
ind
->
Ind
,
ind
->
IndId
,
ind
->
IndCh
,
ind
->
MInd
,
ind
->
MLength
,
ind
->
RBuffer
.
length
);
free_buff
=
1
;
/* Signal Layer */
if
(
chan
->
e
.
D3Id
==
ind
->
IndId
)
{
idi_IndParse
(
ccard
,
chan
,
&
message
,
ind
->
RBuffer
.
P
,
ind
->
RBuffer
.
length
);
switch
(
ind
->
Ind
)
{
case
HANGUP
:
eicon_log
(
ccard
,
8
,
"idi_ind: Ch%d: Hangup
\n
"
,
chan
->
No
);
while
((
skb2
=
skb_dequeue
(
&
chan
->
e
.
X
)))
{
dev_kfree_skb
(
skb2
);
}
spin_lock_irqsave
(
&
eicon_lock
,
flags
);
chan
->
queued
=
0
;
chan
->
pqueued
=
0
;
chan
->
waitq
=
0
;
chan
->
waitpq
=
0
;
spin_unlock_irqrestore
(
&
eicon_lock
,
flags
);
if
(
message
.
e_cau
[
0
]
&
0x7f
)
{
cmd
.
driver
=
ccard
->
myid
;
cmd
.
arg
=
chan
->
No
;
sprintf
(
cmd
.
parm
.
num
,
"E%02x%02x"
,
chan
->
cause
[
0
]
&
0x7f
,
message
.
e_cau
[
0
]
&
0x7f
);
cmd
.
command
=
ISDN_STAT_CAUSE
;
ccard
->
interface
.
statcallb
(
&
cmd
);
}
chan
->
cause
[
0
]
=
0
;
if
(((
chan
->
fsm_state
==
EICON_STATE_ACTIVE
)
||
(
chan
->
fsm_state
==
EICON_STATE_WMCONN
))
||
((
chan
->
l2prot
==
ISDN_PROTO_L2_FAX
)
&&
(
chan
->
fsm_state
==
EICON_STATE_OBWAIT
)))
{
chan
->
fsm_state
=
EICON_STATE_NULL
;
}
else
{
if
(
chan
->
e
.
B2Id
)
idi_do_req
(
ccard
,
chan
,
REMOVE
,
1
);
chan
->
statectrl
&=
~
WAITING_FOR_HANGUP
;
chan
->
statectrl
&=
~
IN_HOLD
;
if
(
chan
->
statectrl
&
HAVE_CONN_REQ
)
{
eicon_log
(
ccard
,
32
,
"idi_req: Ch%d: queueing delayed conn_req
\n
"
,
chan
->
No
);
chan
->
statectrl
&=
~
HAVE_CONN_REQ
;
if
((
chan
->
tskb1
)
&&
(
chan
->
tskb2
))
{
skb_queue_tail
(
&
chan
->
e
.
X
,
chan
->
tskb1
);
skb_queue_tail
(
&
ccard
->
sndq
,
chan
->
tskb2
);
eicon_schedule_tx
(
ccard
);
}
chan
->
tskb1
=
NULL
;
chan
->
tskb2
=
NULL
;
}
else
{
chan
->
fsm_state
=
EICON_STATE_NULL
;
cmd
.
driver
=
ccard
->
myid
;
cmd
.
arg
=
chan
->
No
;
cmd
.
command
=
ISDN_STAT_DHUP
;
ccard
->
interface
.
statcallb
(
&
cmd
);
eicon_idi_listen_req
(
ccard
,
chan
);
#ifdef CONFIG_ISDN_TTY_FAX
chan
->
fax
=
0
;
#endif
}
}
break
;
case
INDICATE_IND
:
eicon_log
(
ccard
,
8
,
"idi_ind: Ch%d: Indicate_Ind
\n
"
,
chan
->
No
);
if
(
chan
->
fsm_state
!=
EICON_STATE_LISTEN
)
{
eicon_log
(
ccard
,
1
,
"idi_err: Ch%d: Incoming call on wrong state (%d).
\n
"
,
chan
->
No
,
chan
->
fsm_state
);
idi_do_req
(
ccard
,
chan
,
HANGUP
,
0
);
break
;
}
chan
->
fsm_state
=
EICON_STATE_ICALL
;
idi_bc2si
(
message
.
bc
,
message
.
hlc
,
message
.
sin
,
&
chan
->
si1
,
&
chan
->
si2
);
strcpy
(
chan
->
cpn
,
message
.
cpn
+
1
);
strcpy
(
chan
->
oad
,
message
.
oad
);
strcpy
(
chan
->
dsa
,
message
.
dsa
);
strcpy
(
chan
->
osa
,
message
.
osa
);
chan
->
plan
=
message
.
plan
;
chan
->
screen
=
message
.
screen
;
try_stat_icall_again:
cmd
.
driver
=
ccard
->
myid
;
cmd
.
command
=
ISDN_STAT_ICALL
;
cmd
.
arg
=
chan
->
No
;
cmd
.
parm
.
setup
.
si1
=
chan
->
si1
;
cmd
.
parm
.
setup
.
si2
=
chan
->
si2
;
strcpy
(
tnum
,
chan
->
cpn
);
if
(
strlen
(
chan
->
dsa
))
{
strcat
(
tnum
,
"."
);
strcat
(
tnum
,
chan
->
dsa
);
}
tnum
[
ISDN_MSNLEN
-
1
]
=
0
;
strcpy
(
cmd
.
parm
.
setup
.
eazmsn
,
tnum
);
strcpy
(
tnum
,
chan
->
oad
);
if
(
strlen
(
chan
->
osa
))
{
strcat
(
tnum
,
"."
);
strcat
(
tnum
,
chan
->
osa
);
}
tnum
[
ISDN_MSNLEN
-
1
]
=
0
;
strcpy
(
cmd
.
parm
.
setup
.
phone
,
tnum
);
cmd
.
parm
.
setup
.
plan
=
chan
->
plan
;
cmd
.
parm
.
setup
.
screen
=
chan
->
screen
;
tmp
=
ccard
->
interface
.
statcallb
(
&
cmd
);
switch
(
tmp
)
{
case
0
:
/* no user responding */
idi_do_req
(
ccard
,
chan
,
HANGUP
,
0
);
chan
->
fsm_state
=
EICON_STATE_NULL
;
break
;
case
1
:
/* alert */
eicon_log
(
ccard
,
8
,
"idi_req: Ch%d: Call Alert
\n
"
,
chan
->
No
);
if
((
chan
->
fsm_state
==
EICON_STATE_ICALL
)
||
(
chan
->
fsm_state
==
EICON_STATE_ICALLW
))
{
chan
->
fsm_state
=
EICON_STATE_ICALL
;
idi_do_req
(
ccard
,
chan
,
CALL_ALERT
,
0
);
}
break
;
case
2
:
/* reject */
eicon_log
(
ccard
,
8
,
"idi_req: Ch%d: Call Reject
\n
"
,
chan
->
No
);
idi_do_req
(
ccard
,
chan
,
REJECT
,
0
);
break
;
case
3
:
/* incomplete number */
eicon_log
(
ccard
,
8
,
"idi_req: Ch%d: Incomplete Number
\n
"
,
chan
->
No
);
chan
->
fsm_state
=
EICON_STATE_ICALLW
;
break
;
}
break
;
case
INFO_IND
:
eicon_log
(
ccard
,
8
,
"idi_ind: Ch%d: Info_Ind
\n
"
,
chan
->
No
);
if
((
chan
->
fsm_state
==
EICON_STATE_ICALLW
)
&&
(
message
.
cpn
[
0
]))
{
strcat
(
chan
->
cpn
,
message
.
cpn
+
1
);
goto
try_stat_icall_again
;
}
break
;
case
CALL_IND
:
eicon_log
(
ccard
,
8
,
"idi_ind: Ch%d: Call_Ind
\n
"
,
chan
->
No
);
if
((
chan
->
fsm_state
==
EICON_STATE_ICALL
)
||
(
chan
->
fsm_state
==
EICON_STATE_IWAIT
))
{
chan
->
fsm_state
=
EICON_STATE_IBWAIT
;
cmd
.
driver
=
ccard
->
myid
;
cmd
.
command
=
ISDN_STAT_DCONN
;
cmd
.
arg
=
chan
->
No
;
ccard
->
interface
.
statcallb
(
&
cmd
);
switch
(
chan
->
l2prot
)
{
case
ISDN_PROTO_L2_FAX
:
#ifdef CONFIG_ISDN_TTY_FAX
if
(
chan
->
fax
)
chan
->
fax
->
phase
=
ISDN_FAX_PHASE_A
;
#endif
break
;
case
ISDN_PROTO_L2_MODEM
:
/* do nothing, wait for connect */
break
;
case
ISDN_PROTO_L2_V11096
:
case
ISDN_PROTO_L2_V11019
:
case
ISDN_PROTO_L2_V11038
:
case
ISDN_PROTO_L2_TRANS
:
idi_do_req
(
ccard
,
chan
,
N_CONNECT
,
1
);
break
;
default:
;
/* On most incoming calls we use automatic connect */
/* idi_do_req(ccard, chan, N_CONNECT, 1); */
}
}
else
{
if
(
chan
->
fsm_state
!=
EICON_STATE_ACTIVE
)
idi_hangup
(
ccard
,
chan
);
}
break
;
case
CALL_CON
:
eicon_log
(
ccard
,
8
,
"idi_ind: Ch%d: Call_Con
\n
"
,
chan
->
No
);
if
(
chan
->
fsm_state
==
EICON_STATE_OCALL
)
{
/* check if old NetID has been removed */
if
(
chan
->
e
.
B2Id
)
{
eicon_log
(
ccard
,
1
,
"eicon: Ch%d: old net_id %x still exist, removing.
\n
"
,
chan
->
No
,
chan
->
e
.
B2Id
);
idi_do_req
(
ccard
,
chan
,
REMOVE
,
1
);
}
#ifdef CONFIG_ISDN_TTY_FAX
if
(
chan
->
l2prot
==
ISDN_PROTO_L2_FAX
)
{
if
(
chan
->
fax
)
{
chan
->
fax
->
phase
=
ISDN_FAX_PHASE_A
;
}
else
{
eicon_log
(
ccard
,
1
,
"idi_ind: Call_Con with NULL fax struct, ERROR
\n
"
);
idi_hangup
(
ccard
,
chan
);
break
;
}
}
#endif
chan
->
fsm_state
=
EICON_STATE_OBWAIT
;
cmd
.
driver
=
ccard
->
myid
;
cmd
.
command
=
ISDN_STAT_DCONN
;
cmd
.
arg
=
chan
->
No
;
ccard
->
interface
.
statcallb
(
&
cmd
);
idi_do_req
(
ccard
,
chan
,
ASSIGN
,
1
);
idi_do_req
(
ccard
,
chan
,
N_CONNECT
,
1
);
}
else
idi_hangup
(
ccard
,
chan
);
break
;
case
AOC_IND
:
eicon_log
(
ccard
,
8
,
"idi_ind: Ch%d: Advice of Charge
\n
"
,
chan
->
No
);
break
;
case
CALL_HOLD_ACK
:
chan
->
statectrl
|=
IN_HOLD
;
eicon_log
(
ccard
,
8
,
"idi_ind: Ch%d: Call Hold Ack
\n
"
,
chan
->
No
);
break
;
case
SUSPEND_REJ
:
eicon_log
(
ccard
,
8
,
"idi_ind: Ch%d: Suspend Rejected
\n
"
,
chan
->
No
);
break
;
case
SUSPEND
:
eicon_log
(
ccard
,
8
,
"idi_ind: Ch%d: Suspend Ack
\n
"
,
chan
->
No
);
break
;
case
RESUME
:
eicon_log
(
ccard
,
8
,
"idi_ind: Ch%d: Resume Ack
\n
"
,
chan
->
No
);
break
;
default:
eicon_log
(
ccard
,
8
,
"idi_ind: Ch%d: UNHANDLED SigIndication 0x%02x
\n
"
,
chan
->
No
,
ind
->
Ind
);
}
}
/* Network Layer */
else
if
(
chan
->
e
.
B2Id
==
ind
->
IndId
)
{
if
(
chan
->
No
==
ccard
->
nchannels
)
{
/* Management Indication */
if
(
ind
->
Ind
==
0x04
)
{
/* Trace_Ind */
eicon_parse_trace
(
ccard
,
ind
->
RBuffer
.
P
,
ind
->
RBuffer
.
length
);
}
else
{
idi_IndParse
(
ccard
,
chan
,
&
message
,
ind
->
RBuffer
.
P
,
ind
->
RBuffer
.
length
);
chan
->
fsm_state
=
1
;
}
}
else
switch
(
ind
->
Ind
)
{
case
N_CONNECT_ACK
:
eicon_log
(
ccard
,
16
,
"idi_ind: Ch%d: N_Connect_Ack
\n
"
,
chan
->
No
);
if
(
chan
->
l2prot
==
ISDN_PROTO_L2_MODEM
)
{
chan
->
fsm_state
=
EICON_STATE_WMCONN
;
break
;
}
if
(
chan
->
l2prot
==
ISDN_PROTO_L2_FAX
)
{
#ifdef CONFIG_ISDN_TTY_FAX
chan
->
fsm_state
=
EICON_STATE_ACTIVE
;
idi_parse_edata
(
ccard
,
chan
,
ind
->
RBuffer
.
P
,
ind
->
RBuffer
.
length
);
if
(
chan
->
fax
)
{
if
(
chan
->
fax
->
phase
==
ISDN_FAX_PHASE_B
)
{
idi_fax_send_header
(
ccard
,
chan
,
2
);
cmd
.
driver
=
ccard
->
myid
;
cmd
.
command
=
ISDN_STAT_FAXIND
;
cmd
.
arg
=
chan
->
No
;
chan
->
fax
->
r_code
=
ISDN_TTY_FAX_DCS
;
ccard
->
interface
.
statcallb
(
&
cmd
);
}
}
else
{
eicon_log
(
ccard
,
1
,
"idi_ind: N_Connect_Ack with NULL fax struct, ERROR
\n
"
);
}
#endif
break
;
}
chan
->
fsm_state
=
EICON_STATE_ACTIVE
;
cmd
.
driver
=
ccard
->
myid
;
cmd
.
command
=
ISDN_STAT_BCONN
;
cmd
.
arg
=
chan
->
No
;
strcpy
(
cmd
.
parm
.
num
,
"64000"
);
ccard
->
interface
.
statcallb
(
&
cmd
);
break
;
case
N_CONNECT
:
eicon_log
(
ccard
,
16
,
"idi_ind: Ch%d: N_Connect
\n
"
,
chan
->
No
);
chan
->
e
.
IndCh
=
ind
->
IndCh
;
if
(
chan
->
e
.
B2Id
)
idi_do_req
(
ccard
,
chan
,
N_CONNECT_ACK
,
1
);
if
(
chan
->
l2prot
==
ISDN_PROTO_L2_FAX
)
{
break
;
}
if
(
chan
->
l2prot
==
ISDN_PROTO_L2_MODEM
)
{
chan
->
fsm_state
=
EICON_STATE_WMCONN
;
break
;
}
chan
->
fsm_state
=
EICON_STATE_ACTIVE
;
cmd
.
driver
=
ccard
->
myid
;
cmd
.
command
=
ISDN_STAT_BCONN
;
cmd
.
arg
=
chan
->
No
;
strcpy
(
cmd
.
parm
.
num
,
"64000"
);
ccard
->
interface
.
statcallb
(
&
cmd
);
break
;
case
N_DISC
:
eicon_log
(
ccard
,
16
,
"idi_ind: Ch%d: N_Disc
\n
"
,
chan
->
No
);
if
(
chan
->
e
.
B2Id
)
{
while
((
skb2
=
skb_dequeue
(
&
chan
->
e
.
X
)))
{
dev_kfree_skb
(
skb2
);
}
idi_do_req
(
ccard
,
chan
,
N_DISC_ACK
,
1
);
idi_do_req
(
ccard
,
chan
,
REMOVE
,
1
);
}
#ifdef CONFIG_ISDN_TTY_FAX
if
((
chan
->
l2prot
==
ISDN_PROTO_L2_FAX
)
&&
(
chan
->
fax
)){
idi_parse_edata
(
ccard
,
chan
,
ind
->
RBuffer
.
P
,
ind
->
RBuffer
.
length
);
idi_fax_hangup
(
ccard
,
chan
);
}
#endif
chan
->
e
.
IndCh
=
0
;
spin_lock_irqsave
(
&
eicon_lock
,
flags
);
chan
->
queued
=
0
;
chan
->
pqueued
=
0
;
chan
->
waitq
=
0
;
chan
->
waitpq
=
0
;
spin_unlock_irqrestore
(
&
eicon_lock
,
flags
);
if
(
!
(
chan
->
statectrl
&
IN_HOLD
))
{
idi_do_req
(
ccard
,
chan
,
HANGUP
,
0
);
}
if
(
chan
->
fsm_state
==
EICON_STATE_ACTIVE
)
{
cmd
.
driver
=
ccard
->
myid
;
cmd
.
command
=
ISDN_STAT_BHUP
;
cmd
.
arg
=
chan
->
No
;
ccard
->
interface
.
statcallb
(
&
cmd
);
chan
->
fsm_state
=
EICON_STATE_NULL
;
if
(
!
(
chan
->
statectrl
&
IN_HOLD
))
{
chan
->
statectrl
|=
WAITING_FOR_HANGUP
;
}
}
#ifdef CONFIG_ISDN_TTY_FAX
chan
->
fax
=
0
;
#endif
break
;
case
N_DISC_ACK
:
eicon_log
(
ccard
,
16
,
"idi_ind: Ch%d: N_Disc_Ack
\n
"
,
chan
->
No
);
#ifdef CONFIG_ISDN_TTY_FAX
if
(
chan
->
l2prot
==
ISDN_PROTO_L2_FAX
)
{
idi_parse_edata
(
ccard
,
chan
,
ind
->
RBuffer
.
P
,
ind
->
RBuffer
.
length
);
idi_fax_hangup
(
ccard
,
chan
);
}
#endif
break
;
case
N_DATA_ACK
:
eicon_log
(
ccard
,
128
,
"idi_ind: Ch%d: N_Data_Ack
\n
"
,
chan
->
No
);
break
;
case
N_DATA
:
skb_pull
(
skb
,
sizeof
(
eicon_IND
)
-
1
);
eicon_log
(
ccard
,
128
,
"idi_rcv: Ch%d: %d bytes
\n
"
,
chan
->
No
,
skb
->
len
);
if
(
chan
->
l2prot
==
ISDN_PROTO_L2_FAX
)
{
#ifdef CONFIG_ISDN_TTY_FAX
idi_faxdata_rcv
(
ccard
,
chan
,
skb
);
#endif
}
else
{
ccard
->
interface
.
rcvcallb_skb
(
ccard
->
myid
,
chan
->
No
,
skb
);
free_buff
=
0
;
}
break
;
case
N_UDATA
:
idi_parse_udata
(
ccard
,
chan
,
ind
->
RBuffer
.
P
,
ind
->
RBuffer
.
length
);
break
;
#ifdef CONFIG_ISDN_TTY_FAX
case
N_EDATA
:
idi_edata_action
(
ccard
,
chan
,
ind
->
RBuffer
.
P
,
ind
->
RBuffer
.
length
);
break
;
#endif
default:
eicon_log
(
ccard
,
8
,
"idi_ind: Ch%d: UNHANDLED NetIndication 0x%02x
\n
"
,
chan
->
No
,
ind
->
Ind
);
}
}
else
{
eicon_log
(
ccard
,
1
,
"idi_ind: Ch%d: Ind is neither SIG nor NET !
\n
"
,
chan
->
No
);
}
if
(
free_buff
)
dev_kfree_skb
(
skb
);
}
int
idi_handle_ack_ok
(
eicon_card
*
ccard
,
eicon_chan
*
chan
,
eicon_RC
*
ack
)
{
ulong
flags
;
isdn_ctrl
cmd
;
int
tqueued
=
0
;
int
twaitpq
=
0
;
if
(
ack
->
RcId
!=
((
chan
->
e
.
ReqCh
)
?
chan
->
e
.
B2Id
:
chan
->
e
.
D3Id
))
{
/* I don't know why this happens, should not ! */
/* just ignoring this RC */
eicon_log
(
ccard
,
16
,
"idi_ack: Ch%d: RcId %d not equal to last %d
\n
"
,
chan
->
No
,
ack
->
RcId
,
(
chan
->
e
.
ReqCh
)
?
chan
->
e
.
B2Id
:
chan
->
e
.
D3Id
);
return
1
;
}
/* Management Interface */
if
(
chan
->
No
==
ccard
->
nchannels
)
{
/* Managementinterface: changing state */
if
(
chan
->
e
.
Req
!=
0x02
)
chan
->
fsm_state
=
1
;
}
/* Remove an Id */
if
(
chan
->
e
.
Req
==
REMOVE
)
{
if
(
ack
->
Reference
!=
chan
->
e
.
ref
)
{
/* This should not happen anymore */
eicon_log
(
ccard
,
16
,
"idi_ack: Ch%d: Rc-Ref %d not equal to stored %d
\n
"
,
chan
->
No
,
ack
->
Reference
,
chan
->
e
.
ref
);
}
spin_lock_irqsave
(
&
eicon_lock
,
flags
);
ccard
->
IdTable
[
ack
->
RcId
]
=
NULL
;
if
(
!
chan
->
e
.
ReqCh
)
chan
->
e
.
D3Id
=
0
;
else
chan
->
e
.
B2Id
=
0
;
spin_unlock_irqrestore
(
&
eicon_lock
,
flags
);
eicon_log
(
ccard
,
16
,
"idi_ack: Ch%d: Removed : Id=%x Ch=%d (%s)
\n
"
,
chan
->
No
,
ack
->
RcId
,
ack
->
RcCh
,
(
chan
->
e
.
ReqCh
)
?
"Net"
:
"Sig"
);
return
1
;
}
/* Signal layer */
if
(
!
chan
->
e
.
ReqCh
)
{
eicon_log
(
ccard
,
16
,
"idi_ack: Ch%d: RC OK Id=%x Ch=%d (ref:%d)
\n
"
,
chan
->
No
,
ack
->
RcId
,
ack
->
RcCh
,
ack
->
Reference
);
}
else
{
/* Network layer */
switch
(
chan
->
e
.
Req
&
0x0f
)
{
case
N_CONNECT
:
chan
->
e
.
IndCh
=
ack
->
RcCh
;
eicon_log
(
ccard
,
16
,
"idi_ack: Ch%d: RC OK Id=%x Ch=%d (ref:%d)
\n
"
,
chan
->
No
,
ack
->
RcId
,
ack
->
RcCh
,
ack
->
Reference
);
break
;
case
N_MDATA
:
case
N_DATA
:
tqueued
=
chan
->
queued
;
twaitpq
=
chan
->
waitpq
;
if
((
chan
->
e
.
Req
&
0x0f
)
==
N_DATA
)
{
spin_lock_irqsave
(
&
eicon_lock
,
flags
);
chan
->
waitpq
=
0
;
if
(
chan
->
pqueued
)
chan
->
pqueued
--
;
spin_unlock_irqrestore
(
&
eicon_lock
,
flags
);
#ifdef CONFIG_ISDN_TTY_FAX
if
(
chan
->
l2prot
==
ISDN_PROTO_L2_FAX
)
{
if
(((
chan
->
queued
-
chan
->
waitq
)
<
1
)
&&
(
chan
->
fax2
.
Eop
))
{
chan
->
fax2
.
Eop
=
0
;
if
(
chan
->
fax
)
{
cmd
.
driver
=
ccard
->
myid
;
cmd
.
command
=
ISDN_STAT_FAXIND
;
cmd
.
arg
=
chan
->
No
;
chan
->
fax
->
r_code
=
ISDN_TTY_FAX_SENT
;
ccard
->
interface
.
statcallb
(
&
cmd
);
}
else
{
eicon_log
(
ccard
,
1
,
"idi_ack: Sent with NULL fax struct, ERROR
\n
"
);
}
}
}
#endif
}
spin_lock_irqsave
(
&
eicon_lock
,
flags
);
chan
->
queued
-=
chan
->
waitq
;
if
(
chan
->
queued
<
0
)
chan
->
queued
=
0
;
spin_unlock_irqrestore
(
&
eicon_lock
,
flags
);
if
(((
chan
->
e
.
Req
&
0x0f
)
==
N_DATA
)
&&
(
tqueued
))
{
cmd
.
driver
=
ccard
->
myid
;
cmd
.
command
=
ISDN_STAT_BSENT
;
cmd
.
arg
=
chan
->
No
;
cmd
.
parm
.
length
=
twaitpq
;
ccard
->
interface
.
statcallb
(
&
cmd
);
}
break
;
default:
eicon_log
(
ccard
,
16
,
"idi_ack: Ch%d: RC OK Id=%x Ch=%d (ref:%d)
\n
"
,
chan
->
No
,
ack
->
RcId
,
ack
->
RcCh
,
ack
->
Reference
);
}
}
return
1
;
}
void
idi_handle_ack
(
eicon_card
*
ccard
,
struct
sk_buff
*
skb
)
{
int
j
;
ulong
flags
;
eicon_RC
*
ack
=
(
eicon_RC
*
)
skb
->
data
;
eicon_chan
*
chan
;
isdn_ctrl
cmd
;
int
dCh
=
-
1
;
if
(
!
ccard
)
{
eicon_log
(
ccard
,
1
,
"idi_err: Ch??: null card in handle_ack
\n
"
);
dev_kfree_skb
(
skb
);
return
;
}
spin_lock_irqsave
(
&
eicon_lock
,
flags
);
if
((
chan
=
ccard
->
IdTable
[
ack
->
RcId
])
!=
NULL
)
dCh
=
chan
->
No
;
spin_unlock_irqrestore
(
&
eicon_lock
,
flags
);
switch
(
ack
->
Rc
)
{
case
OK_FC
:
case
N_FLOW_CONTROL
:
case
ASSIGN_RC
:
eicon_log
(
ccard
,
1
,
"idi_ack: Ch%d: unhandled RC 0x%x
\n
"
,
dCh
,
ack
->
Rc
);
break
;
case
READY_INT
:
case
TIMER_INT
:
/* we do nothing here */
break
;
case
OK
:
if
(
!
chan
)
{
eicon_log
(
ccard
,
1
,
"idi_ack: Ch%d: OK on chan without Id
\n
"
,
dCh
);
break
;
}
if
(
!
idi_handle_ack_ok
(
ccard
,
chan
,
ack
))
chan
=
NULL
;
break
;
case
ASSIGN_OK
:
if
(
chan
)
{
eicon_log
(
ccard
,
1
,
"idi_ack: Ch%d: ASSIGN-OK on chan already assigned (%x,%x)
\n
"
,
chan
->
No
,
chan
->
e
.
D3Id
,
chan
->
e
.
B2Id
);
}
spin_lock_irqsave
(
&
eicon_lock
,
flags
);
for
(
j
=
0
;
j
<
ccard
->
nchannels
+
1
;
j
++
)
{
if
((
ccard
->
bch
[
j
].
e
.
ref
==
ack
->
Reference
)
&&
(
ccard
->
bch
[
j
].
e
.
Req
==
ASSIGN
))
{
if
(
!
ccard
->
bch
[
j
].
e
.
ReqCh
)
ccard
->
bch
[
j
].
e
.
D3Id
=
ack
->
RcId
;
else
ccard
->
bch
[
j
].
e
.
B2Id
=
ack
->
RcId
;
ccard
->
IdTable
[
ack
->
RcId
]
=
&
ccard
->
bch
[
j
];
chan
=
&
ccard
->
bch
[
j
];
break
;
}
}
spin_unlock_irqrestore
(
&
eicon_lock
,
flags
);
eicon_log
(
ccard
,
16
,
"idi_ack: Ch%d: Id %x assigned (%s)
\n
"
,
j
,
ack
->
RcId
,
(
ccard
->
bch
[
j
].
e
.
ReqCh
)
?
"Net"
:
"Sig"
);
if
(
j
>
ccard
->
nchannels
)
{
eicon_log
(
ccard
,
24
,
"idi_ack: Ch??: ref %d not found for Id %d
\n
"
,
ack
->
Reference
,
ack
->
RcId
);
}
break
;
case
OUT_OF_RESOURCES
:
case
UNKNOWN_COMMAND
:
case
WRONG_COMMAND
:
case
WRONG_ID
:
case
ADAPTER_DEAD
:
case
WRONG_CH
:
case
UNKNOWN_IE
:
case
WRONG_IE
:
default:
if
(
!
chan
)
{
eicon_log
(
ccard
,
1
,
"idi_ack: Ch%d: Not OK !! on chan without Id
\n
"
,
dCh
);
break
;
}
else
switch
(
chan
->
e
.
Req
)
{
case
12
:
/* Alert */
eicon_log
(
ccard
,
2
,
"eicon_err: Ch%d: Alert Not OK : Rc=%d Id=%x Ch=%d
\n
"
,
dCh
,
ack
->
Rc
,
ack
->
RcId
,
ack
->
RcCh
);
break
;
default:
if
(
dCh
!=
ccard
->
nchannels
)
eicon_log
(
ccard
,
1
,
"eicon_err: Ch%d: Ack Not OK !!: Rc=%d Id=%x Ch=%d Req=%d
\n
"
,
dCh
,
ack
->
Rc
,
ack
->
RcId
,
ack
->
RcCh
,
chan
->
e
.
Req
);
}
if
(
dCh
==
ccard
->
nchannels
)
{
/* Management */
chan
->
fsm_state
=
2
;
eicon_log
(
ccard
,
8
,
"eicon_err: Ch%d: Ack Not OK !!: Rc=%d Id=%x Ch=%d Req=%d
\n
"
,
dCh
,
ack
->
Rc
,
ack
->
RcId
,
ack
->
RcCh
,
chan
->
e
.
Req
);
}
else
if
(
dCh
>=
0
)
{
/* any other channel */
/* card reports error: we hangup */
idi_hangup
(
ccard
,
chan
);
cmd
.
driver
=
ccard
->
myid
;
cmd
.
command
=
ISDN_STAT_DHUP
;
cmd
.
arg
=
chan
->
No
;
ccard
->
interface
.
statcallb
(
&
cmd
);
}
}
spin_lock_irqsave
(
&
eicon_lock
,
flags
);
if
(
chan
)
{
chan
->
e
.
ref
=
0
;
chan
->
e
.
busy
=
0
;
}
spin_unlock_irqrestore
(
&
eicon_lock
,
flags
);
dev_kfree_skb
(
skb
);
eicon_schedule_tx
(
ccard
);
}
int
idi_send_data
(
eicon_card
*
card
,
eicon_chan
*
chan
,
int
ack
,
struct
sk_buff
*
skb
,
int
que
,
int
chk
)
{
struct
sk_buff
*
xmit_skb
;
struct
sk_buff
*
skb2
;
eicon_REQ
*
reqbuf
;
eicon_chan_ptr
*
chan2
;
int
len
,
plen
=
0
,
offset
=
0
;
unsigned
long
flags
;
if
((
!
card
)
||
(
!
chan
))
{
eicon_log
(
card
,
1
,
"idi_err: Ch??: null card/chan in send_data
\n
"
);
return
-
1
;
}
if
(
chan
->
fsm_state
!=
EICON_STATE_ACTIVE
)
{
eicon_log
(
card
,
1
,
"idi_snd: Ch%d: send bytes on state %d !
\n
"
,
chan
->
No
,
chan
->
fsm_state
);
return
-
ENODEV
;
}
len
=
skb
->
len
;
if
(
len
>
EICON_MAX_QUEUE
)
/* too much for the shared memory */
return
-
1
;
if
(
!
len
)
return
0
;
if
((
chk
)
&&
(
chan
->
pqueued
>
1
))
return
0
;
eicon_log
(
card
,
128
,
"idi_snd: Ch%d: %d bytes (Pqueue=%d)
\n
"
,
chan
->
No
,
len
,
chan
->
pqueued
);
spin_lock_irqsave
(
&
eicon_lock
,
flags
);
while
(
offset
<
len
)
{
plen
=
((
len
-
offset
)
>
270
)
?
270
:
len
-
offset
;
xmit_skb
=
alloc_skb
(
plen
+
sizeof
(
eicon_REQ
),
GFP_ATOMIC
);
skb2
=
alloc_skb
(
sizeof
(
eicon_chan_ptr
),
GFP_ATOMIC
);
if
((
!
xmit_skb
)
||
(
!
skb2
))
{
spin_unlock_irqrestore
(
&
eicon_lock
,
flags
);
eicon_log
(
card
,
1
,
"idi_err: Ch%d: alloc_skb failed in send_data()
\n
"
,
chan
->
No
);
if
(
xmit_skb
)
dev_kfree_skb
(
xmit_skb
);
if
(
skb2
)
dev_kfree_skb
(
skb2
);
return
-
ENOMEM
;
}
chan2
=
(
eicon_chan_ptr
*
)
skb_put
(
skb2
,
sizeof
(
eicon_chan_ptr
));
chan2
->
ptr
=
chan
;
reqbuf
=
(
eicon_REQ
*
)
skb_put
(
xmit_skb
,
plen
+
sizeof
(
eicon_REQ
));
if
((
len
-
offset
)
>
270
)
{
reqbuf
->
Req
=
N_MDATA
;
}
else
{
reqbuf
->
Req
=
N_DATA
;
/* if (ack) reqbuf->Req |= N_D_BIT; */
}
reqbuf
->
ReqCh
=
chan
->
e
.
IndCh
;
reqbuf
->
ReqId
=
1
;
memcpy
(
&
reqbuf
->
XBuffer
.
P
,
skb
->
data
+
offset
,
plen
);
reqbuf
->
XBuffer
.
length
=
plen
;
reqbuf
->
Reference
=
1
;
/* Net Entity */
skb_queue_tail
(
&
chan
->
e
.
X
,
xmit_skb
);
skb_queue_tail
(
&
card
->
sndq
,
skb2
);
offset
+=
plen
;
}
if
(
que
)
{
chan
->
queued
+=
len
;
chan
->
pqueued
++
;
}
spin_unlock_irqrestore
(
&
eicon_lock
,
flags
);
eicon_schedule_tx
(
card
);
dev_kfree_skb
(
skb
);
return
len
;
}
int
eicon_idi_manage_assign
(
eicon_card
*
card
)
{
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb2
;
eicon_REQ
*
reqbuf
;
eicon_chan
*
chan
;
eicon_chan_ptr
*
chan2
;
chan
=
&
(
card
->
bch
[
card
->
nchannels
]);
skb
=
alloc_skb
(
270
+
sizeof
(
eicon_REQ
),
GFP_ATOMIC
);
skb2
=
alloc_skb
(
sizeof
(
eicon_chan_ptr
),
GFP_ATOMIC
);
if
((
!
skb
)
||
(
!
skb2
))
{
eicon_log
(
card
,
1
,
"idi_err: alloc_skb failed in manage_assign()
\n
"
);
if
(
skb
)
dev_kfree_skb
(
skb
);
if
(
skb2
)
dev_kfree_skb
(
skb2
);
return
-
ENOMEM
;
}
chan2
=
(
eicon_chan_ptr
*
)
skb_put
(
skb2
,
sizeof
(
eicon_chan_ptr
));
chan2
->
ptr
=
chan
;
reqbuf
=
(
eicon_REQ
*
)
skb_put
(
skb
,
270
+
sizeof
(
eicon_REQ
));
reqbuf
->
XBuffer
.
P
[
0
]
=
0
;
reqbuf
->
Req
=
ASSIGN
;
reqbuf
->
ReqCh
=
0
;
reqbuf
->
ReqId
=
MAN_ID
;
reqbuf
->
XBuffer
.
length
=
1
;
reqbuf
->
Reference
=
2
;
/* Man Entity */
skb_queue_tail
(
&
chan
->
e
.
X
,
skb
);
skb_queue_tail
(
&
card
->
sndq
,
skb2
);
eicon_schedule_tx
(
card
);
return
(
0
);
}
int
eicon_idi_manage_remove
(
eicon_card
*
card
)
{
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb2
;
eicon_REQ
*
reqbuf
;
eicon_chan
*
chan
;
eicon_chan_ptr
*
chan2
;
chan
=
&
(
card
->
bch
[
card
->
nchannels
]);
skb
=
alloc_skb
(
270
+
sizeof
(
eicon_REQ
),
GFP_ATOMIC
);
skb2
=
alloc_skb
(
sizeof
(
eicon_chan_ptr
),
GFP_ATOMIC
);
if
((
!
skb
)
||
(
!
skb2
))
{
eicon_log
(
card
,
1
,
"idi_err: alloc_skb failed in manage_remove()
\n
"
);
if
(
skb
)
dev_kfree_skb
(
skb
);
if
(
skb2
)
dev_kfree_skb
(
skb2
);
return
-
ENOMEM
;
}
chan2
=
(
eicon_chan_ptr
*
)
skb_put
(
skb2
,
sizeof
(
eicon_chan_ptr
));
chan2
->
ptr
=
chan
;
reqbuf
=
(
eicon_REQ
*
)
skb_put
(
skb
,
270
+
sizeof
(
eicon_REQ
));
reqbuf
->
Req
=
REMOVE
;
reqbuf
->
ReqCh
=
0
;
reqbuf
->
ReqId
=
1
;
reqbuf
->
XBuffer
.
length
=
0
;
reqbuf
->
Reference
=
2
;
/* Man Entity */
skb_queue_tail
(
&
chan
->
e
.
X
,
skb
);
skb_queue_tail
(
&
card
->
sndq
,
skb2
);
eicon_schedule_tx
(
card
);
return
(
0
);
}
int
eicon_idi_manage
(
eicon_card
*
card
,
eicon_manifbuf
*
mb
)
{
int
l
=
0
;
int
ret
=
0
;
unsigned
long
timeout
;
int
i
;
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb2
;
eicon_REQ
*
reqbuf
;
eicon_chan
*
chan
;
eicon_chan_ptr
*
chan2
;
chan
=
&
(
card
->
bch
[
card
->
nchannels
]);
if
(
!
(
chan
->
e
.
D3Id
))
{
chan
->
e
.
D3Id
=
1
;
while
((
skb2
=
skb_dequeue
(
&
chan
->
e
.
X
)))
dev_kfree_skb
(
skb2
);
chan
->
e
.
busy
=
0
;
if
((
ret
=
eicon_idi_manage_assign
(
card
)))
{
chan
->
e
.
D3Id
=
0
;
return
(
ret
);
}
timeout
=
jiffies
+
HZ
/
2
;
while
(
time_before
(
jiffies
,
timeout
))
{
if
(
chan
->
e
.
B2Id
)
break
;
SLEEP
(
10
);
}
if
(
!
chan
->
e
.
B2Id
)
{
chan
->
e
.
D3Id
=
0
;
return
-
EIO
;
}
}
chan
->
fsm_state
=
0
;
if
(
!
(
manbuf
=
kmalloc
(
sizeof
(
eicon_manifbuf
),
GFP_KERNEL
)))
{
eicon_log
(
card
,
1
,
"idi_err: alloc_manifbuf failed
\n
"
);
return
-
ENOMEM
;
}
if
(
copy_from_user
(
manbuf
,
mb
,
sizeof
(
eicon_manifbuf
)))
{
kfree
(
manbuf
);
return
-
EFAULT
;
}
skb
=
alloc_skb
(
270
+
sizeof
(
eicon_REQ
),
GFP_ATOMIC
);
skb2
=
alloc_skb
(
sizeof
(
eicon_chan_ptr
),
GFP_ATOMIC
);
if
((
!
skb
)
||
(
!
skb2
))
{
eicon_log
(
card
,
1
,
"idi_err_manif: alloc_skb failed in manage()
\n
"
);
if
(
skb
)
dev_kfree_skb
(
skb
);
if
(
skb2
)
dev_kfree_skb
(
skb2
);
kfree
(
manbuf
);
return
-
ENOMEM
;
}
chan2
=
(
eicon_chan_ptr
*
)
skb_put
(
skb2
,
sizeof
(
eicon_chan_ptr
));
chan2
->
ptr
=
chan
;
reqbuf
=
(
eicon_REQ
*
)
skb_put
(
skb
,
270
+
sizeof
(
eicon_REQ
));
reqbuf
->
XBuffer
.
P
[
l
++
]
=
ESC
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
6
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
0x80
;
for
(
i
=
0
;
i
<
manbuf
->
length
[
0
];
i
++
)
reqbuf
->
XBuffer
.
P
[
l
++
]
=
manbuf
->
data
[
i
];
reqbuf
->
XBuffer
.
P
[
1
]
=
manbuf
->
length
[
0
]
+
1
;
reqbuf
->
XBuffer
.
P
[
l
++
]
=
0
;
reqbuf
->
Req
=
(
manbuf
->
count
)
?
manbuf
->
count
:
MAN_READ
;
reqbuf
->
ReqCh
=
0
;
reqbuf
->
ReqId
=
1
;
reqbuf
->
XBuffer
.
length
=
l
;
reqbuf
->
Reference
=
2
;
/* Man Entity */
skb_queue_tail
(
&
chan
->
e
.
X
,
skb
);
skb_queue_tail
(
&
card
->
sndq
,
skb2
);
manbuf
->
count
=
0
;
manbuf
->
pos
=
0
;
eicon_schedule_tx
(
card
);
timeout
=
jiffies
+
HZ
/
2
;
while
(
time_before
(
jiffies
,
timeout
))
{
if
(
chan
->
fsm_state
)
break
;
SLEEP
(
10
);
}
if
((
!
chan
->
fsm_state
)
||
(
chan
->
fsm_state
==
2
))
{
kfree
(
manbuf
);
return
-
EIO
;
}
if
(
copy_to_user
(
mb
,
manbuf
,
sizeof
(
eicon_manifbuf
)))
{
kfree
(
manbuf
);
return
-
EFAULT
;
}
kfree
(
manbuf
);
return
(
0
);
}
drivers/isdn/eicon/eicon_idi.h
deleted
100644 → 0
View file @
f69c2d56
/* $Id: eicon_idi.h,v 1.1.4.1.2.2 2002/10/01 11:29:13 armin Exp $
*
* ISDN lowlevel-module for the Eicon active cards.
* IDI-Interface
*
* Copyright 1998-2000 by Armin Schindler (mac@melware.de)
* Copyright 1999,2000 Cytronics & Melware (info@melware.de)
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#ifndef E_IDI_H
#define E_IDI_H
#include <linux/config.h>
#undef N_DATA
#undef ID_MASK
#include "pc.h"
#define AOC_IND 26
/* Advice of Charge */
#define PI 0x1e
/* Progress Indicator */
#define NI 0x27
/* Notification Indicator */
#define CALL_HOLD 0x22
#define CALL_HOLD_ACK 0x24
/* defines for statectrl */
#define WAITING_FOR_HANGUP 0x01
#define HAVE_CONN_REQ 0x02
#define IN_HOLD 0x04
typedef
struct
{
char
cpn
[
32
];
char
oad
[
32
];
char
dsa
[
32
];
char
osa
[
32
];
__u8
plan
;
__u8
screen
;
__u8
sin
[
4
];
__u8
chi
[
4
];
__u8
e_chi
[
4
];
__u8
bc
[
12
];
__u8
e_bc
[
12
];
__u8
llc
[
18
];
__u8
hlc
[
5
];
__u8
cau
[
4
];
__u8
e_cau
[
2
];
__u8
e_mt
;
__u8
dt
[
6
];
char
display
[
83
];
char
keypad
[
35
];
char
rdn
[
32
];
}
idi_ind_message
;
typedef
struct
{
__u16
next
__attribute__
((
packed
));
__u8
Req
__attribute__
((
packed
));
__u8
ReqId
__attribute__
((
packed
));
__u8
ReqCh
__attribute__
((
packed
));
__u8
Reserved1
__attribute__
((
packed
));
__u16
Reference
__attribute__
((
packed
));
__u8
Reserved
[
8
]
__attribute__
((
packed
));
eicon_PBUFFER
XBuffer
;
}
eicon_REQ
;
typedef
struct
{
__u16
next
__attribute__
((
packed
));
__u8
Rc
__attribute__
((
packed
));
__u8
RcId
__attribute__
((
packed
));
__u8
RcCh
__attribute__
((
packed
));
__u8
Reserved1
__attribute__
((
packed
));
__u16
Reference
__attribute__
((
packed
));
__u8
Reserved2
[
8
]
__attribute__
((
packed
));
}
eicon_RC
;
typedef
struct
{
__u16
next
__attribute__
((
packed
));
__u8
Ind
__attribute__
((
packed
));
__u8
IndId
__attribute__
((
packed
));
__u8
IndCh
__attribute__
((
packed
));
__u8
MInd
__attribute__
((
packed
));
__u16
MLength
__attribute__
((
packed
));
__u16
Reference
__attribute__
((
packed
));
__u8
RNR
__attribute__
((
packed
));
__u8
Reserved
__attribute__
((
packed
));
__u32
Ack
__attribute__
((
packed
));
eicon_PBUFFER
RBuffer
;
}
eicon_IND
;
typedef
struct
{
__u8
*
Data
;
unsigned
int
Size
;
unsigned
int
Len
;
__u8
*
Next
;
}
eicon_OBJBUFFER
;
extern
int
idi_do_req
(
eicon_card
*
card
,
eicon_chan
*
chan
,
int
cmd
,
int
layer
);
extern
int
idi_hangup
(
eicon_card
*
card
,
eicon_chan
*
chan
);
extern
int
idi_connect_res
(
eicon_card
*
card
,
eicon_chan
*
chan
);
extern
int
eicon_idi_listen_req
(
eicon_card
*
card
,
eicon_chan
*
chan
);
extern
int
idi_connect_req
(
eicon_card
*
card
,
eicon_chan
*
chan
,
char
*
phone
,
char
*
eazmsn
,
int
si1
,
int
si2
);
extern
void
idi_handle_ack
(
eicon_card
*
card
,
struct
sk_buff
*
skb
);
extern
void
idi_handle_ind
(
eicon_card
*
card
,
struct
sk_buff
*
skb
);
extern
int
eicon_idi_manage
(
eicon_card
*
card
,
eicon_manifbuf
*
mb
);
extern
int
idi_send_data
(
eicon_card
*
card
,
eicon_chan
*
chan
,
int
ack
,
struct
sk_buff
*
skb
,
int
que
,
int
chk
);
extern
void
idi_audio_cmd
(
eicon_card
*
ccard
,
eicon_chan
*
chan
,
int
cmd
,
u_char
*
value
);
extern
int
capipmsg
(
eicon_card
*
card
,
eicon_chan
*
chan
,
capi_msg
*
cm
);
#ifdef CONFIG_ISDN_TTY_FAX
extern
void
idi_fax_cmd
(
eicon_card
*
card
,
eicon_chan
*
chan
);
extern
int
idi_faxdata_send
(
eicon_card
*
ccard
,
eicon_chan
*
chan
,
struct
sk_buff
*
skb
);
#endif
#endif
drivers/isdn/eicon/eicon_io.c
deleted
100644 → 0
View file @
f69c2d56
/* $Id: eicon_io.c,v 1.1.4.1.2.2 2002/10/01 11:29:13 armin Exp $
*
* ISDN low-level module for Eicon active ISDN-Cards.
* Code for communicating with hardware.
*
* Copyright 1999,2000 by Armin Schindler (mac@melware.de)
* Copyright 1999,2000 Cytronics & Melware (info@melware.de)
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
* Thanks to Eicon Networks for
* documents, informations and hardware.
*
*/
#include <linux/config.h>
#include "eicon.h"
#include "uxio.h"
void
eicon_io_rcv_dispatch
(
eicon_card
*
ccard
)
{
ulong
flags
;
struct
sk_buff
*
skb
,
*
skb2
,
*
skb_new
;
eicon_IND
*
ind
,
*
ind2
,
*
ind_new
;
eicon_chan
*
chan
;
if
(
!
ccard
)
{
eicon_log
(
ccard
,
1
,
"eicon_err: NULL card in rcv_dispatch !
\n
"
);
return
;
}
while
((
skb
=
skb_dequeue
(
&
ccard
->
rcvq
)))
{
ind
=
(
eicon_IND
*
)
skb
->
data
;
spin_lock_irqsave
(
&
eicon_lock
,
flags
);
if
((
chan
=
ccard
->
IdTable
[
ind
->
IndId
])
==
NULL
)
{
spin_unlock_irqrestore
(
&
eicon_lock
,
flags
);
if
(
DebugVar
&
1
)
{
switch
(
ind
->
Ind
)
{
case
N_DISC_ACK
:
/* doesn't matter if this happens */
break
;
default:
eicon_log
(
ccard
,
1
,
"idi: Indication for unknown channel Ind=%d Id=%x
\n
"
,
ind
->
Ind
,
ind
->
IndId
);
eicon_log
(
ccard
,
1
,
"idi_hdl: Ch??: Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d
\n
"
,
ind
->
Ind
,
ind
->
IndId
,
ind
->
IndCh
,
ind
->
MInd
,
ind
->
MLength
,
ind
->
RBuffer
.
length
);
}
}
dev_kfree_skb
(
skb
);
continue
;
}
spin_unlock_irqrestore
(
&
eicon_lock
,
flags
);
if
(
chan
->
e
.
complete
)
{
/* check for rec-buffer chaining */
if
(
ind
->
MLength
==
ind
->
RBuffer
.
length
)
{
chan
->
e
.
complete
=
1
;
idi_handle_ind
(
ccard
,
skb
);
continue
;
}
else
{
chan
->
e
.
complete
=
0
;
ind
->
Ind
=
ind
->
MInd
;
skb_queue_tail
(
&
chan
->
e
.
R
,
skb
);
continue
;
}
}
else
{
if
(
!
(
skb2
=
skb_dequeue
(
&
chan
->
e
.
R
)))
{
chan
->
e
.
complete
=
1
;
eicon_log
(
ccard
,
1
,
"eicon: buffer incomplete, but 0 in queue
\n
"
);
dev_kfree_skb
(
skb
);
continue
;
}
ind2
=
(
eicon_IND
*
)
skb2
->
data
;
skb_new
=
alloc_skb
(((
sizeof
(
eicon_IND
)
-
1
)
+
ind
->
RBuffer
.
length
+
ind2
->
RBuffer
.
length
),
GFP_ATOMIC
);
if
(
!
skb_new
)
{
eicon_log
(
ccard
,
1
,
"eicon_io: skb_alloc failed in rcv_dispatch()
\n
"
);
dev_kfree_skb
(
skb
);
dev_kfree_skb
(
skb2
);
continue
;
}
ind_new
=
(
eicon_IND
*
)
skb_put
(
skb_new
,
((
sizeof
(
eicon_IND
)
-
1
)
+
ind
->
RBuffer
.
length
+
ind2
->
RBuffer
.
length
));
ind_new
->
Ind
=
ind2
->
Ind
;
ind_new
->
IndId
=
ind2
->
IndId
;
ind_new
->
IndCh
=
ind2
->
IndCh
;
ind_new
->
MInd
=
ind2
->
MInd
;
ind_new
->
MLength
=
ind2
->
MLength
;
ind_new
->
RBuffer
.
length
=
ind2
->
RBuffer
.
length
+
ind
->
RBuffer
.
length
;
memcpy
(
&
ind_new
->
RBuffer
.
P
,
&
ind2
->
RBuffer
.
P
,
ind2
->
RBuffer
.
length
);
memcpy
((
&
ind_new
->
RBuffer
.
P
)
+
ind2
->
RBuffer
.
length
,
&
ind
->
RBuffer
.
P
,
ind
->
RBuffer
.
length
);
dev_kfree_skb
(
skb
);
dev_kfree_skb
(
skb2
);
if
(
ind
->
MLength
==
ind
->
RBuffer
.
length
)
{
chan
->
e
.
complete
=
2
;
idi_handle_ind
(
ccard
,
skb_new
);
continue
;
}
else
{
chan
->
e
.
complete
=
0
;
skb_queue_tail
(
&
chan
->
e
.
R
,
skb_new
);
continue
;
}
}
}
}
void
eicon_io_ack_dispatch
(
eicon_card
*
ccard
)
{
struct
sk_buff
*
skb
;
if
(
!
ccard
)
{
eicon_log
(
ccard
,
1
,
"eicon_err: NULL card in ack_dispatch!
\n
"
);
return
;
}
while
((
skb
=
skb_dequeue
(
&
ccard
->
rackq
)))
{
idi_handle_ack
(
ccard
,
skb
);
}
}
/*
* IO-Functions for ISA cards
*/
u8
ram_inb
(
eicon_card
*
card
,
void
*
adr
)
{
u32
addr
=
(
u32
)
adr
;
return
(
readb
(
addr
));
}
u16
ram_inw
(
eicon_card
*
card
,
void
*
adr
)
{
u32
addr
=
(
u32
)
adr
;
return
(
readw
(
addr
));
}
void
ram_outb
(
eicon_card
*
card
,
void
*
adr
,
u8
data
)
{
u32
addr
=
(
u32
)
adr
;
writeb
(
data
,
addr
);
}
void
ram_outw
(
eicon_card
*
card
,
void
*
adr
,
u16
data
)
{
u32
addr
=
(
u32
)
adr
;
writew
(
data
,
addr
);
}
void
ram_copyfromcard
(
eicon_card
*
card
,
void
*
adrto
,
void
*
adr
,
int
len
)
{
memcpy_fromio
(
adrto
,
adr
,
len
);
}
void
ram_copytocard
(
eicon_card
*
card
,
void
*
adrto
,
void
*
adr
,
int
len
)
{
memcpy_toio
(
adrto
,
adr
,
len
);
}
#ifdef CONFIG_ISDN_DRV_EICON_PCI
/*
* IDI-Callback function
*/
void
eicon_idi_callback
(
ENTITY
*
de
)
{
eicon_card
*
ccard
=
(
eicon_card
*
)
de
->
R
;
struct
sk_buff
*
skb
;
eicon_RC
*
ack
;
eicon_IND
*
ind
;
int
len
=
0
;
if
(
de
->
complete
==
255
)
{
/* Return Code */
skb
=
alloc_skb
(
sizeof
(
eicon_RC
),
GFP_ATOMIC
);
if
(
!
skb
)
{
eicon_log
(
ccard
,
1
,
"eicon_io: skb_alloc failed in _idi_callback()
\n
"
);
}
else
{
ack
=
(
eicon_RC
*
)
skb_put
(
skb
,
sizeof
(
eicon_RC
));
ack
->
Rc
=
de
->
Rc
;
if
(
de
->
Rc
==
ASSIGN_OK
)
{
ack
->
RcId
=
de
->
Id
;
de
->
user
[
1
]
=
de
->
Id
;
}
else
{
ack
->
RcId
=
de
->
user
[
1
];
}
ack
->
RcCh
=
de
->
RcCh
;
ack
->
Reference
=
de
->
user
[
0
];
skb_queue_tail
(
&
ccard
->
rackq
,
skb
);
eicon_schedule_ack
(
ccard
);
eicon_log
(
ccard
,
128
,
"idi_cbk: Ch%d: Rc=%x Id=%x RLen=%x compl=%x
\n
"
,
de
->
user
[
0
],
de
->
Rc
,
ack
->
RcId
,
de
->
RLength
,
de
->
complete
);
}
}
else
{
/* Indication */
if
(
de
->
complete
)
{
len
=
de
->
RLength
;
}
else
{
len
=
270
;
if
(
de
->
RLength
<=
270
)
eicon_log
(
ccard
,
1
,
"eicon_cbk: ind not complete but <= 270
\n
"
);
}
skb
=
alloc_skb
((
sizeof
(
eicon_IND
)
+
len
-
1
),
GFP_ATOMIC
);
if
(
!
skb
)
{
eicon_log
(
ccard
,
1
,
"eicon_io: skb_alloc failed in _idi_callback()
\n
"
);
}
else
{
ind
=
(
eicon_IND
*
)
skb_put
(
skb
,
(
sizeof
(
eicon_IND
)
+
len
-
1
));
ind
->
Ind
=
de
->
Ind
;
ind
->
IndId
=
de
->
user
[
1
];
ind
->
IndCh
=
de
->
IndCh
;
ind
->
MInd
=
de
->
Ind
;
ind
->
RBuffer
.
length
=
len
;
ind
->
MLength
=
de
->
RLength
;
memcpy
(
&
ind
->
RBuffer
.
P
,
&
de
->
RBuffer
->
P
,
len
);
skb_queue_tail
(
&
ccard
->
rcvq
,
skb
);
eicon_schedule_rx
(
ccard
);
eicon_log
(
ccard
,
128
,
"idi_cbk: Ch%d: Ind=%x Id=%x RLen=%x compl=%x
\n
"
,
de
->
user
[
0
],
de
->
Ind
,
ind
->
IndId
,
de
->
RLength
,
de
->
complete
);
}
}
de
->
RNum
=
0
;
de
->
RNR
=
0
;
de
->
Rc
=
0
;
de
->
Ind
=
0
;
}
#endif
/* CONFIG_ISDN_DRV_EICON_PCI */
/*
* Transmit-Function
*/
void
eicon_io_transmit
(
eicon_card
*
ccard
)
{
eicon_isa_card
*
isa_card
;
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb2
;
unsigned
long
flags
;
eicon_pr_ram
*
prram
=
0
;
eicon_isa_com
*
com
=
0
;
eicon_REQ
*
ReqOut
=
0
;
eicon_REQ
*
reqbuf
=
0
;
eicon_chan
*
chan
;
eicon_chan_ptr
*
chan2
;
int
ReqCount
;
int
scom
=
0
;
int
tmp
=
0
;
int
tmpid
=
0
;
int
quloop
=
1
;
int
dlev
=
0
;
ENTITY
*
ep
=
0
;
isa_card
=
&
ccard
->
hwif
.
isa
;
if
(
!
ccard
)
{
eicon_log
(
ccard
,
1
,
"eicon_transmit: NULL card!
\n
"
);
return
;
}
switch
(
ccard
->
type
)
{
#ifdef CONFIG_ISDN_DRV_EICON_ISA
case
EICON_CTYPE_S
:
case
EICON_CTYPE_SX
:
case
EICON_CTYPE_SCOM
:
case
EICON_CTYPE_QUADRO
:
scom
=
1
;
com
=
(
eicon_isa_com
*
)
isa_card
->
shmem
;
break
;
case
EICON_CTYPE_S2M
:
scom
=
0
;
prram
=
(
eicon_pr_ram
*
)
isa_card
->
shmem
;
break
;
#endif
#ifdef CONFIG_ISDN_DRV_EICON_PCI
case
EICON_CTYPE_MAESTRAP
:
scom
=
2
;
break
;
case
EICON_CTYPE_MAESTRAQ
:
scom
=
2
;
break
;
case
EICON_CTYPE_MAESTRA
:
scom
=
2
;
break
;
#endif
default:
eicon_log
(
ccard
,
1
,
"eicon_transmit: unsupported card-type!
\n
"
);
return
;
}
ReqCount
=
0
;
if
(
!
(
skb2
=
skb_dequeue
(
&
ccard
->
sndq
)))
quloop
=
0
;
while
(
quloop
)
{
spin_lock_irqsave
(
&
eicon_lock
,
flags
);
switch
(
scom
)
{
case
1
:
if
((
ram_inb
(
ccard
,
&
com
->
Req
))
||
(
ccard
->
ReadyInt
))
{
if
(
!
ccard
->
ReadyInt
)
{
tmp
=
ram_inb
(
ccard
,
&
com
->
ReadyInt
)
+
1
;
ram_outb
(
ccard
,
&
com
->
ReadyInt
,
tmp
);
ccard
->
ReadyInt
++
;
}
spin_unlock_irqrestore
(
&
eicon_lock
,
flags
);
skb_queue_head
(
&
ccard
->
sndq
,
skb2
);
eicon_log
(
ccard
,
32
,
"eicon: transmit: Card not ready
\n
"
);
return
;
}
break
;
case
0
:
if
(
!
(
ram_inb
(
ccard
,
&
prram
->
ReqOutput
)
-
ram_inb
(
ccard
,
&
prram
->
ReqInput
)))
{
spin_unlock_irqrestore
(
&
eicon_lock
,
flags
);
skb_queue_head
(
&
ccard
->
sndq
,
skb2
);
eicon_log
(
ccard
,
32
,
"eicon: transmit: Card not ready
\n
"
);
return
;
}
break
;
}
spin_unlock_irqrestore
(
&
eicon_lock
,
flags
);
chan2
=
(
eicon_chan_ptr
*
)
skb2
->
data
;
chan
=
chan2
->
ptr
;
if
(
!
chan
->
e
.
busy
)
{
if
((
skb
=
skb_dequeue
(
&
chan
->
e
.
X
)))
{
reqbuf
=
(
eicon_REQ
*
)
skb
->
data
;
if
((
reqbuf
->
Reference
)
&&
(
chan
->
e
.
B2Id
==
0
)
&&
(
reqbuf
->
ReqId
&
0x1f
))
{
eicon_log
(
ccard
,
16
,
"eicon: transmit: error Id=0 on %d (Net)
\n
"
,
chan
->
No
);
}
else
{
spin_lock_irqsave
(
&
eicon_lock
,
flags
);
switch
(
scom
)
{
case
1
:
ram_outw
(
ccard
,
&
com
->
XBuffer
.
length
,
reqbuf
->
XBuffer
.
length
);
ram_copytocard
(
ccard
,
&
com
->
XBuffer
.
P
,
&
reqbuf
->
XBuffer
.
P
,
reqbuf
->
XBuffer
.
length
);
ram_outb
(
ccard
,
&
com
->
ReqCh
,
reqbuf
->
ReqCh
);
break
;
case
0
:
/* get address of next available request buffer */
ReqOut
=
(
eicon_REQ
*
)
&
prram
->
B
[
ram_inw
(
ccard
,
&
prram
->
NextReq
)];
ram_outw
(
ccard
,
&
ReqOut
->
XBuffer
.
length
,
reqbuf
->
XBuffer
.
length
);
ram_copytocard
(
ccard
,
&
ReqOut
->
XBuffer
.
P
,
&
reqbuf
->
XBuffer
.
P
,
reqbuf
->
XBuffer
.
length
);
ram_outb
(
ccard
,
&
ReqOut
->
ReqCh
,
reqbuf
->
ReqCh
);
ram_outb
(
ccard
,
&
ReqOut
->
Req
,
reqbuf
->
Req
);
break
;
}
dlev
=
160
;
if
(
reqbuf
->
ReqId
&
0x1f
)
{
/* if this is no ASSIGN */
if
(
!
reqbuf
->
Reference
)
{
/* Signal Layer */
switch
(
scom
)
{
case
1
:
ram_outb
(
ccard
,
&
com
->
ReqId
,
chan
->
e
.
D3Id
);
break
;
case
0
:
ram_outb
(
ccard
,
&
ReqOut
->
ReqId
,
chan
->
e
.
D3Id
);
break
;
case
2
:
ep
=
&
chan
->
de
;
break
;
}
tmpid
=
chan
->
e
.
D3Id
;
chan
->
e
.
ReqCh
=
0
;
}
else
{
/* Net Layer */
switch
(
scom
)
{
case
1
:
ram_outb
(
ccard
,
&
com
->
ReqId
,
chan
->
e
.
B2Id
);
break
;
case
0
:
ram_outb
(
ccard
,
&
ReqOut
->
ReqId
,
chan
->
e
.
B2Id
);
break
;
case
2
:
ep
=
&
chan
->
be
;
break
;
}
tmpid
=
chan
->
e
.
B2Id
;
chan
->
e
.
ReqCh
=
1
;
if
(((
reqbuf
->
Req
&
0x0f
)
==
0x08
)
||
((
reqbuf
->
Req
&
0x0f
)
==
0x01
))
{
/* Send Data */
chan
->
waitq
=
reqbuf
->
XBuffer
.
length
;
chan
->
waitpq
+=
reqbuf
->
XBuffer
.
length
;
dlev
=
128
;
}
}
}
else
{
/* It is an ASSIGN */
switch
(
scom
)
{
case
1
:
ram_outb
(
ccard
,
&
com
->
ReqId
,
reqbuf
->
ReqId
);
break
;
case
0
:
ram_outb
(
ccard
,
&
ReqOut
->
ReqId
,
reqbuf
->
ReqId
);
break
;
case
2
:
if
(
!
reqbuf
->
Reference
)
ep
=
&
chan
->
de
;
else
ep
=
&
chan
->
be
;
ep
->
Id
=
reqbuf
->
ReqId
;
break
;
}
tmpid
=
reqbuf
->
ReqId
;
if
(
!
reqbuf
->
Reference
)
chan
->
e
.
ReqCh
=
0
;
else
chan
->
e
.
ReqCh
=
1
;
}
switch
(
scom
)
{
case
1
:
chan
->
e
.
ref
=
ccard
->
ref_out
++
;
break
;
case
0
:
chan
->
e
.
ref
=
ram_inw
(
ccard
,
&
ReqOut
->
Reference
);
break
;
case
2
:
chan
->
e
.
ref
=
chan
->
No
;
break
;
}
chan
->
e
.
Req
=
reqbuf
->
Req
;
ReqCount
++
;
switch
(
scom
)
{
case
1
:
ram_outb
(
ccard
,
&
com
->
Req
,
reqbuf
->
Req
);
break
;
case
0
:
ram_outw
(
ccard
,
&
prram
->
NextReq
,
ram_inw
(
ccard
,
&
ReqOut
->
next
));
break
;
case
2
:
#ifdef CONFIG_ISDN_DRV_EICON_PCI
if
(
!
ep
)
break
;
ep
->
callback
=
eicon_idi_callback
;
ep
->
R
=
(
BUFFERS
*
)
ccard
;
ep
->
user
[
0
]
=
(
word
)
chan
->
No
;
ep
->
user
[
1
]
=
(
word
)
tmpid
;
ep
->
XNum
=
1
;
ep
->
RNum
=
0
;
ep
->
RNR
=
0
;
ep
->
Rc
=
0
;
ep
->
Ind
=
0
;
ep
->
X
->
PLength
=
reqbuf
->
XBuffer
.
length
;
memcpy
(
ep
->
X
->
P
,
&
reqbuf
->
XBuffer
.
P
,
reqbuf
->
XBuffer
.
length
);
ep
->
ReqCh
=
reqbuf
->
ReqCh
;
ep
->
Req
=
reqbuf
->
Req
;
#endif
break
;
}
chan
->
e
.
busy
=
1
;
spin_unlock_irqrestore
(
&
eicon_lock
,
flags
);
eicon_log
(
ccard
,
dlev
,
"eicon: Req=%d Id=%x Ch=%d Len=%d Ref=%d
\n
"
,
reqbuf
->
Req
,
tmpid
,
reqbuf
->
ReqCh
,
reqbuf
->
XBuffer
.
length
,
chan
->
e
.
ref
);
#ifdef CONFIG_ISDN_DRV_EICON_PCI
if
(
scom
==
2
)
{
if
(
ep
)
{
ccard
->
d
->
request
(
ep
);
if
(
ep
->
Rc
)
eicon_idi_callback
(
ep
);
}
}
#endif
}
dev_kfree_skb
(
skb
);
}
dev_kfree_skb
(
skb2
);
}
else
{
skb_queue_tail
(
&
ccard
->
sackq
,
skb2
);
eicon_log
(
ccard
,
128
,
"eicon: transmit: busy chan %d
\n
"
,
chan
->
No
);
}
switch
(
scom
)
{
case
1
:
quloop
=
0
;
break
;
case
0
:
case
2
:
if
(
!
(
skb2
=
skb_dequeue
(
&
ccard
->
sndq
)))
quloop
=
0
;
break
;
}
}
if
(
!
scom
)
ram_outb
(
ccard
,
&
prram
->
ReqInput
,
(
__u8
)(
ram_inb
(
ccard
,
&
prram
->
ReqInput
)
+
ReqCount
));
while
((
skb
=
skb_dequeue
(
&
ccard
->
sackq
)))
{
skb_queue_tail
(
&
ccard
->
sndq
,
skb
);
}
}
#ifdef CONFIG_ISDN_DRV_EICON_ISA
/*
* IRQ handler
*/
irqreturn_t
eicon_irq
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
eicon_card
*
ccard
=
(
eicon_card
*
)
dev_id
;
eicon_isa_card
*
isa_card
;
eicon_pr_ram
*
prram
=
0
;
eicon_isa_com
*
com
=
0
;
eicon_RC
*
RcIn
;
eicon_IND
*
IndIn
;
struct
sk_buff
*
skb
;
int
Count
=
0
;
int
Rc
=
0
;
int
Ind
=
0
;
unsigned
char
*
irqprobe
=
0
;
int
scom
=
0
;
int
tmp
=
0
;
int
dlev
=
0
;
if
(
!
ccard
)
{
eicon_log
(
ccard
,
1
,
"eicon_irq: spurious interrupt %d
\n
"
,
irq
);
return
IRQ_NONE
;
}
if
(
ccard
->
type
==
EICON_CTYPE_QUADRO
)
{
tmp
=
4
;
while
(
tmp
)
{
com
=
(
eicon_isa_com
*
)
ccard
->
hwif
.
isa
.
shmem
;
if
((
readb
(
ccard
->
hwif
.
isa
.
intack
)))
{
/* quadro found */
break
;
}
ccard
=
ccard
->
qnext
;
tmp
--
;
}
}
isa_card
=
&
ccard
->
hwif
.
isa
;
switch
(
ccard
->
type
)
{
case
EICON_CTYPE_S
:
case
EICON_CTYPE_SX
:
case
EICON_CTYPE_SCOM
:
case
EICON_CTYPE_QUADRO
:
scom
=
1
;
com
=
(
eicon_isa_com
*
)
isa_card
->
shmem
;
irqprobe
=
&
isa_card
->
irqprobe
;
break
;
case
EICON_CTYPE_S2M
:
scom
=
0
;
prram
=
(
eicon_pr_ram
*
)
isa_card
->
shmem
;
irqprobe
=
&
isa_card
->
irqprobe
;
break
;
default:
eicon_log
(
ccard
,
1
,
"eicon_irq: unsupported card-type!
\n
"
);
return
IRQ_NONE
;
}
if
(
*
irqprobe
)
{
switch
(
ccard
->
type
)
{
case
EICON_CTYPE_S
:
case
EICON_CTYPE_SX
:
case
EICON_CTYPE_SCOM
:
case
EICON_CTYPE_QUADRO
:
if
(
readb
(
isa_card
->
intack
))
{
writeb
(
0
,
&
com
->
Rc
);
writeb
(
0
,
isa_card
->
intack
);
}
(
*
irqprobe
)
++
;
break
;
case
EICON_CTYPE_S2M
:
if
(
readb
(
isa_card
->
intack
))
{
writeb
(
0
,
&
prram
->
RcOutput
);
writeb
(
0
,
isa_card
->
intack
);
}
(
*
irqprobe
)
++
;
break
;
}
return
IRQ_HANDLED
;
}
switch
(
ccard
->
type
)
{
case
EICON_CTYPE_S
:
case
EICON_CTYPE_SX
:
case
EICON_CTYPE_SCOM
:
case
EICON_CTYPE_QUADRO
:
case
EICON_CTYPE_S2M
:
if
(
!
(
readb
(
isa_card
->
intack
)))
{
/* card did not interrupt */
eicon_log
(
ccard
,
1
,
"eicon: IRQ: card reports no interrupt!
\n
"
);
return
IRQ_NONE
;
}
break
;
}
if
(
scom
)
{
/* if a return code is available ... */
if
((
tmp
=
ram_inb
(
ccard
,
&
com
->
Rc
)))
{
eicon_RC
*
ack
;
if
(
tmp
==
READY_INT
)
{
eicon_log
(
ccard
,
64
,
"eicon: IRQ Rc=READY_INT
\n
"
);
if
(
ccard
->
ReadyInt
)
{
ccard
->
ReadyInt
--
;
ram_outb
(
ccard
,
&
com
->
Rc
,
0
);
eicon_schedule_tx
(
ccard
);
}
}
else
{
skb
=
alloc_skb
(
sizeof
(
eicon_RC
),
GFP_ATOMIC
);
if
(
!
skb
)
{
eicon_log
(
ccard
,
1
,
"eicon_io: skb_alloc failed in _irq()
\n
"
);
}
else
{
ack
=
(
eicon_RC
*
)
skb_put
(
skb
,
sizeof
(
eicon_RC
));
ack
->
Rc
=
tmp
;
ack
->
RcId
=
ram_inb
(
ccard
,
&
com
->
RcId
);
ack
->
RcCh
=
ram_inb
(
ccard
,
&
com
->
RcCh
);
ack
->
Reference
=
ccard
->
ref_in
++
;
eicon_log
(
ccard
,
128
,
"eicon: IRQ Rc=%d Id=%x Ch=%d Ref=%d
\n
"
,
tmp
,
ack
->
RcId
,
ack
->
RcCh
,
ack
->
Reference
);
skb_queue_tail
(
&
ccard
->
rackq
,
skb
);
eicon_schedule_ack
(
ccard
);
}
ram_outb
(
ccard
,
&
com
->
Req
,
0
);
ram_outb
(
ccard
,
&
com
->
Rc
,
0
);
}
}
else
{
/* if an indication is available ... */
if
((
tmp
=
ram_inb
(
ccard
,
&
com
->
Ind
)))
{
eicon_IND
*
ind
;
int
len
=
ram_inw
(
ccard
,
&
com
->
RBuffer
.
length
);
skb
=
alloc_skb
((
sizeof
(
eicon_IND
)
+
len
-
1
),
GFP_ATOMIC
);
if
(
!
skb
)
{
eicon_log
(
ccard
,
1
,
"eicon_io: skb_alloc failed in _irq()
\n
"
);
}
else
{
ind
=
(
eicon_IND
*
)
skb_put
(
skb
,
(
sizeof
(
eicon_IND
)
+
len
-
1
));
ind
->
Ind
=
tmp
;
ind
->
IndId
=
ram_inb
(
ccard
,
&
com
->
IndId
);
ind
->
IndCh
=
ram_inb
(
ccard
,
&
com
->
IndCh
);
ind
->
MInd
=
ram_inb
(
ccard
,
&
com
->
MInd
);
ind
->
MLength
=
ram_inw
(
ccard
,
&
com
->
MLength
);
ind
->
RBuffer
.
length
=
len
;
if
((
tmp
==
1
)
||
(
tmp
==
8
))
dlev
=
128
;
else
dlev
=
192
;
eicon_log
(
ccard
,
dlev
,
"eicon: IRQ Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d
\n
"
,
tmp
,
ind
->
IndId
,
ind
->
IndCh
,
ind
->
MInd
,
ind
->
MLength
,
len
);
ram_copyfromcard
(
ccard
,
&
ind
->
RBuffer
.
P
,
&
com
->
RBuffer
.
P
,
len
);
skb_queue_tail
(
&
ccard
->
rcvq
,
skb
);
eicon_schedule_rx
(
ccard
);
}
ram_outb
(
ccard
,
&
com
->
Ind
,
0
);
}
}
}
else
{
/* if return codes are available ... */
if
((
Count
=
ram_inb
(
ccard
,
&
prram
->
RcOutput
)))
{
eicon_RC
*
ack
;
/* get the buffer address of the first return code */
RcIn
=
(
eicon_RC
*
)
&
prram
->
B
[
ram_inw
(
ccard
,
&
prram
->
NextRc
)];
/* for all return codes do ... */
while
(
Count
--
)
{
if
((
Rc
=
ram_inb
(
ccard
,
&
RcIn
->
Rc
)))
{
skb
=
alloc_skb
(
sizeof
(
eicon_RC
),
GFP_ATOMIC
);
if
(
!
skb
)
{
eicon_log
(
ccard
,
1
,
"eicon_io: skb_alloc failed in _irq()
\n
"
);
}
else
{
ack
=
(
eicon_RC
*
)
skb_put
(
skb
,
sizeof
(
eicon_RC
));
ack
->
Rc
=
Rc
;
ack
->
RcId
=
ram_inb
(
ccard
,
&
RcIn
->
RcId
);
ack
->
RcCh
=
ram_inb
(
ccard
,
&
RcIn
->
RcCh
);
ack
->
Reference
=
ram_inw
(
ccard
,
&
RcIn
->
Reference
);
eicon_log
(
ccard
,
128
,
"eicon: IRQ Rc=%d Id=%x Ch=%d Ref=%d
\n
"
,
Rc
,
ack
->
RcId
,
ack
->
RcCh
,
ack
->
Reference
);
skb_queue_tail
(
&
ccard
->
rackq
,
skb
);
eicon_schedule_ack
(
ccard
);
}
ram_outb
(
ccard
,
&
RcIn
->
Rc
,
0
);
}
/* get buffer address of next return code */
RcIn
=
(
eicon_RC
*
)
&
prram
->
B
[
ram_inw
(
ccard
,
&
RcIn
->
next
)];
}
/* clear all return codes (no chaining!) */
ram_outb
(
ccard
,
&
prram
->
RcOutput
,
0
);
}
/* if indications are available ... */
if
((
Count
=
ram_inb
(
ccard
,
&
prram
->
IndOutput
)))
{
eicon_IND
*
ind
;
/* get the buffer address of the first indication */
IndIn
=
(
eicon_IND
*
)
&
prram
->
B
[
ram_inw
(
ccard
,
&
prram
->
NextInd
)];
/* for all indications do ... */
while
(
Count
--
)
{
Ind
=
ram_inb
(
ccard
,
&
IndIn
->
Ind
);
if
(
Ind
)
{
int
len
=
ram_inw
(
ccard
,
&
IndIn
->
RBuffer
.
length
);
skb
=
alloc_skb
((
sizeof
(
eicon_IND
)
+
len
-
1
),
GFP_ATOMIC
);
if
(
!
skb
)
{
eicon_log
(
ccard
,
1
,
"eicon_io: skb_alloc failed in _irq()
\n
"
);
}
else
{
ind
=
(
eicon_IND
*
)
skb_put
(
skb
,
(
sizeof
(
eicon_IND
)
+
len
-
1
));
ind
->
Ind
=
Ind
;
ind
->
IndId
=
ram_inb
(
ccard
,
&
IndIn
->
IndId
);
ind
->
IndCh
=
ram_inb
(
ccard
,
&
IndIn
->
IndCh
);
ind
->
MInd
=
ram_inb
(
ccard
,
&
IndIn
->
MInd
);
ind
->
MLength
=
ram_inw
(
ccard
,
&
IndIn
->
MLength
);
ind
->
RBuffer
.
length
=
len
;
if
((
Ind
==
1
)
||
(
Ind
==
8
))
dlev
=
128
;
else
dlev
=
192
;
eicon_log
(
ccard
,
dlev
,
"eicon: IRQ Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d
\n
"
,
Ind
,
ind
->
IndId
,
ind
->
IndCh
,
ind
->
MInd
,
ind
->
MLength
,
len
);
ram_copyfromcard
(
ccard
,
&
ind
->
RBuffer
.
P
,
&
IndIn
->
RBuffer
.
P
,
len
);
skb_queue_tail
(
&
ccard
->
rcvq
,
skb
);
eicon_schedule_rx
(
ccard
);
}
ram_outb
(
ccard
,
&
IndIn
->
Ind
,
0
);
}
/* get buffer address of next indication */
IndIn
=
(
eicon_IND
*
)
&
prram
->
B
[
ram_inw
(
ccard
,
&
IndIn
->
next
)];
}
ram_outb
(
ccard
,
&
prram
->
IndOutput
,
0
);
}
}
/* clear interrupt */
switch
(
ccard
->
type
)
{
case
EICON_CTYPE_QUADRO
:
writeb
(
0
,
isa_card
->
intack
);
writeb
(
0
,
&
com
[
0x401
]);
break
;
case
EICON_CTYPE_S
:
case
EICON_CTYPE_SX
:
case
EICON_CTYPE_SCOM
:
case
EICON_CTYPE_S2M
:
writeb
(
0
,
isa_card
->
intack
);
break
;
}
return
IRQ_HANDLED
;
}
#endif
drivers/isdn/eicon/eicon_isa.c
deleted
100644 → 0
View file @
f69c2d56
/* $Id: eicon_isa.c,v 1.1.4.1.2.3 2002/10/01 11:29:13 armin Exp $
*
* ISDN low-level module for Eicon active ISDN-Cards.
* Hardware-specific code for old ISA cards.
*
* Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
* Copyright 1998-2000 by Armin Schindler (mac@melware.de)
* Copyright 1999,2000 Cytronics & Melware (info@melware.de)
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include <linux/config.h>
#include "eicon.h"
#include "eicon_isa.h"
#define check_shmem check_region
#define release_shmem release_region
#define request_shmem request_region
char
*
eicon_isa_revision
=
"$Revision: 1.1.4.1.2.3 $"
;
#undef EICON_MCA_DEBUG
#ifdef CONFIG_ISDN_DRV_EICON_ISA
/* Mask for detecting invalid IRQ parameter */
static
int
eicon_isa_valid_irq
[]
=
{
0x1c1c
,
/* 2, 3, 4, 10, 11, 12 (S)*/
0x1c1c
,
/* 2, 3, 4, 10, 11, 12 (SX) */
0x1cbc
,
/* 2, 3, 4, 5, 7, 10, 11, 12 (SCOM) */
0x1cbc
,
/* 2, 3, 4, 5, 6, 10, 11, 12 (Quadro) */
0x1cbc
/* 2, 3, 4, 5, 7, 10, 11, 12 (S2M) */
};
static
void
eicon_isa_release_shmem
(
eicon_isa_card
*
card
)
{
if
(
card
->
mvalid
)
{
iounmap
(
card
->
shmem
);
release_mem_region
(
card
->
physmem
,
card
->
ramsize
);
}
card
->
mvalid
=
0
;
}
static
void
eicon_isa_release_irq
(
eicon_isa_card
*
card
)
{
if
(
!
card
->
master
)
return
;
if
(
card
->
ivalid
)
free_irq
(
card
->
irq
,
card
);
card
->
ivalid
=
0
;
}
void
eicon_isa_release
(
eicon_isa_card
*
card
)
{
eicon_isa_release_irq
(
card
);
eicon_isa_release_shmem
(
card
);
}
void
eicon_isa_printpar
(
eicon_isa_card
*
card
)
{
switch
(
card
->
type
)
{
case
EICON_CTYPE_S
:
case
EICON_CTYPE_SX
:
case
EICON_CTYPE_SCOM
:
case
EICON_CTYPE_QUADRO
:
case
EICON_CTYPE_S2M
:
printk
(
KERN_INFO
"Eicon %s at 0x%lx, irq %d.
\n
"
,
eicon_ctype_name
[
card
->
type
],
card
->
physmem
,
card
->
irq
);
}
}
int
eicon_isa_find_card
(
int
Mem
,
int
Irq
,
char
*
Id
)
{
int
primary
=
1
;
unsigned
long
amem
;
if
(
!
strlen
(
Id
))
return
-
1
;
if
(
Mem
==
-
1
)
return
-
1
;
/* Check for valid membase address */
if
((
Mem
<
0x0c0000
)
||
(
Mem
>
0x0fc000
)
||
(
Mem
&
0xfff
))
{
printk
(
KERN_WARNING
"eicon_isa: invalid membase 0x%x for %s
\n
"
,
Mem
,
Id
);
return
-
1
;
}
if
(
check_mem_region
(
Mem
,
RAMSIZE
))
{
printk
(
KERN_WARNING
"eicon_isa_boot: memory at 0x%x already in use.
\n
"
,
Mem
);
return
-
1
;
}
amem
=
(
unsigned
long
)
ioremap
(
Mem
,
RAMSIZE
);
writew
(
0x55aa
,
amem
+
0x402
);
if
(
readw
(
amem
+
0x402
)
!=
0x55aa
)
primary
=
0
;
writew
(
0
,
amem
+
0x402
);
if
(
readw
(
amem
+
0x402
)
!=
0
)
primary
=
0
;
printk
(
KERN_INFO
"Eicon: Driver-ID: %s
\n
"
,
Id
);
if
(
primary
)
{
printk
(
KERN_INFO
"Eicon: assuming pri card at 0x%x
\n
"
,
Mem
);
writeb
(
0
,
amem
+
0x3ffe
);
iounmap
((
unsigned
char
*
)
amem
);
return
EICON_CTYPE_ISAPRI
;
}
else
{
printk
(
KERN_INFO
"Eicon: assuming bri card at 0x%x
\n
"
,
Mem
);
writeb
(
0
,
amem
+
0x400
);
iounmap
((
unsigned
char
*
)
amem
);
return
EICON_CTYPE_ISABRI
;
}
return
-
1
;
}
int
eicon_isa_bootload
(
eicon_isa_card
*
card
,
eicon_isa_codebuf
*
cb
)
{
int
tmp
;
unsigned
long
timeout
;
eicon_isa_codebuf
cbuf
;
unsigned
char
*
code
;
eicon_isa_boot
*
boot
;
if
(
copy_from_user
(
&
cbuf
,
cb
,
sizeof
(
eicon_isa_codebuf
)))
return
-
EFAULT
;
/* Allocate code-buffer and copy code from userspace */
if
(
cbuf
.
bootstrap_len
>
1024
)
{
printk
(
KERN_WARNING
"eicon_isa_boot: Invalid startup-code size %ld
\n
"
,
cbuf
.
bootstrap_len
);
return
-
EINVAL
;
}
if
(
!
(
code
=
kmalloc
(
cbuf
.
bootstrap_len
,
GFP_KERNEL
)))
{
printk
(
KERN_WARNING
"eicon_isa_boot: Couldn't allocate code buffer
\n
"
);
return
-
ENOMEM
;
}
if
(
copy_from_user
(
code
,
&
cb
->
code
,
cbuf
.
bootstrap_len
))
{
kfree
(
code
);
return
-
EFAULT
;
}
if
(
card
->
type
==
EICON_CTYPE_ISAPRI
)
card
->
ramsize
=
RAMSIZE_P
;
else
card
->
ramsize
=
RAMSIZE
;
if
(
check_mem_region
(
card
->
physmem
,
card
->
ramsize
))
{
printk
(
KERN_WARNING
"eicon_isa_boot: memory at 0x%lx already in use.
\n
"
,
card
->
physmem
);
kfree
(
code
);
return
-
EBUSY
;
}
request_mem_region
(
card
->
physmem
,
card
->
ramsize
,
"Eicon ISA ISDN"
);
card
->
shmem
=
(
eicon_isa_shmem
*
)
ioremap
(
card
->
physmem
,
card
->
ramsize
);
#ifdef EICON_MCA_DEBUG
printk
(
KERN_INFO
"eicon_isa_boot: card->ramsize = %d.
\n
"
,
card
->
ramsize
);
#endif
card
->
mvalid
=
1
;
switch
(
card
->
type
)
{
case
EICON_CTYPE_S
:
case
EICON_CTYPE_SX
:
case
EICON_CTYPE_SCOM
:
case
EICON_CTYPE_QUADRO
:
case
EICON_CTYPE_ISABRI
:
card
->
intack
=
(
__u8
*
)
card
->
shmem
+
INTACK
;
card
->
startcpu
=
(
__u8
*
)
card
->
shmem
+
STARTCPU
;
card
->
stopcpu
=
(
__u8
*
)
card
->
shmem
+
STOPCPU
;
break
;
case
EICON_CTYPE_S2M
:
case
EICON_CTYPE_ISAPRI
:
card
->
intack
=
(
__u8
*
)
card
->
shmem
+
INTACK_P
;
card
->
startcpu
=
(
__u8
*
)
card
->
shmem
+
STARTCPU_P
;
card
->
stopcpu
=
(
__u8
*
)
card
->
shmem
+
STOPCPU_P
;
break
;
default:
printk
(
KERN_WARNING
"eicon_isa_boot: Invalid card type %d
\n
"
,
card
->
type
);
eicon_isa_release_shmem
(
card
);
kfree
(
code
);
return
-
EINVAL
;
}
/* clear any pending irq's */
readb
(
card
->
intack
);
#ifdef CONFIG_MCA
if
(
MCA_bus
)
{
if
(
card
->
type
==
EICON_CTYPE_SCOM
)
{
outb_p
(
0
,
card
->
io
+
1
);
}
else
{
printk
(
KERN_WARNING
"eicon_isa_boot: Card type not supported yet.
\n
"
);
eicon_isa_release_shmem
(
card
);
return
-
EINVAL
;
};
#ifdef EICON_MCA_DEBUG
printk
(
KERN_INFO
"eicon_isa_boot: card->io = %x.
\n
"
,
card
->
io
);
printk
(
KERN_INFO
"eicon_isa_boot: card->irq = %d.
\n
"
,
(
int
)
card
->
irq
);
#endif
}
#else
/* set reset-line active */
writeb
(
0
,
card
->
stopcpu
);
#endif
/* CONFIG_MCA */
/* clear irq-requests */
writeb
(
0
,
card
->
intack
);
readb
(
card
->
intack
);
/* Copy code into card */
memcpy_toio
(
&
card
->
shmem
->
c
,
code
,
cbuf
.
bootstrap_len
);
/* Check for properly loaded code */
if
(
!
check_signature
((
unsigned
long
)
&
card
->
shmem
->
c
,
code
,
1020
))
{
printk
(
KERN_WARNING
"eicon_isa_boot: Could not load startup-code
\n
"
);
eicon_isa_release_shmem
(
card
);
kfree
(
code
);
return
-
EIO
;
}
/* if 16k-ramsize, duplicate the reset-jump-code */
if
(
card
->
ramsize
==
RAMSIZE_P
)
memcpy_toio
((
__u8
*
)
card
->
shmem
+
0x3ff0
,
&
code
[
0x3f0
],
12
);
kfree
(
code
);
boot
=
&
card
->
shmem
->
boot
;
/* Delay 0.2 sec. */
SLEEP
(
HZ
/
5
);
/* Start CPU */
writeb
(
cbuf
.
boot_opt
,
&
boot
->
ctrl
);
#ifdef CONFIG_MCA
if
(
MCA_bus
)
{
outb_p
(
0
,
card
->
io
);
}
#else
writeb
(
0
,
card
->
startcpu
);
#endif
/* CONFIG_MCA */
/* Delay 0.2 sec. */
SLEEP
(
HZ
/
5
);
timeout
=
jiffies
+
(
HZ
*
22
);
while
(
time_before
(
jiffies
,
timeout
))
{
if
(
readb
(
&
boot
->
ctrl
)
==
0
)
break
;
SLEEP
(
10
);
}
if
(
readb
(
&
boot
->
ctrl
)
!=
0
)
{
printk
(
KERN_WARNING
"eicon_isa_boot: CPU test failed.
\n
"
);
#ifdef EICON_MCA_DEBUG
printk
(
KERN_INFO
"eicon_isa_boot: &boot->ctrl = %d.
\n
"
,
readb
(
&
boot
->
ctrl
));
#endif
eicon_isa_release_shmem
(
card
);
return
-
EIO
;
}
/* Check for memory-test errors */
if
(
readw
(
&
boot
->
ebit
))
{
printk
(
KERN_WARNING
"eicon_isa_boot: memory test failed (bit 0x%04x at 0x%08x)
\n
"
,
readw
(
&
boot
->
ebit
),
readl
(
&
boot
->
eloc
));
eicon_isa_release_shmem
(
card
);
return
-
EIO
;
}
/* Check card type and memory size */
tmp
=
readb
(
&
boot
->
card
);
if
((
tmp
<
0
)
||
(
tmp
>
4
))
{
printk
(
KERN_WARNING
"eicon_isa_boot: Type detect failed
\n
"
);
eicon_isa_release_shmem
(
card
);
return
-
EIO
;
}
card
->
type
=
tmp
;
((
eicon_card
*
)
card
->
card
)
->
type
=
tmp
;
tmp
=
readb
(
&
boot
->
msize
);
if
(
tmp
!=
8
&&
tmp
!=
16
&&
tmp
!=
24
&&
tmp
!=
32
&&
tmp
!=
48
&&
tmp
!=
60
)
{
printk
(
KERN_WARNING
"eicon_isa_boot: invalid memsize
\n
"
);
eicon_isa_release_shmem
(
card
);
return
-
EIO
;
}
printk
(
KERN_INFO
"%s: startup-code loaded
\n
"
,
eicon_ctype_name
[
card
->
type
]);
if
((
card
->
type
==
EICON_CTYPE_QUADRO
)
&&
(
card
->
master
))
{
tmp
=
eicon_addcard
(
card
->
type
,
card
->
physmem
,
card
->
irq
,
((
eicon_card
*
)
card
->
card
)
->
regname
,
0
);
printk
(
KERN_INFO
"Eicon: %d adapters added
\n
"
,
tmp
);
}
return
0
;
}
int
eicon_isa_load
(
eicon_isa_card
*
card
,
eicon_isa_codebuf
*
cb
)
{
eicon_isa_boot
*
boot
;
int
tmp
;
unsigned
long
timeout
;
int
j
;
eicon_isa_codebuf
cbuf
;
unsigned
char
*
code
;
unsigned
char
*
p
;
if
(
copy_from_user
(
&
cbuf
,
cb
,
sizeof
(
eicon_isa_codebuf
)))
return
-
EFAULT
;
if
(
!
(
code
=
kmalloc
(
cbuf
.
firmware_len
,
GFP_KERNEL
)))
{
printk
(
KERN_WARNING
"eicon_isa_load: Couldn't allocate code buffer
\n
"
);
return
-
ENOMEM
;
}
if
(
copy_from_user
(
code
,
&
cb
->
code
,
cbuf
.
firmware_len
))
{
kfree
(
code
);
return
-
EFAULT
;
}
boot
=
&
card
->
shmem
->
boot
;
if
((
!
card
->
ivalid
)
&&
card
->
master
)
{
card
->
irqprobe
=
1
;
/* Check for valid IRQ */
if
((
card
->
irq
<
0
)
||
(
card
->
irq
>
15
)
||
(
!
((
1
<<
card
->
irq
)
&
eicon_isa_valid_irq
[
card
->
type
&
0x0f
])))
{
printk
(
KERN_WARNING
"eicon_isa_load: invalid irq: %d
\n
"
,
card
->
irq
);
eicon_isa_release_shmem
(
card
);
kfree
(
code
);
return
-
EINVAL
;
}
/* Register irq */
if
(
!
request_irq
(
card
->
irq
,
&
eicon_irq
,
0
,
"Eicon ISA ISDN"
,
card
))
card
->
ivalid
=
1
;
else
{
printk
(
KERN_WARNING
"eicon_isa_load: irq %d already in use.
\n
"
,
card
->
irq
);
eicon_isa_release_shmem
(
card
);
kfree
(
code
);
return
-
EBUSY
;
}
}
tmp
=
readb
(
&
boot
->
msize
);
if
(
tmp
!=
8
&&
tmp
!=
16
&&
tmp
!=
24
&&
tmp
!=
32
&&
tmp
!=
48
&&
tmp
!=
60
)
{
printk
(
KERN_WARNING
"eicon_isa_load: invalid memsize
\n
"
);
eicon_isa_release_shmem
(
card
);
return
-
EIO
;
}
eicon_isa_printpar
(
card
);
/* Download firmware */
printk
(
KERN_INFO
"%s %dkB, loading firmware ...
\n
"
,
eicon_ctype_name
[
card
->
type
],
tmp
*
16
);
tmp
=
cbuf
.
firmware_len
>>
8
;
p
=
code
;
while
(
tmp
--
)
{
memcpy_toio
(
&
boot
->
b
,
p
,
256
);
writeb
(
1
,
&
boot
->
ctrl
);
timeout
=
jiffies
+
HZ
/
10
;
while
(
time_before
(
jiffies
,
timeout
))
{
if
(
readb
(
&
boot
->
ctrl
)
==
0
)
break
;
SLEEP
(
2
);
}
if
(
readb
(
&
boot
->
ctrl
))
{
printk
(
KERN_WARNING
"eicon_isa_load: download timeout at 0x%x
\n
"
,
p
-
code
);
eicon_isa_release
(
card
);
kfree
(
code
);
return
-
EIO
;
}
p
+=
256
;
}
kfree
(
code
);
/* Initialize firmware parameters */
memcpy_toio
(
&
card
->
shmem
->
c
[
8
],
&
cbuf
.
tei
,
14
);
memcpy_toio
(
&
card
->
shmem
->
c
[
32
],
&
cbuf
.
oad
,
96
);
memcpy_toio
(
&
card
->
shmem
->
c
[
128
],
&
cbuf
.
oad
,
96
);
/* Start firmware, wait for signature */
writeb
(
2
,
&
boot
->
ctrl
);
timeout
=
jiffies
+
(
5
*
HZ
);
while
(
time_before
(
jiffies
,
timeout
))
{
if
(
readw
(
&
boot
->
signature
)
==
0x4447
)
break
;
SLEEP
(
2
);
}
if
(
readw
(
&
boot
->
signature
)
!=
0x4447
)
{
printk
(
KERN_WARNING
"eicon_isa_load: firmware selftest failed %04x
\n
"
,
readw
(
&
boot
->
signature
));
eicon_isa_release
(
card
);
return
-
EIO
;
}
card
->
channels
=
readb
(
&
card
->
shmem
->
c
[
0x3f6
]);
/* clear irq-requests, reset irq-count */
readb
(
card
->
intack
);
writeb
(
0
,
card
->
intack
);
if
(
card
->
master
)
{
card
->
irqprobe
=
1
;
/* Trigger an interrupt and check if it is delivered */
tmp
=
readb
(
&
card
->
shmem
->
com
.
ReadyInt
);
tmp
++
;
writeb
(
tmp
,
&
card
->
shmem
->
com
.
ReadyInt
);
timeout
=
jiffies
+
HZ
/
5
;
while
(
time_before
(
jiffies
,
timeout
))
{
if
(
card
->
irqprobe
>
1
)
break
;
SLEEP
(
2
);
}
if
(
card
->
irqprobe
==
1
)
{
printk
(
KERN_WARNING
"eicon_isa_load: IRQ # %d test failed
\n
"
,
card
->
irq
);
eicon_isa_release
(
card
);
return
-
EIO
;
}
}
#ifdef EICON_MCA_DEBUG
printk
(
KERN_INFO
"eicon_isa_load: IRQ # %d test succeeded.
\n
"
,
card
->
irq
);
#endif
writeb
(
card
->
irq
,
&
card
->
shmem
->
com
.
Int
);
/* initializing some variables */
((
eicon_card
*
)
card
->
card
)
->
ReadyInt
=
0
;
((
eicon_card
*
)
card
->
card
)
->
ref_in
=
1
;
((
eicon_card
*
)
card
->
card
)
->
ref_out
=
1
;
for
(
j
=
0
;
j
<
256
;
j
++
)
((
eicon_card
*
)
card
->
card
)
->
IdTable
[
j
]
=
NULL
;
for
(
j
=
0
;
j
<
(
card
->
channels
+
1
);
j
++
)
{
((
eicon_card
*
)
card
->
card
)
->
bch
[
j
].
e
.
busy
=
0
;
((
eicon_card
*
)
card
->
card
)
->
bch
[
j
].
e
.
D3Id
=
0
;
((
eicon_card
*
)
card
->
card
)
->
bch
[
j
].
e
.
B2Id
=
0
;
((
eicon_card
*
)
card
->
card
)
->
bch
[
j
].
e
.
ref
=
0
;
((
eicon_card
*
)
card
->
card
)
->
bch
[
j
].
e
.
Req
=
0
;
((
eicon_card
*
)
card
->
card
)
->
bch
[
j
].
e
.
complete
=
1
;
((
eicon_card
*
)
card
->
card
)
->
bch
[
j
].
fsm_state
=
EICON_STATE_NULL
;
}
printk
(
KERN_INFO
"Eicon: Supported channels: %d
\n
"
,
card
->
channels
);
printk
(
KERN_INFO
"%s successfully started
\n
"
,
eicon_ctype_name
[
card
->
type
]);
/* Enable normal IRQ processing */
card
->
irqprobe
=
0
;
return
0
;
}
#endif
/* CONFIG_ISDN_DRV_EICON_ISA */
drivers/isdn/eicon/eicon_isa.h
deleted
100644 → 0
View file @
f69c2d56
/* $Id: eicon_isa.h,v 1.1.4.1.2.2 2002/10/01 11:29:13 armin Exp $
*
* ISDN low-level module for Eicon active ISDN-Cards.
*
* Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
* Copyright 1998-2000 by Armin Schindler (mac@melware.de)
* Copyright 1999,2000 Cytronics & Melware (info@melware.de)
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#ifndef eicon_isa_h
#define eicon_isa_h
#ifdef __KERNEL__
#include <linux/config.h>
/* Factory defaults for ISA-Cards */
#define EICON_ISA_MEMBASE 0xd0000
#define EICON_ISA_IRQ 3
/* shmem offset for Quadro parts */
#define EICON_ISA_QOFFSET 0x0800
typedef
struct
{
__u16
length
__attribute__
((
packed
));
/* length of data/parameter field */
__u8
P
[
270
];
/* data/parameter field */
}
eicon_scom_PBUFFER
;
/* General communication buffer */
typedef
struct
{
__u8
Req
;
/* request register */
__u8
ReqId
;
/* request task/entity identification */
__u8
Rc
;
/* return code register */
__u8
RcId
;
/* return code task/entity identification */
__u8
Ind
;
/* Indication register */
__u8
IndId
;
/* Indication task/entity identification */
__u8
IMask
;
/* Interrupt Mask Flag */
__u8
RNR
;
/* Receiver Not Ready (set by PC) */
__u8
XLock
;
/* XBuffer locked Flag */
__u8
Int
;
/* ISDN interrupt */
__u8
ReqCh
;
/* Channel field for layer-3 Requests */
__u8
RcCh
;
/* Channel field for layer-3 Returncodes */
__u8
IndCh
;
/* Channel field for layer-3 Indications */
__u8
MInd
;
/* more data indication field */
__u16
MLength
;
/* more data total packet length */
__u8
ReadyInt
;
/* request field for ready interrupt */
__u8
Reserved
[
12
];
/* reserved space */
__u8
IfType
;
/* 1 = 16k-Interface */
__u16
Signature
__attribute__
((
packed
));
/* ISDN adapter Signature */
eicon_scom_PBUFFER
XBuffer
;
/* Transmit Buffer */
eicon_scom_PBUFFER
RBuffer
;
/* Receive Buffer */
}
eicon_isa_com
;
/* struct for downloading firmware */
typedef
struct
{
__u8
ctrl
;
__u8
card
;
__u8
msize
;
__u8
fill0
;
__u16
ebit
__attribute__
((
packed
));
__u32
eloc
__attribute__
((
packed
));
__u8
reserved
[
20
];
__u16
signature
__attribute__
((
packed
));
__u8
fill
[
224
];
__u8
b
[
256
];
}
eicon_isa_boot
;
/* Shared memory */
typedef
union
{
unsigned
char
c
[
0x400
];
eicon_isa_com
com
;
eicon_isa_boot
boot
;
}
eicon_isa_shmem
;
/*
* card's description
*/
typedef
struct
{
int
ramsize
;
int
irq
;
/* IRQ */
unsigned
long
physmem
;
/* physical memory address */
#ifdef CONFIG_MCA
int
io
;
/* IO-port for MCA brand */
#endif
/* CONFIG_MCA */
void
*
card
;
eicon_isa_shmem
*
shmem
;
/* Shared-memory area */
unsigned
char
*
intack
;
/* Int-Acknowledge */
unsigned
char
*
stopcpu
;
/* Writing here stops CPU */
unsigned
char
*
startcpu
;
/* Writing here starts CPU */
unsigned
char
type
;
/* card type */
int
channels
;
/* No. of channels */
unsigned
char
irqprobe
;
/* Flag: IRQ-probing */
unsigned
char
mvalid
;
/* Flag: Memory is valid */
unsigned
char
ivalid
;
/* Flag: IRQ is valid */
unsigned
char
master
;
/* Flag: Card ist Quadro 1/4 */
}
eicon_isa_card
;
/* Offsets for special locations on standard cards */
#define INTACK 0x03fe
#define STOPCPU 0x0400
#define STARTCPU 0x0401
#define RAMSIZE 0x0400
/* Offsets for special location on PRI card */
#define INTACK_P 0x3ffc
#define STOPCPU_P 0x3ffe
#define STARTCPU_P 0x3fff
#define RAMSIZE_P 0x4000
extern
int
eicon_isa_load
(
eicon_isa_card
*
card
,
eicon_isa_codebuf
*
cb
);
extern
int
eicon_isa_bootload
(
eicon_isa_card
*
card
,
eicon_isa_codebuf
*
cb
);
extern
void
eicon_isa_release
(
eicon_isa_card
*
card
);
extern
void
eicon_isa_printpar
(
eicon_isa_card
*
card
);
extern
void
eicon_isa_transmit
(
eicon_isa_card
*
card
);
extern
int
eicon_isa_find_card
(
int
Mem
,
int
Irq
,
char
*
Id
);
#endif
/* __KERNEL__ */
#endif
/* eicon_isa_h */
drivers/isdn/eicon/eicon_mod.c
deleted
100644 → 0
View file @
f69c2d56
/* $Id: eicon_mod.c,v 1.1.4.1.2.4 2002/10/01 11:29:13 armin Exp $
*
* ISDN lowlevel-module for Eicon active cards.
*
* Copyright 1997 by Fritz Elfert (fritz@isdn4linux.de)
* Copyright 1998-2000 by Armin Schindler (mac@melware.de)
* Copyright 1999,2000 Cytronics & Melware (info@melware.de)
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
* Thanks to Eicon Networks for
* documents, informations and hardware.
*
* Deutsche Mailbox Saar-Lor-Lux GmbH
* for sponsoring and testing fax
* capabilities with Diva Server cards.
* (dor@deutschemailbox.de)
*
*/
#define DRIVERNAME "Eicon active ISDN driver"
#define DRIVERRELEASE "2.0"
#define DRIVERPATCH ".16"
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#ifdef CONFIG_MCA
#include <linux/mca.h>
#include <linux/mca-legacy.h>
#endif
/* CONFIG_MCA */
#include "eicon.h"
#include <linux/isdn/capicmd.h>
#undef N_DATA
#include "adapter.h"
#include "uxio.h"
#define INCLUDE_INLINE_FUNCS
static
eicon_card
*
cards
=
(
eicon_card
*
)
NULL
;
/* glob. var , contains
start of card-list */
static
char
*
eicon_revision
=
"$Revision: 1.1.4.1.2.4 $"
;
extern
char
*
eicon_pci_revision
;
extern
char
*
eicon_isa_revision
;
extern
char
*
eicon_idi_revision
;
extern
int
do_ioctl
(
struct
inode
*
pDivasInode
,
struct
file
*
pDivasFile
,
unsigned
int
command
,
unsigned
long
arg
);
extern
void
eicon_pci_init_conf
(
eicon_card
*
card
);
#define EICON_CTRL_VERSION 2
ulong
DebugVar
;
spinlock_t
eicon_lock
;
DESCRIPTOR
idi_d
[
32
];
/* Parameters to be set by insmod */
#ifdef CONFIG_ISDN_DRV_EICON_ISA
static
int
membase
=
-
1
;
static
int
irq
=
-
1
;
#endif
static
char
*
id
=
"
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0
"
;
MODULE_DESCRIPTION
(
"ISDN4Linux: Driver for Eicon active ISDN cards"
);
MODULE_AUTHOR
(
"Armin Schindler"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_PARM_DESC
(
id
,
"ID-String of first card"
);
MODULE_PARM
(
id
,
"s"
);
#ifdef CONFIG_ISDN_DRV_EICON_ISA
MODULE_PARM_DESC
(
membase
,
"Base address of first ISA card"
);
MODULE_PARM_DESC
(
irq
,
"IRQ of first card"
);
MODULE_PARM
(
membase
,
"i"
);
MODULE_PARM
(
irq
,
"i"
);
#endif
char
*
eicon_ctype_name
[]
=
{
"ISDN-S"
,
"ISDN-SX"
,
"ISDN-SCOM"
,
"ISDN-QUADRO"
,
"ISDN-S2M"
,
"DIVA Server BRI/PCI"
,
"DIVA Server 4BRI/PCI"
,
"DIVA Server 4BRI/PCI"
,
"DIVA Server PRI/PCI"
};
static
char
*
eicon_getrev
(
const
char
*
revision
)
{
char
*
rev
;
char
*
p
;
if
((
p
=
strchr
(
revision
,
':'
)))
{
rev
=
p
+
2
;
p
=
strchr
(
rev
,
'$'
);
*--
p
=
0
;
}
else
rev
=
"?.??"
;
return
rev
;
}
static
eicon_chan
*
find_channel
(
eicon_card
*
card
,
int
channel
)
{
if
((
channel
>=
0
)
&&
(
channel
<
card
->
nchannels
))
return
&
(
card
->
bch
[
channel
]);
eicon_log
(
card
,
1
,
"eicon: Invalid channel %d
\n
"
,
channel
);
return
NULL
;
}
#ifdef CONFIG_PCI
#ifdef CONFIG_ISDN_DRV_EICON_PCI
/*
* Find pcicard with given card number
*/
static
inline
eicon_card
*
eicon_findnpcicard
(
int
driverid
)
{
eicon_card
*
p
=
cards
;
while
(
p
)
{
if
((
p
->
regname
[
strlen
(
p
->
regname
)
-
1
]
==
(
driverid
+
'0'
))
&&
(
p
->
bus
==
EICON_BUS_PCI
))
return
p
;
p
=
p
->
next
;
}
return
(
eicon_card
*
)
0
;
}
#endif
#endif
/* CONFIG_PCI */
static
void
eicon_rcv_dispatch
(
unsigned
long
context
)
{
struct
eicon_card
*
card
=
(
struct
eicon_card
*
)
context
;
switch
(
card
->
bus
)
{
case
EICON_BUS_ISA
:
case
EICON_BUS_MCA
:
case
EICON_BUS_PCI
:
eicon_io_rcv_dispatch
(
card
);
break
;
default:
eicon_log
(
card
,
1
,
"eicon_rcv_dispatch: Illegal bustype %d
\n
"
,
card
->
bus
);
}
}
static
void
eicon_ack_dispatch
(
unsigned
long
context
)
{
struct
eicon_card
*
card
=
(
struct
eicon_card
*
)
context
;
switch
(
card
->
bus
)
{
case
EICON_BUS_ISA
:
case
EICON_BUS_MCA
:
case
EICON_BUS_PCI
:
eicon_io_ack_dispatch
(
card
);
break
;
default:
eicon_log
(
card
,
1
,
"eicon_ack_dispatch: Illegal bustype %d
\n
"
,
card
->
bus
);
}
}
static
void
eicon_transmit
(
unsigned
long
context
)
{
struct
eicon_card
*
card
=
(
struct
eicon_card
*
)
context
;
switch
(
card
->
bus
)
{
case
EICON_BUS_ISA
:
case
EICON_BUS_MCA
:
case
EICON_BUS_PCI
:
eicon_io_transmit
(
card
);
break
;
default:
eicon_log
(
card
,
1
,
"eicon_transmit: Illegal bustype %d
\n
"
,
card
->
bus
);
}
}
static
int
eicon_command
(
eicon_card
*
card
,
isdn_ctrl
*
c
)
{
ulong
a
;
eicon_chan
*
chan
;
eicon_cdef
cdef
;
#ifdef CONFIG_PCI
#ifdef CONFIG_ISDN_DRV_EICON_PCI
dia_start_t
dstart
;
int
idi_length
=
0
;
#endif
#endif
isdn_ctrl
cmd
;
int
ret
=
0
;
unsigned
long
flags
;
eicon_log
(
card
,
16
,
"eicon_cmd 0x%x with arg 0x%lx (0x%lx)
\n
"
,
c
->
command
,
c
->
arg
,
(
ulong
)
*
c
->
parm
.
num
);
switch
(
c
->
command
)
{
case
ISDN_CMD_IOCTL
:
memcpy
(
&
a
,
c
->
parm
.
num
,
sizeof
(
ulong
));
switch
(
c
->
arg
)
{
case
EICON_IOCTL_GETVER
:
return
(
EICON_CTRL_VERSION
);
case
EICON_IOCTL_GETTYPE
:
if
(
card
->
bus
==
EICON_BUS_PCI
)
{
if
(
copy_to_user
((
char
*
)
a
,
&
card
->
hwif
.
pci
.
master
,
sizeof
(
int
)))
return
-
EFAULT
;
}
return
(
card
->
type
);
case
EICON_IOCTL_GETMMIO
:
switch
(
card
->
bus
)
{
case
EICON_BUS_ISA
:
case
EICON_BUS_MCA
:
return
(
int
)
card
->
hwif
.
isa
.
shmem
;
default:
eicon_log
(
card
,
1
,
"eicon: Illegal BUS type %d
\n
"
,
card
->
bus
);
ret
=
-
ENODEV
;
}
#ifdef CONFIG_ISDN_DRV_EICON_ISA
case
EICON_IOCTL_SETMMIO
:
if
(
card
->
flags
&
EICON_FLAGS_LOADED
)
return
-
EBUSY
;
switch
(
card
->
bus
)
{
case
EICON_BUS_ISA
:
if
(
eicon_isa_find_card
(
a
,
card
->
hwif
.
isa
.
irq
,
card
->
regname
)
<
0
)
return
-
EFAULT
;
card
->
hwif
.
isa
.
shmem
=
(
eicon_isa_shmem
*
)
a
;
return
0
;
case
EICON_BUS_MCA
:
#ifdef CONFIG_MCA
if
(
eicon_mca_find_card
(
0
,
a
,
card
->
hwif
.
isa
.
irq
,
card
->
regname
)
<
0
)
return
-
EFAULT
;
card
->
hwif
.
isa
.
shmem
=
(
eicon_isa_shmem
*
)
a
;
return
0
;
#endif
/* CONFIG_MCA */
default:
eicon_log
(
card
,
1
,
"eicon: Illegal BUS type %d
\n
"
,
card
->
bus
);
ret
=
-
ENODEV
;
}
#endif
case
EICON_IOCTL_GETIRQ
:
switch
(
card
->
bus
)
{
case
EICON_BUS_ISA
:
case
EICON_BUS_MCA
:
return
card
->
hwif
.
isa
.
irq
;
default:
eicon_log
(
card
,
1
,
"eicon: Illegal BUS type %d
\n
"
,
card
->
bus
);
ret
=
-
ENODEV
;
}
case
EICON_IOCTL_SETIRQ
:
if
(
card
->
flags
&
EICON_FLAGS_LOADED
)
return
-
EBUSY
;
if
((
a
<
2
)
||
(
a
>
15
))
return
-
EFAULT
;
switch
(
card
->
bus
)
{
case
EICON_BUS_ISA
:
case
EICON_BUS_MCA
:
card
->
hwif
.
isa
.
irq
=
a
;
return
0
;
default:
eicon_log
(
card
,
1
,
"eicon: Illegal BUS type %d
\n
"
,
card
->
bus
);
ret
=
-
ENODEV
;
}
#ifdef CONFIG_ISDN_DRV_EICON_ISA
case
EICON_IOCTL_LOADBOOT
:
if
(
card
->
flags
&
EICON_FLAGS_RUNNING
)
return
-
EBUSY
;
switch
(
card
->
bus
)
{
case
EICON_BUS_ISA
:
case
EICON_BUS_MCA
:
ret
=
eicon_isa_bootload
(
&
(
card
->
hwif
.
isa
),
&
(((
eicon_codebuf
*
)
a
)
->
isa
));
break
;
default:
eicon_log
(
card
,
1
,
"eicon: Illegal BUS type %d
\n
"
,
card
->
bus
);
ret
=
-
ENODEV
;
}
return
ret
;
#endif
#ifdef CONFIG_ISDN_DRV_EICON_ISA
case
EICON_IOCTL_LOADISA
:
if
(
card
->
flags
&
EICON_FLAGS_RUNNING
)
return
-
EBUSY
;
switch
(
card
->
bus
)
{
case
EICON_BUS_ISA
:
case
EICON_BUS_MCA
:
ret
=
eicon_isa_load
(
&
(
card
->
hwif
.
isa
),
&
(((
eicon_codebuf
*
)
a
)
->
isa
));
if
(
!
ret
)
{
card
->
flags
|=
EICON_FLAGS_LOADED
;
card
->
flags
|=
EICON_FLAGS_RUNNING
;
if
(
card
->
hwif
.
isa
.
channels
>
1
)
{
cmd
.
command
=
ISDN_STAT_ADDCH
;
cmd
.
driver
=
card
->
myid
;
cmd
.
arg
=
card
->
hwif
.
isa
.
channels
-
1
;
card
->
interface
.
statcallb
(
&
cmd
);
}
cmd
.
command
=
ISDN_STAT_RUN
;
cmd
.
driver
=
card
->
myid
;
cmd
.
arg
=
0
;
card
->
interface
.
statcallb
(
&
cmd
);
}
break
;
default:
eicon_log
(
card
,
1
,
"eicon: Illegal BUS type %d
\n
"
,
card
->
bus
);
ret
=
-
ENODEV
;
}
return
ret
;
#endif
case
EICON_IOCTL_MANIF
:
if
(
!
card
->
flags
&
EICON_FLAGS_RUNNING
)
return
-
ENODEV
;
if
(
!
card
->
d
)
return
-
ENODEV
;
if
(
!
card
->
d
->
features
&
DI_MANAGE
)
return
-
ENODEV
;
ret
=
eicon_idi_manage
(
card
,
(
eicon_manifbuf
*
)
a
);
return
ret
;
case
EICON_IOCTL_GETXLOG
:
return
-
ENODEV
;
case
EICON_IOCTL_ADDCARD
:
if
(
copy_from_user
(
&
cdef
,
(
char
*
)
a
,
sizeof
(
cdef
)))
return
-
EFAULT
;
if
(
!
(
eicon_addcard
(
0
,
cdef
.
membase
,
cdef
.
irq
,
cdef
.
id
,
0
)))
return
-
EIO
;
return
0
;
case
EICON_IOCTL_DEBUGVAR
:
DebugVar
=
a
;
eicon_log
(
card
,
1
,
"Eicon: Debug Value set to %ld
\n
"
,
DebugVar
);
return
0
;
case
EICON_IOCTL_LOADPCI
:
eicon_log
(
card
,
1
,
"Eicon: Wrong version of load-utility,
\n
"
);
eicon_log
(
card
,
1
,
"Eicon: re-compile eiconctrl !
\n
"
);
eicon_log
(
card
,
1
,
"Eicon: Maybe update of utility is necessary !
\n
"
);
return
-
EINVAL
;
default:
#ifdef CONFIG_PCI
#ifdef CONFIG_ISDN_DRV_EICON_PCI
if
(
c
->
arg
<
EICON_IOCTL_DIA_OFFSET
)
return
-
EINVAL
;
if
(
copy_from_user
(
&
dstart
,
(
char
*
)
a
,
sizeof
(
dstart
)))
return
-
EFAULT
;
if
(
!
(
card
=
eicon_findnpcicard
(
dstart
.
card_id
)))
return
-
EINVAL
;
ret
=
do_ioctl
(
NULL
,
NULL
,
c
->
arg
-
EICON_IOCTL_DIA_OFFSET
,
(
unsigned
long
)
a
);
if
(((
c
->
arg
-
EICON_IOCTL_DIA_OFFSET
)
==
DIA_IOCTL_START
)
&&
(
!
ret
))
{
if
(
card
->
type
!=
EICON_CTYPE_MAESTRAQ
)
{
DIVA_DIDD_Read
(
idi_d
,
sizeof
(
idi_d
));
for
(
idi_length
=
0
;
idi_length
<
32
;
idi_length
++
)
{
if
(
idi_d
[
idi_length
].
type
==
0
)
break
;
}
if
((
idi_length
<
1
)
||
(
idi_length
>=
32
))
{
eicon_log
(
card
,
1
,
"eicon: invalid idi table length.
\n
"
);
break
;
}
card
->
d
=
&
idi_d
[
idi_length
-
1
];
card
->
flags
|=
EICON_FLAGS_LOADED
;
card
->
flags
|=
EICON_FLAGS_RUNNING
;
eicon_pci_init_conf
(
card
);
if
(
card
->
d
->
channels
>
1
)
{
cmd
.
command
=
ISDN_STAT_ADDCH
;
cmd
.
driver
=
card
->
myid
;
cmd
.
arg
=
card
->
d
->
channels
-
1
;
card
->
interface
.
statcallb
(
&
cmd
);
}
cmd
.
command
=
ISDN_STAT_RUN
;
cmd
.
driver
=
card
->
myid
;
cmd
.
arg
=
0
;
card
->
interface
.
statcallb
(
&
cmd
);
eicon_log
(
card
,
1
,
"Eicon: %s started, %d channels (feat. 0x%x)
\n
"
,
(
card
->
type
==
EICON_CTYPE_MAESTRA
)
?
"BRI"
:
"PRI"
,
card
->
d
->
channels
,
card
->
d
->
features
);
}
else
{
int
i
;
DIVA_DIDD_Read
(
idi_d
,
sizeof
(
idi_d
));
for
(
idi_length
=
0
;
idi_length
<
32
;
idi_length
++
)
if
(
idi_d
[
idi_length
].
type
==
0
)
break
;
if
((
idi_length
<
1
)
||
(
idi_length
>=
32
))
{
eicon_log
(
card
,
1
,
"eicon: invalid idi table length.
\n
"
);
break
;
}
for
(
i
=
3
;
i
>=
0
;
i
--
)
{
if
(
!
(
card
=
eicon_findnpcicard
(
dstart
.
card_id
-
i
)))
return
-
EINVAL
;
card
->
flags
|=
EICON_FLAGS_LOADED
;
card
->
flags
|=
EICON_FLAGS_RUNNING
;
card
->
d
=
&
idi_d
[
idi_length
-
(
i
+
1
)];
eicon_pci_init_conf
(
card
);
if
(
card
->
d
->
channels
>
1
)
{
cmd
.
command
=
ISDN_STAT_ADDCH
;
cmd
.
driver
=
card
->
myid
;
cmd
.
arg
=
card
->
d
->
channels
-
1
;
card
->
interface
.
statcallb
(
&
cmd
);
}
cmd
.
command
=
ISDN_STAT_RUN
;
cmd
.
driver
=
card
->
myid
;
cmd
.
arg
=
0
;
card
->
interface
.
statcallb
(
&
cmd
);
eicon_log
(
card
,
1
,
"Eicon: %d/4BRI started, %d channels (feat. 0x%x)
\n
"
,
4
-
i
,
card
->
d
->
channels
,
card
->
d
->
features
);
}
}
}
return
ret
;
#else
return
-
EINVAL
;
#endif
#endif
/* CONFIG_PCI */
}
break
;
case
ISDN_CMD_DIAL
:
if
(
!
card
->
flags
&
EICON_FLAGS_RUNNING
)
return
-
ENODEV
;
if
(
!
(
chan
=
find_channel
(
card
,
c
->
arg
&
0x1f
)))
break
;
spin_lock_irqsave
(
&
eicon_lock
,
flags
);
if
((
chan
->
fsm_state
!=
EICON_STATE_NULL
)
&&
(
chan
->
fsm_state
!=
EICON_STATE_LISTEN
))
{
spin_unlock_irqrestore
(
&
eicon_lock
,
flags
);
eicon_log
(
card
,
1
,
"Dial on channel %d with state %d
\n
"
,
chan
->
No
,
chan
->
fsm_state
);
return
-
EBUSY
;
}
chan
->
fsm_state
=
EICON_STATE_OCALL
;
spin_unlock_irqrestore
(
&
eicon_lock
,
flags
);
ret
=
idi_connect_req
(
card
,
chan
,
c
->
parm
.
setup
.
phone
,
c
->
parm
.
setup
.
eazmsn
,
c
->
parm
.
setup
.
si1
,
c
->
parm
.
setup
.
si2
);
if
(
ret
)
{
cmd
.
driver
=
card
->
myid
;
cmd
.
command
=
ISDN_STAT_DHUP
;
cmd
.
arg
&=
0x1f
;
card
->
interface
.
statcallb
(
&
cmd
);
}
return
ret
;
case
ISDN_CMD_ACCEPTD
:
if
(
!
card
->
flags
&
EICON_FLAGS_RUNNING
)
return
-
ENODEV
;
if
(
!
(
chan
=
find_channel
(
card
,
c
->
arg
&
0x1f
)))
break
;
if
(
chan
->
fsm_state
==
EICON_STATE_ICALL
)
{
idi_connect_res
(
card
,
chan
);
}
return
0
;
case
ISDN_CMD_ACCEPTB
:
if
(
!
card
->
flags
&
EICON_FLAGS_RUNNING
)
return
-
ENODEV
;
return
0
;
case
ISDN_CMD_HANGUP
:
if
(
!
card
->
flags
&
EICON_FLAGS_RUNNING
)
return
-
ENODEV
;
if
(
!
(
chan
=
find_channel
(
card
,
c
->
arg
&
0x1f
)))
break
;
idi_hangup
(
card
,
chan
);
return
0
;
case
ISDN_CMD_SETEAZ
:
if
(
!
card
->
flags
&
EICON_FLAGS_RUNNING
)
return
-
ENODEV
;
if
(
!
(
chan
=
find_channel
(
card
,
c
->
arg
&
0x1f
)))
break
;
chan
->
eazmask
=
0x3ff
;
eicon_idi_listen_req
(
card
,
chan
);
return
0
;
case
ISDN_CMD_CLREAZ
:
if
(
!
card
->
flags
&
EICON_FLAGS_RUNNING
)
return
-
ENODEV
;
if
(
!
(
chan
=
find_channel
(
card
,
c
->
arg
&
0x1f
)))
break
;
chan
->
eazmask
=
0
;
eicon_idi_listen_req
(
card
,
chan
);
return
0
;
case
ISDN_CMD_SETL2
:
if
(
!
card
->
flags
&
EICON_FLAGS_RUNNING
)
return
-
ENODEV
;
if
(
!
(
chan
=
find_channel
(
card
,
c
->
arg
&
0x1f
)))
break
;
chan
->
l2prot
=
(
c
->
arg
>>
8
);
return
0
;
case
ISDN_CMD_SETL3
:
if
(
!
card
->
flags
&
EICON_FLAGS_RUNNING
)
return
-
ENODEV
;
if
(
!
(
chan
=
find_channel
(
card
,
c
->
arg
&
0x1f
)))
break
;
chan
->
l3prot
=
(
c
->
arg
>>
8
);
#ifdef CONFIG_ISDN_TTY_FAX
if
(
chan
->
l3prot
==
ISDN_PROTO_L3_FCLASS2
)
{
chan
->
fax
=
c
->
parm
.
fax
;
eicon_log
(
card
,
128
,
"idi_cmd: Ch%d: SETL3 struct fax=0x%x
\n
"
,
chan
->
No
,
chan
->
fax
);
}
#endif
return
0
;
#ifdef CONFIG_ISDN_TTY_FAX
case
ISDN_CMD_FAXCMD
:
if
(
!
card
->
flags
&
EICON_FLAGS_RUNNING
)
return
-
ENODEV
;
if
(
!
(
chan
=
find_channel
(
card
,
c
->
arg
&
0x1f
)))
break
;
if
(
!
chan
->
fax
)
break
;
idi_fax_cmd
(
card
,
chan
);
return
0
;
#endif
case
ISDN_CMD_AUDIO
:
if
(
!
card
->
flags
&
EICON_FLAGS_RUNNING
)
return
-
ENODEV
;
if
(
!
(
chan
=
find_channel
(
card
,
c
->
arg
&
0x1f
)))
break
;
idi_audio_cmd
(
card
,
chan
,
c
->
arg
>>
8
,
c
->
parm
.
num
);
return
0
;
case
CAPI_PUT_MESSAGE
:
if
(
!
card
->
flags
&
EICON_FLAGS_RUNNING
)
return
-
ENODEV
;
if
(
!
(
chan
=
find_channel
(
card
,
c
->
arg
&
0x1f
)))
break
;
if
(
c
->
parm
.
cmsg
.
Length
<
8
)
break
;
switch
(
c
->
parm
.
cmsg
.
Command
)
{
case
CAPI_FACILITY
:
if
(
c
->
parm
.
cmsg
.
Subcommand
==
CAPI_REQ
)
return
(
capipmsg
(
card
,
chan
,
&
c
->
parm
.
cmsg
));
break
;
case
CAPI_MANUFACTURER
:
default:
break
;
}
return
0
;
}
return
-
EINVAL
;
}
/*
* Find card with given driverId
*/
static
inline
eicon_card
*
eicon_findcard
(
int
driverid
)
{
eicon_card
*
p
=
cards
;
while
(
p
)
{
if
(
p
->
myid
==
driverid
)
return
p
;
p
=
p
->
next
;
}
return
(
eicon_card
*
)
0
;
}
/*
* Wrapper functions for interface to linklevel
*/
static
int
if_command
(
isdn_ctrl
*
c
)
{
eicon_card
*
card
=
eicon_findcard
(
c
->
driver
);
if
(
card
)
return
(
eicon_command
(
card
,
c
));
printk
(
KERN_ERR
"eicon: if_command %d called with invalid driverId %d!
\n
"
,
c
->
command
,
c
->
driver
);
return
-
ENODEV
;
}
static
int
if_writecmd
(
const
u_char
*
buf
,
int
len
,
int
user
,
int
id
,
int
channel
)
{
return
(
len
);
}
static
int
if_readstatus
(
u_char
*
buf
,
int
len
,
int
user
,
int
id
,
int
channel
)
{
int
count
=
0
;
int
cnt
=
0
;
ulong
flags
=
0
;
u_char
*
p
=
buf
;
struct
sk_buff
*
skb
;
eicon_card
*
card
=
eicon_findcard
(
id
);
if
(
card
)
{
if
(
!
card
->
flags
&
EICON_FLAGS_RUNNING
)
return
-
ENODEV
;
spin_lock_irqsave
(
&
eicon_lock
,
flags
);
while
((
skb
=
skb_dequeue
(
&
card
->
statq
)))
{
if
((
skb
->
len
+
count
)
>
len
)
cnt
=
len
-
count
;
else
cnt
=
skb
->
len
;
if
(
user
)
{
spin_unlock_irqrestore
(
&
eicon_lock
,
flags
);
if
(
copy_to_user
(
p
,
skb
->
data
,
cnt
))
return
-
EFAULT
;
spin_lock_irqsave
(
&
eicon_lock
,
flags
);
}
else
memcpy
(
p
,
skb
->
data
,
cnt
);
count
+=
cnt
;
p
+=
cnt
;
if
(
cnt
==
skb
->
len
)
{
dev_kfree_skb
(
skb
);
if
(
card
->
statq_entries
>
0
)
card
->
statq_entries
--
;
}
else
{
skb_pull
(
skb
,
cnt
);
skb_queue_head
(
&
card
->
statq
,
skb
);
spin_unlock_irqrestore
(
&
eicon_lock
,
flags
);
return
count
;
}
}
card
->
statq_entries
=
0
;
spin_unlock_irqrestore
(
&
eicon_lock
,
flags
);
return
count
;
}
printk
(
KERN_ERR
"eicon: if_readstatus called with invalid driverId!
\n
"
);
return
0
;
}
static
int
if_sendbuf
(
int
id
,
int
channel
,
int
ack
,
struct
sk_buff
*
skb
)
{
eicon_card
*
card
=
eicon_findcard
(
id
);
eicon_chan
*
chan
;
int
ret
=
0
;
int
len
;
len
=
skb
->
len
;
if
(
card
)
{
if
(
!
card
->
flags
&
EICON_FLAGS_RUNNING
)
return
-
ENODEV
;
if
(
!
(
chan
=
find_channel
(
card
,
channel
)))
return
-
ENODEV
;
if
(
chan
->
fsm_state
==
EICON_STATE_ACTIVE
)
{
#ifdef CONFIG_ISDN_TTY_FAX
if
(
chan
->
l2prot
==
ISDN_PROTO_L2_FAX
)
{
if
((
ret
=
idi_faxdata_send
(
card
,
chan
,
skb
))
>
0
)
ret
=
len
;
}
else
#endif
ret
=
idi_send_data
(
card
,
chan
,
ack
,
skb
,
1
,
1
);
return
(
ret
);
}
else
{
return
-
ENODEV
;
}
}
printk
(
KERN_ERR
"eicon: if_sendbuf called with invalid driverId!
\n
"
);
return
-
ENODEV
;
}
/* jiftime() copied from HiSax */
static
inline
int
jiftime
(
char
*
s
,
long
mark
)
{
s
+=
8
;
*
s
--
=
'\0'
;
*
s
--
=
mark
%
10
+
'0'
;
mark
/=
10
;
*
s
--
=
mark
%
10
+
'0'
;
mark
/=
10
;
*
s
--
=
'.'
;
*
s
--
=
mark
%
10
+
'0'
;
mark
/=
10
;
*
s
--
=
mark
%
6
+
'0'
;
mark
/=
6
;
*
s
--
=
':'
;
*
s
--
=
mark
%
10
+
'0'
;
mark
/=
10
;
*
s
--
=
mark
%
10
+
'0'
;
return
(
8
);
}
void
eicon_putstatus
(
eicon_card
*
card
,
char
*
buf
)
{
ulong
flags
;
int
count
;
isdn_ctrl
cmd
;
u_char
*
p
;
struct
sk_buff
*
skb
;
if
(
!
card
)
{
if
(
!
(
card
=
cards
))
return
;
}
spin_lock_irqsave
(
&
eicon_lock
,
flags
);
count
=
strlen
(
buf
);
skb
=
alloc_skb
(
count
,
GFP_ATOMIC
);
if
(
!
skb
)
{
spin_unlock_irqrestore
(
&
eicon_lock
,
flags
);
printk
(
KERN_ERR
"eicon: could not alloc skb in putstatus
\n
"
);
return
;
}
p
=
skb_put
(
skb
,
count
);
memcpy
(
p
,
buf
,
count
);
skb_queue_tail
(
&
card
->
statq
,
skb
);
if
(
card
->
statq_entries
>=
MAX_STATUS_BUFFER
)
{
if
((
skb
=
skb_dequeue
(
&
card
->
statq
)))
{
count
-=
skb
->
len
;
dev_kfree_skb
(
skb
);
}
else
count
=
0
;
}
else
card
->
statq_entries
++
;
spin_unlock_irqrestore
(
&
eicon_lock
,
flags
);
if
(
count
)
{
cmd
.
command
=
ISDN_STAT_STAVAIL
;
cmd
.
driver
=
card
->
myid
;
cmd
.
arg
=
count
;
card
->
interface
.
statcallb
(
&
cmd
);
}
}
/*
* Debug and Log
*/
void
eicon_log
(
eicon_card
*
card
,
int
level
,
const
char
*
fmt
,
...)
{
va_list
args
;
char
Line
[
160
];
u_char
*
p
;
if
((
DebugVar
&
level
)
||
(
DebugVar
&
256
))
{
va_start
(
args
,
fmt
);
if
(
DebugVar
&
level
)
{
if
(
DebugVar
&
256
)
{
/* log-buffer */
p
=
Line
;
p
+=
jiftime
(
p
,
jiffies
);
*
p
++
=
32
;
p
+=
vsprintf
(
p
,
fmt
,
args
);
*
p
=
0
;
eicon_putstatus
(
card
,
Line
);
}
else
{
/* printk, syslogd */
vsprintf
(
Line
,
fmt
,
args
);
printk
(
KERN_DEBUG
"%s"
,
Line
);
}
}
va_end
(
args
);
}
}
/*
* Allocate a new card-struct, initialize it
* link it into cards-list.
*/
static
void
eicon_alloccard
(
int
Type
,
int
membase
,
int
irq
,
char
*
id
,
int
card_id
)
{
int
i
;
int
j
;
int
qloop
;
#ifdef CONFIG_ISDN_DRV_EICON_ISA
char
qid
[
5
];
#endif
eicon_card
*
card
;
qloop
=
(
Type
==
EICON_CTYPE_QUADRO
)
?
2
:
0
;
for
(
i
=
0
;
i
<=
qloop
;
i
++
)
{
if
(
!
(
card
=
(
eicon_card
*
)
kmalloc
(
sizeof
(
eicon_card
),
GFP_KERNEL
)))
{
eicon_log
(
card
,
1
,
"eicon: (%s) Could not allocate card-struct.
\n
"
,
id
);
return
;
}
memset
((
char
*
)
card
,
0
,
sizeof
(
eicon_card
));
skb_queue_head_init
(
&
card
->
sndq
);
skb_queue_head_init
(
&
card
->
rcvq
);
skb_queue_head_init
(
&
card
->
rackq
);
skb_queue_head_init
(
&
card
->
sackq
);
skb_queue_head_init
(
&
card
->
statq
);
card
->
statq_entries
=
0
;
tasklet_init
(
&
card
->
snd_tq
,
eicon_transmit
,
(
unsigned
long
)
card
);
tasklet_init
(
&
card
->
rcv_tq
,
eicon_rcv_dispatch
,
(
unsigned
long
)
card
);
tasklet_init
(
&
card
->
ack_tq
,
eicon_ack_dispatch
,
(
unsigned
long
)
card
);
card
->
interface
.
owner
=
THIS_MODULE
;
card
->
interface
.
maxbufsize
=
4000
;
card
->
interface
.
command
=
if_command
;
card
->
interface
.
writebuf_skb
=
if_sendbuf
;
card
->
interface
.
writecmd
=
if_writecmd
;
card
->
interface
.
readstat
=
if_readstatus
;
card
->
interface
.
features
=
ISDN_FEATURE_L2_X75I
|
ISDN_FEATURE_L2_HDLC
|
ISDN_FEATURE_L2_TRANS
|
ISDN_FEATURE_L3_TRANS
|
ISDN_FEATURE_P_UNKNOWN
;
card
->
interface
.
hl_hdrlen
=
20
;
card
->
ptype
=
ISDN_PTYPE_UNKNOWN
;
strlcpy
(
card
->
interface
.
id
,
id
,
sizeof
(
card
->
interface
.
id
));
card
->
myid
=
-
1
;
card
->
type
=
Type
;
switch
(
Type
)
{
#ifdef CONFIG_ISDN_DRV_EICON_ISA
#ifdef CONFIG_MCA
/* only needed for MCA */
case
EICON_CTYPE_S
:
case
EICON_CTYPE_SX
:
case
EICON_CTYPE_SCOM
:
if
(
MCA_bus
)
{
if
(
membase
==
-
1
)
membase
=
EICON_ISA_MEMBASE
;
if
(
irq
==
-
1
)
irq
=
EICON_ISA_IRQ
;
card
->
bus
=
EICON_BUS_MCA
;
card
->
hwif
.
isa
.
card
=
(
void
*
)
card
;
card
->
hwif
.
isa
.
shmem
=
(
eicon_isa_shmem
*
)
membase
;
card
->
hwif
.
isa
.
physmem
=
(
unsigned
long
)
membase
;
card
->
hwif
.
isa
.
master
=
1
;
card
->
hwif
.
isa
.
irq
=
irq
;
card
->
hwif
.
isa
.
type
=
Type
;
card
->
nchannels
=
2
;
card
->
interface
.
channels
=
1
;
}
else
{
printk
(
KERN_WARNING
"eicon (%s): no MCA bus detected.
\n
"
,
card
->
interface
.
id
);
kfree
(
card
);
return
;
}
break
;
#endif
/* CONFIG_MCA */
case
EICON_CTYPE_QUADRO
:
if
(
membase
==
-
1
)
membase
=
EICON_ISA_MEMBASE
;
if
(
irq
==
-
1
)
irq
=
EICON_ISA_IRQ
;
card
->
bus
=
EICON_BUS_ISA
;
card
->
hwif
.
isa
.
card
=
(
void
*
)
card
;
card
->
hwif
.
isa
.
shmem
=
(
eicon_isa_shmem
*
)(
membase
+
(
i
+
1
)
*
EICON_ISA_QOFFSET
);
card
->
hwif
.
isa
.
physmem
=
(
unsigned
long
)(
membase
+
(
i
+
1
)
*
EICON_ISA_QOFFSET
);
card
->
hwif
.
isa
.
master
=
0
;
strcpy
(
card
->
interface
.
id
,
id
);
if
(
id
[
strlen
(
id
)
-
1
]
==
'a'
)
{
card
->
interface
.
id
[
strlen
(
id
)
-
1
]
=
'a'
+
i
+
1
;
}
else
{
sprintf
(
qid
,
"_%c"
,
'2'
+
i
);
strcat
(
card
->
interface
.
id
,
qid
);
}
printk
(
KERN_INFO
"Eicon: Quadro: Driver-Id %s added.
\n
"
,
card
->
interface
.
id
);
if
(
i
==
0
)
{
eicon_card
*
p
=
cards
;
while
(
p
)
{
if
((
p
->
hwif
.
isa
.
master
)
&&
(
p
->
hwif
.
isa
.
irq
==
irq
))
{
p
->
qnext
=
card
;
break
;
}
p
=
p
->
next
;
}
if
(
!
p
)
{
eicon_log
(
card
,
1
,
"eicon_alloccard: Quadro Master not found.
\n
"
);
kfree
(
card
);
return
;
}
}
else
{
cards
->
qnext
=
card
;
}
card
->
hwif
.
isa
.
irq
=
irq
;
card
->
hwif
.
isa
.
type
=
Type
;
card
->
nchannels
=
2
;
card
->
interface
.
channels
=
1
;
break
;
#endif
#ifdef CONFIG_PCI
#ifdef CONFIG_ISDN_DRV_EICON_PCI
case
EICON_CTYPE_MAESTRA
:
card
->
bus
=
EICON_BUS_PCI
;
card
->
interface
.
features
|=
ISDN_FEATURE_L2_V11096
|
ISDN_FEATURE_L2_V11019
|
ISDN_FEATURE_L2_V11038
|
ISDN_FEATURE_L2_MODEM
|
ISDN_FEATURE_L2_FAX
|
ISDN_FEATURE_L3_TRANSDSP
|
ISDN_FEATURE_L3_FCLASS2
;
card
->
hwif
.
pci
.
card
=
(
void
*
)
card
;
card
->
hwif
.
pci
.
master
=
card_id
;
card
->
hwif
.
pci
.
irq
=
irq
;
card
->
hwif
.
pci
.
type
=
Type
;
card
->
flags
=
0
;
card
->
nchannels
=
2
;
card
->
interface
.
channels
=
1
;
break
;
case
EICON_CTYPE_MAESTRAQ
:
card
->
bus
=
EICON_BUS_PCI
;
card
->
interface
.
features
|=
ISDN_FEATURE_L2_V11096
|
ISDN_FEATURE_L2_V11019
|
ISDN_FEATURE_L2_V11038
|
ISDN_FEATURE_L2_MODEM
|
ISDN_FEATURE_L2_FAX
|
ISDN_FEATURE_L3_TRANSDSP
|
ISDN_FEATURE_L3_FCLASS2
;
card
->
hwif
.
pci
.
card
=
(
void
*
)
card
;
card
->
hwif
.
pci
.
master
=
card_id
;
card
->
hwif
.
pci
.
irq
=
irq
;
card
->
hwif
.
pci
.
type
=
Type
;
card
->
flags
=
0
;
card
->
nchannels
=
2
;
card
->
interface
.
channels
=
1
;
break
;
case
EICON_CTYPE_MAESTRAP
:
card
->
bus
=
EICON_BUS_PCI
;
card
->
interface
.
features
|=
ISDN_FEATURE_L2_V11096
|
ISDN_FEATURE_L2_V11019
|
ISDN_FEATURE_L2_V11038
|
ISDN_FEATURE_L2_MODEM
|
ISDN_FEATURE_L2_FAX
|
ISDN_FEATURE_L3_TRANSDSP
|
ISDN_FEATURE_L3_FCLASS2
;
card
->
hwif
.
pci
.
card
=
(
void
*
)
card
;
card
->
hwif
.
pci
.
master
=
card_id
;
card
->
hwif
.
pci
.
irq
=
irq
;
card
->
hwif
.
pci
.
type
=
Type
;
card
->
flags
=
0
;
card
->
nchannels
=
30
;
card
->
interface
.
channels
=
1
;
break
;
#endif
#endif
#ifdef CONFIG_ISDN_DRV_EICON_ISA
case
EICON_CTYPE_ISABRI
:
if
(
membase
==
-
1
)
membase
=
EICON_ISA_MEMBASE
;
if
(
irq
==
-
1
)
irq
=
EICON_ISA_IRQ
;
card
->
bus
=
EICON_BUS_ISA
;
card
->
hwif
.
isa
.
card
=
(
void
*
)
card
;
card
->
hwif
.
isa
.
shmem
=
(
eicon_isa_shmem
*
)
membase
;
card
->
hwif
.
isa
.
physmem
=
(
unsigned
long
)
membase
;
card
->
hwif
.
isa
.
master
=
1
;
card
->
hwif
.
isa
.
irq
=
irq
;
card
->
hwif
.
isa
.
type
=
Type
;
card
->
nchannels
=
2
;
card
->
interface
.
channels
=
1
;
break
;
case
EICON_CTYPE_ISAPRI
:
if
(
membase
==
-
1
)
membase
=
EICON_ISA_MEMBASE
;
if
(
irq
==
-
1
)
irq
=
EICON_ISA_IRQ
;
card
->
bus
=
EICON_BUS_ISA
;
card
->
hwif
.
isa
.
card
=
(
void
*
)
card
;
card
->
hwif
.
isa
.
shmem
=
(
eicon_isa_shmem
*
)
membase
;
card
->
hwif
.
isa
.
physmem
=
(
unsigned
long
)
membase
;
card
->
hwif
.
isa
.
master
=
1
;
card
->
hwif
.
isa
.
irq
=
irq
;
card
->
hwif
.
isa
.
type
=
Type
;
card
->
nchannels
=
30
;
card
->
interface
.
channels
=
1
;
break
;
#endif
default:
eicon_log
(
card
,
1
,
"eicon_alloccard: Invalid type %d
\n
"
,
Type
);
kfree
(
card
);
return
;
}
if
(
!
(
card
->
bch
=
(
eicon_chan
*
)
kmalloc
(
sizeof
(
eicon_chan
)
*
(
card
->
nchannels
+
1
)
,
GFP_KERNEL
)))
{
eicon_log
(
card
,
1
,
"eicon: (%s) Could not allocate bch-struct.
\n
"
,
id
);
kfree
(
card
);
return
;
}
for
(
j
=
0
;
j
<
(
card
->
nchannels
+
1
);
j
++
)
{
memset
((
char
*
)
&
card
->
bch
[
j
],
0
,
sizeof
(
eicon_chan
));
card
->
bch
[
j
].
statectrl
=
0
;
card
->
bch
[
j
].
l2prot
=
ISDN_PROTO_L2_X75I
;
card
->
bch
[
j
].
l3prot
=
ISDN_PROTO_L3_TRANS
;
card
->
bch
[
j
].
e
.
D3Id
=
0
;
card
->
bch
[
j
].
e
.
B2Id
=
0
;
card
->
bch
[
j
].
e
.
Req
=
0
;
card
->
bch
[
j
].
No
=
j
;
card
->
bch
[
j
].
tskb1
=
NULL
;
card
->
bch
[
j
].
tskb2
=
NULL
;
skb_queue_head_init
(
&
card
->
bch
[
j
].
e
.
X
);
skb_queue_head_init
(
&
card
->
bch
[
j
].
e
.
R
);
}
#ifdef CONFIG_ISDN_DRV_EICON_PCI
/* *** Diva Server *** */
if
(
!
(
card
->
dbuf
=
(
DBUFFER
*
)
kmalloc
((
sizeof
(
DBUFFER
)
*
(
card
->
nchannels
+
1
))
*
2
,
GFP_KERNEL
)))
{
eicon_log
(
card
,
1
,
"eicon: (%s) Could not allocate DBUFFER-struct.
\n
"
,
id
);
kfree
(
card
);
kfree
(
card
->
bch
);
return
;
}
if
(
!
(
card
->
sbuf
=
(
BUFFERS
*
)
kmalloc
((
sizeof
(
BUFFERS
)
*
(
card
->
nchannels
+
1
))
*
2
,
GFP_KERNEL
)))
{
eicon_log
(
card
,
1
,
"eicon: (%s) Could not allocate BUFFERS-struct.
\n
"
,
id
);
kfree
(
card
);
kfree
(
card
->
bch
);
kfree
(
card
->
dbuf
);
return
;
}
if
(
!
(
card
->
sbufp
=
(
char
*
)
kmalloc
((
270
*
(
card
->
nchannels
+
1
))
*
2
,
GFP_KERNEL
)))
{
eicon_log
(
card
,
1
,
"eicon: (%s) Could not allocate BUFFERSP-struct.
\n
"
,
id
);
kfree
(
card
);
kfree
(
card
->
bch
);
kfree
(
card
->
dbuf
);
kfree
(
card
->
sbuf
);
return
;
}
for
(
j
=
0
;
j
<
(
card
->
nchannels
+
1
);
j
++
)
{
memset
((
char
*
)
&
card
->
dbuf
[
j
],
0
,
sizeof
(
DBUFFER
));
card
->
bch
[
j
].
de
.
RBuffer
=
(
DBUFFER
*
)
&
card
->
dbuf
[
j
];
memset
((
char
*
)
&
card
->
dbuf
[
j
+
(
card
->
nchannels
+
1
)],
0
,
sizeof
(
BUFFERS
));
card
->
bch
[
j
].
be
.
RBuffer
=
(
DBUFFER
*
)
&
card
->
dbuf
[
j
+
(
card
->
nchannels
+
1
)];
memset
((
char
*
)
&
card
->
sbuf
[
j
],
0
,
sizeof
(
BUFFERS
));
card
->
bch
[
j
].
de
.
X
=
(
BUFFERS
*
)
&
card
->
sbuf
[
j
];
memset
((
char
*
)
&
card
->
sbuf
[
j
+
(
card
->
nchannels
+
1
)],
0
,
sizeof
(
BUFFERS
));
card
->
bch
[
j
].
be
.
X
=
(
BUFFERS
*
)
&
card
->
sbuf
[
j
+
(
card
->
nchannels
+
1
)];
memset
((
char
*
)
&
card
->
sbufp
[
j
],
0
,
270
);
card
->
bch
[
j
].
de
.
X
->
P
=
(
char
*
)
&
card
->
sbufp
[
j
*
270
];
memset
((
char
*
)
&
card
->
sbufp
[
j
+
(
card
->
nchannels
+
1
)],
0
,
270
);
card
->
bch
[
j
].
be
.
X
->
P
=
(
char
*
)
&
card
->
sbufp
[(
j
+
(
card
->
nchannels
+
1
))
*
270
];
}
/* *** */
#endif
/* CONFIG_ISDN_DRV_EICON_PCI */
card
->
next
=
cards
;
cards
=
card
;
}
}
/*
* register card at linklevel
*/
static
int
eicon_registercard
(
eicon_card
*
card
)
{
switch
(
card
->
bus
)
{
#ifdef CONFIG_ISDN_DRV_EICON_ISA
case
EICON_BUS_ISA
:
/* TODO something to print */
break
;
#ifdef CONFIG_MCA
case
EICON_BUS_MCA
:
eicon_isa_printpar
(
&
card
->
hwif
.
isa
);
break
;
#endif
/* CONFIG_MCA */
#endif
case
EICON_BUS_PCI
:
break
;
default:
eicon_log
(
card
,
1
,
"eicon_registercard: Illegal BUS type %d
\n
"
,
card
->
bus
);
return
-
1
;
}
if
(
!
register_isdn
(
&
card
->
interface
))
{
printk
(
KERN_WARNING
"eicon_registercard: Unable to register %s
\n
"
,
card
->
interface
.
id
);
return
-
1
;
}
card
->
myid
=
card
->
interface
.
channels
;
sprintf
(
card
->
regname
,
"%s"
,
card
->
interface
.
id
);
return
0
;
}
static
void
__exit
unregister_card
(
eicon_card
*
card
)
{
isdn_ctrl
cmd
;
cmd
.
command
=
ISDN_STAT_UNLOAD
;
cmd
.
driver
=
card
->
myid
;
card
->
interface
.
statcallb
(
&
cmd
);
switch
(
card
->
bus
)
{
#ifdef CONFIG_ISDN_DRV_EICON_ISA
case
EICON_BUS_ISA
:
#ifdef CONFIG_MCA
case
EICON_BUS_MCA
:
#endif
/* CONFIG_MCA */
eicon_isa_release
(
&
card
->
hwif
.
isa
);
break
;
#endif
case
EICON_BUS_PCI
:
break
;
default:
eicon_log
(
card
,
1
,
"eicon: Invalid BUS type %d
\n
"
,
card
->
bus
);
break
;
}
}
static
void
eicon_freecard
(
eicon_card
*
card
)
{
int
i
;
for
(
i
=
0
;
i
<
(
card
->
nchannels
+
1
);
i
++
)
{
skb_queue_purge
(
&
card
->
bch
[
i
].
e
.
X
);
skb_queue_purge
(
&
card
->
bch
[
i
].
e
.
R
);
}
skb_queue_purge
(
&
card
->
sndq
);
skb_queue_purge
(
&
card
->
rcvq
);
skb_queue_purge
(
&
card
->
rackq
);
skb_queue_purge
(
&
card
->
sackq
);
skb_queue_purge
(
&
card
->
statq
);
#ifdef CONFIG_ISDN_DRV_EICON_PCI
kfree
(
card
->
sbufp
);
kfree
(
card
->
sbuf
);
kfree
(
card
->
dbuf
);
#endif
kfree
(
card
->
bch
);
kfree
(
card
);
}
int
eicon_addcard
(
int
Type
,
int
membase
,
int
irq
,
char
*
id
,
int
card_id
)
{
eicon_card
*
p
;
eicon_card
*
q
=
NULL
;
int
registered
;
int
added
=
0
;
int
failed
=
0
;
#ifdef CONFIG_ISDN_DRV_EICON_ISA
if
(
!
Type
)
/* ISA */
if
((
Type
=
eicon_isa_find_card
(
membase
,
irq
,
id
))
<
0
)
return
0
;
#endif
eicon_alloccard
(
Type
,
membase
,
irq
,
id
,
card_id
);
p
=
cards
;
while
(
p
)
{
registered
=
0
;
if
(
!
p
->
interface
.
statcallb
)
{
/* Not yet registered.
* Try to register and activate it.
*/
added
++
;
switch
(
p
->
bus
)
{
#ifdef CONFIG_ISDN_DRV_EICON_ISA
case
EICON_BUS_ISA
:
case
EICON_BUS_MCA
:
if
(
eicon_registercard
(
p
))
break
;
registered
=
1
;
break
;
#endif
case
EICON_BUS_PCI
:
#ifdef CONFIG_PCI
#ifdef CONFIG_ISDN_DRV_EICON_PCI
if
(
eicon_registercard
(
p
))
break
;
registered
=
1
;
break
;
#endif
#endif
default:
printk
(
KERN_ERR
"eicon: addcard: Invalid BUS type %d
\n
"
,
p
->
bus
);
}
}
else
/* Card already registered */
registered
=
1
;
if
(
registered
)
{
/* Init OK, next card ... */
q
=
p
;
p
=
p
->
next
;
}
else
{
/* registering failed, remove card from list, free memory */
printk
(
KERN_ERR
"eicon: Initialization of %s failed
\n
"
,
p
->
interface
.
id
);
if
(
q
)
{
q
->
next
=
p
->
next
;
eicon_freecard
(
p
);
p
=
q
->
next
;
}
else
{
cards
=
p
->
next
;
eicon_freecard
(
p
);
p
=
cards
;
}
failed
++
;
}
}
return
(
added
-
failed
);
}
static
int
__init
eicon_init
(
void
)
{
int
card_count
=
0
;
char
tmprev
[
50
];
DebugVar
=
1
;
eicon_lock
=
(
spinlock_t
)
SPIN_LOCK_UNLOCKED
;
printk
(
KERN_INFO
"%s Rev: "
,
DRIVERNAME
);
strcpy
(
tmprev
,
eicon_revision
);
printk
(
"%s/"
,
eicon_getrev
(
tmprev
));
strcpy
(
tmprev
,
eicon_pci_revision
);
#ifdef CONFIG_ISDN_DRV_EICON_PCI
printk
(
"%s/"
,
eicon_getrev
(
tmprev
));
#else
printk
(
"---/"
);
#endif
strcpy
(
tmprev
,
eicon_isa_revision
);
#ifdef CONFIG_ISDN_DRV_EICON_ISA
printk
(
"%s/"
,
eicon_getrev
(
tmprev
));
#else
printk
(
"---/"
);
#endif
strcpy
(
tmprev
,
eicon_idi_revision
);
printk
(
"%s
\n
"
,
eicon_getrev
(
tmprev
));
printk
(
KERN_INFO
"%s Release: %s%s
\n
"
,
DRIVERNAME
,
DRIVERRELEASE
,
DRIVERPATCH
);
#ifdef CONFIG_ISDN_DRV_EICON_ISA
#ifdef CONFIG_MCA
/* Check if we have MCA-bus */
if
(
!
MCA_bus
)
{
printk
(
KERN_INFO
"eicon: No MCA bus, ISDN-interfaces not probed.
\n
"
);
}
else
{
eicon_log
(
NULL
,
8
,
"eicon_mca_find_card, irq=%d.
\n
"
,
irq
);
if
(
!
eicon_mca_find_card
(
0
,
membase
,
irq
,
id
))
card_count
++
;
};
#else
card_count
=
eicon_addcard
(
0
,
membase
,
irq
,
id
,
0
);
#endif
/* CONFIG_MCA */
#endif
/* CONFIG_ISDN_DRV_EICON_ISA */
#ifdef CONFIG_PCI
#ifdef CONFIG_ISDN_DRV_EICON_PCI
DivasCardsDiscover
();
card_count
+=
eicon_pci_find_card
(
id
);
#endif
#endif
if
(
!
cards
)
{
#ifdef MODULE
#ifndef CONFIG_ISDN_DRV_EICON_PCI
#ifndef CONFIG_ISDN_DRV_EICON_ISA
printk
(
KERN_INFO
"Eicon: Driver is neither ISA nor PCI compiled !
\n
"
);
printk
(
KERN_INFO
"Eicon: Driver not loaded !
\n
"
);
#else
printk
(
KERN_INFO
"Eicon: No cards defined, driver not loaded !
\n
"
);
#endif
#else
printk
(
KERN_INFO
"Eicon: No PCI-cards found, driver not loaded !
\n
"
);
#endif
#endif
/* MODULE */
return
-
ENODEV
;
}
else
printk
(
KERN_INFO
"Eicon: %d card%s added
\n
"
,
card_count
,
(
card_count
>
1
)
?
"s"
:
""
);
return
0
;
}
#ifdef CONFIG_ISDN_DRV_EICON_PCI
void
DIVA_DIDD_Write
(
DESCRIPTOR
*
,
int
);
EXPORT_SYMBOL_NOVERS
(
DIVA_DIDD_Read
);
EXPORT_SYMBOL_NOVERS
(
DIVA_DIDD_Write
);
EXPORT_SYMBOL_NOVERS
(
DivasPrintf
);
#else
int
DivasCardNext
;
card_t
DivasCards
[
1
];
#endif
static
void
__exit
eicon_exit
(
void
)
{
#ifdef CONFIG_PCI
#ifdef CONFIG_ISDN_DRV_EICON_PCI
card_t
*
pCard
;
word
wCardIndex
;
extern
int
Divas_major
;
int
iTmp
=
0
;
#endif
#endif
eicon_card
*
card
=
cards
;
eicon_card
*
last
;
while
(
card
)
{
#ifdef CONFIG_ISDN_DRV_EICON_ISA
#ifdef CONFIG_MCA
if
(
MCA_bus
)
{
mca_mark_as_unused
(
card
->
mca_slot
);
mca_set_adapter_procfn
(
card
->
mca_slot
,
NULL
,
NULL
);
};
#endif
/* CONFIG_MCA */
#endif
unregister_card
(
card
);
card
=
card
->
next
;
}
card
=
cards
;
while
(
card
)
{
last
=
card
;
card
=
card
->
next
;
eicon_freecard
(
last
);
}
#ifdef CONFIG_PCI
#ifdef CONFIG_ISDN_DRV_EICON_PCI
pCard
=
DivasCards
;
for
(
wCardIndex
=
0
;
wCardIndex
<
MAX_CARDS
;
wCardIndex
++
)
{
if
((
pCard
->
hw
)
&&
(
pCard
->
hw
->
in_use
))
{
(
*
pCard
->
card_reset
)(
pCard
);
UxIsrRemove
(
pCard
->
hw
,
pCard
);
UxCardHandleFree
(
pCard
->
hw
);
if
(
pCard
->
e_tbl
!=
NULL
)
{
kfree
(
pCard
->
e_tbl
);
}
if
(
pCard
->
hw
->
card_type
==
DIA_CARD_TYPE_DIVA_SERVER_B
)
{
release_region
(
pCard
->
hw
->
io_base
,
0x20
);
release_region
(
pCard
->
hw
->
reset_base
,
0x80
);
}
// If this is a 4BRI ...
if
(
pCard
->
hw
->
card_type
==
DIA_CARD_TYPE_DIVA_SERVER_Q
)
{
// Skip over the next 3 virtual adapters
wCardIndex
+=
3
;
// But free their handles
for
(
iTmp
=
0
;
iTmp
<
3
;
iTmp
++
)
{
pCard
++
;
UxCardHandleFree
(
pCard
->
hw
);
if
(
pCard
->
e_tbl
!=
NULL
)
{
kfree
(
pCard
->
e_tbl
);
}
}
}
}
pCard
++
;
}
unregister_chrdev
(
Divas_major
,
"Divas"
);
#endif
#endif
/* CONFIG_PCI */
printk
(
KERN_INFO
"%s unloaded
\n
"
,
DRIVERNAME
);
}
#ifndef MODULE
static
int
__init
eicon_setup
(
char
*
line
)
{
int
i
,
argc
;
int
ints
[
5
];
char
*
str
;
str
=
get_options
(
line
,
4
,
ints
);
argc
=
ints
[
0
];
i
=
1
;
#ifdef CONFIG_ISDN_DRV_EICON_ISA
if
(
argc
)
{
membase
=
irq
=
-
1
;
if
(
argc
)
{
membase
=
ints
[
i
];
i
++
;
argc
--
;
}
if
(
argc
)
{
irq
=
ints
[
i
];
i
++
;
argc
--
;
}
if
(
strlen
(
str
))
{
strcpy
(
id
,
str
);
}
else
{
strcpy
(
id
,
"eicon"
);
}
printk
(
KERN_INFO
"Eicon ISDN active driver setup (id=%s membase=0x%x irq=%d)
\n
"
,
id
,
membase
,
irq
);
}
#else
printk
(
KERN_INFO
"Eicon ISDN active driver setup
\n
"
);
#endif
return
(
1
);
}
__setup
(
"eicon="
,
eicon_setup
);
#endif
/* MODULE */
#ifdef CONFIG_ISDN_DRV_EICON_ISA
#ifdef CONFIG_MCA
struct
eicon_mca_adapters_struct
{
char
*
name
;
int
adf_id
;
};
/* possible MCA-brands of eicon cards */
struct
eicon_mca_adapters_struct
eicon_mca_adapters
[]
=
{
{
"ISDN-P/2 Adapter"
,
0x6abb
},
{
"ISDN-[S|SX|SCOM]/2 Adapter"
,
0x6a93
},
{
"DIVA /MCA"
,
0x6336
},
{
NULL
,
0
},
};
int
eicon_mca_find_card
(
int
type
,
/* type-idx of eicon-card */
int
membase
,
int
irq
,
char
*
id
)
/* name of eicon-isdn-dev */
{
int
j
,
curr_slot
=
0
;
eicon_log
(
NULL
,
8
,
"eicon_mca_find_card type: %d, membase: %#x, irq %d
\n
"
,
type
,
membase
,
irq
);
/* find a no-driver-assigned eicon card */
for
(
j
=
0
;
eicon_mca_adapters
[
j
].
adf_id
!=
0
;
j
++
)
{
for
(
curr_slot
=
0
;
curr_slot
<=
MCA_MAX_SLOT_NR
;
curr_slot
++
)
{
curr_slot
=
mca_find_unused_adapter
(
eicon_mca_adapters
[
j
].
adf_id
,
curr_slot
);
if
(
curr_slot
!=
MCA_NOTFOUND
)
{
/* check if pre-set parameters match
these of the card, check cards memory */
if
(
!
(
int
)
eicon_mca_probe
(
curr_slot
,
j
,
membase
,
irq
,
id
))
{
return
0
;
/* means: adapter parms did match */
};
};
break
;
/* MCA_NOTFOUND-branch: no matching adapter of
THIS flavor found, next flavor */
};
};
/* all adapter flavors checked without match, finito with: */
return
-
ENODEV
;
};
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* stolen from 3c523.c/elmc_getinfo, ewe, 10.5.1999
*/
int
eicon_info
(
char
*
buf
,
int
slot
,
void
*
d
)
{
int
len
=
0
;
struct
eicon_card
*
dev
;
dev
=
(
struct
eicon_card
*
)
d
;
if
(
dev
==
NULL
)
return
len
;
len
+=
sprintf
(
buf
+
len
,
"eicon ISDN adapter, type %d.
\n
"
,
dev
->
type
);
len
+=
sprintf
(
buf
+
len
,
"IRQ: %d
\n
"
,
dev
->
hwif
.
isa
.
irq
);
len
+=
sprintf
(
buf
+
len
,
"MEMBASE: %#lx
\n
"
,
(
unsigned
long
)
dev
->
hwif
.
isa
.
shmem
);
return
len
;
};
int
eicon_mca_probe
(
int
slot
,
/* slot-nr where the card was detected */
int
a_idx
,
/* idx-nr of probed card in eicon_mca_adapters */
int
membase
,
int
irq
,
char
*
id
)
/* name of eicon-isdn-dev */
{
unsigned
char
adf_pos0
;
int
cards_irq
,
cards_membase
,
cards_io
;
int
type
=
EICON_CTYPE_S
;
int
irq_array
[]
=
{
0
,
3
,
4
,
2
};
int
irq_array1
[]
=
{
3
,
4
,
0
,
0
,
2
,
10
,
11
,
12
};
adf_pos0
=
mca_read_stored_pos
(
slot
,
2
);
eicon_log
(
NULL
,
8
,
"eicon_mca_probe irq=%d, membase=%d
\n
"
,
irq
,
membase
);
switch
(
a_idx
)
{
case
0
:
/* P/2-Adapter (== PRI/S2M ? ) */
cards_membase
=
0xC0000
+
((
adf_pos0
>>
4
)
*
0x4000
);
if
(
membase
==
-
1
)
{
membase
=
cards_membase
;
}
else
{
if
(
membase
!=
cards_membase
)
return
-
ENODEV
;
};
cards_irq
=
irq_array
[((
adf_pos0
&
0xC
)
>>
2
)];
if
(
irq
==
-
1
)
{
irq
=
cards_irq
;
}
else
{
if
(
irq
!=
cards_irq
)
return
-
ENODEV
;
};
cards_io
=
0xC00
+
((
adf_pos0
>>
4
)
*
0x10
);
type
=
EICON_CTYPE_ISAPRI
;
break
;
case
1
:
/* [S|SX|SCOM]/2 */
cards_membase
=
0xC0000
+
((
adf_pos0
>>
4
)
*
0x2000
);
if
(
membase
==
-
1
)
{
membase
=
cards_membase
;
}
else
{
if
(
membase
!=
cards_membase
)
return
-
ENODEV
;
};
cards_irq
=
irq_array
[((
adf_pos0
&
0xC
)
>>
2
)];
if
(
irq
==
-
1
)
{
irq
=
cards_irq
;
}
else
{
if
(
irq
!=
cards_irq
)
return
-
ENODEV
;
};
cards_io
=
0xC00
+
((
adf_pos0
>>
4
)
*
0x10
);
type
=
EICON_CTYPE_SCOM
;
break
;
case
2
:
/* DIVA/MCA */
cards_io
=
0x200
+
((
adf_pos0
>>
4
)
*
0x20
);
cards_irq
=
irq_array1
[(
adf_pos0
&
0x7
)];
if
(
irq
==
-
1
)
{
irq
=
cards_irq
;
}
else
{
if
(
irq
!=
cards_irq
)
return
-
ENODEV
;
};
type
=
0
;
break
;
default:
return
-
ENODEV
;
};
/* matching membase & irq */
if
(
1
==
eicon_addcard
(
type
,
membase
,
irq
,
id
,
0
))
{
mca_set_adapter_name
(
slot
,
eicon_mca_adapters
[
a_idx
].
name
);
mca_set_adapter_procfn
(
slot
,
(
MCA_ProcFn
)
eicon_info
,
cards
);
mca_mark_as_used
(
slot
);
cards
->
mca_slot
=
slot
;
/* card->io noch setzen oder ?? */
cards
->
mca_io
=
cards_io
;
cards
->
hwif
.
isa
.
io
=
cards_io
;
/* reset card */
outb_p
(
0
,
cards_io
+
1
);
eicon_log
(
NULL
,
8
,
"eicon_addcard: successful for slot # %d.
\n
"
,
cards
->
mca_slot
+
1
);
return
0
;
/* eicon_addcard added a card */
}
else
{
return
-
ENODEV
;
};
};
#endif
/* CONFIG_MCA */
#endif
/* CONFIG_ISDN_DRV_EICON_ISA */
module_init
(
eicon_init
);
module_exit
(
eicon_exit
);
drivers/isdn/eicon/eicon_pci.c
deleted
100644 → 0
View file @
f69c2d56
/* $Id: eicon_pci.c,v 1.1.4.1.2.3 2002/10/01 11:29:13 armin Exp $
*
* ISDN low-level module for Eicon active ISDN-Cards.
* Hardware-specific code for PCI cards.
*
* Copyright 1998-2000 by Armin Schindler (mac@melware.de)
* Copyright 1999,2000 Cytronics & Melware (info@melware.de)
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
* Thanks to Eicon Networks for
* documents, informations and hardware.
*
*/
#include <linux/config.h>
#include <linux/pci.h>
#include "eicon.h"
#include "eicon_pci.h"
#undef N_DATA
#include "adapter.h"
#include "uxio.h"
char
*
eicon_pci_revision
=
"$Revision: 1.1.4.1.2.3 $"
;
#ifdef CONFIG_PCI
/* entire stuff is only for PCI */
#ifdef CONFIG_ISDN_DRV_EICON_PCI
int
eicon_pci_find_card
(
char
*
ID
)
{
int
pci_cards
=
0
;
int
card_id
=
0
;
int
had_q
=
0
;
int
ctype
=
0
;
char
did
[
20
];
card_t
*
pCard
;
word
wCardIndex
;
pCard
=
DivasCards
;
for
(
wCardIndex
=
0
;
wCardIndex
<
MAX_CARDS
;
wCardIndex
++
)
{
if
((
pCard
->
hw
)
&&
(
pCard
->
hw
->
in_use
))
{
switch
(
pCard
->
hw
->
card_type
)
{
case
DIA_CARD_TYPE_DIVA_SERVER
:
ctype
=
EICON_CTYPE_MAESTRAP
;
card_id
++
;
had_q
=
0
;
break
;
case
DIA_CARD_TYPE_DIVA_SERVER_B
:
ctype
=
EICON_CTYPE_MAESTRA
;
card_id
++
;
had_q
=
0
;
break
;
case
DIA_CARD_TYPE_DIVA_SERVER_Q
:
ctype
=
EICON_CTYPE_MAESTRAQ
;
if
(
!
had_q
)
card_id
++
;
if
(
++
had_q
>=
4
)
had_q
=
0
;
break
;
default:
printk
(
KERN_ERR
"eicon_pci: unknown card type %d !
\n
"
,
pCard
->
hw
->
card_type
);
goto
err
;
}
sprintf
(
did
,
"%s%d"
,
(
strlen
(
ID
)
<
1
)
?
"eicon"
:
ID
,
pci_cards
);
if
((
!
ctype
)
||
(
!
(
eicon_addcard
(
ctype
,
0
,
pCard
->
hw
->
irq
,
did
,
card_id
))))
{
printk
(
KERN_ERR
"eicon_pci: Card could not be added !
\n
"
);
}
else
{
pci_cards
++
;
printk
(
KERN_INFO
"%s: DriverID='%s' CardID=%d
\n
"
,
eicon_ctype_name
[
ctype
],
did
,
card_id
);
}
err:
;
}
pCard
++
;
}
return
pci_cards
;
}
void
eicon_pci_init_conf
(
eicon_card
*
card
)
{
int
j
;
/* initializing some variables */
card
->
ReadyInt
=
0
;
for
(
j
=
0
;
j
<
256
;
j
++
)
card
->
IdTable
[
j
]
=
NULL
;
for
(
j
=
0
;
j
<
(
card
->
d
->
channels
+
1
);
j
++
)
{
card
->
bch
[
j
].
e
.
busy
=
0
;
card
->
bch
[
j
].
e
.
D3Id
=
0
;
card
->
bch
[
j
].
e
.
B2Id
=
0
;
card
->
bch
[
j
].
e
.
ref
=
0
;
card
->
bch
[
j
].
e
.
Req
=
0
;
card
->
bch
[
j
].
e
.
complete
=
1
;
card
->
bch
[
j
].
fsm_state
=
EICON_STATE_NULL
;
}
}
#endif
#endif
/* CONFIG_PCI */
drivers/isdn/eicon/eicon_pci.h
deleted
100644 → 0
View file @
f69c2d56
/* $Id: eicon_pci.h,v 1.1.4.1.2.2 2002/10/01 11:29:13 armin Exp $
*
* ISDN low-level module for Eicon active ISDN-Cards (PCI part).
*
* Copyright 1998-2000 by Armin Schindler (mac@melware.de)
* Copyright 1999,2000 Cytronics & Melware (info@melware.de)
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#ifndef eicon_pci_h
#define eicon_pci_h
#ifdef __KERNEL__
/*
* card's description
*/
typedef
struct
{
int
irq
;
/* IRQ */
int
channels
;
/* No. of supported channels */
void
*
card
;
unsigned
char
type
;
/* card type */
unsigned
char
master
;
/* Flag: Card is Quadro 1/4 */
}
eicon_pci_card
;
extern
int
eicon_pci_find_card
(
char
*
ID
);
#endif
/* __KERNEL__ */
#endif
/* eicon_pci_h */
drivers/isdn/eicon/fourbri.c
deleted
100644 → 0
View file @
f69c2d56
/*
* Diva Server 4BRI specific part of initialisation
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.7
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include "sys.h"
#include "idi.h"
#include "divas.h"
#include "pc.h"
#include "pr_pc.h"
#include "dsp_defs.h"
#include "constant.h"
#include "adapter.h"
#include "uxio.h"
#define TEST_INT_DIVAS_Q 0x13
#define DIVAS_MAINT_OFFSET 0xff00
/* value for 4BRI card */
#define MQ_BOARD_DSP_OFFSET 0x00a00000
#define MQ_DSP1_ADDR_OFFSET 0x00000008
#define MQ_DSP_JUNK_OFFSET 0x00000400
#define MQ_DSP1_DATA_OFFSET 0x00000000
#define MQ_BOARD_ISAC_DSP_RESET 0x00800028
#define MQ_BREG_RISC 0x1200
/* RISC Reset */
#define MQ_ISAC_DSP_RESET 0x0028
/* ISAC and DSP reset address offset */
#define MQ_RISC_COLD_RESET_MASK 0x0001
/* RISC Cold reset */
#define MQ_RISC_WARM_RESET_MASK 0x0002
/* RISC Warm reset */
#define MQ_IRQ_REQ_ON 0x1
#define MQ_IRQ_REQ_OFF 0x0
#define MQ_BREG_IRQ_TEST 0x0608
#define PLX9054_INTCSR 0x69
#define PLX9054_INT_ENA 0x09
#define DIVAS_IOBASE 0x01
#define M_PCI_RESET 0x10
byte
mem_in
(
ADAPTER
*
a
,
void
*
adr
);
word
mem_inw
(
ADAPTER
*
a
,
void
*
adr
);
void
mem_in_buffer
(
ADAPTER
*
a
,
void
*
adr
,
void
*
P
,
word
length
);
void
mem_look_ahead
(
ADAPTER
*
a
,
PBUFFER
*
RBuffer
,
ENTITY
*
e
);
void
mem_out
(
ADAPTER
*
a
,
void
*
adr
,
byte
data
);
void
mem_outw
(
ADAPTER
*
a
,
void
*
adr
,
word
data
);
void
mem_out_buffer
(
ADAPTER
*
a
,
void
*
adr
,
void
*
P
,
word
length
);
void
mem_inc
(
ADAPTER
*
a
,
void
*
adr
);
int
Divas4BRIInitPCI
(
card_t
*
card
,
dia_card_t
*
cfg
);
static
int
fourbri_ISR
(
card_t
*
card
);
int
FPGA_Download
(
word
,
dword
,
byte
*
,
byte
*
,
int
);
extern
byte
FPGA_Bytes
[];
extern
void
*
get_card
(
int
);
byte
UxCardPortIoIn
(
ux_diva_card_t
*
card
,
byte
*
base
,
int
offset
);
void
UxCardPortIoOut
(
ux_diva_card_t
*
card
,
byte
*
base
,
int
offset
,
byte
);
word
GetProtFeatureValue
(
char
*
sw_id
);
void
memcp
(
byte
*
dst
,
byte
*
src
,
dword
dwLen
);
int
memcm
(
byte
*
dst
,
byte
*
src
,
dword
dwLen
);
static
int
diva_server_4bri_reset
(
card_t
*
card
)
{
byte
*
ctl
;
DPRINTF
((
"divas: reset Diva Server 4BRI"
));
ctl
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_CTL_MEMORY
);
/* stop RISC, DSP's and ISAC */
UxCardMemOut
(
card
->
hw
,
&
ctl
[
MQ_BREG_RISC
],
0
);
UxCardMemOut
(
card
->
hw
,
&
ctl
[
MQ_ISAC_DSP_RESET
],
0
);
UxCardMemDetach
(
card
->
hw
,
ctl
);
return
0
;
}
static
int
diva_server_4bri_config
(
card_t
*
card
,
dia_config_t
*
config
)
{
byte
*
shared
;
int
i
,
j
;
DPRINTF
((
"divas: configure Diva Server 4BRI"
));
shared
=
(
byte
*
)
UxCardMemAttach
(
card
->
hw
,
DIVAS_SHARED_MEMORY
);
for
(
i
=
0
;
i
<
256
;
i
++
)
{
UxCardMemOut
(
card
->
hw
,
&
shared
[
i
],
0
);
}
UxCardMemOut
(
card
->
hw
,
&
shared
[
8
],
config
->
tei
);
UxCardMemOut
(
card
->
hw
,
&
shared
[
9
],
config
->
nt2
);
UxCardMemOut
(
card
->
hw
,
&
shared
[
10
],
config
->
sig_flags
);
UxCardMemOut
(
card
->
hw
,
&
shared
[
11
],
config
->
watchdog
);
UxCardMemOut
(
card
->
hw
,
&
shared
[
12
],
config
->
permanent
);
UxCardMemOut
(
card
->
hw
,
&
shared
[
13
],
config
->
x_interface
);
UxCardMemOut
(
card
->
hw
,
&
shared
[
14
],
config
->
stable_l2
);
UxCardMemOut
(
card
->
hw
,
&
shared
[
15
],
config
->
no_order_check
);
UxCardMemOut
(
card
->
hw
,
&
shared
[
16
],
config
->
handset_type
);
UxCardMemOut
(
card
->
hw
,
&
shared
[
17
],
0
);
UxCardMemOut
(
card
->
hw
,
&
shared
[
18
],
config
->
low_channel
);
UxCardMemOut
(
card
->
hw
,
&
shared
[
19
],
config
->
prot_version
);
UxCardMemOut
(
card
->
hw
,
&
shared
[
20
],
config
->
crc4
);
if
((
card
->
hw
->
features
)
&&
(
card
->
hw
->
features
&
PROTCAP_V90D
))
{
DPRINTF
((
"divas: Signifying V.90"
));
UxCardMemOut
(
card
->
hw
,
&
shared
[
22
],
4
);
}
else
{
UxCardMemOut
(
card
->
hw
,
&
shared
[
22
],
0
);
}
for
(
i
=
0
;
i
<
2
;
i
++
)
{
for
(
j
=
0
;
j
<
32
;
j
++
)
{
UxCardMemOut
(
card
->
hw
,
&
shared
[
32
+
(
i
*
96
)
+
j
],
config
->
terminal
[
i
].
oad
[
j
]);
}
for
(
j
=
0
;
j
<
32
;
j
++
)
{
UxCardMemOut
(
card
->
hw
,
&
shared
[
64
+
(
i
*
96
)
+
j
],
config
->
terminal
[
i
].
osa
[
j
]);
}
for
(
j
=
0
;
j
<
32
;
j
++
)
{
UxCardMemOut
(
card
->
hw
,
&
shared
[
96
+
(
i
*
96
)
+
j
],
config
->
terminal
[
i
].
spid
[
j
]);
}
}
UxCardMemDetach
(
card
->
hw
,
shared
);
return
0
;
}
static
void
diva_server_4bri_reset_int
(
card_t
*
card
)
{
byte
*
ctl
;
ctl
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_CTL_MEMORY
);
UxCardMemOut
(
card
->
hw
,
&
ctl
[
MQ_BREG_IRQ_TEST
],
MQ_IRQ_REQ_OFF
);
UxCardMemDetach
(
card
->
hw
,
ctl
);
return
;
}
static
int
diva_server_4bri_test_int
(
card_t
*
card
)
{
byte
*
ctl
,
i
;
byte
*
reg
;
DPRINTF
((
"divas: test interrupt for Diva Server 4BRI"
));
/* We get the last (dummy) adapter in so we need to go back to the first */
card
=
get_card
(
card
->
cfg
.
card_id
-
3
);
/* Enable interrupts on PLX chip */
reg
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_REG_MEMORY
);
UxCardPortIoOut
(
card
->
hw
,
reg
,
PLX9054_INTCSR
,
PLX9054_INT_ENA
);
UxCardMemDetach
(
card
->
hw
,
reg
);
/* Set the test interrupt flag */
card
->
test_int_pend
=
TEST_INT_DIVAS_Q
;
/* Now to trigger the interrupt */
ctl
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_CTL_MEMORY
);
UxCardMemOut
(
card
->
hw
,
&
ctl
[
MQ_BREG_IRQ_TEST
],
MQ_IRQ_REQ_ON
);
UxCardMemDetach
(
card
->
hw
,
ctl
);
for
(
i
=
0
;
i
<
50
;
i
++
)
{
if
(
!
card
->
test_int_pend
)
{
break
;
}
UxPause
(
10
);
}
if
(
card
->
test_int_pend
)
{
DPRINTF
((
"active: timeout waiting for card to interrupt"
));
return
(
-
1
);
}
return
0
;
}
static
void
print_hdr
(
unsigned
char
*
code
,
int
offset
)
{
unsigned
char
hdr
[
80
];
int
i
;
i
=
0
;
while
((
i
<
(
DIM
(
hdr
)
-
1
))
&&
(
code
[
offset
+
i
]
!=
'\0'
)
&&
(
code
[
offset
+
i
]
!=
'\r'
)
&&
(
code
[
offset
+
i
]
!=
'\n'
))
{
hdr
[
i
]
=
code
[
offset
+
i
];
i
++
;
}
hdr
[
i
]
=
'\0'
;
DPRINTF
((
"divas: loading %s"
,
hdr
));
}
static
int
diva_server_4bri_load
(
card_t
*
card
,
dia_load_t
*
load
)
{
byte
*
pRAM
=
NULL
;
int
download_offset
=
0
;
card_t
*
FirstCard
;
byte
sw_id
[
80
];
DPRINTF
((
"divas: loading Diva Server 4BRI[%d]"
,
load
->
card_id
));
switch
(
load
->
code_type
)
{
case
DIA_CPU_CODE
:
DPRINTF
((
"divas: RISC code"
));
print_hdr
(
load
->
code
,
0x80
);
card
->
hw
->
features
=
GetProtFeatureValue
((
char
*
)
&
load
->
code
[
0x80
]);
download_offset
=
0
;
// Protocol code written to offset 0
pRAM
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_RAM_MEMORY
);
break
;
case
DIA_DSP_CODE
:
DPRINTF
((
"divas: DSP code"
));
print_hdr
(
load
->
code
,
0x0
);
FirstCard
=
get_card
(
load
->
card_id
-
3
);
if
((
card
->
hw
->
features
)
&&
(
card
->
hw
->
features
&
PROTCAP_V90D
))
{
download_offset
=
MQ_V90D_DSP_CODE_BASE
;
}
else
{
download_offset
=
MQ_ORG_DSP_CODE_BASE
;
}
pRAM
=
UxCardMemAttach
(
FirstCard
->
hw
,
DIVAS_RAM_MEMORY
);
download_offset
+=
(((
sizeof
(
dword
)
+
(
sizeof
(
t_dsp_download_desc
)
*
DSP_MAX_DOWNLOAD_COUNT
))
+
3
)
&
0xFFFFFFFC
);
break
;
case
DIA_TABLE_CODE
:
DPRINTF
((
"divas: TABLE code"
));
FirstCard
=
get_card
(
load
->
card_id
-
3
);
if
((
card
->
hw
->
features
)
&&
(
card
->
hw
->
features
&
PROTCAP_V90D
))
{
download_offset
=
MQ_V90D_DSP_CODE_BASE
+
sizeof
(
dword
);
}
else
{
download_offset
=
MQ_ORG_DSP_CODE_BASE
+
sizeof
(
dword
);
}
pRAM
=
UxCardMemAttach
(
FirstCard
->
hw
,
DIVAS_RAM_MEMORY
);
break
;
case
DIA_CONT_CODE
:
DPRINTF
((
"divas: continuation code"
));
break
;
case
DIA_DLOAD_CNT
:
DPRINTF
((
"divas: COUNT code"
));
FirstCard
=
get_card
(
load
->
card_id
-
3
);
if
((
card
->
hw
->
features
)
&&
(
card
->
hw
->
features
&
PROTCAP_V90D
))
{
download_offset
=
MQ_V90D_DSP_CODE_BASE
;
}
else
{
download_offset
=
MQ_ORG_DSP_CODE_BASE
;
}
pRAM
=
UxCardMemAttach
(
FirstCard
->
hw
,
DIVAS_RAM_MEMORY
);
break
;
case
DIA_FPGA_CODE
:
DPRINTF
((
"divas: 4BRI FPGA download - %d bytes"
,
load
->
length
));
if
(
FPGA_Download
(
IDI_ADAPTER_MAESTRAQ
,
card
->
hw
->
io_base
,
sw_id
,
load
->
code
,
load
->
length
)
==
-
1
)
{
DPRINTF
((
"divas: FPGA download failed"
));
return
-
1
;
}
/* NOW reset the 4BRI */
diva_server_4bri_reset
(
card
);
return
0
;
// No need for anything further loading
default:
DPRINTF
((
"divas: unknown code type"
));
return
-
1
;
}
memcp
(
pRAM
+
(
download_offset
&
0x3FFFFF
),
load
->
code
,
load
->
length
);
{
int
mism_off
;
if
((
mism_off
=
memcm
(
pRAM
+
(
download_offset
&
0x3FFFFF
),
load
->
code
,
load
->
length
)))
{
DPRINTF
((
"divas: memory mismatch at offset %d"
,
mism_off
));
UxCardMemDetach
(
card
->
hw
,
pRAM
);
return
-
1
;
}
}
UxCardMemDetach
(
card
->
hw
,
pRAM
);
return
0
;
}
static
int
diva_server_4bri_start
(
card_t
*
card
,
byte
*
channels
)
{
byte
*
ctl
;
byte
*
shared
,
i
;
int
adapter_num
;
DPRINTF
((
"divas: start Diva Server 4BRI"
));
*
channels
=
0
;
card
->
is_live
=
FALSE
;
ctl
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_CTL_MEMORY
);
UxCardMemOutW
(
card
->
hw
,
&
ctl
[
MQ_BREG_RISC
],
MQ_RISC_COLD_RESET_MASK
);
UxPause
(
2
);
UxCardMemOutW
(
card
->
hw
,
&
ctl
[
MQ_BREG_RISC
],
MQ_RISC_WARM_RESET_MASK
|
MQ_RISC_COLD_RESET_MASK
);
UxPause
(
10
);
UxCardMemDetach
(
card
->
hw
,
ctl
);
shared
=
(
byte
*
)
UxCardMemAttach
(
card
->
hw
,
DIVAS_SHARED_MEMORY
);
for
(
i
=
0
;
i
<
300
;
++
i
)
{
UxPause
(
10
)
;
if
(
UxCardMemInW
(
card
->
hw
,
&
shared
[
0x1E
])
==
0x4447
)
{
DPRINTF
((
"divas: Protocol startup time %d.%02d seconds"
,
(
i
/
100
),
(
i
%
100
)
));
break
;
}
}
if
(
i
==
300
)
{
DPRINTF
((
"divas: Timeout starting card"
));
DPRINTF
((
"divas: Signature == 0x%04X"
,
UxCardMemInW
(
card
->
hw
,
&
shared
[
0x1E
])));
UxCardMemDetach
(
card
->
hw
,
shared
);
return
-
1
;
}
UxCardMemDetach
(
card
->
hw
,
shared
);
for
(
adapter_num
=
3
;
adapter_num
>=
0
;
adapter_num
--
)
{
card_t
*
qbri_card
;
qbri_card
=
get_card
(
card
->
cfg
.
card_id
-
adapter_num
);
if
(
qbri_card
)
{
qbri_card
->
is_live
=
TRUE
;
shared
=
UxCardMemAttach
(
qbri_card
->
hw
,
DIVAS_SHARED_MEMORY
);
*
channels
+=
UxCardMemIn
(
qbri_card
->
hw
,
&
shared
[
0x3F6
]);
UxCardMemDetach
(
qbri_card
->
hw
,
shared
);
}
else
{
DPRINTF
((
"divas: Couldn't get card info %d"
,
card
->
cfg
.
card_id
));
}
}
diva_server_4bri_test_int
(
card
);
return
0
;
}
static
int
diva_server_4bri_mem_get
(
card_t
*
card
,
mem_block_t
*
mem_block
)
{
byte
*
a
;
byte
*
card_addr
;
word
length
=
0
;
int
i
;
a
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_RAM_MEMORY
);
card_addr
=
a
;
card_addr
+=
mem_block
->
addr
;
for
(
i
=
0
;
i
<
sizeof
(
mem_block
->
data
);
i
++
)
{
mem_block
->
data
[
i
]
=
UxCardMemIn
(
card
->
hw
,
card_addr
);
card_addr
++
;
length
++
;
}
UxCardMemDetach
(
card
->
hw
,
a
);
return
length
;
}
/*
* Initialise 4BRI specific entry points
*/
int
Divas4BriInit
(
card_t
*
card
,
dia_card_t
*
cfg
)
{
// byte sw_id[80];
// extern int FPGA_Done;
DPRINTF
((
"divas: initialise Diva Server 4BRI"
));
if
(
Divas4BRIInitPCI
(
card
,
cfg
)
==
-
1
)
{
return
-
1
;
}
/* Need to download the FPGA */
/* if (!FPGA_Done)
{
int retVal;
retVal=FPGA_Download(IDI_ADAPTER_MAESTRAQ,
cfg->io_base,
sw_id,
FPGA_Bytes
);
if(retVal==-1)
{
DPRINTF(("divas: FPGA Download Failed"));
return -1;
}
FPGA_Done = 1;
} */
card
->
card_reset
=
diva_server_4bri_reset
;
card
->
card_load
=
diva_server_4bri_load
;
card
->
card_config
=
diva_server_4bri_config
;
card
->
card_start
=
diva_server_4bri_start
;
card
->
reset_int
=
diva_server_4bri_reset_int
;
card
->
card_mem_get
=
diva_server_4bri_mem_get
;
card
->
xlog_offset
=
DIVAS_MAINT_OFFSET
;
card
->
out
=
DivasOut
;
card
->
test_int
=
DivasTestInt
;
card
->
dpc
=
DivasDpc
;
card
->
clear_int
=
DivasClearInt
;
card
->
card_isr
=
fourbri_ISR
;
card
->
a
.
ram_out
=
mem_out
;
card
->
a
.
ram_outw
=
mem_outw
;
card
->
a
.
ram_out_buffer
=
mem_out_buffer
;
card
->
a
.
ram_inc
=
mem_inc
;
card
->
a
.
ram_in
=
mem_in
;
card
->
a
.
ram_inw
=
mem_inw
;
card
->
a
.
ram_in_buffer
=
mem_in_buffer
;
card
->
a
.
ram_look_ahead
=
mem_look_ahead
;
return
0
;
}
void
memcp
(
byte
*
dst
,
byte
*
src
,
dword
dwLen
)
{
while
(
dwLen
)
{
*
dst
=
*
src
;
dst
++
;
src
++
;
dwLen
--
;
}
}
int
memcm
(
byte
*
dst
,
byte
*
src
,
dword
dwLen
)
{
int
offset
=
0
;
while
(
offset
<
dwLen
)
{
if
(
*
dst
!=
*
src
)
return
(
offset
+
1
);
offset
++
;
src
++
;
dst
++
;
}
return
0
;
}
/*int fourbri_ISR (card_t* card)
{
int served = 0;
byte *DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
if (UxCardPortIoIn (card->hw, DivasIOBase, M_PCI_RESET) & 0x01)
{
served = 1;
card->int_pend += 1;
DivasDpcSchedule();
UxCardPortIoOut (card->hw, DivasIOBase, M_PCI_RESET, 0x08);
}
UxCardMemDetach(card->hw, DivasIOBase);
return (served != 0);
}*/
static
int
fourbri_ISR
(
card_t
*
card
)
{
byte
*
ctl
;
card
->
int_pend
+=
1
;
DivasDpcSchedule
();
/* ISR DPC */
ctl
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_CTL_MEMORY
);
UxCardMemOut
(
card
->
hw
,
&
ctl
[
MQ_BREG_IRQ_TEST
],
MQ_IRQ_REQ_OFF
);
UxCardMemDetach
(
card
->
hw
,
ctl
);
return
(
1
);
}
drivers/isdn/eicon/fpga.c
deleted
100644 → 0
View file @
f69c2d56
/*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.2
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include "sys.h"
#include "idi.h"
#include "uxio.h"
#define FPGA_PORT 0x6E
#define FPGA_DLOAD_BUFLEN 256
#define NAME_OFFSET 0x10
#define NAME_MAXLEN 12
#define DATE_OFFSET 0x2c
#define DATE_MAXLEN 10
word
UxCardPortIoInW
(
ux_diva_card_t
*
card
,
byte
*
base
,
int
offset
);
void
UxCardPortIoOutW
(
ux_diva_card_t
*
card
,
byte
*
base
,
int
offset
,
word
);
void
UxPause
(
long
int
);
/*-------------------------------------------------------------------------*/
/* Loads the FPGA configuration file onto the hardware. */
/* Function returns 0 on success, else an error number. */
/* On success, an identifier string is returned in the buffer */
/* */
/* A buffer of FPGA_BUFSIZE, a handle to the already opened bitstream */
/* file and a file read function has to be provided by the operating */
/* system part. */
/* ----------------------------------------------------------------------- */
int
FPGA_Download
(
word
cardtype
,
dword
RegBase
,
byte
*
strbuf
,
byte
FPGA_SRC
[],
int
FPGA_LEN
)
{
word
i
,
j
,
k
;
word
baseval
,
Mask_PROGRAM
,
Mask_DONE
,
Mask_CCLK
,
Mask_DIN
;
dword
addr
;
byte
*
pFPGA
;
//--- check for legal cardtype
switch
(
cardtype
)
{
case
IDI_ADAPTER_MAESTRAQ
:
addr
=
RegBase
;
// address where to access FPGA
Mask_PROGRAM
=
0x0001
;
// FPGA pins at address
Mask_DONE
=
0x0002
;
Mask_CCLK
=
0x0100
;
Mask_DIN
=
0x0400
;
baseval
=
0x000d
;
// PROGRAM hi, CCLK lo, DIN lo by default
break
;
default:
DPRINTF
((
"divas: FPGA Download ,Illegal Card"
));
return
-
1
;
// illegal card
}
//--- generate id string from file content
for
(
j
=
NAME_OFFSET
,
k
=
0
;
j
<
(
NAME_OFFSET
+
NAME_MAXLEN
);
j
++
,
k
++
)
//name
{
if
(
!
FPGA_SRC
[
j
])
break
;
strbuf
[
k
]
=
FPGA_SRC
[
j
];
}
strbuf
[
k
++
]
=
' '
;
for
(
j
=
DATE_OFFSET
;
j
<
(
DATE_OFFSET
+
DATE_MAXLEN
);
j
++
,
k
++
)
// date
{
if
(
!
FPGA_SRC
[
j
])
break
;
strbuf
[
k
]
=
FPGA_SRC
[
j
];
}
strbuf
[
k
]
=
0
;
DPRINTF
((
"divas: FPGA Download - %s"
,
strbuf
));
//--- prepare download, Pulse PROGRAM pin down.
UxCardPortIoOutW
(
NULL
,
(
byte
*
)
addr
,
FPGA_PORT
,
baseval
&~
Mask_PROGRAM
);
// PROGRAM low pulse
UxCardPortIoOutW
(
NULL
,
(
byte
*
)
addr
,
FPGA_PORT
,
baseval
);
// release
UxPause
(
50
);
// wait until FPGA finised internal memory clear
//--- check done pin, must be low
if
(
UxCardPortIoInW
(
NULL
,
(
byte
*
)
addr
,
FPGA_PORT
)
&
Mask_DONE
)
{
DPRINTF
((
"divas: FPGA_ERR_DONE_WRONG_LEVEL"
));
return
-
1
;
}
pFPGA
=
FPGA_SRC
;
i
=
0
;
/* Move past the header */
while
((
FPGA_SRC
[
i
]
!=
0xFF
)
&&
(
i
<
FPGA_LEN
))
{
i
++
;
}
// We've hit the 0xFF so move on to the next byte
// i++;
DPRINTF
((
"divas: FPGA Code starts at offset %d"
,
i
));
//--- put data onto the FPGA
for
(;
i
<
FPGA_LEN
;
i
++
)
{
//--- put byte onto FPGA
for
(
j
=
0
;
j
<
8
;
j
++
)
{
if
(
FPGA_SRC
[
i
]
&
(
0x80
>>
j
))
baseval
|=
Mask_DIN
;
// write a hi
else
baseval
&=~
Mask_DIN
;
// write a lo
UxCardPortIoOutW
(
NULL
,
(
byte
*
)
addr
,
FPGA_PORT
,
baseval
);
UxCardPortIoOutW
(
NULL
,
(
byte
*
)
addr
,
FPGA_PORT
,
baseval
|
Mask_CCLK
);
// set CCLK hi
UxCardPortIoOutW
(
NULL
,
(
byte
*
)
addr
,
FPGA_PORT
,
baseval
);
// set CCLK lo
}
}
//--- add some additional startup clock cycles and check done pin
for
(
i
=
0
;
i
<
5
;
i
++
)
{
UxCardPortIoOutW
(
NULL
,
(
byte
*
)
addr
,
FPGA_PORT
,
baseval
|
Mask_CCLK
);
// set CCLK hi
UxCardPortIoOutW
(
NULL
,
(
byte
*
)
addr
,
FPGA_PORT
,
baseval
);
// set CCLK lo
}
UxPause
(
100
);
if
(
UxCardPortIoInW
(
NULL
,
(
byte
*
)
addr
,
FPGA_PORT
)
&
Mask_DONE
)
{
DPRINTF
((
"divas: FPGA download successful"
));
}
else
{
DPRINTF
((
"divas: FPGA download failed - 0x%x"
,
UxCardPortIoInW
(
NULL
,
(
byte
*
)
addr
,
FPGA_PORT
)));
return
-
1
;
}
return
0
;
}
drivers/isdn/eicon/idi.c
deleted
100644 → 0
View file @
f69c2d56
/*
* Core driver for Diva Server cards
* Implements the IDI interface
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.8
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include "idi.h"
#include "adapter.h"
#include "pc.h"
#include "pr_pc.h"
#include "sys.h"
#include "uxio.h"
/* IDI request functions */
static
void
request
(
card_t
*
card
,
ENTITY
*
e
);
static
void
req_0
(
ENTITY
*
e
)
{
request
(
&
DivasCards
[
0
],
e
);
}
static
void
req_1
(
ENTITY
*
e
)
{
request
(
&
DivasCards
[
1
],
e
);
}
static
void
req_2
(
ENTITY
*
e
)
{
request
(
&
DivasCards
[
2
],
e
);
}
static
void
req_3
(
ENTITY
*
e
)
{
request
(
&
DivasCards
[
3
],
e
);
}
static
void
req_4
(
ENTITY
*
e
)
{
request
(
&
DivasCards
[
4
],
e
);
}
static
void
req_5
(
ENTITY
*
e
)
{
request
(
&
DivasCards
[
5
],
e
);
}
static
void
req_6
(
ENTITY
*
e
)
{
request
(
&
DivasCards
[
6
],
e
);
}
static
void
req_7
(
ENTITY
*
e
)
{
request
(
&
DivasCards
[
7
],
e
);
}
static
void
req_8
(
ENTITY
*
e
)
{
request
(
&
DivasCards
[
8
],
e
);
}
static
void
req_9
(
ENTITY
*
e
)
{
request
(
&
DivasCards
[
9
],
e
);
}
static
void
req_10
(
ENTITY
*
e
)
{
request
(
&
DivasCards
[
10
],
e
);
}
static
void
req_11
(
ENTITY
*
e
)
{
request
(
&
DivasCards
[
11
],
e
);
}
static
void
req_12
(
ENTITY
*
e
)
{
request
(
&
DivasCards
[
12
],
e
);
}
static
void
req_13
(
ENTITY
*
e
)
{
request
(
&
DivasCards
[
13
],
e
);
}
static
void
req_14
(
ENTITY
*
e
)
{
request
(
&
DivasCards
[
14
],
e
);
}
static
void
req_15
(
ENTITY
*
e
)
{
request
(
&
DivasCards
[
15
],
e
);
}
IDI_CALL
DivasIdiRequest
[
16
]
=
{
&
req_0
,
&
req_1
,
&
req_2
,
&
req_3
,
&
req_4
,
&
req_5
,
&
req_6
,
&
req_7
,
&
req_8
,
&
req_9
,
&
req_10
,
&
req_11
,
&
req_12
,
&
req_13
,
&
req_14
,
&
req_15
};
#define PR_RAM ((struct pr_ram *)0)
#define RAM ((struct dual *)0)
/*------------------------------------------------------------------*/
/* local function prototypes */
/*------------------------------------------------------------------*/
static
byte
isdn_rc
(
ADAPTER
*
,
byte
,
byte
,
byte
,
word
);
static
byte
isdn_ind
(
ADAPTER
*
,
byte
,
byte
,
byte
,
PBUFFER
*
,
byte
,
word
);
/*
* IDI related functions
*/
static
ENTITY
*
entity_ptr
(
ADAPTER
*
a
,
byte
e_no
)
{
card_t
*
card
;
card
=
a
->
io
;
return
card
->
e_tbl
[
e_no
].
e
;
}
static
void
CALLBACK
(
ADAPTER
*
a
,
ENTITY
*
e
)
{
card_t
*
card
=
a
->
io
;
if
(
card
->
log_types
&
DIVAS_LOG_IDI
)
{
DivasLogIdi
(
card
,
e
,
FALSE
);
}
(
*
e
->
callback
)(
e
);
}
static
void
*
PTR_P
(
ADAPTER
*
a
,
ENTITY
*
e
,
void
*
P
)
{
return
(
P
);
}
static
void
*
PTR_R
(
ADAPTER
*
a
,
ENTITY
*
e
)
{
return
((
void
*
)
e
->
R
);
}
static
void
*
PTR_X
(
ADAPTER
*
a
,
ENTITY
*
e
)
{
return
((
void
*
)
e
->
X
);
}
static
void
free_entity
(
ADAPTER
*
a
,
byte
e_no
)
{
card_t
*
card
;
int
ipl
;
card
=
a
->
io
;
ipl
=
UxCardLock
(
card
->
hw
);
card
->
e_tbl
[
e_no
].
e
=
NULL
;
card
->
e_count
--
;
UxCardUnlock
(
card
->
hw
,
ipl
);
return
;
}
static
void
assign_queue
(
ADAPTER
*
a
,
byte
e_no
,
word
ref
)
{
card_t
*
card
;
int
ipl
;
card
=
a
->
io
;
ipl
=
UxCardLock
(
card
->
hw
);
card
->
e_tbl
[
e_no
].
assign_ref
=
ref
;
card
->
e_tbl
[
e_no
].
next
=
card
->
assign
;
card
->
assign
=
e_no
;
UxCardUnlock
(
card
->
hw
,
ipl
);
return
;
}
static
byte
get_assign
(
ADAPTER
*
a
,
word
ref
)
{
card_t
*
card
;
byte
e_no
;
int
ipl
;
card
=
a
->
io
;
ipl
=
UxCardLock
(
card
->
hw
);
e_no
=
(
byte
)
card
->
assign
;
while
(
e_no
)
{
if
(
card
->
e_tbl
[
e_no
].
assign_ref
==
ref
)
{
break
;
}
e_no
=
card
->
e_tbl
[
e_no
].
next
;
}
UxCardUnlock
(
card
->
hw
,
ipl
);
return
e_no
;
}
static
void
req_queue
(
ADAPTER
*
a
,
byte
e_no
)
{
card_t
*
card
;
int
ipl
;
card
=
a
->
io
;
ipl
=
UxCardLock
(
card
->
hw
);
card
->
e_tbl
[
e_no
].
next
=
0
;
if
(
card
->
e_head
)
{
card
->
e_tbl
[
card
->
e_tail
].
next
=
e_no
;
card
->
e_tail
=
e_no
;
}
else
{
card
->
e_head
=
e_no
;
card
->
e_tail
=
e_no
;
}
UxCardUnlock
(
card
->
hw
,
ipl
);
return
;
}
static
byte
look_req
(
ADAPTER
*
a
)
{
card_t
*
card
;
card
=
a
->
io
;
return
(
card
->
e_head
);
}
static
void
next_req
(
ADAPTER
*
a
)
{
card_t
*
card
;
int
ipl
;
card
=
a
->
io
;
ipl
=
UxCardLock
(
card
->
hw
);
card
->
e_head
=
card
->
e_tbl
[
card
->
e_head
].
next
;
if
(
!
card
->
e_head
)
{
card
->
e_tail
=
0
;
}
UxCardUnlock
(
card
->
hw
,
ipl
);
return
;
}
/*
* IDI request function for active cards
*/
static
void
request
(
card_t
*
card
,
ENTITY
*
e
)
{
word
*
special_req
;
int
i
;
int
ipl
;
if
(
card
->
log_types
&
DIVAS_LOG_IDI
)
{
DivasLogIdi
(
card
,
e
,
TRUE
);
}
if
(
!
e
->
Req
)
{
special_req
=
(
word
*
)
e
;
switch
(
*
special_req
)
{
case
REQ_REMOVE
:
return
;
case
REQ_NAME
:
for
(
i
=
0
;
i
<
DIM
(
card
->
cfg
.
name
);
i
++
)
{
((
struct
get_name_s
*
)
e
)
->
name
[
i
]
=
card
->
cfg
.
name
[
i
];
}
return
;
case
REQ_SERIAL
:
case
REQ_XLOG
:
DPRINTF
((
"IDI: attempted REQ_SERIAL or REQ_XLOG"
));
return
;
default:
return
;
}
}
ipl
=
UxCardLock
(
card
->
hw
);
if
(
!
(
e
->
Id
&
0x1f
))
{
DPRINTF
((
"IDI: ASSIGN req"
));
for
(
i
=
1
;
i
<
card
->
e_max
;
i
++
)
{
if
(
!
card
->
e_tbl
[
i
].
e
)
{
break
;
}
}
if
(
i
==
card
->
e_max
)
{
DPRINTF
((
"IDI: request all ids in use (IDI req ignored)"
));
UxCardUnlock
(
card
->
hw
,
ipl
);
e
->
Rc
=
OUT_OF_RESOURCES
;
return
;
}
card
->
e_tbl
[
i
].
e
=
e
;
card
->
e_count
++
;
e
->
No
=
(
byte
)
i
;
e
->
More
=
0
;
e
->
RCurrent
=
0xff
;
}
else
{
i
=
e
->
No
;
}
if
(
e
->
More
&
XBUSY
)
{
DPRINTF
((
"IDI: request - entity is busy"
));
UxCardUnlock
(
card
->
hw
,
ipl
);
return
;
}
e
->
More
|=
XBUSY
;
e
->
More
&=
~
XMOREF
;
e
->
XCurrent
=
0
;
e
->
XOffset
=
0
;
card
->
e_tbl
[
i
].
next
=
0
;
if
(
card
->
e_head
)
{
card
->
e_tbl
[
card
->
e_tail
].
next
=
i
;
card
->
e_tail
=
i
;
}
else
{
card
->
e_head
=
i
;
card
->
e_tail
=
i
;
}
UxCardUnlock
(
card
->
hw
,
ipl
);
DivasScheduleRequestDpc
();
return
;
}
static
byte
pr_ready
(
ADAPTER
*
a
)
{
byte
ReadyCount
;
ReadyCount
=
(
byte
)(
a
->
ram_in
(
a
,
&
PR_RAM
->
ReqOutput
)
-
a
->
ram_in
(
a
,
&
PR_RAM
->
ReqInput
));
if
(
!
ReadyCount
)
{
if
(
!
a
->
ReadyInt
)
{
a
->
ram_inc
(
a
,
&
PR_RAM
->
ReadyInt
);
a
->
ReadyInt
++
;
}
}
return
ReadyCount
;
}
/*------------------------------------------------------------------*/
/* output function */
/*------------------------------------------------------------------*/
void
DivasOut
(
ADAPTER
*
a
)
{
byte
e_no
;
ENTITY
*
this
=
NULL
;
BUFFERS
*
X
;
word
length
;
word
i
;
word
clength
;
REQ
*
ReqOut
;
byte
more
;
byte
ReadyCount
;
byte
ReqCount
;
byte
Id
;
/* while a request is pending ... */
e_no
=
look_req
(
a
);
if
(
!
e_no
)
{
return
;
}
ReadyCount
=
pr_ready
(
a
);
if
(
!
ReadyCount
)
{
DPRINTF
((
"IDI: card not ready for next request"
));
return
;
}
ReqCount
=
0
;
while
(
e_no
&&
ReadyCount
)
{
next_req
(
a
);
this
=
entity_ptr
(
a
,
e_no
);
#ifdef USE_EXTENDED_DEBUGS
if
(
!
this
)
{
ISDN_ADAPTER
*
io
=
(
ISDN_ADAPTER
*
)
a
->
io
;
DBG_FTL
((
"!A%d ==> NULL entity ptr - try to ignore"
,
(
int
)
io
->
ANum
))
e_no
=
look_req
(
a
)
;
ReadyCount
--
;
continue
;
}
{
ISDN_ADAPTER
*
io
=
(
ISDN_ADAPTER
*
)
a
->
io
;
DPRINTF
((
"IDI: >A%d Id=0x%x Req=0x%x"
,
io
->
ANum
,
this
->
Id
,
this
->
Req
))
}
#else
DPRINTF
((
"IDI: >REQ=%x,Id=%x,Ch=%x"
,
this
->
Req
,
this
->
Id
,
this
->
ReqCh
));
#endif
/* get address of next available request buffer */
ReqOut
=
(
REQ
*
)
&
PR_RAM
->
B
[
a
->
ram_inw
(
a
,
&
PR_RAM
->
NextReq
)];
/* now copy the data from the current data buffer into the */
/* adapters request buffer */
length
=
0
;
i
=
this
->
XCurrent
;
X
=
PTR_X
(
a
,
this
);
while
(
i
<
this
->
XNum
&&
length
<
270
)
{
clength
=
(
word
)(
270
-
length
);
if
(
clength
>
X
[
i
].
PLength
-
this
->
XOffset
)
clength
=
X
[
i
].
PLength
-
this
->
XOffset
;
a
->
ram_out_buffer
(
a
,
&
ReqOut
->
XBuffer
.
P
[
length
],
PTR_P
(
a
,
this
,
&
X
[
i
].
P
[
this
->
XOffset
]),
clength
);
length
+=
clength
;
this
->
XOffset
+=
clength
;
if
(
this
->
XOffset
==
X
[
i
].
PLength
)
{
this
->
XCurrent
=
(
byte
)
++
i
;
this
->
XOffset
=
0
;
}
}
a
->
ram_outw
(
a
,
&
ReqOut
->
XBuffer
.
length
,
length
);
a
->
ram_out
(
a
,
&
ReqOut
->
ReqId
,
this
->
Id
);
a
->
ram_out
(
a
,
&
ReqOut
->
ReqCh
,
this
->
ReqCh
);
/* if it's a specific request (no ASSIGN) ... */
if
(
this
->
Id
&
0x1f
)
{
/* if buffers are left in the list of data buffers do */
/* do chaining (LL_MDATA, N_MDATA) */
this
->
More
++
;
if
(
i
<
this
->
XNum
&&
this
->
MInd
)
{
a
->
ram_out
(
a
,
&
ReqOut
->
Req
,
this
->
MInd
);
more
=
TRUE
;
}
else
{
this
->
More
|=
XMOREF
;
a
->
ram_out
(
a
,
&
ReqOut
->
Req
,
this
->
Req
);
more
=
FALSE
;
}
/* if we did chaining, this entity is put back into the */
/* request queue */
if
(
more
)
{
req_queue
(
a
,
this
->
No
);
}
}
/* else it's a ASSIGN */
else
{
/* save the request code used for buffer chaining */
this
->
MInd
=
0
;
if
(
this
->
Id
==
BLLC_ID
)
this
->
MInd
=
LL_MDATA
;
if
(
this
->
Id
==
NL_ID
||
this
->
Id
==
TASK_ID
||
this
->
Id
==
MAN_ID
)
this
->
MInd
=
N_MDATA
;
/* send the ASSIGN */
this
->
More
|=
XMOREF
;
a
->
ram_out
(
a
,
&
ReqOut
->
Req
,
this
->
Req
);
/* save the reference of the ASSIGN */
assign_queue
(
a
,
this
->
No
,
a
->
ram_inw
(
a
,
&
ReqOut
->
Reference
));
}
a
->
ram_outw
(
a
,
&
PR_RAM
->
NextReq
,
a
->
ram_inw
(
a
,
&
ReqOut
->
next
));
ReadyCount
--
;
ReqCount
++
;
e_no
=
look_req
(
a
);
}
/* send the filled request buffers to the ISDN adapter */
a
->
ram_out
(
a
,
&
PR_RAM
->
ReqInput
,
(
byte
)(
a
->
ram_in
(
a
,
&
PR_RAM
->
ReqInput
)
+
ReqCount
));
/* if it is a 'unreturncoded' UREMOVE request, remove the */
/* Id from our table after sending the request */
if
(
this
->
Req
==
UREMOVE
&&
this
->
Id
)
{
Id
=
this
->
Id
;
e_no
=
a
->
IdTable
[
Id
];
free_entity
(
a
,
e_no
);
a
->
IdTable
[
Id
]
=
0
;
this
->
Id
=
0
;
}
}
/*------------------------------------------------------------------*/
/* isdn interrupt handler */
/*------------------------------------------------------------------*/
byte
DivasDpc
(
ADAPTER
*
a
)
{
byte
Count
;
RC
*
RcIn
;
IND
*
IndIn
;
byte
c
;
byte
RNRId
;
byte
Rc
;
byte
Ind
;
/* if return codes are available ... */
if
((
Count
=
a
->
ram_in
(
a
,
&
PR_RAM
->
RcOutput
)))
{
DPRINTF
((
"IDI: #Rc=%x"
,
Count
));
/* get the buffer address of the first return code */
RcIn
=
(
RC
*
)
&
PR_RAM
->
B
[
a
->
ram_inw
(
a
,
&
PR_RAM
->
NextRc
)];
/* for all return codes do ... */
while
(
Count
--
)
{
if
((
Rc
=
a
->
ram_in
(
a
,
&
RcIn
->
Rc
)))
{
/* call return code handler, if it is not our return code */
/* the handler returns 2 */
/* for all return codes we process, we clear the Rc field */
isdn_rc
(
a
,
Rc
,
a
->
ram_in
(
a
,
&
RcIn
->
RcId
),
a
->
ram_in
(
a
,
&
RcIn
->
RcCh
),
a
->
ram_inw
(
a
,
&
RcIn
->
Reference
));
a
->
ram_out
(
a
,
&
RcIn
->
Rc
,
0
);
}
/* get buffer address of next return code */
RcIn
=
(
RC
*
)
&
PR_RAM
->
B
[
a
->
ram_inw
(
a
,
&
RcIn
->
next
)];
}
/* clear all return codes (no chaining!) */
a
->
ram_out
(
a
,
&
PR_RAM
->
RcOutput
,
0
);
/* call output function */
DivasOut
(
a
);
}
/* clear RNR flag */
RNRId
=
0
;
/* if indications are available ... */
if
((
Count
=
a
->
ram_in
(
a
,
&
PR_RAM
->
IndOutput
)))
{
DPRINTF
((
"IDI: #Ind=%x"
,
Count
));
/* get the buffer address of the first indication */
IndIn
=
(
IND
*
)
&
PR_RAM
->
B
[
a
->
ram_inw
(
a
,
&
PR_RAM
->
NextInd
)];
/* for all indications do ... */
while
(
Count
--
)
{
/* if the application marks an indication as RNR, all */
/* indications from the same Id delivered in this interrupt */
/* are marked RNR */
if
(
RNRId
&&
RNRId
==
a
->
ram_in
(
a
,
&
IndIn
->
IndId
))
{
a
->
ram_out
(
a
,
&
IndIn
->
Ind
,
0
);
a
->
ram_out
(
a
,
&
IndIn
->
RNR
,
TRUE
);
}
else
{
Ind
=
a
->
ram_in
(
a
,
&
IndIn
->
Ind
);
if
(
Ind
)
{
RNRId
=
0
;
/* call indication handler, a return value of 2 means chain */
/* a return value of 1 means RNR */
/* for all indications we process, we clear the Ind field */
c
=
isdn_ind
(
a
,
Ind
,
a
->
ram_in
(
a
,
&
IndIn
->
IndId
),
a
->
ram_in
(
a
,
&
IndIn
->
IndCh
),
&
IndIn
->
RBuffer
,
a
->
ram_in
(
a
,
&
IndIn
->
MInd
),
a
->
ram_inw
(
a
,
&
IndIn
->
MLength
));
if
(
c
==
1
)
{
DPRINTF
((
"IDI: RNR"
));
a
->
ram_out
(
a
,
&
IndIn
->
Ind
,
0
);
RNRId
=
a
->
ram_in
(
a
,
&
IndIn
->
IndId
);
a
->
ram_out
(
a
,
&
IndIn
->
RNR
,
TRUE
);
}
}
}
/* get buffer address of next indication */
IndIn
=
(
IND
*
)
&
PR_RAM
->
B
[
a
->
ram_inw
(
a
,
&
IndIn
->
next
)];
}
a
->
ram_out
(
a
,
&
PR_RAM
->
IndOutput
,
0
);
}
return
FALSE
;
}
byte
DivasTestInt
(
ADAPTER
*
a
)
{
return
a
->
ram_in
(
a
,(
void
*
)
0x3fe
);
}
void
DivasClearInt
(
ADAPTER
*
a
)
{
a
->
ram_out
(
a
,(
void
*
)
0x3fe
,
0
);
}
/*------------------------------------------------------------------*/
/* return code handler */
/*------------------------------------------------------------------*/
static
byte
isdn_rc
(
ADAPTER
*
a
,
byte
Rc
,
byte
Id
,
byte
Ch
,
word
Ref
)
{
ENTITY
*
this
;
byte
e_no
;
#ifdef USE_EXTENDED_DEBUGS
{
ISDN_ADAPTER
*
io
=
(
ISDN_ADAPTER
*
)
a
->
io
;
DPRINTF
((
"IDI: <A%d Id=0x%x Rc=0x%x"
,
io
->
ANum
,
Id
,
Rc
))
}
#else
DPRINTF
((
"IDI: <RC(Rc=%x,Id=%x,Ch=%x)"
,
Rc
,
Id
,
Ch
));
#endif
/* check for ready interrupt */
if
(
Rc
==
READY_INT
)
{
if
(
a
->
ReadyInt
)
{
a
->
ReadyInt
--
;
return
0
;
}
return
2
;
}
/* if we know this Id ... */
e_no
=
a
->
IdTable
[
Id
];
if
(
e_no
)
{
this
=
entity_ptr
(
a
,
e_no
);
this
->
RcCh
=
Ch
;
/* if it is a return code to a REMOVE request, remove the */
/* Id from our table */
if
(
this
->
Req
==
REMOVE
&&
Rc
==
OK
)
{
free_entity
(
a
,
e_no
);
a
->
IdTable
[
Id
]
=
0
;
this
->
Id
=
0
;
/**************************************************************/
if
((
this
->
More
&
XMOREC
)
>
1
)
{
this
->
More
&=
~
XMOREC
;
this
->
More
|=
1
;
DPRINTF
((
"isdn_rc, Id=%x, correct More on REMOVE"
,
Id
));
}
}
if
(
Rc
==
OK_FC
)
{
this
->
Rc
=
Rc
;
this
->
More
=
(
this
->
More
&
(
~
XBUSY
|
XMOREC
))
|
1
;
this
->
complete
=
0xFF
;
CALLBACK
(
a
,
this
);
return
0
;
}
if
(
this
->
More
&
XMOREC
)
this
->
More
--
;
/* call the application callback function */
if
(
this
->
More
&
XMOREF
&&
!
(
this
->
More
&
XMOREC
))
{
this
->
Rc
=
Rc
;
this
->
More
&=~
XBUSY
;
this
->
complete
=
0xff
;
CALLBACK
(
a
,
this
);
}
return
0
;
}
/* if it's an ASSIGN return code check if it's a return */
/* code to an ASSIGN request from us */
if
((
Rc
&
0xf0
)
==
ASSIGN_RC
)
{
e_no
=
get_assign
(
a
,
Ref
);
if
(
e_no
)
{
this
=
entity_ptr
(
a
,
e_no
);
this
->
Id
=
Id
;
/* call the application callback function */
this
->
Rc
=
Rc
;
this
->
More
&=~
XBUSY
;
this
->
complete
=
0xff
;
CALLBACK
(
a
,
this
);
if
(
Rc
==
ASSIGN_OK
)
{
a
->
IdTable
[
Id
]
=
e_no
;
}
else
{
free_entity
(
a
,
e_no
);
a
->
IdTable
[
Id
]
=
0
;
this
->
Id
=
0
;
}
return
1
;
}
}
return
2
;
}
/*------------------------------------------------------------------*/
/* indication handler */
/*------------------------------------------------------------------*/
static
byte
isdn_ind
(
ADAPTER
*
a
,
byte
Ind
,
byte
Id
,
byte
Ch
,
PBUFFER
*
RBuffer
,
byte
MInd
,
word
MLength
)
{
ENTITY
*
this
;
word
clength
;
word
offset
;
BUFFERS
*
R
;
#ifdef USE_EXTENDED_DEBUGS
{
ISDN_ADAPTER
*
io
=
(
ISDN_ADAPTER
*
)
a
->
io
;
DPRINTF
((
"IDI: <A%d Id=0x%x Ind=0x%x"
,
io
->
ANum
,
Id
,
Ind
))
}
#else
DPRINTF
((
"IDI: <IND(Ind=%x,Id=%x,Ch=%x)"
,
Ind
,
Id
,
Ch
));
#endif
if
(
a
->
IdTable
[
Id
])
{
this
=
entity_ptr
(
a
,
a
->
IdTable
[
Id
]);
this
->
IndCh
=
Ch
;
/* if the Receive More flag is not yet set, this is the */
/* first buffer of the packet */
if
(
this
->
RCurrent
==
0xff
)
{
/* check for receive buffer chaining */
if
(
Ind
==
this
->
MInd
)
{
this
->
complete
=
0
;
this
->
Ind
=
MInd
;
}
else
{
this
->
complete
=
1
;
this
->
Ind
=
Ind
;
}
/* call the application callback function for the receive */
/* look ahead */
this
->
RLength
=
MLength
;
a
->
ram_look_ahead
(
a
,
RBuffer
,
this
);
this
->
RNum
=
0
;
CALLBACK
(
a
,
this
);
/* map entity ptr, selector could be re-mapped by call to */
/* IDI from within callback */
this
=
entity_ptr
(
a
,
a
->
IdTable
[
Id
]);
/* check for RNR */
if
(
this
->
RNR
==
1
)
{
this
->
RNR
=
0
;
return
1
;
}
/* if no buffers are provided by the application, the */
/* application want to copy the data itself including */
/* N_MDATA/LL_MDATA chaining */
if
(
!
this
->
RNR
&&
!
this
->
RNum
)
{
return
0
;
}
/* if there is no RNR, set the More flag */
this
->
RCurrent
=
0
;
this
->
ROffset
=
0
;
}
if
(
this
->
RNR
==
2
)
{
if
(
Ind
!=
this
->
MInd
)
{
this
->
RCurrent
=
0xff
;
this
->
RNR
=
0
;
}
return
0
;
}
/* if we have received buffers from the application, copy */
/* the data into these buffers */
offset
=
0
;
R
=
PTR_R
(
a
,
this
);
do
{
if
(
this
->
ROffset
==
R
[
this
->
RCurrent
].
PLength
)
{
this
->
ROffset
=
0
;
this
->
RCurrent
++
;
}
clength
=
a
->
ram_inw
(
a
,
&
RBuffer
->
length
)
-
offset
;
if
(
clength
>
R
[
this
->
RCurrent
].
PLength
-
this
->
ROffset
)
clength
=
R
[
this
->
RCurrent
].
PLength
-
this
->
ROffset
;
if
(
R
[
this
->
RCurrent
].
P
)
{
a
->
ram_in_buffer
(
a
,
&
RBuffer
->
P
[
offset
],
PTR_P
(
a
,
this
,
&
R
[
this
->
RCurrent
].
P
[
this
->
ROffset
]),
clength
);
}
offset
+=
clength
;
this
->
ROffset
+=
clength
;
}
while
(
offset
<
(
a
->
ram_inw
(
a
,
&
RBuffer
->
length
)));
/* if it's the last buffer of the packet, call the */
/* application callback function for the receive complete */
/* call */
if
(
Ind
!=
this
->
MInd
)
{
R
[
this
->
RCurrent
].
PLength
=
this
->
ROffset
;
if
(
this
->
ROffset
)
this
->
RCurrent
++
;
this
->
RNum
=
this
->
RCurrent
;
this
->
RCurrent
=
0xff
;
this
->
Ind
=
Ind
;
this
->
complete
=
2
;
CALLBACK
(
a
,
this
);
}
return
0
;
}
return
2
;
}
drivers/isdn/eicon/idi.h
deleted
100644 → 0
View file @
f69c2d56
/*
* External IDI interface
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.0
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#if !defined(IDI_H)
#define IDI_H
#include "sys.h"
/* typedefs for our data structures */
typedef
struct
get_name_s
GET_NAME
;
typedef
struct
entity_s
ENTITY
;
typedef
struct
buffers_s
BUFFERS
;
/* IDI request/callback function pointer */
typedef
void
(
*
IDI_CALL
)(
ENTITY
*
);
typedef
struct
{
word
length
;
/* length of data/parameter field */
byte
P
[
270
];
/* data/parameter field */
}
DBUFFER
;
#define REQ_NAME 0x0100
#define BOARD_NAME_LENGTH 9
struct
get_name_s
{
word
command
;
/* command = 0x0100 */
byte
name
[
BOARD_NAME_LENGTH
];
};
#define REQ_REMOVE 0x0000
/* pointer to word which is 0 */
#define REQ_SERIAL 0x0200
struct
get_serial_s
{
word
command
;
/* command = 0x0200 */
dword
serial
;
/* serial number */
};
#define REQ_POSTCALL 0x0300
struct
postcall_s
{
word
command
;
/* command = 0x0300 */
word
dummy
;
/* not used */
IDI_CALL
callback
;
/* routine address to call back */
ENTITY
*
contxt
;
/* ptr to entity to use */
};
#define REQ_XLOG 0x0400
/* structure is card dependent/defined locally */
struct
buffers_s
{
word
PLength
;
byte
*
P
;
};
struct
entity_s
{
byte
Req
;
/* pending request */
byte
Rc
;
/* return code received */
byte
Ind
;
/* indication received */
byte
ReqCh
;
/* channel of current Req */
byte
RcCh
;
/* channel of current Rc */
byte
IndCh
;
/* channel of current Ind */
byte
Id
;
/* ID used by this entity */
byte
GlobalId
;
/* reserved field */
byte
XNum
;
/* number of X-buffers */
byte
RNum
;
/* number of R-buffers */
BUFFERS
*
X
;
/* pointer to X-buffer list */
BUFFERS
*
R
;
/* pointer to R-buffer list */
word
RLength
;
/* length of current R-data */
DBUFFER
*
RBuffer
;
/* buffer of current R-data */
byte
RNR
;
/* receive not ready flag */
byte
complete
;
/* receive complete status */
IDI_CALL
callback
;
word
user
[
2
];
/* fields used by the driver internally */
byte
No
;
/* entity number */
byte
reserved2
;
/* reserved field */
byte
More
;
/* R/X More flags */
byte
MInd
;
/* MDATA coding for this ID */
byte
XCurrent
;
/* current transmit buffer */
byte
RCurrent
;
/* current receive buffer */
word
XOffset
;
/* offset in x-buffer */
word
ROffset
;
/* offset in r-buffer */
};
typedef
struct
{
byte
type
;
byte
channels
;
word
features
;
/* dword serial; */
IDI_CALL
request
;
}
DESCRIPTOR
;
extern
void
DIVA_DIDD_Read
(
DESCRIPTOR
*
,
int
);
/* descriptor type field coding */
#define IDI_ADAPTER_S 1
#define IDI_ADAPTER_PR 2
#define IDI_ADAPTER_DIVA 3
#define IDI_ADAPTER_MAESTRA 4
#define IDI_ADAPTER_MAESTRAQ 5
#define IDI_ADAPTER_MAESTRAP 6
#define IDI_VADAPTER 0x40
#define IDI_DRIVER 0x80
#define IDI_DIMAINT 0xff
/* feature bit mask values */
#define DI_VOICE 0x0
/* obsolete define */
#define DI_FAX3 0x1
#define DI_MODEM 0x2
#define DI_POST 0x4
#define DI_V110 0x8
#define DI_V120 0x10
#define DI_POTS 0x20
#define DI_CODEC 0x40
#define DI_MANAGE 0x80
#define DI_V_42 0x0100
#define DI_EXTD_FAX 0x0200
/* Extended FAX (ECM, 2D, T.6, Polling) */
#endif
/* IDI_H */
drivers/isdn/eicon/kprintf.c
deleted
100644 → 0
View file @
f69c2d56
/*
* Source file for kernel interface to kernel log facility
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.3
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include "eicon.h"
#include "sys.h"
#include <stdarg.h>
#include "divas.h"
#include "divalog.h"
#include "uxio.h"
void
DivasPrintf
(
char
*
fmt
,
...)
{
klog_t
log
;
/* log entry buffer */
va_list
argptr
;
/* pointer to additional args */
va_start
(
argptr
,
fmt
);
/* clear log entry */
memset
((
void
*
)
&
log
,
0
,
sizeof
(
klog_t
));
log
.
card
=
-
1
;
log
.
type
=
KLOG_TEXT_MSG
;
/* time stamp the entry */
log
.
time_stamp
=
UxTimeGet
();
/* call vsprintf to format the user's information */
vsnprintf
(
log
.
buffer
,
DIM
(
log
.
buffer
),
fmt
,
argptr
);
va_end
(
argptr
);
/* send to the log streams driver and return */
DivasLogAdd
(
&
log
,
sizeof
(
klog_t
));
return
;
}
drivers/isdn/eicon/lincfg.c
deleted
100644 → 0
View file @
f69c2d56
/*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.9
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include <linux/fs.h>
#undef N_DATA
/* Because we have our own definition */
#include <asm/io.h>
#include "sys.h"
#include "idi.h"
#include "constant.h"
#include "divas.h"
#undef ID_MASK
#include "pc.h"
#include "pr_pc.h"
#include "adapter.h"
#include "uxio.h"
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/ioport.h>
struct
file_operations
Divas_fops
;
int
Divas_major
;
extern
int
do_ioctl
(
struct
inode
*
pDivasInode
,
struct
file
*
pDivasFile
,
unsigned
int
command
,
unsigned
long
arg
);
extern
unsigned
int
do_poll
(
struct
file
*
pFile
,
struct
poll_table_struct
*
pPollTable
);
extern
ssize_t
do_read
(
struct
file
*
pFile
,
char
*
pUserBuffer
,
size_t
BufferSize
,
loff_t
*
pOffset
);
extern
int
do_open
(
struct
inode
*
,
struct
file
*
);
extern
int
do_release
(
struct
inode
*
,
struct
file
*
);
int
FPGA_Done
=
0
;
int
DivasCardsDiscover
(
void
)
{
struct
pci_dev
*
pdev
=
NULL
;
word
wNumCards
=
0
,
wDeviceIndex
=
0
;
word
PCItmp
;
dword
j
,
i
;
unsigned
int
PCIserial
;
dia_card_t
Card
;
byte
*
b
;
while
((
pdev
=
pci_find_device
(
PCI_VENDOR_ID_EICON
,
PCI_DEVICE_ID_EICON_MAESTRAQ
,
pdev
)))
{
dword
dwRAM
,
dwDivasIOBase
,
dwCFG
,
dwCTL
;
printk
(
KERN_DEBUG
"Divas: DIVA Server 4BRI Found
\n
"
);
dwRAM
=
pci_resource_start
(
pdev
,
2
);
dwDivasIOBase
=
pci_resource_start
(
pdev
,
1
);
dwCFG
=
pci_resource_start
(
pdev
,
0
);
dwCTL
=
pci_resource_start
(
pdev
,
3
);
/* Retrieve the serial number */
pci_write_config_word
(
pdev
,
0x4E
,
0x00FC
);
for
(
j
=
0
,
PCItmp
=
0
;
j
<
10000
&&
!
PCItmp
;
j
++
)
{
pci_read_config_word
(
pdev
,
0x4E
,
&
PCItmp
);
PCItmp
&=
0x8000
;
// extract done flag
}
pci_read_config_dword
(
pdev
,
0x50
,
&
PCIserial
);
Card
.
memory
[
DIVAS_RAM_MEMORY
]
=
ioremap
(
dwRAM
,
0x400000
);
Card
.
memory
[
DIVAS_CTL_MEMORY
]
=
ioremap
(
dwCTL
,
0x2000
);
Card
.
memory
[
DIVAS_CFG_MEMORY
]
=
ioremap
(
dwCFG
,
0x100
);
Card
.
io_base
=
dwDivasIOBase
;
Card
.
card_type
=
DIA_CARD_TYPE_DIVA_SERVER_Q
;
Card
.
bus_type
=
DIA_BUS_TYPE_PCI
;
Card
.
pdev
=
pdev
;
Card
.
irq
=
pdev
->
irq
;
FPGA_Done
=
0
;
/* Create four virtual card structures as we want to treat
the 4Bri card as 4 Bri cards*/
for
(
i
=
0
;
i
<
4
;
i
++
)
{
b
=
Card
.
memory
[
DIVAS_RAM_MEMORY
];
b
+=
(
MQ_PROTCODE_OFFSET
)
*
(
i
==
0
?
0
:
1
);
DPRINTF
((
"divas: offset = 0x%x"
,
i
*
MQ_PROTCODE_OFFSET
));
Card
.
memory
[
DIVAS_RAM_MEMORY
]
=
b
;
b
=
Card
.
memory
[
DIVAS_RAM_MEMORY
];
b
+=
MQ_SM_OFFSET
;
Card
.
memory
[
DIVAS_SHARED_MEMORY
]
=
b
;
Card
.
slot
=
-
1
;
sprintf
(
Card
.
name
,
"DIVASQ%ld"
,
i
);
Card
.
serial
=
PCIserial
;
Card
.
card_id
=
wNumCards
;
if
(
DivasCardNew
(
&
Card
)
!=
0
)
{
break
;
}
wNumCards
++
;
}
}
pdev
=
NULL
;
while
((
pdev
=
pci_find_device
(
PCI_VENDOR_ID_EICON
,
PCI_DEVICE_ID_EICON_MAESTRA
,
pdev
)))
{
dword
dwPLXIOBase
,
dwDivasIOBase
;
printk
(
KERN_DEBUG
"Divas: DIVA Server BRI (S/T) Found
\n
"
);
dwPLXIOBase
=
pci_resource_start
(
pdev
,
1
);
dwDivasIOBase
=
pci_resource_start
(
pdev
,
2
);
Card
.
card_id
=
wNumCards
;
Card
.
card_type
=
DIA_CARD_TYPE_DIVA_SERVER_B
;
Card
.
bus_type
=
DIA_BUS_TYPE_PCI
;
Card
.
pdev
=
pdev
;
Card
.
irq
=
pdev
->
irq
;
Card
.
reset_base
=
dwPLXIOBase
;
Card
.
io_base
=
dwDivasIOBase
;
Card
.
slot
=
-
1
;
strcpy
(
Card
.
name
,
"DIVASB"
);
if
(
check_region
(
Card
.
io_base
,
0x20
))
{
printk
(
KERN_WARNING
"Divas: DIVA I/O Base already in use 0x%x-0x%x
\n
"
,
Card
.
io_base
,
Card
.
io_base
+
0x1F
);
}
if
(
check_region
(
Card
.
reset_base
,
0x80
))
{
printk
(
KERN_WARNING
"Divas: PLX I/O Base already in use 0x%x-0x%x
\n
"
,
Card
.
reset_base
,
Card
.
reset_base
+
0x7F
);
continue
;
}
if
(
DivasCardNew
(
&
Card
)
!=
0
)
{
continue
;
}
wNumCards
++
;
}
pdev
=
NULL
;
while
((
pdev
=
pci_find_device
(
PCI_VENDOR_ID_EICON
,
PCI_DEVICE_ID_EICON_MAESTRAQ_U
,
pdev
)))
{
dword
dwPLXIOBase
,
dwDivasIOBase
;
printk
(
KERN_DEBUG
"Divas: DIVA Server BRI (U) Found
\n
"
);
dwPLXIOBase
=
pci_resource_start
(
pdev
,
1
);
dwDivasIOBase
=
pci_resource_start
(
pdev
,
2
);
Card
.
card_id
=
wNumCards
;
Card
.
card_type
=
DIA_CARD_TYPE_DIVA_SERVER_B
;
Card
.
bus_type
=
DIA_BUS_TYPE_PCI
;
Card
.
pdev
=
pdev
;
Card
.
irq
=
pdev
->
irq
;
Card
.
reset_base
=
dwPLXIOBase
;
Card
.
io_base
=
dwDivasIOBase
;
Card
.
slot
=
-
1
;
strcpy
(
Card
.
name
,
"DIVASB"
);
if
(
check_region
(
Card
.
io_base
,
0x20
))
{
printk
(
KERN_WARNING
"Divas: DIVA I/O Base already in use 0x%x-0x%x
\n
"
,
Card
.
io_base
,
Card
.
io_base
+
0x1F
);
continue
;
}
if
(
check_region
(
Card
.
reset_base
,
0x80
))
{
printk
(
KERN_WARNING
"Divas: PLX I/O Base already in use 0x%x-0x%x
\n
"
,
Card
.
reset_base
,
Card
.
reset_base
+
0x7F
);
continue
;
}
if
(
DivasCardNew
(
&
Card
)
!=
0
)
{
continue
;
}
wNumCards
++
;
}
wDeviceIndex
=
0
;
pdev
=
NULL
;
while
((
pdev
=
pci_find_device
(
PCI_VENDOR_ID_EICON
,
PCI_DEVICE_ID_EICON_MAESTRAQ_U
,
pdev
)))
{
dword
dwRAM
,
dwREG
,
dwCFG
;
printk
(
KERN_DEBUG
"Divas: DIVA Server PRI Found
\n
"
);
dwRAM
=
pci_resource_start
(
pdev
,
0
);
dwREG
=
pci_resource_start
(
pdev
,
2
);
dwCFG
=
pci_resource_start
(
pdev
,
4
);
Card
.
memory
[
DIVAS_RAM_MEMORY
]
=
ioremap
(
dwRAM
,
0x10000
);
Card
.
memory
[
DIVAS_REG_MEMORY
]
=
ioremap
(
dwREG
,
0x4000
);
Card
.
memory
[
DIVAS_CFG_MEMORY
]
=
ioremap
(
dwCFG
,
0x1000
);
Card
.
memory
[
DIVAS_SHARED_MEMORY
]
=
Card
.
memory
[
DIVAS_RAM_MEMORY
]
+
DIVAS_SHARED_OFFSET
;
Card
.
card_id
=
wNumCards
;
Card
.
card_type
=
DIA_CARD_TYPE_DIVA_SERVER
;
Card
.
bus_type
=
DIA_BUS_TYPE_PCI
;
Card
.
pdev
=
pdev
;
Card
.
irq
=
pdev
->
irq
;
Card
.
slot
=
-
1
;
strcpy
(
Card
.
name
,
"DIVASP"
);
if
(
DivasCardNew
(
&
Card
)
!=
0
)
{
continue
;
}
wNumCards
++
;
}
printk
(
KERN_INFO
"Divas: %d cards detected
\n
"
,
wNumCards
);
if
(
wNumCards
==
0
)
{
return
-
1
;
}
Divas_fops
.
ioctl
=
do_ioctl
;
Divas_fops
.
poll
=
do_poll
;
Divas_fops
.
read
=
do_read
;
Divas_fops
.
open
=
do_open
;
Divas_fops
.
release
=
do_release
;
Divas_major
=
register_chrdev
(
0
,
"Divas"
,
&
Divas_fops
);
if
(
Divas_major
<
0
)
{
printk
(
KERN_WARNING
"Divas: Unable to register character driver
\n
"
);
return
-
1
;
}
return
0
;
}
/* Error return -1 */
int
DivasConfigGet
(
dia_card_t
*
card
)
{
/* Retrieve Config from O/S? Not in Linux */
return
0
;
}
dia_config_t
*
DivasConfig
(
card_t
*
card
,
dia_config_t
*
config
)
{
/* If config retrieved from OS then copy the data into a dia_config_t structure here
and return the pointer here. If the config 'came from above' then just
return config;
*/
return
config
;
}
drivers/isdn/eicon/linchr.c
deleted
100644 → 0
View file @
f69c2d56
/*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.12
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/poll.h>
#include <linux/fs.h>
#include <linux/slab.h>
#undef N_DATA
#include "adapter.h"
#include "divas.h"
#include "divalog.h"
extern
int
DivasCardNext
;
void
UxPause
(
long
ms
);
int
DivasGetMem
(
mem_block_t
*
);
#define DIA_IOCTL_UNLOCK 12
void
UnlockDivas
(
void
);
int
do_ioctl
(
struct
inode
*
pDivasInode
,
struct
file
*
pDivasFile
,
unsigned
int
command
,
unsigned
long
arg
)
{
byte
*
pUserCards
,
card_i
;
word
wCardNum
;
switch
(
command
)
{
case
DIA_IOCTL_CONFIG
:
{
dia_config_t
DivaConfig
;
if
(
copy_from_user
(
&
DivaConfig
,
(
void
*
)
arg
,
sizeof
(
dia_config_t
)))
return
-
EFAULT
;
DivasCardConfig
(
&
DivaConfig
);
return
0
;
}
case
DIA_IOCTL_DETECT
:
pUserCards
=
(
byte
*
)
arg
;
if
(
!
verify_area
(
VERIFY_WRITE
,
pUserCards
,
20
))
{
if
(
__put_user
(
DivasCardNext
,
pUserCards
++
))
return
-
EFAULT
;
for
(
card_i
=
1
;
card_i
<
20
;
card_i
++
)
{
if
(
__put_user
((
byte
)
DivasCards
[
card_i
-
1
].
cfg
.
card_type
,
pUserCards
++
))
return
-
EFAULT
;
}
}
else
return
-
EFAULT
;
return
0
;
case
DIA_IOCTL_START
:
{
dia_start_t
DivaStart
;
if
(
copy_from_user
(
&
DivaStart
,
(
void
*
)
arg
,
sizeof
(
dia_start_t
)))
return
-
EFAULT
;
return
DivasCardStart
(
DivaStart
.
card_id
);
}
case
DIA_IOCTL_FLAVOUR
:
return
0
;
case
DIA_IOCTL_LOAD
:
{
dia_load_t
DivaLoad
;
if
(
copy_from_user
(
&
DivaLoad
,
(
void
*
)
arg
,
sizeof
(
dia_load_t
)))
return
-
EFAULT
;
if
(
!
verify_area
(
VERIFY_READ
,
DivaLoad
.
code
,
DivaLoad
.
length
))
{
if
(
DivasCardLoad
(
&
DivaLoad
))
{
printk
(
KERN_WARNING
"Divas: Error loading DIVA Server adapter
\n
"
);
return
-
EINVAL
;
}
return
0
;
}
return
-
EFAULT
;
}
case
DIA_IOCTL_LOG
:
{
dia_log_t
DivaLog
;
if
(
copy_from_user
(
&
DivaLog
,
(
void
*
)
arg
,
sizeof
(
dia_log_t
)))
return
-
EFAULT
;
DivasLog
(
&
DivaLog
);
return
0
;
}
case
DIA_IOCTL_XLOG_REQ
:
if
(
get_user
(
wCardNum
,
(
word
*
)
arg
))
return
-
EFAULT
;
DivasXlogReq
(
wCardNum
);
return
0
;
case
DIA_IOCTL_GET_NUM
:
if
(
put_user
(
DivasCardNext
,
(
int
*
)
arg
))
return
-
EFAULT
;
return
0
;
case
DIA_IOCTL_GET_LIST
:
{
dia_card_list_t
cards
;
DPRINTF
((
"divas: DIA_IOCTL_GET_LIST"
));
DivasGetList
(
&
cards
);
if
(
copy_to_user
((
void
*
)
arg
,
&
cards
,
sizeof
(
cards
)))
return
-
EFAULT
;
return
0
;
}
case
DIA_IOCTL_GET_MEM
:
{
mem_block_t
mem_block
;
if
(
copy_from_user
(
&
mem_block
,
(
void
*
)
arg
,
sizeof
(
mem_block_t
)))
return
-
EFAULT
;
DivasGetMem
(
&
mem_block
);
return
0
;
}
case
DIA_IOCTL_UNLOCK
:
UnlockDivas
();
return
0
;
default:
return
-
EINVAL
;
}
return
-
EINVAL
;
}
unsigned
int
do_poll
(
struct
file
*
pFile
,
struct
poll_table_struct
*
pPollTable
)
{
word
wMask
=
0
;
if
(
!
DivasLogFifoEmpty
())
wMask
|=
POLLIN
|
POLLRDNORM
;
return
wMask
;
}
ssize_t
do_read
(
struct
file
*
pFile
,
char
*
pUserBuffer
,
size_t
BufferSize
,
loff_t
*
pOffset
)
{
klog_t
*
pClientLogBuffer
=
(
klog_t
*
)
pUserBuffer
;
klog_t
*
pHeadItem
;
if
(
BufferSize
<
sizeof
(
klog_t
))
return
-
EIO
;
pHeadItem
=
(
klog_t
*
)
DivasLogFifoRead
();
if
(
pHeadItem
)
{
if
(
copy_to_user
(
pClientLogBuffer
,
pHeadItem
,
sizeof
(
klog_t
)))
{
kfree
(
pHeadItem
);
return
-
EFAULT
;
}
kfree
(
pHeadItem
);
return
sizeof
(
klog_t
);
}
return
0
;
}
static
int
private_usage_count
;
int
do_open
(
struct
inode
*
pInode
,
struct
file
*
pFile
)
{
MOD_INC_USE_COUNT
;
#ifdef MODULE
private_usage_count
++
;
#endif
return
0
;
}
int
do_release
(
struct
inode
*
pInode
,
struct
file
*
pFile
)
{
MOD_DEC_USE_COUNT
;
#ifdef MODULE
private_usage_count
--
;
#endif
return
0
;
}
void
UnlockDivas
(
void
)
{
while
(
private_usage_count
>
0
)
{
private_usage_count
--
;
MOD_DEC_USE_COUNT
;
}
}
drivers/isdn/eicon/linio.c
deleted
100644 → 0
View file @
f69c2d56
/*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.16
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#define N_DATA
#include <linux/config.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/smp_lock.h>
#include <asm/io.h>
#include <asm/system.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/delay.h>
#undef N_DATA
#include "uxio.h"
static
int
log_on
=
0
;
int
Divasdevflag
=
0
;
spinlock_t
diva_lock
=
SPIN_LOCK_UNLOCKED
;
static
ux_diva_card_t
card_pool
[
MAX_CARDS
];
void
UxPause
(
long
int
ms
)
{
unsigned
long
timeout
=
jiffies
+
((
ms
*
HZ
)
/
1000
);
while
(
time_before
(
jiffies
,
timeout
));
}
int
UxCardHandleGet
(
ux_diva_card_t
**
card
,
dia_card_t
*
cfg
)
{
int
i
;
ux_diva_card_t
*
c
;
if
(
cfg
->
bus_type
!=
DIA_BUS_TYPE_PCI
)
{
DPRINTF
((
"divas hw: type not PCI (%d)"
,
cfg
->
bus_type
));
return
-
1
;
}
for
(
i
=
0
;
(
i
<
DIM
(
card_pool
))
&&
(
card_pool
[
i
].
in_use
);
i
++
)
{
;
}
if
(
i
==
DIM
(
card_pool
))
{
DPRINTF
((
"divas hw: card_pool exhausted"
));
return
-
1
;
}
c
=
*
card
=
&
card_pool
[
i
];
switch
(
cfg
->
bus_type
)
{
case
DIA_BUS_TYPE_PCI
:
c
->
pdev
=
cfg
->
pdev
;
c
->
io_base
=
cfg
->
io_base
;
c
->
reset_base
=
cfg
->
reset_base
;
c
->
card_type
=
cfg
->
card_type
;
c
->
mapped
=
NULL
;
c
->
slot
=
cfg
->
slot
;
c
->
irq
=
(
int
)
cfg
->
irq
;
c
->
pDRAM
=
cfg
->
memory
[
DIVAS_RAM_MEMORY
];
c
->
pDEVICES
=
cfg
->
memory
[
DIVAS_REG_MEMORY
];
c
->
pCONFIG
=
cfg
->
memory
[
DIVAS_CFG_MEMORY
];
c
->
pSHARED
=
cfg
->
memory
[
DIVAS_SHARED_MEMORY
];
c
->
pCONTROL
=
cfg
->
memory
[
DIVAS_CTL_MEMORY
];
/* c->bus_type = DIA_BUS_TYPE_PCI;
c->bus_num = cfg->bus_num & 0x3f;
c->slot = cfg->slot;
c->irq = (int) cfg->irq;
c->int_priority = (int) cfg->int_priority;
c->card_type = cfg->card_type;
c->io_base = cfg->io_base;
c->reset_base = cfg->reset_base;
c->pDRAM = cfg->memory[DIVAS_RAM_MEMORY];
c->pDEVICES = cfg->memory[DIVAS_REG_MEMORY];
c->pCONFIG = cfg->memory[DIVAS_CFG_MEMORY];
c->pSHARED = cfg->memory[DIVAS_SHARED_MEMORY];
DPRINTF(("divas hw: pDRAM is 0x%x", c->pDRAM));
DPRINTF(("divas hw: pSHARED is 0x%x", c->pSHARED));
DPRINTF(("divas hw: pCONFIG is 0x%x", c->pCONFIG));
c->cm_key = cm_getbrdkey("Divas", cfg->card_id);*/
break
;
default:
break
;
}
c
->
in_use
=
TRUE
;
return
0
;
}
void
UxCardHandleFree
(
ux_diva_card_t
*
card
)
{
card
->
in_use
=
FALSE
;
}
#define PLX_IOBASE 0
#define DIVAS_IOBASE 1
void
*
UxCardMemAttach
(
ux_diva_card_t
*
card
,
int
id
)
{
if
(
card
->
card_type
==
DIA_CARD_TYPE_DIVA_SERVER
)
{
switch
(
id
)
{
case
DIVAS_SHARED_MEMORY
:
card
->
mapped
=
card
->
pSHARED
;
return
card
->
pSHARED
;
break
;
case
DIVAS_RAM_MEMORY
:
card
->
mapped
=
card
->
pDRAM
;
return
card
->
pDRAM
;
break
;
case
DIVAS_REG_MEMORY
:
card
->
mapped
=
card
->
pDEVICES
;
return
card
->
pDEVICES
;
break
;
case
DIVAS_CFG_MEMORY
:
card
->
mapped
=
card
->
pCONFIG
;
return
card
->
pCONFIG
;
break
;
default:
ASSERT
(
FALSE
);
card
->
mapped
=
NULL
;
return
(
void
*
)
0
;
}
}
else
if
(
card
->
card_type
==
DIA_CARD_TYPE_DIVA_SERVER_B
)
{
switch
(
id
)
{
case
PLX_IOBASE
:
return
(
void
*
)
card
->
reset_base
;
break
;
case
DIVAS_IOBASE
:
return
(
void
*
)
card
->
io_base
;
break
;
default:
ASSERT
(
FALSE
);
return
0
;
}
}
else
if
(
card
->
card_type
==
DIA_CARD_TYPE_DIVA_SERVER_Q
)
{
switch
(
id
)
{
case
DIVAS_SHARED_MEMORY
:
card
->
mapped
=
card
->
pSHARED
;
return
card
->
pSHARED
;
break
;
case
DIVAS_RAM_MEMORY
:
card
->
mapped
=
card
->
pDRAM
;
return
card
->
pDRAM
;
break
;
case
DIVAS_REG_MEMORY
:
card
->
mapped
=
(
void
*
)
card
->
io_base
;
return
(
void
*
)
card
->
io_base
;
break
;
case
DIVAS_CTL_MEMORY
:
card
->
mapped
=
card
->
pCONTROL
;
return
card
->
pCONTROL
;
break
;
default:
// ASSERT(FALSE);
DPRINTF
((
"divas: Trying to attach to mem %d"
,
id
));
card
->
mapped
=
NULL
;
return
(
void
*
)
0
;
}
}
else
DPRINTF
((
"divas: Tried to attach to unknown card"
));
/* Unknown card type */
return
NULL
;
}
void
UxCardMemDetach
(
ux_diva_card_t
*
card
,
void
*
address
)
{
return
;
// Just a place holder. No un-mapping done.
}
void
UxCardLog
(
int
turn_on
)
{
log_on
=
turn_on
;
}
/*
* Control Register I/O Routines to be performed on Attached I/O ports
*/
void
UxCardPortIoOut
(
ux_diva_card_t
*
card
,
void
*
AttachedBase
,
int
offset
,
byte
the_byte
)
{
word
base
=
(
word
)
(
dword
)
AttachedBase
;
base
+=
offset
;
outb
(
the_byte
,
base
);
}
void
UxCardPortIoOutW
(
ux_diva_card_t
*
card
,
void
*
AttachedBase
,
int
offset
,
word
the_word
)
{
word
base
=
(
word
)
(
dword
)
AttachedBase
;
base
+=
offset
;
outw
(
the_word
,
base
);
}
void
UxCardPortIoOutD
(
ux_diva_card_t
*
card
,
void
*
AttachedBase
,
int
offset
,
dword
the_dword
)
{
word
base
=
(
word
)
(
dword
)
AttachedBase
;
base
+=
offset
;
outl
(
the_dword
,
base
);
}
byte
UxCardPortIoIn
(
ux_diva_card_t
*
card
,
void
*
AttachedBase
,
int
offset
)
{
word
base
=
(
word
)
(
dword
)
AttachedBase
;
base
+=
offset
;
return
inb
(
base
);
}
word
UxCardPortIoInW
(
ux_diva_card_t
*
card
,
void
*
AttachedBase
,
int
offset
)
{
word
base
=
(
word
)
(
dword
)
AttachedBase
;
base
+=
offset
;
return
inw
(
base
);
}
/*
* Memory mapped card I/O functions
*/
byte
UxCardMemIn
(
ux_diva_card_t
*
card
,
void
*
address
)
{
byte
b
;
volatile
byte
*
t
=
(
byte
*
)
address
;
b
=
*
t
;
if
(
log_on
)
{
byte
*
a
=
address
;
a
-=
(
int
)
card
->
mapped
;
DPRINTF
((
"divas hw: read 0x%02x from 0x%x (memory mapped)"
,
b
&
0xff
,
a
));
}
return
(
b
);
}
word
UxCardMemInW
(
ux_diva_card_t
*
card
,
void
*
address
)
{
word
w
;
volatile
word
*
t
=
(
word
*
)
address
;
w
=
*
t
;
if
(
log_on
)
{
byte
*
a
=
address
;
a
-=
(
int
)
card
->
mapped
;
DPRINTF
((
"divas hw: read 0x%04x from 0x%x (memory mapped)"
,
w
&
0xffff
,
a
));
}
return
(
w
);
}
dword
UxCardMemInD
(
ux_diva_card_t
*
card
,
void
*
address
)
{
dword
dw
;
volatile
dword
*
t
=
(
dword
*
)
address
;
dw
=
*
t
;
if
(
log_on
)
{
byte
*
a
=
address
;
a
-=
(
int
)
card
->
mapped
;
DPRINTF
((
"divas hw: read 0x%08x from 0x%x (memory mapped)"
,
dw
,
a
));
}
return
(
dw
);
}
void
UxCardMemInBuffer
(
ux_diva_card_t
*
card
,
void
*
address
,
void
*
buffer
,
int
length
)
{
volatile
byte
*
pSource
=
address
;
byte
*
pDest
=
buffer
;
while
(
length
--
)
{
*
pDest
++
=
*
pSource
++
;
}
if
(
log_on
)
{
byte
*
a
=
address
;
a
-=
(
int
)
card
->
mapped
;
pDest
=
buffer
;
DPRINTF
((
"divas hw: read %02x %02x %02x %02x %02x %02x %02x %02x from 0x%x (memory mapped)"
,
pDest
[
0
]
&
0xff
,
pDest
[
1
]
&
0xff
,
pDest
[
2
]
&
0xff
,
pDest
[
3
]
&
0xff
,
pDest
[
4
]
&
0xff
,
pDest
[
5
]
&
0xff
,
pDest
[
6
]
&
0xff
,
pDest
[
7
]
&
0xff
,
a
));
}
return
;
}
void
UxCardMemOut
(
ux_diva_card_t
*
card
,
void
*
address
,
byte
data
)
{
volatile
byte
*
t
=
(
byte
*
)
address
;
if
(
log_on
)
{
byte
*
a
=
address
;
a
-=
(
int
)
card
->
mapped
;
DPRINTF
((
"divas hw: wrote 0x%02x to 0x%x (memory mapped)"
,
data
&
0xff
,
a
));
}
*
t
=
data
;
return
;
}
void
UxCardMemOutW
(
ux_diva_card_t
*
card
,
void
*
address
,
word
data
)
{
volatile
word
*
t
=
(
word
*
)
address
;
if
(
log_on
)
{
byte
*
a
=
address
;
a
-=
(
int
)
card
->
mapped
;
DPRINTF
((
"divas hw: wrote 0x%04x to 0x%x (memory mapped)"
,
data
&
0xffff
,
a
));
}
*
t
=
data
;
return
;
}
void
UxCardMemOutD
(
ux_diva_card_t
*
card
,
void
*
address
,
dword
data
)
{
volatile
dword
*
t
=
(
dword
*
)
address
;
if
(
log_on
)
{
byte
*
a
=
address
;
a
-=
(
int
)
card
->
mapped
;
DPRINTF
((
"divas hw: wrote 0x%08x to 0x%x (memory mapped)"
,
data
,
a
));
}
*
t
=
data
;
return
;
}
void
UxCardMemOutBuffer
(
ux_diva_card_t
*
card
,
void
*
address
,
void
*
buffer
,
int
length
)
{
byte
*
pSource
=
buffer
;
byte
*
pDest
=
address
;
while
(
length
--
)
{
*
pDest
++
=
*
pSource
++
;
}
if
(
log_on
)
{
byte
*
a
=
address
;
a
-=
(
int
)
card
->
mapped
;
pDest
=
buffer
;
DPRINTF
((
"divas hw: wrote %02x %02x %02x %02x %02x %02x %02x %02x to 0x%x (memory mapped)"
,
pDest
[
0
]
&
0xff
,
pDest
[
1
]
&
0xff
,
pDest
[
2
]
&
0xff
,
pDest
[
3
]
&
0xff
,
pDest
[
4
]
&
0xff
,
pDest
[
5
]
&
0xff
,
pDest
[
6
]
&
0xff
,
pDest
[
7
]
&
0xff
,
a
));
}
return
;
}
/*
* Memory mapped card I/O functions
*/
byte
UxCardIoIn
(
ux_diva_card_t
*
card
,
void
*
AttachedDivasIOBase
,
void
*
address
)
{
byte
the_byte
;
outb
(
0xFF
,
card
->
io_base
+
0xC
);
outw
((
word
)
(
dword
)
address
,
card
->
io_base
+
4
);
the_byte
=
inb
(
card
->
io_base
);
if
(
log_on
)
{
DPRINTF
((
"divas hw: read 0x%02x from 0x%x (I/O mapped)"
,
the_byte
&
0xff
,
address
));
}
return
the_byte
;
}
word
UxCardIoInW
(
ux_diva_card_t
*
card
,
void
*
AttachedDivasIOBase
,
void
*
address
)
{
word
the_word
;
outb
(
0xFF
,
card
->
io_base
+
0xC
);
outw
((
word
)
(
dword
)
address
,
card
->
io_base
+
4
);
the_word
=
inw
(
card
->
io_base
);
if
(
log_on
)
{
DPRINTF
((
"divas hw: read 0x%04x from 0x%x (I/O mapped)"
,
the_word
&
0xffff
,
address
));
}
return
the_word
;
}
dword
UxCardIoInD
(
ux_diva_card_t
*
card
,
void
*
AttachedDivasIOBase
,
void
*
address
)
{
dword
the_dword
;
outb
(
0xFF
,
card
->
io_base
+
0xC
);
outw
((
word
)
(
dword
)
address
,
card
->
io_base
+
4
);
the_dword
=
inl
(
card
->
io_base
);
if
(
log_on
)
{
DPRINTF
((
"divas hw: read 0x%08x from 0x%x (I/O mapped)"
,
the_dword
,
address
));
}
return
the_dword
;
}
void
UxCardIoInBuffer
(
ux_diva_card_t
*
card
,
void
*
AttachedDivasIOBase
,
void
*
address
,
void
*
buffer
,
int
length
)
{
byte
*
pSource
=
address
;
byte
*
pDest
=
buffer
;
if
((
word
)
(
dword
)
address
&
0x1
)
{
outb
(
0xFF
,
card
->
io_base
+
0xC
);
outw
((
word
)
(
dword
)
pSource
,
card
->
io_base
+
4
);
*
pDest
=
(
byte
)
inb
(
card
->
io_base
);
pDest
++
;
pSource
++
;
length
--
;
if
(
!
length
)
{
return
;
}
}
outb
(
0xFF
,
card
->
io_base
+
0xC
);
outw
((
word
)
(
dword
)
pSource
,
card
->
io_base
+
4
);
insw
(
card
->
io_base
,
(
word
*
)
pDest
,
length
%
2
?
(
length
+
1
)
>>
1
:
length
>>
1
);
if
(
log_on
)
{
pDest
=
buffer
;
DPRINTF
((
"divas hw: read %02x %02x %02x %02x %02x %02x %02x %02x from 0x%x (I/O mapped)"
,
pDest
[
0
]
&
0xff
,
pDest
[
1
]
&
0xff
,
pDest
[
2
]
&
0xff
,
pDest
[
3
]
&
0xff
,
pDest
[
4
]
&
0xff
,
pDest
[
5
]
&
0xff
,
pDest
[
6
]
&
0xff
,
pDest
[
7
]
&
0xff
,
address
));
}
return
;
}
/* Output */
void
UxCardIoOut
(
ux_diva_card_t
*
card
,
void
*
AttachedDivasIOBase
,
void
*
address
,
byte
data
)
{
if
(
log_on
)
{
DPRINTF
((
"divas hw: wrote 0x%02x to 0x%x (I/O mapped)"
,
data
&
0xff
,
address
));
}
outb
(
0xFF
,
card
->
io_base
+
0xC
);
outw
((
word
)
(
dword
)
address
,
card
->
io_base
+
4
);
outb
((
byte
)
data
&
0xFF
,
card
->
io_base
);
return
;
}
void
UxCardIoOutW
(
ux_diva_card_t
*
card
,
void
*
AttachedDivasIOBase
,
void
*
address
,
word
data
)
{
if
(
log_on
)
{
DPRINTF
((
"divas hw: wrote 0x%04x to 0x%x (I/O mapped)"
,
data
&
0xffff
,
address
));
}
outb
(
0xFF
,
card
->
io_base
+
0xC
);
outw
((
word
)
(
dword
)
address
,
card
->
io_base
+
4
);
outw
((
word
)
data
&
0xFFFF
,
card
->
io_base
);
return
;
}
void
UxCardIoOutD
(
ux_diva_card_t
*
card
,
void
*
AttachedDivasIOBase
,
void
*
address
,
dword
data
)
{
if
(
log_on
)
{
DPRINTF
((
"divas hw: wrote 0x%08x to 0x%x (I/O mapped)"
,
data
,
address
));
}
outb
(
0xFF
,
card
->
io_base
+
0xC
);
outw
((
word
)
(
dword
)
address
,
card
->
io_base
+
4
);
outl
((
dword
)
data
&
0xFFFFFFFF
,
card
->
io_base
);
return
;
}
void
UxCardIoOutBuffer
(
ux_diva_card_t
*
card
,
void
*
AttachedDivasIOBase
,
void
*
address
,
void
*
buffer
,
int
length
)
{
byte
*
pSource
=
buffer
;
byte
*
pDest
=
address
;
if
((
word
)
(
dword
)
address
&
1
)
{
outb
(
0xFF
,
card
->
io_base
+
0xC
);
outw
((
word
)
(
dword
)
pDest
,
card
->
io_base
+
4
);
outb
(
*
pSource
,
card
->
io_base
);
pSource
++
;
pDest
++
;
length
--
;
if
(
!
length
)
{
return
;
}
}
outb
(
0xFF
,
card
->
io_base
+
0xC
);
outw
((
word
)
(
dword
)
pDest
,
card
->
io_base
+
4
);
outsw
(
card
->
io_base
,
(
word
*
)
pSource
,
length
%
2
?
(
length
+
1
)
>>
1
:
length
>>
1
);
if
(
log_on
)
{
pDest
=
buffer
;
DPRINTF
((
"divas hw: wrote %02x %02x %02x %02x %02x %02x %02x %02x to 0x%x (I/O mapped)"
,
pDest
[
0
]
&
0xff
,
pDest
[
1
]
&
0xff
,
pDest
[
2
]
&
0xff
,
pDest
[
3
]
&
0xff
,
pDest
[
4
]
&
0xff
,
pDest
[
5
]
&
0xff
,
pDest
[
6
]
&
0xff
,
pDest
[
7
]
&
0xff
,
address
));
}
return
;
}
irqreturn_t
Divasintr
(
int
arg
,
void
*
unused
,
struct
pt_regs
*
unused_regs
)
{
int
i
;
card_t
*
card
=
NULL
;
ux_diva_card_t
*
ux_ref
=
NULL
;
for
(
i
=
0
;
i
<
DivasCardNext
;
i
++
)
{
if
(
arg
==
DivasCards
[
i
].
cfg
.
irq
)
{
card
=
&
DivasCards
[
i
];
ux_ref
=
card
->
hw
;
if
((
ux_ref
)
&&
(
card
->
is_live
))
{
(
*
ux_ref
->
user_isr
)(
ux_ref
->
user_isr_arg
);
}
else
{
DPRINTF
((
"divas: ISR couldn't locate card"
));
}
}
}
return
IRQ_HANDLED
;
}
int
UxIsrInstall
(
ux_diva_card_t
*
card
,
isr_fn_t
*
isr_fn
,
void
*
isr_arg
)
{
int
result
;
card
->
user_isr
=
isr_fn
;
card
->
user_isr_arg
=
isr_arg
;
result
=
request_irq
(
card
->
irq
,
Divasintr
,
SA_INTERRUPT
|
SA_SHIRQ
,
"Divas"
,
(
void
*
)
isr_arg
);
return
result
;
}
void
UxIsrRemove
(
ux_diva_card_t
*
card
,
void
*
dev_id
)
{
free_irq
(
card
->
irq
,
card
->
user_isr_arg
);
}
void
UxPciConfigWrite
(
ux_diva_card_t
*
card
,
int
size
,
int
offset
,
void
*
value
)
{
switch
(
size
)
{
case
sizeof
(
byte
):
pci_write_config_byte
(
card
->
pdev
,
offset
,
*
(
byte
*
)
value
);
break
;
case
sizeof
(
word
):
pci_write_config_word
(
card
->
pdev
,
offset
,
*
(
word
*
)
value
);
break
;
case
sizeof
(
dword
):
pci_write_config_dword
(
card
->
pdev
,
offset
,
*
(
dword
*
)
value
);
break
;
default:
printk
(
KERN_WARNING
"Divas: Invalid size in UxPciConfigWrite
\n
"
);
}
}
void
UxPciConfigRead
(
ux_diva_card_t
*
card
,
int
size
,
int
offset
,
void
*
value
)
{
switch
(
size
)
{
case
sizeof
(
byte
):
pci_read_config_byte
(
card
->
pdev
,
offset
,
(
byte
*
)
value
);
break
;
case
sizeof
(
word
):
pci_read_config_word
(
card
->
pdev
,
offset
,
(
word
*
)
value
);
break
;
case
sizeof
(
dword
):
pci_read_config_dword
(
card
->
pdev
,
offset
,
(
unsigned
int
*
)
value
);
break
;
default:
printk
(
KERN_WARNING
"Divas: Invalid size in UxPciConfigRead
\n
"
);
}
}
void
*
UxAlloc
(
unsigned
int
size
)
{
void
*
m
;
m
=
kmalloc
(
size
,
GFP_ATOMIC
);
return
m
;
}
void
UxFree
(
void
*
ptr
)
{
kfree
(
ptr
);
}
long
UxCardLock
(
ux_diva_card_t
*
card
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
diva_lock
,
flags
);
return
flags
;
}
void
UxCardUnlock
(
ux_diva_card_t
*
card
,
unsigned
long
ipl
)
{
spin_unlock_irqrestore
(
&
diva_lock
,
ipl
);
}
dword
UxTimeGet
(
void
)
{
return
jiffies
;
}
long
UxInterlockedIncrement
(
ux_diva_card_t
*
card
,
long
*
dst
)
{
register
volatile
long
*
p
;
register
long
ret
;
int
ipl
;
p
=
dst
;
ipl
=
UxCardLock
(
card
);
*
p
+=
1
;
ret
=
*
p
;
UxCardUnlock
(
card
,
ipl
);
return
(
ret
);
}
long
UxInterlockedDecrement
(
ux_diva_card_t
*
card
,
long
*
dst
)
{
register
volatile
long
*
p
;
register
long
ret
;
int
ipl
;
p
=
dst
;
ipl
=
UxCardLock
(
card
);
*
p
-=
1
;
ret
=
*
p
;
UxCardUnlock
(
card
,
ipl
);
return
(
ret
);
}
drivers/isdn/eicon/linsys.c
deleted
100644 → 0
View file @
f69c2d56
/*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.10
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include <linux/sched.h>
#undef N_DATA
#include <linux/workqueue.h>
#include <linux/smp.h>
struct
pt_regs
;
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include "sys.h"
#include "divas.h"
#include "adapter.h"
#include "divalog.h"
#include "uxio.h"
static
struct
tasklet_struct
DivasTask
;
int
Divas4BRIInitPCI
(
card_t
*
card
,
dia_card_t
*
cfg
)
{
/* Use UxPciConfigWrite routines to initialise PCI config space */
/* wPCIcommand = 0x03;
cm_write_devconfig16(CMKey, PCI_COMMAND, &wPCIcommand);
wPCIcommand = 0x280;
cm_write_devconfig16(CMKey, PCI_STATUS, &wPCIcommand);
bPCIcommand = 0x30;
cm_write_devconfig16(CMKey, PCI_STATUS, &wPCIcommand);
*/
return
0
;
}
int
DivasPRIInitPCI
(
card_t
*
card
,
dia_card_t
*
cfg
)
{
/* Use UxPciConfigWrite routines to initialise PCI config space */
/* wPCIcommand = 0x03;
cm_write_devconfig16(CMKey, PCI_COMMAND, &wPCIcommand);
wPCIcommand = 0x280;
cm_write_devconfig16(CMKey, PCI_STATUS, &wPCIcommand);
bPCIcommand = 0x30;
cm_write_devconfig8(CMKey, PCI_LATENCY, &bPCIcommand);*/
return
0
;
}
int
DivasBRIInitPCI
(
card_t
*
card
,
dia_card_t
*
cfg
)
{
/* Need to set these platform dependent values after patching */
card
->
hw
->
reset_base
=
card
->
cfg
.
reset_base
;
card
->
hw
->
io_base
=
card
->
cfg
.
io_base
;
request_region
(
card
->
hw
->
reset_base
,
0x80
,
"Divas"
);
request_region
(
card
->
hw
->
io_base
,
0x20
,
"Divas"
);
/* Same as for PRI */
return
DivasPRIInitPCI
(
card
,
cfg
);
}
/* ######################### Stubs of routines that are not done yet ################## */
/*void DivasLogIdi(card_t *card, ENTITY *e, int request)
{
}
*/
int
DivasDpcSchedule
(
void
)
{
tasklet_schedule
(
&
DivasTask
);
return
0
;
}
int
DivasScheduleRequestDpc
(
void
)
{
tasklet_schedule
(
&
DivasTask
);
return
0
;
}
void
DivasInitDpc
(
void
)
{
tasklet_init
(
&
DivasTask
,
DivasDoDpc
,
0
);
}
void
DivasLogAdd
(
void
*
buffer
,
int
length
)
{
static
boolean_t
overflow
=
FALSE
;
static
boolean_t
busy
=
FALSE
;
/* make sure we're not interrupting ourselves */
if
(
busy
)
{
printk
(
KERN_DEBUG
"Divas: Logging interrupting self !
\n
"
);
return
;
}
busy
=
TRUE
;
/* ignore call if daemon isn't running and we've reached limit */
if
(
DivasLogFifoFull
())
{
if
(
!
overflow
)
{
printk
(
KERN_DEBUG
"Divas: Trace buffer full
\n
"
);
overflow
=
TRUE
;
}
busy
=
FALSE
;
return
;
}
DivasLogFifoWrite
(
buffer
,
length
);
busy
=
FALSE
;
return
;
}
/* #################################################################################### */
drivers/isdn/eicon/log.c
deleted
100644 → 0
View file @
f69c2d56
/*
* Source file for diva log facility
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.5
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include "sys.h"
#include "idi.h"
#include "divas.h"
#include "adapter.h"
#include "divalog.h"
#include "uxio.h"
/*Counter to monitor number of messages */
static
int
m_count
;
#define MAX_BUFFERED_MSGS (1000)
/* Our Linked List Structure to hold message */
typedef
struct
klog_link
{
klog_t
klog
;
struct
klog_link
*
next
;
}
KNODE
;
/* First & Last structures in list*/
KNODE
*
head
;
KNODE
*
tail
;
/*
* retrieve message from FIFO buffer
* returns NULL if buffer empty
* otherwise returns pointer to entry
*/
char
*
DivasLogFifoRead
(
void
)
{
KNODE
*
old_head
;
if
(
head
==
NULL
)
{
/* Buffer Empty - No Messages */
return
NULL
;
}
m_count
--
;
/* Keep track of message to be read & increment to next message*/
old_head
=
head
;
head
=
head
->
next
;
/*Return ptr to Msg */
return
((
char
*
)
old_head
);
}
/*
* write message into FIFO buffer
*/
void
DivasLogFifoWrite
(
char
*
entry
,
int
length
)
{
KNODE
*
new_klog
;
if
(
head
==
NULL
)
{
/* No Entries in Log */
tail
=
NULL
;
m_count
=
0
;
new_klog
=
UxAlloc
(
sizeof
(
KNODE
));
if
(
new_klog
==
NULL
)
{
return
;
}
m_count
++
;
memset
(
new_klog
,
0
,
sizeof
(
KNODE
));
/* Set head & tail to point to the new Msg Struct */
head
=
tail
=
new_klog
;
tail
->
next
=
NULL
;
}
else
{
new_klog
=
UxAlloc
(
sizeof
(
KNODE
));
if
(
new_klog
==
NULL
)
{
return
;
}
m_count
++
;
memset
(
new_klog
,
0
,
sizeof
(
KNODE
));
/* Let last Msg Struct point to new Msg Struct & inc tail */
tail
->
next
=
new_klog
;
tail
=
new_klog
;
tail
->
next
=
NULL
;
}
if
(
length
>
sizeof
(
klog_t
))
{
length
=
sizeof
(
klog_t
);
}
memcpy
(
&
tail
->
klog
,
entry
,
length
);
return
;
}
/*
* DivaslogFifoEmpty:return TRUE if FIFO buffer is empty,otherwise FALSE
*/
int
DivasLogFifoEmpty
(
void
)
{
return
(
m_count
==
0
);
}
/*
*DivasLogFifoFull:return TRUE if FIFO buffer is full,otherwise FALSE
*/
int
DivasLogFifoFull
(
void
)
{
return
(
m_count
==
MAX_BUFFERED_MSGS
);
}
/*
* generate an IDI log entry
*/
void
DivasLogIdi
(
card_t
*
card
,
ENTITY
*
e
,
int
request
)
{
klog_t
klog
;
memset
(
&
klog
,
0
,
sizeof
(
klog
));
klog
.
time_stamp
=
UxTimeGet
();
klog
.
length
=
sizeof
(
ENTITY
)
>
sizeof
(
klog
.
buffer
)
?
sizeof
(
klog
.
buffer
)
:
sizeof
(
ENTITY
);
klog
.
card
=
(
int
)
(
card
-
DivasCards
);
klog
.
type
=
request
?
KLOG_IDI_REQ
:
KLOG_IDI_CALLBACK
;
klog
.
code
=
0
;
memcpy
(
klog
.
buffer
,
e
,
klog
.
length
);
/* send to the log driver and return */
DivasLogAdd
(
&
klog
,
sizeof
(
klog
));
return
;
}
drivers/isdn/eicon/pc.h
deleted
100644 → 0
View file @
f69c2d56
/*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.2
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#ifndef PC_H_INCLUDED
#define PC_H_INCLUDED
/*------------------------------------------------------------------*/
/* buffer definition */
/*------------------------------------------------------------------*/
typedef
struct
{
word
length
;
/* length of data/parameter field */
byte
P
[
270
];
/* data/parameter field */
}
PBUFFER
;
/*------------------------------------------------------------------*/
/* dual port ram structure */
/*------------------------------------------------------------------*/
struct
dual
{
byte
Req
;
/* request register */
byte
ReqId
;
/* request task/entity identification */
byte
Rc
;
/* return code register */
byte
RcId
;
/* return code task/entity identification */
byte
Ind
;
/* Indication register */
byte
IndId
;
/* Indication task/entity identification */
byte
IMask
;
/* Interrupt Mask Flag */
byte
RNR
;
/* Receiver Not Ready (set by PC) */
byte
XLock
;
/* XBuffer locked Flag */
byte
Int
;
/* ISDN-S interrupt */
byte
ReqCh
;
/* Channel field for layer-3 Requests */
byte
RcCh
;
/* Channel field for layer-3 Returncodes */
byte
IndCh
;
/* Channel field for layer-3 Indications */
byte
MInd
;
/* more data indication field */
word
MLength
;
/* more data total packet length */
byte
ReadyInt
;
/* request field for ready interrupt */
byte
SWReg
;
/* Software register for special purposes */
byte
Reserved
[
11
];
/* reserved space */
byte
InterfaceType
;
/* interface type 1=16K interface */
word
Signature
;
/* ISDN-S adapter Signature (GD) */
PBUFFER
XBuffer
;
/* Transmit Buffer */
PBUFFER
RBuffer
;
/* Receive Buffer */
};
/*------------------------------------------------------------------*/
/* SWReg Values (0 means no command) */
/*------------------------------------------------------------------*/
#define SWREG_DIE_WITH_LEDON 0x01
#define SWREG_HALT_CPU 0x02
/* Push CPU into a while(1) loop */
/*------------------------------------------------------------------*/
/* Id Fields Coding */
/*------------------------------------------------------------------*/
#define ID_MASK 0xe0
/* Mask for the ID field */
#define GL_ERR_ID 0x1f
/* ID for error reporting on global requests*/
#define DSIG_ID 0x00
/* ID for D-channel signaling */
#define NL_ID 0x20
/* ID for network-layer access (B or D) */
#define BLLC_ID 0x60
/* ID for B-channel link level access */
#define TASK_ID 0x80
/* ID for dynamic user tasks */
#define TIMER_ID 0xa0
/* ID for timer task */
#define TEL_ID 0xc0
/* ID for telephone support */
#define MAN_ID 0xe0
/* ID for management */
/*------------------------------------------------------------------*/
/* ASSIGN and REMOVE requests are the same for all entities */
/*------------------------------------------------------------------*/
#define ASSIGN 0x01
#define UREMOVE 0xfe
/* without returncode */
#define REMOVE 0xff
/*------------------------------------------------------------------*/
/* Timer Interrupt Task Interface */
/*------------------------------------------------------------------*/
#define ASSIGN_TIM 0x01
#define REMOVE_TIM 0xff
/*------------------------------------------------------------------*/
/* dynamic user task interface */
/*------------------------------------------------------------------*/
#define ASSIGN_TSK 0x01
#define REMOVE_TSK 0xff
#define LOAD 0xf0
#define RELOCATE 0xf1
#define START 0xf2
#define LOAD2 0xf3
#define RELOCATE2 0xf4
/*------------------------------------------------------------------*/
/* dynamic user task messages */
/*------------------------------------------------------------------*/
#define TSK_B2 0x0000
#define TSK_WAKEUP 0x2000
#define TSK_TIMER 0x4000
#define TSK_TSK 0x6000
#define TSK_PC 0xe000
/*------------------------------------------------------------------*/
/* LL management primitives */
/*------------------------------------------------------------------*/
#define ASSIGN_LL 1
/* assign logical link */
#define REMOVE_LL 0xff
/* remove logical link */
/*------------------------------------------------------------------*/
/* LL service primitives */
/*------------------------------------------------------------------*/
#define LL_UDATA 1
/* link unit data request/indication */
#define LL_ESTABLISH 2
/* link establish request/indication */
#define LL_RELEASE 3
/* link release request/indication */
#define LL_DATA 4
/* data request/indication */
#define LL_LOCAL 5
/* switch to local operation (COM only) */
#define LL_DATA_PEND 5
/* data pending indication (SDLC SHM only) */
#define LL_REMOTE 6
/* switch to remote operation (COM only) */
#define LL_TEST 8
/* link test request */
#define LL_MDATA 9
/* more data request/indication */
#define LL_BUDATA 10
/* broadcast unit data request/indication */
#define LL_XID 12
/* XID command request/indication */
#define LL_XID_R 13
/* XID response request/indication */
/*------------------------------------------------------------------*/
/* NL service primitives */
/*------------------------------------------------------------------*/
#define N_MDATA 1
/* more data to come REQ/IND */
#define N_CONNECT 2
/* OSI N-CONNECT REQ/IND */
#define N_CONNECT_ACK 3
/* OSI N-CONNECT CON/RES */
#define N_DISC 4
/* OSI N-DISC REQ/IND */
#define N_DISC_ACK 5
/* OSI N-DISC CON/RES */
#define N_RESET 6
/* OSI N-RESET REQ/IND */
#define N_RESET_ACK 7
/* OSI N-RESET CON/RES */
#define N_DATA 8
/* OSI N-DATA REQ/IND */
#define N_EDATA 9
/* OSI N-EXPEDITED DATA REQ/IND */
#define N_UDATA 10
/* OSI D-UNIT-DATA REQ/IND */
#define N_BDATA 11
/* BROADCAST-DATA REQ/IND */
#define N_DATA_ACK 12
/* data ack ind for D-bit procedure */
#define N_EDATA_ACK 13
/* data ack ind for INTERRUPT */
#define N_Q_BIT 0x10
/* Q-bit for req/ind */
#define N_M_BIT 0x20
/* M-bit for req/ind */
#define N_D_BIT 0x40
/* D-bit for req/ind */
/*------------------------------------------------------------------*/
/* Signaling management primitives */
/*------------------------------------------------------------------*/
#define ASSIGN_SIG 1
/* assign signaling task */
#define UREMOVE_SIG 0xfe
/* remove signaling task without returncode */
#define REMOVE_SIG 0xff
/* remove signaling task */
/*------------------------------------------------------------------*/
/* Signaling service primitives */
/*------------------------------------------------------------------*/
#define CALL_REQ 1
/* call request */
#define CALL_CON 1
/* call confirmation */
#define CALL_IND 2
/* incoming call connected */
#define LISTEN_REQ 2
/* listen request */
#define HANGUP 3
/* hangup request/indication */
#define SUSPEND 4
/* call suspend request/confirm */
#define RESUME 5
/* call resume request/confirm */
#define SUSPEND_REJ 6
/* suspend rejected indication */
#define USER_DATA 8
/* user data for user to user signaling */
#define CONGESTION 9
/* network congestion indication */
#define INDICATE_REQ 10
/* request to indicate an incoming call */
#define INDICATE_IND 10
/* indicates that there is an incoming call */
#define CALL_RES 11
/* accept an incoming call */
#define CALL_ALERT 12
/* send ALERT for incoming call */
#define INFO_REQ 13
/* INFO request */
#define INFO_IND 13
/* INFO indication */
#define REJECT 14
/* reject an incoming call */
#define RESOURCES 15
/* reserve B-Channel hardware resources */
#define TEL_CTRL 16
/* Telephone control request/indication */
#define STATUS_REQ 17
/* Request D-State (returned in INFO_IND) */
#define FAC_REG_REQ 18
/* connection idependent fac registration */
#define FAC_REG_ACK 19
/* fac registration acknowledge */
#define FAC_REG_REJ 20
/* fac registration reject */
#define CALL_COMPLETE 21
/* send a CALL_PROC for incoming call */
#define FACILITY_REQ 22
/* send a Facility Message type */
#define FACILITY_IND 22
/* Facility Message type indication */
#define SIG_CTRL 29
/* Control for signalling hardware */
#define DSP_CTRL 30
/* Control for DSPs */
#define LAW_REQ 31
/* Law config request for (returns info_i) */
/*------------------------------------------------------------------*/
/* management service primitives */
/*------------------------------------------------------------------*/
#define MAN_READ 2
#define MAN_WRITE 3
#define MAN_EXECUTE 4
#define MAN_EVENT_ON 5
#define MAN_EVENT_OFF 6
#define MAN_LOCK 7
#define MAN_UNLOCK 8
#define MAN_INFO_IND 2
#define MAN_EVENT_IND 3
#define MAN_TRACE_IND 4
#define MAN_ESC 0x80
/*------------------------------------------------------------------*/
/* return code coding */
/*------------------------------------------------------------------*/
#define UNKNOWN_COMMAND 0x01
/* unknown command */
#define WRONG_COMMAND 0x02
/* wrong command */
#define WRONG_ID 0x03
/* unknown task/entity id */
#define WRONG_CH 0x04
/* wrong task/entity id */
#define UNKNOWN_IE 0x05
/* unknown information el. */
#define WRONG_IE 0x06
/* wrong information el. */
#define OUT_OF_RESOURCES 0x07
/* ISDN-S card out of res. */
#define ADAPTER_DEAD 0x08
/* ISDN card CPU halted */
#define N_FLOW_CONTROL 0x10
/* Flow-Control, retry */
#define ASSIGN_RC 0xe0
/* ASSIGN acknowledgement */
#define ASSIGN_OK 0xef
/* ASSIGN OK */
#define OK_FC 0xfc
/* Flow-Control RC */
#define READY_INT 0xfd
/* Ready interrupt */
#define TIMER_INT 0xfe
/* timer interrupt */
#define OK 0xff
/* command accepted */
/*------------------------------------------------------------------*/
/* information elements */
/*------------------------------------------------------------------*/
#define SHIFT 0x90
/* codeset shift */
#define MORE 0xa0
/* more data */
#define CL 0xb0
/* congestion level */
/* codeset 0 */
#define BC 0x04
/* Bearer Capability */
#define CAU 0x08
/* cause */
#define CAD 0x0c
/* Connected address */
#define CAI 0x10
/* call identity */
#define CHI 0x18
/* channel identification */
#define LLI 0x19
/* logical link id */
#define CHA 0x1a
/* charge advice */
#define DT 0x29
/* ETSI date/time */
#define KEY 0x2c
/* keypad information element */
#define FTY 0x1c
/* facility information element */
#define DSP 0x28
/* display */
#define OAD 0x6c
/* origination address */
#define OSA 0x6d
/* origination sub-address */
#define CPN 0x70
/* called party number */
#define DSA 0x71
/* destination sub-address */
#define RDX 0x73
/* redirected number extended */
#define RDN 0x74
/* redirected number */
#define LLC 0x7c
/* low layer compatibility */
#define HLC 0x7d
/* high layer compatibility */
#define UUI 0x7e
/* user user information */
#define ESC 0x7f
/* escape extension */
#define DLC 0x20
/* data link layer configuration */
#define NLC 0x21
/* network layer configuration */
/* codeset 6 */
#define SIN 0x01
/* service indicator */
#define CIF 0x02
/* charging information */
#define DATE 0x03
/* date */
#define CPS 0x07
/* called party status */
/*------------------------------------------------------------------*/
/* TEL_CTRL contents */
/*------------------------------------------------------------------*/
#define RING_ON 0x01
#define RING_OFF 0x02
#define HANDS_FREE_ON 0x03
#define HANDS_FREE_OFF 0x04
#define ON_HOOK 0x80
#define OFF_HOOK 0x90
#endif
drivers/isdn/eicon/pc_maint.h
deleted
100644 → 0
View file @
f69c2d56
/*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.0
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#ifndef PC_MAINT_H
#define PC_MAINT_H
#if !defined(MIPS_SCOM)
#define BUFFER_SZ 48
#define MAINT_OFFS 0x380
#else
#define BUFFER_SZ 128
#define MAINT_OFFS 0xff00
#endif
#define MIPS_BUFFER_SZ 128
#define MIPS_MAINT_OFFS 0xff00
#define DO_LOG 1
#define MEMR 2
#define MEMW 3
#define IOR 4
#define IOW 5
#define B1TEST 6
#define B2TEST 7
#define BTESTOFF 8
#define DSIG_STATS 9
#define B_CH_STATS 10
#define D_CH_STATS 11
#define BL1_STATS 12
#define BL1_STATS_C 13
#define GET_VERSION 14
#define OS_STATS 15
#define XLOG_SET_MASK 16
#define XLOG_GET_MASK 17
#define DSP_READ 20
#define DSP_WRITE 21
#define OK 0xff
#define MORE_EVENTS 0xfe
#define NO_EVENT 1
struct
DSigStruc
{
byte
Id
;
byte
uX
;
byte
listen
;
byte
active
;
byte
sin
[
3
];
byte
bc
[
6
];
byte
llc
[
6
];
byte
hlc
[
6
];
byte
oad
[
20
];
};
struct
BL1Struc
{
dword
cx_b1
;
dword
cx_b2
;
dword
cr_b1
;
dword
cr_b2
;
dword
px_b1
;
dword
px_b2
;
dword
pr_b1
;
dword
pr_b2
;
word
er_b1
;
word
er_b2
;
};
struct
L2Struc
{
dword
XTotal
;
dword
RTotal
;
word
XError
;
word
RError
;
};
struct
OSStruc
{
word
free_n
;
};
typedef
union
{
struct
DSigStruc
DSigStats
;
struct
BL1Struc
BL1Stats
;
struct
L2Struc
L2Stats
;
struct
OSStruc
OSStats
;
byte
b
[
BUFFER_SZ
];
word
w
[
BUFFER_SZ
>>
1
];
word
l
[
BUFFER_SZ
>>
2
];
/* word is wrong, do not use! Use 'd' instead. */
dword
d
[
BUFFER_SZ
>>
2
];
}
BUFFER
;
typedef
union
{
struct
DSigStruc
DSigStats
;
struct
BL1Struc
BL1Stats
;
struct
L2Struc
L2Stats
;
struct
OSStruc
OSStats
;
byte
b
[
MIPS_BUFFER_SZ
];
word
w
[
MIPS_BUFFER_SZ
>>
1
];
word
l
[
BUFFER_SZ
>>
2
];
/* word is wrong, do not use! Use 'd' instead. */
dword
d
[
MIPS_BUFFER_SZ
>>
2
];
}
MIPS_BUFFER
;
#if !defined(MIPS_SCOM)
struct
pc_maint
{
byte
req
;
byte
rc
;
byte
*
mem
;
/*far*/
short
length
;
word
port
;
byte
fill
[
6
];
BUFFER
data
;
};
#else
struct
pc_maint
{
byte
req
;
byte
rc
;
byte
reserved
[
2
];
/* R3000 alignment ... */
byte
far
*
mem
;
short
length
;
word
port
;
byte
fill
[
4
];
/* data at offset 16 */
BUFFER
data
;
};
#endif
struct
mi_pc_maint
{
byte
req
;
byte
rc
;
byte
reserved
[
2
];
/* R3000 alignment ... */
byte
*
mem
;
/*far*/
short
length
;
word
port
;
byte
fill
[
4
];
/* data at offset 16 */
MIPS_BUFFER
data
;
};
#endif
/* PC_MAINT_H */
drivers/isdn/eicon/pr_pc.h
deleted
100644 → 0
View file @
f69c2d56
/*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.0
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#if !defined(PR_PC_H)
#define PR_PC_H
struct
pr_ram
{
word
NextReq
;
/* pointer to next Req Buffer */
word
NextRc
;
/* pointer to next Rc Buffer */
word
NextInd
;
/* pointer to next Ind Buffer */
byte
ReqInput
;
/* number of Req Buffers sent */
byte
ReqOutput
;
/* number of Req Buffers returned */
byte
ReqReserved
;
/* number of Req Buffers reserved */
byte
Int
;
/* ISDN-P interrupt */
byte
XLock
;
/* Lock field for arbitration */
byte
RcOutput
;
/* number of Rc buffers received */
byte
IndOutput
;
/* number of Ind buffers received */
byte
IMask
;
/* Interrupt Mask Flag */
byte
Reserved1
[
2
];
/* reserved field, do not use */
byte
ReadyInt
;
/* request field for ready interrupt */
byte
Reserved2
[
12
];
/* reserved field, do not use */
byte
InterfaceType
;
/* interface type 1=16K interface */
word
Signature
;
/* ISDN-P initialized indication */
byte
B
[
1
];
/* buffer space for Req,Ind and Rc */
};
typedef
struct
{
word
next
;
byte
Req
;
byte
ReqId
;
byte
ReqCh
;
byte
Reserved1
;
word
Reference
;
byte
Reserved
[
8
];
PBUFFER
XBuffer
;
}
REQ
;
typedef
struct
{
word
next
;
byte
Rc
;
byte
RcId
;
byte
RcCh
;
byte
Reserved1
;
word
Reference
;
byte
Reserved2
[
8
];
}
RC
;
typedef
struct
{
word
next
;
byte
Ind
;
byte
IndId
;
byte
IndCh
;
byte
MInd
;
word
MLength
;
word
Reference
;
byte
RNR
;
byte
Reserved
;
dword
Ack
;
PBUFFER
RBuffer
;
}
IND
;
#endif
drivers/isdn/eicon/pri.c
deleted
100644 → 0
View file @
f69c2d56
/*
* Diva Server PRI specific part of initialisation
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.5
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include "sys.h"
#include "idi.h"
#include "divas.h"
#include "pc.h"
#include "pr_pc.h"
#include "dsp_defs.h"
#include "adapter.h"
#include "uxio.h"
#define DIVAS_LOAD_CMD 0x02
#define DIVAS_START_CMD 0x03
#define DIVAS_IRQ_RESET 0xC18
#define DIVAS_IRQ_RESET_VAL 0xFE
#define TEST_INT_DIVAS 0x11
#define TEST_INT_DIVAS_BRI 0x12
#define DIVAS_RESET 0x81
#define DIVAS_LED1 0x04
#define DIVAS_LED2 0x08
#define DIVAS_LED3 0x20
#define DIVAS_LED4 0x40
#define DIVAS_RESET_REG 0x20
#define DIVAS_SIGNATURE 0x4447
/* offset to start of MAINT area (used by xlog) */
#define DIVAS_MAINT_OFFSET 0xef00
/* value for PRI card */
#define MP_PROTOCOL_ADDR 0xA0011000
#define MP_DSP_CODE_BASE 0xa03a0000
typedef
struct
{
dword
cmd
;
dword
addr
;
dword
len
;
dword
err
;
dword
live
;
dword
reserved
[(
0x1020
>>
2
)
-
6
];
dword
signature
;
byte
data
[
1
];
}
diva_server_boot_t
;
byte
mem_in
(
ADAPTER
*
a
,
void
*
adr
);
word
mem_inw
(
ADAPTER
*
a
,
void
*
adr
);
void
mem_in_buffer
(
ADAPTER
*
a
,
void
*
adr
,
void
*
P
,
word
length
);
void
mem_look_ahead
(
ADAPTER
*
a
,
PBUFFER
*
RBuffer
,
ENTITY
*
e
);
void
mem_out
(
ADAPTER
*
a
,
void
*
adr
,
byte
data
);
void
mem_outw
(
ADAPTER
*
a
,
void
*
adr
,
word
data
);
void
mem_out_buffer
(
ADAPTER
*
a
,
void
*
adr
,
void
*
P
,
word
length
);
void
mem_inc
(
ADAPTER
*
a
,
void
*
adr
);
int
DivasPRIInitPCI
(
card_t
*
card
,
dia_card_t
*
cfg
);
static
int
pri_ISR
(
card_t
*
card
);
static
int
diva_server_reset
(
card_t
*
card
)
{
byte
*
reg
;
diva_server_boot_t
*
boot
=
NULL
;
dword
live
=
0
;
int
i
=
0
;
dword
dwWait
;
DPRINTF
((
"divas: reset Diva Server PRI"
));
reg
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_REG_MEMORY
);
UxCardMemOut
(
card
->
hw
,
&
reg
[
DIVAS_RESET_REG
],
DIVAS_RESET
|
DIVAS_LED1
|
DIVAS_LED2
|
DIVAS_LED3
|
DIVAS_LED4
);
for
(
dwWait
=
0x000fffff
;
dwWait
;
dwWait
--
)
;
UxCardMemOut
(
card
->
hw
,
&
reg
[
DIVAS_RESET_REG
],
0x00
);
for
(
dwWait
=
0x000fffff
;
dwWait
;
dwWait
--
)
;
UxCardMemDetach
(
card
->
hw
,
reg
);
boot
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_RAM_MEMORY
);
UxCardMemOutD
(
card
->
hw
,
boot
->
reserved
,
0
);
live
=
UxCardMemInD
(
card
->
hw
,
&
boot
->
live
);
for
(
i
=
0
;
i
<
5
;
i
++
)
{
if
(
live
!=
UxCardMemInD
(
card
->
hw
,
&
boot
->
live
))
{
break
;
}
UxPause
(
10
);
}
if
(
i
==
5
)
{
UxCardMemDetach
(
card
->
hw
,
boot
);
DPRINTF
((
"divas: card is reset but CPU not running"
));
return
-
1
;
}
UxCardMemDetach
(
card
->
hw
,
boot
);
DPRINTF
((
"divas: card reset after %d ms"
,
i
*
10
));
return
0
;
}
static
int
diva_server_config
(
card_t
*
card
,
dia_config_t
*
config
)
{
byte
*
shared
;
int
i
,
j
;
DPRINTF
((
"divas: configure Diva Server PRI"
));
shared
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_SHARED_MEMORY
);
UxCardLog
(
0
);
for
(
i
=
0
;
i
<
256
;
i
++
)
{
UxCardMemOut
(
card
->
hw
,
&
shared
[
i
],
0
);
}
UxCardMemOut
(
card
->
hw
,
&
shared
[
8
],
config
->
tei
);
UxCardMemOut
(
card
->
hw
,
&
shared
[
9
],
config
->
nt2
);
UxCardMemOut
(
card
->
hw
,
&
shared
[
10
],
config
->
sig_flags
);
UxCardMemOut
(
card
->
hw
,
&
shared
[
11
],
config
->
watchdog
);
UxCardMemOut
(
card
->
hw
,
&
shared
[
12
],
config
->
permanent
);
UxCardMemOut
(
card
->
hw
,
&
shared
[
13
],
config
->
x_interface
);
UxCardMemOut
(
card
->
hw
,
&
shared
[
14
],
config
->
stable_l2
);
UxCardMemOut
(
card
->
hw
,
&
shared
[
15
],
config
->
no_order_check
);
UxCardMemOut
(
card
->
hw
,
&
shared
[
16
],
config
->
handset_type
);
UxCardMemOut
(
card
->
hw
,
&
shared
[
17
],
0
);
UxCardMemOut
(
card
->
hw
,
&
shared
[
18
],
config
->
low_channel
);
UxCardMemOut
(
card
->
hw
,
&
shared
[
19
],
config
->
prot_version
);
UxCardMemOut
(
card
->
hw
,
&
shared
[
20
],
config
->
crc4
);
for
(
i
=
0
;
i
<
2
;
i
++
)
{
for
(
j
=
0
;
j
<
32
;
j
++
)
{
UxCardMemOut
(
card
->
hw
,
&
shared
[
32
+
(
i
*
96
)
+
j
],
config
->
terminal
[
i
].
oad
[
j
]);
}
for
(
j
=
0
;
j
<
32
;
j
++
)
{
UxCardMemOut
(
card
->
hw
,
&
shared
[
64
+
(
i
*
96
)
+
j
],
config
->
terminal
[
i
].
osa
[
j
]);
}
for
(
j
=
0
;
j
<
32
;
j
++
)
{
UxCardMemOut
(
card
->
hw
,
&
shared
[
96
+
(
i
*
96
)
+
j
],
config
->
terminal
[
i
].
spid
[
j
]);
}
}
UxCardMemDetach
(
card
->
hw
,
shared
);
return
0
;
}
static
void
diva_server_reset_int
(
card_t
*
card
)
{
byte
*
cfg
;
cfg
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_CFG_MEMORY
);
UxCardMemOutW
(
card
->
hw
,
&
cfg
[
DIVAS_IRQ_RESET
],
DIVAS_IRQ_RESET_VAL
);
UxCardMemOutW
(
card
->
hw
,
&
cfg
[
DIVAS_IRQ_RESET
+
2
],
0
);
UxCardMemDetach
(
card
->
hw
,
cfg
);
return
;
}
static
int
diva_server_test_int
(
card_t
*
card
)
{
int
i
;
byte
*
shared
;
byte
req_int
;
DPRINTF
((
"divas: test interrupt for Diva Server PRI"
));
shared
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_SHARED_MEMORY
);
UxCardMemIn
(
card
->
hw
,
&
shared
[
0x3FE
]);
UxCardMemOut
(
card
->
hw
,
&
shared
[
0x3FE
],
0
);
UxCardMemIn
(
card
->
hw
,
&
shared
[
0x3FE
]);
UxCardMemDetach
(
card
->
hw
,
shared
);
diva_server_reset_int
(
card
);
shared
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_SHARED_MEMORY
);
card
->
test_int_pend
=
TEST_INT_DIVAS
;
req_int
=
UxCardMemIn
(
card
->
hw
,
&
(((
struct
pr_ram
*
)
shared
)
->
ReadyInt
));
req_int
++
;
UxCardMemOut
(
card
->
hw
,
&
(((
struct
pr_ram
*
)
shared
)
->
ReadyInt
),
req_int
);
UxCardMemDetach
(
card
->
hw
,
shared
);
UxCardLog
(
0
);
for
(
i
=
0
;
i
<
50
;
i
++
)
{
if
(
!
card
->
test_int_pend
)
{
break
;
}
UxPause
(
10
);
}
if
(
card
->
test_int_pend
)
{
DPRINTF
((
"active: timeout waiting for card to interrupt"
));
return
(
-
1
);
}
return
0
;
}
static
void
print_hdr
(
unsigned
char
*
code
,
int
offset
)
{
unsigned
char
hdr
[
80
];
int
i
;
i
=
0
;
while
((
i
<
(
DIM
(
hdr
)
-
1
))
&&
(
code
[
offset
+
i
]
!=
'\0'
)
&&
(
code
[
offset
+
i
]
!=
'\r'
)
&&
(
code
[
offset
+
i
]
!=
'\n'
))
{
hdr
[
i
]
=
code
[
offset
+
i
];
i
++
;
}
hdr
[
i
]
=
'\0'
;
DPRINTF
((
"divas: loading %s"
,
hdr
));
}
static
int
diva_server_load
(
card_t
*
card
,
dia_load_t
*
load
)
{
diva_server_boot_t
*
boot
;
int
i
,
offset
,
length
;
dword
cmd
=
0
;
DPRINTF
((
"divas: loading Diva Server PRI"
));
boot
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_RAM_MEMORY
);
switch
(
load
->
code_type
)
{
case
DIA_CPU_CODE
:
DPRINTF
((
"divas: RISC code"
));
print_hdr
(
load
->
code
,
0x80
);
UxCardMemOutD
(
card
->
hw
,
&
boot
->
addr
,
MP_PROTOCOL_ADDR
);
break
;
case
DIA_DSP_CODE
:
DPRINTF
((
"divas: DSP code"
));
print_hdr
(
load
->
code
,
0x0
);
UxCardMemOutD
(
card
->
hw
,
&
boot
->
addr
,
(
MP_DSP_CODE_BASE
+
(((
sizeof
(
dword
)
+
(
sizeof
(
t_dsp_download_desc
)
*
DSP_MAX_DOWNLOAD_COUNT
))
+
~
ALIGNMENT_MASK_MAESTRA
)
&
ALIGNMENT_MASK_MAESTRA
)));
break
;
case
DIA_TABLE_CODE
:
DPRINTF
((
"divas: TABLE code"
));
UxCardMemOutD
(
card
->
hw
,
&
boot
->
addr
,
(
MP_DSP_CODE_BASE
+
sizeof
(
dword
)));
break
;
case
DIA_CONT_CODE
:
DPRINTF
((
"divas: continuation code"
));
break
;
case
DIA_DLOAD_CNT
:
DPRINTF
((
"divas: COUNT code"
));
UxCardMemOutD
(
card
->
hw
,
&
boot
->
addr
,
MP_DSP_CODE_BASE
);
break
;
default:
DPRINTF
((
"divas: unknown code type"
));
UxCardMemDetach
(
card
->
hw
,
boot
);
return
-
1
;
}
UxCardLog
(
0
);
offset
=
0
;
do
{
length
=
(
load
->
length
-
offset
>=
400
)
?
400
:
load
->
length
-
offset
;
for
(
i
=
0
;
i
<
length
;
i
++
)
{
UxCardMemOut
(
card
->
hw
,
&
boot
->
data
[
i
],
load
->
code
[
offset
+
i
]);
}
for
(
i
=
0
;
i
<
length
;
i
++
)
{
if
(
load
->
code
[
offset
+
i
]
!=
UxCardMemIn
(
card
->
hw
,
&
boot
->
data
[
i
]))
{
UxCardMemDetach
(
card
->
hw
,
boot
);
DPRINTF
((
"divas: card code block verify failed"
));
return
-
1
;
}
}
UxCardMemOutD
(
card
->
hw
,
&
boot
->
len
,
(
length
+
3
)
/
4
);
UxCardMemOutD
(
card
->
hw
,
&
boot
->
cmd
,
DIVAS_LOAD_CMD
);
for
(
i
=
0
;
i
<
50000
;
i
++
)
{
cmd
=
UxCardMemInD
(
card
->
hw
,
&
boot
->
cmd
);
if
(
!
cmd
)
{
break
;
}
/*UxPause(1);*/
}
if
(
cmd
)
{
DPRINTF
((
"divas: timeout waiting for card to ACK load (offset = %d)"
,
offset
));
UxCardMemDetach
(
card
->
hw
,
boot
);
return
-
1
;
}
offset
+=
length
;
}
while
(
offset
<
load
->
length
);
UxCardMemDetach
(
card
->
hw
,
boot
);
DPRINTF
((
"divas: DIVA Server card loaded"
));
return
0
;
}
static
int
diva_server_start
(
card_t
*
card
,
byte
*
channels
)
{
diva_server_boot_t
*
boot
;
byte
*
ram
;
int
i
;
dword
signature
=
0
;
DPRINTF
((
"divas: start Diva Server PRI"
));
card
->
is_live
=
FALSE
;
boot
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_RAM_MEMORY
);
UxCardMemOutD
(
card
->
hw
,
&
boot
->
addr
,
MP_PROTOCOL_ADDR
);
UxCardMemOutD
(
card
->
hw
,
&
boot
->
cmd
,
DIVAS_START_CMD
);
UxCardLog
(
0
);
for
(
i
=
0
;
i
<
300
;
i
++
)
{
signature
=
UxCardMemInD
(
card
->
hw
,
&
boot
->
signature
);
if
((
signature
>>
16
)
==
DIVAS_SIGNATURE
)
{
DPRINTF
((
"divas: started card after %d ms"
,
i
*
10
));
break
;
}
UxPause
(
10
);
}
if
((
signature
>>
16
)
!=
DIVAS_SIGNATURE
)
{
UxCardMemDetach
(
card
->
hw
,
boot
);
DPRINTF
((
"divas: timeout waiting for card to run protocol code (sig = 0x%x)"
,
signature
));
return
-
1
;
}
card
->
is_live
=
TRUE
;
ram
=
(
byte
*
)
boot
;
ram
+=
DIVAS_SHARED_OFFSET
;
*
channels
=
UxCardMemIn
(
card
->
hw
,
&
ram
[
0x3F6
]);
card
->
serial_no
=
UxCardMemInD
(
card
->
hw
,
&
ram
[
0x3F0
]);
UxCardMemDetach
(
card
->
hw
,
boot
);
if
(
diva_server_test_int
(
card
))
{
DPRINTF
((
"divas: interrupt test failed"
));
return
-
1
;
}
DPRINTF
((
"divas: DIVA Server card started"
));
return
0
;
}
static
int
diva_server_mem_get
(
card_t
*
card
,
mem_block_t
*
mem_block
)
{
byte
*
a
;
byte
*
card_addr
;
word
length
=
0
;
int
i
;
a
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_RAM_MEMORY
);
card_addr
=
a
;
card_addr
+=
mem_block
->
addr
;
for
(
i
=
0
;
i
<
sizeof
(
mem_block
->
data
);
i
++
)
{
mem_block
->
data
[
i
]
=
UxCardMemIn
(
card
->
hw
,
card_addr
);
card_addr
++
;
length
++
;
}
UxCardMemDetach
(
card
->
hw
,
a
);
return
length
;
}
/*
* Initialise PRI specific entry points
*/
int
DivasPriInit
(
card_t
*
card
,
dia_card_t
*
cfg
)
{
DPRINTF
((
"divas: initialise Diva Server PRI"
));
if
(
DivasPRIInitPCI
(
card
,
cfg
)
==
-
1
)
{
return
-
1
;
}
card
->
card_reset
=
diva_server_reset
;
card
->
card_load
=
diva_server_load
;
card
->
card_config
=
diva_server_config
;
card
->
card_start
=
diva_server_start
;
card
->
reset_int
=
diva_server_reset_int
;
card
->
card_mem_get
=
diva_server_mem_get
;
card
->
xlog_offset
=
DIVAS_MAINT_OFFSET
;
card
->
out
=
DivasOut
;
card
->
test_int
=
DivasTestInt
;
card
->
dpc
=
DivasDpc
;
card
->
clear_int
=
DivasClearInt
;
card
->
card_isr
=
pri_ISR
;
card
->
a
.
ram_out
=
mem_out
;
card
->
a
.
ram_outw
=
mem_outw
;
card
->
a
.
ram_out_buffer
=
mem_out_buffer
;
card
->
a
.
ram_inc
=
mem_inc
;
card
->
a
.
ram_in
=
mem_in
;
card
->
a
.
ram_inw
=
mem_inw
;
card
->
a
.
ram_in_buffer
=
mem_in_buffer
;
card
->
a
.
ram_look_ahead
=
mem_look_ahead
;
return
0
;
}
static
int
pri_ISR
(
card_t
*
card
)
{
int
served
=
0
;
byte
*
cfg
=
UxCardMemAttach
(
card
->
hw
,
DIVAS_CFG_MEMORY
);
volatile
unsigned
long
*
isr
=
(
unsigned
long
*
)
&
cfg
[
DIVAS_IRQ_RESET
];
register
unsigned
long
val
=
*
isr
;
if
(
val
&
0x80000000
)
/* our card had caused interrupt ??? */
{
served
=
1
;
card
->
int_pend
+=
1
;
DivasDpcSchedule
();
/* ISR DPC */
*
isr
=
(
unsigned
long
)
~
0x03E00000
;
/* Clear interrupt line */
}
UxCardMemDetach
(
card
->
hw
,
cfg
);
return
(
served
!=
0
);
}
drivers/isdn/eicon/sys.h
deleted
100644 → 0
View file @
f69c2d56
/*
* Environment provided by system and miscellaneous definitions
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.2
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#if !defined(SYS_H)
#define SYS_H
/* abreviations for unsigned types */
typedef
int
boolean_t
;
typedef
unsigned
char
byte
;
typedef
unsigned
long
dword
;
typedef
unsigned
short
word
;
/* abreviations for volatile types */
typedef
volatile
byte
vbyte
;
typedef
volatile
word
vword
;
typedef
volatile
dword
vdword
;
/* Booleans */
#if !defined(TRUE)
#define TRUE (1)
#define FALSE (0)
#endif
/* NULL pointer */
#if !defined(NULL)
#define NULL ((void *) 0)
#endif
/* Return the dimension of an array */
#if !defined(DIM)
#define DIM(array) (sizeof (array)/sizeof ((array)[0]))
#endif
/*
* Return the number of milliseconds since last boot
*/
extern
dword
UxTimeGet
(
void
);
extern
void
DivasSprintf
(
char
*
buffer
,
char
*
format
,
...);
extern
void
DivasPrintf
(
char
*
format
,
...);
/* fatal errors, asserts and tracing */
void
HwFatalErrorFrom
(
char
*
file
,
int
line
);
void
HwFatalError
(
void
);
/* void HwAssert(char *file, int line, char *condition); */
#include <linux/kernel.h>
#include <linux/string.h>
#define _PRINTK printk
#define _PRINTF DivasPrintf
void
_PRINTF
(
char
*
format
,
...);
#define PRINTF(arg_list) _PRINTF arg_list
#if defined DTRACE
# define DPRINTF(arg_list) _PRINTF arg_list
# define KDPRINTF(arg_list) _PRINTF arg_list ; _PRINTK arg_list ; _PRINTK("\n");
#else
# define DPRINTF(arg_list) (void)0
# define KDPRINTF(arg_list) _PRINTK arg_list ; _PRINTK("\n");
#endif
#if !defined(ASSERT)
#if defined DEBUG || defined DBG
# define HwFatalError() HwFatalErrorFrom(__FILE__, __LINE__)
# define ASSERT(cond) \
if (!(cond)) \
{ \
/* HwAssert(__FILE__, __LINE__, #cond);*/
\
}
#else
# define ASSERT(cond) ((void)0)
#endif
#endif
/* !defined(ASSERT) */
#define TRACE (_PRINTF(__FILE__"@%d\n", __LINE__))
#endif
/* SYS_H */
drivers/isdn/eicon/uxio.h
deleted
100644 → 0
View file @
f69c2d56
/*
* Interface to Unix specific code for performing card I/O
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.6
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#if !defined(UXIO_H)
#define UXIO_H
#include "sys.h"
#include "adapter.h"
struct
pt_regs
;
/* user callback, returns zero if interrupt was from this card */
typedef
void
isr_fn_t
(
void
*
);
struct
ux_diva_card_s
{
word
in_use
;
int
io_base
;
int
reset_base
;
int
card_type
;
byte
*
mapped
;
struct
pci_dev
*
pdev
;
int
slot
;
int
irq
;
byte
*
pDRAM
;
byte
*
pDEVICES
;
byte
*
pCONFIG
;
byte
*
pSHARED
;
byte
*
pCONTROL
;
word
features
;
void
*
user_isr_arg
;
isr_fn_t
*
user_isr
;
};
/*
* Get a card handle to enable card to be accessed
*/
int
UxCardHandleGet
(
ux_diva_card_t
**
card
,
dia_card_t
*
cfg
);
/*
* Free a card handle as no longer needed
*/
void
UxCardHandleFree
(
ux_diva_card_t
*
card
);
/*
* Lock and unlock access to a card
*/
long
UxCardLock
(
ux_diva_card_t
*
card
);
void
UxCardUnlock
(
ux_diva_card_t
*
card
,
unsigned
long
ipl
);
/*
* Set the mapping address for PCI cards
*/
int
UxCardAddrMappingSet
(
ux_diva_card_t
*
card
,
int
id
,
void
*
address
,
int
size
);
/*
* Attach card to memory to enable it to be accessed
* Returns the mapped address
*/
void
*
UxCardMemAttach
(
ux_diva_card_t
*
card
,
int
id
);
/*
* map card out of memory after completion of access
*/
void
UxCardMemDetach
(
ux_diva_card_t
*
card
,
void
*
address
);
/*
* input functions for memory-mapped cards
*/
byte
UxCardMemIn
(
ux_diva_card_t
*
card
,
void
*
address
);
word
UxCardMemInW
(
ux_diva_card_t
*
card
,
void
*
address
);
dword
UxCardMemInD
(
ux_diva_card_t
*
card
,
void
*
address
);
void
UxCardMemInBuffer
(
ux_diva_card_t
*
card
,
void
*
address
,
void
*
buffer
,
int
length
);
/*
* output functions for memory-mapped cards
*/
void
UxCardMemOut
(
ux_diva_card_t
*
card
,
void
*
address
,
byte
data
);
void
UxCardMemOutW
(
ux_diva_card_t
*
card
,
void
*
address
,
word
data
);
void
UxCardMemOutD
(
ux_diva_card_t
*
card
,
void
*
address
,
dword
data
);
void
UxCardMemOutBuffer
(
ux_diva_card_t
*
card
,
void
*
address
,
void
*
buffer
,
int
length
);
/*
* input functions for I/O-mapped cards
*/
byte
UxCardIoIn
(
ux_diva_card_t
*
card
,
void
*
,
void
*
address
);
word
UxCardIoInW
(
ux_diva_card_t
*
card
,
void
*
,
void
*
address
);
dword
UxCardIoInD
(
ux_diva_card_t
*
card
,
void
*
,
void
*
address
);
void
UxCardIoInBuffer
(
ux_diva_card_t
*
card
,
void
*
,
void
*
address
,
void
*
buffer
,
int
length
);
/*
* output functions for I/O-mapped cards
*/
void
UxCardIoOut
(
ux_diva_card_t
*
card
,
void
*
,
void
*
address
,
byte
data
);
void
UxCardIoOutW
(
ux_diva_card_t
*
card
,
void
*
,
void
*
address
,
word
data
);
void
UxCardIoOutD
(
ux_diva_card_t
*
card
,
void
*
,
void
*
address
,
dword
data
);
void
UxCardIoOutBuffer
(
ux_diva_card_t
*
card
,
void
*
,
void
*
address
,
void
*
buffer
,
int
length
);
/*
* Get specified PCI config
*/
void
UxPciConfigRead
(
ux_diva_card_t
*
card
,
int
size
,
int
offset
,
void
*
value
);
/*
* Set specified PCI config
*/
void
UxPciConfigWrite
(
ux_diva_card_t
*
card
,
int
size
,
int
offset
,
void
*
value
);
/* allocate memory, returning NULL if none available */
void
*
UxAlloc
(
unsigned
int
size
);
void
UxFree
(
void
*
);
/*
* Pause for specified number of milli-seconds
*/
void
UxPause
(
long
ms
);
/*
* Install an ISR for the specified card
*/
int
UxIsrInstall
(
ux_diva_card_t
*
card
,
isr_fn_t
*
isr_fn
,
void
*
isr_arg
);
/*
* Remove an ISR for the specified card
*/
void
UxIsrRemove
(
ux_diva_card_t
*
card
,
void
*
);
/*
* DEBUG function to turn logging ON or OFF
*/
void
UxCardLog
(
int
turn_on
);
long
UxInterlockedIncrement
(
ux_diva_card_t
*
card
,
long
*
dst
);
long
UxInterlockedDecrement
(
ux_diva_card_t
*
card
,
long
*
dst
);
#endif
/* of UXIO_H */
drivers/isdn/eicon/xlog.c
deleted
100644 → 0
View file @
f69c2d56
/*
* Unix Eicon active card driver
* XLOG related functions
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.2
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include "sys.h"
#include "idi.h"
#include "pc.h"
#include "pc_maint.h"
#include "divalog.h"
#include "adapter.h"
#include "uxio.h"
/*
* convert/copy XLOG info into a KLOG entry
*/
static
void
xlog_to_klog
(
byte
*
b
,
int
size
,
int
card_num
)
{
typedef
struct
{
word
code
;
word
time_hi
;
word
time_lo
;
word
xcode
;
byte
data
[
2
];
}
card_xlog_t
;
card_xlog_t
*
x
;
klog_t
klog
;
x
=
(
card_xlog_t
*
)
b
;
memset
(
&
klog
,
0
,
sizeof
(
klog
));
klog
.
time_stamp
=
(
dword
)
x
->
time_hi
;
klog
.
time_stamp
=
(
klog
.
time_stamp
<<
16
)
|
(
dword
)
x
->
time_lo
;
klog
.
length
=
size
>
sizeof
(
klog
.
buffer
)
?
sizeof
(
klog
.
buffer
)
:
size
;
klog
.
card
=
card_num
;
if
(
x
->
code
==
1
)
{
klog
.
type
=
KLOG_XTXT_MSG
;
klog
.
code
=
0
;
memcpy
(
klog
.
buffer
,
&
x
->
xcode
,
klog
.
length
);
}
else
if
(
x
->
code
==
2
)
{
klog
.
type
=
KLOG_XLOG_MSG
;
klog
.
code
=
x
->
xcode
;
memcpy
(
klog
.
buffer
,
&
x
->
data
,
klog
.
length
);
}
else
{
char
*
c
;
int
i
;
klog
.
type
=
KLOG_TEXT_MSG
;
klog
.
code
=
0
;
c
=
"divas: invalid xlog message code from card"
;
i
=
0
;
while
(
*
c
)
{
klog
.
buffer
[
i
]
=
*
c
;
c
++
;
i
++
;
}
klog
.
buffer
[
i
]
=
*
c
;
}
/* send to the log driver and return */
DivasLogAdd
(
&
klog
,
sizeof
(
klog
));
return
;
}
/*
* send an XLOG request down to specified card
* if response available from previous request then read it
* if not then just send down new request, ready for next time
*/
void
DivasXlogReq
(
int
card_num
)
{
card_t
*
card
;
ADAPTER
*
a
;
if
((
card_num
<
0
)
||
(
card_num
>
DivasCardNext
))
{
DPRINTF
((
"xlog: invalid card number"
));
return
;
}
card
=
&
DivasCards
[
card_num
];
if
(
DivasXlogRetrieve
(
card
))
{
return
;
}
/* send down request for next time */
a
=
&
card
->
a
;
a
->
ram_out
(
a
,
(
word
*
)
(
card
->
xlog_offset
+
1
),
0
);
a
->
ram_out
(
a
,
(
word
*
)
(
dword
)
(
card
->
xlog_offset
),
DO_LOG
);
return
;
}
/*
* retrieve XLOG request from specified card
* returns non-zero if new request sent to card
*/
int
DivasXlogRetrieve
(
card_t
*
card
)
{
ADAPTER
*
a
;
struct
mi_pc_maint
pcm
;
a
=
&
card
->
a
;
/* get status of last request */
pcm
.
rc
=
a
->
ram_in
(
a
,
(
word
*
)(
card
->
xlog_offset
+
1
));
/* if nothing there from previous request, send down a new one */
if
(
pcm
.
rc
==
OK
)
{
/* read in response */
a
->
ram_in_buffer
(
a
,
(
word
*
)
(
dword
)
card
->
xlog_offset
,
&
pcm
,
sizeof
(
pcm
));
xlog_to_klog
((
byte
*
)
&
pcm
.
data
,
sizeof
(
pcm
.
data
),
(
int
)
(
card
-
DivasCards
));
}
/* if any response received from card, re-send request */
if
(
pcm
.
rc
)
{
a
->
ram_out
(
a
,
(
word
*
)
(
card
->
xlog_offset
+
1
),
0
);
a
->
ram_out
(
a
,
(
word
*
)
(
dword
)
(
card
->
xlog_offset
),
DO_LOG
);
return
1
;
}
return
0
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment